commsISRs.c

Go to the documentation of this file.
00001 /*      commsISRs.c
00002 
00003         Copyright 2008 Fred Cooke
00004 
00005         This file is part of the FreeEMS project.
00006 
00007         FreeEMS software is free software: you can redistribute it and/or modify
00008         it under the terms of the GNU General Public License as published by
00009         the Free Software Foundation, either version 3 of the License, or
00010         (at your option) any later version.
00011 
00012         FreeEMS software is distributed in the hope that it will be useful,
00013         but WITHOUT ANY WARRANTY; without even the implied warranty of
00014         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015         GNU General Public License for more details.
00016 
00017         You should have received a copy of the GNU General Public License
00018         along with any FreeEMS software.  If not, see <http://www.gnu.org/licenses/>.
00019 
00020         We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org
00021 
00022         Thank you for choosing FreeEMS to run your engine! */
00023 
00024 #define COMMSISRS_C
00025 #include "inc/freeEMS.h"
00026 #include "inc/interrupts.h"
00027 #include "inc/utils.h"
00028 #include "inc/commsCore.h"
00029 #include "inc/commsISRs.h"
00030 
00031 
00032 /* The C89 standard is used in the 3.3.6 GCC compiler, please   *
00033  * see the following URL for more info on inline functions :    *
00034  * http://gcc.gnu.org/onlinedocs/gcc-3.3.6/Inline.html#Inline   */
00035 
00036 
00037 /* Increment the pointer, decrement the length, and send it! */
00038 extern inline void sendAndIncrement(unsigned char rawValue){
00039         SCI0DRL = rawValue;
00040         TXPacketLengthToSendSCI0--;
00041         TXBufferCurrentPositionSCI0++;
00042 }
00043 
00044 
00045 /* Store and checksum the value, then increment the pointer and length */
00046 extern inline void receiveAndIncrement(const unsigned char value){
00047         *RXBufferCurrentPosition = value;
00048         RXCalculatedChecksum += value;
00049         RXBufferCurrentPosition++;
00050         RXPacketLengthReceived++;
00051 }
00052 
00053 
00054 /* Reset serial reception to one of two states */
00055 void resetReceiveState(unsigned char sourceIDState){ // WRONG
00056         /* Set the receive buffer pointer to the beginning */
00057         RXBufferCurrentPosition = (unsigned char*)&RXBuffer;
00058 
00059         /* Zero the flags, buffer length and checksum */
00060         RXPacketLengthReceived = 0;
00061         RXCalculatedChecksum = 0;
00062         RXStateFlags = 0;
00063 
00064         /* Set the source ID state (clear all or all but one flag(s)) */
00065         RXBufferContentSourceID = sourceIDState;
00066 
00067         /* Which ever interface we are setting is the one we came from. By definition   */
00068         /* it must be on and we want it to stay on, so just turn off all the others.    */
00069         if(sourceIDState & COM_SET_SCI0_INTERFACE_ID){
00070                 /* Turn off all others here */
00071                 // TODO CAN0CTL1 &= CANCTL1_RX_DISABLE;
00072                 // TODO CAN0CTL1 &= CANCTL1_RX_ISR_DISABLE;
00073                 /* SPI ? I2C ? SCI1 ? */
00074         }else if(sourceIDState & COM_SET_CAN0_INTERFACE_ID){
00075                 /* Turn off all others here */
00076                 /* Only SCI for now */
00077                 SCI0CR2 &= SCICR2_RX_DISABLE;
00078                 SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00079                 /* SPI ? I2C ? SCI1 ? */
00080         }else{ /* If clearing all flags then enable RX on all interfaces */
00081                 /* Only SCI for now */
00082                 SCI0CR2 |= SCICR2_RX_ENABLE;
00083                 SCI0CR2 |= SCICR2_RX_ISR_ENABLE;
00084                 // TODO CAN0CTL1 |= CANCTL1_RX_ENABLE;
00085                 // TODO CAN0CTL1 |= CANCTL1_RX_ISR_ENABLE;
00086                 /* SPI ? I2C ? SCI1 ? */
00087         }
00088 }
00089 
00090 
00091 /* SCI0 ISR handles all interrupts for SCI0 by reading the flag registers and acting appropriately. */
00092 void SCI0ISR(void){
00093         /* Read the flags register */
00094         unsigned char flags = SCI0SR1;
00095         /* Note: Combined with reading or writing the data register this also clears the flags. */
00096 
00097         /* Start counting */
00098         unsigned short start = TCNT;
00099 
00100         /* If the RX interrupt is enabled check RX related flags */
00101         if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){
00102                 /* Grab the received byte from the register */
00103                 unsigned char rawByte = SCI0DRL;
00104 
00105                 PORTB |= BIT0;
00106 
00107                 /* Record error conditions always */
00108                 unsigned char resetOnError = 0;
00109                 /* If there is noise on the receive line record it */
00110                 if(flags & SCISR1_RX_NOISE){
00111                         Counters.serialNoiseErrorCounter++;
00112                         resetOnError++;
00113                 }/* If an overrun occurs record it */
00114                 if(flags & SCISR1_RX_OVERRUN){
00115                         Counters.serialOverrunErrorCounter++;
00116                         resetOnError++;
00117                 }/* If a framing error occurs record it */
00118                 if(flags & SCISR1_RX_FRAMING){
00119                         Counters.serialFramingErrorCounter++;
00120                         resetOnError++;
00121                 }/* If a parity error occurs record it */
00122                 if(flags & SCISR1_RX_PARITY){
00123                         Counters.serialParityErrorCounter++;
00124                         resetOnError++;
00125                 }
00126 
00127                 /* Drop out because of error flags      */
00128                 if(resetOnError){
00129                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00130                         PORTB |= BIT1;
00131                         return;
00132                 }
00133 
00134                 /* If there is data waiting to be received */
00135                 if(flags & SCISR1_RX_REGISTER_FULL){
00136                         PORTB |= BIT2;
00137                         /* Look for a start bresetReceiveStateyte to indicate a new packet */
00138                         if(rawByte == START_BYTE){
00139                                 PORTB |= BIT3;
00140                                 /* If another interface is using it (Note, clear flag, not normal) */
00141                                 if(RXBufferContentSourceID & COM_CLEAR_SCI0_INTERFACE_ID){
00142                                         /* Turn off our reception */
00143                                         SCI0CR2 &= SCICR2_RX_DISABLE;
00144                                         SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00145                                         PORTB |= BIT4;
00146                                 }else{
00147                                         PORTB |= BIT5;
00148                                         /* If we are using it */
00149                                         if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00150                                                 /* Increment the counter */
00151                                                 Counters.serialStartInsidePacketCounter++;
00152                                         }
00153                                         /* Reset to us using it unless someone else was */
00154                                         resetReceiveState(COM_SET_SCI0_INTERFACE_ID);
00155                                 }
00156                         }else if(RXPacketLengthReceived >= RX_BUFFER_SIZE){
00157                                 /* Buffer was full, record and reset */
00158                                 Counters.serialPacketOverLengthCounter++;
00159                                 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00160                                 PORTB |= BIT6;
00161                         }else if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00162                                 if(RXStateFlags & RX_SCI_ESCAPED_NEXT){
00163                                         PORTB |= BIT7;
00164                                         /* Clear escaped byte next flag, thanks Karsten! ((~ != !) == (! ~= ~)) == LOL */
00165                                         RXStateFlags &= RX_SCI_NOT_ESCAPED_NEXT;
00166 
00167                                         if(rawByte == ESCAPED_ESCAPE_BYTE){
00168                                                 /* Store and checksum escape byte */
00169                                                 receiveAndIncrement(ESCAPE_BYTE);
00170                                         }else if(rawByte == ESCAPED_START_BYTE){
00171                                                 /* Store and checksum start byte */
00172                                                 receiveAndIncrement(START_BYTE);
00173                                         }else if(rawByte == ESCAPED_STOP_BYTE){
00174                                                 /* Store and checksum stop byte */
00175                                                 receiveAndIncrement(STOP_BYTE);
00176                                         }else{
00177                                                 /* Otherwise reset and record as data is bad */
00178                                                 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00179                                                 Counters.serialEscapePairMismatchCounter++;
00180                                         }
00181                                 }else if(rawByte == ESCAPE_BYTE){
00182                                         PORTA |= BIT0;
00183                                         /* Set flag to indicate that the next byte should be un-escaped. */
00184                                         RXStateFlags |= RX_SCI_ESCAPED_NEXT;
00185                                 }else if(rawByte == STOP_BYTE){
00186                                         PORTA |= BIT1;
00187                                         /* Turn off reception */
00188                                         SCI0CR2 &= SCICR2_RX_DISABLE;
00189                                         SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00190 
00191                                         /* Bring the checksum back to where it should be */
00192                                         unsigned char RXReceivedChecksum = (unsigned char)*(RXBufferCurrentPosition - 1);
00193                                         RXCalculatedChecksum -= RXReceivedChecksum;
00194 
00195                                         /* Check that the checksum matches */
00196                                         if(RXCalculatedChecksum == RXReceivedChecksum){
00197                                                 /* If it's OK set process flag */
00198                                                 RXStateFlags |= RX_READY_TO_PROCESS;
00199                                                 PORTA |= BIT2;
00200                                         }else{
00201                                                 PORTA |= BIT3;
00202                                                 /* Otherwise reset the state and record it */
00203                                                 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00204                                                 Counters.serialChecksumMismatchCounter++;
00205                                         }
00206                                 }else{
00207                                         PORTA |= BIT4;
00208                                         /* If it isn't special process it! */
00209                                         receiveAndIncrement(rawByte);
00210                                 }
00211                         }else{
00212                                 /* Do nothing : drop the byte */
00213                                 PORTA |= BIT5;
00214                         }
00215                 }
00216         }
00217 
00218         /* If the TX interrupt is enabled check the register empty flag. */
00219         if((SCI0CR2 & SCICR2_TX_ISR_ENABLE) && (flags & SCISR1_TX_REGISTER_EMPTY)){
00220                 /* Get the byte to be sent from the buffer */
00221                 unsigned char rawValue = *TXBufferCurrentPositionSCI0;
00222 
00223                 if(TXPacketLengthToSendSCI0 > 0){
00224                         if(TXByteEscaped == 0){
00225                                 /* If the raw value needs to be escaped */
00226                                 if(rawValue == ESCAPE_BYTE){
00227                                         SCI0DRL = ESCAPE_BYTE;
00228                                         TXByteEscaped = ESCAPED_ESCAPE_BYTE;
00229                                 }else if(rawValue == START_BYTE){
00230                                         SCI0DRL = ESCAPE_BYTE;
00231                                         TXByteEscaped = ESCAPED_START_BYTE;
00232                                 }else if(rawValue == STOP_BYTE){
00233                                         SCI0DRL = ESCAPE_BYTE;
00234                                         TXByteEscaped = ESCAPED_STOP_BYTE;
00235                                 }else{ /* Otherwise just send it */
00236                                         sendAndIncrement(rawValue);
00237                                 }
00238                         }else{
00239                                 sendAndIncrement(TXByteEscaped);
00240                                 TXByteEscaped = 0;
00241                         }
00242                 }else{ /* Length is zero */
00243                         /* Turn off transmission interrupt */
00244                         SCI0CR2 &= SCICR2_TX_ISR_DISABLE;
00245                         /* Send the stop byte */
00246                         SCI0DRL = STOP_BYTE;
00247                         /* Clear the TX in progress flag */
00248                         TXBufferInUseFlags &= COM_CLEAR_SCI0_INTERFACE_ID;
00249                 }
00250         }
00251 
00252         /* Record how long the operation took */
00253         RuntimeVars.serialISRRuntime = TCNT - start;
00254 }

Generated on Mon Nov 10 21:18:50 2008 for freeems by  doxygen 1.5.2