commsISRs.c File Reference

Send and receive bytes serially. More...

#include "inc/freeEMS.h"
#include "inc/interrupts.h"
#include "inc/utils.h"
#include "inc/commsCore.h"
#include "inc/commsISRs.h"
Include dependency graph for commsISRs.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define COMMSISRS_C

Functions

void sendAndIncrement (unsigned char rawValue)
 Send And Increment.
void receiveAndIncrement (const unsigned char value)
 Receive And Increment.
void resetReceiveState (unsigned char sourceIDState)
 Reset Receive State.
void SCI0ISR ()
 Serial Communication Interface 0 ISR.

Detailed Description

Send and receive bytes serially.

This file contains the code for both send and receive of serial bytes through the UART SCI0 device. It is purely interrupt driven and controlled by a set of register and non-register flags that are toggled both inside and outside this file. Some additional helper functions are also kept here.

Todo:
TODO SCI0ISR() needs to be split into some hash defines and an include file that formats it to be the ISR for a specific channel.
Author:
Fred Cooke

Definition in file commsISRs.c.


Define Documentation

#define COMMSISRS_C

Definition at line 44 of file commsISRs.c.


Function Documentation

void receiveAndIncrement ( const unsigned char  value  )  [inline]

Receive And Increment.

Store the value and add it to the checksum, then increment the pointer and length.

Author:
Fred Cooke
Note:
This is an extern inline function and as such is always inlined.
Parameters:
value is the byte of data to store in the buffer and add to the checksum.

Definition at line 84 of file commsISRs.c.

References RXBufferCurrentPosition, RXCalculatedChecksum, and RXPacketLengthReceived.

Referenced by SCI0ISR().

00084                                                                  {
00085     *RXBufferCurrentPosition = value;
00086     RXCalculatedChecksum += value;
00087     RXBufferCurrentPosition++;
00088     RXPacketLengthReceived++;
00089 }

void resetReceiveState ( unsigned char  sourceIDState  ) 

Reset Receive State.

Reset communications reception to the state provided.

Author:
Fred Cooke
Todo:
TODO this is in the wrong file!! Either move the header declaration or move the function!
Parameters:
sourceIDState is the state to apply to the RX buffer state variable.

Todo:
TODO CAN0CTL1 &= CANCTL1_RX_DISABLE;
Todo:
TODO CAN0CTL1 &= CANCTL1_RX_ISR_DISABLE;
Todo:
TODO CAN0CTL1 |= CANCTL1_RX_ENABLE;
Todo:
TODO CAN0CTL1 |= CANCTL1_RX_ISR_ENABLE;

Definition at line 102 of file commsISRs.c.

References COM_SET_CAN0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, RXBufferContentSourceID, RXBufferCurrentPosition, RXCalculatedChecksum, RXPacketLengthReceived, RXStateFlags, SCI0CR2, SCICR2_RX_DISABLE, SCICR2_RX_ENABLE, SCICR2_RX_ISR_DISABLE, and SCICR2_RX_ISR_ENABLE.

Referenced by decodePacketAndRespond(), and SCI0ISR().

00102                                                    {
00103     /* Set the receive buffer pointer to the beginning */
00104     RXBufferCurrentPosition = (unsigned char*)&RXBuffer;
00105 
00106     /* Zero the flags, buffer length and checksum */
00107     RXPacketLengthReceived = 0;
00108     RXCalculatedChecksum = 0;
00109     RXStateFlags = 0;
00110 
00111     /* Set the source ID state (clear all or all but one flag(s)) */
00112     RXBufferContentSourceID = sourceIDState;
00113 
00114     /* Which ever interface we are setting is the one we came from. By definition   */
00115     /* it must be on and we want it to stay on, so just turn off all the others.    */
00116     if(sourceIDState & COM_SET_SCI0_INTERFACE_ID){
00117         /* Turn off all others here */
00120         /* SPI ? I2C ? SCI1 ? */
00121     }else if(sourceIDState & COM_SET_CAN0_INTERFACE_ID){
00122         /* Turn off all others here */
00123         /* Only SCI for now */
00124         SCI0CR2 &= SCICR2_RX_DISABLE;
00125         SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00126         /* SPI ? I2C ? SCI1 ? */
00127     }else{ /* If clearing all flags then enable RX on all interfaces */
00128         /* Only SCI for now */
00129         SCI0CR2 |= SCICR2_RX_ENABLE;
00130         SCI0CR2 |= SCICR2_RX_ISR_ENABLE;
00133         /* SPI ? I2C ? SCI1 ? */
00134     }
00135 }

void SCI0ISR ( void   ) 

Serial Communication Interface 0 ISR.

SCI0 ISR handles all interrupts for SCI0 by reading flags and acting appropriately. Its functions are to send raw bytes out over the wire from a buffer and to receive bytes from the wire un-escape them, checksum them and store them in a buffer.

Author:
Fred Cooke
Todo:

TODO Move this code into an include file much like the fuel interrupts such that it can be used for multiple UART SCI devices without duplication.

TODO Remove the debug code that uses the IO ports to light LEDs during specific actions.

