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);
    }
}
Committer:
chris215
Date:
Sun Jul 06 17:22:32 2014 +0000
Revision:
8:b5ba0df2d0db
Parent:
7:6edb20845684
Child:
9:b74deaac80f9
Improve stability when using obj read commands and listening to Genie events.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chris215 0:d2ed5a44c802 1 #include "mbed.h"
chris215 0:d2ed5a44c802 2 #include "mbed_genie.h"
chris215 0:d2ed5a44c802 3
chris215 3:11c49c49cd1a 4 Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin) : _screen(TxPin,RxPin) , _reset(resetpin)
chris215 2:f283764fe9b7 5 {
chris215 3:11c49c49cd1a 6 //reset the 4d screen
chris215 3:11c49c49cd1a 7 _reset = 0;
chris215 6:f4d3977b0eae 8 _screen.baud(9600);
chris215 7:6edb20845684 9 _genieUserHandler = NULL;
chris215 8:b5ba0df2d0db 10 RxStateTimeoutErrors = 0;
chris215 2:f283764fe9b7 11 }
chris215 6:f4d3977b0eae 12 void Mbed4dGenie::Start()
chris215 6:f4d3977b0eae 13 {
chris215 6:f4d3977b0eae 14 _reset = 1;
chris215 7:6edb20845684 15 wait(3.0); //4D datasheet says that the screen can take up to 3000 ms before
chris215 7:6edb20845684 16 //becomming responsive to serial commands.
chris215 7:6edb20845684 17 _t.start();
chris215 7:6edb20845684 18 Reset();
chris215 7:6edb20845684 19 _genieFlushEventQueue();
chris215 7:6edb20845684 20 _screen.attach(this,&Mbed4dGenie::RxIrqHandler,Serial::RxIrq);
chris215 7:6edb20845684 21 }
chris215 7:6edb20845684 22
chris215 7:6edb20845684 23
chris215 7:6edb20845684 24 void Mbed4dGenie::RxIrqHandler(void)
chris215 7:6edb20845684 25 {
chris215 7:6edb20845684 26 char c;
chris215 7:6edb20845684 27 //Loop to read all byte present in UART FIFO
chris215 7:6edb20845684 28 do
chris215 7:6edb20845684 29 {
chris215 7:6edb20845684 30 c = _screen.getc();
chris215 7:6edb20845684 31 ManageReceiveData(c);
chris215 7:6edb20845684 32 }
chris215 7:6edb20845684 33 while(_screen.readable());
chris215 7:6edb20845684 34 }
chris215 7:6edb20845684 35
chris215 7:6edb20845684 36 void Mbed4dGenie::ManageReceiveData(char data)
chris215 7:6edb20845684 37 {
chris215 7:6edb20845684 38 switch(state)
chris215 7:6edb20845684 39 {
chris215 7:6edb20845684 40 case CommIdle:
chris215 2:f283764fe9b7 41
chris215 7:6edb20845684 42 if(data == GENIE_ACK || data == GENIE_NAK)
chris215 7:6edb20845684 43 {
chris215 7:6edb20845684 44 LastResponse = data;
chris215 7:6edb20845684 45 }
chris215 7:6edb20845684 46 else if(data == GENIE_REPORT_OBJ || data == GENIE_REPORT_EVENT)
chris215 7:6edb20845684 47 {
chris215 8:b5ba0df2d0db 48 RxMaxTimeout = _t.read_ms() + RESYNC_PERIOD;
chris215 7:6edb20845684 49 checksum = data;
chris215 7:6edb20845684 50 rx_data[rxframe_count++] = data;
chris215 8:b5ba0df2d0db 51 state = CommInProgress;
chris215 7:6edb20845684 52 }
chris215 7:6edb20845684 53 break;
chris215 7:6edb20845684 54
chris215 7:6edb20845684 55
chris215 7:6edb20845684 56 case CommInProgress:
chris215 7:6edb20845684 57 checksum = checksum ^ data;
chris215 7:6edb20845684 58 rx_data[rxframe_count++] = data;
chris215 7:6edb20845684 59
chris215 7:6edb20845684 60 if(rxframe_count >= GENIE_FRAME_SIZE)
chris215 7:6edb20845684 61 {
chris215 7:6edb20845684 62 if (checksum == 0) {
chris215 7:6edb20845684 63 _genieEnqueueEvent(rx_data);
chris215 7:6edb20845684 64 if(_genieUserHandler != NULL)
chris215 7:6edb20845684 65 {
chris215 7:6edb20845684 66 (_genieUserHandler)();
chris215 7:6edb20845684 67 }
chris215 7:6edb20845684 68 }
chris215 7:6edb20845684 69 state = CommIdle;
chris215 7:6edb20845684 70 rxframe_count = 0;
chris215 7:6edb20845684 71 LastResponse = NO_RESPONSE;
chris215 7:6edb20845684 72 }
chris215 7:6edb20845684 73 break;
chris215 7:6edb20845684 74 default:
chris215 7:6edb20845684 75 state = CommIdle;
chris215 7:6edb20845684 76 rxframe_count = 0;
chris215 7:6edb20845684 77 LastResponse = NO_RESPONSE;
chris215 7:6edb20845684 78 break;
chris215 7:6edb20845684 79 }
chris215 2:f283764fe9b7 80 }
chris215 2:f283764fe9b7 81
chris215 7:6edb20845684 82
chris215 2:f283764fe9b7 83 ///////////////////////// genieWriteObject //////////////////////
chris215 0:d2ed5a44c802 84 //
chris215 2:f283764fe9b7 85 // Write data to an object on the display
chris215 0:d2ed5a44c802 86 //
chris215 6:f4d3977b0eae 87 int8_t Mbed4dGenie::genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
chris215 2:f283764fe9b7 88 {
chris215 6:f4d3977b0eae 89 uint16_t msb, lsb ;
chris215 6:f4d3977b0eae 90 uint8_t checksum ;
chris215 6:f4d3977b0eae 91
chris215 7:6edb20845684 92 //wait for interface to be ready before sending stuff
chris215 7:6edb20845684 93 if(WaitForIdle())
chris215 7:6edb20845684 94 return ERROR_RESYNC;
chris215 7:6edb20845684 95
chris215 6:f4d3977b0eae 96 lsb = data&0xFF;
chris215 6:f4d3977b0eae 97 msb = (data>>8) & 0xFF;
chris215 6:f4d3977b0eae 98
chris215 6:f4d3977b0eae 99 _screen.putc(GENIE_WRITE_OBJ) ;
chris215 6:f4d3977b0eae 100 checksum = GENIE_WRITE_OBJ ;
chris215 6:f4d3977b0eae 101 _screen.putc(object) ;
chris215 6:f4d3977b0eae 102 checksum ^= object ;
chris215 6:f4d3977b0eae 103 _screen.putc(index) ;
chris215 6:f4d3977b0eae 104 checksum ^= index ;
chris215 6:f4d3977b0eae 105 _screen.putc(msb) ;
chris215 6:f4d3977b0eae 106 checksum ^= msb;
chris215 6:f4d3977b0eae 107 _screen.putc(lsb) ;
chris215 6:f4d3977b0eae 108 checksum ^= lsb;
chris215 6:f4d3977b0eae 109 _screen.putc(checksum) ;
chris215 6:f4d3977b0eae 110
chris215 7:6edb20845684 111 return Mbed4dGenie::WaitForAnswer();
chris215 7:6edb20845684 112 }
chris215 7:6edb20845684 113 int8_t Mbed4dGenie::genieWriteStr (uint16_t index, char *string)
chris215 7:6edb20845684 114 {
chris215 7:6edb20845684 115 char *p ;
chris215 7:6edb20845684 116 unsigned int checksum ;
chris215 7:6edb20845684 117 int len = strlen (string) ;
chris215 7:6edb20845684 118
chris215 7:6edb20845684 119
chris215 7:6edb20845684 120 if (len > 255)
chris215 7:6edb20845684 121 return -1 ;
chris215 7:6edb20845684 122
chris215 7:6edb20845684 123
chris215 7:6edb20845684 124 //wait for interface to be ready before sending stuff
chris215 7:6edb20845684 125 if(WaitForIdle())
chris215 7:6edb20845684 126 return ERROR_RESYNC;
chris215 7:6edb20845684 127
chris215 7:6edb20845684 128
chris215 7:6edb20845684 129 _screen.putc(GENIE_WRITE_STR) ; checksum = GENIE_WRITE_STR ;
chris215 7:6edb20845684 130 _screen.putc(index) ; checksum ^= index ;
chris215 7:6edb20845684 131 _screen.putc((unsigned char)len) ; checksum ^= len ;
chris215 7:6edb20845684 132 for (p = string ; *p ; ++p) {
chris215 7:6edb20845684 133 _screen.putc (*p) ;
chris215 7:6edb20845684 134 checksum ^= *p ;
chris215 7:6edb20845684 135 }
chris215 7:6edb20845684 136 _screen.putc(checksum) ;
chris215 2:f283764fe9b7 137
chris215 7:6edb20845684 138 return Mbed4dGenie::WaitForAnswer();
chris215 7:6edb20845684 139 }
chris215 7:6edb20845684 140 int8_t Mbed4dGenie::genieReadObj (uint16_t object, uint16_t index)
chris215 7:6edb20845684 141 {
chris215 7:6edb20845684 142 //wait for interface to be ready before sending stuff
chris215 7:6edb20845684 143 if(WaitForIdle())
chris215 7:6edb20845684 144 return ERROR_RESYNC;
chris215 7:6edb20845684 145 unsigned int checksum ;
chris215 7:6edb20845684 146
chris215 7:6edb20845684 147 _screen.putc(GENIE_READ_OBJ) ; checksum = GENIE_READ_OBJ ;
chris215 7:6edb20845684 148 _screen.putc(object) ; checksum ^= object ;
chris215 7:6edb20845684 149 _screen.putc(index) ; checksum ^= index ;
chris215 7:6edb20845684 150 _screen.putc(checksum) ;
chris215 7:6edb20845684 151
chris215 8:b5ba0df2d0db 152 //Here we dont wiat for a typical answer
chris215 8:b5ba0df2d0db 153 //The screen will respond with an NACK if the command was not understood, otherwise it will send a report object frame
chris215 8:b5ba0df2d0db 154 return WaitForReadAnswer();
chris215 0:d2ed5a44c802 155 }
chris215 7:6edb20845684 156 void Mbed4dGenie::writec(char data)
chris215 7:6edb20845684 157 {
chris215 7:6edb20845684 158 _screen.putc(data);
chris215 7:6edb20845684 159 }
chris215 7:6edb20845684 160 bool Mbed4dGenie::WaitForIdle()
chris215 7:6edb20845684 161 {
chris215 8:b5ba0df2d0db 162 if(state != CommIdle)
chris215 8:b5ba0df2d0db 163 {
chris215 8:b5ba0df2d0db 164 long timeout = _t.read_ms() + TIMEOUT_PERIOD;
chris215 8:b5ba0df2d0db 165 long timerReading = 0;
chris215 8:b5ba0df2d0db 166 if(_t.read_ms() >= RxMaxTimeout)
chris215 8:b5ba0df2d0db 167 {
chris215 8:b5ba0df2d0db 168 Reset();
chris215 8:b5ba0df2d0db 169 RxStateTimeoutErrors++;
chris215 8:b5ba0df2d0db 170 }
chris215 8:b5ba0df2d0db 171 while(timerReading < timeout && state != CommIdle)
chris215 8:b5ba0df2d0db 172 {
chris215 8:b5ba0df2d0db 173 timerReading = _t.read_ms();
chris215 8:b5ba0df2d0db 174 }
chris215 8:b5ba0df2d0db 175 LastResponse = 0;
chris215 8:b5ba0df2d0db 176 return (timerReading >= timeout);
chris215 8:b5ba0df2d0db 177 }
chris215 8:b5ba0df2d0db 178
chris215 8:b5ba0df2d0db 179 return false;
chris215 8:b5ba0df2d0db 180 }
chris215 8:b5ba0df2d0db 181
chris215 8:b5ba0df2d0db 182 int8_t Mbed4dGenie::WaitForReadAnswer()
chris215 8:b5ba0df2d0db 183 {
chris215 7:6edb20845684 184 long timeout = _t.read_ms() + TIMEOUT_PERIOD;
chris215 7:6edb20845684 185 long timerReading = 0;
chris215 8:b5ba0df2d0db 186 while(state == CommIdle && LastResponse != ERROR_NAK && timerReading < timeout)
chris215 7:6edb20845684 187 {
chris215 7:6edb20845684 188 timerReading = _t.read_ms();
chris215 7:6edb20845684 189 }
chris215 8:b5ba0df2d0db 190 if(LastResponse == ERROR_NAK)//check if the screen returned a NACK
chris215 8:b5ba0df2d0db 191 {
chris215 8:b5ba0df2d0db 192 LastResponse = NO_RESPONSE;
chris215 8:b5ba0df2d0db 193 return ERROR_NAK;
chris215 8:b5ba0df2d0db 194 }
chris215 8:b5ba0df2d0db 195 else if(LastResponse >= timeout) //check if we timed out while waiting for response
chris215 8:b5ba0df2d0db 196 {
chris215 8:b5ba0df2d0db 197 LastResponse = NO_RESPONSE;
chris215 8:b5ba0df2d0db 198 return ERROR_TIMEOUT;
chris215 8:b5ba0df2d0db 199 }
chris215 8:b5ba0df2d0db 200 //if we get here it means we didnt timeout and the screen did accept the command
chris215 8:b5ba0df2d0db 201 LastResponse = NO_RESPONSE;
chris215 8:b5ba0df2d0db 202 return ERROR_NONE;
chris215 7:6edb20845684 203 }
chris215 0:d2ed5a44c802 204
chris215 6:f4d3977b0eae 205 int8_t Mbed4dGenie::WaitForAnswer()
chris215 6:f4d3977b0eae 206 {
chris215 0:d2ed5a44c802 207
chris215 6:f4d3977b0eae 208 long timeout = _t.read_ms() + TIMEOUT_PERIOD;
chris215 6:f4d3977b0eae 209 long timerReading = 0;
chris215 7:6edb20845684 210 while(LastResponse != GENIE_ACK && LastResponse != ERROR_NAK && timerReading < timeout)
chris215 6:f4d3977b0eae 211 {
chris215 6:f4d3977b0eae 212 timerReading = _t.read_ms();
chris215 6:f4d3977b0eae 213 }
chris215 6:f4d3977b0eae 214
chris215 7:6edb20845684 215 if(LastResponse == ERROR_NAK)
chris215 6:f4d3977b0eae 216 {
chris215 8:b5ba0df2d0db 217 LastResponse = NO_RESPONSE;
chris215 8:b5ba0df2d0db 218 return ERROR_NAK;
chris215 6:f4d3977b0eae 219 }
chris215 7:6edb20845684 220 else if(LastResponse >= timeout)
chris215 6:f4d3977b0eae 221 {
chris215 8:b5ba0df2d0db 222 LastResponse = NO_RESPONSE;
chris215 6:f4d3977b0eae 223 return ERROR_TIMEOUT;
chris215 6:f4d3977b0eae 224 }
chris215 8:b5ba0df2d0db 225 LastResponse = NO_RESPONSE;
chris215 6:f4d3977b0eae 226 return ERROR_NONE;
chris215 7:6edb20845684 227 }
chris215 7:6edb20845684 228
chris215 7:6edb20845684 229 void Mbed4dGenie::Reset(void)
chris215 7:6edb20845684 230 {
chris215 7:6edb20845684 231 LastResponse = NO_RESPONSE;
chris215 7:6edb20845684 232 state = CommIdle;
chris215 7:6edb20845684 233 while(_screen.readable())
chris215 7:6edb20845684 234 _screen.getc();
chris215 7:6edb20845684 235 }
chris215 7:6edb20845684 236
chris215 7:6edb20845684 237 ////////////////////// _genieFlushEventQueue ////////////////////
chris215 7:6edb20845684 238 //
chris215 7:6edb20845684 239 // Reset all the event queue variables and start from scratch.
chris215 7:6edb20845684 240 //
chris215 7:6edb20845684 241 void Mbed4dGenie::_genieFlushEventQueue(void) {
chris215 7:6edb20845684 242 _genieEventQueue.rd_index = 0;
chris215 7:6edb20845684 243 _genieEventQueue.wr_index = 0;
chris215 7:6edb20845684 244 _genieEventQueue.n_events = 0;
chris215 7:6edb20845684 245 }
chris215 7:6edb20845684 246
chris215 7:6edb20845684 247 ////////////////////// _genieEnqueueEvent ///////////////////
chris215 7:6edb20845684 248 //
chris215 7:6edb20845684 249 // Copy the bytes from a buffer supplied by the caller
chris215 7:6edb20845684 250 // to the input queue
chris215 7:6edb20845684 251 //
chris215 7:6edb20845684 252 // Parms: uint8_t * data, a pointer to the user's data
chris215 7:6edb20845684 253 //
chris215 7:6edb20845684 254 // Returns: TRUE if there was an empty location in the queue
chris215 7:6edb20845684 255 // to copy the data into
chris215 7:6edb20845684 256 // FALSE if not
chris215 7:6edb20845684 257 // Sets: ERROR_REPLY_OVR if there was no room in the queue
chris215 7:6edb20845684 258 //
chris215 7:6edb20845684 259 bool Mbed4dGenie::_genieEnqueueEvent (uint8_t * data) {
chris215 7:6edb20845684 260
chris215 7:6edb20845684 261
chris215 7:6edb20845684 262 if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) {
chris215 7:6edb20845684 263 memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data,
chris215 7:6edb20845684 264 GENIE_FRAME_SIZE);
chris215 7:6edb20845684 265 _genieEventQueue.wr_index++;
chris215 7:6edb20845684 266 _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1;
chris215 7:6edb20845684 267 _genieEventQueue.n_events++;
chris215 7:6edb20845684 268 return TRUE;
chris215 7:6edb20845684 269 } else {
chris215 7:6edb20845684 270 return FALSE;
chris215 7:6edb20845684 271 }
chris215 7:6edb20845684 272 }
chris215 7:6edb20845684 273 ////////////////////// genieDequeueEvent ///////////////////
chris215 7:6edb20845684 274 //
chris215 7:6edb20845684 275 // Copy the bytes from a queued input event to a buffer supplied
chris215 7:6edb20845684 276 // by the caller.
chris215 7:6edb20845684 277 //
chris215 7:6edb20845684 278 // Parms: genieFrame * buff, a pointer to the user's buffer
chris215 7:6edb20845684 279 //
chris215 7:6edb20845684 280 // Returns: TRUE if there was an event to copy
chris215 7:6edb20845684 281 // FALSE if not
chris215 7:6edb20845684 282 //
chris215 7:6edb20845684 283 bool Mbed4dGenie::genieDequeueEvent(genieFrame * buff) {
chris215 7:6edb20845684 284
chris215 7:6edb20845684 285
chris215 7:6edb20845684 286 if (_genieEventQueue.n_events > 0) {
chris215 7:6edb20845684 287 memcpy (buff, &_genieEventQueue.frames[_genieEventQueue.rd_index],
chris215 7:6edb20845684 288 GENIE_FRAME_SIZE);
chris215 7:6edb20845684 289 _genieEventQueue.rd_index++;
chris215 7:6edb20845684 290 _genieEventQueue.rd_index &= MAX_GENIE_EVENTS -1;
chris215 7:6edb20845684 291 _genieEventQueue.n_events--;
chris215 7:6edb20845684 292 return TRUE;
chris215 7:6edb20845684 293 }
chris215 7:6edb20845684 294 return FALSE;
chris215 7:6edb20845684 295 }
chris215 7:6edb20845684 296 void Mbed4dGenie::genieAttachEventHandler(genieUserEventHandlerPtr handler)
chris215 7:6edb20845684 297 {
chris215 7:6edb20845684 298 _genieUserHandler = handler;
chris215 7:6edb20845684 299 }
chris215 7:6edb20845684 300 bool Mbed4dGenie::PendingFrames(void)
chris215 7:6edb20845684 301 {
chris215 7:6edb20845684 302 return (_genieEventQueue.n_events>0);
chris215 2:f283764fe9b7 303 }