states.c

code format="c"
 * 1) include 
 * 2) include "define.h"
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 

extern char recvbuf[]; extern char* recvbuf_iPtr; extern char* recvbuf_ePtr;

extern const rom unsigned char _intro[]; extern const rom unsigned char _ul[]; extern const rom unsigned char _ur[]; extern const rom unsigned char _fy[]; extern const rom unsigned char _wh[]; extern const rom unsigned char _ct[]; extern const rom unsigned char _te[]; extern const rom unsigned char _ce[]; extern const rom unsigned char _rw[]; extern const rom unsigned char _ss[]; extern const rom unsigned char _sr[]; extern const rom unsigned char _cs[]; extern const rom unsigned char _outro[]; extern const rom unsigned char _fs[];

extern const rom unsigned char _raw1[]; extern const rom unsigned char _currwh[]; extern const rom unsigned char _dev1[]; extern const rom unsigned char _dev2[]; extern const rom unsigned char _gs[]; extern const rom unsigned char _os[];

extern const rom unsigned char _11[]; extern const rom unsigned char _12[]; extern const rom unsigned char _13[]; extern const rom unsigned char _14[];

extern const rom unsigned char _key[]; extern const rom unsigned char _enter[];

extern const rom unsigned char _ts[];

extern const rom unsigned char _cr[]; extern const rom unsigned char _lf[];

extern const rom unsigned char _count1[]; extern const rom unsigned char _count1b[]; extern const rom unsigned char _count2[]; extern const rom unsigned char _count3[]; extern const rom unsigned char _count4[]; extern const rom unsigned char _count5[];

extern const rom unsigned char _calib1[]; extern const rom unsigned char _calib2[]; extern const rom unsigned char _calib3[]; extern const rom unsigned char _calib4[];

extern const rom unsigned char _colon[];

extern const rom unsigned char _LCDmenu[]; extern const rom unsigned char _LCDcurrwh[]; extern const rom unsigned char _LCDgs[]; extern const rom unsigned char _LCDos[];

extern const rom unsigned char _LCDcount1[]; extern const rom unsigned char _LCDcount2[]; extern const rom unsigned char _LCDcount3[]; extern const rom unsigned char _LCDcount4[]; extern const rom unsigned char _LCDback[];

extern const rom unsigned char _speakCount4[];

extern const rom unsigned char _fac1[];

extern unsigned char unit;   /** Current mass unit, GRAMS or OUNCES. */ unsigned char mode = LOCAL;    /** Current mode: LOCAL, REMOTE, or FACTORY. */ unsigned char modeOld = ' ';   /** Stores the previous mode. */ unsigned char func = WEIGH;    /** Current function: WEIGH, COUNT, CALIBRATE, etc. */ unsigned char funcOld = ' ';   /** Stores the previous function. */ unsigned char phase = 0;   /** The phase is a subsection of func, used for stepping through COUNT and CALIBRATE. */ extern int mass;       /** The current mass, in a GRAMS or OUNCES as specified by unit. */ extern int varMass;       /** Current variance mass. */ extern int tareMass;       /** Current tare mass. */ extern int rawMass;       /** Current raw mass. */ int lastMass = 0x7FFF;       /** Stores the previous mass. Initialised value used to assure a change upon first reading. */ unsigned char msg[10] = "";   /** A temporary variable for storing the mass as a string, for output. */ unsigned char speak_str[35] = ""; /** A temporary variable for storing the output for the TTS. */ unsigned char ok = 0;       /** If the user hits enter or presses okay, this is set. */ unsigned char back = 0;       /** If the user hits escape or presses back, this is set. */ unsigned char absMode = LOCAL;   /** This is an absolute storage of whether we are in LOCAL or REMOTE (and only these options) */

int countSet1Mass = 0;       /** Temporary variable for storing first count mass value. */ int countSet2Mass = 0;       /** Temporary variable for storing second count mass value. */ int countItems = 0;       /** Temporary variable for storing count item number. */ int countItems2 = 0;       /** Temporary variable for storing count item number. */ float countMassPerItem = 0;   /** Temporary variable for storing count mass per item. Float for accuracy. */ unsigned char stringItems[6];   /** Temporary variable for storing the string of the number of items in count. */ unsigned char numInput = FALSE; /** If TRUE, numerical input are treated as such, rather than being menu options. */ unsigned char numbuf[5];   /** Stores up to 4 digits of numerical input, plus space for termination character. */ unsigned char numbufi = 0;   /** Index for numbuf. */ unsigned char mute = 0;       /** Stores if the user has muted/unmuted the system. */

