Mbed 4dGenie class

Dependents:   Genie_Test 039847382-S3_DS1621_and_LCD_V1

This is a work in progress.

4dGenie class to use with 4dLCD screens that are using the genie environment.

There are still some rare occasions where the 4dLCD might crash, for now i have no solution to this except doing a reset of the 4dLCD.

Please make sure to have the most up to date PmmC loaded on the screen.

usage example :

Mbed4dGenie test program

#include "mbed.h"
#include "mbed_genie.h"

DigitalOut myled(LED1);
/*
    The Mbed4dGenie class requires 3 parameters
    1 - Tx pin
    2 - Rx pin
    3 - Reset pin
*/
Mbed4dGenie lcd4d(PTE0,PTE1,PTB9);



int main() {
    int temp = 0;
printf("Mbed Genie demo \n\r");
lcd4d.Start();


 /*
 for example, in this loop we increment the thermometer0 object from 0 to 100
 */
 
    while(1) {
        if(temp >= 100)
        {
            temp = -1;
        }
        else
        {
            temp++;
        }

        lcd4d.genieWriteObject(GENIE_OBJ_LED_DIGITS,1,temp);

        myled = 1;
        wait(0.05);
        myled = 0;
        wait(0.05);
    }
}
Revision:
6:f4d3977b0eae
Parent:
3:11c49c49cd1a
Child:
7:6edb20845684
--- a/mbed_genie.cpp	Sun Feb 23 17:32:37 2014 +0000
+++ b/mbed_genie.cpp	Fri Jul 04 02:44:49 2014 +0000
@@ -1,540 +1,73 @@
-
 #include "mbed.h"
 #include "mbed_genie.h"
 
-Serial pc(USBTX,USBRX);
-
 Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin) : _screen(TxPin,RxPin) , _reset(resetpin)
 {
     //reset the 4d screen
-    _reset = 1;
-    wait(0.25);
     _reset = 0;
-    _genieLinkStates[4] = GENIE_LINK_IDLE;
-    _genieLinkStates[3] = GENIE_LINK_IDLE;
-    _genieLinkStates[2] = GENIE_LINK_IDLE;
-    _genieLinkStates[1] = GENIE_LINK_IDLE;
-    _genieLinkStates[0] = GENIE_LINK_IDLE;
-    _genieLinkState = &_genieLinkStates[0];
-    
-    _genieTimeout = TIMEOUT_PERIOD;
-    _genieError = ERROR_NONE;
-    rxframe_count = 0;
-    
-    _genieUserHandler = NULL;
-    _screen.attach(this,&Mbed4dGenie::RxIrqHandler,Serial::RxIrq);
-    _t.start();
-}
-void Mbed4dGenie::genieAttachEventHandler(genieUserEventHandlerPtr handler)
-{
-    _genieUserHandler = handler;
-}
-void Mbed4dGenie::RxIrqHandler(void)
-{
-    do 
-    {
-        genieDoEvents();
-    }
-    while(_screen.readable ());
+    _screen.baud(9600);
 }
