A demonstration of how to drive the onboard LEDS on the LPC1768 via a 4.3 inch touch-screen display from 4D Systems
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 }
Generated on Tue Jul 12 2022 22:46:18 by 1.7.2