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:

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 41 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 81 of file commsISRs.c.

References RXBufferCurrentPosition, RXCalculatedChecksum, and RXPacketLengthReceived.

Referenced by SCI0ISR().

00081                                                                  {
00082     *RXBufferCurrentPosition = value;
00083     RXCalculatedChecksum += value;
00084     RXBufferCurrentPosition++;
00085     RXPacketLengthReceived++;
00086 }

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!

TODO CAN0CTL1 &= CANCTL1_RX_ISR_DISABLE;

TODO CAN0CTL1 |= CANCTL1_RX_ISR_ENABLE;

Parameters:
sourceIDState is the state to apply to the RX buffer state variable.

Todo:
TODO CAN0CTL1 &= CANCTL1_RX_DISABLE;

Todo:
TODO CAN0CTL1 |= CANCTL1_RX_ENABLE;

Definition at line 99 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().

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

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 147 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.

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

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 64 of file commsISRs.c.

References SCI0DRL, TXBufferCurrentPositionSCI0, and TXPacketLengthToSendSCI0.

Referenced by SCI0ISR().

00064                                                            {
00065     SCI0DRL = rawValue;
00066     TXPacketLengthToSendSCI0--;
00067     TXBufferCurrentPositionSCI0++;
00068 }


Generated on Mon Jan 26 00:16:25 2009 for FreeEMS by  doxygen 1.5.8