PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

669 lines
18KB

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