--- /dev/null
+See VirtulWire.h for latest change log
--- /dev/null
+This software is Copyright (C) 2008 Mike McCauley. Use is subject to license
+conditions. The main licensing options available are GPL V2 or Commercial:
+
+Open Source Licensing GPL V2
+
+This is the appropriate option if you want to share the source code of your
+application with everyone you distribute it to, and you also want to give them
+the right to share who uses it. If you wish to use this software under Open
+Source Licensing, you must contribute all your source code to the open source
+community in accordance with the GPL Version 2 when your application is
+distributed. See http://www.gnu.org/copyleft/gpl.html
+
+Commercial Licensing
+
+This is the appropriate option if you are creating proprietary applications
+and you are not prepared to distribute and share the source code of your
+application. Contact info@open.com.au for details.
--- /dev/null
+VirtualWire/doc
+VirtualWire/LICENSE
+VirtualWire/README
+VirtualWire/Makefile
+VirtualWire/VirtualWire.cpp
+VirtualWire/VirtualWire.h
+VirtualWire/CHANGES
+VirtualWire/MANIFEST
+VirtualWire/keywords.txt
+VirtualWire/util/crc16.h
+VirtualWire/examples/client/client.pde
+VirtualWire/examples/transmitter/transmitter.pde
+VirtualWire/examples/receiver/receiver.pde
+VirtualWire/examples/server/server.pde
--- /dev/null
+# Makefile
+#
+# Makefile for the Arduino VirtualWire project
+#
+# Author: Mike McCauley (mikem@airspayce.com)
+# Copyright (C) 2011 Mike McCauley
+# $Id: Makefile,v 1.1 2013/01/14 06:49:29 mikem Exp mikem $
+
+PROJNAME = VirtualWire
+# Dont forget to also change the version at the top of RF22.h:
+DISTFILE = $(PROJNAME)-1.19.zip
+
+all: doxygen dist upload
+
+doxygen:
+ doxygen project.cfg
+
+ci:
+ (cd ..;ci -l `cat $(PROJNAME)/MANIFEST`)
+
+dist:
+ (cd ..; zip $(PROJNAME)/$(DISTFILE) `cat $(PROJNAME)/MANIFEST`)
+
+upload:
+ rsync -avz $(DISTFILE) doc/ www.airspayce.com:public_html/mikem/arduino/$(PROJNAME)
+ rsync -avz ../../doc/VirtualWire.pdf doc/ www.airspayce.com:public_html/mikem/arduino/
--- /dev/null
+Virtual Wire
+
+This is the VirtualWire library for Arduino
+It provides a simple message passing protocol for a range of inexpensive
+transmitter and receiver modules.
+
+See http://www.open.com.au/mikem/arduino/VirtualWire.pdf for full documentation.
+
--- /dev/null
+// VirtualWire.cpp
+//
+// Virtual Wire implementation for Arduino
+// See the README file in this directory fdor documentation
+// See also
+// ASH Transceiver Software Designer's Guide of 2002.08.07
+// http://www.rfm.com/products/apnotes/tr_swg05.pdf
+//
+// Changes:
+// 1.5 2008-05-25: fixed a bug that could prevent messages with certain
+// bytes sequences being received (false message start detected)
+// 1.6 2011-09-10: Patch from David Bath to prevent unconditional reenabling of the receiver
+// at end of transmission.
+//
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: VirtualWire.cpp,v 1.13 2013/08/06 23:43:41 mikem Exp mikem $
+
+
+#if defined(ARDUINO)
+ #if (ARDUINO < 100)
+ #include "WProgram.h"
+ #endif
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+ #include "legacymsp430.h"
+ #include "Energia.h"
+#elif defined(MCU_STM32F103RE) // Maple etc
+#include <string.h>
+#else // error
+ #error Platform not defined
+#endif
+
+#include "VirtualWire.h"
+#include <util/crc16.h>
+
+
+static uint8_t vw_tx_buf[(VW_MAX_MESSAGE_LEN * 2) + VW_HEADER_LEN]
+ = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
+
+// Number of symbols in vw_tx_buf to be sent;
+static uint8_t vw_tx_len = 0;
+
+// Index of the next symbol to send. Ranges from 0 to vw_tx_len
+static uint8_t vw_tx_index = 0;
+
+// Bit number of next bit to send
+static uint8_t vw_tx_bit = 0;
+
+// Sample number for the transmitter. Runs 0 to 7 during one bit interval
+static uint8_t vw_tx_sample = 0;
+
+// Flag to indicated the transmitter is active
+static volatile uint8_t vw_tx_enabled = 0;
+
+// Total number of messages sent
+static uint16_t vw_tx_msg_count = 0;
+
+// The digital IO pin number of the press to talk, enables the transmitter hardware
+static uint8_t vw_ptt_pin = 10;
+static uint8_t vw_ptt_inverted = 0;
+
+// The digital IO pin number of the receiver data
+static uint8_t vw_rx_pin = 11;
+static uint8_t vw_rx_inverted = 0;
+
+// The digital IO pin number of the transmitter data
+static uint8_t vw_tx_pin = 12;
+
+// Current receiver sample
+static uint8_t vw_rx_sample = 0;
+
+// Last receiver sample
+static uint8_t vw_rx_last_sample = 0;
+
+// PLL ramp, varies between 0 and VW_RX_RAMP_LEN-1 (159) over
+// VW_RX_SAMPLES_PER_BIT (8) samples per nominal bit time.
+// When the PLL is synchronised, bit transitions happen at about the
+// 0 mark.
+static uint8_t vw_rx_pll_ramp = 0;
+
+// This is the integrate and dump integral. If there are <5 0 samples in the PLL cycle
+// the bit is declared a 0, else a 1
+static uint8_t vw_rx_integrator = 0;
+
+// Flag indictate if we have seen the start symbol of a new message and are
+// in the processes of reading and decoding it
+static uint8_t vw_rx_active = 0;
+
+// Flag to indicate that a new message is available
+static volatile uint8_t vw_rx_done = 0;
+
+// Flag to indicate the receiver PLL is to run
+static uint8_t vw_rx_enabled = 0;
+
+// Last 12 bits received, so we can look for the start symbol
+static uint16_t vw_rx_bits = 0;
+
+// How many bits of message we have received. Ranges from 0 to 12
+static uint8_t vw_rx_bit_count = 0;
+
+// The incoming message buffer
+static uint8_t vw_rx_buf[VW_MAX_MESSAGE_LEN];
+
+// The incoming message expected length
+static uint8_t vw_rx_count = 0;
+
+// The incoming message buffer length received so far
+static volatile uint8_t vw_rx_len = 0;
+
+// Number of bad messages received and dropped due to bad lengths
+static uint8_t vw_rx_bad = 0;
+
+// Number of good messages received
+static uint8_t vw_rx_good = 0;
+
+// 4 bit to 6 bit symbol converter table
+// Used to convert the high and low nybbles of the transmitted data
+// into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s
+// with at most 3 consecutive identical bits
+static uint8_t symbols[] =
+{
+ 0xd, 0xe, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
+ 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
+};
+
+// Cant really do this as a real C++ class, since we need to have
+// an ISR
+extern "C"
+{
+
+// Compute CRC over count bytes.
+// This should only be ever called at user level, not interrupt level
+uint16_t vw_crc(uint8_t *ptr, uint8_t count)
+{
+ uint16_t crc = 0xffff;
+
+ while (count-- > 0)
+ crc = _crc_ccitt_update(crc, *ptr++);
+ return crc;
+}
+
+// Convert a 6 bit encoded symbol into its 4 bit decoded equivalent
+uint8_t vw_symbol_6to4(uint8_t symbol)
+{
+ uint8_t i;
+
+ // Linear search :-( Could have a 64 byte reverse lookup table?
+ for (i = 0; i < 16; i++)
+ if (symbol == symbols[i]) return i;
+ return 0; // Not found
+}
+
+// Set the output pin number for transmitter data
+void vw_set_tx_pin(uint8_t pin)
+{
+ vw_tx_pin = pin;
+}
+
+// Set the pin number for input receiver data
+void vw_set_rx_pin(uint8_t pin)
+{
+ vw_rx_pin = pin;
+}
+
+// Set the rx pin inverted
+void vw_set_rx_inverted(uint8_t inverted)
+{
+ vw_rx_inverted = inverted;
+}
+
+// Set the output pin number for transmitter PTT enable
+void vw_set_ptt_pin(uint8_t pin)
+{
+ vw_ptt_pin = pin;
+}
+
+// Set the ptt pin inverted (low to transmit)
+void vw_set_ptt_inverted(uint8_t inverted)
+{
+ vw_ptt_inverted = inverted;
+}
+
+// Called 8 times per bit period
+// Phase locked loop tries to synchronise with the transmitter so that bit
+// transitions occur at about the time vw_rx_pll_ramp is 0;
+// Then the average is computed over each bit period to deduce the bit value
+void vw_pll()
+{
+ // Integrate each sample
+ if (vw_rx_sample)
+ vw_rx_integrator++;
+
+ if (vw_rx_sample != vw_rx_last_sample)
+ {
+ // Transition, advance if ramp > 80, retard if < 80
+ vw_rx_pll_ramp += ((vw_rx_pll_ramp < VW_RAMP_TRANSITION)
+ ? VW_RAMP_INC_RETARD
+ : VW_RAMP_INC_ADVANCE);
+ vw_rx_last_sample = vw_rx_sample;
+ }
+ else
+ {
+ // No transition
+ // Advance ramp by standard 20 (== 160/8 samples)
+ vw_rx_pll_ramp += VW_RAMP_INC;
+ }
+ if (vw_rx_pll_ramp >= VW_RX_RAMP_LEN)
+ {
+ // Add this to the 12th bit of vw_rx_bits, LSB first
+ // The last 12 bits are kept
+ vw_rx_bits >>= 1;
+
+ // Check the integrator to see how many samples in this cycle were high.
+ // If < 5 out of 8, then its declared a 0 bit, else a 1;
+ if (vw_rx_integrator >= 5)
+ vw_rx_bits |= 0x800;
+
+ vw_rx_pll_ramp -= VW_RX_RAMP_LEN;
+ vw_rx_integrator = 0; // Clear the integral for the next cycle
+
+ if (vw_rx_active)
+ {
+ // We have the start symbol and now we are collecting message bits,
+ // 6 per symbol, each which has to be decoded to 4 bits
+ if (++vw_rx_bit_count >= 12)
+ {
+ // Have 12 bits of encoded message == 1 byte encoded
+ // Decode as 2 lots of 6 bits into 2 lots of 4 bits
+ // The 6 lsbits are the high nybble
+ uint8_t this_byte =
+ (vw_symbol_6to4(vw_rx_bits & 0x3f)) << 4
+ | vw_symbol_6to4(vw_rx_bits >> 6);
+
+ // The first decoded byte is the byte count of the following message
+ // the count includes the byte count and the 2 trailing FCS bytes
+ // REVISIT: may also include the ACK flag at 0x40
+ if (vw_rx_len == 0)
+ {
+ // The first byte is the byte count
+ // Check it for sensibility. It cant be less than 4, since it
+ // includes the bytes count itself and the 2 byte FCS
+ vw_rx_count = this_byte;
+ if (vw_rx_count < 4 || vw_rx_count > VW_MAX_MESSAGE_LEN)
+ {
+ // Stupid message length, drop the whole thing
+ vw_rx_active = false;
+ vw_rx_bad++;
+ return;
+ }
+ }
+ vw_rx_buf[vw_rx_len++] = this_byte;
+
+ if (vw_rx_len >= vw_rx_count)
+ {
+ // Got all the bytes now
+ vw_rx_active = false;
+ vw_rx_good++;
+ vw_rx_done = true; // Better come get it before the next one starts
+ }
+ vw_rx_bit_count = 0;
+ }
+ }
+ // Not in a message, see if we have a start symbol
+ else if (vw_rx_bits == 0xb38)
+ {
+ // Have start symbol, start collecting message
+ vw_rx_active = true;
+ vw_rx_bit_count = 0;
+ vw_rx_len = 0;
+ vw_rx_done = false; // Too bad if you missed the last message
+ }
+ }
+}
+
+#if defined(__arm__) && defined(CORE_TEENSY)
+ // This allows the AVR interrupt code below to be run from an
+ // IntervalTimer object. It must be above vw_setup(), so the
+ // the TIMER1_COMPA_vect function name is defined.
+ #ifdef SIGNAL
+ #undef SIGNAL
+ #endif
+ #define SIGNAL(f) void f(void)
+ #ifdef TIMER1_COMPA_vect
+ #undef TIMER1_COMPA_vect
+ #endif
+ void TIMER1_COMPA_vect(void);
+#endif
+
+
+// Speed is in bits per sec RF rate
+#if defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+void vw_setup(uint16_t speed)
+{
+ // Calculate the counter overflow count based on the required bit speed
+ // and CPU clock rate
+ uint16_t ocr1a = (F_CPU / 8UL) / speed;
+
+ // This code is for Energia/MSP430
+ TA0CCR0 = ocr1a; // Ticks for 62,5 us
+ TA0CTL = TASSEL_2 + MC_1; // SMCLK, up mode
+ TA0CCTL0 |= CCIE; // CCR0 interrupt enabled
+
+ // Set up digital IO pins
+ pinMode(vw_tx_pin, OUTPUT);
+ pinMode(vw_rx_pin, INPUT);
+ pinMode(vw_ptt_pin, OUTPUT);
+ digitalWrite(vw_ptt_pin, vw_ptt_inverted);
+}
+
+#elif defined (ARDUINO) // Arduino specific
+
+// Common function for setting timer ticks @ prescaler values for speed
+// Returns prescaler index into {0, 1, 8, 64, 256, 1024} array
+// and sets nticks to compare-match value if lower than max_ticks
+// returns 0 & nticks = 0 on fault
+static uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
+{
+ // Clock divider (prescaler) values - 0/3333: error flag
+ uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
+ uint8_t prescaler=0; // index into array & return bit value
+ unsigned long ulticks; // calculate by ntick overflow
+
+ // Div-by-zero protection
+ if (speed == 0)
+ {
+ // signal fault
+ *nticks = 0;
+ return 0;
+ }
+
+ // test increasing prescaler (divisor), decreasing ulticks until no overflow
+ for (prescaler=1; prescaler < 7; prescaler += 1)
+ {
+ // Amount of time per CPU clock tick (in seconds)
+ float clock_time = (1.0 / (float(F_CPU) / float(prescalers[prescaler])));
+ // Fraction of second needed to xmit one bit
+ float bit_time = ((1.0 / float(speed)) / 8.0);
+ // number of prescaled ticks needed to handle bit time @ speed
+ ulticks = long(bit_time / clock_time);
+ // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
+ if ((ulticks > 1) && (ulticks < max_ticks))
+ {
+ break; // found prescaler
+ }
+ // Won't fit, check with next prescaler value
+ }
+
+ // Check for error
+ if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
+ {
+ // signal fault
+ *nticks = 0;
+ return 0;
+ }
+
+ *nticks = ulticks;
+ return prescaler;
+}
+
+void vw_setup(uint16_t speed)
+{
+ uint16_t nticks; // number of prescaled ticks needed
+ uint8_t prescaler; // Bit values for CS0[2:0]
+
+#ifdef __AVR_ATtiny85__
+ // figure out prescaler value and counter match value
+ prescaler = _timer_calc(speed, (uint8_t)-1, &nticks);
+ if (!prescaler)
+ {
+ return; // fault
+ }
+
+ TCCR0A = 0;
+ TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected
+
+ // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
+ TCCR0B = 0;
+ TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)
+
+ // Number of ticks to count before firing interrupt
+ OCR0A = uint8_t(nticks);
+
+ // Set mask to fire interrupt when OCF0A bit is set in TIFR0
+ TIMSK |= _BV(OCIE0A);
+
+#elif defined(__arm__) && defined(CORE_TEENSY)
+ // on Teensy 3.0 (32 bit ARM), use an interval timer
+ IntervalTimer *t = new IntervalTimer();
+ t->begin(TIMER1_COMPA_vect, 125000.0 / (float)(speed));
+
+#else // ARDUINO
+ // This is the path for most Arduinos
+ // figure out prescaler value and counter match value
+ prescaler = _timer_calc(speed, (uint16_t)-1, &nticks);
+ if (!prescaler)
+ {
+ return; // fault
+ }
+
+ TCCR1A = 0; // Output Compare pins disconnected
+ TCCR1B = _BV(WGM12); // Turn on CTC mode
+
+ // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
+ TCCR1B |= prescaler;
+
+ // Caution: special procedures for setting 16 bit regs
+ // is handled by the compiler
+ OCR1A = nticks;
+ // Enable interrupt
+#ifdef TIMSK1
+ // atmega168
+ TIMSK1 |= _BV(OCIE1A);
+#else
+ // others
+ TIMSK |= _BV(OCIE1A);
+#endif // TIMSK1
+
+#endif // __AVR_ATtiny85__
+
+ // Set up digital IO pins
+ pinMode(vw_tx_pin, OUTPUT);
+ pinMode(vw_rx_pin, INPUT);
+ pinMode(vw_ptt_pin, OUTPUT);
+ digitalWrite(vw_ptt_pin, vw_ptt_inverted);
+}
+
+#elif defined(MCU_STM32F103RE) // Maple etc
+HardwareTimer timer(MAPLE_TIMER);
+void vw_setup(uint16_t speed)
+{
+ // Set up digital IO pins
+ pinMode(vw_tx_pin, OUTPUT);
+ pinMode(vw_rx_pin, INPUT);
+ pinMode(vw_ptt_pin, OUTPUT);
+ digitalWrite(vw_ptt_pin, vw_ptt_inverted);
+
+ // Pause the timer while we're configuring it
+ timer.pause();
+ timer.setPeriod((1000000/8)/speed);
+ // Set up an interrupt on channel 1
+ timer.setChannel1Mode(TIMER_OUTPUT_COMPARE);
+ timer.setCompare(TIMER_CH1, 1); // Interrupt 1 count after each update
+ void vw_Int_Handler(); // defined below
+ timer.attachCompare1Interrupt(vw_Int_Handler);
+
+ // Refresh the timer's count, prescale, and overflow
+ timer.refresh();
+
+ // Start the timer counting
+ timer.resume();
+}
+
+#endif
+
+// Start the transmitter, call when the tx buffer is ready to go and vw_tx_len is
+// set to the total number of symbols to send
+void vw_tx_start()
+{
+ vw_tx_index = 0;
+ vw_tx_bit = 0;
+ vw_tx_sample = 0;
+
+ // Enable the transmitter hardware
+ digitalWrite(vw_ptt_pin, true ^ vw_ptt_inverted);
+
+ // Next tick interrupt will send the first bit
+ vw_tx_enabled = true;
+}
+
+// Stop the transmitter, call when all bits are sent
+void vw_tx_stop()
+{
+ // Disable the transmitter hardware
+ digitalWrite(vw_ptt_pin, false ^ vw_ptt_inverted);
+ digitalWrite(vw_tx_pin, false);
+
+ // No more ticks for the transmitter
+ vw_tx_enabled = false;
+}
+
+// Enable the receiver. When a message becomes available, vw_rx_done flag
+// is set, and vw_wait_rx() will return.
+void vw_rx_start()
+{
+ if (!vw_rx_enabled)
+ {
+ vw_rx_enabled = true;
+ vw_rx_active = false; // Never restart a partial message
+ }
+}
+
+// Disable the receiver
+void vw_rx_stop()
+{
+ vw_rx_enabled = false;
+}
+
+// Return true if the transmitter is active
+uint8_t vw_tx_active()
+{
+ return vw_tx_enabled;
+}
+
+// Wait for the transmitter to become available
+// Busy-wait loop until the ISR says the message has been sent
+void vw_wait_tx()
+{
+ while (vw_tx_enabled)
+ ;
+}
+
+// Wait for the receiver to get a message
+// Busy-wait loop until the ISR says a message is available
+// can then call vw_get_message()
+void vw_wait_rx()
+{
+ while (!vw_rx_done)
+ ;
+}
+
+// Wait at most max milliseconds for the receiver to receive a message
+// Return the truth of whether there is a message
+uint8_t vw_wait_rx_max(unsigned long milliseconds)
+{
+ unsigned long start = millis();
+
+ while (!vw_rx_done && ((millis() - start) < milliseconds))
+ ;
+ return vw_rx_done;
+}
+
+// Wait until transmitter is available and encode and queue the message
+// into vw_tx_buf
+// The message is raw bytes, with no packet structure imposed
+// It is transmitted preceded a byte count and followed by 2 FCS bytes
+uint8_t vw_send(uint8_t* buf, uint8_t len)
+{
+ uint8_t i;
+ uint8_t index = 0;
+ uint16_t crc = 0xffff;
+ uint8_t *p = vw_tx_buf + VW_HEADER_LEN; // start of the message area
+ uint8_t count = len + 3; // Added byte count and FCS to get total number of bytes
+
+ if (len > VW_MAX_PAYLOAD)
+ return false;
+
+ // Wait for transmitter to become available
+ vw_wait_tx();
+
+ // Encode the message length
+ crc = _crc_ccitt_update(crc, count);
+ p[index++] = symbols[count >> 4];
+ p[index++] = symbols[count & 0xf];
+
+ // Encode the message into 6 bit symbols. Each byte is converted into
+ // 2 6-bit symbols, high nybble first, low nybble second
+ for (i = 0; i < len; i++)
+ {
+ crc = _crc_ccitt_update(crc, buf[i]);
+ p[index++] = symbols[buf[i] >> 4];
+ p[index++] = symbols[buf[i] & 0xf];
+ }
+
+ // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
+ // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
+ // VW sends FCS as low byte then hi byte
+ crc = ~crc;
+ p[index++] = symbols[(crc >> 4) & 0xf];
+ p[index++] = symbols[crc & 0xf];
+ p[index++] = symbols[(crc >> 12) & 0xf];
+ p[index++] = symbols[(crc >> 8) & 0xf];
+
+ // Total number of 6-bit symbols to send
+ vw_tx_len = index + VW_HEADER_LEN;
+
+ // Start the low level interrupt handler sending symbols
+ vw_tx_start();
+
+ return true;
+}
+
+// Return true if there is a message available
+uint8_t vw_have_message()
+{
+ return vw_rx_done;
+}
+
+// Get the last message received (without byte count or FCS)
+// Copy at most *len bytes, set *len to the actual number copied
+// Return true if there is a message and the FCS is OK
+uint8_t vw_get_message(uint8_t* buf, uint8_t* len)
+{
+ uint8_t rxlen;
+
+ // Message available?
+ if (!vw_rx_done)
+ return false;
+
+ // Wait until vw_rx_done is set before reading vw_rx_len
+ // then remove bytecount and FCS
+ rxlen = vw_rx_len - 3;
+
+ // Copy message (good or bad)
+ if (*len > rxlen)
+ *len = rxlen;
+ memcpy(buf, vw_rx_buf + 1, *len);
+
+ vw_rx_done = false; // OK, got that message thanks
+
+ // Check the FCS, return goodness
+ return (vw_crc(vw_rx_buf, vw_rx_len) == 0xf0b8); // FCS OK?
+}
+
+uint8_t vw_get_rx_good()
+{
+ return vw_rx_good;
+}
+
+uint8_t vw_get_rx_bad()
+{
+ return vw_rx_bad;
+}
+
+// This is the interrupt service routine called when timer1 overflows
+// Its job is to output the next bit from the transmitter (every 8 calls)
+// and to call the PLL code if the receiver is enabled
+//ISR(SIG_OUTPUT_COMPARE1A)
+#if defined (ARDUINO) // Arduino specific
+
+#ifdef __AVR_ATtiny85__
+SIGNAL(TIM0_COMPA_vect)
+#else // Assume Arduino Uno (328p or similar)
+SIGNAL(TIMER1_COMPA_vect)
+#endif // __AVR_ATtiny85__
+
+{
+ if (vw_rx_enabled && !vw_tx_enabled)
+ vw_rx_sample = digitalRead(vw_rx_pin) ^ vw_rx_inverted;
+
+ // Do transmitter stuff first to reduce transmitter bit jitter due
+ // to variable receiver processing
+ if (vw_tx_enabled && vw_tx_sample++ == 0)
+ {
+ // Send next bit
+ // Symbols are sent LSB first
+ // Finished sending the whole message? (after waiting one bit period
+ // since the last bit)
+ if (vw_tx_index >= vw_tx_len)
+ {
+ vw_tx_stop();
+ vw_tx_msg_count++;
+ }
+ else
+ {
+ digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
+ if (vw_tx_bit >= 6)
+ {
+ vw_tx_bit = 0;
+ vw_tx_index++;
+ }
+ }
+ }
+ if (vw_tx_sample > 7)
+ vw_tx_sample = 0;
+
+ if (vw_rx_enabled && !vw_tx_enabled)
+ vw_pll();
+}
+ // LaunchPad or Maple:
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) || defined(MCU_STM32F103RE)
+void vw_Int_Handler()
+{
+ if (vw_rx_enabled && !vw_tx_enabled)
+ vw_rx_sample = digitalRead(vw_rx_pin) ^ vw_rx_inverted;
+
+ // Do transmitter stuff first to reduce transmitter bit jitter due
+ // to variable receiver processing
+ if (vw_tx_enabled && vw_tx_sample++ == 0)
+ {
+ // Send next bit
+ // Symbols are sent LSB first
+ // Finished sending the whole message? (after waiting one bit period
+ // since the last bit)
+ if (vw_tx_index >= vw_tx_len)
+ {
+ vw_tx_stop();
+ vw_tx_msg_count++;
+ }
+ else
+ {
+ digitalWrite(vw_tx_pin, vw_tx_buf[vw_tx_index] & (1 << vw_tx_bit++));
+ if (vw_tx_bit >= 6)
+ {
+ vw_tx_bit = 0;
+ vw_tx_index++;
+ }
+ }
+ }
+ if (vw_tx_sample > 7)
+ vw_tx_sample = 0;
+
+ if (vw_rx_enabled && !vw_tx_enabled)
+ vw_pll();
+}
+#if defined(__MSP430G2452__) || defined(__MSP430G2553__)
+interrupt(TIMER0_A0_VECTOR) Timer_A_int(void)
+{
+ vw_Int_Handler();
+};
+#endif
+
+#endif
+
+
+}
--- /dev/null
+// VirtualWire.h
+//
+// Virtual Wire implementation for Arduino and other boards
+// See the README file in this directory for documentation
+//
+// Author: Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS
+// Copyright (C) 2008 Mike McCauley
+// $Id: VirtualWire.h,v 1.10 2013/08/06 23:43:41 mikem Exp mikem $
+
+/// \mainpage VirtualWire library for Arduino and other boards
+///
+/// This is the VirtualWire library.
+///
+/// VirtualWire is an library for Arduino, Maple and others that provides features to send short
+/// messages, without addressing, retransmit or acknowledgment, a bit like UDP
+/// over wireless, using ASK (amplitude shift keying). Supports a number of
+/// inexpensive radio transmitters and receivers. All that is required is
+/// transmit data, receive data and (for transmitters, optionally) a PTT
+/// transmitter enable. Can also be used over various analog connections (not just a data radio),
+/// such as the audio channel of an A/V sender
+///
+/// It is intended to be compatible with the RF Monolithics (www.rfm.com)
+/// Virtual Wire protocol, but this has not been tested.
+///
+/// Does not use the Arduino UART. Messages are sent with a training preamble,
+/// message length and checksum. Messages are sent with 4-to-6 bit encoding
+/// for good DC balance, and a CRC checksum for message integrity.
+///
+/// Why not just use a UART connected directly to the
+/// transmitter/receiver? As discussed in the RFM documentation, ASK receivers
+/// require a burst of training pulses to synchronize the transmitter and
+/// receiver, and also requires good balance between 0s and 1s in the message
+/// stream in order to maintain the DC balance of the message. UARTs do not
+/// provide these. They work a bit with ASK wireless, but not as well as this
+/// code.
+///
+/// This library provides classes for
+/// - VirtualWire: unaddressed, unreliable messages
+///
+/// Example Arduino programs are included to show the main modes of use.
+///
+/// The version of the package that this documentation refers to can be downloaded
+/// from http://www.airspayce.com/mikem/arduino/VirtualWire/VirtualWire-1.19.zip
+/// You can find the latest version at http://www.airspayce.com/mikem/arduino/VirtualWire
+///
+/// You can also find online help and disussion at http://groups.google.com/group/virtualwire
+/// Please use that group for all questions and discussions on this topic.
+/// Do not contact the author directly, unless it is to discuss commercial licensing.
+///
+/// \par Supported Hardware
+/// A range of communications hardware is supported. The ones listed below are
+/// available in common retail outlets in Australian and other countries for
+/// under $10 per unit. Many other modules may also work with this software.
+/// Runs on ATmega8/168 (Arduino Diecimila, Uno etc) and ATmega328 and possibly
+/// others. Also runs on on Energia with MSP430G2553 / G2452 and Arduino with
+/// ATMega328 (courtesy Yannick DEVOS - XV4Y), but untested by us.
+/// It also runs on Teensy 3.0 (courtesy of Paul Stoffregen), but untested by us.
+/// Also compiles and runs on ATtiny85 in Arduino environment, courtesy r4z0r7o3.
+/// Also compiles on maple-ide-v0.0.12, and runs on Maple, flymaple 1.1 etc.
+///
+/// - Receivers
+/// - RX-B1 (433.92MHz) (also known as ST-RX04-ASK)
+/// - Transmitters:
+/// - TX-C1 (433.92MHz)
+/// - Transceivers
+/// - DR3100 (433.92MHz)
+///
+/// For testing purposes you can connect 2 VirtualWire instances directly, by
+/// connecting pin 12 of one to 11 of the other and vice versa, like this for a duplex connection:
+///
+/// <code>
+/// Arduino 1 wires Arduino 1
+/// D11-----------------------------D12
+/// D12-----------------------------D11
+/// GND-----------------------------GND
+/// </code>
+///
+/// You can also connect 2 VirtualWire instances over a suitable analog
+/// transmitter/receiver, such as the audio channel of an A/V transmitter/receiver. You may need
+/// buffers at each end of the connection to convert the 0-5V digital output to a suitable analog voltage.
+///
+/// \par Installation
+/// To install, unzip the library into the libraries sub-directory of your
+/// Arduino application directory. Then launch the Arduino environment; you
+/// should see the library in the Sketch->Import Library menu, and example
+/// code in
+/// File->Sketchbook->Examples->VirtualWire menu.
+///
+/// \par Open Source Licensing GPL V2
+///
+/// This is the appropriate option if you want to share the source code of your
+/// application with everyone you distribute it to, and you also want to give them
+/// the right to share who uses it. If you wish to use this software under Open
+/// Source Licensing, you must contribute all your source code to the open source
+/// community in accordance with the GPL Version 2 when your application is
+/// distributed. See http://www.gnu.org/copyleft/gpl.html
+///
+/// \par Commercial Licensing
+///
+/// This is the appropriate option if you are creating proprietary applications
+/// and you are not prepared to distribute and share the source code of your
+/// application. Contact info@airspayce.com for details.
+///
+/// \par Revision History
+/// \version 1.0 Original release
+///
+/// \version 1.1 2008-06-24
+/// Now can compile for atmega8
+/// Reported by creatrope
+/// \version 1.2 2009-03-30
+/// Fixed a problem that prevented compiling with arduino-0015
+/// Reported by Jaime Castro
+/// \version 1.3 2009-04-01
+/// Fixed a compatibility problem with ATMEGA328 of the new arduino
+/// Now use SIGNAL(TIMER1_COMPA_vect) instead of ISR(SIG_OUTPUT_COMPARE1A)
+/// as discussed in
+/// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1237714550/11
+/// and reported by Jaime Castro.
+/// \version 1.4 2010-01-29
+/// Added vx_tx_active(), suggested by Alan Burlison.
+/// \version 1.5 2011-09-09
+/// Added vx_tx_active() function.
+/// \version 1.6 2012-01-10
+/// Fixed a problem where the receiver was always reenabled after
+/// transmission. Reported by David Bath
+/// \version 1.9 2012-02-07 Documentation updates
+/// Documentation updates
+/// \version 1.10 Updated CHANGES file with changes since 1.4.
+/// \version 1.11 Converted documentation to Doxygen. Moved CHANGES log to this version history.
+/// Ensure vw_rx_pin is not accessed unless receiver is enabled
+/// \version 1.12 Compiles and runs on on Energia with MSP430G2553 / G2452 and Arduino with ATMega328.
+/// Patches contributed by Yannick DEVOS - XV4Y
+/// \version 1.13 util/crc16.h needed for compiling on Energia with MSP430G2553 / G2452 was accidentally
+/// left out of the distribution
+/// \version 1.14 Added support ATtiny85 on Arduino, patch provided by r4z0r7o3.
+/// \version 1.15 Updated author and distribution location details to airspayce.com
+/// \version 1.16 Added support for Teensy 3.0, contributed by Paul Stoffregen.
+/// \version 1.17 Increase default MAX_MESSAGE_LENGTH to 80. Added vw_get_rx_good() and vw_get_rx_bad()
+/// functions.
+/// \version 1.18 Added support for Maple, Flymaple etc with STM32F103RE processor using timer 1.
+/// Tested with Flymaple 1.1 and maple-ide-v0.0.12
+/// \version 1.19 Added new function vw_rx_inverted(), to allow the incoming RX to be inverted (normally high).
+/// Minor improvements to timer setup for Maple. Name vw_tx_active() changed from incorrect
+/// vx_tx_active()
+///
+/// \par Implementation Details
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \par Performance
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \par Connections
+/// See: http://www.airspayce.com/mikem/arduino/VirtualWire.pdf
+///
+/// \file VirtualWire.h
+/// \brief VirtualWire API
+///
+/// To use the VirtualWire library, you must have
+/// \code
+/// #include <VirtualWire.h>
+/// \endcode
+/// At the top of your sketch.
+///
+
+#ifndef VirtualWire_h
+#define VirtualWire_h
+
+#include <stdlib.h>
+#if defined(ARDUINO)
+ #if ARDUINO >= 100
+ #include <Arduino.h>
+ #else
+ #include <wiring.h>
+ #endif
+#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
+ #include "legacymsp430.h"
+ #include "Energia.h"
+#elif defined(MCU_STM32F103RE) // Maple etc
+ #include <wirish.h>
+ #include <string.h>
+ #include <stdint.h>
+// Defines which timer to use on Maple
+#define MAPLE_TIMER 1
+#else // error
+ #error Platform not defined
+#endif
+
+// These defs cause trouble on some versions of Arduino
+#undef abs
+#undef double
+#undef round
+
+/// Maximum number of bytes in a message, counting the byte count and FCS
+#define VW_MAX_MESSAGE_LEN 80
+
+/// The maximum payload length
+#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3
+
+/// The size of the receiver ramp. Ramp wraps modulu this number
+#define VW_RX_RAMP_LEN 160
+
+/// Number of samples per bit
+#define VW_RX_SAMPLES_PER_BIT 8
+
+// Ramp adjustment parameters
+// Standard is if a transition occurs before VW_RAMP_TRANSITION (80) in the ramp,
+// the ramp is retarded by adding VW_RAMP_INC_RETARD (11)
+// else by adding VW_RAMP_INC_ADVANCE (29)
+// If there is no transition it is adjusted by VW_RAMP_INC (20)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC (VW_RX_RAMP_LEN/VW_RX_SAMPLES_PER_BIT)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_TRANSITION VW_RX_RAMP_LEN/2
+/// Internal ramp adjustment parameter
+#define VW_RAMP_ADJUST 9
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC_RETARD (VW_RAMP_INC-VW_RAMP_ADJUST)
+/// Internal ramp adjustment parameter
+#define VW_RAMP_INC_ADVANCE (VW_RAMP_INC+VW_RAMP_ADJUST)
+
+/// Outgoing message bits grouped as 6-bit words
+/// 36 alternating 1/0 bits, followed by 12 bits of start symbol
+/// Followed immediately by the 4-6 bit encoded byte count,
+/// message buffer and 2 byte FCS
+/// Each byte from the byte count on is translated into 2x6-bit words
+/// Caution, each symbol is transmitted LSBit first,
+/// but each byte is transmitted high nybble first
+#define VW_HEADER_LEN 8
+
+// Cant really do this as a real C++ class, since we need to have
+// an ISR
+extern "C"
+{
+ /// Set the digital IO pin to be for transmit data.
+ /// This pin will only be accessed if
+ /// the transmitter is enabled
+ /// \param[in] pin The Arduino pin number for transmitting data. Defaults to 12.
+ extern void vw_set_tx_pin(uint8_t pin);
+
+ /// Set the digital IO pin to be for receive data.
+ /// This pin will only be accessed if
+ /// the receiver is enabled
+ /// \param[in] pin The Arduino pin number for receiving data. Defaults to 11.
+ extern void vw_set_rx_pin(uint8_t pin);
+
+ /// By default the RX pin is expected to be low when idle, and to pulse high
+ /// for each data pulse.
+ /// This flag forces it to be inverted. This may be necessary if your transport medium
+ /// inverts the logic of your signal, such as happens with some types of A/V tramsmitter.
+ /// \param[in] inverted True to invert sense of receiver input
+ extern void vw_set_rx_inverted(uint8_t inverted);
+
+ // Set the digital IO pin to enable the transmitter (press to talk, PTT)'
+ /// This pin will only be accessed if
+ /// the transmitter is enabled
+ /// \param[in] pin The Arduino pin number to enable the transmitter. Defaults to 10.
+ extern void vw_set_ptt_pin(uint8_t pin);
+
+ /// By default the PTT pin goes high when the transmitter is enabled.
+ /// This flag forces it low when the transmitter is enabled.
+ /// \param[in] inverted True to invert PTT
+ extern void vw_set_ptt_inverted(uint8_t inverted);
+
+ /// Initialise the VirtualWire software, to operate at speed bits per second
+ /// Call this one in your setup() after any vw_set_* calls
+ /// Must call vw_rx_start() before you will get any messages
+ /// \param[in] speed Desired speed in bits per second
+ extern void vw_setup(uint16_t speed);
+
+ /// Start the Phase Locked Loop listening to the receiver
+ /// Must do this before you can receive any messages
+ /// When a message is available (good checksum or not), vw_have_message();
+ /// will return true.
+ extern void vw_rx_start();
+
+ /// Stop the Phase Locked Loop listening to the receiver
+ /// No messages will be received until vw_rx_start() is called again
+ /// Saves interrupt processing cycles
+ extern void vw_rx_stop();
+
+ /// Returns the state of the
+ /// transmitter
+ /// \return true if the transmitter is active else false
+ extern uint8_t vw_tx_active();
+
+ /// Block until the transmitter is idle
+ /// then returns
+ extern void vw_wait_tx();
+
+ /// Block until a message is available
+ /// then returns
+ extern void vw_wait_rx();
+
+ /// Block until a message is available or for a max time
+ /// \param[in] milliseconds Maximum time to wait in milliseconds.
+ /// \return true if a message is available, false if the wait timed out.
+ extern uint8_t vw_wait_rx_max(unsigned long milliseconds);
+
+ /// Send a message with the given length. Returns almost immediately,
+ /// and message will be sent at the right timing by interrupts
+ /// \param[in] buf Pointer to the data to transmit
+ /// \param[in] len Number of octetes to transmit
+ /// \return true if the message was accepted for transmission, false if the message is too long (>VW_MAX_MESSAGE_LEN - 3)
+ extern uint8_t vw_send(uint8_t* buf, uint8_t len);
+
+ /// Returns true if an unread message is available
+ /// \return true if a message is available to read
+ extern uint8_t vw_have_message();
+
+ /// If a message is available (good checksum or not), copies
+ /// up to *len octets to buf.
+ /// \param[in] buf Pointer to location to save the read data (must be at least *len bytes.
+ /// \param[in,out] len Available space in buf. Will be set to the actual number of octets read
+ /// \return true if there was a message and the checksum was good
+ extern uint8_t vw_get_message(uint8_t* buf, uint8_t* len);
+
+ /// Returns the count of good messages received
+ /// Caution,: this is an 8 bit count and can easily overflow
+ /// \return Count of good messages received
+ extern uint8_t vw_get_rx_good();
+
+ /// Returns the count of bad messages received, ie
+ /// messages with bogus lengths, indicating corruption
+ /// or lost octets.
+ /// Caution,: this is an 8 bit count and can easily overflow
+ /// \return Count of bad messages received
+ extern uint8_t vw_get_rx_bad();
+}
+
+/// @example client.pde
+/// Client side of simple client/server pair using VirtualWire
+
+/// @example server.pde
+/// Server side of simple client/server pair using VirtualWire
+
+/// @example transmitter.pde
+/// Transmitter side of simple one-way transmitter->receiver pair using VirtualWire
+
+/// @example receiver.pde
+/// Transmitter side of simple one-way transmitter->receiver pair using VirtualWire
+
+#endif
--- /dev/null
+// client.pde
+//
+// Simple example of how to use VirtualWire to send and receive messages
+// with a DR3100 module.
+// Send a message to another arduino running the 'server' example, which
+// should send a reply, which we will check
+//
+// See VirtualWire.h for detailed API docs
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: client.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $
+
+#include <VirtualWire.h>
+
+void setup()
+{
+ Serial.begin(9600); // Debugging only
+ Serial.println("setup");
+
+ // Initialise the IO and ISR
+ vw_set_ptt_inverted(true); // Required for DR3100
+ vw_setup(2000); // Bits per sec
+ vw_rx_start(); // Start the receiver PLL running
+}
+
+void loop()
+{
+ const char *msg = "hello";
+ uint8_t buf[VW_MAX_MESSAGE_LEN];
+ uint8_t buflen = VW_MAX_MESSAGE_LEN;
+
+ digitalWrite(13, true); // Flash a light to show transmitting
+ vw_send((uint8_t *)msg, strlen(msg));
+ vw_wait_tx(); // Wait until the whole message is gone
+ Serial.println("Sent");
+ digitalWrite(13, false);
+
+ // Wait at most 200ms for a reply
+ if (vw_wait_rx_max(200))
+ {
+ if (vw_get_message(buf, &buflen)) // Non-blocking
+ {
+ int i;
+
+ // Message with a good checksum received, dump it.
+ Serial.print("Got: ");
+
+ for (i = 0; i < buflen; i++)
+ {
+ Serial.print(buf[i], HEX);
+ Serial.print(" ");
+ }
+ Serial.println("");
+ }
+ }
+ else
+ Serial.println("Timout");
+
+}
--- /dev/null
+// receiver.pde
+//
+// Simple example of how to use VirtualWire to receive messages
+// Implements a simplex (one-way) receiver with an Rx-B1 module
+//
+// See VirtualWire.h for detailed API docs
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $
+
+#include <VirtualWire.h>
+
+void setup()
+{
+ Serial.begin(9600); // Debugging only
+ Serial.println("setup");
+
+ // Initialise the IO and ISR
+ vw_set_ptt_inverted(true); // Required for DR3100
+ vw_setup(2000); // Bits per sec
+
+ vw_rx_start(); // Start the receiver PLL running
+}
+
+void loop()
+{
+ uint8_t buf[VW_MAX_MESSAGE_LEN];
+ uint8_t buflen = VW_MAX_MESSAGE_LEN;
+
+ if (vw_get_message(buf, &buflen)) // Non-blocking
+ {
+ int i;
+
+ digitalWrite(13, true); // Flash a light to show received good message
+ // Message with a good checksum received, dump it.
+ Serial.print("Got: ");
+
+ for (i = 0; i < buflen; i++)
+ {
+ Serial.print(buf[i], HEX);
+ Serial.print(" ");
+ }
+ Serial.println("");
+ digitalWrite(13, false);
+ }
+}
--- /dev/null
+// server.pde
+//
+// Simple example of how to use VirtualWire to send and receive messages
+// with a DR3100 module.
+// Wait for a message from another arduino running the 'client' example,
+// and send a reply.
+// You can use this as the basis of a remote control/remote sensing system
+//
+// See VirtualWire.h for detailed API docs
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: server.pde,v 1.1 2008/04/20 09:24:17 mikem Exp $
+
+#include <VirtualWire.h>
+
+void setup()
+{
+ Serial.begin(9600); // Debugging only
+ Serial.println("setup");
+
+ // Initialise the IO and ISR
+ vw_set_ptt_inverted(true); // Required for DR3100
+ vw_setup(2000); // Bits per sec
+ vw_rx_start(); // Start the receiver PLL running
+}
+
+void loop()
+{
+ const char *msg = "hello";
+ uint8_t buf[VW_MAX_MESSAGE_LEN];
+ uint8_t buflen = VW_MAX_MESSAGE_LEN;
+
+ // Wait for a message
+ vw_wait_rx();
+ if (vw_get_message(buf, &buflen)) // Non-blocking
+ {
+ int i;
+ const char *msg = "goodbye";
+
+ digitalWrite(13, true); // Flash a light to show received good message
+ // Message with a good checksum received, dump it.
+ Serial.print("Got: ");
+
+ for (i = 0; i < buflen; i++)
+ {
+ Serial.print(buf[i], HEX);
+ Serial.print(" ");
+ }
+ Serial.println("");
+
+ // Send a reply
+ vw_send((uint8_t *)msg, strlen(msg));
+ digitalWrite(13, false);
+ }
+}
--- /dev/null
+// transmitter.pde
+//
+// Simple example of how to use VirtualWire to transmit messages
+// Implements a simplex (one-way) transmitter with an TX-C1 module
+//
+// See VirtualWire.h for detailed API docs
+// Author: Mike McCauley (mikem@airspayce.com)
+// Copyright (C) 2008 Mike McCauley
+// $Id: transmitter.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $
+
+#include <VirtualWire.h>
+
+void setup()
+{
+ Serial.begin(9600); // Debugging only
+ Serial.println("setup");
+
+ // Initialise the IO and ISR
+ vw_set_ptt_inverted(true); // Required for DR3100
+ vw_setup(2000); // Bits per sec
+}
+
+void loop()
+{
+ const char *msg = "hello";
+
+ digitalWrite(13, true); // Flash a light to show transmitting
+ vw_send((uint8_t *)msg, strlen(msg));
+ vw_wait_tx(); // Wait until the whole message is gone
+ digitalWrite(13, false);
+ delay(200);
+}
--- /dev/null
+VirtualWire KEYWORD1
+
--- /dev/null
+/* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
+ Copyright (c) 2005, 2007 Joerg Wunsch
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of the copyright holders nor the names of
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE. */
+
+// Port to Energia / MPS430 by Yannick DEVOS XV4Y - (c) 2013
+// http://xv4y.radioclub.asia/
+//
+
+/* $Id: crc16.h 2136 2010-06-08 12:03:38Z joerg_wunsch $ */
+
+#ifndef _UTIL_CRC16_H_
+#define _UTIL_CRC16_H_
+
+#include <stdint.h>
+
+#define lo8(x) ((x)&0xff)
+#define hi8(x) ((x)>>8)
+
+ uint16_t crc16_update(uint16_t crc, uint8_t a)
+ {
+ int i;
+
+ crc ^= a;
+ for (i = 0; i < 8; ++i)
+ {
+ if (crc & 1)
+ crc = (crc >> 1) ^ 0xA001;
+ else
+ crc = (crc >> 1);
+ }
+
+ return crc;
+ }
+
+ uint16_t crc_xmodem_update (uint16_t crc, uint8_t data)
+ {
+ int i;
+
+ crc = crc ^ ((uint16_t)data << 8);
+ for (i=0; i<8; i++)
+ {
+ if (crc & 0x8000)
+ crc = (crc << 1) ^ 0x1021;
+ else
+ crc <<= 1;
+ }
+
+ return crc;
+ }
+ uint16_t _crc_ccitt_update (uint16_t crc, uint8_t data)
+ {
+ data ^= lo8 (crc);
+ data ^= data << 4;
+
+ return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4)
+ ^ ((uint16_t)data << 3));
+ }
+
+ uint8_t _crc_ibutton_update(uint8_t crc, uint8_t data)
+ {
+ uint8_t i;
+
+ crc = crc ^ data;
+ for (i = 0; i < 8; i++)
+ {
+ if (crc & 0x01)
+ crc = (crc >> 1) ^ 0x8C;
+ else
+ crc >>= 1;
+ }
+
+ return crc;
+ }
+
+
+#endif /* _UTIL_CRC16_H_ */