Definition at line 150 of file commsISRs.c.

References BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, CLEAR_ALL_SOURCE_ID_FLAGS, COM_CLEAR_SCI0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, Counter::commsChecksumMismatches, Counters, ESCAPE_BYTE, ESCAPED_ESCAPE_BYTE, ESCAPED_START_BYTE, ESCAPED_STOP_BYTE, PORTA, PORTB, receiveAndIncrement(), resetReceiveState(), RuntimeVars, RX_BUFFER_SIZE, RX_READY_TO_PROCESS, RX_SCI_ESCAPED_NEXT, RX_SCI_NOT_ESCAPED_NEXT, RXBufferContentSourceID, RXBufferCurrentPosition, RXCalculatedChecksum, RXPacketLengthReceived, RXStateFlags, SCI0CR2, SCI0DRL, SCI0SR1, SCICR2_RX_DISABLE, SCICR2_RX_ISR_DISABLE, SCICR2_RX_ISR_ENABLE, SCICR2_TX_ISR_DISABLE, SCICR2_TX_ISR_ENABLE, SCISR1_RX_FRAMING, SCISR1_RX_NOISE, SCISR1_RX_OVERRUN, SCISR1_RX_PARITY, SCISR1_RX_REGISTER_FULL, SCISR1_TX_REGISTER_EMPTY, sendAndIncrement(), Counter::serialEscapePairMismatches, Counter::serialFramingErrors, RuntimeVar::serialISRRuntime, Counter::serialNoiseErrors, Counter::serialOverrunErrors, Counter::serialPacketsOverLength, Counter::serialParityErrors, Counter::serialStartsInsideAPacket, START_BYTE, STOP_BYTE, TCNT, TXBufferCurrentPositionSCI0, TXBufferInUseFlags, TXByteEscaped, and TXPacketLengthToSendSCI0.

