A demonstration of how to drive the onboard LEDS on the LPC1768 via a 4.3 inch touch-screen display from 4D Systems

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_genie.cpp Source File

mbed_genie.cpp

00001 
00002 #include "mbed.h"
00003 #include "mbed_genie.h"
00004 
00005 DigitalOut genieReset(p8);  //genie reset pin on pin 8 of the mbed
00006 
00007 Serial screen(p9,p10);
00008 Serial pc(USBTX,USBRX);
00009 Timer t;
00010 
00011 
00012 
00013 void           _genieFlushEventQueue        (void);
00014 void           _handleError                        (void);
00015 void           _geniePutchar                        (uint8_t c);
00016 uint8_t        _genieGetchar                        (void);
00017 void           _genieSetLinkState                (uint16_t newstate);
00018 uint16_t       _genieGetLinkState                (void);        
00019 bool           _genieEnqueueEvent                (uint8_t * data);
00020 //////////////////////////////////////////////////////////////
00021 // A structure to hold up to MAX_GENIE_EVENTS events receive
00022 // from the display
00023 //
00024 static genieEventQueueStruct _genieEventQueue;
00025 
00026 //////////////////////////////////////////////////////////////
00027 // Pointer to the user's event handler function
00028 //
00029 static genieUserEventHandlerPtr _genieUserHandler = NULL;
00030 
00031 
00032 //////////////////////////////////////////////////////////////
00033 // Simple 5-deep stack for the link state, this allows 
00034 // genieDoEvents() to save the current state, receive a frame,
00035 // then restore the state
00036 //
00037 static uint8_t _genieLinkStates[5] = {GENIE_LINK_IDLE};
00038 //
00039 // Stack pointer
00040 //
00041 static uint8_t *_genieLinkState = &_genieLinkStates[0];
00042 
00043 
00044 //////////////////////////////////////////////////////////////
00045 // Number of mS the genieGetChar() function will wait before
00046 // giving up on the display
00047 static int _genieTimeout = TIMEOUT_PERIOD;
00048 
00049 
00050 //////////////////////////////////////////////////////////////
00051 // Number of times we have had a timeout
00052 static int _genieTimeouts = 0;
00053 
00054 
00055 //////////////////////////////////////////////////////////////
00056 // Global error variable
00057 static int _genieError = ERROR_NONE;
00058 
00059 
00060 
00061 
00062 static uint8_t        rxframe_count = 0;
00063 
00064 
00065 //////////////////////////////////////////////////////////////
00066 // Number of fatal errors encountered
00067 static int _genieFatalErrors = 0;
00068 ////////////////////// genieGetEventData ////////////////////////
00069 //
00070 // Returns the LSB and MSB of the event's data combined into
00071 // a single uint16
00072 //
00073 // The data is transmitted from the display in big-endian format 
00074 // and stored the same so the user can't just access it as an int 
00075 // directly from the structure. 
00076 //
00077 uint16_t genieGetEventData (genieFrame * e) {
00078         return  (e->reportObject.data_msb << 8) + e->reportObject.data_lsb;
00079 }
00080 
00081 //////////////////////// genieEventIs ///////////////////////////
00082 //
00083 // Compares the cmd, object and index fields of the event's 
00084 // structure.
00085 //
00086 // Returns:                TRUE if all the fields match the caller's parms
00087 //                                FALSE if any of them don't
00088 //
00089 bool genieEventIs(genieFrame * e, uint8_t cmd, uint8_t object, uint8_t index) {
00090 
00091 
00092         return (e->reportObject.cmd == cmd &&
00093                 e->reportObject.object == object &&
00094                 e->reportObject.index == index);
00095 
00096 }
00097 
00098 ////////////////////// _geniePushLinkState //////////////////////
00099 //
00100 // Push a link state onto a FILO stack
00101 //
00102 void _geniePushLinkState (uint8_t newstate) {
00103 
00104 
00105         _genieLinkState++;
00106         _genieSetLinkState(newstate);
00107 
00108 
00109 }
00110 
00111 
00112 ////////////////////// _geniePopLinkState //////////////////////
00113 //
00114 // Pop a link state from a FILO stack
00115 //
00116 void _geniePopLinkState (void) {
00117         if (_genieLinkState > &_genieLinkStates[0]) {
00118                 *_genieLinkState = 0xFF;
00119                 _genieLinkState--;
00120         }
00121 }
00122 
00123 ///////////////// _genieFlushSerialInput ///////////////////
00124 //
00125 // Removes and discards all characters from the currently 
00126 // used serial port's Rx buffer.
00127 //
00128 void _genieFlushSerialInput(void) {
00129         do {
00130                 _genieGetchar();
00131         } while (_genieError != ERROR_NOCHAR);
00132 }
00133 
00134 ///////////////////////// _handleError /////////////////////////
00135 //
00136 // So far really just a debugging aid, but can be enhanced to
00137 // help recover from errors.
00138 //
00139 void _handleError (void) {
00140 //        Serial2.write (_genieError + (1<<5));
00141 //        if (_genieError == GENIE_NAK) genieResync();
00142 }
00143 
00144 
00145 
00146 
00147 ////////////////////// _genieFlushEventQueue ////////////////////
00148 //
00149 // Reset all the event queue variables and start from scratch.
00150 //
00151 void _genieFlushEventQueue(void) {
00152         _genieEventQueue.rd_index = 0;
00153         _genieEventQueue.wr_index = 0;
00154         _genieEventQueue.n_events = 0;
00155 }
00156 bool GenieReadable(void){
00157     if (screen.readable())
00158     {
00159         return TRUE;
00160     }
00161     else
00162     {
00163         return FALSE;
00164     }
00165 }
00166 ///////////////////////// genieDoEvents /////////////////////////
00167 //
00168 // This is the heart of the Genie comms state machine.
00169 //
00170 uint16_t genieDoEvents (void) {
00171         uint8_t c;
00172         static uint8_t        rx_data[6];
00173         static uint8_t        checksum = 0;
00174 
00175         if (GenieReadable())
00176         {
00177             c = _genieGetchar();
00178             //pc.putc(c);
00179     
00180             ////////////////////////////////////////////
00181             //
00182             // If there are no characters to process and we have 
00183             // queued events call the user's handler function.
00184             //
00185             if (_genieError == ERROR_NOCHAR) {
00186             //pc.printf("EventCalled!\n\r");
00187                     if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
00188                     return GENIE_EVENT_NONE;
00189             }
00190             
00191             ///////////////////////////////////////////
00192             //
00193             // Main state machine
00194             //
00195             switch (_genieGetLinkState()) {
00196                     case GENIE_LINK_IDLE:
00197                             switch (c) {
00198                                     case GENIE_REPORT_EVENT:
00199                                     // event frame out of the blue, set the link state
00200                                     // and fall through to the frame-accumulate code
00201                                     // at the end of this function
00202                                     _geniePushLinkState(GENIE_LINK_RXEVENT);
00203                                     break;
00204                                             
00205                                     default:
00206                                     // error, bad character, no other character 
00207                                     // is acceptable in this state
00208                                     return GENIE_EVENT_RXCHAR;
00209                                     
00210                             }
00211                             break;
00212                                     
00213                     case GENIE_LINK_WFAN:
00214                             switch (c) {
00215     
00216     
00217                                     case GENIE_ACK:
00218                                             _geniePopLinkState();
00219                                             return GENIE_EVENT_RXCHAR;
00220     
00221     
00222                                     case GENIE_NAK:
00223                                             _geniePopLinkState();
00224                                             _genieError = ERROR_NAK;
00225                                             _handleError();
00226                                             return GENIE_EVENT_RXCHAR;
00227                             
00228                                     case GENIE_REPORT_EVENT:
00229                                             // event frame out of the blue while waiting for an ACK
00230                                             // save/set the link state and fall through to the 
00231                                             // frame-accumulate code at the end of this function
00232                                             _geniePushLinkState(GENIE_LINK_RXEVENT);
00233                                             break;
00234     
00235     
00236                                     case GENIE_REPORT_OBJ:
00237                                     default:
00238                                             // error, bad character
00239                                             return GENIE_EVENT_RXCHAR;        
00240                             }
00241                             break;
00242     
00243     
00244                     case GENIE_LINK_WF_RXREPORT: // waiting for the first byte of a report
00245                             switch (c) {
00246                             
00247                                     case GENIE_REPORT_EVENT:
00248                                     // event frame out of the blue while waiting for the first
00249                                     // byte of a report frame
00250                                     // save/set the link state and fall through to the
00251                                     // frame-accumulate code at the end of this function
00252                                     _geniePushLinkState(GENIE_LINK_RXEVENT);
00253                                     break;
00254     
00255     
00256                                     case GENIE_REPORT_OBJ:
00257                                     // first byte of a report frame
00258                                     // replace the GENIE_LINK_WF_RXREPORT link state 
00259                                     // with GENIE_LINK_RXREPORT to indicate that we
00260                                     // are now receiving a report frame
00261                                     _geniePopLinkState();
00262                                     _geniePushLinkState(GENIE_LINK_RXREPORT);
00263                                     break;
00264     
00265     
00266                                     case GENIE_ACK:
00267                                     case GENIE_NAK:
00268                                     default:
00269                                     // error, bad character
00270                                     return GENIE_EVENT_RXCHAR;
00271     //                                break;
00272                             }
00273     
00274     
00275                     case GENIE_LINK_RXREPORT:                // already receiving report
00276                     case GENIE_LINK_RXEVENT:                // already receiving event
00277                     default:
00278                             break;
00279                     
00280             }
00281     
00282     
00283             ///////////////////////////////////////////////////////
00284             // We get here if we are in the process of receiving 
00285             // a report or event frame. Accumulate GENIE_FRAME_SIZE 
00286             // bytes into a local buffer then queue them as a frame
00287             // into the event queue
00288             //
00289             if (_genieGetLinkState() == GENIE_LINK_RXREPORT || \
00290                     _genieGetLinkState() == GENIE_LINK_RXEVENT) {
00291                             
00292                     checksum = (rxframe_count == 0) ? c : checksum ^ c;
00293     
00294     
00295                     rx_data[rxframe_count] = c;
00296     
00297     
00298                     if (rxframe_count == GENIE_FRAME_SIZE -1) {
00299                     //pc.printf("FrameReceived!\n\r");
00300                             // all bytes received, if the CS is good 
00301                             // queue the frame and restore the link state
00302                             if (checksum == 0) {
00303                                     _genieEnqueueEvent(rx_data);
00304                                     if (_genieEventQueue.n_events > 0 && _genieUserHandler!= NULL) (_genieUserHandler)();
00305                                     //return GENIE_EVENT_NONE;
00306                                     rxframe_count = 0;
00307                                     // revert the link state to whatever it was before
00308                                     // we started accumulating this frame
00309                                     _geniePopLinkState();
00310                                     return GENIE_EVENT_RXCHAR;
00311                             } else {
00312                                     _genieError = ERROR_BAD_CS;
00313                                     _handleError();
00314                             }        
00315                     }
00316                     rxframe_count++;
00317                     return GENIE_EVENT_RXCHAR;
00318             }
00319     }   
00320 }
00321 
00322 ////////////////////// genieDequeueEvent ///////////////////
00323 //
00324 // Copy the bytes from a queued input event to a buffer supplied 
00325 // by the caller.
00326 //
00327 // Parms:        genieFrame * buff, a pointer to the user's buffer
00328 //
00329 // Returns:        TRUE if there was an event to copy
00330 //                        FALSE if not
00331 //
00332 bool genieDequeueEvent(genieFrame * buff) {
00333 
00334 
00335         if (_genieEventQueue.n_events > 0) {
00336                 memcpy (buff, &_genieEventQueue.frames[_genieEventQueue.rd_index], 
00337                                 GENIE_FRAME_SIZE);
00338                 _genieEventQueue.rd_index++;
00339                 _genieEventQueue.rd_index &= MAX_GENIE_EVENTS -1;
00340                 _genieEventQueue.n_events--;
00341                 return TRUE;
00342         } 
00343         return FALSE;
00344 }
00345 
00346 
00347 
00348 
00349 
00350 ////////////////////// _genieWaitForIdle ////////////////////////
00351 //
00352 // Wait for the link to become idle or for the timeout period, 
00353 // whichever comes first.
00354 //
00355 void _genieWaitForIdle (void) {
00356         uint16_t do_event_result;
00357         long timeout = t.read_ms() + _genieTimeout;
00358 
00359         for ( ; t.read_ms() < timeout;) {
00360 
00361          
00362             do_event_result = genieDoEvents();             
00363                 // if there was a character received from the 
00364                 // display restart the timeout because doEvents
00365                 // is in the process of receiving something
00366                 if (do_event_result == GENIE_EVENT_RXCHAR) {
00367                         timeout = t.read_ms() + _genieTimeout;
00368                         return;
00369                 }
00370                 
00371                 if (_genieGetLinkState() == GENIE_LINK_IDLE) {
00372                         return;
00373                 }
00374         }
00375         _genieError = ERROR_TIMEOUT;
00376         _handleError();
00377         return;
00378 }
00379 
00380 ///////////////////////// genieWriteObject //////////////////////
00381 //
00382 // Write data to an object on the display
00383 //
00384 uint16_t genieWriteObject (uint16_t object, uint16_t index, uint16_t data)
00385 {
00386         uint16_t msb, lsb ;
00387         uint8_t checksum ;
00388 
00389 
00390         _genieWaitForIdle();
00391 
00392 
00393         lsb = data&0xFF;
00394         msb = (data>>8) & 0xFF;
00395 
00396 
00397         _genieError = ERROR_NONE;
00398 
00399 
00400         _geniePutchar(GENIE_WRITE_OBJ) ; checksum  = GENIE_WRITE_OBJ ;
00401         _geniePutchar(object) ;          checksum ^= object ;
00402         _geniePutchar(index) ;           checksum ^= index ;
00403         _geniePutchar(msb) ;             checksum ^= msb;
00404         _geniePutchar(lsb) ;             checksum ^= lsb;
00405         _geniePutchar(checksum) ;
00406 
00407 
00408         _geniePushLinkState(GENIE_LINK_WFAN);        
00409 }
00410 
00411 /////////////////////// genieWriteContrast //////////////////////
00412 // 
00413 // Alter the display contrast (backlight)
00414 //
00415 // Parms:        uint8_t value: The required contrast setting, only
00416 //                values from 0 to 15 are valid. 0 or 1 for most displays
00417 //      and 0 to 15 for the uLCD-43
00418 //
00419 void genieWriteContrast (uint16_t value) {
00420         unsigned int checksum ;
00421 
00422 
00423         _genieWaitForIdle();
00424 
00425 
00426         _geniePutchar(GENIE_WRITE_CONTRAST) ; checksum  = GENIE_WRITE_CONTRAST ;
00427         _geniePutchar(value) ;                checksum ^= value ;
00428         _geniePutchar(checksum) ;
00429 
00430 
00431         _geniePushLinkState(GENIE_LINK_WFAN);
00432 
00433 
00434 }
00435 
00436 
00437 //////////////////////// _genieWriteStrX ///////////////////////
00438 //
00439 // Non-user function used by genieWriteStr() and genieWriteStrU()
00440 //
00441 static int _genieWriteStrX (uint16_t code, uint16_t index, char *string)
00442 {
00443         char *p ;
00444         unsigned int checksum ;
00445         int len = strlen (string) ;
00446 
00447 
00448         if (len > 255)
00449         return -1 ;
00450 
00451 
00452         _genieWaitForIdle();
00453 
00454 
00455         _geniePutchar(code) ;               checksum  = code ;
00456         _geniePutchar(index) ;              checksum ^= index ;
00457         _geniePutchar((unsigned char)len) ; checksum ^= len ;
00458         for (p = string ; *p ; ++p)        {
00459                 _geniePutchar (*p) ;
00460                 checksum ^= *p ;
00461         }
00462         _geniePutchar(checksum) ;
00463 
00464 
00465         _geniePushLinkState(GENIE_LINK_WFAN);
00466 
00467 
00468         return 0 ;
00469 }
00470 /////////////////////// genieWriteStr ////////////////////////
00471 //
00472 // Write a string to the display (ASCII)
00473 //
00474 uint16_t genieWriteStr (uint16_t index, char *string) {
00475  
00476   return _genieWriteStrX (GENIE_WRITE_STR, index, string);
00477 }
00478 
00479 
00480 /////////////////////// genieWriteStrU ////////////////////////
00481 //
00482 // Write a string to the display (Unicode)
00483 //
00484 uint16_t genieWriteStrU (uint16_t index, char *string) {
00485 
00486 
00487   return _genieWriteStrX (GENIE_WRITE_STRU, index, string);
00488 
00489 
00490 }
00491 /////////////////// genieAttachEventHandler //////////////////////
00492 //
00493 // "Attaches" a pointer to the users event handler by writing 
00494 // the pointer into the variable used by doEVents()
00495 //
00496 void genieAttachEventHandler (genieUserEventHandlerPtr handler) {
00497         _genieUserHandler = handler;
00498 }
00499 
00500 
00501 ////////////////////// _genieEnqueueEvent ///////////////////
00502 //
00503 // Copy the bytes from a buffer supplied by the caller 
00504 // to the input queue 
00505 //
00506 // Parms:        uint8_t * data, a pointer to the user's data
00507 //
00508 // Returns:        TRUE if there was an empty location in the queue
00509 //                                to copy the data into
00510 //                        FALSE if not
00511 // Sets:        ERROR_REPLY_OVR if there was no room in the queue
00512 //
00513 bool _genieEnqueueEvent (uint8_t * data) {
00514 
00515 
00516         if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) {
00517                 memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data, 
00518                                 GENIE_FRAME_SIZE);
00519                 _genieEventQueue.wr_index++;
00520                 _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1;
00521                 _genieEventQueue.n_events++;
00522                 return TRUE;
00523         } else {
00524                 _genieError = ERROR_REPLY_OVR;
00525                 _handleError();
00526                 return FALSE;
00527         }
00528 }
00529 ///////////////////// _genieSetLinkState ////////////////////////
00530 //
00531 // Set the logical state of the link to the display.
00532 //
00533 // Parms:        uint16_t newstate, a value to be written to the 
00534 //                                link's _genieLinkState variable. Valid values are
00535 //                GENIE_LINK_IDLE                        0
00536 //                GENIE_LINK_WFAN                        1 // waiting for Ack or Nak
00537 //                GENIE_LINK_WF_RXREPORT        2 // waiting for a report frame
00538 //                GENIE_LINK_RXREPORT                3 // receiving a report frame
00539 //                GENIE_LINK_RXEVENT                4 // receiving an event frame
00540 //                GENIE_LINK_SHDN                        5
00541 //
00542 void _genieSetLinkState (uint16_t newstate) {
00543         
00544         *_genieLinkState = newstate;
00545 
00546 
00547         if (newstate == GENIE_LINK_RXREPORT || \
00548                 newstate == GENIE_LINK_RXEVENT)
00549                 rxframe_count = 0;        
00550 }
00551 
00552 
00553 /////////////////////// _genieGetLinkState //////////////////////
00554 //
00555 // Get the current logical state of the link to the display.
00556 //
00557 uint16_t _genieGetLinkState (void) {
00558         return *_genieLinkState;
00559 }
00560 
00561 /////////////////////// _geniePutchar ///////////////////////////
00562 //
00563 // Output the supplied character to the Genie display over 
00564 // the selected serial port
00565 //
00566 void _geniePutchar (uint8_t c) {
00567   //      if (screen != NULL)
00568                 screen.putc(c);
00569 }
00570 
00571 
00572 //////////////////////// _genieGetchar //////////////////////////
00573 //
00574 // Get a character from the selected Genie serial port
00575 //
00576 // Returns:        ERROR_NOHANDLER if an Rx handler has not 
00577 //                                been defined
00578 //                        ERROR_NOCHAR if no bytes have beeb received
00579 //                        The char if there was one to get
00580 // Sets:        _genieError with any errors encountered
00581 //
00582 uint8_t _genieGetchar() {
00583         uint16_t result;
00584 
00585 
00586         _genieError = ERROR_NONE;
00587 
00588         return (screen.getc());
00589 }
00590 
00591 void RxIrqHandler(void)
00592 {
00593     do 
00594     {
00595         genieDoEvents();
00596     }
00597     while(screen.readable ());
00598 }
00599 
00600 
00601 void TickerIrq(void)
00602 {
00603 }
00604 
00605 
00606 void SetupGenie(void)
00607 {
00608     screen.baud(9600);
00609     pc.baud(9600);
00610     screen.attach(&RxIrqHandler,Serial::RxIrq);
00611     t.start();
00612  //   EventChk.attach(&TickerIrq,0.05);
00613 }