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