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.
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
Generated on Tue Jul 12 2022 22:58:49 by
1.7.2