libraries / VirtualWire / VirtualWire.cppon commit Added link to project report (97a3ba0)
   1// VirtualWire.cpp
   2//
   3// Virtual Wire implementation for Arduino
   4// See the README file in this directory fdor documentation
   5// See also
   6// ASH Transceiver Software Designer's Guide of 2002.08.07
   7//   http://www.rfm.com/products/apnotes/tr_swg05.pdf
   8//
   9// Changes:
  10// 1.5 2008-05-25: fixed a bug that could prevent messages with certain
  11//  bytes sequences being received (false message start detected)
  12// 1.6 2011-09-10: Patch from David Bath to prevent unconditional reenabling of the receiver
  13//  at end of transmission.
  14//
  15// Author: Mike McCauley (mikem@airspayce.com)
  16// Copyright (C) 2008 Mike McCauley
  17// $Id: VirtualWire.cpp,v 1.9 2013/02/14 22:02:11 mikem Exp mikem $
  18
  19
  20#if defined(ARDUINO)
  21 #if (ARDUINO < 100)
  22  #include "WProgram.h"
  23 #endif
  24#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
  25 #include "legacymsp430.h"
  26 #include "Energia.h"
  27#else // error
  28 #error Platform not defined
  29#endif
  30
  31#include "VirtualWire.h"
  32#include <util/crc16.h>
  33
  34
  35static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN] 
  36     = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
  37
  38// Number of symbols in vw_tx_buf to be sent;
  39static uint8_t vw_tx_len = 0;
  40
  41// Index of the next symbol to send. Ranges from 0 to vw_tx_len
  42static uint8_t vw_tx_index = 0;
  43
  44// Bit number of next bit to send
  45static uint8_t vw_tx_bit = 0;
  46
  47// Sample number for the transmitter. Runs 0 to 7 during one bit interval
  48static uint8_t vw_tx_sample = 0;
  49
  50// Flag to indicated the transmitter is active
  51static volatile uint8_t vw_tx_enabled = 0;
  52
  53// Total number of messages sent
  54static uint16_t vw_tx_msg_count = 0;
  55
  56// The digital IO pin number of the press to talk, enables the transmitter hardware
  57static uint8_t vw_ptt_pin = 10;
  58static uint8_t vw_ptt_inverted = 0;
  59
  60// The digital IO pin number of the receiver data
  61static uint8_t vw_rx_pin = 11;
  62
  63// The digital IO pin number of the transmitter data
  64static uint8_t vw_tx_pin = 12;
  65
  66// Current receiver sample
  67static uint8_t vw_rx_sample = 0;
  68
  69// Last receiver sample
  70static uint8_t vw_rx_last_sample = 0;
  71
  72// PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over 
  73// VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time. 
  74// When the PLL is synchronised, bit transitions happen at about the
  75// 0 mark. 
  76static uint8_t vw_rx_pll_ramp = 0;
  77
  78// This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle
  79// the bit is declared a 0, else a 1
  80static uint8_t vw_rx_integrator = 0;
  81
  82// Flag indictate if we have seen the start symbol of a new message and are
  83// in the processes of reading and decoding it
  84static uint8_t vw_rx_active = 0;
  85
  86// Flag to indicate that a new message is available
  87static volatile uint8_t vw_rx_done = 0;
  88
  89// Flag to indicate the receiver PLL is to run
  90static uint8_t vw_rx_enabled = 0;
  91
  92// Last 12 bits received, so we can look for the start symbol
  93static uint16_t vw_rx_bits = 0;
  94
  95// How many bits of message we have received. Ranges from 0 to 12
  96static uint8_t vw_rx_bit_count = 0;
  97
  98// The incoming message buffer
  99static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN];
 100
 101// The incoming message expected length
 102static uint8_t vw_rx_count = 0;
 103
 104// The incoming message buffer length received so far
 105static volatile uint8_t vw_rx_len = 0;
 106
 107// Number of bad messages received and dropped due to bad lengths
 108static uint8_t vw_rx_bad = 0;
 109
 110// Number of good messages received
 111static uint8_t vw_rx_good = 0;
 112
 113// 4 bit to 6 bit symbol converter table
 114// Used to convert the high and low nybbles of the transmitted data
 115// into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s 
 116// with at most 3 consecutive identical bits
 117static uint8_t symbols[] =
 118{
 119    0xd,  0xe,  0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 
 120    0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
 121};
 122
 123// Cant really do this as a real C++ class, since we need to have 
 124// an ISR
 125extern "C"
 126{
 127
 128// Compute CRC over count bytes.
 129// This should only be ever called at user level, not interrupt level
 130uint16_t vw_crc(uint8_t *ptr, uint8_t count)
 131{
 132    uint16_t crc = 0xffff;
 133
 134    while (count-- > 0) 
 135        crc = _crc_ccitt_update(crc, *ptr++);
 136    return crc;
 137}
 138
 139// Convert a 6 bit encoded symbol into its 4 bit decoded equivalent
 140uint8_t vw_symbol_6to4(uint8_t symbol)
 141{
 142    uint8_t i;
 143    
 144    // Linear search :-( Could have a 64 byte reverse lookup table?
 145    for (i = 0; i < 16; i++)
 146        if (symbol == symbols[i]) return i;
 147    return 0; // Not found
 148}
 149
 150// Set the output pin number for transmitter data
 151void vw_set_tx_pin(uint8_t pin)
 152{
 153    vw_tx_pin = pin;
 154}
 155
 156// Set the pin number for input receiver data
 157void vw_set_rx_pin(uint8_t pin)
 158{
 159    vw_rx_pin = pin;
 160}
 161
 162// Set the output pin number for transmitter PTT enable
 163void vw_set_ptt_pin(uint8_t pin)
 164{
 165    vw_ptt_pin = pin;
 166}
 167
 168// Set the ptt pin inverted (low to transmit)
 169void vw_set_ptt_inverted(uint8_t inverted)
 170{
 171    vw_ptt_inverted = inverted;
 172}
 173
 174// Called 8 times per bit period
 175// Phase locked loop tries to synchronise with the transmitter so that bit 
 176// transitions occur at about the time vw_rx_pll_ramp is 0;
 177// Then the average is computed over each bit period to deduce the bit value
 178void vw_pll()
 179{
 180    // Integrate each sample
 181    if (vw_rx_sample)
 182        vw_rx_integrator++;
 183
 184    if (vw_rx_sample != vw_rx_last_sample)
 185    {
 186        // Transition, advance if ramp > 80, retard if < 80
 187        vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION) 
 188                           ? VW_RAMP_INC_RETARD 
 189                           : VW_RAMP_INC_ADVANCE);
 190        vw_rx_last_sample = vw_rx_sample;
 191    }
 192    else
 193    {
 194        // No transition
 195        // Advance ramp by standard 20 (== 160/8 samples)
 196        vw_rx_pll_ramp += VW_RAMP_INC;
 197    }
 198    if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN)
 199    {
 200        // Add this to the 12th bit of vw_rx_bits, LSB first
 201        // The last 12 bits are kept
 202        vw_rx_bits >>= 1;
 203
 204        // Check the integrator to see how many samples in this cycle were high.
 205        // If < 5 out of 8, then its declared a 0 bit, else a 1;
 206        if (vw_rx_integrator >= 5)
 207            vw_rx_bits |= 0x800;
 208
 209        vw_rx_pll_ramp -= VW_RX_RAMP_LEN;
 210        vw_rx_integrator = 0; // Clear the integral for the next cycle
 211
 212        if (vw_rx_active)
 213        {
 214            // We have the start symbol and now we are collecting message bits,
 215            // 6 per symbol, each which has to be decoded to 4 bits
 216            if (++vw_rx_bit_count >= 12)
 217            {
 218                // Have 12 bits of encoded message == 1 byte encoded
 219                // Decode as 2 lots of 6 bits into 2 lots of 4 bits
 220                // The 6 lsbits are the high nybble
 221                uint8_t this_byte = 
 222                    (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4 
 223                    | vw_symbol_6to4(vw_rx_bits >> 6);
 224
 225                // The first decoded byte is the byte count of the following message
 226                // the count includes the byte count and the 2 trailing FCS bytes
 227                // REVISIT: may also include the ACK flag at 0x40
 228                if (vw_rx_len == 0)
 229                {
 230                    // The first byte is the byte count
 231                    // Check it for sensibility. It cant be less than 4, since it
 232                    // includes the bytes count itself and the 2 byte FCS
 233                    vw_rx_count = this_byte;
 234                    if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN)
 235                    {
 236                        // Stupid message length, drop the whole thing
 237                        vw_rx_active = false;
 238                        vw_rx_bad++;
 239                        return;
 240                    }
 241                }
 242                vw_rx_buf[vw_rx_len++] = this_byte;
 243
 244                if (vw_rx_len >= vw_rx_count)
 245                {
 246                    // Got all the bytes now
 247                    vw_rx_active = false;
 248                    vw_rx_good++;
 249                    vw_rx_done = true; // Better come get it before the next one starts
 250                }
 251                vw_rx_bit_count = 0;
 252            }
 253        }
 254        // Not in a message, see if we have a start symbol
 255        else if (vw_rx_bits == 0xb38)
 256        {
 257            // Have start symbol, start collecting message
 258            vw_rx_active = true;
 259            vw_rx_bit_count = 0;
 260            vw_rx_len = 0;
 261            vw_rx_done = false; // Too bad if you missed the last message
 262        }
 263    }
 264}
 265
 266// Common function for setting timer ticks @ prescaler values for speed
 267// Returns prescaler index into {0, 1, 8, 64, 256, 1024} array
 268// and sets nticks to compare-match value if lower than max_ticks
 269// returns 0 & nticks = 0 on fault
 270static uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
 271{
 272    // Clock divider (prescaler) values - 0/3333: error flag
 273    uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
 274    uint8_t prescaler=0; // index into array & return bit value
 275    unsigned long ulticks; // calculate by ntick overflow
 276
 277    // Div-by-zero protection
 278    if (speed == 0)
 279    {
 280        // signal fault
 281        *nticks = 0;
 282        return 0;
 283    }
 284
 285    // test increasing prescaler (divisor), decreasing ulticks until no overflow
 286    for (prescaler=1; prescaler < 7; prescaler += 1)
 287    {
 288        // Amount of time per CPU clock tick (in seconds)
 289        float clock_time = (1.0 / (float(F_CPU) / float(prescalers[prescaler])));
 290        // Fraction of second needed to xmit one bit
 291        float bit_time = ((1.0 / float(speed)) / 8.0);
 292        // number of prescaled ticks needed to handle bit time @ speed
 293        ulticks = long(bit_time / clock_time);
 294        // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
 295        if ((ulticks > 1) && (ulticks < max_ticks))
 296        {
 297            break; // found prescaler
 298        }
 299        // Won't fit, check with next prescaler value
 300    }
 301
 302    // Check for error
 303    if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
 304    {
 305        // signal fault
 306        *nticks = 0;
 307        return 0;
 308    }
 309
 310    *nticks = ulticks;
 311    return prescaler;
 312}
 313
 314#if defined(__arm__) && defined(CORE_TEENSY)
 315  // This allows the AVR interrupt code below to be run from an
 316  // IntervalTimer object.  It must be above vw_setup(), so the
 317  // the TIMER1_COMPA_vect function name is defined.
 318  #ifdef SIGNAL
 319  #undef SIGNAL
 320  #endif
 321  #define SIGNAL(f) void f(void)
 322  #ifdef TIMER1_COMPA_vect
 323  #undef TIMER1_COMPA_vect
 324  #endif
 325  void TIMER1_COMPA_vect(void);
 326#endif
 327
 328
 329// Speed is in bits per sec RF rate
 330#if defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
 331void vw_setup(uint16_t speed)
 332{
 333        // Calculate the counter overflow count based on the required bit speed
 334        // and CPU clock rate
 335        uint16_t ocr1a = (F_CPU / 8UL) / speed;
 336                
 337        // This code is for Energia/MSP430
 338        TA0CCR0 = ocr1a;                                // Ticks for 62,5 us
 339        TA0CTL = TASSEL_2 + MC_1;       // SMCLK, up mode
 340        TA0CCTL0 |= CCIE;               // CCR0 interrupt enabled
 341                
 342        // Set up digital IO pins
 343        pinMode(vw_tx_pin, OUTPUT);
 344        pinMode(vw_rx_pin, INPUT);
 345        pinMode(vw_ptt_pin, OUTPUT);
 346        digitalWrite(vw_ptt_pin, vw_ptt_inverted);
 347}       
 348
 349#elif defined (ARDUINO) // Arduino specific
 350void vw_setup(uint16_t speed)
 351{
 352    uint16_t nticks; // number of prescaled ticks needed
 353    uint8_t prescaler; // Bit values for CS0[2:0]
 354
 355#ifdef __AVR_ATtiny85__
 356    // figure out prescaler value and counter match value
 357    prescaler = _timer_calc(speed, (uint8_t)-1, &nticks);
 358    if (!prescaler)
 359    {
 360        return; // fault
 361    }
 362
 363    TCCR0A = 0;
 364    TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected
 365
 366    // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
 367    TCCR0B = 0;
 368    TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)
 369
 370    // Number of ticks to count before firing interrupt
 371    OCR0A = uint8_t(nticks);
 372
 373    // Set mask to fire interrupt when OCF0A bit is set in TIFR0
 374    TIMSK |= _BV(OCIE0A);
 375
 376#elif defined(__arm__) && defined(CORE_TEENSY)
 377    // on Teensy 3.0 (32 bit ARM), use an interval timer
 378    IntervalTimer *t = new IntervalTimer();
 379    t->begin(TIMER1_COMPA_vect, 125000.0 / (float)(speed));
 380
 381#else // ARDUINO
 382    // This is the path for most Arduinos
 383    // figure out prescaler value and counter match value
 384    prescaler = _timer_calc(speed, (uint16_t)-1, &nticks);
 385    if (!prescaler)
 386    {
 387        return; // fault
 388    }
 389
 390    TCCR1A = 0; // Output Compare pins disconnected
 391    TCCR1B = _BV(WGM12); // Turn on CTC mode
 392
 393    // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
 394    TCCR1B |= prescaler;
 395
 396    // Caution: special procedures for setting 16 bit regs
 397    // is handled by the compiler
 398    OCR1A = nticks;
 399    // Enable interrupt
 400#ifdef TIMSK1
 401    // atmega168
 402    TIMSK1 |= _BV(OCIE1A);
 403#else
 404    // others
 405    TIMSK |= _BV(OCIE1A);
 406#endif // TIMSK1
 407
 408#endif // __AVR_ATtiny85__
 409
 410    // Set up digital IO pins
 411    pinMode(vw_tx_pin, OUTPUT);
 412    pinMode(vw_rx_pin, INPUT);
 413    pinMode(vw_ptt_pin, OUTPUT);
 414    digitalWrite(vw_ptt_pin, vw_ptt_inverted);
 415}
 416
 417#endif // ARDUINO
 418
 419// Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is
 420// set to the total number of symbols to send
 421void vw_tx_start()
 422{
 423    vw_tx_index = 0;
 424    vw_tx_bit = 0;
 425    vw_tx_sample = 0;
 426
 427    // Enable the transmitter hardware
 428    digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted);
 429
 430    // Next tick interrupt will send the first bit
 431    vw_tx_enabled = true;
 432}
 433
 434// Stop the transmitter, call when all bits are sent
 435void vw_tx_stop()
 436{
 437    // Disable the transmitter hardware
 438    digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted);
 439    digitalWrite(vw_tx_pin, false);
 440
 441    // No more ticks for the transmitter
 442    vw_tx_enabled = false;
 443}
 444
 445// Enable the receiver. When a message becomes available, vw_rx_done flag
 446// is set, and vw_wait_rx() will return.
 447void vw_rx_start()
 448{
 449    if (!vw_rx_enabled)
 450    {
 451        vw_rx_enabled = true;
 452        vw_rx_active = false; // Never restart a partial message
 453    }
 454}
 455
 456// Disable the receiver
 457void vw_rx_stop()
 458{
 459    vw_rx_enabled = false;
 460}
 461
 462// Return true if the transmitter is active
 463uint8_t vx_tx_active()
 464{
 465    return vw_tx_enabled;
 466}
 467
 468// Wait for the transmitter to become available
 469// Busy-wait loop until the ISR says the message has been sent
 470void vw_wait_tx()
 471{
 472    while (vw_tx_enabled)
 473        ;
 474}
 475
 476// Wait for the receiver to get a message
 477// Busy-wait loop until the ISR says a message is available
 478// can then call vw_get_message()
 479void vw_wait_rx()
 480{
 481    while (!vw_rx_done)
 482        ;
 483}
 484
 485// Wait at most max milliseconds for the receiver to receive a message
 486// Return the truth of whether there is a message
 487uint8_t vw_wait_rx_max(unsigned long milliseconds)
 488{
 489    unsigned long start = millis();
 490
 491    while (!vw_rx_done && ((millis() - start) < milliseconds))
 492        ;
 493    return vw_rx_done;
 494}
 495
 496// Wait until transmitter is available and encode and queue the message
 497// into vw_tx_buf
 498// The message is raw bytes, with no packet structure imposed
 499// It is transmitted preceded a byte count and followed by 2 FCS bytes
 500uint8_t vw_send(uint8_t* buf, uint8_t len)
 501{
 502    uint8_t i;
 503    uint8_t index = 0;
 504    uint16_t crc = 0xffff;
 505    uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area
 506    uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes
 507
 508    if (len > VW_MAX_PAYLOAD)
 509        return false;
 510
 511    // Wait for transmitter to become available
 512    vw_wait_tx();
 513
 514    // Encode the message length
 515    crc = _crc_ccitt_update(crc, count);
 516    p[index++] = symbols[count >> 4];
 517    p[index++] = symbols[count & 0xf];
 518
 519    // Encode the message into 6 bit symbols. Each byte is converted into 
 520    // 2 6-bit symbols, high nybble first, low nybble second
 521    for (i = 0; i < len; i++)
 522    {
 523        crc = _crc_ccitt_update(crc, buf[i]);
 524        p[index++] = symbols[buf[i] >> 4];
 525        p[index++] = symbols[buf[i] & 0xf];
 526    }
 527
 528    // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
 529    // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
 530    // VW sends FCS as low byte then hi byte
 531    crc = ~crc;
 532    p[index++] = symbols[(crc >> 4)  & 0xf];
 533    p[index++] = symbols[crc & 0xf];
 534    p[index++] = symbols[(crc >> 12) & 0xf];
 535    p[index++] = symbols[(crc >> 8)  & 0xf];
 536
 537    // Total number of 6-bit symbols to send
 538    vw_tx_len = index + VW_HEADER_LEN;
 539
 540    // Start the low level interrupt handler sending symbols
 541    vw_tx_start();
 542
 543    return true;
 544}
 545
 546// Return true if there is a message available
 547uint8_t vw_have_message()
 548{
 549    return vw_rx_done;
 550}
 551
 552// Get the last message received (without byte count or FCS)
 553// Copy at most *len bytes, set *len to the actual number copied
 554// Return true if there is a message and the FCS is OK
 555uint8_t vw_get_message(uint8_t* buf, uint8_t* len)
 556{
 557    uint8_t rxlen;
 558    
 559    // Message available?
 560    if (!vw_rx_done)
 561        return false;
 562    
 563    // Wait until vw_rx_done is set before reading vw_rx_len
 564    // then remove bytecount and FCS
 565    rxlen = vw_rx_len - 3;
 566    
 567    // Copy message (good or bad)
 568    if (*len > rxlen)
 569        *len = rxlen;
 570    memcpy(buf, vw_rx_buf + 1, *len);
 571    
 572    vw_rx_done = false; // OK, got that message thanks
 573    
 574    // Check the FCS, return goodness
 575    return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK?
 576}
 577
 578// This is the interrupt service routine called when timer1 overflows
 579// Its job is to output the next bit from the transmitter (every 8 calls)
 580// and to call the PLL code if the receiver is enabled
 581//ISR(SIG_OUTPUT_COMPARE1A)
 582#if defined (ARDUINO) // Arduino specific
 583
 584#ifdef __AVR_ATtiny85__
 585SIGNAL(TIM0_COMPA_vect)
 586#else // Assume Arduino Uno (328p or similar)
 587
 588SIGNAL(TIMER1_COMPA_vect)
 589#endif // __AVR_ATtiny85__
 590
 591{
 592    if (vw_rx_enabled && !vw_tx_enabled)
 593        vw_rx_sample = digitalRead(vw_rx_pin);
 594    
 595    // Do transmitter stuff first to reduce transmitter bit jitter due 
 596    // to variable receiver processing
 597    if (vw_tx_enabled && vw_tx_sample++ == 0)
 598    {
 599        // Send next bit
 600        // Symbols are sent LSB first
 601        // Finished sending the whole message? (after waiting one bit period 
 602        // since the last bit)
 603        if (vw_tx_index >= vw_tx_len)
 604        {
 605            vw_tx_stop();
 606            vw_tx_msg_count++;
 607        }
 608        else
 609        {
 610            digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
 611            if (vw_tx_bit >= 6)
 612            {
 613                vw_tx_bit = 0;
 614                vw_tx_index++;
 615            }
 616        }
 617    }
 618    if (vw_tx_sample > 7)
 619        vw_tx_sample = 0;
 620    
 621    if (vw_rx_enabled && !vw_tx_enabled)
 622        vw_pll();
 623}
 624#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
 625void vw_Int_Handler()
 626{
 627    if (vw_rx_enabled && !vw_tx_enabled)
 628        vw_rx_sample = digitalRead(vw_rx_pin);
 629    
 630    // Do transmitter stuff first to reduce transmitter bit jitter due 
 631    // to variable receiver processing
 632    if (vw_tx_enabled && vw_tx_sample++ == 0)
 633    {
 634        // Send next bit
 635        // Symbols are sent LSB first
 636        // Finished sending the whole message? (after waiting one bit period 
 637        // since the last bit)
 638        if (vw_tx_index >= vw_tx_len)
 639        {
 640            vw_tx_stop();
 641            vw_tx_msg_count++;
 642        }
 643        else
 644        {
 645            digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
 646            if (vw_tx_bit >= 6)
 647            {
 648                vw_tx_bit = 0;
 649                vw_tx_index++;
 650            }
 651        }
 652    }
 653    if (vw_tx_sample > 7)
 654        vw_tx_sample = 0;
 655    
 656    if (vw_rx_enabled && !vw_tx_enabled)
 657        vw_pll();
 658}
 659
 660interrupt(TIMER0_A0_VECTOR) Timer_A_int(void) 
 661{
 662    vw_Int_Handler();
 663};
 664
 665#endif
 666
 667
 668}