-//////////////////////// _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 Mbed4dGenie::_genieGetchar() {
-
-        _genieError = ERROR_NONE;
-
-        return (_screen.getc());
-}
-///////////////////// _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 Mbed4dGenie::_genieSetLinkState (uint16_t newstate) {
+void Mbed4dGenie::Start()
+{
+    _reset = 1;
+    wait(0.2);  //wait some time to let the lcd screen intialised itself
+    //empty the uart buffer
+    while(_screen.readable())
+        _screen.getc();
         
-        *_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 Mbed4dGenie::_genieGetLinkState (void) {
-        return *_genieLinkState;
+    _t.start();
 }
 
-/////////////////////// _geniePutchar ///////////////////////////
-//
-// Output the supplied character to the Genie display over 
-// the selected serial port
-//
-void Mbed4dGenie::_geniePutchar (uint8_t c) {
-  //      if (screen != NULL)
-                _screen.putc(c);
-}
-////////////////////// _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 Mbed4dGenie::_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;
-        }
-}
-////////////////////// 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 Mbed4dGenie::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 Mbed4dGenie::_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 Mbed4dGenie::genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
+int8_t Mbed4dGenie::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);  
-        return GENIE_EVENT_NONE;      
-}
-/////////////////////// 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 Mbed4dGenie::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()
-//
-int Mbed4dGenie::_genieWriteStrX (uint16_t code, uint16_t index, char *string)
-{
-        char *p ;
-        unsigned int checksum ;
-        int len = strlen (string) ;
-
-
-        if (len > 255)
-        return -1 ;
-
-
-        _genieWaitForIdle();
-
+    uint16_t msb, lsb ;
+    uint8_t checksum ;
+    
+    lsb = data&0xFF;
+    msb = (data>>8) & 0xFF;
+    
+    _screen.putc(GENIE_WRITE_OBJ) ; 
+    checksum  = GENIE_WRITE_OBJ ;
+    _screen.putc(object) ;          
+    checksum ^= object ;
+    _screen.putc(index) ;           
+    checksum ^= index ;
+    _screen.putc(msb) ;             
+    checksum ^= msb;
+    _screen.putc(lsb) ;             
+    checksum ^= lsb;
+    _screen.putc(checksum) ;
+    
+       
 
-        _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 Mbed4dGenie::genieWriteStr (uint16_t index, char *string) {
- 
-  return _genieWriteStrX (GENIE_WRITE_STR, index, string);
-}
-/////////////////////// genieWriteStrU ////////////////////////
-//
-// Write a string to the display (Unicode)
-//
-uint16_t Mbed4dGenie::genieWriteStrU (uint16_t index, char *string) {
-
-  return _genieWriteStrX (GENIE_WRITE_STRU, index, string);
-
-}
-//////////////////////////////////////////////////////////////
-// 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 Mbed4dGenie::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 Mbed4dGenie::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 Mbed4dGenie::_geniePushLinkState (uint8_t newstate) {
-
-
-        _genieLinkState++;
-        _genieSetLinkState(newstate);
-
-
+     return  Mbed4dGenie::WaitForAnswer();    
 }
 
 
-////////////////////// _geniePopLinkState //////////////////////
-//
-// Pop a link state from a FILO stack
-//
-void Mbed4dGenie::_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 Mbed4dGenie::_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 Mbed4dGenie::_handleError (void) {
-}
-
-
-
-
-////////////////////// _genieFlushEventQueue ////////////////////
-//
-// Reset all the event queue variables and start from scratch.
-//
-void Mbed4dGenie::_genieFlushEventQueue(void) {
-        _genieEventQueue.rd_index = 0;
-        _genieEventQueue.wr_index = 0;
-        _genieEventQueue.n_events = 0;
-}
-bool Mbed4dGenie::GenieReadable(void){
-    if (_screen.readable())
-    {
-        return TRUE;
-    }
-    else
-    {
-        return FALSE;
-    }
-}
-///////////////////////// genieDoEvents /////////////////////////
-//
-// This is the heart of the Genie comms state machine.
-//
-uint16_t Mbed4dGenie::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) {
-    
+int8_t Mbed4dGenie::WaitForAnswer()
+{
+    int8_t operation_result = 0; 
     
-                                    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;
-            }
-    }  
-    return GENIE_EVENT_NONE; 
+    long timeout = _t.read_ms() + TIMEOUT_PERIOD;
+    long timerReading = 0;
+    while(operation_result != GENIE_ACK && operation_result != ERROR_NAK && timerReading < timeout)
+    {
+        if(_screen.readable())
+            operation_result = _screen.getc();
+        timerReading = _t.read_ms();
+    }
+           
+    if(operation_result == ERROR_NAK)
+    {
+        return ERROR_NONE;
+    }
+    else if(timerReading >= timeout)
+    {   
+        return ERROR_TIMEOUT;
+    }
+    return ERROR_NONE;
 }
\ No newline at end of file