libraries / VirtualWire / VirtualWire.cppon commit Added final version of code (649c546)
   1// VirtualWire.cpp
   2//
   3// Virtual Wire implementation for Arduino
   4// See the README file in this directory fdor documentation
   5//
   6// Changes:
   7// 2008-05-25: fixed a bug that could prevent messages with certain
   8//  bytes sequences being received (false message start detected)
   9//
  10// Author: Mike McCauley (mikem@open.com.au)
  11// Copyright (C) 2008 Mike McCauley
  12// $Id: VirtualWire.cpp,v 1.4 2009/03/31 20:49:41 mikem Exp mikem $
  13
  14#include "WProgram.h"
  15#include "VirtualWire.h"
  16#include <util/crc16.h>
  17
  18static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN] 
  19     = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
  20
  21// Number of symbols in vw_tx_buf to be sent;
  22static uint8_t vw_tx_len = 0;
  23
  24// Index of the next symbol to send. Ranges from 0 to vw_tx_len
  25static uint8_t vw_tx_index = 0;
  26
  27// Bit number of next bit to send
  28static uint8_t vw_tx_bit = 0;
  29
  30// Sample number for the transmitter. Runs 0 to 7 during one bit interval
  31static uint8_t vw_tx_sample = 0;
  32
  33// Flag to indicated the transmitter is active
  34static volatile uint8_t vw_tx_enabled = 0;
  35
  36// Total number of messages sent
  37static uint16_t vw_tx_msg_count = 0;
  38
  39// The digital IO pin number of the press to talk, enables the transmitter hardware
  40static uint8_t vw_ptt_pin = 10;
  41static uint8_t vw_ptt_inverted = 0;
  42
  43// The digital IO pin number of the receiver data
  44static uint8_t vw_rx_pin = 11;
  45
  46// The digital IO pin number of the transmitter data
  47static uint8_t vw_tx_pin = 12;
  48
  49// Current receiver sample
  50static uint8_t vw_rx_sample = 0;
  51
  52// Last receiver sample
  53static uint8_t vw_rx_last_sample = 0;
  54
  55// PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over 
  56// VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time. 
  57// When the PLL is synchronised, bit transitions happen at about the
  58// 0 mark. 
  59static uint8_t vw_rx_pll_ramp = 0;
  60
  61// This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle
  62// the bit is declared a 0, else a 1
  63static uint8_t vw_rx_integrator = 0;
  64
  65// Flag indictate if we have seen the start symbol of a new message and are
  66// in the processes of reading and decoding it
  67static uint8_t vw_rx_active = 0;
  68
  69// Flag to indicate that a new message is available
  70static volatile uint8_t vw_rx_done = 0;
  71
  72// Flag to indicate the receiver PLL is to run
  73static uint8_t vw_rx_enabled = 0;
  74
  75// Last 12 bits received, so we can look for the start symbol
  76static uint16_t vw_rx_bits = 0;
  77
  78// How many bits of message we have received. Ranges from 0 to 12
  79static uint8_t vw_rx_bit_count = 0;
  80
  81// The incoming message buffer
  82static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN];
  83
  84// The incoming message expected length
  85static uint8_t vw_rx_count = 0;
  86
  87// The incoming message buffer length received so far
  88static volatile uint8_t vw_rx_len = 0;
  89
  90// Number of bad messages received and dropped due to bad lengths
  91static uint8_t vw_rx_bad = 0;
  92
  93// Number of good messages received
  94static uint8_t vw_rx_good = 0;
  95
  96// 4 bit to 6 bit symbol converter table
  97// Used to convert the high and low nybbles of the transmitted data
  98// into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s 
  99// with at most 2 consecutive identical bits
 100static uint8_t symbols[] =
 101{
 102    0xd,  0xe,  0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 
 103    0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
 104};
 105
 106// Cant really do this as a real C++ class, since we need to have 
 107// an ISR
 108extern "C"
 109{
 110
 111// Compute CRC over count bytes.
 112// This should only be ever called at user level, not interrupt level
 113uint16_t vw_crc(uint8_t *ptr, uint8_t count)
 114{
 115    uint16_t crc = 0xffff;
 116
 117    while (count-- > 0) 
 118        crc = _crc_ccitt_update(crc, *ptr++);
 119    return crc;
 120}
 121
 122// Convert a 6 bit encoded symbol into its 4 bit decoded equivalent
 123uint8_t vw_symbol_6to4(uint8_t symbol)
 124{
 125    uint8_t i;
 126    
 127    // Linear search :-( Could have a 64 byte reverse lookup table?
 128    for (i = 0; i < 16; i++)
 129        if (symbol == symbols[i]) return i;
 130    return 0; // Not found
 131}
 132
 133// Set the output pin number for transmitter data
 134void vw_set_tx_pin(uint8_t pin)
 135{
 136    vw_tx_pin = pin;
 137}
 138
 139// Set the pin number for input receiver data
 140void vw_set_rx_pin(uint8_t pin)
 141{
 142    vw_rx_pin = pin;
 143}
 144
 145// Set the output pin number for transmitter PTT enable
 146void vw_set_ptt_pin(uint8_t pin)
 147{
 148    vw_ptt_pin = pin;
 149}
 150
 151// Set the ptt pin inverted (low to transmit)
 152void vw_set_ptt_inverted(uint8_t inverted)
 153{
 154    vw_ptt_inverted = inverted;
 155}
 156
 157// Called 8 times per bit period
 158// Phase locked loop tries to synchronise with the transmitter so that bit 
 159// transitions occur at about the time vw_rx_pll_ramp is 0;
 160// Then the average is computed over each bit period to deduce the bit value
 161void vw_pll()
 162{
 163    // Integrate each sample
 164    if (vw_rx_sample)
 165        vw_rx_integrator++;
 166
 167    if (vw_rx_sample != vw_rx_last_sample)
 168    {
 169        // Transition, advance if ramp > 80, retard if < 80
 170        vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION) 
 171                           ? VW_RAMP_INC_RETARD 
 172                           : VW_RAMP_INC_ADVANCE);
 173        vw_rx_last_sample = vw_rx_sample;
 174    }
 175    else
 176    {
 177        // No transition
 178        // Advance ramp by standard 20 (== 160/8 samples)
 179        vw_rx_pll_ramp += VW_RAMP_INC;
 180    }
 181    if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN)
 182    {
 183        // Add this to the 12th bit of vw_rx_bits, LSB first
 184        // The last 12 bits are kept
 185        vw_rx_bits >>= 1;
 186
 187        // Check the integrator to see how many samples in this cycle were high.
 188        // If < 5 out of 8, then its declared a 0 bit, else a 1;
 189        if (vw_rx_integrator >= 5)
 190            vw_rx_bits |= 0x800;
 191
 192        vw_rx_pll_ramp -= VW_RX_RAMP_LEN;
 193        vw_rx_integrator = 0; // Clear the integral for the next cycle
 194
 195        if (vw_rx_active)
 196        {
 197            // We have the start symbol and now we are collecting message bits,
 198            // 6 per symbol, each which has to be decoded to 4 bits
 199            if (++vw_rx_bit_count >= 12)
 200            {
 201                // Have 12 bits of encoded message == 1 byte encoded
 202                // Decode as 2 lots of 6 bits into 2 lots of 4 bits
 203                // The 6 lsbits are the high nybble
 204                uint8_t this_byte = 
 205                    (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4 
 206                    | vw_symbol_6to4(vw_rx_bits >> 6);
 207
 208                // The first decoded byte is the byte count of the following message
 209                // the count includes the byte count and the 2 trailing FCS bytes
 210                // REVISIT: may also include the ACK flag at 0x40
 211                if (vw_rx_len == 0)
 212                {
 213                    // The first byte is the byte count
 214                    // Check it for sensibility. It cant be less than 4, since it
 215                    // includes the bytes count itself and the 2 byte FCS
 216                    vw_rx_count = this_byte;
 217                    if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN)
 218                    {
 219                        // Stupid message length, drop the whole thing
 220                        vw_rx_active = false;
 221                        vw_rx_bad++;
 222                        return;
 223                    }
 224                }
 225                vw_rx_buf[vw_rx_len++] = this_byte;
 226
 227                if (vw_rx_len >= vw_rx_count)
 228                {
 229                    // Got all the bytes now
 230                    vw_rx_active = false;
 231                    vw_rx_good++;
 232                    vw_rx_done = true; // Better come get it before the next one starts
 233                }
 234                vw_rx_bit_count = 0;
 235            }
 236        }
 237        // Not in a message, see if we have a start symbol
 238        else if (vw_rx_bits == 0xb38)
 239        {
 240            // Have start symbol, start collecting message
 241            vw_rx_active = true;
 242            vw_rx_bit_count = 0;
 243            vw_rx_len = 0;
 244            vw_rx_done = false; // Too bad if you missed the last message
 245        }
 246    }
 247}
 248
 249// Speed is in bits per sec RF rate
 250void vw_setup(uint16_t speed)
 251{
 252    // Calculate the OCR1A overflow count based on the required bit speed
 253    // and CPU clock rate
 254    uint16_t ocr1a = (F_CPU / 8UL) / speed;
 255
 256#ifndef TEST
 257    // Set up timer1 for a tick every 62.50 microseconds 
 258    // for 2000 bits per sec
 259    TCCR1A = 0;
 260    TCCR1B = _BV(WGM12) | _BV(CS10);
 261    // Caution: special procedures for setting 16 bit regs
 262    OCR1A = ocr1a;
 263    // Enable interrupt
 264#ifdef TIMSK1
 265    // atmega168
 266    TIMSK1 |= _BV(OCIE1A);
 267#else
 268    // others
 269    TIMSK |= _BV(OCIE1A);
 270#endif
 271
 272#endif
 273
 274    // Set up digital IO pins
 275    pinMode(vw_tx_pin, OUTPUT);
 276    pinMode(vw_rx_pin, INPUT);
 277    pinMode(vw_ptt_pin, OUTPUT);
 278    digitalWrite(vw_ptt_pin, vw_ptt_inverted);
 279}
 280
 281// Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is
 282// set to the total number of symbols to send
 283void vw_tx_start()
 284{
 285    vw_tx_index = 0;
 286    vw_tx_bit = 0;
 287    vw_tx_sample = 0;
 288
 289    // Disable the receiver PLL
 290    vw_rx_enabled = false;
 291
 292    // Enable the transmitter hardware
 293    digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted);
 294
 295    // Next tick interrupt will send the first bit
 296    vw_tx_enabled = true;
 297}
 298
 299// Stop the transmitter, call when all bits are sent
 300void vw_tx_stop()
 301{
 302    // Disable the transmitter hardware
 303    digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted);
 304    digitalWrite(vw_tx_pin, false);
 305
 306    // No more ticks for the transmitter
 307    vw_tx_enabled = false;
 308
 309    // Enable the receiver PLL
 310    vw_rx_enabled = true;
 311}
 312
 313// Enable the receiver. When a message becomes available, vw_rx_done flag
 314// is set, and vw_wait_rx() will return.
 315void vw_rx_start()
 316{
 317    if (!vw_rx_enabled)
 318    {
 319        vw_rx_enabled = true;
 320        vw_rx_active = false; // Never restart a partial message
 321    }
 322}
 323
 324// Disable the receiver
 325void vw_rx_stop()
 326{
 327    vw_rx_enabled = false;
 328}
 329
 330// Wait for the transmitter to become available
 331// Busy-wait loop until the ISR says the message has been sent
 332void vw_wait_tx()
 333{
 334    while (vw_tx_enabled)
 335        ;
 336}
 337
 338// Wait for the receiver to get a message
 339// Busy-wait loop until the ISR says a message is available
 340// can then call vw_get_message()
 341void vw_wait_rx()
 342{
 343    while (!vw_rx_done)
 344        ;
 345}
 346
 347// Wait at most max milliseconds for the receiver to receive a message
 348// Return the truth of whether there is a message
 349uint8_t vw_wait_rx_max(unsigned long milliseconds)
 350{
 351    unsigned long start = millis();
 352
 353    while (!vw_rx_done && ((millis() - start) < milliseconds))
 354        ;
 355    return vw_rx_done;
 356}
 357
 358// Wait until transmitter is available and encode and queue the message
 359// into vw_tx_buf
 360// The message is raw bytes, with no packet structure imposed
 361// It is transmitted preceded a byte count and followed by 2 FCS bytes
 362uint8_t vw_send(uint8_t* buf, uint8_t len)
 363{
 364    uint8_t i;
 365    uint8_t index = 0;
 366    uint16_t crc = 0xffff;
 367    uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area
 368    uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes
 369
 370    if (len > VW_MAX_PAYLOAD)
 371        return false;
 372
 373    // Wait for transmitter to become available
 374    vw_wait_tx();
 375
 376    // Encode the message length
 377    crc = _crc_ccitt_update(crc, count);
 378    p[index++] = symbols[count >> 4];
 379    p[index++] = symbols[count & 0xf];
 380
 381    // Encode the message into 6 bit symbols. Each byte is converted into 
 382    // 2 6-bit symbols, high nybble first, low nybble second
 383    for (i = 0; i < len; i++)
 384    {
 385        crc = _crc_ccitt_update(crc, buf[i]);
 386        p[index++] = symbols[buf[i] >> 4];
 387        p[index++] = symbols[buf[i] & 0xf];
 388    }
 389
 390    // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
 391    // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
 392    // VW sends FCS as low byte then hi byte
 393    crc = ~crc;
 394    p[index++] = symbols[(crc >> 4)  & 0xf];
 395    p[index++] = symbols[crc & 0xf];
 396    p[index++] = symbols[(crc >> 12) & 0xf];
 397    p[index++] = symbols[(crc >> 8)  & 0xf];
 398
 399    // Total number of 6-bit symbols to send
 400    vw_tx_len = index + VW_HEADER_LEN;
 401
 402    // Start the low level interrupt handler sending symbols
 403    vw_tx_start();
 404
 405    return true;
 406}
 407
 408// This is the interrupt service routine called when timer1 overflows
 409// Its job is to output the next bit from the transmitter (every 8 calls)
 410// and to call the PLL code if the receiver is enabled
 411//ISR(SIG_OUTPUT_COMPARE1A)
 412SIGNAL(TIMER1_COMPA_vect)
 413{
 414    vw_rx_sample = digitalRead(vw_rx_pin);
 415
 416    // Do transmitter stuff first to reduce transmitter bit jitter due 
 417    // to variable receiver processing
 418    if (vw_tx_enabled && vw_tx_sample++ == 0)
 419    {
 420        // Send next bit
 421        // Symbols are sent LSB first
 422        // Finished sending the whole message? (after waiting one bit period 
 423        // since the last bit)
 424        if (vw_tx_index >= vw_tx_len)
 425        {
 426            vw_tx_stop();
 427            vw_tx_msg_count++;
 428        }
 429        else
 430        {
 431            digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
 432            if (vw_tx_bit >= 6)
 433            {
 434                vw_tx_bit = 0;
 435                vw_tx_index++;
 436            }
 437        }
 438    }
 439    if (vw_tx_sample > 7)
 440        vw_tx_sample = 0;
 441
 442    if (vw_rx_enabled)
 443        vw_pll();
 444}
 445
 446// Return true if there is a message available
 447uint8_t vw_have_message()
 448{
 449    return vw_rx_done;
 450}
 451
 452// Get the last message received (without byte count or FCS)
 453// Copy at most *len bytes, set *len to the actual number copied
 454// Return true if there is a message and the FCS is OK
 455uint8_t vw_get_message(uint8_t* buf, uint8_t* len)
 456{
 457    uint8_t rxlen;
 458
 459    // Message available?
 460    if (!vw_rx_done)
 461        return false;
 462
 463    // Wait until vw_rx_done is set before reading vw_rx_len
 464    // then remove bytecount and FCS
 465    rxlen = vw_rx_len - 3;
 466
 467    // Copy message (good or bad)
 468    if (*len > rxlen)
 469        *len = rxlen;
 470    memcpy(buf, vw_rx_buf + 1, *len);
 471
 472    vw_rx_done = false; // OK, got that message thanks
 473
 474    // Check the FCS, return goodness
 475    return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK?
 476}
 477
 478}