I'm working on calculator project using LM3S316 microcontroller & Keil software
I have some confusion about how can I work with KEYPAD-SMALLCALC
So, my question is :
how can I use this keypad and initialize it
also, how can I represent values and use it
finally, how to connect it with LCD
Thank You
The KEYPAD-SMALL-CALC is a matrix keypad, meaning you should configure some pins as input and some pins as output.
This is a decent library that i personally have used for a project of mine using a matrix keypad - https://github.com/nimaltd/KeyPad
You should be able to integrate it in your code without too much issues.
In short you have cols and rows. In the example provided the rows are input pins and the cols are output pins. There is a for cycle that is checking for a button press. By default rows are high, once a button is pressed the library checks for a combination between row and col that determinate which button has been pressed.
For configuration pins the easiest way would probably to use software such as "STM32CubeMX" which generates c code with your MCU configuration, you can easily configurate there the matrix keypad rows, cols and decide which pins you should use for the LCD.
Edit : Here is a modified version of the github library i have personally used in a project
source keyboard.c
#include "keyboard.h"
//#define _KEYPAD_DELAY(x) HAL_Delay(x)
const GPIO_TypeDef* _KEYPAD_COLUMN_GPIO_PORT[] =
{
COL_1_GPIO_Port,
COL_2_GPIO_Port,
COL_3_GPIO_Port,
COL_4_GPIO_Port,
COL_5_GPIO_Port,
COL_6_GPIO_Port,
COL_7_GPIO_Port,
COL_8_GPIO_Port
};
const uint16_t _KEYPAD_COLUMN_GPIO_PIN[] =
{
COL_1_Pin,
COL_2_Pin,
COL_3_Pin,
COL_4_Pin,
COL_5_Pin,
COL_6_Pin,
COL_7_Pin,
COL_8_Pin
};
const GPIO_TypeDef* _KEYPAD_ROW_GPIO_PORT[] =
{
ROW_1_GPIO_Port,
ROW_2_GPIO_Port,
ROW_3_GPIO_Port,
ROW_4_GPIO_Port
};
const uint16_t _KEYPAD_ROW_GPIO_PIN[] =
{
ROW_1_Pin,
ROW_2_Pin,
ROW_3_Pin,
ROW_4_Pin
};
KeyPad_t KeyPad;
//#############################################################################################
void KeyPad_Init(void)
{
KeyPad.ColumnSize = sizeof(_KEYPAD_COLUMN_GPIO_PIN)/2;
KeyPad.RowSize = sizeof(_KEYPAD_ROW_GPIO_PIN)/2;
}
//#############################################################################################
uint16_t KeyPad_Scan(void)
{
uint16_t key = 0;
uint8_t hold_key = 0;
int int_btn_cnt = 0;
int int_button_state_change = 0;
GPIO_PinState int_button_current_state = GPIO_PIN_SET;
GPIO_PinState int_button_last_state = GPIO_PIN_SET;
for(uint8_t c=0 ; c<KeyPad.ColumnSize ; c++)
{
for(uint8_t i=0 ; i<KeyPad.ColumnSize ; i++)
HAL_GPIO_WritePin((GPIO_TypeDef*)_KEYPAD_COLUMN_GPIO_PORT[i],_KEYPAD_COLUMN_GPIO_PIN[i],GPIO_PIN_SET);
HAL_GPIO_WritePin((GPIO_TypeDef*)_KEYPAD_COLUMN_GPIO_PORT[c],_KEYPAD_COLUMN_GPIO_PIN[c],GPIO_PIN_RESET);
for(uint8_t r=0 ; r<KeyPad.RowSize ; r++){
while(HAL_GPIO_ReadPin((GPIO_TypeDef*)_KEYPAD_ROW_GPIO_PORT[r],_KEYPAD_ROW_GPIO_PIN[r])==GPIO_PIN_RESET){
int_btn_cnt++;
if(int_btn_cnt == _KEYPAD_DEBOUNCE_TIME_MS){
key |= 1<<c;
key |= 1<<(r+8);
return key;
}
}
int_btn_cnt = 0;
}
}
return key;
}
//#############################################################################################
uint16_t KeyPad_WaitForKey(uint32_t Timeout_ms)
{
volatile uint16_t keyRead;
while(Timeout_ms==0)
{
keyRead = KeyPad_Scan();
if(keyRead!=0)
{
KeyPad.LastKey = keyRead;
return keyRead;
}
}
uint32_t StartTime = HAL_GetTick();
while(HAL_GetTick()-StartTime < Timeout_ms)
{
keyRead = KeyPad_Scan();
if(keyRead!=0){
KeyPad.LastKey = keyRead;
return keyRead;
}
}
return 0;
}
//#############################################################################################
char KeyPad_WaitForKeyGetChar(uint32_t Timeout_ms)
{
char result = 0;
switch(KeyPad_WaitForKey(Timeout_ms))
{
case 0x802: // ^
result = '^';
break;
case 0x804: // 7
result = '7';
break;
case 0x808: // 7
result = '8';
break;
case 0x810: // 9
result = '9';
break;
case 0x820: // 04
result = 0xFF;
break;
case 0x840: // D+
result = 0xFE;
break;
case 0x880: // M
result = 'M';
break;
case 0x401: // -%
result = '-';
break;
case 0x402: // +%
result = '+';
break;
case 0x404: // 4
result = '4';
break;
case 0x408: // 6
result = '5';
break;
case 0x410: // 6
result = '6';
break;
case 0x420: // 03
result = 0xFD;
break;
case 0x440: // PRUREP
result = 0xFC;
break;
case 0x480: // STL
result = 0xFB;
break;
case 0x201: // ALT
result = 0xFA;
break;
case 0x202: // CLK
result = 0xF9;
break;
case 0x204: // 1
result = '1';
break;
case 0x208: // 3
result = '2';
break;
case 0x210: // 3
result = '3';
break;
case 0x220: // 02
result = 0xF8;
break;
case 0x240: // PY1 RA
result = 0xF7;
break;
case 0x101: // C
result = 'C';
break;
case 0x102: // VD
result = 0xF6;
break;
case 0x104: // 0
result = '0';
break;
case 0x108: // .
result = '.';
break;
case 0x110: // QTY
result = 0xF5;
break;
case 0x120: // 01
result = 0xF4;
break;
case 0x140: // PY2PO
result = 0xF3;
break;
case 0x180: // TL
result = 0xF2;
break;
}
return result;
}
and the header file keyboard.h
#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__
#include <stdint.h>
#include <stdbool.h>
typedef struct
{
uint8_t ColumnSize;
uint8_t RowSize;
uint16_t LastKey;
}KeyPad_t;
void KeyPad_Init(void);
uint16_t KeyPad_WaitForKey(uint32_t Timeout_ms);
char KeyPad_WaitForKeyGetChar(uint32_t Timeout_ms);
#define _KEYPAD_DEBOUNCE_TIME_MS 5
#endif /* __KEYBOARD_H__ */
You should only configure the const arrays with the ports and pins you are planning to use and use the library like this :
init keyboard at the start of your program:
KeyPad_Init();
and use it like this
uint8_t key = KeyPad_WaitForKeyGetChar(1); // wait 1 ms
key is the value of the pressed key, if you use KeyPad_WaitForKeyGetChar(0) the code will stay here and wait for a key press.
Hope it helps!
Related
I read data from 2D-array buffer and write data to lcd using the 2-index row index and column index how to optimization this two byte (gu8LcdBufferColumn, gu8LcdBufferRow) to (single byte) in which the last 2-bit as a row index and first the 6 bit as column index.
two case the LCD_UPDATE_WRITE is write data into lcd and LCD_UPDATE_POS update the line of lcd
case LCD_UPDATE_WRITE:
if (gu8LcdBufferColumn != LCD_NUMBER_OF_BYTE) {
lcdWriteByte(gu8LCDBuffer[gu8LcdBufferRow][gu8LcdBufferColumn]);
gu8LcdBufferColumn++;
} else {
gu8LcdBufferColumn = 0;
gu8LcdBufferRow++;
if (gu8LcdBufferRow == LCD_NUMBER_OF_LINES) {
gu8LcdBufferRow = 0;
genLCDUpdateState = LCD_UPDATE_CHECK;
return (LCD_OK);
} else {
genLCDUpdateState = LCD_UPDATE_POS;
}
}
break;
case LCD_UPDATE_POS:
digitalPinWrite(LCD_RS, GPIO_LOW);
if (gu8LcdBufferRow == 0) {
lcdWriteByte(LCD_LINE_ONE_START);
} else if (gu8LcdBufferRow == 1) {
lcdWriteByte(LCD_LINE_TWO_START);
} else if (gu8LcdBufferRow == 2) {
lcdWriteByte(LCD_LINE_THREE_START);
} else if (gu8LcdBufferRow == 3) {
lcdWriteByte(LCD_LINE_FOUR_START);
}
digitalPinWrite(LCD_RS, GPIO_HIGH);
genLCDUpdateState = LCD_UPDATE_WRITE;
break;
last edit of this code with sync task two write data into lcd from buffer the macros lcd_line0_start and others is a hardware address in lcd convert this code to async task using switch case and write byte in each loop
case LCD_UPDATE_WRITE:
u8odd = 0;
u8even = 0;
if (bitIsClear(gu8LcdOPtion, LCD_DISPLAY)) {
/*the display on write command*/
digitalPinWrite(LCD_RS, GPIO_LOW);
/*set the display on*/
lcdWriteByte(LCD_DISPLAY_ON_COMMAND);
digitalPinWrite(LCD_RS, GPIO_HIGH);
genLCDUpdateState = LCD_UPDATE_CHECK; /*default state*/
return (LCD_OK);
}
for (uint8_t i = 0; i < LCD_NUMBER_OF_LINES; i++) {
digitalPinWrite(LCD_RS, GPIO_LOW);
if (i % 2 == 0) {
/*the number is even the start is 0x00 and D7 equal 1 = 0x80*/
/*line 0 and line 2*/
lcdWriteByte(LCD_LINE0_START + u8even);
u8even = LCD_NUMBER_OF_BYTE;
} else {
/*the number is odd*/
/*line 1 and line 3*/
/*the start is 0x40 and D7 = 1 a value is 0xc0*/
lcdWriteByte(LCD_LINE1_START + u8odd);
u8odd = (LCD_NUMBER_OF_BYTE);
}
digitalPinWrite(LCD_RS, GPIO_HIGH);
for (int j = 0; j < LCD_NUMBER_OF_BYTE; j++) {
lcdWriteByte(gu8LCDBuffer[i][j]);
}
}
/*the display on write command*/
digitalPinWrite(LCD_RS, GPIO_LOW);
/*set the display on*/
lcdWriteByte(LCD_DISPLAY_ON_COMMAND);
digitalPinWrite(LCD_RS, GPIO_HIGH);
genLCDUpdateState = LCD_UPDATE_POS; /*default state*/
break;
#include <FirebaseESP8266.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#define FIREBASE_HOST "####"
#define FIREBASE_AUTH "####"
// defines pins numbers
const int trigPin = 2; //D4
const int echoPin = 0; //D3
const int led = 4; //D2
// defines variables
long duration;
int distance = 0;
int wifi = 0;
int water = 0;
int water1 = 0;
//Firebase object..
FirebaseData firebaseData;
WiFiManager wifiManager;
void setup(){
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(led, OUTPUT);
Serial.begin(115200);
wifiManager.autoConnect("Aqua","123456789");
Serial.println();
Serial.print("Connected, IP address:" );
Serial.print(WiFi.localIP());
Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}
void loop(){
//digitalWrite(led, LOW);
if(WiFi.status() != WL_CONNECTED){
wifi = 0;
if (Firebase.setInt(firebaseData, "/Connectivity", wifi)){}
wifiManager.autoConnect("Aqua","123456789");
}
else{
wifi = 1;
if (Firebase.setInt(firebaseData, "/Connectivity", wifi)){}
}
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
if (Firebase.setInt(firebaseData, "/Distance", distance)) {
Serial.print("Distance = ");
Serial.println(distance);
Serial.println("\n");
delay(1000);
}
else
Serial.println(firebaseData.errorReason());
distance= duration*0.034/2;
water1 = water;
switch(distance){
case 2:
case 3:water = 500;
break;
case 4:
case 5:
case 6: water = 400;
break;
case 7:
case 8:water = 300;
break;
case 9:
case 10:
case 11:water = 200;
break;
case 12:
case 13:
case 14: water = 100;
break;
case 15: water = 0;
break;
default : water = water1;
break;
}
//I WANT TO STORE DISTANCE'S VALUE AND CHECK IF ITS THE SAME LAST 5 TIMES THEN EXECUTE BELOW CODE
if (Firebase.setInt(firebaseData, "/WaterLevel", water)) {
}
else
Serial.println(firebaseData.errorReason());
}
I WANT TO STORE DISTANCE'S VALUE AND CHECK IF ITS THE SAME LAST 5 TIMES
The distance's value is generated again and again I just want to store the previous 5 value of distance and compare them, and if they are same then execute the last if() condition
Is there a way to store only the previous 5 values generated by the variable "distance" and check if they are same
First, declare a local integer variable at the top:
int distanceSame = 1;
Then another one storing the last value:
int lastDistance = -1;
After this line
distance= duration*0.034/2;
check if the current distance value matches lastDistance variable, and if so, increment the distanceSame, otherwise reset it like this:
if(distance == lastDistance) {
// Increment counter
distanceSame++;
} else {
distanceSame = 1;
}
// prepare lastDistance for next cycle
lastDistance = distance;
And execute your code if the previous 5 values of distance are same.
if(distanceSame >= 5) {
if (Firebase.setInt(firebaseData, "/WaterLevel", water)) {
}
else
Serial.println(firebaseData.errorReason());
}
}
I've recently finished code for a PIC18F252 which uses the built in ADC to convert analogue inputs from 3 sensors into digital outputs that can be sent to motors. The code builds and uploads to the PIC perfectly fine, but unfortunately just doesn't work, and I'm struggling to see where the issue is.
After testing the output ports for the motors, I've found that they are all outputting the same signal, when they shouldn't be, and it doesn't change depending on the sensors.
My first thought is that there's something wrong between the output of the ADC (loading the result from ADRESH), and the if statements used to assign a digital value to these outputs.
I can't upload the entire code as this is coursework, but I've added the relevant parts. I've only included my function for AD conversion using one channel, but the functions for the other two channels are the same, just changing variables.
If anyone is able to spot an issue with this code (presumably around the if statements) I would be grateful!
#include <p18F252.h> // PIC specific definitions
#include <xc.h> // Xc8 compiler specifics
#include <stdio.h> // Standard C I/O library
#include <stdlib.h> // Standard C library
// Function declarations
void Config_ADC(void);
void delay(void);
void Motor_Output(unsigned char x, unsigned char y, unsigned char z);
void channel3(void);
unsigned char leftSens = 0b00000000; //Initialise left sensor variable
void Config_ADC(void){
// ADC Setup
TRISA = 0xFF; // configure port A as inputs
ADCON1bits.ADFM =0; // left justified
ADCON1bits.PCFG3=0;
ADCON1bits.PCFG2=1;
ADCON1bits.PCFG1=0;
ADCON1bits.PCFG0=0;
ADCON1bits.ADCS2=0;
ADCON0bits.ADCS1=1;
ADCON0bits.ADCS0=0;
ADCON0bits.ADON =1;
}
// Function for a delay of 1ms
void delay(void){
T2CON = 0x49; // start counting from 73
PR2 = 0x7C; // stop count at 124
T2CONbits.TMR2ON = 1; // activate timer 2
while(!PIR1bits.TMR2IF); // wait for timer flag
T2CONbits.TMR2ON = 0; // stop timer 2
PIR1bits.TMR2IF = 0; // clear flag
}
void channel3(void){
ADCON0bits.CHS2 = 0; //Channel selection
ADCON0bits.CHS1 = 1;
ADCON0bits.CHS0 = 1;
delay(); // Acquisition time to charge hold capacitor
ADCON0bits.GO_DONE = 1; // Start Conversion
while(ADCON0bits.GO_DONE); // Wait for A/D Conversion to complete
leftSens = ADRESH; // Return result
}
void main(void){
TRISB = 0x00; // configure Port B as output
Config_ADC(); // load ADC
while(1) { //loop forever/
channel3(); // Call channel 3 conversion
Motor_Output(leftSens, middleSens, rightSens);
}
}
// Function to send instructions to motors
void Motor_Output(unsigned char x, unsigned char y, unsigned char z){
int left, middle, right;
if(x >= 173){left = 1;} //173 chosen as threshold 8 bit value
else if(x < 173){left = 0;}
else if(y >= 173){middle = 1;}
else if(y < 173){middle = 0;}
else if(z >= 173){right = 1;}
else if(z < 173){right = 0;}
unsigned char output;
output = (left << 2) | (middle << 1) | right; //Bit shifted variables into one value
switch(output){
case 0x0:
PORTBbits.RB7 = 0; //Test for each output and activate motors accordingly
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
case 0x1:
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 1;
PORTBbits.RB4 = 0;
case 0x2:
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
case 0x3:
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 1;
PORTBbits.RB4 = 0;
case 0x4:
PORTBbits.RB7 = 1;
PORTBbits.RB6 = 0;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
case 0x5:
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
case 0x6:
PORTBbits.RB7 = 1;
PORTBbits.RB6 = 0;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
case 0x7:
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
}
return;
}
Without going any deeper in analysis there are two major problems:
The if-else if-chain will do just one assigment to left. To make that obvious I have indented your source this way without any other changes:
if (x >= 173) { // Either THIS...
left = 1;
} else
if (x < 173) { // Or THAT will be true.
left = 0;
} else // None of the following is executed therefore.
if (y >= 173) {
middle = 1;
} else
if (y < 173) {
middle = 0;
} else
if (z >= 173) {
right = 1;
} else
if (z < 173) {
right = 0;
}
So middle and right will have undefined values.
All your cases in the switch are missing a break. So only the last case or none at all will be executed. Why "none"? Because middle and right have undefined values, resulting in a random value in output.
Note: "Random" might be always the same value, depending on the bits set or reset at the locations of middle and right, respectively.
Quick question: Is it by design that you are falling through your switch-cases?
void Motor_Output(unsigned char x, unsigned char y, unsigned char z){
// ...
switch(output){
case 0x0:
... <-- no break, will continue to execute next case
case 0x1:
... <-- no break, will continue to execute next case
case 0x2:
... <-- no break, will continue to execute next case
case 0x3:
... <-- no break, will continue to execute next case
case 0x4:
... <-- no break, will continue to execute next case
case 0x5:
... <-- no break, will continue to execute next case
case 0x6:
... <-- no break, will continue to execute next case
case 0x7:
... <-- no break, will continue to execute next case
}
return;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm facing some issues with my state machine (function automate()). It seems that the enum always keep the same values instead of changing it depending on differents conditions in the function.
My output is always "DECREMENT_PARA_1" Can anyone tell me why the variable etat_courant doesn't keep the value in memory for each iteration please ? Thanks in advance ! Here is my code :
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//PARAMETRES
enum Etat {INIT, DECREMENT_PARA_1, INCREMENT_PARA_1, ETAT_INVARIANT_1, DECREMENT_PARA_2, ETAT_INVARIANT_2, INCREMENT_PARA_2, RADAR_SATURE};
//Prototypes
void automate(int tddv_estime, int tab_para_automate[][2], enum Etat *etat_courant, int* para_1_courant, int* para_2_courant);
void fct_test(int scenario[]);
int main()
{
int scenario[15] = {21, 21, 20, 12, 12, 20, 22, 22, 22, 22, 22, 22, 22, 22, 500};
fct_test(scenario);
return 0;
}
/*-----------------------------------------------------------------------
Fonction fct_test
-------------------------------------------------------------------------*/
void fct_test(int scenario[])
{
int increment = 1;
int tddv_estime;
int para_1_courant = 10;
int para_2_courant = 4;
int para_1_min = 5;
int para_1_max = 10;
int para_2_min = 1;
int para_2_max = 4;
int tab_para_automate[2][2] = {{0}};
int tab_para_application[1][3] = {{0}};
tab_para_automate[0][0] = para_1_min;
tab_para_automate[0][1] = para_1_max;
tab_para_automate[1][0] = para_2_min;
tab_para_automate[1][1] = para_2_max;
tab_para_application[0][0] = para_1_courant;
tab_para_application[0][1] = para_2_courant;
tab_para_application[0][2] = increment;
int i;
enum Etat etat_courant = INIT;
for (i=0 ; i<15 ; i++)
{
tddv_estime = scenario[i];
printf("%d\n",scenario[i]);
automate(tddv_estime, tab_para_automate, &etat_courant, ¶_1_courant, ¶_2_courant);
}
//}
}
/*-----------------------------------------------------------------------
Fonction automate
-------------------------------------------------------------------------*/
void automate(int tddv_estime, int tab_para_automate[][2], enum Etat *etat_courant, int* para_1_courant, int* para_2_courant)
{
int evenement;
int tddv_worst = 20;
if (tddv_estime < tddv_worst)
evenement = 1; //Etat initial
if (tddv_estime > tddv_worst)
evenement = 2; //Decrement para1
if (tddv_estime < tddv_worst && *para_1_courant<= tab_para_automate[0][1])
evenement = 3; //Increment para1
if (tddv_estime == tddv_worst)
evenement = 4; //Etat Invariant 1
if (tddv_estime > tddv_worst && *para_1_courant <= tab_para_automate[0][0])
evenement = 5; //Decrement para_2
if (tddv_estime < tddv_worst && *para_2_courant <= tab_para_automate[1][1])
evenement = 6; //Increment para2
if (tddv_estime == tddv_worst)
evenement = 7; //Etat Invariant 2
if (tddv_estime > tddv_worst && *para_1_courant<= tab_para_automate[0][0] && *para_2_courant<= tab_para_automate[1][0])
evenement = 8; //Etat radar sature
switch (*etat_courant) {
case INIT:
switch(evenement)
{
case 1:
*etat_courant = INIT;
printf("ETAT_INITIAL\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case DECREMENT_PARA_1:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case INCREMENT_PARA_1:
switch(evenement)
{
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
}
break;
case ETAT_INVARIANT_1:
switch(evenement)
{
case 2:
*etat_courant = DECREMENT_PARA_1;
printf("DECREMENT_PARA_1\n");
break;
case 4:
*etat_courant = ETAT_INVARIANT_1;
printf("ETAT_INVARIANT_1\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
}
break;
case DECREMENT_PARA_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
case 8:
*etat_courant = RADAR_SATURE;
printf("RADAR_SATURE\n");
break;
}
break;
case ETAT_INVARIANT_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
}
break;
case INCREMENT_PARA_2:
switch(evenement)
{
case 5:
*etat_courant = DECREMENT_PARA_2;
printf("DECREMENT_PARA_2\n");
break;
case 7:
*etat_courant = ETAT_INVARIANT_2;
printf("ETAT_INVARIANT_2\n");
break;
case 6:
*etat_courant = INCREMENT_PARA_2;
printf("INCREMENT_PARA_2\n");
break;
case 3:
*etat_courant = INCREMENT_PARA_1;
printf("INCREMENT_PARA_1\n");
break;
}
break;
default :
exit(1);
break;
}
}
Can anyone tell me why the variable etat_courant doesn't keep the value in memory for each iteration please ?
It actually is keeping the value in memory: it can not do otherwise, etat_courant will be kept in memory until fct_test(...) returns. The reason the output is always DECREMENT_PARA_1 is purely due to the logic in your automate() function.
For example, you have a redundant comparison in your automate() function - which is overriding a previous assignment of evenement.
if (tddv_estime == tddv_worst)
evenement = 4; //Etat Invariant 1
// ...
if (tddv_estime == tddv_worst)
evenement = 7; //Etat Invariant 2
If - and this is just hypothetical (whether or not this is the right thing to do depends on what you are trying to achieve) - you remove the second comparison, the output will vary at least once.
As an aside ... It is safer to pass the size of the array to your fct_test(...) function - as in
int main(void) {
int scenario[] = {21, 21, 20, 12, 12, 20, 22, 22,
22, 22, 22, 22, 22, 22, 500};
fct_test(scenario, sizeof(scenario)/sizeof(scenario[0]));
return 0;
}
void fct_test(int *scenario, size_t array_len) {
// Etc. (ommitted for brevity )
for (i = 0; i < array_len; i++) {
tddv_estime = scenario[i];
// etc.
}
}
(Note that I added a return 0 in your main() also - which you were missing.)
so, I have this code:
/*
* CXenon VM v0.0.0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#define IADD 1 // integer add
#define ISUB 2 // integer substract
#define IMUL 3 // integer multiply
#define IDIV 4 // integer divide
#define ILT 5 // integer less than
#define IEQ 6 // integer equals
#define BR 7
#define BRT 8
#define BRF 9
#define ICONST 10 // integer constant
#define LOAD 11 // load from data memory
#define GLOAD 12 // global load from data memory
#define STORE 13 // store in data memory
#define GSTORE 14 // global store in data memory
#define PRINT 15 // print
#define PRINTLN 16 // print with trailing newline
#define POP 17 // pop from stack
#define CALL 18 // call function
#define RET 19
#define FADD 20
#define FSUB 21
#define FMUL 22
#define FDIV 23
#define FCONST 24
#define FLT 25
#define FEQ 26
#define FMT 27
#define FNEQ 28
#define IMT 29
#define INEQ 30
#define BCONST 31
#define BEQ 32
#define BNEQ 33
#define BTRUE 34
#define BFALSE 35
#define HALT 36
char* opcodes[] = {
"",
"IADD",
"ISUB",
"IMULL",
"IDIV",
"ILT",
"IEQ",
"BR",
"BRT",
"BRF",
"ICONST",
"LOAD",
"GLOAD",
"STORE",
"GSTORE",
"PRINT",
"PRINTLN",
"POP",
"CALL",
"RET",
"FADD",
"FSUB",
"FMUL",
"FDIV",
"FCONST",
"FLT",
"FEQ",
"FMT",
"FNEQ",
"IMT",
"INEQ",
"BCONST",
"BEQ",
"BNEQ",
"BTRUE",
"BFALSE",
"HALT"
};
struct stack_base{
char* somechars;
char achar;
int anint;
float afloat;
bool abool;
};
int vm_cpu(struct stack_base* code, bool trace, int datasize){
struct stack_base stack[100];
struct stack_base data[datasize];
int ip = 0; // instructionpointer
int fp; // framepointer
int sp = -1; // stackpointer
int v;
int addr;
int nargs;
int rvalue;
int a, b;
float fv;
float fa, fb;
bool bv;
bool ba, bb;
int opcode = code[ip].anint; // fetch
int size = sizeof(code); // declares size of code
//bool trace = false;
while(ip < size){
if(trace){
printf("%04d: %s\n",ip, opcodes[opcode]); // prints trace
}
ip++;
switch(opcode){
case ICONST:
v = code[ip].anint;
ip++;
sp++;
stack[sp].anint = v;
break;
case ISUB:
b = stack[sp--].anint;
a = stack[sp--].anint;
stack[++sp].anint = a - b;
break;
case IADD:
b = stack[sp--].anint;
a = stack[sp--].anint;
stack[++sp].anint = a + b;
break;
case IMUL:
b = stack[sp--].anint;
a = stack[sp--].anint;
stack[++sp].anint = a * b;
break;
case IDIV:
b = stack[sp--].anint;
a = stack[sp--].anint;
stack[++sp].anint = a/b;
break;
case ILT:
b = stack[sp--].anint;
a = stack[sp--].anint;
if(a > b){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case IMT:
b = stack[sp--].anint;
a = stack[sp--].anint;
if(a < b){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case IEQ:
b = stack[sp--].anint;
a = stack[sp--].anint;
if(a == b){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case INEQ:
b = stack[sp--].anint;
a = stack[sp--].anint;
if(a != b){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case FCONST:
fv = code[ip].afloat;
ip++;
sp++;
stack[sp].afloat = fv;
break;
case FSUB:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
stack[++sp].afloat = fa + fb;
break;
case FADD:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
stack[++sp].afloat = fa + fb;
break;
case FMUL:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
stack[++sp].afloat = fa * fb;
break;
case FDIV:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
stack[++sp].afloat = fa/fb;
break;
case FEQ:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
if(fa == fb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case FLT:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
if(fa > fb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case FMT:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
if(fa < fb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case FNEQ:
fb = stack[sp--].afloat;
fa = stack[sp--].afloat;
if(fa != fb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case BCONST:
bv = code[ip].anint;
ip++;
sp++;
if(bv == BTRUE){
stack[sp].abool = true;
break;
}
else if(bv == BFALSE){
stack[sp].abool = false;
break;
}
case BNEQ:
bb = stack[sp--].abool;
ba = stack[sp--].abool;
if(ba == bb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case BEQ:
bb = stack[sp--].abool;
ba = stack[sp--].abool;
if(ba != bb){
stack[++sp].abool = true;
break;
}
else {
stack[++sp].abool = false;
break;
}
case PRINT:
v = stack[sp].anint;
sp--;
printf("%i", v);
break;
case PRINTLN:
//v = stack[sp].anint;
//fv = stack[sp].afloat;
bv = stack[sp].abool;
sp--;
printf("%d\n", bv);
break;
case GLOAD:
addr = code[ip].anint;
ip++;
v = data[addr].anint;
sp++;
stack[sp].anint = v;
break;
case GSTORE:
v = stack[sp].anint;
sp--;
addr = code[ip].anint;
ip++;
data[addr].anint = v;
break;
case CALL:
addr = code[ip++].anint;
nargs = code[ip++].anint;
stack[++sp].anint = nargs;
stack[++sp].anint = fp;
stack[++sp].anint = ip;
fp = sp;
ip = addr;
break;
case RET:
rvalue = stack[sp--].anint;
sp = fp;
ip = stack[sp--].anint;
fp = stack[sp--].anint;
nargs = stack[sp--].anint;
sp -= nargs;
stack[sp++].anint = rvalue;
break;
case HALT:
return 0;
break;
}
opcode = code[ip].anint;
}
}
void main(){
struct stack_base hello[] = {
BCONST, BTRUE,
BCONST, BTRUE,
BNEQ,
PRINTLN,
HALT
};
vm_cpu(hello, true, 4);
}
when I compile that code, I get these errors:
thewatcher#thewatcher ~/Xenon/CXenon/src $ gcc main.c -o test
main.c: In function ‘main’:
main.c:402:9: warning: initialization makes pointer from integer without a cast [enabled by default]
BCONST, BTRUE,
^
main.c:402:9: warning: (near initialization for ‘hello[0].somechars’) [enabled by default]
main.c:405:9: warning: initialization makes pointer from integer without a cast [enabled by default]
PRINTLN,
^
main.c:405:9: warning: (near initialization for ‘hello[1].somechars’) [enabled by default]
I don't understand why this happens and I have no idea how to solve this. Could someone help me?
The structure member initialization in your main function is different from you structure definition.
You structure member should be initialized like this.
struct stack_base hello[] = {
{
"hey there",'a',22,11,true
},
{
"thank you",'b',11,11,false
},
{
"hello",'c',11,11,true
}
};
And the following line,
int size = sizeof(code);
code is just a pointer to the structure whose size is always 4 (older systems) or 8 (newer systems) bytes. I guess you are trying to find number of members in hello[] structure array. In this case either you have to pass this number separately as a function to vm_cpu function or use some logic to determine this number within the vm_cpu function.
In case you don't want to pass no. of members as an argument, initialize the structure in main fn as follows:
struct stack_base hello[] = {
{
"abc",'a',11,11,true
},
{
"abc",'a',11,11,true
},
{
"abc",'a',11,11,true
},NULL
};
And in vm_cpu function, use the following logic to find out no. of structure array elements.
int size = 0;
struct stack_base *ptr = code;
while(ptr[size].somechars) {
size++;
ptr++;
}
size--;
printf("The no. of elements of structure array: %d\n", size);
If you initialize your structure array hello correctly, the errors you are facing should disappear. The way you initialize it currently is very confusing, as the compiler tells you:
warning: (near initialization for ‘hello[0].somechars’) [enabled by default]
Meaning that there is an error with the way you initialize your structure array (see here to fully understand the grammar involved in the error). Your second error:
warning: initialization makes pointer from integer without a cast
The compiler is also confused in your initialization of your structure array. Take, for example, this initialization:
struct my_struct {
int a;
int b;
}
//Create a structure assigning the value of a to 10 and b to 20:
struct my_struct foo = {10, 20};
This will initialize one structure, not multiple. If you wanted to use a similar syntax creating an array of structures, you could do something like this:
//Use my_struct from the previous example
struct my_struct foo[] {
{.a = 10, .b = 20},
{.a = 1, .b = 2},
{.a = 5, .b = 5}
};
To understand this syntax further, see designated initializers. The syntax above creates an array of structures with these members for each structure in the array:
foo[0].a = 10;
foo[0].b = 20;
foo[1].a = 1;
foo[1].b = 2;
foo[2].a = 5;
foo[2].b = 5;
Initialize struct stack_base hello[] to have these values for each member:
//hello[0].somechars will be assigned the string "hello"
hello[0].achar = 'a';
hello[0].anint = 1;
hello[0].afloat = 1.0;
hello[0].abool = 0;
//hello[1].somechars will be assigned the string "bye bye"
hello[1].achar = 'b';
hello[1].anint = 2;
hello[1].afloat = 10.0;
hello[1].abool = 1;
Then, you could write:
struct stack_base hello[] {
{.achar = 'a', .anint = 1, .afloat = 1.0, .abool = 0},
{.achar = 'b', .anint = 2, .afloat = 10.0, .abool = 1}
};
//Assign strings to achar
strcpy(hello[0].somechars, "hello");
strcpy(hello[1].somechars, "bye bye");
In the example above, instead of assigning exact values to each member of the structure, it would make sense for you to replace the assignments to each member with the constants. For example, you might replace .anint = 1 with .anint = BCONST, etc.
Currently, however, it is simply confusing the way you have initialized your structure array.