Stephen Davis
/
BT_Hub
Library set up as dummy module on mbed to mimic Nordic.
rs485.cpp
- Committer:
- Stephen_NewVistas
- Date:
- 2016-12-13
- Revision:
- 2:9ab591cf81b8
- Parent:
- 1:d6b18299a715
File content as of revision 2:9ab591cf81b8:
#include <string.h> #include <stdio.h> #include "rs485.h" #define DEBUG static list_t functionList = { .index = 0 }; Packet buildPacket; static unsigned int buffPtr; static unsigned char buffer[128+1]; int checksum; int pState = START; int returnState; unsigned int plength; unsigned char command; int message; static unsigned char packetBuffer[128]; static unsigned int packetBufferSize; /************************** External Functions******************************** * These functions need to be externall defined to be able to process packets * and to send out chars over the bus. /************************** External Functions********************************/ extern int Bluetooth_ReceivePacket( Packet *_packet ); extern int Bluetooth_SendChar( unsigned char ); extern const unsigned char DEVADDRESS; /****************************************************************************** * Function void RegisterCommand( command , function ) * * When a command is registered with this function it will be added to the function * list. Once on the list, when a packet is received on the bus containing that * command the associated function will get called and it will be passed the data * within the packet as a parameter. * * PreCondition: None * * Input: 'command' - command byte * 'function' - pointer to function to be called * * Output: None * * Side Effects: None * *****************************************************************************/ unsigned char RegisterCommand( unsigned char _command , void (*_function)( unsigned char *) ){ functionList.list[ functionList.index ].function = _function; functionList.list[ functionList.index ].command = _command; functionList.index++; return 0; } /****************************************************************************** * Function void CheckFunction( Packet * ) * * This passes in a packet and compares the command byte with a list of registered * commands. If it finds a match it will call that function along with the data * in the packet. * * PreCondition: None * * Input: '_packet' - packet containing command byte and data * * Output: '1' - command matched and function called * '2' - no command found * * Side Effects: None * *****************************************************************************/ int CheckFunction( Packet *_packet ){ int i = 0; void (*Caller)(unsigned char *); for( i = 0 ; i < functionList.index ; i++ ){ if( _packet->command == functionList.list[i].command ){ Caller = (void (*)(unsigned char *))functionList.list[i].function; Caller( (unsigned char *)_packet->packetData ); return 1; } } return 0; } void RS495_Init( void ){ } /****************************************************************************** * Function void SendAck( void ) * * Sends an acknowledge byte over the bus. It calls an external function to * handle the actual hardware communication. * * PreCondition: None * * Input: '_packet' - prebuilt packet to send * * Output: None * * Side Effects: None * *****************************************************************************/ static void SendAck( void ){ #ifdef DEBUG pc.printf( "\n\rAck Sent.\n\r" ); #endif // DEBUG unsigned char ack = ACKCHAR; Bluetooth_SendChar( ack ); } /****************************************************************************** * Function void SendNack( void ) * * Sends a non acknowledge byte over the bus. It calls an external function to * handle the actual hardware communication. * * PreCondition: None * * Input: '_packet' - prebuilt packet to send * * Output: None * * Side Effects: None * *****************************************************************************/ static void SendNack( void ){ #ifdef DEBUG pc.printf( "\n\rNack Sent.\n\r" ); #endif // DEBUG unsigned char nack = NAKCHAR; Bluetooth_SendChar( nack ); } /****************************************************************************** * Function void ProcessPacket( Packet *) * * Gets automatically called once an entire packet is successfully received. * May modify what is done, but it should just pass the packet over to * an external function where it can be correctly handled. * * PreCondition: None * * Input: '_packet' - packet received on bus * * Output: None * * Side Effects: None * *****************************************************************************/ static int ProcessPacket( Packet *_packet ){ return Bluetooth_ReceivePacket( _packet ); } /****************************************************************************** * Function void setResponse(int, int, int) * * This function sets the feedback information to be send in the master device. * * PreCondition: None * * Input: '_packet' - prebuilt packet to send * * Output: None * * Side Effects: None * *****************************************************************************/ void SendMessage( void ){ int j = 0; Bluetooth_SendChar( packetBuffer[ j++ ] ); while( j < packetBufferSize ){ if( packetBuffer[ j ] == STARTPACK ){ Bluetooth_SendChar( ESCAPE ); // #SCD Added this line, I think it should be here Bluetooth_SendChar( 0x01 ); j++; } else if( packetBuffer[ j ] == ESCAPE ){ Bluetooth_SendChar( ESCAPE ); Bluetooth_SendChar( ESCAPE ); j++; } else if( packetBuffer[ j ] == STARTPOLL ){ Bluetooth_SendChar( ESCAPE ); Bluetooth_SendChar( 0x02 ); j++; } else{ Bluetooth_SendChar( packetBuffer[ j++ ] ); } } } /****************************************************************************** * Function void SetResponse( Packet *_packet ) * * This function sets the feedback information to be send in the master device. * * PreCondition: None * * Input: '_packet' - prebuilt packet to send * * Output: None * * Side Effects: None * *****************************************************************************/ void SetResponsePacket( Packet *_packet ){ packetBufferSize = getFormattedPacket(_packet, packetBuffer); message = 1; } /****************************************************************************** * Function void SetResponseWithData( unsigned char deviceID, unsigned char command, unsigned char * data, unsigned short dataLength) * * This function sets the feedback information to be send in the master device. * * PreCondition: None * * Input: 'deviceID' - address where the packet is going 'command' - command to be sent '*data' - point to unsiged char array packet with data 'dataLength' - length of 'data' * * Output: None * * Side Effects: None * *****************************************************************************/ void SetResponseWithData( unsigned char deviceID, unsigned char command, unsigned char * data, unsigned short dataLength){ // build packet to be sent Packet packet; packet.deviceID = deviceID; packet.sourceID = DEVADDRESS; packet.command = command; packet.packetLength = dataLength; memcpy( packet.packetData , data , dataLength ); packetBufferSize = getFormattedPacket(&packet, packetBuffer); // print message to be sent #ifdef DEBUG pc.printf( "Message to send: "); unsigned short length = 0; for( length = 1 ; length < ( dataLength + sizeof( packet.deviceID ) + sizeof( packet.sourceID ) + sizeof( packet.command ) + sizeof( packet.packetLength ) + 1 ) ; length++ ){ pc.printf( "%x " , packetBuffer[ length ] ); } pc.printf( "\n\r" ); #endif message = 1; } /****************************************************************************** * Function void SerialHandler(unsigned char ) * * This function handles the received data from the Serial Communication. * * PreCondition: None * * Input: 'RXByte' - the received data from Serial Communication * * * Output: None * * Side Effects: Will call functions to send ACK, NACK and process a packet * once an entire packet is received. * *****************************************************************************/ void SerialHandler(unsigned char RXByte){ #ifdef DEBUG pc.printf( "RXByte: %x" , RXByte ); #endif // check the incoming byte for special characters if( RXByte == STARTPACK ){ // start of packet byte #ifdef DEBUG pc.printf( " - STARTBYTE\n\r" ); #endif pState = DEVICEADDRESS; // move on to check the destination address buffPtr = 0; // reset buffer pointer buffer[buffPtr++] = STARTPACK; // load RXByte into buffer checksum = STARTPACK; // add to checksum return; // exit function, will be called again in next state } else if( RXByte == STARTPOLL ){ // poll byte #ifdef DEBUG pc.printf( " - STARTPOLL\n\r" ); #endif pState = POLL; // move on to check the distination address return; // exit function, will be called again in next state } else if( RXByte == ESCAPE ){ // escape byte if( pState == HANDLEESCAPE ){ // if this is the second escape byte in a row } else{ #ifdef DEBUG pc.printf( " - ESCAPE TO " ); #endif returnState = pState; // if this is the first escape byte, record the current state pState = HANDLEESCAPE; // change state return; // exit function, will be called again in next state } } if( pState == HANDLEESCAPE ){ // if entering here RXByte needs to be unescaped switch( RXByte ){ case 1: // unescape a 0x7F/Start of packet byte RXByte = 0x7F; #ifdef DEBUG pc.printf( " -> %x" , RXByte ); #endif break; case 2: // unescape a 0x8F/Poll byte RXByte = 0x8F; #ifdef DEBUG pc.printf( " -> %x" , RXByte ); #endif break; case ESCAPE: // unescape a 0x8E/Escape byte RXByte = 0x8E; #ifdef DEBUG pc.printf( " -> %x" , RXByte ); #endif break; } pState = returnState; // change back to state before escape byte received } switch( pState ){ case POLL: // of switch( pState ) // poll state checks RXByte to see if there is an address match if( RXByte == DEVADDRESS ){ // if the device is being polled... #ifdef DEBUG pc.printf( " - Address Match: %x" , DEVADDRESS ); #endif if( message ){ // if a message is available send it #ifdef DEBUG pc.printf( " - Message to Send\n\r" ); #endif SendMessage(); // #SCD haven't tested this pState = RESPONSE; // change state to wait for ACK or NACK } else{ // device is pulled but no message to be sent #ifdef DEBUG pc.printf( " - No message to Send\n\r" ); #endif SendAck(); // just send an ACK pState = START; } } else{ pState = START; // device not addressed, do nothing } break; case START: // of switch( pState ) // this state really does nothing and just waits for pState = START; // if the device is not addressed in a packet break; case RESPONSE: // of switch( pState ) // a message was sent it last state and now this state is switch( RXByte ){ case ACKCHAR: // ACK is received - message successful, clear message to be sent #ifdef DEBUG pc.printf( " - ACK RECEIVED\n\r" ); #endif message = 0; pState = START; break; case NAKCHAR: // NACK is received - message not successful #ifdef DEBUG pc.printf( " - NACK RECEIVED\n\r" ); #endif if( message ){ // if a message still needs to be sent, send again SendMessage(); message = 0; // clear message after this seconda attempt to prevent too many tries pState = RESPONSE; // set state to come by here next time around } else{ // if a NACK is received for the second time in a row //#error #SCD // throw an error and do not resend pc.printf( "Received two NACKs from master. Message failed.\n\r" ); } break; default: #ifdef DEBUG pc.printf( " - EXPECTED ACK or NACK\n\r" ); #endif pState = START; // if neither an ACK nor NACK is received, reset state break; } break; case DEVICEADDRESS: // of switch( pState ) // checks to see if device is addressed in current packet #ifdef DEBUG pc.printf( " - DEVICEADDRESS\n\r" ); #endif if( RXByte == DEVADDRESS ){ #ifdef PRINT_ADDRESS_MATCH pc.printf( "Address Match: %d\n\r" , DEVADDRESS ); #endif pState = SOURCEADD; // next state is grabbing the source device ID buffer[buffPtr++] = RXByte; // add RXByte to buffer buildPacket.deviceID = RXByte; // build packet checksum += RXByte; // add RXByte to checksum } else{ pState = START; // if device is not addressed reset state } break; case SOURCEADD: // of switch( pState ) // records the source address of the packet #ifdef DEBUG pc.printf( " - SOURCEADD\n\r" ); #endif pState = COLLECTCOMMAND; // state advances to get the command byte buffer[buffPtr++] = RXByte; // add RXByte to buffer buildPacket.sourceID = RXByte; // build packet checksum += RXByte; // add RXByte to checksum break; case COLLECTCOMMAND: // of switch( pState )// records the command byte of the packet #ifdef DEBUG pc.printf( " - COMMAND\n\r" ); #endif command = RXByte; // record command byte buildPacket.command = RXByte; // build packet pState = COLLECTCOUNT1; // advance to get packetLength buffer[buffPtr++] = RXByte; // add RXByte to buffer checksum += RXByte; // add RXByte to checksum break; case COLLECTCOUNT1: // of switch( pState ) // records first byte of packetLength #ifdef DEBUG pc.printf( " - COUNT MSB \n\r" ); #endif pState = COLLECTCOUNT2; // advance state to get next byte of packetLength plength = RXByte; plength <<= 8; // store byte in packetLength #SCD is this storing correctly? buffer[buffPtr++] = RXByte; // add RXByte to buffer checksum += RXByte; // add RXByte to checksum break; case COLLECTCOUNT2: // of switch( pState ) // records second byte of packetLength #ifdef DEBUG pc.printf( " - COUNT LSB\n\r" ); #endif plength += RXByte; // add RXByte to packetLength total buildPacket.packetLength = plength; // build packet buffer[buffPtr++] = RXByte; // add RXByte to buffer checksum += RXByte; // add RXByte to checksum if( plength == 0 ) // if packetLength is 0, advance to checksum state pState = COLLECTCHECKSUM; else // otherwise move on to collect packet payload pState = COLLECTPACKET; break; case COLLECTPACKET: // of switch( pState ) // collects packetData, enters this state multiple times #ifdef DEBUG pc.printf( " - PACKETDATA \n\r" ); #endif plength--; // decrement length buffer[buffPtr++] = RXByte; // add RXByte to buffer checksum += RXByte; // add RXByte to checksum if( plength == 0 ){ // if collected all packetData advance state pState = COLLECTCHECKSUM; } break; case COLLECTCHECKSUM:// of switch( pState ) // collects checksum of packet and checks for validity #ifdef DEBUG pc.printf( " - CHECKSUM\n\r" ); #endif memcpy( &buildPacket.packetData , &buffer[6] , buildPacket.packetLength ); if( RXByte == ( ( checksum* - 1 ) & 0xFF ) ){ // compares RXByte with LSB of checksum message = 0; // if checksum is correct clear message #SCD could a message be waiting? memset(packetBuffer, '\0', 128); // clear packetBuffer buffer[buffPtr++] = RXByte; // add RXByte to buffer #ifdef DEBUG pc.printf( "Receive Buffer: " ); // debug print received packet unsigned int i = 0; for( i = 0 ; i < buffPtr ; i++ ){ pc.printf( "%x " , buffer[ i ] ); } pc.printf( "\n\r" ); #endif int errorResult = ProcessPacket( &buildPacket ); if( errorResult == -1 ){ // check to make sure function performed properly //#SCD setResponse(RPIADDRESS, command, ERRORCOMMAND); } SendAck(); // send an ACK } else{ SendNack(); // if checksum is not corret, send a NACK } pState = START; break; } // end switch( pState ) } // end serial2Handler function