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