| 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@