switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

View File

@@ -0,0 +1 @@
See VirtulWire.h for latest change log

View File

@@ -0,0 +1,17 @@
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.

View File

@@ -0,0 +1,14 @@
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

View File

@@ -0,0 +1,26 @@
# 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.15.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/

View File

@@ -0,0 +1,8 @@
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.

View File

@@ -0,0 +1,662 @@
// 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.9 2013/02/14 22:02:11 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"
#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;
// 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
};
// This new feature allows to call an external function from the timer interrupt (interesting for small microcontroller without many timers)
static void (*_Funct)(void)=NULL;
// 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 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
}
}
}
// Common function for setting timer ticks @ prescaler values for speed
// Returns prescaler index into {0, 0, 3, 6, 8, 10, 12} array
// and sets nticks to compare-match value if lower than max_ticks
// returns 0 & nticks = 0 on fault
uint8_t prescalers[] PROGMEM = {0, 0, 3, 6, 8, 10, 12}; /* Must be outside the function */
uint8_t _timer_calc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
{
// Clock divider (prescaler) values - 0/4096: error flag
/* Trick: use power of 2 rather than divisor values: only uint8_t table needed */
uint8_t prescaler=0; // index into array & return bit value
uint32_t 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)
{
/* Trick: compute in frequency domain rather than in time domain: no need of floats */
// Amount of time per CPU clock tick (in seconds)
uint32_t clock_freq = F_CPU >> (uint8_t)pgm_read_byte(&prescalers[prescaler]);
// Fraction of second needed to xmit one bit
uint32_t bit_freq = (uint32_t)speed << 3;/* 8 samples */
// number of prescaled ticks needed to handle bit time @ speed
ulticks = clock_freq / bit_freq;
// 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 < 2UL) || (ulticks > (uint32_t)max_ticks))
{
// signal fault
*nticks = 0;
return 0;
}
*nticks = (uint16_t)ulticks;
return prescaler;
}
// 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
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);
#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);
}
#endif // ARDUINO
// Declare an external function to call in the timer interruption
void vw_declare_timer_Ovf_funct(void (*Funct)(void))
{
uint8_t oldSREG = SREG;
cli();
_Funct=Funct;
SREG = oldSREG;
}
// 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 vx_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?
}
// 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__
ISR(TIM0_COMPA_vect, ISR_NOBLOCK)
#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);
// 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();
//PL{
if(_Funct) _Funct();
//PL}
}
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__) // LaunchPad specific
void vw_Int_Handler()
{
if (vw_rx_enabled && !vw_tx_enabled)
vw_rx_sample = digitalRead(vw_rx_pin);
// 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();
}
interrupt(TIMER0_A0_VECTOR) Timer_A_int(void)
{
vw_Int_Handler();
};
#endif
}

View File

@@ -0,0 +1,297 @@
// VirtualWire.h
//
// Virtual Wire implementation for Arduino
// See the README file in this directory fdor 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.6 2013/02/14 22:02:11 mikem Exp mikem $
/// \mainpage VirtualWire library for Arduino
///
/// This is the Arduino VirtualWire library.
///
/// VirtualWire is an Arduino library 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.
///
/// 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 the Arduino 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.15.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 blow 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).
/// Also compiles and runs on ATtiny85 in Arduino environment, courtesy r4z0r7o3.
///
/// - Receivers
/// - RX-B1 (433.92MHz) (also known as ST-RX04-ASK)
/// - Transmitters:
/// - TX-C1 (433.92MHz)
/// - Transceivers
/// - DR3100 (433.92MHz)
///
/// \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
///
/// \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"
#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 30
/// 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);
// 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 vx_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);
/// Declare an external function to call when the timer overflows.
/// \param[in] Funct Pointer to the function to call when timer overflows (eg: Software PWM management function)
extern void vw_declare_timer_Ovf_funct(void (*Funct)(void));
}
/// @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

View File

@@ -0,0 +1,59 @@
// 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");
}

View File

@@ -0,0 +1,46 @@
// 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);
}
}

View File

@@ -0,0 +1,55 @@
// 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);
}
}

View File

@@ -0,0 +1,32 @@
// 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);
}

View File

@@ -0,0 +1,2 @@
VirtualWire KEYWORD1

View File

@@ -0,0 +1,103 @@
/* 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_ */