Syed Shakeeb Sadiq / 4dGENIE

Dependents:   Genie_mbed_Gecko

Fork of 4dGENIE by christian b

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_genie.cpp Source File

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 }