void clearScreen(void); unsigned char parseMode(unsigned char iChar); unsigned char parseFunc(unsigned char iChar); void printInstructions(char mode, char func); void generateLine1(char key, char* function); void generateLine2(char key, char* function); extern unsigned char* get_rom_string(const rom unsigned char* txPtr); extern void transmit(unsigned char* message); void redrawStatus(void); void phaseStates(void); extern void setTare(void); extern void int_to_string(int rawNumber, unsigned char* string); void drawMenuLCD(void); extern void string_LCD(unsigned char* pointer); extern void get_weight_line(int weight, char* unit, char* output); extern void tts_send_string(char* command, char* output); extern void speak(char* outstring); extern void tts_reset(void); extern char tts_is_ready(void); extern void calibrate(unsigned int zeroVoltage, unsigned int secondVoltage, int secondMass, char massUnit);

extern unsigned int getVoltage(void); void calibrate_mode(void); void count_mode(void);

/** * Checks input characters from the recieve buffer, and modifies the state of the program based * on this input. The phaseStates function is then called, evaluating the implications of any * changes. * * Important globals modified: func, mode, phase * @pre The LCD, serial, and TTS are all initialized * @post LCD, serial, and/or TTS output. The tare may be modified. */ void checkState (void) {   unsigned char rcb = *recvbuf_ePtr; Delay10KTCYx(1);   //Delay to fix buffer problems

if((recvbuf_ePtr != recvbuf_iPtr))   //If there's a new character in the receive buffer {       rcb = *recvbuf_ePtr;        //Get the character

// Keypad handling - convert into char (as if serial input) to be handled by rest of routine if((rcb >= '0') && (rcb <= '9') ) //This is a number input from the keypad {           if(numInput)        //If we treat it as numerical input {               numbuf[numbufi] = rcb; numbufi++; if (numbufi == 3) {                   ok = 1; //maximum 4 digits in number }           rcb = 0; }           else    //Keypad input as menu selection {               switch(rcb) {                   case '1': rcb = WEIGH; break;

case '2': rcb = COUNT; break;

case '3': rcb = TARE; break;

case '4': rcb = CHANGEUNIT; break;

case '7': rcb = LOCAL; break;

case '8': mute = 1 - mute; break;

case '9': //Respeak mute = 0; if(func == WEIGH)   //If number, recalculate mass stuff {                           int_to_string(mass, msg); string_LCD(get_rom_string(_LCDcurrwh)); string_LCD(msg); strcpy(speak_str,msg);

if (unit == GRAMS) {                               strcatpgm2ram(speak_str,_gs); }                           else {                               strcatpgm2ram(speak_str,_os); }                       }

if(tts_is_ready) {                           speak(speak_str); }                       rcb = 0; break;

}           }        }

// Reset flags ok = 0; back = 0;

//Need to detect special characters and input number, but I'm not sure how to store it all yet. //A small buffer is needed for the numbers. if(rcb == '\r' || rcb == '#')   //If carriage return or OK        { rcb = OK; ok = 1; }       if(rcb == BACK || rcb == '\b' || rcb == 27) //If back, backspace or escape {           rcb = BACK; back = 1; }

mode = parseMode(rcb);       // Check for a valid mode character. if (!mode) {           mode = modeOld; }

func = parseFunc(rcb);       // Check for a valid function character.

if (!func) {           func = funcOld; }

if ((mode != FACTORY) && (func >=65) && (func <= 90))   // Factory functions allowed only in factory mode. {           //Between 65 and 90 are capital letters, so factory function characters must be capitals func = funcOld; if((func >=65) && (func <= 90)) {               func = WEIGH; }       }

if(mode != modeOld || func != funcOld)   //If the state has changed {           phase = 0;    //Reset the phase lastMass = 0x7FFF; }

if (rcb == CHANGEUNIT) {           unit = !unit; }

rcb = 0; recvbuf_ePtr++;

if (recvbuf_ePtr >= recvbuf + I_BUFSIZE) {           recvbuf_ePtr = recvbuf; }   }

//Set absolute mode setting if(mode != modeOld) {       if(mode == REMOTE || mode == FACTORY) {           absMode = REMOTE; func = WEIGH; }       if(mode == LOCAL) {           absMode = LOCAL; func = MENU; }       redrawStatus; }

phaseStates;   //Run through main logic

modeOld = mode; funcOld = func; }

