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); } }
mbed_genie.cpp
- Committer:
- chris215
- Date:
- 2014-07-08
- Revision:
- 10:4d9f1be4a901
- Parent:
- 9:b74deaac80f9
- Child:
- 11:9196f72fc325
File content as of revision 10:4d9f1be4a901:
#include "mbed.h" #include "mbed_genie.h" Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin) : _screen(TxPin,RxPin) , _reset(resetpin) { //reset the 4d screen _reset = 0; _screen.baud(9600); _genieUserHandler = NULL; RxStateTimeoutErrors = 0; } void Mbed4dGenie::Start() { _reset = 1; 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); } ////////////////////// 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; } void Mbed4dGenie::RxIrqHandler(void) { char c; //Loop to read all byte present in UART FIFO do { c = _screen.getc(); if(_t.read_ms() >= RxMaxTimeout && state == CommInProgress) { Reset(); } ManageReceiveData(c); } while(_screen.readable()); } void Mbed4dGenie::ManageReceiveData(char data) { switch(state) { case CommIdle: if(data == GENIE_ACK || data == GENIE_NAK) { LastResponse = data; } else if(data == GENIE_REPORT_OBJ || data == GENIE_REPORT_EVENT) { RxMaxTimeout = _t.read_ms() + RESYNC_PERIOD; checksum = data; rx_data[rxframe_count++] = data; state = CommInProgress; } 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 // int8_t Mbed4dGenie::genieWriteObject (uint16_t object, uint16_t index, uint16_t data) { 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; _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) ; 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(); } 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) ; //Here we dont wiat for a typical answer //The screen will respond with an NACK if the command was not understood, otherwise it will send a report object frame return 0;//WaitForReadAnswer(); } void Mbed4dGenie::writec(char data) { _screen.putc(data); } bool Mbed4dGenie::WaitForIdle() { if(state != CommIdle) { long timeout = _t.read_ms() + TIMEOUT_PERIOD; long timerReading = 0; if(_t.read_ms() >= RxMaxTimeout) { Reset(); RxStateTimeoutErrors++; } while(timerReading < timeout && state != CommIdle) { timerReading = _t.read_ms(); } LastResponse = 0; return (timerReading >= timeout); } return false; } int8_t Mbed4dGenie::WaitForReadAnswer() { long timeout = _t.read_ms() + TIMEOUT_PERIOD; long timerReading = 0; while(state == CommIdle && LastResponse != ERROR_NAK && timerReading < timeout) { timerReading = _t.read_ms(); } if(LastResponse == ERROR_NAK)//check if the screen returned a NACK { LastResponse = NO_RESPONSE; return ERROR_NAK; } else if(_t.read_ms() >= timeout) //check if we timed out while waiting for response { LastResponse = NO_RESPONSE; return ERROR_TIMEOUT; } //if we get here it means we didnt timeout and the screen did accept the command LastResponse = NO_RESPONSE; return ERROR_NONE; } int8_t Mbed4dGenie::WaitForAnswer() { long timeout = _t.read_ms() + TIMEOUT_PERIOD; long timerReading = 0; while(LastResponse != GENIE_ACK && LastResponse != ERROR_NAK && timerReading < timeout) { timerReading = _t.read_ms(); } if(LastResponse == ERROR_NAK) { LastResponse = NO_RESPONSE; return ERROR_NAK; } else if(_t.read_ms() >= timeout) { printf("Current timer:%d ; timeout:%d\n\r",_t.read_ms(),timeout); LastResponse = NO_RESPONSE; return ERROR_TIMEOUT; } LastResponse = NO_RESPONSE; 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); }