Library set up as dummy module on mbed to mimic Nordic.

Dependencies:   mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rs485.cpp Source File

rs485.cpp

00001 #include <string.h>
00002 #include <stdio.h>
00003 
00004 #include "rs485.h"
00005 
00006 #define DEBUG
00007 
00008 static list_t functionList = { .index = 0 };
00009 
00010 Packet buildPacket;
00011 static unsigned int buffPtr;
00012 static unsigned char buffer[128+1];
00013 int checksum;
00014 int pState = START;
00015 int returnState;
00016 unsigned int plength;
00017 unsigned char command;
00018 int message;
00019 static unsigned char packetBuffer[128];
00020 static unsigned int packetBufferSize;
00021 
00022 /************************** External Functions********************************
00023 *   These functions need to be externall defined to be able to process packets
00024 *    and to send out chars over the bus.
00025 /************************** External Functions********************************/
00026 extern int Bluetooth_ReceivePacket( Packet *_packet );
00027 extern int Bluetooth_SendChar( unsigned char );
00028 extern const unsigned char DEVADDRESS;
00029 
00030 /******************************************************************************
00031  * Function void RegisterCommand( command , function )
00032  *
00033  * When a command is registered with this function it will be added to the function
00034  *  list. Once on the list, when a packet is received on the bus containing that
00035  *  command the associated function will get called and it will be passed the data
00036  *  within the packet as a parameter.
00037  *
00038  * PreCondition:    None
00039  *
00040  * Input:           'command'  - command byte
00041  *                  'function' - pointer to function to be called
00042  *                  
00043  * Output:          None
00044  *
00045  * Side Effects:    None
00046  *
00047  *****************************************************************************/
00048 unsigned char RegisterCommand( unsigned char _command , void (*_function)( unsigned char *) ){
00049     functionList.list[ functionList.index ].function = _function;
00050     functionList.list[ functionList.index ].command = _command;
00051     functionList.index++;      
00052     return 0;
00053 }
00054 
00055 /******************************************************************************
00056  * Function void CheckFunction( Packet * )
00057  *
00058  * This passes in a packet and compares the command byte with a list of registered
00059  *  commands. If it finds a match it will call that function along with the data
00060  *  in the packet.
00061  *
00062  * PreCondition:    None
00063  *
00064  * Input:           '_packet' - packet containing command byte and data
00065  *                  
00066  * Output:          '1' - command matched and function called
00067  *                  '2' - no command found
00068  *
00069  * Side Effects:    None
00070  *
00071  *****************************************************************************/
00072 int CheckFunction( Packet *_packet ){
00073     int i = 0;
00074     void (*Caller)(unsigned char *);
00075     for( i = 0 ; i < functionList.index ; i++ ){
00076         if( _packet->command == functionList.list[i].command ){
00077             Caller = (void (*)(unsigned char *))functionList.list[i].function;
00078             Caller( (unsigned char *)_packet->packetData );
00079             return 1;
00080         }
00081     }
00082     return 0;
00083 }
00084 
00085 void RS495_Init( void ){
00086        
00087 }
00088 
00089 /******************************************************************************
00090  * Function void SendAck( void )
00091  *
00092  * Sends an acknowledge byte over the bus. It calls an external function to
00093  *  handle the actual hardware communication.
00094  *
00095  * PreCondition:    None
00096  *
00097  * Input:           '_packet' - prebuilt packet to send
00098  *                  
00099  * Output:          None
00100  *
00101  * Side Effects:    None
00102  *
00103  *****************************************************************************/ 
00104 static void SendAck( void ){
00105     #ifdef DEBUG
00106         pc.printf( "\n\rAck Sent.\n\r" );
00107     #endif // DEBUG
00108     unsigned char ack = ACKCHAR;
00109     Bluetooth_SendChar( ack );
00110 }
00111 
00112 /******************************************************************************
00113  * Function void SendNack( void )
00114  *
00115  * Sends a non acknowledge byte over the bus. It calls an external function to
00116  *  handle the actual hardware communication.
00117  *
00118  * PreCondition:    None
00119  *
00120  * Input:           '_packet' - prebuilt packet to send
00121  *                  
00122  * Output:          None
00123  *
00124  * Side Effects:    None
00125  *
00126  *****************************************************************************/ 
00127 static void SendNack( void ){
00128     #ifdef DEBUG
00129         pc.printf( "\n\rNack Sent.\n\r" );
00130     #endif // DEBUG
00131     unsigned char nack = NAKCHAR;
00132     Bluetooth_SendChar( nack );
00133 }
00134 
00135 /******************************************************************************
00136  * Function void ProcessPacket( Packet *)
00137  *
00138  * Gets automatically called once an entire packet is successfully received.
00139  *  May modify what is done, but it should just pass the packet over to 
00140  *  an external function where it can be correctly handled.
00141  *
00142  * PreCondition:    None
00143  *
00144  * Input:           '_packet' - packet received on bus
00145  *                  
00146  * Output:          None
00147  *
00148  * Side Effects:    None
00149  *
00150  *****************************************************************************/ 
00151 static int ProcessPacket( Packet *_packet ){
00152     return Bluetooth_ReceivePacket( _packet );
00153 }
00154 
00155 /******************************************************************************
00156  * Function void setResponse(int, int, int)
00157  *
00158  * This function sets the feedback information to be send in the master device.
00159  *
00160  * PreCondition:    None
00161  *
00162  * Input:           '_packet' - prebuilt packet to send
00163  *                  
00164  * Output:          None
00165  *
00166  * Side Effects:    None
00167  *
00168  *****************************************************************************/  
00169 void SendMessage( void ){    
00170     int j = 0;
00171     Bluetooth_SendChar( packetBuffer[ j++ ] );
00172     while( j < packetBufferSize ){
00173         if( packetBuffer[ j ] ==  STARTPACK ){
00174             Bluetooth_SendChar( ESCAPE );     //  #SCD Added this line, I think it should be here
00175             Bluetooth_SendChar( 0x01 );
00176             j++;
00177         }
00178         else if( packetBuffer[ j ] == ESCAPE ){
00179             Bluetooth_SendChar( ESCAPE );
00180             Bluetooth_SendChar( ESCAPE );
00181             j++;
00182         }
00183         else if( packetBuffer[ j ] ==  STARTPOLL ){
00184             Bluetooth_SendChar( ESCAPE );
00185             Bluetooth_SendChar( 0x02 );
00186             j++;
00187         }
00188         else{
00189             Bluetooth_SendChar( packetBuffer[ j++ ] );
00190         }
00191     }    
00192 }
00193 
00194 /******************************************************************************
00195  * Function void SetResponse( Packet *_packet )
00196  *
00197  * This function sets the feedback information to be send in the master device.
00198  *
00199  * PreCondition:    None
00200  *
00201  * Input:           '_packet' - prebuilt packet to send
00202  *                  
00203  * Output:          None
00204  *
00205  * Side Effects:    None
00206  *
00207  *****************************************************************************/ 
00208  void SetResponsePacket( Packet *_packet ){
00209     packetBufferSize = getFormattedPacket(_packet, packetBuffer);    
00210     message = 1;
00211 }
00212 
00213 /******************************************************************************
00214  * Function void SetResponseWithData( unsigned char deviceID, unsigned char 
00215     command, unsigned char * data, unsigned short dataLength)
00216  *
00217  * This function sets the feedback information to be send in the master device.
00218  *
00219  * PreCondition:    None
00220  *
00221  * Input:           'deviceID'   - address where the packet is going
00222                     'command'    - command to be sent
00223                     '*data'      - point to unsiged char array packet with data
00224                     'dataLength' - length of 'data'
00225  *                  
00226  * Output:          None
00227  *
00228  * Side Effects:    None
00229  *
00230  *****************************************************************************/ 
00231 void SetResponseWithData( unsigned char deviceID, unsigned char command, unsigned char * data, unsigned short dataLength){
00232         
00233     //  build packet to be sent    
00234     Packet packet;    
00235     packet.deviceID = deviceID;
00236     packet.sourceID = DEVADDRESS;
00237     packet.command = command;
00238     packet.packetLength = dataLength;
00239     memcpy( packet.packetData , data , dataLength );
00240     packetBufferSize = getFormattedPacket(&packet, packetBuffer);
00241     
00242     //  print message to be sent
00243     #ifdef DEBUG
00244         pc.printf( "Message to send: ");    
00245         unsigned short length = 0;
00246         for( length = 1 ; length < ( dataLength + sizeof( packet.deviceID ) + sizeof( packet.sourceID ) + sizeof( packet.command ) + sizeof( packet.packetLength ) + 1 ) ; length++ ){
00247             pc.printf( "%x " , packetBuffer[ length ] );   
00248         }
00249         pc.printf( "\n\r" );
00250     #endif
00251     
00252     message = 1;
00253 }
00254 
00255 /******************************************************************************
00256  * Function void SerialHandler(unsigned char )
00257  *
00258  * This function handles the received data from the Serial Communication.
00259  *
00260  * PreCondition:    None
00261  *
00262  * Input:           'RXByte' - the received data from Serial Communication
00263  *
00264  *
00265  * Output:          None
00266  *
00267  * Side Effects:    Will call functions to send ACK, NACK and process a packet
00268  *                   once an entire packet is received.
00269  *
00270  *****************************************************************************/
00271 void SerialHandler(unsigned char RXByte){
00272     
00273     #ifdef DEBUG
00274         pc.printf( "RXByte: %x" , RXByte );
00275     #endif
00276 
00277 
00278     //  check the incoming byte for special characters
00279     if( RXByte ==  STARTPACK ){                     //  start of packet byte
00280         #ifdef DEBUG
00281             pc.printf( " - STARTBYTE\n\r" );
00282         #endif
00283         pState = DEVICEADDRESS;                     //  move on to check the destination address
00284         buffPtr = 0;                                //  reset buffer pointer
00285         buffer[buffPtr++] = STARTPACK;              //  load RXByte into buffer
00286         checksum = STARTPACK;                       //  add to checksum
00287         return;                                     //  exit function, will be called again in next state
00288     }
00289     else if( RXByte == STARTPOLL ){                 //  poll byte
00290         #ifdef DEBUG
00291             pc.printf( " - STARTPOLL\n\r" );
00292         #endif
00293         pState = POLL;                              //  move on to check the distination address
00294         return;                                     //  exit function, will be called again in next state
00295     }
00296     else if( RXByte == ESCAPE ){                    //  escape byte
00297         if( pState == HANDLEESCAPE ){               //  if this is the second escape byte in a row
00298         }
00299         else{
00300             #ifdef DEBUG
00301                 pc.printf( " - ESCAPE TO " );
00302             #endif
00303             returnState = pState;                   //  if this is the first escape byte, record the current state
00304             pState = HANDLEESCAPE;                  //  change state
00305             return;                                 //  exit function, will be called again in next state
00306         }
00307     }
00308 
00309     if( pState == HANDLEESCAPE ){                   //  if entering here RXByte needs to be unescaped
00310         switch( RXByte ){
00311             case 1:                                 //  unescape a 0x7F/Start of packet byte
00312                 RXByte = 0x7F;
00313                 #ifdef DEBUG
00314                     pc.printf( " -> %x" , RXByte );
00315                 #endif
00316                 break;
00317 
00318             case 2:                                 //  unescape a 0x8F/Poll byte
00319                 RXByte = 0x8F;
00320                 #ifdef DEBUG
00321                     pc.printf( " -> %x" , RXByte );
00322                 #endif
00323                 break;
00324 
00325             case ESCAPE:                            //  unescape a 0x8E/Escape byte
00326                 RXByte = 0x8E;
00327                 #ifdef DEBUG
00328                     pc.printf( " -> %x" , RXByte );
00329                 #endif
00330                 break;
00331         }
00332         pState = returnState;                       //  change back to state before escape byte received
00333     }
00334 
00335     switch( pState ){
00336 
00337         case POLL: //  of switch( pState )          //  poll state checks RXByte to see if there is an address match
00338 
00339 
00340             if( RXByte == DEVADDRESS ){             //  if the device is being polled...
00341                 #ifdef DEBUG
00342                    pc.printf( " - Address Match: %x" , DEVADDRESS );
00343                 #endif
00344 
00345                 if( message ){                      //  if a message is available send it
00346                     #ifdef DEBUG
00347                         pc.printf( " - Message to Send\n\r" );
00348                     #endif
00349                     SendMessage();                //  #SCD haven't tested this
00350                     pState = RESPONSE;              //  change state to wait for ACK or NACK
00351                 }
00352                 else{                               //  device is pulled but no message to be sent
00353                     #ifdef DEBUG
00354                         pc.printf( " - No message to Send\n\r" );
00355                     #endif
00356                   SendAck();                        //  just send an ACK
00357                   pState = START;
00358                 }
00359             }
00360             else{
00361                  pState = START;                    //  device not addressed, do nothing
00362             }
00363             break;
00364 
00365         case START: //  of switch( pState )         //  this state really does nothing and just waits for
00366             pState = START;                         //   if the device is not addressed in a packet
00367             break;
00368 
00369         case RESPONSE: //  of switch( pState )      //  a message was sent it last state and now this state is
00370 
00371             switch( RXByte ){
00372 
00373                 case ACKCHAR:                       //  ACK is received - message successful, clear message to be sent
00374                         #ifdef DEBUG
00375                             pc.printf( " - ACK RECEIVED\n\r" );
00376                         #endif
00377                     message = 0;
00378                     pState = START;
00379                     break;
00380 
00381                 case NAKCHAR:                       //  NACK is received - message not successful
00382                         #ifdef DEBUG
00383                             pc.printf( " - NACK RECEIVED\n\r" );
00384                         #endif
00385                     if( message ){                  //  if a message still needs to be sent, send again
00386                         SendMessage();
00387                         message = 0;                //  clear message after this seconda attempt to prevent too many tries
00388                         pState = RESPONSE;          //  set state to come by here next time around
00389                     }
00390                     else{                           //  if a NACK is received for the second time in a row
00391                         //#error #SCD               //  throw an error and do not resend
00392                         pc.printf( "Received two NACKs from master. Message failed.\n\r" );
00393                     }
00394                     break;
00395 
00396                 default:
00397                         #ifdef DEBUG
00398                             pc.printf( " - EXPECTED ACK or NACK\n\r" );
00399                         #endif
00400                     pState = START;                 //  if neither an ACK nor NACK is received, reset state
00401                     break;
00402 
00403             }
00404             break;
00405 
00406         case DEVICEADDRESS: //  of switch( pState ) //  checks to see if device is addressed in current packet
00407                 #ifdef DEBUG
00408                     pc.printf( " - DEVICEADDRESS\n\r" );
00409                 #endif
00410 
00411             if( RXByte == DEVADDRESS ){
00412                 #ifdef PRINT_ADDRESS_MATCH
00413                    pc.printf( "Address Match: %d\n\r" , DEVADDRESS );
00414                 #endif
00415 
00416                 pState = SOURCEADD;                 //  next state is grabbing the source device ID
00417                 buffer[buffPtr++] = RXByte;         //  add RXByte to buffer
00418                 buildPacket.deviceID = RXByte;      //  build packet
00419                 checksum += RXByte;                 //  add RXByte to checksum
00420             }
00421             else{
00422                 pState = START;                     //  if device is not addressed reset state
00423             }
00424 
00425             break;
00426 
00427         case SOURCEADD: //  of switch( pState )     //  records the source address of the packet
00428             #ifdef DEBUG
00429                 pc.printf( " - SOURCEADD\n\r" );
00430             #endif
00431 
00432             pState = COLLECTCOMMAND;                //  state advances to get the command byte
00433             buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00434             buildPacket.sourceID = RXByte;           //  build packet
00435             checksum += RXByte;                     //  add RXByte to checksum
00436             break;
00437 
00438         case COLLECTCOMMAND: //  of switch( pState )//  records the command byte of the packet
00439             #ifdef DEBUG
00440                 pc.printf( " - COMMAND\n\r" );
00441             #endif
00442 
00443             command = RXByte;                       //  record command byte
00444             buildPacket.command = RXByte;           //  build packet
00445             pState = COLLECTCOUNT1;                 //  advance to get packetLength
00446             buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00447             checksum += RXByte;                     //  add RXByte to checksum
00448             break;
00449 
00450         case COLLECTCOUNT1: //  of switch( pState ) //  records first byte of packetLength
00451             #ifdef DEBUG
00452                 pc.printf( " - COUNT MSB \n\r" );
00453             #endif
00454 
00455             pState = COLLECTCOUNT2;                 //  advance state to get next byte of packetLength
00456             plength = RXByte;
00457             plength <<= 8;                  //  store byte in packetLength #SCD is this storing correctly?
00458             buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00459             checksum += RXByte;                     //  add RXByte to checksum
00460             break;
00461 
00462         case COLLECTCOUNT2: //  of switch( pState ) //  records second byte of packetLength
00463             #ifdef DEBUG
00464                 pc.printf( " - COUNT LSB\n\r" );
00465             #endif
00466 
00467             plength += RXByte;                      //  add RXByte to packetLength total
00468             buildPacket.packetLength = plength;     //  build packet
00469             buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00470             checksum += RXByte;                     //  add RXByte to checksum
00471             if( plength == 0 )                      //  if packetLength is 0, advance to checksum state
00472                 pState = COLLECTCHECKSUM;
00473             else                                    //  otherwise move on to collect packet payload
00474                 pState = COLLECTPACKET;
00475             break;
00476 
00477         case COLLECTPACKET: //  of switch( pState ) //  collects packetData, enters this state multiple times
00478             #ifdef DEBUG
00479                 pc.printf( " - PACKETDATA \n\r" );
00480             #endif
00481 
00482             plength--;                              //  decrement length
00483             buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00484             checksum += RXByte;                     //  add RXByte to checksum
00485 
00486             if( plength == 0 ){                     //  if collected all packetData advance state
00487                 pState = COLLECTCHECKSUM;
00488             }
00489             break;
00490 
00491         case COLLECTCHECKSUM://  of switch( pState )        // collects checksum of packet and checks for validity
00492             #ifdef DEBUG
00493                 pc.printf( " - CHECKSUM\n\r" );
00494             #endif
00495             memcpy( &buildPacket.packetData , &buffer[6] , buildPacket.packetLength );
00496 
00497             if( RXByte == ( ( checksum* - 1 ) & 0xFF ) ){   //  compares RXByte with LSB of checksum
00498                 message = 0;                                //  if checksum is correct clear message #SCD could a message be waiting?
00499                 memset(packetBuffer, '\0', 128);            //  clear packetBuffer
00500                
00501                 buffer[buffPtr++] = RXByte;             //  add RXByte to buffer
00502                 
00503                 #ifdef DEBUG
00504                    pc.printf( "Receive Buffer: " );       //  debug print received packet
00505                     unsigned int i = 0;
00506                     for( i = 0 ; i < buffPtr ; i++ ){
00507                        pc.printf( "%x " , buffer[ i ] );
00508                     }
00509                    pc.printf( "\n\r" );
00510                 #endif
00511 
00512                 int errorResult = ProcessPacket( &buildPacket );
00513 
00514                 if( errorResult == -1 ){                                    //  check to make sure function performed properly
00515                     //#SCD setResponse(RPIADDRESS, command, ERRORCOMMAND);
00516                 }
00517                 SendAck();                                          //  send an ACK
00518             }
00519             else{
00520                 SendNack();                              //  if checksum is not corret, send a NACK
00521             }
00522 
00523             pState = START;
00524             break;
00525 
00526     }   //  end switch( pState )
00527 
00528 }   //  end serial2Handler function
00529 
00530