PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

667 lines
18KB

  1. /* FreqCount Library, for measuring frequencies
  2. * http://www.pjrc.com/teensy/td_libs_FreqCount.html
  3. * Copyright (c) 2014 PJRC.COM, LLC - Paul Stoffregen <paul@pjrc.com>
  4. *
  5. * Version 1.1
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #ifndef FreqCount_timers_h_
  26. #define FreqCount_timers_h_
  27. static uint32_t count_prev;
  28. static volatile uint32_t count_output;
  29. static volatile uint8_t count_ready;
  30. static volatile uint32_t usec;
  31. // Arduino Mega
  32. #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  33. // #define COUNTER_USE_TIMER1 // T1 is not connected
  34. // #define COUNTER_USE_TIMER3 // T3 is not connected
  35. // #define COUNTER_USE_TIMER4 // T4 is not connected
  36. #define COUNTER_USE_TIMER5 // T5 is pin 47
  37. #define TIMER_USE_TIMER2
  38. //Teensy 4.0
  39. #elif defined(__IMXRT1062__)
  40. IMXRT_TMR_t * TMRx = (IMXRT_TMR_t *)&IMXRT_TMR4;
  41. #define COUNTER_USE_QT4
  42. #define TIMER_USE_INTERVALTIMER_T4
  43. // Teensy 3.0 & 3.1 & LC
  44. #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
  45. #define COUNTER_USE_LPTMR // LPTMR is pin 13 (has LED connected)
  46. #define TIMER_USE_INTERVALTIMER
  47. // Teensy 2.0
  48. #elif defined(__AVR_ATmega32U4__)
  49. #define COUNTER_USE_TIMER1 // T1 is pin 11 (has LED connected)
  50. #define TIMER_USE_TIMER4H
  51. // Teensy++ 1.0 & 2.0
  52. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  53. #define COUNTER_USE_TIMER1 // T1 is pin 6 (has LED connected)
  54. //#define COUNTER_USE_TIMER3 // T3 is pin 13
  55. #define TIMER_USE_TIMER2
  56. // Sanguino
  57. #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
  58. #define COUNTER_USE_TIMER1 // T1 is pin 1
  59. #define TIMER_USE_TIMER2
  60. // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
  61. #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
  62. #define COUNTER_USE_TIMER1 // T1 is pin 5
  63. #define TIMER_USE_TIMER2
  64. #else
  65. #error "Unknown chip, please edit me with timer+counter definitions"
  66. #endif
  67. /**********************************************/
  68. /* Counter Hardware Abstraction */
  69. /**********************************************/
  70. #if defined(COUNTER_USE_LPTMR) // 16 bit LPTMR on Freescale Kinetis
  71. static inline void counter_init(void)
  72. {
  73. SIM_SCGC5 |= SIM_SCGC5_LPTIMER;
  74. LPTMR0_CSR = 0;
  75. LPTMR0_PSR = 0b00000100; // bypass prescaler/filter
  76. LPTMR0_CMR = 0xFFFF;
  77. LPTMR0_CSR = 0b00100110; // counter, input=alt2, free running mode
  78. CORE_PIN13_CONFIG = PORT_PCR_MUX(3);
  79. }
  80. static inline void counter_start(void)
  81. {
  82. LPTMR0_CSR = 0b00100111; // enable
  83. }
  84. static inline void counter_shutdown(void)
  85. {
  86. LPTMR0_CSR = 0;
  87. }
  88. static inline uint16_t counter_read(void)
  89. {
  90. LPTMR0_CNR = 0; // writing cause sync with hardware
  91. return LPTMR0_CNR;
  92. }
  93. static inline uint8_t counter_overflow(void)
  94. {
  95. return (LPTMR0_CSR & 0x80) ? 1 : 0;
  96. }
  97. static inline void counter_overflow_reset(void)
  98. {
  99. LPTMR0_CSR = 0b10100111;
  100. }
  101. #elif defined(COUNTER_USE_QT4)
  102. static inline void counter_init(void)
  103. {
  104. CCM_CCGR6 |= CCM_CCGR6_QTIMER4(CCM_CCGR_ON); //enable QTMR4
  105. IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11 = 1; // QT4 Timer2 on pin 9
  106. int cnt = 65536 ; // full cycle
  107. TMRx->CH[2].CTRL = 0; // stop
  108. TMRx->CH[2].CNTR = 0;
  109. TMRx->CH[2].LOAD = 0; // start val after compare
  110. TMRx->CH[2].COMP1 = cnt - 1; // count up to this val and start again
  111. TMRx->CH[2].CMPLD1 = cnt - 1;
  112. TMRx->CH[2].SCTRL = 0;
  113. TMRx->CH[3].CTRL = 0; // stop
  114. TMRx->CH[3].CNTR = 0;
  115. TMRx->CH[3].LOAD = 0; // start val after compare
  116. TMRx->CH[3].COMP1 = 0;
  117. TMRx->CH[3].CMPLD1 = 0;
  118. TMRx->CH[3].CTRL = TMR_CTRL_CM(7) | TMR_CTRL_PCS(6); //clock from clock 2
  119. TMRx->CH[2].CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(2) | TMR_CTRL_LENGTH ;
  120. }
  121. #elif defined(COUNTER_USE_TIMER1) // 16 bit Timer 1 on Atmel AVR
  122. static uint8_t saveTCCR1A, saveTCCR1B;
  123. static inline void counter_init(void)
  124. {
  125. saveTCCR1A = TCCR1A;
  126. saveTCCR1B = TCCR1B;
  127. TCCR1B = 0;
  128. TCCR1A = 0;
  129. TCNT1 = 0;
  130. TIFR1 = (1<<TOV1);
  131. TIMSK1 = 0;
  132. }
  133. static inline void counter_start(void)
  134. {
  135. TCCR1B = (1<<CS12) | (1<<CS11) | (1<<CS10);
  136. }
  137. static inline void counter_shutdown(void)
  138. {
  139. TCCR1B = 0;
  140. TCCR1A = saveTCCR1A;
  141. TCCR1B = saveTCCR1B;
  142. }
  143. static inline uint16_t counter_read(void)
  144. {
  145. return TCNT1;
  146. }
  147. static inline uint8_t counter_overflow(void)
  148. {
  149. return TIFR1 & (1<<TOV1);
  150. }
  151. static inline void counter_overflow_reset(void)
  152. {
  153. TIFR1 = (1<<TOV1);
  154. }
  155. #elif defined(COUNTER_USE_TIMER3) // 16 bit Timer 3 on Atmel AVR
  156. static uint8_t saveTCCR3A, saveTCCR3B;
  157. static inline void counter_init(void)
  158. {
  159. saveTCCR3A = TCCR3A;
  160. saveTCCR3B = TCCR3B;
  161. TCCR3B = 0;
  162. TCCR3A = 0;
  163. TCNT3 = 0;
  164. TIFR3 = (1<<TOV3);
  165. TIMSK3 = 0;
  166. }
  167. static inline void counter_start(void)
  168. {
  169. TCCR3B = (1<<CS32) | (1<<CS31) | (1<<CS30);
  170. }
  171. static inline void counter_shutdown(void)
  172. {
  173. TCCR3B = 0;
  174. TCCR3A = saveTCCR3A;
  175. TCCR3B = saveTCCR3B;
  176. }
  177. static inline uint16_t counter_read(void)
  178. {
  179. return TCNT3;
  180. }
  181. static inline uint8_t counter_overflow(void)
  182. {
  183. return TIFR3 & (1<<TOV3);
  184. }
  185. static inline void counter_overflow_reset(void)
  186. {
  187. TIFR3 = (1<<TOV3);
  188. }
  189. #elif defined(COUNTER_USE_TIMER4) // 16 bit Timer 4 on Atmel AVR
  190. static uint8_t saveTCCR4A, saveTCCR4B;
  191. static inline void counter_init(void)
  192. {
  193. saveTCCR4A = TCCR4A;
  194. saveTCCR4B = TCCR4B;
  195. TCCR4B = 0;
  196. TCCR4A = 0;
  197. TCNT4 = 0;
  198. TIFR4 = (1<<TOV4);
  199. TIMSK4 = 0;
  200. }
  201. static inline void counter_start(void)
  202. {
  203. TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40);
  204. }
  205. static inline void counter_shutdown(void)
  206. {
  207. TCCR4B = 0;
  208. TCCR4A = saveTCCR4A;
  209. TCCR4B = saveTCCR4B;
  210. }
  211. static inline uint16_t counter_read(void)
  212. {
  213. return TCNT4;
  214. }
  215. static inline uint8_t counter_overflow(void)
  216. {
  217. return TIFR4 & (1<<TOV4);
  218. }
  219. static inline void counter_overflow_reset(void)
  220. {
  221. TIFR4 = (1<<TOV4);
  222. }
  223. #elif defined(COUNTER_USE_TIMER5) // 16 bit Timer 5 on Atmel AVR
  224. static uint8_t saveTCCR5A, saveTCCR5B;
  225. static inline void counter_init(void)
  226. {
  227. saveTCCR5A = TCCR5A;
  228. saveTCCR5B = TCCR5B;
  229. TCCR5B = 0;
  230. TCCR5A = 0;
  231. TCNT5 = 0;
  232. TIFR5 = (1<<TOV5);
  233. TIMSK5 = 0;
  234. }
  235. static inline void counter_start(void)
  236. {
  237. TCCR5B = (1<<CS52) | (1<<CS51) | (1<<CS50);
  238. }
  239. static inline void counter_shutdown(void)
  240. {
  241. TCCR5B = 0;
  242. TCCR5A = saveTCCR5A;
  243. TCCR5B = saveTCCR5B;
  244. }
  245. static inline uint16_t counter_read(void)
  246. {
  247. return TCNT5;
  248. }
  249. static inline uint8_t counter_overflow(void)
  250. {
  251. return TIFR5 & (1<<TOV5);
  252. }
  253. static inline void counter_overflow_reset(void)
  254. {
  255. TIFR5 = (1<<TOV5);
  256. }
  257. #endif // COUNTER_USE_***
  258. /**********************************************/
  259. /* Timer Hardware Abstraction */
  260. /**********************************************/
  261. #if defined(TIMER_USE_INTERVALTIMER) // Teensyduino IntervalTimer
  262. static IntervalTimer itimer;
  263. static void timer_interrupt(void);
  264. static inline uint16_t timer_init(uint16_t msec)
  265. {
  266. return msec;
  267. }
  268. static inline void timer_start(void)
  269. {
  270. // IntervalTimer is capable of longer intervals, but
  271. // LPTMR can overflow. Limiting to 1 ms allows counting
  272. // up to 65.535 MHz... LPTMR on Teensy 3.1 can do 65 MHz!
  273. itimer.begin(timer_interrupt, 1000);
  274. }
  275. static inline void timer_shutdown(void)
  276. {
  277. itimer.end();
  278. }
  279. #define TIMER_ISR_VECTOR timer_interrupt
  280. #ifdef ISR
  281. #undef ISR
  282. #endif
  283. #define ISR(name) void name (void)
  284. #elif defined(TIMER_USE_INTERVALTIMER_T4)
  285. static IntervalTimer itimer;
  286. volatile uint32_t count;
  287. static void timer_callback()
  288. {
  289. count = TMRx->CH[2].CNTR | TMRx->CH[3].HOLD << 16; // atomic
  290. count_ready = 1;
  291. }
  292. static inline uint16_t timer_init(uint32_t usec)
  293. {
  294. itimer.begin(timer_callback, usec); //timer correction
  295. return usec;
  296. }
  297. static inline void timer_start(void)
  298. {
  299. }
  300. static inline void timer_shutdown(void)
  301. {
  302. }
  303. #elif defined(TIMER_USE_TIMER2) // 8 bit Timer 2 on Atmel AVR
  304. /* 1ms 2ms 4ms 8ms
  305. 16 MHz 128x125 256x125 256x250 1024x125
  306. 12 MHz 64x188 128x188 256x188 1024x94 //Not exact ms values: 2% error
  307. 8 MHz 64x125 128x125 256x125 256x250
  308. 4 MHz 32x125 64x125 128x125 256x125
  309. 2 MHz 8x250 32x125 64x125 128x125
  310. 1 MHz 8x125 8x250 32x125 64x125
  311. */
  312. #if F_CPU == 16000000L
  313. #define TIMER2_OCR2A_1MS_VAL 124 // div 125
  314. #define TIMER2_TCCR2B_1MS_VAL (1<<CS22) | (1<<CS20) // div 128
  315. #define TIMER2_OCR2A_2MS_VAL 124 // div 125
  316. #define TIMER2_TCCR2B_2MS_VAL (1<<CS22) | (1<<CS21) // div 256
  317. #define TIMER2_OCR2A_4MS_VAL 249 // div 250
  318. #define TIMER2_TCCR2B_4MS_VAL (1<<CS22) | (1<<CS21) // div 256
  319. #define TIMER2_OCR2A_8MS_VAL 124 // div 125
  320. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) | (1<<CS21) | (1<<CS20) // div 1024
  321. #elif F_CPU == 12000000L
  322. #define TIMER2_OCR2A_1MS_VAL 187 // div 188
  323. #define TIMER2_TCCR2B_1MS_VAL (1<<CS22) // div 64
  324. #define TIMER2_OCR2A_2MS_VAL 187 // div 125
  325. #define TIMER2_TCCR2B_2MS_VAL (1<<CS22) | (1<<CS20) // div 128
  326. #define TIMER2_OCR2A_4MS_VAL 187 // div 250
  327. #define TIMER2_TCCR2B_4MS_VAL (1<<CS22) | (1<<CS21) // div 256
  328. #define TIMER2_OCR2A_8MS_VAL 93 // div 125
  329. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) | (1<<CS21) | (1<<CS20) // div 1024
  330. #elif F_CPU == 8000000L
  331. #define TIMER2_OCR2A_1MS_VAL 124 // div 125
  332. #define TIMER2_TCCR2B_1MS_VAL (1<<CS22) // div 64
  333. #define TIMER2_OCR2A_2MS_VAL 124 // div 125
  334. #define TIMER2_TCCR2B_2MS_VAL (1<<CS22) | (1<<CS20) // div 128
  335. #define TIMER2_OCR2A_4MS_VAL 124 // div 125
  336. #define TIMER2_TCCR2B_4MS_VAL (1<<CS22) | (1<<CS21) // div 256
  337. #define TIMER2_OCR2A_8MS_VAL 249 // div 250
  338. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) | (1<<CS21) // div 256
  339. #elif F_CPU == 4000000L
  340. #define TIMER2_OCR2A_1MS_VAL 124 // div 125
  341. #define TIMER2_TCCR2B_1MS_VAL (1<<CS21) | (1<<CS20) // div 32
  342. #define TIMER2_OCR2A_2MS_VAL 124 // div 125
  343. #define TIMER2_TCCR2B_2MS_VAL (1<<CS22) // div 64
  344. #define TIMER2_OCR2A_4MS_VAL 124 // div 125
  345. #define TIMER2_TCCR2B_4MS_VAL (1<<CS22) | (1<<CS20) // div 128
  346. #define TIMER2_OCR2A_8MS_VAL 124 // div 125
  347. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) | (1<<CS21) // div 256
  348. #elif F_CPU == 2000000L
  349. #define TIMER2_OCR2A_1MS_VAL 249 // div 250
  350. #define TIMER2_TCCR2B_1MS_VAL (1<<CS21) // div 8
  351. #define TIMER2_OCR2A_2MS_VAL 124 // div 125
  352. #define TIMER2_TCCR2B_2MS_VAL (1<<CS21) | (1<<CS20) // div 32
  353. #define TIMER2_OCR2A_4MS_VAL 124 // div 125
  354. #define TIMER2_TCCR2B_4MS_VAL (1<<CS22) // div 64
  355. #define TIMER2_OCR2A_8MS_VAL 124 // div 125
  356. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) | (1<<CS21) // div 128
  357. #elif F_CPU == 1000000L
  358. #define TIMER2_OCR2A_1MS_VAL 124 // div 125
  359. #define TIMER2_TCCR2B_1MS_VAL (1<<CS21) // div 8
  360. #define TIMER2_OCR2A_2MS_VAL 249 // div 250
  361. #define TIMER2_TCCR2B_2MS_VAL (1<<CS21) // div 8
  362. #define TIMER2_OCR2A_4MS_VAL 124 // div 125
  363. #define TIMER2_TCCR2B_4MS_VAL (1<<CS21) | (1<<CS20) // div 32
  364. #define TIMER2_OCR2A_8MS_VAL 124 // div 125
  365. #define TIMER2_TCCR2B_8MS_VAL (1<<CS22) // div 64
  366. #else
  367. #error "Clock must be 16, 12, 8, 4, 2 or 1 MHz"
  368. #endif
  369. static uint8_t saveTCCR2A, saveTCCR2B;
  370. static uint8_t startTCCR2B;
  371. static inline uint16_t timer_init(uint16_t msec)
  372. {
  373. uint16_t gate_len;
  374. saveTCCR2A = TCCR2A;
  375. saveTCCR2B = TCCR2B;
  376. TCCR2B = 0;
  377. TCCR2A = (1<<WGM21);
  378. if ((msec & 7) == 0) {
  379. gate_len = msec >> 3;
  380. OCR2A = TIMER2_OCR2A_8MS_VAL;
  381. startTCCR2B = TIMER2_TCCR2B_8MS_VAL;
  382. } else if ((msec & 3) == 0) {
  383. gate_len = msec >> 2;
  384. OCR2A = TIMER2_OCR2A_4MS_VAL;
  385. startTCCR2B = TIMER2_TCCR2B_4MS_VAL;
  386. } else if ((msec & 1) == 0) {
  387. gate_len = msec >> 1;
  388. OCR2A = TIMER2_OCR2A_2MS_VAL;
  389. startTCCR2B = TIMER2_TCCR2B_2MS_VAL;
  390. } else {
  391. gate_len = msec;
  392. OCR2A = TIMER2_OCR2A_1MS_VAL;
  393. startTCCR2B = TIMER2_TCCR2B_1MS_VAL;
  394. }
  395. TIFR2 = (1<<OCF2A);
  396. TCNT2 = 0;
  397. return gate_len;
  398. }
  399. static inline void timer_start(void)
  400. {
  401. GTCCR = (1<<PSRASY);
  402. TCCR2B = startTCCR2B;
  403. TIMSK2 = (1<<OCIE2A);
  404. }
  405. static inline void timer_shutdown(void)
  406. {
  407. TCCR2B = 0;
  408. TIMSK2 = 0;
  409. TCCR2A = saveTCCR2A;
  410. TCCR2B = saveTCCR2B;
  411. }
  412. #define TIMER_ISR_VECTOR TIMER2_COMPA_vect
  413. /*
  414. There is a typical latency from the timer interrupt until the first
  415. actual line of code executes. Here is a typical compiler output of
  416. approximately 34 cycles. When starting, this same delay is used to
  417. begin counting, so the first reading will not have 34 cycles of
  418. extra measurement. Because each measurement period gates instantly
  419. after the previous, this approximate correction only affects the
  420. first measurement. If you do not define TIMER_LATENCY_CYCLES, this
  421. extra delay is skipped (saving a tiny bit of code space), and the
  422. only downside is a slight inaccuracy in the first measurement.
  423. 2 00000326 <__vector_13>:
  424. 2 326: 1f 92 push r1
  425. 2 328: 0f 92 push r0
  426. 1 32a: 0f b6 in r0, 0x3f ; 63
  427. 2 32c: 0f 92 push r0
  428. 1 32e: 11 24 eor r1, r1
  429. 2 330: ef 92 push r14
  430. 2 332: ff 92 push r15
  431. 2 334: 0f 93 push r16
  432. 2 336: 1f 93 push r17
  433. 2 338: 2f 93 push r18
  434. 2 33a: 3f 93 push r19
  435. 2 33c: 4f 93 push r20
  436. 2 33e: 5f 93 push r21
  437. 2 340: 8f 93 push r24
  438. 2 342: 9f 93 push r25
  439. 2 344: af 93 push r26
  440. 2 346: bf 93 push r27
  441. */
  442. #define TIMER_LATENCY_CYCLES 34
  443. #elif defined(TIMER_USE_TIMER4H) // 10 bit "high speed" Timer 4 on Atmel AVR
  444. #define TIMER4H_OCR4C_VAL 124 // always div 125
  445. #if F_CPU == 16000000L
  446. #define TIMER4H_TCCR4B_1MS_VAL (1<<CS43) // div 128
  447. #define TIMER4H_TCCR4B_2MS_VAL (1<<CS43) | (1<<CS40) // div 256
  448. #define TIMER4H_TCCR4B_4MS_VAL (1<<CS43) | (1<<CS41) // div 512
  449. #define TIMER4H_TCCR4B_8MS_VAL (1<<CS43) | (1<<CS41) | (1<<CS40) // div 1024
  450. #elif F_CPU == 8000000L
  451. #define TIMER4H_TCCR4B_1MS_VAL (1<<CS42) | (1<<CS41) | (1<<CS40) // div 64
  452. #define TIMER4H_TCCR4B_2MS_VAL (1<<CS43) // div 128
  453. #define TIMER4H_TCCR4B_4MS_VAL (1<<CS43) | (1<<CS40) // div 256
  454. #define TIMER4H_TCCR4B_8MS_VAL (1<<CS43) | (1<<CS41) // div 512
  455. #elif F_CPU == 4000000L
  456. #define TIMER4H_TCCR4B_1MS_VAL (1<<CS42) | (1<<CS41) // div 32
  457. #define TIMER4H_TCCR4B_2MS_VAL (1<<CS42) | (1<<CS41) | (1<<CS40) // div 64
  458. #define TIMER4H_TCCR4B_4MS_VAL (1<<CS43) // div 128
  459. #define TIMER4H_TCCR4B_8MS_VAL (1<<CS43) | (1<<CS40) // div 256
  460. #elif F_CPU == 2000000L
  461. #define TIMER4H_TCCR4B_1MS_VAL (1<<CS42) | (1<<CS40) // div 16
  462. #define TIMER4H_TCCR4B_2MS_VAL (1<<CS42) | (1<<CS41) // div 32
  463. #define TIMER4H_TCCR4B_4MS_VAL (1<<CS42) | (1<<CS41) | (1<<CS40) // div 64
  464. #define TIMER4H_TCCR4B_8MS_VAL (1<<CS43) // div 128
  465. #elif F_CPU == 1000000L
  466. #define TIMER4H_TCCR4B_1MS_VAL (1<<CS42) // div 8
  467. #define TIMER4H_TCCR4B_2MS_VAL (1<<CS42) | (1<<CS40) // div 16
  468. #define TIMER4H_TCCR4B_4MS_VAL (1<<CS42) | (1<<CS41) // div 32
  469. #define TIMER4H_TCCR4B_8MS_VAL (1<<CS42) | (1<<CS41) | (1<<CS40) // div 64
  470. #else
  471. #error "Clock must be 16, 8, 4, 2 or 1 MHz"
  472. #endif
  473. static uint8_t saveTCCR4A, saveTCCR4B, saveTCCR4C, saveTCCR4D, saveTCCR4E, saveOCR4C;
  474. static uint8_t startTCCR4B;
  475. // input is the number of milliseconds required
  476. // output is the number of interrupts needed for that number of milliseconds
  477. static inline uint16_t timer_init(uint16_t msec)
  478. {
  479. uint16_t gate_len;
  480. saveTCCR4A = TCCR4A;
  481. saveTCCR4B = TCCR4B;
  482. saveTCCR4C = TCCR4C;
  483. saveTCCR4D = TCCR4D;
  484. saveTCCR4E = TCCR4E;
  485. saveOCR4C = OCR4C;
  486. TCCR4B = 0;
  487. TCCR4A = 0;
  488. TCCR4C = 0;
  489. TCCR4D = 0;
  490. TCCR4E = 0;
  491. OCR4C = TIMER4H_OCR4C_VAL;
  492. if ((msec & 7) == 0) {
  493. gate_len = msec >> 3;
  494. startTCCR4B = TIMER4H_TCCR4B_8MS_VAL | (1<<PSR4);
  495. } else if ((msec & 3) == 0) {
  496. gate_len = msec >> 2;
  497. startTCCR4B = TIMER4H_TCCR4B_4MS_VAL | (1<<PSR4);
  498. } else if ((msec & 1) == 0) {
  499. gate_len = msec >> 1;
  500. startTCCR4B = TIMER4H_TCCR4B_2MS_VAL | (1<<PSR4);
  501. } else {
  502. gate_len = msec;
  503. startTCCR4B = TIMER4H_TCCR4B_1MS_VAL | (1<<PSR4);
  504. }
  505. TIFR4 = (1<<TOV4);
  506. TCNT4 = 0;
  507. return gate_len;
  508. }
  509. static inline void timer_start(void)
  510. {
  511. TCCR4B = startTCCR4B;
  512. TIMSK4 = (1<<TOIE4);
  513. }
  514. static inline void timer_shutdown(void)
  515. {
  516. TCCR4B = 0;
  517. TIMSK4 = 0;
  518. OCR4C = saveOCR4C;
  519. TCCR4A = saveTCCR4A;
  520. TCCR4C = saveTCCR4C;
  521. TCCR4D = saveTCCR4D;
  522. TCCR4E = saveTCCR4E;
  523. TCCR4B = saveTCCR4B;
  524. }
  525. #define TIMER_ISR_VECTOR TIMER4_OVF_vect
  526. #define TIMER_LATENCY_CYCLES 34
  527. #endif // TIMER_USE_***
  528. static inline void timer_isr_latency_delay(void)
  529. {
  530. #ifdef TIMER_LATENCY_CYCLES
  531. #ifdef __AVR__
  532. uint8_t cycles_times_3 = TIMER_LATENCY_CYCLES / 3;
  533. asm volatile(
  534. "L_%=_loop:"
  535. "subi %0, 1" "\n\t"
  536. "brne L_%=_loop" "\n\t"
  537. : "+d" (cycles_times_3)
  538. : "0" (cycles_times_3)
  539. );
  540. #endif
  541. #endif
  542. }
  543. /**********************************************/
  544. /* Board Specific Interrupts (to hog) */
  545. /**********************************************/
  546. static inline void disable_other_interrupts(void)
  547. {
  548. }
  549. static inline void restore_other_interrupts(void)
  550. {
  551. }
  552. #endif