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:
7:6edb20845684
Parent:
6:f4d3977b0eae
Child:
8:b5ba0df2d0db
--- a/mbed_genie.cpp	Fri Jul 04 02:44:49 2014 +0000
+++ b/mbed_genie.cpp	Sat Jul 05 15:11:57 2014 +0000
@@ -6,18 +6,79 @@
     //reset the 4d screen
     _reset = 0;
     _screen.baud(9600);
+    _genieUserHandler = NULL;
 }
 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();
+    wait(3.0);  //4D datasheet says that the screen can take up to 3000 ms before
+                //becomming responsive to serial commands.        
+    _t.start();
+    Reset();
+    _genieFlushEventQueue();
+    _screen.attach(this,&Mbed4dGenie::RxIrqHandler,Serial::RxIrq);
+}
+
+
+void Mbed4dGenie::RxIrqHandler(void)
+{
+    char c;
+    //Loop to read all byte present in UART FIFO
+    do
+    {
+        c = _screen.getc();
+        ManageReceiveData(c);
+    }
+    while(_screen.readable());
+}
+
+void Mbed4dGenie::ManageReceiveData(char data)
+{
+    switch(state)
+    {
+        case CommIdle: 
         
-    _t.start();
+            if(data == GENIE_ACK || data == GENIE_NAK)
+            {
+                LastResponse = data;
+            }   
+            else if(data == GENIE_REPORT_OBJ || data == GENIE_REPORT_EVENT)
+            {
+                checksum = data;
+                rx_data[rxframe_count++] = data;
+                state = CommInProgress; 
+                LastResponse = NO_RESPONSE;             
+            }                     
+            break;
+        
+        
+        case CommInProgress: 
+            checksum = checksum ^ data;
+            rx_data[rxframe_count++] = data;
+            
+            if(rxframe_count >= GENIE_FRAME_SIZE)
+            {
+                if (checksum == 0) {
+                        _genieEnqueueEvent(rx_data); 
+                        if(_genieUserHandler != NULL)
+                        {
+                            (_genieUserHandler)();
+                        }
+                    } 
+                state = CommIdle;
+                rxframe_count = 0;
+                LastResponse = NO_RESPONSE;
+            }        
+            break;
+        default:
+            state = CommIdle;
+            rxframe_count = 0;
+            LastResponse = NO_RESPONSE;
+            break;
+    }
 }
 
+
 ///////////////////////// genieWriteObject //////////////////////
 //
 // Write data to an object on the display
@@ -27,6 +88,10 @@
     uint16_t msb, lsb ;
     uint8_t checksum ;
     
+    //wait for interface to be ready before sending stuff
+    if(WaitForIdle())
+        return ERROR_RESYNC;
+
     lsb = data&0xFF;
     msb = (data>>8) & 0xFF;
     
@@ -42,32 +107,159 @@
     checksum ^= lsb;
     _screen.putc(checksum) ;
     
-       
+     return Mbed4dGenie::WaitForAnswer();    
+}
+int8_t Mbed4dGenie::genieWriteStr (uint16_t index, char *string)
+{
+        char *p ;
+        unsigned int checksum ;
+        int len = strlen (string) ;
+
+
+        if (len > 255)
+        return -1 ;
+
+
+        //wait for interface to be ready before sending stuff
+        if(WaitForIdle())
+            return ERROR_RESYNC;
+
+
+        _screen.putc(GENIE_WRITE_STR) ;               checksum  = GENIE_WRITE_STR ;
+        _screen.putc(index) ;              checksum ^= index ;
+        _screen.putc((unsigned char)len) ; checksum ^= len ;
+        for (p = string ; *p ; ++p)        {
+                _screen.putc (*p) ;
+                checksum ^= *p ;
+        }
+        _screen.putc(checksum) ;
 
-     return  Mbed4dGenie::WaitForAnswer();    
+        return  Mbed4dGenie::WaitForAnswer();
+}
+int8_t  Mbed4dGenie::genieReadObj (uint16_t object, uint16_t index)
+{
+    //wait for interface to be ready before sending stuff
+    if(WaitForIdle())
+        return ERROR_RESYNC;
+    unsigned int checksum ;
+    
+    _screen.putc(GENIE_READ_OBJ) ;     checksum  = GENIE_READ_OBJ ;
+    _screen.putc(object) ;             checksum ^= object ;   
+    _screen.putc(index) ;              checksum ^= index ; 
+    _screen.putc(checksum) ;
+        
+    return  0;//Mbed4dGenie::WaitForAnswer();
 }
-
+void Mbed4dGenie::writec(char data)
+{
+    _screen.putc(data);
+}
+bool Mbed4dGenie::WaitForIdle()
+{
+    long timeout = _t.read_ms() + TIMEOUT_PERIOD;
+    long timerReading = 0;
+    
+    while(timerReading < timeout && state != CommIdle)
+    {
+        timerReading = _t.read_ms();
+    }
+    LastResponse = 0;
+    return (timerReading >= timeout);
+}
 
 int8_t Mbed4dGenie::WaitForAnswer()
 {
-    int8_t operation_result = 0; 
     
     long timeout = _t.read_ms() + TIMEOUT_PERIOD;
     long timerReading = 0;
-    while(operation_result != GENIE_ACK && operation_result != ERROR_NAK && timerReading < timeout)
+    while(LastResponse != GENIE_ACK && LastResponse != ERROR_NAK && timerReading < timeout)
     {
-        if(_screen.readable())
-            operation_result = _screen.getc();
         timerReading = _t.read_ms();
     }
            
-    if(operation_result == ERROR_NAK)
+    if(LastResponse == ERROR_NAK)
     {
         return ERROR_NONE;
     }
-    else if(timerReading >= timeout)
+    else if(LastResponse >= timeout)
     {   
         return ERROR_TIMEOUT;
     }
     return ERROR_NONE;
+}
+
+void Mbed4dGenie::Reset(void)
+{
+    LastResponse = NO_RESPONSE;
+    state = CommIdle;
+    while(_screen.readable())
+        _screen.getc();
+}
+
+////////////////////// _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;
+}
+
+////////////////////// _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 {
+                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;
+}
+void Mbed4dGenie::genieAttachEventHandler(genieUserEventHandlerPtr handler)
+{
+    _genieUserHandler = handler;
+}
+bool Mbed4dGenie::PendingFrames(void)
+{
+    return (_genieEventQueue.n_events>0);
 }
\ No newline at end of file