PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

RH_ASK.cpp 26KB

3 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. // RH_ASK.cpp
  2. //
  3. // Copyright (C) 2014 Mike McCauley
  4. // $Id: RH_ASK.cpp,v 1.18 2016/07/07 00:02:53 mikem Exp mikem $
  5. #include <RH_ASK.h>
  6. #include <RHCRC.h>
  7. #if (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
  8. HardwareTimer timer(MAPLE_TIMER);
  9. #endif
  10. #if (RH_PLATFORM == RH_PLATFORM_ESP8266)
  11. // interrupt handler and related code must be in RAM on ESP8266,
  12. // according to issue #46.
  13. #define INTERRUPT_ATTR ICACHE_RAM_ATTR
  14. #else
  15. #define INTERRUPT_ATTR
  16. #endif
  17. // RH_ASK on Arduino uses Timer 1 to generate interrupts 8 times per bit interval
  18. // Define RH_ASK_ARDUINO_USE_TIMER2 if you want to use Timer 2 instead of Timer 1 on Arduino
  19. // You may need this to work around other librraies that insist on using timer 1
  20. // Should be moved to header file
  21. //#define RH_ASK_ARDUINO_USE_TIMER2
  22. // Interrupt handler uses this to find the most recently initialised instance of this driver
  23. static RH_ASK* thisASKDriver;
  24. // 4 bit to 6 bit symbol converter table
  25. // Used to convert the high and low nybbles of the transmitted data
  26. // into 6 bit symbols for transmission. Each 6-bit symbol has 3 1s and 3 0s
  27. // with at most 3 consecutive identical bits
  28. static uint8_t symbols[] =
  29. {
  30. 0xd, 0xe, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
  31. 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34
  32. };
  33. // This is the value of the start symbol after 6-bit conversion and nybble swapping
  34. #define RH_ASK_START_SYMBOL 0xb38
  35. RH_ASK::RH_ASK(uint16_t speed, uint8_t rxPin, uint8_t txPin, uint8_t pttPin, bool pttInverted)
  36. :
  37. _speed(speed),
  38. _rxPin(rxPin),
  39. _txPin(txPin),
  40. _pttPin(pttPin),
  41. _pttInverted(pttInverted)
  42. {
  43. // Initialise the first 8 nibbles of the tx buffer to be the standard
  44. // preamble. We will append messages after that. 0x38, 0x2c is the start symbol before
  45. // 6-bit conversion to RH_ASK_START_SYMBOL
  46. uint8_t preamble[RH_ASK_PREAMBLE_LEN] = {0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c};
  47. memcpy(_txBuf, preamble, sizeof(preamble));
  48. }
  49. bool RH_ASK::init()
  50. {
  51. if (!RHGenericDriver::init())
  52. return false;
  53. thisASKDriver = this;
  54. #if (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  55. #ifdef RH_ASK_PTT_PIN
  56. RH_ASK_PTT_DDR |= (1<<RH_ASK_PTT_PIN);
  57. RH_ASK_TX_DDR |= (1<<RH_ASK_TX_PIN);
  58. RH_ASK_RX_DDR &= ~(1<<RH_ASK_RX_PIN);
  59. #else
  60. RH_ASK_TX_DDR |= (1<<RH_ASK_TX_PIN);
  61. RH_ASK_RX_DDR &= ~(1<<RH_ASK_RX_PIN);
  62. #endif
  63. #else
  64. // Set up digital IO pins for arduino
  65. pinMode(_txPin, OUTPUT);
  66. pinMode(_rxPin, INPUT);
  67. pinMode(_pttPin, OUTPUT);
  68. #endif
  69. // Ready to go
  70. setModeIdle();
  71. timerSetup();
  72. return true;
  73. }
  74. // Put these prescaler structs in PROGMEM, not on the stack
  75. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  76. #if defined(RH_ASK_ARDUINO_USE_TIMER2)
  77. // Timer 2 has different prescalers
  78. PROGMEM static const uint16_t prescalers[] = {0, 1, 8, 32, 64, 128, 256, 3333};
  79. #else
  80. PROGMEM static const uint16_t prescalers[] = {0, 1, 8, 64, 256, 1024, 3333};
  81. #endif
  82. #define NUM_PRESCALERS (sizeof(prescalers) / sizeof( uint16_t))
  83. #endif
  84. // Common function for setting timer ticks @ prescaler values for speed
  85. // Returns prescaler index into {0, 1, 8, 64, 256, 1024} array
  86. // and sets nticks to compare-match value if lower than max_ticks
  87. // returns 0 & nticks = 0 on fault
  88. uint8_t RH_ASK::timerCalc(uint16_t speed, uint16_t max_ticks, uint16_t *nticks)
  89. {
  90. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  91. // Clock divider (prescaler) values - 0/3333: error flag
  92. uint8_t prescaler; // index into array & return bit value
  93. unsigned long ulticks; // calculate by ntick overflow
  94. // Div-by-zero protection
  95. if (speed == 0)
  96. {
  97. // signal fault
  98. *nticks = 0;
  99. return 0;
  100. }
  101. // test increasing prescaler (divisor), decreasing ulticks until no overflow
  102. // 1/Fraction of second needed to xmit one bit
  103. unsigned long inv_bit_time = ((unsigned long)speed) * 8;
  104. for (prescaler=1; prescaler < NUM_PRESCALERS; prescaler += 1)
  105. {
  106. // Integer arithmetic courtesy Jim Remington
  107. // 1/Amount of time per CPU clock tick (in seconds)
  108. uint16_t prescalerValue;
  109. memcpy_P(&prescalerValue, &prescalers[prescaler], sizeof(uint16_t));
  110. unsigned long inv_clock_time = F_CPU / ((unsigned long)prescalerValue);
  111. // number of prescaled ticks needed to handle bit time @ speed
  112. ulticks = inv_clock_time / inv_bit_time;
  113. // Test if ulticks fits in nticks bitwidth (with 1-tick safety margin)
  114. if ((ulticks > 1) && (ulticks < max_ticks))
  115. break; // found prescaler
  116. // Won't fit, check with next prescaler value
  117. }
  118. // Check for error
  119. if ((prescaler == 6) || (ulticks < 2) || (ulticks > max_ticks))
  120. {
  121. // signal fault
  122. *nticks = 0;
  123. return 0;
  124. }
  125. *nticks = ulticks;
  126. return prescaler;
  127. #else
  128. return 0; // not implemented or needed on other platforms
  129. #endif
  130. }
  131. // The idea here is to get 8 timer interrupts per bit period
  132. void RH_ASK::timerSetup()
  133. {
  134. #if (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  135. uint16_t nticks;
  136. uint8_t prescaler = timerCalc(_speed, (uint16_t)-1, &nticks);
  137. if (!prescaler) return;
  138. _COMB(TCCR,RH_ASK_TIMER_INDEX,A)= 0;
  139. _COMB(TCCR,RH_ASK_TIMER_INDEX,B)= _BV(WGM12);
  140. _COMB(TCCR,RH_ASK_TIMER_INDEX,B)|= prescaler;
  141. _COMB(OCR,RH_ASK_TIMER_INDEX,A)= nticks;
  142. _COMB(TI,MSK,RH_ASK_TIMER_INDEX)|= _BV(_COMB(OCIE,RH_ASK_TIMER_INDEX,A));
  143. #elif (RH_PLATFORM == RH_PLATFORM_MSP430) // LaunchPad specific
  144. // Calculate the counter overflow count based on the required bit speed
  145. // and CPU clock rate
  146. uint16_t ocr1a = (F_CPU / 8UL) / _speed;
  147. // This code is for Energia/MSP430
  148. TA0CCR0 = ocr1a; // Ticks for 62,5 us
  149. TA0CTL = TASSEL_2 + MC_1; // SMCLK, up mode
  150. TA0CCTL0 |= CCIE; // CCR0 interrupt enabled
  151. #elif (RH_PLATFORM == RH_PLATFORM_ARDUINO) // Arduino specific
  152. #if !(defined(__arm__) && defined(CORE_TEENSY) )
  153. uint16_t nticks; // number of prescaled ticks needed
  154. uint8_t prescaler; // Bit values for CS0[2:0]
  155. #endif
  156. #ifdef RH_PLATFORM_ATTINY
  157. // figure out prescaler value and counter match value
  158. // REVISIT: does not correctly handle 1MHz clock speeds, only works with 8MHz clocks
  159. // At 1MHz clock, get 1/8 of the expected baud rate
  160. prescaler = timerCalc(_speed, (uint8_t)-1, &nticks);
  161. if (!prescaler)
  162. return; // fault
  163. TCCR0A = 0;
  164. TCCR0A = _BV(WGM01); // Turn on CTC mode / Output Compare pins disconnected
  165. // convert prescaler index to TCCRnB prescaler bits CS00, CS01, CS02
  166. TCCR0B = 0;
  167. TCCR0B = prescaler; // set CS00, CS01, CS02 (other bits not needed)
  168. // Number of ticks to count before firing interrupt
  169. OCR0A = uint8_t(nticks);
  170. // Set mask to fire interrupt when OCF0A bit is set in TIFR0
  171. #ifdef TIMSK0
  172. // ATtiny84
  173. TIMSK0 |= _BV(OCIE0A);
  174. #else
  175. // ATtiny85
  176. TIMSK |= _BV(OCIE0A);
  177. #endif
  178. #elif defined(__arm__) && defined(CORE_TEENSY)
  179. // on Teensy 3.0 (32 bit ARM), use an interval timer
  180. IntervalTimer *t = new IntervalTimer();
  181. void TIMER1_COMPA_vect(void);
  182. t->begin(TIMER1_COMPA_vect, 125000 / _speed);
  183. #elif defined (__arm__) && defined(ARDUINO_ARCH_SAMD)
  184. // Arduino Zero
  185. #define RH_ASK_ZERO_TIMER TC3
  186. // Clock speed is 48MHz, prescaler of 64 gives a good range of available speeds vs precision
  187. #define RH_ASK_ZERO_PRESCALER 64
  188. #define RH_ASK_ZERO_TIMER_IRQ TC3_IRQn
  189. // Enable clock for TC
  190. REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TCC2_TC3)) ;
  191. while ( GCLK->STATUS.bit.SYNCBUSY == 1 ); // wait for sync
  192. // The type cast must fit with the selected timer mode
  193. TcCount16* TC = (TcCount16*)RH_ASK_ZERO_TIMER; // get timer struct
  194. TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; // Disable TC
  195. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  196. TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16; // Set Timer counter Mode to 16 bits
  197. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  198. TC->CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; // Set TC as Match Frequency
  199. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  200. // Compute the count required to achieve the requested baud (with 8 interrupts per bit)
  201. uint32_t rc = (VARIANT_MCK / _speed) / RH_ASK_ZERO_PRESCALER / 8;
  202. TC->CTRLA.reg |= TC_CTRLA_PRESCALER_DIV64; // Set prescaler to agree with RH_ASK_ZERO_PRESCALER
  203. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  204. TC->CC[0].reg = rc; // FIXME
  205. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  206. // Interrupts
  207. TC->INTENSET.reg = 0; // disable all interrupts
  208. TC->INTENSET.bit.MC0 = 1; // enable compare match to CC0
  209. // Enable InterruptVector
  210. NVIC_ClearPendingIRQ(RH_ASK_ZERO_TIMER_IRQ);
  211. NVIC_EnableIRQ(RH_ASK_ZERO_TIMER_IRQ);
  212. // Enable TC
  213. TC->CTRLA.reg |= TC_CTRLA_ENABLE;
  214. while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync
  215. #elif defined(__arm__) && defined(ARDUINO_SAM_DUE)
  216. // Arduino Due
  217. // Clock speed is 84MHz
  218. // Due has 9 timers in 3 blocks of 3.
  219. // We use timer 1 TC1_IRQn on TC0 channel 1, since timers 0, 2, 3, 4, 5 are used by the Servo library
  220. #define RH_ASK_DUE_TIMER TC0
  221. #define RH_ASK_DUE_TIMER_CHANNEL 1
  222. #define RH_ASK_DUE_TIMER_IRQ TC1_IRQn
  223. pmc_set_writeprotect(false);
  224. pmc_enable_periph_clk(RH_ASK_DUE_TIMER_IRQ);
  225. // Clock speed 4 can handle all reasonable _speeds we might ask for. Its divisor is 128
  226. // and we want 8 interrupts per bit
  227. uint32_t rc = (VARIANT_MCK / _speed) / 128 / 8;
  228. TC_Configure(RH_ASK_DUE_TIMER, RH_ASK_DUE_TIMER_CHANNEL,
  229. TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
  230. TC_SetRC(RH_ASK_DUE_TIMER, RH_ASK_DUE_TIMER_CHANNEL, rc);
  231. // Enable the RC Compare Interrupt
  232. RH_ASK_DUE_TIMER->TC_CHANNEL[RH_ASK_DUE_TIMER_CHANNEL].TC_IER = TC_IER_CPCS;
  233. NVIC_ClearPendingIRQ(RH_ASK_DUE_TIMER_IRQ);
  234. NVIC_EnableIRQ(RH_ASK_DUE_TIMER_IRQ);
  235. TC_Start(RH_ASK_DUE_TIMER, RH_ASK_DUE_TIMER_CHANNEL);
  236. #else
  237. // This is the path for most Arduinos
  238. // figure out prescaler value and counter match value
  239. #if defined(RH_ASK_ARDUINO_USE_TIMER2)
  240. prescaler = timerCalc(_speed, (uint8_t)-1, &nticks);
  241. if (!prescaler)
  242. return; // fault
  243. // Use timer 2
  244. TCCR2A = _BV(WGM21); // Turn on CTC mode)
  245. // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
  246. TCCR2B = prescaler;
  247. // Caution: special procedures for setting 16 bit regs
  248. // is handled by the compiler
  249. OCR2A = nticks;
  250. // Enable interrupt
  251. #ifdef TIMSK2
  252. // atmega168
  253. TIMSK2 |= _BV(OCIE2A);
  254. #else
  255. // others
  256. TIMSK |= _BV(OCIE2A);
  257. #endif // TIMSK2
  258. #else
  259. // Use timer 1
  260. prescaler = timerCalc(_speed, (uint16_t)-1, &nticks);
  261. if (!prescaler)
  262. return; // fault
  263. TCCR1A = 0; // Output Compare pins disconnected
  264. TCCR1B = _BV(WGM12); // Turn on CTC mode
  265. // convert prescaler index to TCCRnB prescaler bits CS10, CS11, CS12
  266. TCCR1B |= prescaler;
  267. // Caution: special procedures for setting 16 bit regs
  268. // is handled by the compiler
  269. OCR1A = nticks;
  270. // Enable interrupt
  271. #ifdef TIMSK1
  272. // atmega168
  273. TIMSK1 |= _BV(OCIE1A);
  274. #else
  275. // others
  276. TIMSK |= _BV(OCIE1A);
  277. #endif // TIMSK1
  278. #endif
  279. #endif
  280. #elif (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
  281. // Pause the timer while we're configuring it
  282. timer.pause();
  283. timer.setPeriod((1000000/8)/_speed);
  284. // Set up an interrupt on channel 1
  285. timer.setChannel1Mode(TIMER_OUTPUT_COMPARE);
  286. timer.setCompare(TIMER_CH1, 1); // Interrupt 1 count after each update
  287. void interrupt(); // defined below
  288. timer.attachCompare1Interrupt(interrupt);
  289. // Refresh the timer's count, prescale, and overflow
  290. timer.refresh();
  291. // Start the timer counting
  292. timer.resume();
  293. #elif (RH_PLATFORM == RH_PLATFORM_STM32F2) // Photon
  294. // Inspired by SparkIntervalTimer
  295. // We use Timer 6
  296. void TimerInterruptHandler(); // Forward declaration for interrupt handler
  297. #define SYSCORECLOCK 60000000UL // Timer clock tree uses core clock / 2
  298. TIM_TimeBaseInitTypeDef timerInitStructure;
  299. NVIC_InitTypeDef nvicStructure;
  300. TIM_TypeDef* TIMx;
  301. uint32_t period = (1000000 / 8) / _speed; // In microseconds
  302. uint16_t prescaler = (uint16_t)(SYSCORECLOCK / 1000000UL) - 1; //To get TIM counter clock = 1MHz
  303. attachSystemInterrupt(SysInterrupt_TIM6_Update, TimerInterruptHandler);
  304. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
  305. nvicStructure.NVIC_IRQChannel = TIM6_DAC_IRQn;
  306. TIMx = TIM6;
  307. nvicStructure.NVIC_IRQChannelPreemptionPriority = 10;
  308. nvicStructure.NVIC_IRQChannelSubPriority = 1;
  309. nvicStructure.NVIC_IRQChannelCmd = ENABLE;
  310. NVIC_Init(&nvicStructure);
  311. timerInitStructure.TIM_Prescaler = prescaler;
  312. timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  313. timerInitStructure.TIM_Period = period;
  314. timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  315. timerInitStructure.TIM_RepetitionCounter = 0;
  316. TIM_TimeBaseInit(TIMx, &timerInitStructure);
  317. TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE);
  318. TIM_Cmd(TIMx, ENABLE);
  319. #elif (RH_PLATFORM == RH_PLATFORM_CHIPKIT_CORE)
  320. // UsingChipKIT Core on Arduino IDE
  321. uint32_t chipkit_timer_interrupt_handler(uint32_t currentTime); // Forward declaration
  322. attachCoreTimerService(chipkit_timer_interrupt_handler);
  323. #elif (RH_PLATFORM == RH_PLATFORM_UNO32)
  324. // Under old MPIDE, which has been discontinued:
  325. // ON Uno32 we use timer1
  326. OpenTimer1(T1_ON | T1_PS_1_1 | T1_SOURCE_INT, (F_CPU / 8) / _speed);
  327. ConfigIntTimer1(T1_INT_ON | T1_INT_PRIOR_1);
  328. #elif (RH_PLATFORM == RH_PLATFORM_ESP8266)
  329. void INTERRUPT_ATTR esp8266_timer_interrupt_handler(); // Forward declarat
  330. // The - 120 is a heuristic to correct for interrupt handling overheads
  331. _timerIncrement = (clockCyclesPerMicrosecond() * 1000000 / 8 / _speed) - 120;
  332. timer0_isr_init();
  333. timer0_attachInterrupt(esp8266_timer_interrupt_handler);
  334. timer0_write(ESP.getCycleCount() + _timerIncrement);
  335. // timer0_write(ESP.getCycleCount() + 41660000);
  336. #endif
  337. }
  338. void INTERRUPT_ATTR RH_ASK::setModeIdle()
  339. {
  340. if (_mode != RHModeIdle)
  341. {
  342. // Disable the transmitter hardware
  343. writePtt(LOW);
  344. writeTx(LOW);
  345. _mode = RHModeIdle;
  346. }
  347. }
  348. void RH_ASK::setModeRx()
  349. {
  350. if (_mode != RHModeRx)
  351. {
  352. // Disable the transmitter hardware
  353. writePtt(LOW);
  354. writeTx(LOW);
  355. _mode = RHModeRx;
  356. }
  357. }
  358. void RH_ASK::setModeTx()
  359. {
  360. if (_mode != RHModeTx)
  361. {
  362. // PRepare state varibles for a new transmission
  363. _txIndex = 0;
  364. _txBit = 0;
  365. _txSample = 0;
  366. // Enable the transmitter hardware
  367. writePtt(HIGH);
  368. _mode = RHModeTx;
  369. }
  370. }
  371. // Call this often
  372. bool RH_ASK::available()
  373. {
  374. if (_mode == RHModeTx)
  375. return false;
  376. setModeRx();
  377. if (_rxBufFull)
  378. {
  379. validateRxBuf();
  380. _rxBufFull= false;
  381. }
  382. return _rxBufValid;
  383. }
  384. bool RH_ASK::recv(uint8_t* buf, uint8_t* len)
  385. {
  386. if (!available())
  387. return false;
  388. if (buf && len)
  389. {
  390. // Skip the length and 4 headers that are at the beginning of the rxBuf
  391. // and drop the trailing 2 bytes of FCS
  392. uint8_t message_len = _rxBufLen-RH_ASK_HEADER_LEN - 3;
  393. if (*len > message_len)
  394. *len = message_len;
  395. memcpy(buf, _rxBuf+RH_ASK_HEADER_LEN+1, *len);
  396. }
  397. _rxBufValid = false; // Got the most recent message, delete it
  398. // printBuffer("recv:", buf, *len);
  399. return true;
  400. }
  401. // Caution: this may block
  402. bool RH_ASK::send(const uint8_t* data, uint8_t len)
  403. {
  404. uint8_t i;
  405. uint16_t index = 0;
  406. uint16_t crc = 0xffff;
  407. uint8_t *p = _txBuf + RH_ASK_PREAMBLE_LEN; // start of the message area
  408. uint8_t count = len + 3 + RH_ASK_HEADER_LEN; // Added byte count and FCS and headers to get total number of bytes
  409. if (len > RH_ASK_MAX_MESSAGE_LEN)
  410. return false;
  411. // Wait for transmitter to become available
  412. waitPacketSent();
  413. // Encode the message length
  414. crc = RHcrc_ccitt_update(crc, count);
  415. p[index++] = symbols[count >> 4];
  416. p[index++] = symbols[count & 0xf];
  417. // Encode the headers
  418. crc = RHcrc_ccitt_update(crc, _txHeaderTo);
  419. p[index++] = symbols[_txHeaderTo >> 4];
  420. p[index++] = symbols[_txHeaderTo & 0xf];
  421. crc = RHcrc_ccitt_update(crc, _txHeaderFrom);
  422. p[index++] = symbols[_txHeaderFrom >> 4];
  423. p[index++] = symbols[_txHeaderFrom & 0xf];
  424. crc = RHcrc_ccitt_update(crc, _txHeaderId);
  425. p[index++] = symbols[_txHeaderId >> 4];
  426. p[index++] = symbols[_txHeaderId & 0xf];
  427. crc = RHcrc_ccitt_update(crc, _txHeaderFlags);
  428. p[index++] = symbols[_txHeaderFlags >> 4];
  429. p[index++] = symbols[_txHeaderFlags & 0xf];
  430. // Encode the message into 6 bit symbols. Each byte is converted into
  431. // 2 6-bit symbols, high nybble first, low nybble second
  432. for (i = 0; i < len; i++)
  433. {
  434. crc = RHcrc_ccitt_update(crc, data[i]);
  435. p[index++] = symbols[data[i] >> 4];
  436. p[index++] = symbols[data[i] & 0xf];
  437. }
  438. // Append the fcs, 16 bits before encoding (4 6-bit symbols after encoding)
  439. // Caution: VW expects the _ones_complement_ of the CCITT CRC-16 as the FCS
  440. // VW sends FCS as low byte then hi byte
  441. crc = ~crc;
  442. p[index++] = symbols[(crc >> 4) & 0xf];
  443. p[index++] = symbols[crc & 0xf];
  444. p[index++] = symbols[(crc >> 12) & 0xf];
  445. p[index++] = symbols[(crc >> 8) & 0xf];
  446. // Total number of 6-bit symbols to send
  447. _txBufLen = index + RH_ASK_PREAMBLE_LEN;
  448. // Start the low level interrupt handler sending symbols
  449. setModeTx();
  450. return true;
  451. }
  452. // Read the RX data input pin, taking into account platform type and inversion.
  453. bool INTERRUPT_ATTR RH_ASK::readRx()
  454. {
  455. bool value;
  456. #if (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  457. value = ((RH_ASK_RX_PORT & (1<<RH_ASK_RX_PIN)) ? 1 : 0);
  458. #else
  459. value = digitalRead(_rxPin);
  460. #endif
  461. return value ^ _rxInverted;
  462. }
  463. // Write the TX output pin, taking into account platform type.
  464. void INTERRUPT_ATTR RH_ASK::writeTx(bool value)
  465. {
  466. #if (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  467. ((value) ? (RH_ASK_TX_PORT |= (1<<RH_ASK_TX_PIN)) : (RH_ASK_TX_PORT &= ~(1<<RH_ASK_TX_PIN)));
  468. #else
  469. digitalWrite(_txPin, value);
  470. #endif
  471. }
  472. // Write the PTT output pin, taking into account platform type and inversion.
  473. void INTERRUPT_ATTR RH_ASK::writePtt(bool value)
  474. {
  475. #if (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  476. #if RH_ASK_PTT_PIN
  477. ((value) ? (RH_ASK_PTT_PORT |= (1<<RH_ASK_PTT_PIN)) : (RH_ASK_PTT_PORT &= ~(1<<RH_ASK_PTT_PIN)));
  478. #else
  479. ((value) ? (RH_ASK_TX_PORT |= (1<<RH_ASK_TX_PIN)) : (RH_ASK_TX_PORT &= ~(1<<RH_ASK_TX_PIN)));
  480. #endif
  481. #else
  482. digitalWrite(_pttPin, value ^ _pttInverted);
  483. #endif
  484. }
  485. uint8_t RH_ASK::maxMessageLength()
  486. {
  487. return RH_ASK_MAX_MESSAGE_LEN;
  488. }
  489. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
  490. #if defined(RH_PLATFORM_ATTINY)
  491. #define RH_ASK_TIMER_VECTOR TIM0_COMPA_vect
  492. #else // Assume Arduino Uno (328p or similar)
  493. #if defined(RH_ASK_ARDUINO_USE_TIMER2)
  494. #define RH_ASK_TIMER_VECTOR TIMER2_COMPA_vect
  495. #else
  496. #define RH_ASK_TIMER_VECTOR TIMER1_COMPA_vect
  497. #endif
  498. #endif
  499. #elif (RH_ASK_PLATFORM == RH_ASK_PLATFORM_GENERIC_AVR8)
  500. #define __COMB(a,b,c) (a##b##c)
  501. #define _COMB(a,b,c) __COMB(a,b,c)
  502. #define RH_ASK_TIMER_VECTOR _COMB(TIMER,RH_ASK_TIMER_INDEX,_COMPA_vect)
  503. #endif
  504. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(__arm__) && defined(CORE_TEENSY)
  505. void TIMER1_COMPA_vect(void)
  506. {
  507. thisASKDriver->handleTimerInterrupt();
  508. }
  509. #elif (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined (__arm__) && defined(ARDUINO_ARCH_SAMD)
  510. // Arduino Zero
  511. void TC3_Handler()
  512. {
  513. // The type cast must fit with the selected timer mode
  514. TcCount16* TC = (TcCount16*)RH_ASK_ZERO_TIMER; // get timer struct
  515. TC->INTFLAG.bit.MC0 = 1;
  516. thisASKDriver->handleTimerInterrupt();
  517. }
  518. #elif (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(__arm__) && defined(ARDUINO_SAM_DUE)
  519. // Arduino Due
  520. void TC1_Handler()
  521. {
  522. TC_GetStatus(RH_ASK_DUE_TIMER, 1);
  523. thisASKDriver->handleTimerInterrupt();
  524. }
  525. #elif (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_GENERIC_AVR8)
  526. // This is the interrupt service routine called when timer1 overflows
  527. // Its job is to output the next bit from the transmitter (every 8 calls)
  528. // and to call the PLL code if the receiver is enabled
  529. //ISR(SIG_OUTPUT_COMPARE1A)
  530. ISR(RH_ASK_TIMER_VECTOR)
  531. {
  532. thisASKDriver->handleTimerInterrupt();
  533. }
  534. #elif (RH_PLATFORM == RH_PLATFORM_MSP430) || (RH_PLATFORM == RH_PLATFORM_STM32)
  535. // LaunchPad, Maple
  536. void interrupt()
  537. {
  538. thisASKDriver->handleTimerInterrupt();
  539. }
  540. #elif (RH_PLATFORM == RH_PLATFORM_STM32F2) // Photon
  541. void TimerInterruptHandler()
  542. {
  543. thisASKDriver->handleTimerInterrupt();
  544. }
  545. #elif (RH_PLATFORM == RH_PLATFORM_MSP430)
  546. interrupt(TIMER0_A0_VECTOR) Timer_A_int(void)
  547. {
  548. thisASKDriver->handleTimerInterrupt();
  549. };
  550. #elif (RH_PLATFORM == RH_PLATFORM_CHIPKIT_CORE)
  551. // Using ChipKIT Core on Arduino IDE
  552. uint32_t chipkit_timer_interrupt_handler(uint32_t currentTime)
  553. {
  554. thisASKDriver->handleTimerInterrupt();
  555. return (currentTime + ((CORE_TICK_RATE * 1000)/8)/thisASKDriver->speed());
  556. }
  557. #elif (RH_PLATFORM == RH_PLATFORM_UNO32)
  558. // Under old MPIDE, which has been discontinued:
  559. extern "C"
  560. {
  561. void __ISR(_TIMER_1_VECTOR, ipl1) timerInterrupt(void)
  562. {
  563. thisASKDriver->handleTimerInterrupt();
  564. mT1ClearIntFlag(); // Clear timer 1 interrupt flag
  565. }
  566. }
  567. #elif (RH_PLATFORM == RH_PLATFORM_ESP8266)
  568. void INTERRUPT_ATTR esp8266_timer_interrupt_handler()
  569. {
  570. // timer0_write(ESP.getCycleCount() + 41660000);
  571. // timer0_write(ESP.getCycleCount() + (clockCyclesPerMicrosecond() * 100) - 120 );
  572. timer0_write(ESP.getCycleCount() + thisASKDriver->_timerIncrement);
  573. // static int toggle = 0;
  574. // toggle = (toggle == 1) ? 0 : 1;
  575. // digitalWrite(4, toggle);
  576. thisASKDriver->handleTimerInterrupt();
  577. }
  578. #endif
  579. // Convert a 6 bit encoded symbol into its 4 bit decoded equivalent
  580. uint8_t INTERRUPT_ATTR RH_ASK::symbol_6to4(uint8_t symbol)
  581. {
  582. uint8_t i;
  583. uint8_t count;
  584. // Linear search :-( Could have a 64 byte reverse lookup table?
  585. // There is a little speedup here courtesy Ralph Doncaster:
  586. // The shortcut works because bit 5 of the symbol is 1 for the last 8
  587. // symbols, and it is 0 for the first 8.
  588. // So we only have to search half the table
  589. for (i = (symbol>>2) & 8, count=8; count-- ; i++)
  590. if (symbol == symbols[i]) return i;
  591. return 0; // Not found
  592. }
  593. // Check whether the latest received message is complete and uncorrupted
  594. // We should always check the FCS at user level, not interrupt level
  595. // since it is slow
  596. void RH_ASK::validateRxBuf()
  597. {
  598. uint16_t crc = 0xffff;
  599. // The CRC covers the byte count, headers and user data
  600. for (uint8_t i = 0; i < _rxBufLen; i++)
  601. crc = RHcrc_ccitt_update(crc, _rxBuf[i]);
  602. if (crc != 0xf0b8) // CRC when buffer and expected CRC are CRC'd
  603. {
  604. // Reject and drop the message
  605. _rxBad++;
  606. _rxBufValid = false;
  607. return;
  608. }
  609. // Extract the 4 headers that follow the message length
  610. _rxHeaderTo = _rxBuf[1];
  611. _rxHeaderFrom = _rxBuf[2];
  612. _rxHeaderId = _rxBuf[3];
  613. _rxHeaderFlags = _rxBuf[4];
  614. if (_promiscuous ||
  615. _rxHeaderTo == _thisAddress ||
  616. _rxHeaderTo == RH_BROADCAST_ADDRESS)
  617. {
  618. _rxGood++;
  619. _rxBufValid = true;
  620. }
  621. }
  622. void INTERRUPT_ATTR RH_ASK::receiveTimer()
  623. {
  624. bool rxSample = readRx();
  625. // Integrate each sample
  626. if (rxSample)
  627. _rxIntegrator++;
  628. if (rxSample != _rxLastSample)
  629. {
  630. // Transition, advance if ramp > 80, retard if < 80
  631. _rxPllRamp += ((_rxPllRamp < RH_ASK_RAMP_TRANSITION)
  632. ? RH_ASK_RAMP_INC_RETARD
  633. : RH_ASK_RAMP_INC_ADVANCE);
  634. _rxLastSample = rxSample;
  635. }
  636. else
  637. {
  638. // No transition
  639. // Advance ramp by standard 20 (== 160/8 samples)
  640. _rxPllRamp += RH_ASK_RAMP_INC;
  641. }
  642. if (_rxPllRamp >= RH_ASK_RX_RAMP_LEN)
  643. {
  644. // Add this to the 12th bit of _rxBits, LSB first
  645. // The last 12 bits are kept
  646. _rxBits >>= 1;
  647. // Check the integrator to see how many samples in this cycle were high.
  648. // If < 5 out of 8, then its declared a 0 bit, else a 1;
  649. if (_rxIntegrator >= 5)
  650. _rxBits |= 0x800;
  651. _rxPllRamp -= RH_ASK_RX_RAMP_LEN;
  652. _rxIntegrator = 0; // Clear the integral for the next cycle
  653. if (_rxActive)
  654. {
  655. // We have the start symbol and now we are collecting message bits,
  656. // 6 per symbol, each which has to be decoded to 4 bits
  657. if (++_rxBitCount >= 12)
  658. {
  659. // Have 12 bits of encoded message == 1 byte encoded
  660. // Decode as 2 lots of 6 bits into 2 lots of 4 bits
  661. // The 6 lsbits are the high nybble
  662. uint8_t this_byte =
  663. (symbol_6to4(_rxBits & 0x3f)) << 4
  664. | symbol_6to4(_rxBits >> 6);
  665. // The first decoded byte is the byte count of the following message
  666. // the count includes the byte count and the 2 trailing FCS bytes
  667. // REVISIT: may also include the ACK flag at 0x40
  668. if (_rxBufLen == 0)
  669. {
  670. // The first byte is the byte count
  671. // Check it for sensibility. It cant be less than 7, since it
  672. // includes the byte count itself, the 4 byte header and the 2 byte FCS
  673. _rxCount = this_byte;
  674. if (_rxCount < 7 || _rxCount > RH_ASK_MAX_PAYLOAD_LEN)
  675. {
  676. // Stupid message length, drop the whole thing
  677. _rxActive = false;
  678. _rxBad++;
  679. return;
  680. }
  681. }
  682. _rxBuf[_rxBufLen++] = this_byte;
  683. if (_rxBufLen >= _rxCount)
  684. {
  685. // Got all the bytes now
  686. _rxActive = false;
  687. _rxBufFull = true;
  688. setModeIdle();
  689. }
  690. _rxBitCount = 0;
  691. }
  692. }
  693. // Not in a message, see if we have a start symbol
  694. else if (_rxBits == RH_ASK_START_SYMBOL)
  695. {
  696. // Have start symbol, start collecting message
  697. _rxActive = true;
  698. _rxBitCount = 0;
  699. _rxBufLen = 0;
  700. }
  701. }
  702. }
  703. void INTERRUPT_ATTR RH_ASK::transmitTimer()
  704. {
  705. if (_txSample++ == 0)
  706. {
  707. // Send next bit
  708. // Symbols are sent LSB first
  709. // Finished sending the whole message? (after waiting one bit period
  710. // since the last bit)
  711. if (_txIndex >= _txBufLen)
  712. {
  713. setModeIdle();
  714. _txGood++;
  715. }
  716. else
  717. {
  718. writeTx(_txBuf[_txIndex] & (1 << _txBit++));
  719. if (_txBit >= 6)
  720. {
  721. _txBit = 0;
  722. _txIndex++;
  723. }
  724. }
  725. }
  726. if (_txSample > 7)
  727. _txSample = 0;
  728. }
  729. void INTERRUPT_ATTR RH_ASK::handleTimerInterrupt()
  730. {
  731. if (_mode == RHModeRx)
  732. receiveTimer(); // Receiving
  733. else if (_mode == RHModeTx)
  734. transmitTimer(); // Transmitting
  735. }