/** * Calls the relevant functions to clear the screen on the terminal and redraw the menu. * @pre The serial must be initialised * @post See clearScreen and printInstructions in Scales.c */ void redrawStatus(void) {   if(absMode == LOCAL)    //Since this function is for serial only, quit if we're not using serial {       return; }   clearScreen; printInstructions(mode, func); }

/** * Evaluates the effect of the func and mode variables, which may have been modified in the checkState * function. * * This method will output menus and displays to the serial, LCD, and TTS where appropriate, based on * the current state of the program. * * The phase variable is used extensively in the functions Count and Calibrate to step through the * individual states of the functions. This method will, based in received input, choose when to * move forwards, and will, when complete, return to the main menu or weigh function, where appropriate. * * Important globals modified: func, mode, phase * @pre LCD, serial, and TTS are initialised * @post LCD, serial, and/or TTS output where appropriate. Calibration and Tare may be performed. */ void phaseStates(void) {   if(back) {       if(mode == LOCAL) {           func = MENU; phase = 0; }       else {           func = WEIGH; phase = 0; }       back = 0; }

switch (func) {       case MENU:    //Should be LCD only if(func != funcOld) {               drawMenuLCD; }           break; case WEIGH: if(mass != lastMass) {               int_to_string(mass, msg);

if(absMode == REMOTE) {                   redrawStatus;

transmit(get_rom_string(_currwh)); transmit(msg);

if (unit == GRAMS) {                       transmit(get_rom_string(_gs)); }                   else {                       transmit(get_rom_string(_os)); }                   transmit(get_rom_string(_outro)); }               else {                   string_LCD(get_rom_string(_LCDcurrwh)); string_LCD(msg); strcpy(speak_str,msg);

if (unit == GRAMS) {                       string_LCD(get_rom_string(_LCDgs)); strcatpgm2ram(speak_str,_gs);

}                   else {                       string_LCD(get_rom_string(_LCDos)); strcatpgm2ram(speak_str,_os); }                   string_LCD(get_rom_string(_LCDback));

if(tts_is_ready && !mute) {                       speak(speak_str); }               }                lastMass = mass; }           break;

case COUNT: void count_mode(void); break;

case TARE: setTare; func = WEIGH; phase = 0; break;

case CALIBRATE:           //Should never happen in local mode, so not designed to cope with LCD calibrate_mode(/*mode, func, phase, ok, unit*/); break; case STATS:

if(mass != lastMass) {               int_to_string(varMass, msg);

if(absMode == REMOTE) {                   redrawStatus; transmit(get_rom_string(_dev2)); transmit(get_rom_string(_outro));

transmit(get_rom_string(_dev1)); transmit(msg);

if (unit == GRAMS) {                       transmit(get_rom_string(_gs)); }                   else {                       transmit(get_rom_string(_os)); }                   transmit(get_rom_string(_outro)); }               lastMass = mass; }           break;

case RAW: if(mass != lastMass) {               rawMass = mass + tareMass; int_to_string(rawMass, msg);

if(absMode == REMOTE) {                   redrawStatus;

transmit(get_rom_string(_raw1)); transmit(msg);

if (unit == GRAMS) {                       transmit(get_rom_string(_gs)); }                   else {                       transmit(get_rom_string(_os)); }                   transmit(get_rom_string(_outro)); }               lastMass = mass; }           break;

case SAMPLES: //Not written yet break; } }

/** * Draws the main menu on the LCD. This menu shows the main options available to * the user. * @pre LCD is initialised * @post The menu is added to the LCD buffer */ void drawMenuLCD(void) {   if(absMode == REMOTE) {       return; }   string_LCD(get_rom_string(_LCDmenu)); if (unit == GRAMS)   //Append !unit {       string_LCD(get_rom_string(_os)); }   else {       string_LCD(get_rom_string(_gs)); }

}

/** * To be called strictly by phaseStates only, under case CALIBRATE. * Uses the phase variable to move between stages in the calibrate * state. * * See calibrate in scales.c for further postcondition and global variable * information. * * Important globals modified: phase, func. * @pre func = CALIBRATE, mode = FACTORY, serial initialised * @post Phase moves on, or calibration is performed and finishes output to serial. */ void calibrate_mode(void) {   static unsigned int v1, v2, m1, m2; unsigned char calibrationString[16]; switch(phase) {               case 0: //First prompt: Unload scales and press enter redrawStatus; transmit(get_rom_string(_calib1)); transmit(get_rom_string(_enter)); transmit(get_rom_string(_outro)); phase = 1; ok = 0; break; case 1: //Wait until OK and store voltage if(ok) {                       v1 = getVoltage; m1 = 0; ok = 0; phase = 2; }                   break; case 2: //Second prompt //Ask user to put some known quantity on the scales redrawStatus; transmit(get_rom_string(_calib2)); transmit(get_rom_string(_enter)); transmit(get_rom_string(_outro)); ok = 0; phase = 3; case 3: //Wait until OK and store mass if(ok) {                       v2 = getVoltage; ok = 0; phase = 4; }                   break; case 4: //Third prompt //Ask user to specify how much is on the scales in the working unit redrawStatus; transmit(get_rom_string(_calib3)); if (unit == GRAMS) {                       transmit(get_rom_string(_gs)); }                   else {                       transmit(get_rom_string(_os)); }                   transmit(get_rom_string(_colon)); transmit(get_rom_string(_outro)); phase = 5; case 5: //Wait until OK and store value numInput = TRUE; //Allow the user to input numbers if(ok) {                       numbuf[numbufi] = '\0'; transmit(numbuf); m2 = atoi(numbuf); //must fix to accept user input numInput = FALSE; ok = 0; phase = 6; }                   break; case 6: //Fourth prompt redrawStatus; transmit(get_rom_string(_calib4)); transmit(get_rom_string(_calib1)); transmit(get_rom_string(_enter)); transmit(get_rom_string(_outro)); //sprintf(calibrationString,"v1 = %d, m1 = %d, v2 = %d, m2 = %d\n",v1,m1,v2,m2); //transmit(calibrationString); //Delay10KTCYx(10);

phase = 7; break; case 7: //Wait for OK, then back to main menu calibrate(v1, v2, m2, unit); //   setTare; if(ok) {                       ok = 0; func = WEIGH; phase = 0; }                   break; } }

/** * To be called strictly by phaseStates only, under case COUNT. * Uses the phase variable to move between stages in the count state. * If count is performed, the results will be displayed. * Output to serial, or LCD and TTS. * Important globals modified: phase, func. * @pre func = COUNT, and serial, TTS, and LCD initialised * @post Phase moves on, or count is performed and finished. */ void count_mode(void) {   switch(phase) {       case 0: //First prompt //Please load a number of identical items.... if(absMode == REMOTE) {               redrawStatus; transmit(get_rom_string(_count1)); transmit(get_rom_string(_enter)); transmit(get_rom_string(_outro)); }           else {               string_LCD(get_rom_string(_LCDcount1)); if(tts_is_ready && !mute) {                   strcpy(speak_str,get_rom_string(_LCDcount1)); speak(speak_str); }           }            phase = 1; //String has been transmitted - wait for user to confirm break; case 1: //Wait until OK and store mass if(ok) {               countSet1Mass = mass; ok = 0; phase = 2; }           break; case 2: //Second prompt //Ask user how many items are on the scales if(absMode == REMOTE) {               redrawStatus; transmit(get_rom_string(_count2)); transmit(get_rom_string(_enter)); transmit(get_rom_string(_outro)); }           else {               string_LCD(get_rom_string(_LCDcount2)); if(tts_is_ready && !mute) {                   strcpy(speak_str,get_rom_string(_LCDcount2)); speak(speak_str); }           }            phase = 3; case 3: //Wait until OK and store value numInput = TRUE; if(ok) {               numbuf[numbufi] = '\0'; transmit(numbuf); countItems = atoi(numbuf); numInput = FALSE; numbufi = 0; ok = 0; phase = 4; }           break; case 4: //Third prompt //Ask user to load any number of items to be counted. if(absMode == REMOTE) {               redrawStatus; transmit(get_rom_string(_count3)); transmit(get_rom_string(_enter)); }           else {               string_LCD(get_rom_string(_LCDcount3)); if(tts_is_ready && !mute) {                   strcpy(speak_str,get_rom_string(_LCDcount3)); speak(speak_str); }           }            phase = 5; case 5: //Wait until OK and store mass if(ok) {               countSet2Mass = mass; ok = 0; phase = 6; }           break; case 6: //Fourth prompt countMassPerItem = 1.0 * countSet1Mass / countItems; countItems2 = (int)(countSet2Mass / countMassPerItem + 0.5); int_to_string(countItems2,stringItems); if(absMode == REMOTE) {               redrawStatus; transmit(get_rom_string(_count4)); transmit(stringItems); transmit(get_rom_string(_count5)); transmit(get_rom_string(_outro)); }           else {               string_LCD(get_rom_string(_LCDcount4)); string_LCD(stringItems); string_LCD(get_rom_string(_LCDback)); if(tts_is_ready && !mute) {

strcpy(speak_str,stringItems); strcatpgm2ram(speak_str,_speakCount4); speak(speak_str); }           }            phase = 7; break; case 7: //Wait for OK, then back to main menu if(ok) {               ok = 0; func = WEIGH; phase = 0; }           break; } } code