Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of 4dGENIE by
mbed_genie.cpp
00001 #include "mbed.h" 00002 #include "mbed_genie.h" 00003 00004 Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin) : _screen(TxPin,RxPin) , _reset(resetpin) 00005 { 00006 //reset the 4d screen 00007 _reset = 0; 00008 _screen.baud(9600); 00009 _genieUserHandler = NULL; 00010 RxStateTimeoutErrors = 0; 00011 } 00012 Mbed4dGenie::Mbed4dGenie(PinName TxPin,PinName RxPin, PinName resetpin,uint32_t baud) : _screen(TxPin,RxPin) , _reset(resetpin) 00013 { 00014 //reset the 4d screen 00015 _reset = 0; 00016 _screen.baud(baud); 00017 _genieUserHandler = NULL; 00018 RxStateTimeoutErrors = 0; 00019 } 00020 void Mbed4dGenie::Start() 00021 { 00022 _reset = 1; 00023 wait(3.0); //4D datasheet says that the screen can take up to 3000 ms before 00024 //becomming responsive to serial commands. 00025 _waitTimer.start(); 00026 _receptionTimer.start(); 00027 Reset(); 00028 _genieFlushEventQueue(); 00029 _screen.attach(this,&Mbed4dGenie::RxIrqHandler,Serial::RxIrq); 00030 } 00031 00032 00033 ////////////////////// genieGetEventData //////////////////////// 00034 // 00035 // Returns the LSB and MSB of the event's data combined into 00036 // a single uint16 00037 // 00038 // The data is transmitted from the display in big-endian format 00039 // and stored the same so the user can't just access it as an int 00040 // directly from the structure. 00041 // 00042 uint16_t Mbed4dGenie::genieGetEventData (genieFrame * e) { 00043 return (e->reportObject.data_msb << 8) + e->reportObject.data_lsb; 00044 } 00045 00046 void Mbed4dGenie::RxIrqHandler(void) 00047 { 00048 char c; 00049 //Loop to read all byte present in UART FIFO 00050 do 00051 { 00052 c = _screen.getc(); 00053 /* 00054 check if we are in reception mode and if we timeout 00055 */ 00056 if(_receptionTimer.read_ms() >= RxMaxTimeout && state == CommInProgress) 00057 { 00058 /* 00059 if we get here, it means something bad has happened and 00060 we need to reet communication status 00061 */ 00062 Reset(); 00063 } 00064 ManageReceiveData(c); 00065 } 00066 while(_screen.readable()); 00067 } 00068 00069 void Mbed4dGenie::ManageReceiveData(char data) 00070 { 00071 switch(state) 00072 { 00073 case CommIdle: 00074 00075 if(data == GENIE_ACK || data == GENIE_NAK) 00076 { 00077 LastResponse = data; 00078 } 00079 else if(data == GENIE_REPORT_OBJ || data == GENIE_REPORT_EVENT) 00080 { 00081 //re-initialise the reception timer 00082 _receptionTimer.reset(); 00083 RxMaxTimeout = _receptionTimer.read_ms() + RESYNC_PERIOD; 00084 checksum = data; 00085 rx_data[rxframe_count++] = data; 00086 state = CommInProgress; 00087 } 00088 break; 00089 00090 00091 case CommInProgress: 00092 checksum = checksum ^ data; 00093 rx_data[rxframe_count++] = data; 00094 00095 if(rxframe_count >= GENIE_FRAME_SIZE) 00096 { 00097 if (checksum == 0) { 00098 _genieEnqueueEvent(rx_data); 00099 if(_genieUserHandler != NULL) 00100 { 00101 (_genieUserHandler)(); 00102 } 00103 } 00104 state = CommIdle; 00105 rxframe_count = 0; 00106 LastResponse = NO_RESPONSE; 00107 } 00108 break; 00109 default: 00110 state = CommIdle; 00111 rxframe_count = 0; 00112 LastResponse = NO_RESPONSE; 00113 break; 00114 } 00115 } 00116 00117 00118 ///////////////////////// genieWriteObject ////////////////////// 00119 // 00120 // Write data to an object on the display 00121 // 00122 int8_t Mbed4dGenie::genieWriteObject (uint16_t object, uint16_t index, uint16_t data) 00123 { 00124 uint16_t msb, lsb ; 00125 uint8_t checksum ; 00126 00127 //wait for interface to be ready before sending stuff 00128 if(WaitForIdle()) 00129 return ERROR_RESYNC; 00130 00131 lsb = data&0xFF; 00132 msb = (data>>8) & 0xFF; 00133 00134 _screen.putc(GENIE_WRITE_OBJ) ; 00135 checksum = GENIE_WRITE_OBJ ; 00136 _screen.putc(object) ; 00137 checksum ^= object ; 00138 _screen.putc(index) ; 00139 checksum ^= index ; 00140 _screen.putc(msb) ; 00141 checksum ^= msb; 00142 _screen.putc(lsb) ; 00143 checksum ^= lsb; 00144 _screen.putc(checksum) ; 00145 00146 return Mbed4dGenie::WaitForAnswer(); 00147 } 00148 int8_t Mbed4dGenie::genieWriteStr (uint16_t index, char *string) 00149 { 00150 char *p ; 00151 unsigned int checksum ; 00152 int len = strlen (string) ; 00153 00154 00155 if (len > 255) 00156 return -1 ; 00157 00158 00159 //wait for interface to be ready before sending stuff 00160 if(WaitForIdle()) 00161 return ERROR_RESYNC; 00162 00163 00164 _screen.putc(GENIE_WRITE_STR) ; checksum = GENIE_WRITE_STR ; 00165 _screen.putc(index) ; checksum ^= index ; 00166 _screen.putc((unsigned char)len) ; checksum ^= len ; 00167 for (p = string ; *p ; ++p) { 00168 _screen.putc (*p) ; 00169 checksum ^= *p ; 00170 } 00171 _screen.putc(checksum) ; 00172 00173 return Mbed4dGenie::WaitForAnswer(); 00174 } 00175 int8_t Mbed4dGenie::genieReadObj (uint16_t object, uint16_t index) 00176 { 00177 //wait for interface to be ready before sending stuff 00178 if(WaitForIdle()) 00179 return ERROR_RESYNC; 00180 unsigned int checksum ; 00181 00182 _screen.putc(GENIE_READ_OBJ) ; checksum = GENIE_READ_OBJ ; 00183 _screen.putc(object) ; checksum ^= object ; 00184 _screen.putc(index) ; checksum ^= index ; 00185 _screen.putc(checksum) ; 00186 00187 //Here we dont wiat for a typical answer 00188 //The screen will respond with an NACK if the command was not understood, otherwise it will send a report object frame 00189 return 0;//WaitForReadAnswer(); 00190 } 00191 void Mbed4dGenie::writec(char data) 00192 { 00193 _screen.putc(data); 00194 } 00195 bool Mbed4dGenie::WaitForIdle() 00196 { 00197 /* 00198 If the communication is still in progress 00199 lets wait for it to finish or check/wait for timeout 00200 */ 00201 if(state != CommIdle) 00202 { 00203 long timeout = _receptionTimer.read_ms() + TIMEOUT_PERIOD; 00204 long timerReading = 0; 00205 if(_receptionTimer.read_ms() >= RxMaxTimeout) 00206 { 00207 Reset(); 00208 RxStateTimeoutErrors++; 00209 } 00210 while(timerReading < timeout && state != CommIdle) 00211 { 00212 timerReading = _receptionTimer.read_ms(); 00213 } 00214 LastResponse = 0; 00215 return (timerReading >= timeout); 00216 } 00217 00218 return false; 00219 } 00220 00221 /* 00222 Not used for now, since the screen will answer with either a report event or NAK 00223 Since those two answers are so different, there is no efficient means to receive 00224 both in interrupt. No wait to NAK will be done. DONT USE THIS FUNCTION ... YET 00225 */ 00226 int8_t Mbed4dGenie::WaitForReadAnswer() 00227 { 00228 _waitTimer.reset(); 00229 long timeout = _waitTimer.read_ms() + TIMEOUT_PERIOD; 00230 long timerReading = 0; 00231 while(state == CommIdle && LastResponse != ERROR_NAK && timerReading < timeout) 00232 { 00233 timerReading = _waitTimer.read_ms(); 00234 } 00235 if(LastResponse == ERROR_NAK)//check if the screen returned a NACK 00236 { 00237 LastResponse = NO_RESPONSE; 00238 return ERROR_NAK; 00239 } 00240 else if(_waitTimer.read_ms() >= timeout) //check if we timed out while waiting for response 00241 { 00242 00243 LastResponse = NO_RESPONSE; 00244 return ERROR_TIMEOUT; 00245 } 00246 //if we get here it means we didnt timeout and the screen did accept the command 00247 LastResponse = NO_RESPONSE; 00248 return ERROR_NONE; 00249 } 00250 00251 int8_t Mbed4dGenie::WaitForAnswer() 00252 { 00253 _waitTimer.reset(); 00254 long timeout = _waitTimer.read_ms() + TIMEOUT_PERIOD; 00255 long timerReading = 0; 00256 while(LastResponse != GENIE_ACK && LastResponse != ERROR_NAK && timerReading < timeout) 00257 { 00258 timerReading = _waitTimer.read_ms(); 00259 } 00260 00261 if(LastResponse == ERROR_NAK) 00262 { 00263 LastResponse = NO_RESPONSE; 00264 return ERROR_NAK; 00265 } 00266 else if(_waitTimer.read_ms() >= timeout) 00267 { 00268 printf("Current timer:%d ; timeout:%d\n\r",_waitTimer.read_ms(),timeout); 00269 LastResponse = NO_RESPONSE; 00270 return ERROR_TIMEOUT; 00271 } 00272 LastResponse = NO_RESPONSE; 00273 return ERROR_NONE; 00274 } 00275 00276 void Mbed4dGenie::Reset(void) 00277 { 00278 LastResponse = NO_RESPONSE; 00279 state = CommIdle; 00280 _receptionTimer.reset(); 00281 _waitTimer.reset(); 00282 while(_screen.readable()) 00283 _screen.getc(); 00284 } 00285 00286 ////////////////////// _genieFlushEventQueue //////////////////// 00287 // 00288 // Reset all the event queue variables and start from scratch. 00289 // 00290 void Mbed4dGenie::_genieFlushEventQueue(void) { 00291 _genieEventQueue.rd_index = 0; 00292 _genieEventQueue.wr_index = 0; 00293 _genieEventQueue.n_events = 0; 00294 } 00295 00296 ////////////////////// _genieEnqueueEvent /////////////////// 00297 // 00298 // Copy the bytes from a buffer supplied by the caller 00299 // to the input queue 00300 // 00301 // Parms: uint8_t * data, a pointer to the user's data 00302 // 00303 // Returns: TRUE if there was an empty location in the queue 00304 // to copy the data into 00305 // FALSE if not 00306 // Sets: ERROR_REPLY_OVR if there was no room in the queue 00307 // 00308 bool Mbed4dGenie::_genieEnqueueEvent (uint8_t * data) { 00309 00310 00311 if (_genieEventQueue.n_events < MAX_GENIE_EVENTS-2) { 00312 memcpy (&_genieEventQueue.frames[_genieEventQueue.wr_index], data, 00313 GENIE_FRAME_SIZE); 00314 _genieEventQueue.wr_index++; 00315 _genieEventQueue.wr_index &= MAX_GENIE_EVENTS -1; 00316 _genieEventQueue.n_events++; 00317 return TRUE; 00318 } else { 00319 return FALSE; 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 Mbed4dGenie::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 void Mbed4dGenie::genieAttachEventHandler(genieUserEventHandlerPtr handler) 00346 { 00347 _genieUserHandler = handler; 00348 } 00349 bool Mbed4dGenie::PendingFrames(void) 00350 { 00351 return (_genieEventQueue.n_events>0); 00352 }
Generated on Fri Jul 15 2022 12:18:26 by
1.7.2
