Remote Access Control


comms.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
00048 #include "comms.h"
00049 #include "common.h"
00050 #include "config.h"
00051 
00052 
00053 
00055 static const byte * volatile nextUSIByte;
00057 static volatile byte USIBytesLeft;
00058 
00059 
00060 
00061 #ifdef USE_UART
00062 
00064 static byte uartPartTwo;
00065 
00067 #pragma vector = USI_OVF_vect
00068 __interrupt void USIOverflowHandler(void)
00069 {
00070         if( uartPartTwo != 0x00 ) { // Part two needs to be transmitted?
00071                 USIDR = (USIDR&0xe0) | uartPartTwo; // OR it into USI Data register.
00072                 USISR = (1<<USIOIF) | (16-6); // Seed timer to overflow in 6 bit shifts.
00073                 uartPartTwo = 0x00; // Clear part two, indicating that it has been sent.
00074         } else {
00075                 --USIBytesLeft; // One less byte left to transmit.
00076 
00077                 if( USIBytesLeft > 0 ) {
00078                         byte tempByte = *nextUSIByte++;
00079                         // Put next byte in output register.
00080                         USIDR = 0x80 |
00081                                 ((tempByte<<5)&(1<<5)) |
00082                                 ((tempByte<<3)&(1<<4)) |
00083                                 ((tempByte<<1)&(1<<3)) |
00084                                 ((tempByte>>1)&(1<<2)) |
00085                                 ((tempByte>>3)&(1<<1)) |
00086                                 ((tempByte>>5)&(1<<0));
00087                         // Prepare part two for next interrupt.
00088                         uartPartTwo = 0x07 |
00089                                 ((tempByte>>2)&(1<<4)) |
00090                                 ((tempByte>>4)&(1<<3));
00091 
00092                         // Clear overflow flag and seed USI timer
00093                         // to overflow in 5 bit shifts.
00094                         USISR = (1<<USIOIF) | (16-5);
00095 
00096                 } else {
00097                         // Stop timer providing clock to USI module.
00098                         TCCR0B = 0x00;
00099                         // Clear USI overflow flag.
00100                         USISR = (1<<USIOIF);
00101                 }
00102         }
00103 }
00104 
00105 
00106 
00107 void startTransmission( const byte * buffer, byte byteCount )
00108 {
00109         // Prepare control variables.
00110         byte tempByte = *buffer++;
00111         nextUSIByte = buffer;
00112         USIBytesLeft = byteCount;
00113 
00114         USIDR = 0x80 |
00115                 ((tempByte<<5)&(1<<5)) |
00116                 ((tempByte<<3)&(1<<4)) |
00117                 ((tempByte<<1)&(1<<3)) |
00118                 ((tempByte>>1)&(1<<2)) |
00119                 ((tempByte>>3)&(1<<1)) |
00120                 ((tempByte>>5)&(1<<0));
00121         uartPartTwo = 0x07 |
00122                 ((tempByte>>2)&(1<<4)) |
00123                 ((tempByte>>4)&(1<<3));
00124 
00125         // Clear overflow flag and seed USI timer
00126         // to overflow in 5 bit shifts.
00127         USISR = (1<<USIOIF) | (16-5);
00128 
00129         // Start USI in Three-wire mode clocked by
00130         // Timer/Counter0 Compare Match A. Overflow interrupt enabled.
00131         USICR = (1<<USIOIE) |
00132                 (0<<USIWM1) | (1<<USIWM0) |   // Three-wire mode, data output on PB1.
00133                 (0<<USICS1) | (1<<USICS0);
00134 
00135         // Reset Timer/Counter0 value.
00136         TCNT0 = 0x00;
00137         // Set data rate to 19200 bps (ie. 9600 bps with Manchester).
00138         OCR0A = 51; // approx. (8MHz/8/19200bps)-1, ref. CTC Mode in datasheet.
00139         TCCR0A = (1<<WGM01);
00140         // Start Timer/Counter0 with CPU clock / 8.
00141         TCCR0B = (0<<CS02) | (1<<CS01) | (0<<CS00);
00142 }
00143 
00144 
00145 void continueTransmission( const byte * buffer, byte byteCount )
00146 {
00147         startTransmission( buffer, byteCount );
00148 }
00149 
00150 
00151 #else
00152 
00153 
00154 
00156 static byte manchesterPartTwo;
00158 static byte manchesterPartThree;
00159 
00161 static const byte __flash manchesterNibble[ 16 ] = {
00162 #ifndef INVERTED_MANCHESTER
00163         0x55, // 01 01 01 01
00164         0x56, // 01 01 01 10
00165         0x59, // 01 01 10 01
00166         0x5a, // 01 01 10 10
00167 
00168         0x65, // 01 10 01 01
00169         0x66, // 01 10 01 10
00170         0x69, // 01 10 10 01
00171         0x6a, // 01 10 10 10
00172 
00173         0x95, // 10 01 01 01
00174         0x96, // 10 01 01 10
00175         0x99, // 10 01 10 01
00176         0x9a, // 10 01 10 10
00177 
00178         0xa5, // 10 10 01 01
00179         0xa6, // 10 10 01 10
00180         0xa9, // 10 10 10 01
00181         0xaa  // 10 10 10 10
00182 #else
00183         0xaa, // 10 10 10 10
00184         0xa9, // 10 10 10 01
00185         0xa6, // 10 10 01 10
00186         0xa5, // 10 10 01 01
00187 
00188         0x9a, // 10 01 10 10
00189         0x99, // 10 01 10 01
00190         0x96, // 10 01 01 10
00191         0x95, // 10 01 01 01
00192 
00193         0x6a, // 01 10 10 10
00194         0x69, // 01 10 10 01
00195         0x66, // 01 10 01 10
00196         0x65, // 01 10 01 01
00197 
00198         0x5a, // 01 01 10 10
00199         0x59, // 01 01 10 01
00200         0x56, // 01 01 01 10
00201         0x55  // 01 01 01 01
00202 #endif
00203 };
00204 
00205 
00206 
00208 #pragma vector = USI_OVF_vect
00209 __interrupt void USIOverflowHandler(void)
00210 {
00211         // 'manchesterPartTwo' is non-zero if part two has not been sent.
00212         if( manchesterPartTwo != 0x00 ) {
00213                 USISR = (1<<USIOIF) | (16-7);
00214                 USIDR = manchesterPartTwo;
00215                 manchesterPartTwo = 0x00;
00216 
00217                 // 'manchesterPartThree' is non-zero if part three has not been sent.
00218         } else if( manchesterPartThree != 0x00 ) {
00219                 USISR = (1<<USIOIF) | (16-2);
00220                 USIDR = manchesterPartThree;
00221                 manchesterPartThree = 0x00;
00222 
00223                 // If part two and three are zero, it's time to prepare next byte.
00224         } else {
00225                 // Clear overflow flag and seed USI counter.
00226                 // to overflow in 7 bit shifts. It is important to
00227                 // seed the timer this early, so that the computations
00228                 // below does not affect the transmission timing.
00229                 USISR = (1<<USIOIF) | (16-7);
00230 
00231                 --USIBytesLeft; // One less byte left to transmit.
00232 
00233                 // If bytes left, prepare for sending the next.
00234                 if( USIBytesLeft > 0 ) {
00235                         byte currentByte = *nextUSIByte++;
00236                         byte manchesterByte1;
00237                         byte manchesterByte2;
00238 
00239                         // Prepare Manchester pattern.
00240                         manchesterByte1 = manchesterNibble[ currentByte >> 4 ];
00241                         manchesterByte2 = manchesterNibble[ currentByte & 0x0f ];
00242 
00243                         // Put bit 0-6 of pattern at the end of USI data register.
00244                         USIDR = USIDR & 0x80 | (manchesterByte1 >> 1);
00245 
00246                         // Prepare part two of pattern, ie. bits 6-13.
00247                         manchesterPartTwo = (manchesterByte1 << 6) | (manchesterByte2 >> 2);
00248 
00249                         // Prepare part three of pattern, ie. bits 13-15 and 5 dummy zero bits.
00250                         manchesterPartThree = (manchesterByte2 << 5);
00251                 } else {
00252                         // No bytes left => turn off further interrupts, in case
00253                         // the call to stopTransmission is delayed.
00254                         // The USI module will continue transmittion zeros.
00255                         // We cannot stop the whole USI module, since the user
00256                         // might want to continue transmitting. In that case, the
00257                         // user must call continueTransmission as soon as possible
00258                         // after returning from waitForTransmission.
00259                         USICR &= ~(1<<USIOIE); // Disable interrupts.
00260                 }
00261         }
00262 }
00263 
00264 
00265 
00266 void startTransmission( const byte * buffer, byte byteCount )
00267 {
00268         // Prepare control variables.
00269         byte currentByte = *buffer++;
00270         nextUSIByte = buffer;
00271         USIBytesLeft = byteCount;
00272 
00273         // Prepare Manchester pattern.
00274         byte manchesterByte1 = manchesterNibble[ currentByte >> 4 ];
00275         byte manchesterByte2 = manchesterNibble[ currentByte & 0x0f ];
00276 
00277         // Put idle bit value and bit 0-6 of pattern in USI data register.
00278         // This is the first part of the pattern. The output pin changes immediately.
00279         USIDR = 0x80 | (manchesterByte1 >> 1);
00280 
00281         // Prepare part two of pattern, ie. bits 6-13.
00282         manchesterPartTwo = (manchesterByte1 << 6) | (manchesterByte2 >> 2);
00283 
00284         // Prepare part three of pattern, ie. bits 13-15 and 5 dummy zero bits.
00285         manchesterPartThree = (manchesterByte2 << 5);
00286 
00287         // Clear overflow flag and seed USI timer
00288         // to overflow in 7 bit shifts, so that last bit of first part of pattern is left.
00289         USISR = (1<<USIOIF) | (16-7);
00290 
00291         // Start USI in Three-wire mode clocked by
00292         // Timer/Counter0 Compare Match A. Overflow interrupt enabled.
00293   #ifdef ASK
00294         USICR = (1<<USIOIE) |
00295                 (0<<USIWM1) | (1<<USIWM0) |   // Three-wire mode, data output on PB1.
00296                 (0<<USICS1) | (1<<USICS0);
00297   #endif
00298   #ifdef FSK
00299         USICR = (1<<USIOIE) |
00300                 (1<<USIWM1) | (0<<USIWM0) |   // Two-wire mode, data output on PB0 (open collector).
00301                 (0<<USICS1) | (1<<USICS0);
00302         DDRB |= (1<<PB0); // Enable data line output open collector driver.
00303         PORTB |= ((1<<PB1) | (1<<PB0)); // Turn on carrier wave and give data line to USI module.
00304   #endif
00305 
00306   #ifdef BPS_19200
00307         // Set data rate to 19200 bps (ie. 9600 bps with Manchester).
00308         TCNT0 = 0x00;
00309         OCR0A = 51; // approx. (8MHz/8/19200bps)-1, ref. CTC Mode in datasheet.
00310         TCCR0A = (1<<WGM01); // Clear on Compare Match.
00311         TCCR0B = (0<<CS02) | (1<<CS01) | (0<<CS00); // Prescaler factor 8.
00312   #endif
00313   #ifdef BPS_9600
00314         // Set data rate to 9600 bps (ie. 4800 bps with Manchester).
00315         TCNT0 = 0x00;
00316         OCR0A = 103; // approx. (8MHz/8/9600bps)-1, ref. CTC Mode in datasheet.
00317         TCCR0A = (1<<WGM01); // Clear on Compare Match.
00318         TCCR0B = (0<<CS02) | (1<<CS01) | (0<<CS00); // Prescaler factor 8.
00319   #endif
00320   #ifdef BPS_4800
00321         // Set data rate to 4800 bps (ie. 2400 bps with Manchester).
00322         TCNT0 = 0x00;
00323         OCR0A = 25; // approx. (8MHz/64/2400bps)-1, ref. CTC Mode in datasheet.
00324         TCCR0A = (1<<WGM01); // Clear on Compare Match.
00325         TCCR0B = (0<<CS02) | (1<<CS01) | (1<<CS00); // Prescaler factor 64.
00326   #endif
00327   #ifdef BPS_2400
00328         // Set data rate to 2400 bps (ie. 1200 bps with Manchester).
00329         TCNT0 = 0x00;
00330         OCR0A = 51; // approx. (8MHz/64/2400bps)-1, ref. CTC Mode in datasheet.
00331         TCCR0A = (1<<WGM01); // Clear on Compare Match.
00332         TCCR0B = (0<<CS02) | (1<<CS01) | (1<<CS00); // Prescaler factor 64.
00333   #endif
00334 }
00335 
00336 
00337 
00338 void continueTransmission( const byte * buffer, byte byteCount )
00339 {
00340         // Prepare control variables.
00341         byte currentByte = *buffer++;
00342         nextUSIByte = buffer;
00343         USIBytesLeft = byteCount;
00344 
00345         // Prepare Manchester pattern.
00346         byte manchesterByte1 = manchesterNibble[ currentByte >> 4 ];
00347         byte manchesterByte2 = manchesterNibble[ currentByte & 0x0f ];
00348 
00349         // Put bit 0-6 of pattern at the end of USI data register.
00350         USIDR = USIDR & 0x80 | (manchesterByte1 >> 1);
00351 
00352         // Prepare part two of pattern, ie. bits 6-13.
00353         manchesterPartTwo = (manchesterByte1 << 6) | (manchesterByte2 >> 2);
00354 
00355         // Prepare part three of pattern, ie. bits 13-15 and 5 dummy zero bits.
00356         manchesterPartThree = (manchesterByte2 << 5);
00357 
00358         // Enable USI interrupts again.
00359         USICR |= (1<<USIOIE);
00360 }
00361 
00362 
00363 
00364 #endif // #ifdef USE_UART
00365 
00366 
00367 
00368 void stopTransmission()
00369 {
00370         USICR = 0x00;
00371   #ifdef FSK
00372         PORTB &= ~((1<<PB1) | (1<<PB0)); // Turn off carrier wave and release data line.
00373         DDRB &= ~(1<<PB0); // Disable data line output open collector driver.
00374   #endif
00375 }
00376 
00377 
00378 
00379 void waitForTransmission()
00380 {
00381         // Enter Idle sleep mode while waiting for transmission to finish.
00382         MCUCR = (1<<SE) | (0<<SM1) | (0<<SM0);
00383         while( USIBytesLeft ) { __sleep(); }
00384 }
00385 
@DOC_TITLE@
Generated on Fri Aug 8 11:03:16 2008 for AVR411 Secure Rolling Code Algorithm (Transmitter) by doxygen 1.4.7