This repository has been archived by the owner on Feb 21, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
VirtualWire.h
451 lines (414 loc) · 20 KB
/
VirtualWire.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
// VirtualWire.h
//
// Virtual Wire implementation for Arduino and other boards
// See the README file in this directory for documentation
//
// Author: Mike McCauley ([email protected]) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS
// Copyright (C) 2008 Mike McCauley
// $Id: VirtualWire.h,v 1.14 2014/03/26 01:09:36 mikem Exp mikem $
/// \mainpage VirtualWire library for Arduino and other boards
///
/// This is the VirtualWire library.
///
/// \par END OF LIFE NOTICE
///
/// This VirtualWire library has now been superceded by the RadioHead
/// library http://www.airspayce.com/mikem/arduino/RadioHead
/// RadioHead and its RH_ASK driver provides all the features supported by VirtualWire, and much more
/// besides, including Reliable Datagrams, Addressing, Routing and Meshes. All the platforms that
/// VirtualWire supported are also supported by RadioHead.
///
/// This library will no longer be maintained or updated, but we will continue to publish
/// it for the benefit of the the community. Nevertheless we recommend upgrading to RadioHead where
/// possible.
///
/// VirtualWire is a 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.
///
/// But 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.27.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.
/// Before asking a question or reporting a bug, please read http://www.catb.org/esr/faqs/smart-questions.html
///
/// \par Theory of operation
///
/// See ASH Transceiver Software Designer's Guide of 2002.08.07
/// http://www.rfm.com/products/apnotes/tr_swg05.pdf
///
/// \par Supported Hardware
///
/// A range of communications
/// hardware is supported. The ones listed below are available in common retail
/// outlets in Australia and other countries for under $10 per unit. Many
/// other modules may also work with this software.
///
/// Runs on a wide range of Arduino processors using Arduino IDE 1.0 or later.
/// 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 and 3.1 (courtesy of Paul
/// Stoffregen) using the Arduino IDE 1.0.5 and the Teensyduino addon 1.18.
/// 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. Runs on ATmega8/168 (Arduino Diecimila,
/// Uno etc), ATmega328 and can run on almost any other AVR8 platform,
/// without relying on the Arduino framework, by properly configuring the
/// library using 'VirtualWire_Config.h' header file for describing the access
/// to IO pins and for setting up the timer. From version 1.22 the library can
/// be compiled by a C compiler (by renaming VirtualWire.cpp into
/// VirtualWire.c) and can be easily integrated with other IDEs like 'Atmel
/// Studio' for example (courtesy of Alexandru Mircescu).
///
/// - 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>
/// <pre>
/// Arduino 1 wires Arduino 1
/// D11-----------------------------D12
/// D12-----------------------------D11
/// GND-----------------------------GND
/// </pre>
/// </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.
///
/// Caution: ATTiny85 has only 2 timers, one (timer 0) usually used for
/// millis() and one (timer 1) for PWM analog outputs. The VirtualWire
/// library, when built for ATTiny85, takes over timer 0, which prevents use
/// of millis() etc but does permit analog outputs.
///
/// \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 Donations
///
/// This library is offered under a free GPL license for those who want to use it that way.
/// We try hard to keep it up to date, fix bugs
/// and to provide free support. If this library has helped you save time or money, please consider donating at
/// http://www.airspayce.com or here:
///
/// \htmlonly <form action="https://www.paypal.com/cgi-bin/webscr" method="post"><input type="hidden" name="cmd" value="_donations" /> <input type="hidden" name="business" value="[email protected]" /> <input type="hidden" name="lc" value="AU" /> <input type="hidden" name="item_name" value="Airspayce" /> <input type="hidden" name="item_number" value="VirtualWire" /> <input type="hidden" name="currency_code" value="USD" /> <input type="hidden" name="bn" value="PP-DonationsBF:btn_donateCC_LG.gif:NonHosted" /> <input type="image" alt="PayPal — The safer, easier way to pay online." name="submit" src="https://www.paypalobjects.com/en_AU/i/btn/btn_donateCC_LG.gif" /> <img alt="" src="https://www.paypalobjects.com/en_AU/i/scr/pixel.gif" width="1" height="1" border="0" /></form> \endhtmlonly
///
/// \par Trademarks
///
/// VirtualWire is a trademark of AirSpayce Pty Ltd. The VirtualWire mark was first used on April 20 2008 for
/// international trade, and is used only in relation to data communications hardware and software and related services.
/// It is not to be confused with any other similar marks covering other goods and services.
///
/// \par Copyright
///
/// This software is Copyright (C) 2011-2014 Mike McCauley. Use is subject to license
/// conditions. The main licensing options available are GPL V2 or Commercial:
///
/// \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 [email protected] 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()
/// \version 1.20 Added support for ATtiny84, patched by Chuck Benedict.
/// \version 1.21 Added support for most AVR8 platforms with proper configuration, without depending
/// on Arduino environment, such as Atmega32u2, Atmega32U4, At90USB162 etc,
/// contributed by Alexandru Daniel Mircescu.
/// \version 1.22 Alexandru Daniel Mircescu fixed some problems with the recently added AtMega32U2 support.
/// \version 1.23 Fixed some errors and inaccuracies in documentation, with the kind assistance of Alexandru
/// Mircescu.
/// \version 1.24 Minor performance improvement to vw_symbol_6to4() courtesy Ralph Doncaster.
/// \version 1.25 Removed all use of floating point code, with assistance of a patch from Jim Remington.
/// Result is smaller code size.
/// \version 1.26 Removed util/crc16.h from distribution, since it is now included in arduino IDE
/// since version 1.0. Support for arduino IDE prior to 1.0 is now abandoned.
/// \version 1.27 Reinstated VWutil/crc16.h for the benefit of other platforms such as Teensy.
/// Testing on Teensy 3.1. Added End Of Life notice. This library will no longer be maintained
/// and updated: use RadioHead instead.
///
/// \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 <stdint.h>
#include "VirtualWire_Config.h"
// Currently supported platforms
#define VW_PLATFORM_ARDUINO 1
#define VW_PLATFORM_MSP430 2
#define VW_PLATFORM_STM32 3
#define VW_PLATFORM_GENERIC_AVR8 4
#define VW_PLATFORM_UNO32 5
// Select platform automatically, if possible
#ifndef VW_PLATFORM
#if defined(ARDUINO)
#define VW_PLATFORM VW_PLATFORM_ARDUINO
#elif defined(__MSP430G2452__) || defined(__MSP430G2553__)
#define VW_PLATFORM VW_PLATFORM_MSP430
#elif defined(MCU_STM32F103RE)
#define VW_PLATFORM VW_PLATFORM_STM32
#elif defined MPIDE
#define VW_PLATFORM VW_PLATFORM_UNO32
#else
#error Platform not defined!
#endif
#endif
#if (VW_PLATFORM == VW_PLATFORM_ARDUINO)
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <wiring.h>
#endif
#elif (VW_PLATFORM == VW_PLATFORM_MSP430)// LaunchPad specific
#include "legacymsp430.h"
#include "Energia.h"
#elif (VW_PLATFORM == VW_PLATFORM_STM32) // Maple etc
#include <stdint.h>
// Defines which timer to use on Maple
#define MAPLE_TIMER 1
#elif (VW_PLATFORM == VW_PLATFORM_UNO32)
#elif (VW_PLATFORM != VW_PLATFORM_GENERIC_AVR8)
#error Platform unknown!
#endif
// These defs cause trouble on some versions of Arduino
#undef abs
#undef double
#undef round
#ifndef VW_MAX_MESSAGE_LEN
/// Maximum number of bytes in a message, counting the byte count and FCS
#define VW_MAX_MESSAGE_LEN 80
#endif //VW_MAX_MESSAGE_LEN
#if !defined(VW_RX_SAMPLES_PER_BIT)
/// Number of samples per bit
#define VW_RX_SAMPLES_PER_BIT 8
#endif //VW_RX_SAMPLES_PER_BIT
/// The maximum payload length
#define VW_MAX_PAYLOAD VW_MAX_MESSAGE_LEN-3
/// The size of the receiver ramp. Ramp wraps modulo this number
#define VW_RX_RAMP_LEN 160
// 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
#ifdef __cplusplus
extern "C"
{
#endif //__cplusplus
#if (VW_PLATFORM != VW_PLATFORM_GENERIC_AVR8 )
// Set the digital IO pin which will be used 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);
/// 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);
#endif
/// 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);
/// 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();
#ifdef __cplusplus
} // extern "C"
#endif //__cplusplus
/// @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 /* VirtualWire_h */