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); } }
Diff: mbed_genie.cpp
- 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