00150               {
00151     /* Read the flags register */
00152     unsigned char flags = SCI0SR1;
00153     /* Note: Combined with reading or writing the data register this also clears the flags. */
00154 
00155     /* Start counting */
00156     unsigned short start = TCNT;
00157 
00158     /* If the RX interrupt is enabled check RX related flags */
00159     if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){
00160         /* Grab the received byte from the register */
00161         unsigned char rawByte = SCI0DRL;
00162 
00163         PORTB |= BIT0;
00164 
00165         /* Record error conditions always */
00166         unsigned char resetOnError = 0;
00167         /* If there is noise on the receive line record it */
00168         if(flags & SCISR1_RX_NOISE){
00169             Counters.serialNoiseErrors++;
00170             resetOnError++;
00171         }/* If an overrun occurs record it */
00172         if(flags & SCISR1_RX_OVERRUN){
00173             Counters.serialOverrunErrors++;
00174             resetOnError++;
00175         }/* If a framing error occurs record it */
00176         if(flags & SCISR1_RX_FRAMING){
00177             Counters.serialFramingErrors++;
00178             resetOnError++;
00179         }/* If a parity error occurs record it */
00180         if(flags & SCISR1_RX_PARITY){
00181             Counters.serialParityErrors++;
00182             resetOnError++;
00183         }
00184 
00185         /* Drop out because of error flags  */
00186         if(resetOnError){
00187             resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00188             PORTB |= BIT1;
00189             return;
00190         }
00191 
00192         /* If there is data waiting to be received */
00193         if(flags & SCISR1_RX_REGISTER_FULL){
00194             PORTB |= BIT2;
00195             /* Look for a start bresetReceiveStateyte to indicate a new packet */
00196             if(rawByte == START_BYTE){
00197                 PORTB |= BIT3;
00198                 /* If another interface is using it (Note, clear flag, not normal) */
00199                 if(RXBufferContentSourceID & COM_CLEAR_SCI0_INTERFACE_ID){
00200                     /* Turn off our reception */
00201                     SCI0CR2 &= SCICR2_RX_DISABLE;
00202                     SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00203                     PORTB |= BIT4;
00204                 }else{
00205                     PORTB |= BIT5;
00206                     /* If we are using it */
00207                     if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00208                         /* Increment the counter */
00209                         Counters.serialStartsInsideAPacket++;
00210                     }
00211                     /* Reset to us using it unless someone else was */
00212                     resetReceiveState(COM_SET_SCI0_INTERFACE_ID);
00213                 }
00214             }else if(RXPacketLengthReceived >= RX_BUFFER_SIZE){
00215                 /* Buffer was full, record and reset */
00216                 Counters.serialPacketsOverLength++;
00217                 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00218                 PORTB |= BIT6;
00219             }else if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00220                 if(RXStateFlags & RX_SCI_ESCAPED_NEXT){
00221                     PORTB |= BIT7;
00222                     /* Clear escaped byte next flag, thanks Karsten! ((~ != !) == (! ~= ~)) == LOL */
00223                     RXStateFlags &= RX_SCI_NOT_ESCAPED_NEXT;
00224 
00225                     if(rawByte == ESCAPED_ESCAPE_BYTE){
00226                         /* Store and checksum escape byte */
00227                         receiveAndIncrement(ESCAPE_BYTE);
00228                     }else if(rawByte == ESCAPED_START_BYTE){
00229                         /* Store and checksum start byte */
00230                         receiveAndIncrement(START_BYTE);
00231                     }else if(rawByte == ESCAPED_STOP_BYTE){
00232                         /* Store and checksum stop byte */
00233                         receiveAndIncrement(STOP_BYTE);
00234                     }else{
00235                         /* Otherwise reset and record as data is bad */
00236                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00237                         Counters.serialEscapePairMismatches++;
00238                     }
00239                 }else if(rawByte == ESCAPE_BYTE){
00240                     PORTA |= BIT0;
00241                     /* Set flag to indicate that the next byte should be un-escaped. */
00242                     RXStateFlags |= RX_SCI_ESCAPED_NEXT;
00243                 }else if(rawByte == STOP_BYTE){
00244                     PORTA |= BIT1;
00245                     /* Turn off reception */
00246                     SCI0CR2 &= SCICR2_RX_DISABLE;
00247                     SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00248 
00249                     /* Bring the checksum back to where it should be */
00250                     unsigned char RXReceivedChecksum = (unsigned char)*(RXBufferCurrentPosition - 1);
00251                     RXCalculatedChecksum -= RXReceivedChecksum;
00252 
00253                     /* Check that the checksum matches */
00254                     if(RXCalculatedChecksum == RXReceivedChecksum){
00255                         /* If it's OK set process flag */
00256                         RXStateFlags |= RX_READY_TO_PROCESS;
00257                         PORTA |= BIT2;
00258                     }else{
00259                         PORTA |= BIT3;
00260                         /* Otherwise reset the state and record it */
00261                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00262                         Counters.commsChecksumMismatches++;
00263                     }
00264                 }else{
00265                     PORTA |= BIT4;
00266                     /* If it isn't special process it! */
00267                     receiveAndIncrement(rawByte);
00268                 }
00269             }else{
00270                 /* Do nothing : drop the byte */
00271                 PORTA |= BIT5;
00272             }
00273         }
00274     }
00275 
00276     /* If the TX interrupt is enabled check the register empty flag. */
00277     if((SCI0CR2 & SCICR2_TX_ISR_ENABLE) && (flags & SCISR1_TX_REGISTER_EMPTY)){
00278         /* Get the byte to be sent from the buffer */
00279         unsigned char rawValue = *TXBufferCurrentPositionSCI0;
00280 
00281         if(TXPacketLengthToSendSCI0 > 0){
00282             if(TXByteEscaped == 0){
00283                 /* If the raw value needs to be escaped */
00284                 if(rawValue == ESCAPE_BYTE){
00285                     SCI0DRL = ESCAPE_BYTE;
00286                     TXByteEscaped = ESCAPED_ESCAPE_BYTE;
00287                 }else if(rawValue == START_BYTE){
00288                     SCI0DRL = ESCAPE_BYTE;
00289                     TXByteEscaped = ESCAPED_START_BYTE;
00290                 }else if(rawValue == STOP_BYTE){
00291                     SCI0DRL = ESCAPE_BYTE;
00292                     TXByteEscaped = ESCAPED_STOP_BYTE;
00293                 }else{ /* Otherwise just send it */
00294                     sendAndIncrement(rawValue);
00295                 }
00296             }else{
00297                 sendAndIncrement(TXByteEscaped);
00298                 TXByteEscaped = 0;
00299             }
00300         }else{ /* Length is zero */
00301             /* Turn off transmission interrupt */
00302             SCI0CR2 &= SCICR2_TX_ISR_DISABLE;
00303             /* Send the stop byte */
00304             SCI0DRL = STOP_BYTE;
00305             while(!(SCI0SR1 & 0x80)){/* Wait for ever until able to send then move on */}
00306             SCI0DRL = STOP_BYTE; // nasty hack that works... means at least one and most 2 stops are sent so stuff works, but is messy... there must be a better way.
00307             /* Clear the TX in progress flag */
00308             TXBufferInUseFlags &= COM_CLEAR_SCI0_INTERFACE_ID;
00309         }
00310     }
00311 
00312     /* Record how long the operation took */
00313     RuntimeVars.serialISRRuntime = TCNT - start;
00314 }

Here is the call graph for this function:

void sendAndIncrement ( unsigned char  rawValue  )  [inline]

Send And Increment.

Increment the pointer, decrement the length, and send it!

Author:
Fred Cooke
Note:
This is an extern inline function and as such is always inlined.
Parameters:
rawValue is the raw byte to be sent down the serial line.

Definition at line 67 of file commsISRs.c.

References SCI0DRL, TXBufferCurrentPositionSCI0, and TXPacketLengthToSendSCI0.

Referenced by SCI0ISR().

00067                                                            {
00068     SCI0DRL = rawValue;
00069     TXPacketLengthToSendSCI0--;
00070     TXBufferCurrentPositionSCI0++;
00071 }

Generated on Sat Oct 16 21:29:05 2010 for FreeEMS by  doxygen 1.6.3