Chrono

Dependencies:   mbed SDFileSystem

Files at this revision

API Documentation at this revision

Comitter:
pathae
Date:
Tue Apr 07 12:24:23 2020 +0000
Parent:
4:f5cff5165941
Commit message:
Tir

Changed in this revision

SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
eeprom_flash.cpp Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed_genie.cpp Show annotated file Show diff for this revision Revisions of this file
mbed_genie.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Tue Apr 07 12:24:23 2020 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/neilt6/code/SDFileSystem/#3fa5eaf48e81
--- a/eeprom_flash.cpp	Mon Apr 06 15:24:07 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-#include "mbed.h"
-#include "eeprom_flash.h"
-Serial pc(USBTX, USBRX); //Initalise PC serial comms
-DigitalOut myled(LED1);
-/*
- * Must call this first to enable writing
- */
-void enableEEPROMWriting() {
-    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
-    FLASH_PageErase(EEPROM_START_ADDRESS); // required to re-write
-    CLEAR_BIT(FLASH->CR, FLASH_CR_PER);    // Bug fix: bit PER has been set in Flash_PageErase(), must clear it here
-}
-
-void disableEEPROMWriting() {
-    HAL_FLASH_Lock();
-}
-
-/*
- * Writing function
- * Must call enableEEPROMWriting() first
- */
-HAL_StatusTypeDef writeEEPROMHalfWord(uint32_t address, uint16_t data) {
-    HAL_StatusTypeDef status;
-    address = address + EEPROM_START_ADDRESS;
-    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data);
-    return status;
-}
-
-/*
- * Reading functions
- */
-uint16_t readEEPROMHalfWord(uint32_t address) {
-    uint16_t val = 0;
-    address = address + EEPROM_START_ADDRESS;
-    val = *(__IO uint16_t*)address;
-     return val;
-}
-
-//Programme de test
-
-int main() {
-int adresse = 0x00;
-char donnee1 = 11;
-char donnee2 = 22;
-char donnee3 = 33;
-int lecture;
-pc.baud(9600);
-
-/* Ecriture*/
-enableEEPROMWriting(); //autorisation d'ecriture dans l'eeprom
-writeEEPROMHalfWord(adresse, donnee1);
-writeEEPROMHalfWord(adresse+2, donnee2);
-writeEEPROMHalfWord(adresse+4, donnee3);
-disableEEPROMWriting(); //Interdiction d'ecriture
-
- myled=!myled;
-        wait(0.5);
-        myled=!myled;
-        wait(0.5);
-
-/*lecture et affichage*/
-lecture=readEEPROMHalfWord(adresse);
-if (lecture==11)
-    {
-        myled=!myled;
-        wait(0.5);
-        myled=!myled;
-        wait(0.5);
-        myled=!myled;
-        wait(0.5);
-    }
-pc.printf ("valeur lue: %d\n\r",lecture);
-lecture=readEEPROMHalfWord(adresse+2);
-pc.printf ("valeur lue: %d\n\r",lecture);
-lecture=readEEPROMHalfWord(adresse+4);
-pc.printf ("valeur lue: %d\n\r",lecture);
- while(1);
-}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Apr 07 12:24:23 2020 +0000
@@ -0,0 +1,298 @@
+#include "mbed.h"
+#include "mbed_genie.h"
+#include "SDFileSystem.h"
+#include "eeprom_flash.h"
+SDFileSystem sd(D11, D12, D13, D10, "sd"); // the pinout on the mbed Cool Components workshop board
+AnalogIn TensionBatterie(A1);
+DigitalOut DELVERTE (PB_2);
+DigitalOut DELORANGE (PB_1);
+DigitalOut DELROUGE (PB_15,1); 
+InterruptIn BOUTONPAUSE(USER_BUTTON);
+//Prototype des routines d'interruption
+void compt_secondes();
+void valeur_volt();
+int temps_global_secondes, temps_global_minutes, temps_global_heures, numero_tir1 = 1, numero_tir2 = 0, numero_tir_depart = 1, pause = 0,bloqueur, kchrono = 0,locker =0;
+int i = 15, j_tir = 0;
+int adresse = 0x00;
+char donnee1 = 11;
+char donnee2 = 22;
+char donnee3 = 33;
+float valeur_tension, valeur_analogique;  // Permet d'avoir des mesures precises pour la tension    
+    char cMonText[1024];
+    char cMonText2[1024];
+    char chiffre1[6];
+    char chrono[40];
+    char i1=0;
+    char j=0;
+    char k=0;
+    int val1;
+    char chiffre2[6];
+    char type_tir[40];
+    char i2=0;
+    char j2=0;
+    char k2=0;
+    int val2;
+//Déclaration des interruptions Ticker 
+Ticker Horloge_Global_Seconde;
+Ticker Valeur_Tension_Volt;
+/*************************************************************************************************
+  Interruption générée automatiquement toutes les secondes pour décrémenter le compteur  **
+*************************************************************************************************/   
+//Must call this first to enable writing
+void enableEEPROMWriting() {
+    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
+    FLASH_PageErase(EEPROM_START_ADDRESS); // required to re-write
+    CLEAR_BIT(FLASH->CR, FLASH_CR_PER);    // Bug fix: bit PER has been set in Flash_PageErase(), must clear it here
+}
+void disableEEPROMWriting() {
+    HAL_FLASH_Lock();
+}
+//Writing function
+//Must call enableEEPROMWriting() first
+HAL_StatusTypeDef writeEEPROMHalfWord(uint32_t address, uint16_t data) {
+    HAL_StatusTypeDef status;
+    address = address + EEPROM_START_ADDRESS;
+    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data);
+    return status;
+}
+//Reading functions
+uint16_t readEEPROMHalfWord(uint32_t address) {
+    uint16_t val = 0;
+    address = address + EEPROM_START_ADDRESS;
+    val = *(__IO uint16_t*)address;
+     return val;
+}
+
+void vidReadText(char * cTxt)
+{
+    unsigned char caractereActuel;  // Début lecture SD
+    int iIndex=0;
+    FILE *fp = fopen("/sd/Temps.txt", "r");
+    if(fp == NULL) 
+    {
+        error("Could not open file \n");
+    }
+    else
+    {
+         // Boucle de lecture des caractères un à un
+         strcpy(cTxt,"");
+         printf("\n\r");
+           do{
+                 caractereActuel = fgetc(fp); // On lit le caractère
+                 if(caractereActuel != 255) sprintf(cTxt,"%s%c",cTxt, caractereActuel); // On l'affiche
+                 iIndex++;
+            }    while (caractereActuel != 255);
+            fclose(fp); 
+    } // Fin lecture SD
+}
+
+void vidReadText2(char * cTxt2)
+{
+    unsigned char caractereActuel2;  // Début lecture SD 2
+    int iIndex2=0;
+    FILE *fp = fopen("/sd/Ordre.txt", "r");
+    if(fp == NULL) 
+    {
+        error("Could not open file \n");
+    }
+    else
+    {
+         // Boucle de lecture des caractères un à un
+         strcpy(cTxt2,"");
+         printf("\n\r");
+           do{
+                 caractereActuel2 = fgetc(fp); // On lit le caractère
+                 if(caractereActuel2 != 255) sprintf(cTxt2,"%s%c",cTxt2, caractereActuel2); // On l'affiche
+                 iIndex2++;
+            }    while (caractereActuel2 != 255);
+            fclose(fp); 
+    } // Fin lecture SD 2
+}
+
+
+ void compt_secondes() //-------------------------------- Compteur seconde ----------------------------------------
+  {
+    if(bloqueur == 0) // Début bloqueur
+    {
+    chrono[kchrono]=chrono[kchrono]-1;
+    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x00, chrono[kchrono]);      //Ecrit sur Leddigits0 la valeur de chrono
+    genieWriteObject(GENIE_OBJ_GAUGE , 0x00, chrono[kchrono]);
+    temps_global_secondes = temps_global_secondes + 1;
+    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x01, temps_global_secondes);
+        if(temps_global_secondes == 60){
+                temps_global_secondes = 0;
+                temps_global_minutes = temps_global_minutes + 1;
+                genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x02, temps_global_minutes);
+                    if(temps_global_minutes == 60)
+                    {
+                    temps_global_minutes = 0;
+                    temps_global_heures = temps_global_heures + 1;
+                    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x03, temps_global_heures);
+                    }
+    }
+    
+    if (numero_tir_depart == 1){ // Début décompte
+        genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x04, numero_tir1);
+        temps_global_secondes= 0;
+        genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x02, temps_global_secondes);
+        temps_global_minutes = 0;
+        genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x02, temps_global_minutes);
+        temps_global_heures = 0;
+        genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x02, temps_global_heures);
+        numero_tir_depart++;
+        genieWriteObject(GENIE_OBJ_USER_LED, 0x00, 0);
+        }
+    if(chrono[kchrono] == 0){
+                
+                if (type_tir[j_tir+1] == 0) // Tir normale
+                {
+                    numero_tir1++;
+                    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x04, numero_tir1);
+                    genieWriteObject(GENIE_OBJ_USER_LED, 0x00, 0);
+                }
+                
+                if (type_tir[j_tir+1] == 1) // Tir distance
+                {
+                    numero_tir2++;
+                    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x04, numero_tir2);
+                    genieWriteObject(GENIE_OBJ_USER_LED, 0x00, 1);
+                }             
+                
+                j_tir++;
+                chrono[kchrono] = chrono[kchrono+1];
+                kchrono++;
+            } // Fin partie décompte seconde
+    } // Fin bloqueur           
+    genieFrame Event;
+    genieDequeueEvent(&Event);
+    //event report from an object
+    if(Event.reportObject.cmd == GENIE_REPORT_EVENT) {
+        /*
+        for example here we check if we received a message from 4dbuttons objects
+        the index is the button number, refer to the 4dgenie project to know the index
+        */
+        if (Event.reportObject.object == GENIE_OBJ_4DBUTTON) {              // If the Reported Message was from a button
+            if (Event.reportObject.index == 9) { // Début Enclenchement bouton 9
+                if (i<15)
+                {
+                i++;
+                }
+                genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x05, i);
+                genieWriteContrast(i);
+            } // Fin Enclenchement bouton 9
+            if (Event.reportObject.index == 10) { // Début Enclenchement bouton 10
+                if (i>0)
+                {
+                i--;
+                }
+                genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x05, i);
+                genieWriteContrast(i);
+            } // Fin Enclenchement bouton 10
+            if (Event.reportObject.index == 15) { // Début Enclenchement bouton 15
+            vidReadText(cMonText);
+            vidReadText2(cMonText2);
+            i1=0;
+            k=0;
+            i2=0;
+            k2=0;
+       
+    while(cMonText[i1]!='*')
+        {
+            while(cMonText[i1]!=',')
+                {
+                    chiffre1[j]=cMonText[i1];
+                    i1++;
+                    j++;
+                }
+            val1 = atoi(chiffre1);
+            chrono[k]=val1;
+            j=0;
+            i1++;
+            k++;
+        }
+i1=0;
+k=0;
+
+    while(cMonText2[i2]!='*')
+        {
+            while(cMonText2[i2]!=',')
+                {
+                    chiffre2[j2]=cMonText2[i2];
+                    i2++;
+                    j2++;
+                }
+            val2 = atoi(chiffre2);
+            type_tir[k2]=val2;
+            j2=0;
+            i2++;
+            k2++;
+        }
+i2=0;
+k2=0;
+            } // Fin Enclenchement bouton 15
+            
+        }    
+        }  
+    return;
+    }    
+    
+void valeur_volt() // ---------------------------------------------- Lecteur Tension ------------------------
+  {
+    valeur_analogique = TensionBatterie.read(); // Convertis la valeur obtenus entre 0 et 1
+    valeur_tension = valeur_analogique * 6; // On multiplie notre valeur obtenus pour avoir la tension d entree
+    genieWriteObject(GENIE_OBJ_METER , 0x00,valeur_tension);
+    return;
+    }
+
+void pause1()
+    {
+    if(pause == 0)
+        {
+            pause++;
+        }
+    else
+        {
+            pause--;
+        }
+    }
+
+/************************
+*  Programme principal  *
+*************************/
+
+int main()
+{
+    
+    wait(3);
+    DELROUGE = 0;
+    
+    /* Ecriture*/
+enableEEPROMWriting(); //autorisation d'ecriture dans l'eeprom
+writeEEPROMHalfWord(adresse, donnee1);
+writeEEPROMHalfWord(adresse+2, donnee2);
+writeEEPROMHalfWord(adresse+4, donnee3);
+disableEEPROMWriting(); //Interdiction d'ecriture
+   
+    SetupGenie();
+    genieWriteContrast(i); //Permet de modifier la luminosite
+    genieWriteObject(GENIE_OBJ_LED_DIGITS, 0x05, i);
+    BOUTONPAUSE.fall(&pause1);
+//Initialisation de l'interruption "Ticker" toutes les secondes 
+    Horloge_Global_Seconde.attach(&compt_secondes,1); //Appel de la fonction toutes les secondes.
+    Valeur_Tension_Volt.attach(&valeur_volt,30);
+
+    while(1) {
+            if(pause == 0)
+            {
+                DELVERTE = 0;
+                DELORANGE = 1;
+                bloqueur = 1;
+            }        
+            if(pause == 1)
+            {
+                DELVERTE = 1;
+                DELORANGE = 0;
+                bloqueur = 0;
+            }           
+             } // Fin while
+} // Fin main
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_genie.cpp	Tue Apr 07 12:24:23 2020 +0000
@@ -0,0 +1,617 @@
+
+#include "mbed.h"
+#include "mbed_genie.h"
+
+DigitalOut genieReset(PC_7);  //genie reset pin on pin 8 of the mbed
+
+Serial screen(PA_9,PA_10);
+Serial pc(USBTX,USBRX);
+Timer t;
+
+
+
+void           _genieFlushEventQueue        (void);
+void           _handleError                        (void);
+void           _geniePutchar                        (uint8_t c);
+uint8_t        _genieGetchar                        (void);
+void           _genieSetLinkState                (uint16_t newstate);
+uint16_t       _genieGetLinkState                (void);        
+bool           _genieEnqueueEvent                (uint8_t * data);
+//////////////////////////////////////////////////////////////
+// A structure to hold up to MAX_GENIE_EVENTS events receive
+// from the display
+//
+static genieEventQueueStruct _genieEventQueue;
+
+//////////////////////////////////////////////////////////////
+// Pointer to the user's event handler function
+//
+static genieUserEventHandlerPtr _genieUserHandler = NULL;
+
+
+//////////////////////////////////////////////////////////////
+// Simple 5-deep stack for the link state, this allows 
+// genieDoEvents() to save the current state, receive a frame,
+// then restore the state
+//
+static uint8_t _genieLinkStates[5] = {GENIE_LINK_IDLE};
+//
+// Stack pointer
+//
+static uint8_t *_genieLinkState = &_genieLinkStates[0];
+
+
+//////////////////////////////////////////////////////////////
+// Number of mS the genieGetChar() function will wait before
+// giving up on the display
+static int _genieTimeout = TIMEOUT_PERIOD;
+
+
+//////////////////////////////////////////////////////////////
+// Number of times we have had a timeout
+static int _genieTimeouts = 0;
+
+
+//////////////////////////////////////////////////////////////
+// Global error variable
+static int _genieError = ERROR_NONE;
+
+
+
+
+static uint8_t        rxframe_count = 0;
+
+
+//////////////////////////////////////////////////////////////
+// Number of fatal errors encountered
+static int _genieFatalErrors = 0;
+////////////////////// genieGetEventData ////////////////////////
+//
+// Returns the LSB and MSB of the event's data combined into
+// a single uint16
+//
+// The data is transmitted from the display in big-endian format 
+// and stored the same so the user can't just access it as an int 
+// directly from the structure. 
+//
+uint16_t genieGetEventData (genieFrame * e) {
+        return  (e->reportObject.data_msb << 8) + e->reportObject.data_lsb;
+}
+
+
+
+
+//////////////////////// genieEventIs ///////////////////////////
+//
+// Compares the cmd, object and index fields of the event's 
+// structure.
+//
+// Returns:                TRUE if all the fields match the caller's parms
+//                                FALSE if any of them don't
+//
+bool genieEventIs(genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index) {
+
+
+        return (e->reportObject.cmd == cmd &&
+                e->reportObject.object == object &&
+                e->reportObject.index == index);
+
+
+}
+
+////////////////////// _geniePushLinkState //////////////////////
+//
+// Push a link state onto a FILO stack
+//
+void _geniePushLinkState (uint8_t newstate) {
+
+
+        _genieLinkState++;
+        _genieSetLinkState(newstate);
+
+
+}
+
+
+////////////////////// _geniePopLinkState //////////////////////
+//
+// Pop a link state from a FILO stack
+//
+void _geniePopLinkState (void) {
+        if (_genieLinkState > &_genieLinkStates[0]) {
+                *_genieLinkState = 0xFF;
+                _genieLinkState--;
+        }
+}
+
+///////////////// _genieFlushSerialInput ///////////////////
+//
+// Removes and discards all characters from the currently 
+// used serial port's Rx buffer.
+//
+void _genieFlushSerialInput(void) {
+        do {
+                _genieGetchar();
+        } while (_genieError != ERROR_NOCHAR);
+}
+
+///////////////////////// _handleError /////////////////////////
+//
+// So far really just a debugging aid, but can be enhanced to
+// help recover from errors.
+//
+void _handleError (void) {
+//        Serial2.write (_genieError + (1<<5));
+//        if (_genieError == GENIE_NAK) genieResync();
+}
+
+
+
+
+////////////////////// _genieFlushEventQueue ////////////////////
+//
+// Reset all the event queue variables and start from scratch.
+//
+void _genieFlushEventQueue(void) {
+        _genieEventQueue.rd_index = 0;
+        _genieEventQueue.wr_index = 0;
+        _genieEventQueue.n_events = 0;
+}
+bool GenieReadable(void){
+    if (screen.readable())
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+///////////////////////// genieDoEvents /////////////////////////
+//
+// This is the heart of the Genie comms state machine.
+//
+uint16_t genieDoEvents (void) {
+        uint8_t c;
+        static uint8_t        rx_data[6];
+        static uint8_t        checksum = 0;
+
+        if (GenieReadable())
+        {
+            c = _genieGetchar();
+            //pc.putc(c);
+    
+            ////////////////////////////////////////////
+            //
+            // If there are no characters to process and we have 
+            // queued events call the user's handler function.
+            //
+            if (_genieError == ERROR_NOCHAR) {
+            //pc.printf("EventCalled!\n\r");
+                    if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
+                    return GENIE_EVENT_NONE;
+            }
+            
+            ///////////////////////////////////////////
+            //
+            // Main state machine
+            //
+            switch (_genieGetLinkState()) {
+                    case GENIE_LINK_IDLE:
+                            switch (c) {
+                                    case GENIE_REPORT_EVENT:
+                                    // event frame out of the blue, set the link state
+                                    // and fall through to the frame-accumulate code
+                                    // at the end of this function
+                                    _geniePushLinkState(GENIE_LINK_RXEVENT);
+                                    break;
+                                            
+                                    default:
+                                    // error, bad character, no other character 
+                                    // is acceptable in this state
+                                    return GENIE_EVENT_RXCHAR;
+                                    
+                            }
+                            break;
+                                    
+                    case GENIE_LINK_WFAN:
+                            switch (c) {
+    
+    
+                                    case GENIE_ACK:
+                                            _geniePopLinkState();
+                                            return GENIE_EVENT_RXCHAR;
+    
+    
+                                    case GENIE_NAK:
+                                            _geniePopLinkState();
+                                            _genieError = ERROR_NAK;
+                                            _handleError();
+                                            return GENIE_EVENT_RXCHAR;
+                            
+                                    case GENIE_REPORT_EVENT:
+                                            // event frame out of the blue while waiting for an ACK
+                                            // save/set the link state and fall through to the 
+                                            // frame-accumulate code at the end of this function
+                                            _geniePushLinkState(GENIE_LINK_RXEVENT);
+                                            break;
+    
+    
+                                    case GENIE_REPORT_OBJ:
+                                    default:
+                                            // error, bad character
+                                            return GENIE_EVENT_RXCHAR;        
+                            }
+                            break;
+    
+    
+                    case GENIE_LINK_WF_RXREPORT: // waiting for the first byte of a report
+                            switch (c) {
+                            
+                                    case GENIE_REPORT_EVENT:
+                                    // event frame out of the blue while waiting for the first
+                                    // byte of a report frame
+                                    // save/set the link state and fall through to the
+                                    // frame-accumulate code at the end of this function
+                                    _geniePushLinkState(GENIE_LINK_RXEVENT);
+                                    break;
+    
+    
+                                    case GENIE_REPORT_OBJ:
+                                    // first byte of a report frame
+                                    // replace the GENIE_LINK_WF_RXREPORT link state 
+                                    // with GENIE_LINK_RXREPORT to indicate that we
+                                    // are now receiving a report frame
+                                    _geniePopLinkState();
+                                    _geniePushLinkState(GENIE_LINK_RXREPORT);
+                                    break;
+    
+    
+                                    case GENIE_ACK:
+                                    case GENIE_NAK:
+                                    default:
+                                    // error, bad character
+                                    return GENIE_EVENT_RXCHAR;
+    //                                break;
+                            }
+    
+    
+                    case GENIE_LINK_RXREPORT:                // already receiving report
+                    case GENIE_LINK_RXEVENT:                // already receiving event
+                    default:
+                            break;
+                    
+            }
+    
+    
+            ///////////////////////////////////////////////////////
+            // We get here if we are in the process of receiving 
+            // a report or event frame. Accumulate GENIE_FRAME_SIZE 
+            // bytes into a local buffer then queue them as a frame
+            // into the event queue
+            //
+            if (_genieGetLinkState() == GENIE_LINK_RXREPORT || \
+                    _genieGetLinkState() == GENIE_LINK_RXEVENT) {
+                            
+                    checksum = (rxframe_count == 0) ? c : checksum ^ c;
+    
+    
+                    rx_data[rxframe_count] = c;
+    
+    
+                    if (rxframe_count == GENIE_FRAME_SIZE -1) {
+                    //pc.printf("FrameReceived!\n\r");
+                            // all bytes received, if the CS is good 
+                            // queue the frame and restore the link state
+                            if (checksum == 0) {
+                                    _genieEnqueueEvent(rx_data);
+                                    if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
+                                    //return GENIE_EVENT_NONE;
+                                    rxframe_count = 0;
+                                    // revert the link state to whatever it was before
+                                    // we started accumulating this frame
+                                    _geniePopLinkState();
+                                    return GENIE_EVENT_RXCHAR;
+                            } else {
+                                    _genieError = ERROR_BAD_CS;
+                                    _handleError();
+                            }        
+                    }
+                    rxframe_count++;
+                    return GENIE_EVENT_RXCHAR;
+            }
+    }   
+}
+
+////////////////////// genieDequeueEvent ///////////////////
+//
+// Copy the bytes from a queued input event to a buffer supplied 
+// by the caller.
+//
+// Parms:        genieFrame * buff, a pointer to the user's buffer
+//
+// Returns:        TRUE if there was an event to copy
+//                        FALSE if not
+//
+bool genieDequeueEvent(genieFrame * buff) {
+
+
+        if (_genieEventQueue.n_events > 0) {
+                memcpy (buff, &_genieEventQueue.frames[_genieEventQueue.rd_index], 
+                                GENIE_FRAME_SIZE);
+                _genieEventQueue.rd_index++;
+                _genieEventQueue.rd_index &= MAX_GENIE_EVENTS -1;
+                _genieEventQueue.n_events--;
+                return TRUE;
+        } 
+        return FALSE;
+}
+
+
+
+
+
+////////////////////// _genieWaitForIdle ////////////////////////
+//
+// Wait for the link to become idle or for the timeout period, 
+// whichever comes first.
+//
+void _genieWaitForIdle (void) {
+        uint16_t do_event_result;
+        long timeout = t.read_ms() + _genieTimeout;
+
+        for ( ; t.read_ms() < timeout;) {
+
+         
+            do_event_result = genieDoEvents();             
+                // if there was a character received from the 
+                // display restart the timeout because doEvents
+                // is in the process of receiving something
+                if (do_event_result == GENIE_EVENT_RXCHAR) {
+                        timeout = t.read_ms() + _genieTimeout;
+                        return;
+                }
+                
+                if (_genieGetLinkState() == GENIE_LINK_IDLE) {
+                        return;
+                }
+        }
+        _genieError = ERROR_TIMEOUT;
+        _handleError();
+        return;
+}
+
+///////////////////////// genieWriteObject //////////////////////
+//
+// Write data to an object on the display
+//
+uint16_t genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
+{
+        uint16_t msb, lsb ;
+        uint8_t checksum ;
+
+
+        _genieWaitForIdle();
+
+
+        lsb = data&0xFF;
+        msb = (data>>8) & 0xFF;
+
+
+        _genieError = ERROR_NONE;
+
+
+        _geniePutchar(GENIE_WRITE_OBJ) ; checksum  = GENIE_WRITE_OBJ ;
+        _geniePutchar(object) ;          checksum ^= object ;
+        _geniePutchar(index) ;           checksum ^= index ;
+        _geniePutchar(msb) ;             checksum ^= msb;
+        _geniePutchar(lsb) ;             checksum ^= lsb;
+        _geniePutchar(checksum) ;
+
+
+        _geniePushLinkState(GENIE_LINK_WFAN);        
+}
+
+/////////////////////// genieWriteContrast //////////////////////
+// 
+// Alter the display contrast (backlight)
+//
+// Parms:        uint8_t value: The required contrast setting, only
+//                values from 0 to 15 are valid. 0 or 1 for most displays
+//      and 0 to 15 for the uLCD-43
+//
+void genieWriteContrast (uint16_t value) {
+        unsigned int checksum ;
+
+
+        _genieWaitForIdle();
+
+
+        _geniePutchar(GENIE_WRITE_CONTRAST) ; checksum  = GENIE_WRITE_CONTRAST ;
+        _geniePutchar(value) ;                checksum ^= value ;
+        _geniePutchar(checksum) ;
+
+
+        _geniePushLinkState(GENIE_LINK_WFAN);
+
+
+}
+
+
+//////////////////////// _genieWriteStrX ///////////////////////
+//
+// Non-user function used by genieWriteStr() and genieWriteStrU()
+//
+static int _genieWriteStrX (uint16_t code, uint16_t index, char *string)
+{
+        char *p ;
+        unsigned int checksum ;
+        int len = strlen (string) ;
+
+
+        if (len > 255)
+        return -1 ;
+
+
+        _genieWaitForIdle();
+
+
+        _geniePutchar(code) ;               checksum  = code ;
+        _geniePutchar(index) ;              checksum ^= index ;
+        _geniePutchar((unsigned char)len) ; checksum ^= len ;
+        for (p = string ; *p ; ++p)        {
+                _geniePutchar (*p) ;
+                checksum ^= *p ;
+        }
+        _geniePutchar(checksum) ;
+
+
+        _geniePushLinkState(GENIE_LINK_WFAN);
+
+
+        return 0 ;
+}
+/////////////////////// genieWriteStr ////////////////////////
+//
+// Write a string to the display (ASCII)
+//
+uint16_t genieWriteStr (uint16_t index, char *string) {
+ 
+  return _genieWriteStrX (GENIE_WRITE_STR, index, string);
+}
+
+
+/////////////////////// genieWriteStrU ////////////////////////
+//
+// Write a string to the display (Unicode)
+//
+uint16_t genieWriteStrU (uint16_t index, char *string) {
+
+
+  return _genieWriteStrX (GENIE_WRITE_STRU, index, string);
+
+
+}
+/////////////////// genieAttachEventHandler //////////////////////
+//
+// "Attaches" a pointer to the users event handler by writing 
+// the pointer into the variable used by doEVents()
+//
+void genieAttachEventHandler (genieUserEventHandlerPtr handler) {
+        _genieUserHandler = handler;
+}
+
+
+////////////////////// _genieEnqueueEvent ///////////////////
+//
+// Copy the bytes from a buffer supplied by the caller 
+// to the input queue 
+//
+// Parms:        uint8_t * data, a pointer to the user's data
+//
+// Returns:        TRUE if there was an empty location in the queue
+//                                to copy the data into
+//                        FALSE if not
+// Sets:        ERROR_REPLY_OVR if there was no room in the queue
+//
+bool _genieEnqueueEvent (uint8_t * data) {
+
+
+        if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) {
+                memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data, 
+                                GENIE_FRAME_SIZE);
+                _genieEventQueue.wr_index++;
+                _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1;
+                _genieEventQueue.n_events++;
+                return TRUE;
+        } else {
+                _genieError = ERROR_REPLY_OVR;
+                _handleError();
+                return FALSE;
+        }
+}
+///////////////////// _genieSetLinkState ////////////////////////
+//
+// Set the logical state of the link to the display.
+//
+// Parms:        uint16_t newstate, a value to be written to the 
+//                                link's _genieLinkState variable. Valid values are
+//                GENIE_LINK_IDLE                        0
+//                GENIE_LINK_WFAN                        1 // waiting for Ack or Nak
+//                GENIE_LINK_WF_RXREPORT        2 // waiting for a report frame
+//                GENIE_LINK_RXREPORT                3 // receiving a report frame
+//                GENIE_LINK_RXEVENT                4 // receiving an event frame
+//                GENIE_LINK_SHDN                        5
+//
+void _genieSetLinkState (uint16_t newstate) {
+        
+        *_genieLinkState = newstate;
+
+
+        if (newstate == GENIE_LINK_RXREPORT || \
+                newstate == GENIE_LINK_RXEVENT)
+                rxframe_count = 0;        
+}
+
+
+/////////////////////// _genieGetLinkState //////////////////////
+//
+// Get the current logical state of the link to the display.
+//
+uint16_t _genieGetLinkState (void) {
+        return *_genieLinkState;
+}
+
+/////////////////////// _geniePutchar ///////////////////////////
+//
+// Output the supplied character to the Genie display over 
+// the selected serial port
+//
+void _geniePutchar (uint8_t c) {
+  //      if (screen != NULL)
+                screen.putc(c);
+}
+
+
+//////////////////////// _genieGetchar //////////////////////////
+//
+// Get a character from the selected Genie serial port
+//
+// Returns:        ERROR_NOHANDLER if an Rx handler has not 
+//                                been defined
+//                        ERROR_NOCHAR if no bytes have beeb received
+//                        The char if there was one to get
+// Sets:        _genieError with any errors encountered
+//
+uint8_t _genieGetchar() {
+        uint16_t result;
+
+
+        _genieError = ERROR_NONE;
+
+        return (screen.getc());
+}
+
+void RxIrqHandler(void)
+{
+    do 
+    {
+        genieDoEvents();
+    }
+    while(screen.readable ());
+}
+
+
+void TickerIrq(void)
+{
+}
+
+
+void SetupGenie(void)
+{
+    screen.baud(19200);
+    pc.baud(19200);
+    screen.attach(&RxIrqHandler,Serial::RxIrq);
+    //t.start();
+ //   EventChk.attach(&TickerIrq,0.05);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_genie.h	Tue Apr 07 12:24:23 2020 +0000
@@ -0,0 +1,136 @@
+#undef  GENIE_DEBUG
+
+#define GENIE_VERSION   "GenieMbed 17-Nov-2013"
+
+// Genie commands & replys:
+
+#define GENIE_ACK       0x06
+#define GENIE_NAK       0x15
+
+#define TIMEOUT_PERIOD  500
+#define RESYNC_PERIOD   100
+
+#define GENIE_READ_OBJ          0
+#define GENIE_WRITE_OBJ         1
+#define GENIE_WRITE_STR         2
+#define GENIE_WRITE_STRU        3
+#define GENIE_WRITE_CONTRAST    4
+#define GENIE_REPORT_OBJ        5
+#define GENIE_REPORT_EVENT      7
+
+// Objects
+//  the manual says:
+//      Note: Object IDs may change with future releases; it is not
+//      advisable to code their values as constants.
+ 
+#define GENIE_OBJ_DIPSW         0
+#define GENIE_OBJ_KNOB          1
+#define GENIE_OBJ_ROCKERSW      2
+#define GENIE_OBJ_ROTARYSW      3
+#define GENIE_OBJ_SLIDER        4
+#define GENIE_OBJ_TRACKBAR      5
+#define GENIE_OBJ_WINBUTTON     6
+#define GENIE_OBJ_ANGULAR_METER 7
+#define GENIE_OBJ_COOL_GAUGE    8
+#define GENIE_OBJ_CUSTOM_DIGITS 9
+#define GENIE_OBJ_FORM          10
+#define GENIE_OBJ_GAUGE         11
+#define GENIE_OBJ_IMAGE         12
+#define GENIE_OBJ_KEYBOARD      13
+#define GENIE_OBJ_LED           14
+#define GENIE_OBJ_LED_DIGITS    15
+#define GENIE_OBJ_METER         16
+#define GENIE_OBJ_STRINGS       17
+#define GENIE_OBJ_THERMOMETER   18
+#define GENIE_OBJ_USER_LED      19
+#define GENIE_OBJ_VIDEO         20
+#define GENIE_OBJ_STATIC_TEXT   21
+#define GENIE_OBJ_SOUND         22
+#define GENIE_OBJ_TIMER         23
+#define GENIE_OBJ_SPECTRUM      24
+#define GENIE_OBJ_SCOPE         25
+#define GENIE_OBJ_TANK          26
+#define GENIE_OBJ_USERIMAGES    27
+#define GENIE_OBJ_PINOUTPUT     28
+#define GENIE_OBJ_PININPUT      29
+#define GENIE_OBJ_4DBUTTON      30
+#define GENIE_OBJ_ANIBUTTON     31
+#define GENIE_OBJ_COLORPICKER   32
+#define GENIE_OBJ_USERBUTTON    33
+
+// Structure to store replys returned from a display
+
+#define     GENIE_FRAME_SIZE    6
+struct genieFrameReportObj {
+    uint8_t     cmd;
+    uint8_t     object;
+    uint8_t     index;
+    uint8_t     data_msb;
+    uint8_t     data_lsb;
+};
+ 
+/////////////////////////////////////////////////////////////////////
+// The Genie frame definition
+//
+// The union allows the data to be referenced as an array of uint8_t
+// or a structure of type genieFrameReportObj, eg
+//
+//  genieFrame f;
+//  f.bytes[4];
+//  f.reportObject.data_lsb
+//
+//  both methods get the same byte
+//
+union genieFrame {
+    uint8_t             bytes[GENIE_FRAME_SIZE];
+    genieFrameReportObj reportObject;
+};
+
+#define MAX_GENIE_EVENTS    16  // MUST be a power of 2
+#define MAX_GENIE_FATALS    10
+
+struct genieEventQueueStruct {
+    genieFrame  frames[MAX_GENIE_EVENTS];
+    uint8_t     rd_index;
+    uint8_t     wr_index;
+    uint8_t     n_events;
+};
+
+typedef void        (*geniePutCharFuncPtr)      (uint8_t c, uint32_t baud);
+typedef uint16_t    (*genieGetCharFuncPtr)      (void);
+typedef void        (*genieUserEventHandlerPtr) (void);
+
+#define ERROR_NONE          0
+#define ERROR_TIMEOUT       -1  // 255  0xFF
+#define ERROR_NOHANDLER     -2  // 254  0xFE
+#define ERROR_NOCHAR        -3  // 253  0xFD
+#define ERROR_NAK           -4  // 252  0xFC
+#define ERROR_REPLY_OVR     -5  // 251  0xFB
+#define ERROR_RESYNC        -6  // 250  0xFA
+#define ERROR_NODISPLAY     -7  // 249  0xF9
+#define ERROR_BAD_CS        -8  // 248  0xF8
+
+#define GENIE_LINK_IDLE         0
+#define GENIE_LINK_WFAN         1 // waiting for Ack or Nak
+#define GENIE_LINK_WF_RXREPORT  2 // waiting for a report frame
+#define GENIE_LINK_RXREPORT     3 // receiving a report frame
+#define GENIE_LINK_RXEVENT      4 // receiving an event frame
+#define GENIE_LINK_SHDN         5
+
+#define GENIE_EVENT_NONE    0
+#define GENIE_EVENT_RXCHAR  1
+
+#ifndef        TRUE
+#define        TRUE        (1==1)
+#define        FALSE        (!TRUE)
+#endif
+
+void            SetupGenie(void);
+void            genieAttachEventHandler     (genieUserEventHandlerPtr handler);
+extern bool     genieDequeueEvent           (genieFrame * buff);
+extern bool     genieEventIs                (genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index);
+extern uint16_t genieGetEventData           (genieFrame * e); 
+extern uint16_t genieWriteObject            (uint16_t object, uint16_t index, uint16_t data);
+extern uint16_t        genieWriteStr                        (uint16_t index, char *string);
+extern void                genieWriteContrast                (uint16_t value);
+