/* FreqCount Library, for measuring frequencies * http://www.pjrc.com/teensy/td_libs_FreqCount.html * Copyright (c) 2014 PJRC.COM, LLC - Paul Stoffregen * * Version 1.1 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #ifndef FreqCount_timers_h_ #define FreqCount_timers_h_ static uint32_t count_prev; static volatile uint32_t count_output; static volatile uint8_t count_ready; static volatile uint32_t usec; // Arduino Mega #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // #define COUNTER_USE_TIMER1 // T1 is not connected // #define COUNTER_USE_TIMER3 // T3 is not connected // #define COUNTER_USE_TIMER4 // T4 is not connected #define COUNTER_USE_TIMER5 // T5 is pin 47 #define TIMER_USE_TIMER2 //Teensy 4.0 #elif defined(__IMXRT1062__) IMXRT_TMR_t * TMRx = (IMXRT_TMR_t *)&IMXRT_TMR4; #define COUNTER_USE_QT4 #define TIMER_USE_INTERVALTIMER_T4 // Teensy 3.0 & 3.1 & LC #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MKL26Z64__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) #define COUNTER_USE_LPTMR // LPTMR is pin 13 (has LED connected) #define TIMER_USE_INTERVALTIMER // Teensy 2.0 #elif defined(__AVR_ATmega32U4__) #define COUNTER_USE_TIMER1 // T1 is pin 11 (has LED connected) #define TIMER_USE_TIMER4H // Teensy++ 1.0 & 2.0 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) #define COUNTER_USE_TIMER1 // T1 is pin 6 (has LED connected) //#define COUNTER_USE_TIMER3 // T3 is pin 13 #define TIMER_USE_TIMER2 // Sanguino #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) #define COUNTER_USE_TIMER1 // T1 is pin 1 #define TIMER_USE_TIMER2 // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc #elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) #define COUNTER_USE_TIMER1 // T1 is pin 5 #define TIMER_USE_TIMER2 #else #error "Unknown chip, please edit me with timer+counter definitions" #endif /**********************************************/ /* Counter Hardware Abstraction */ /**********************************************/ #if defined(COUNTER_USE_LPTMR) // 16 bit LPTMR on Freescale Kinetis static inline void counter_init(void) { SIM_SCGC5 |= SIM_SCGC5_LPTIMER; LPTMR0_CSR = 0; LPTMR0_PSR = 0b00000100; // bypass prescaler/filter LPTMR0_CMR = 0xFFFF; LPTMR0_CSR = 0b00100110; // counter, input=alt2, free running mode CORE_PIN13_CONFIG = PORT_PCR_MUX(3); } static inline void counter_start(void) { LPTMR0_CSR = 0b00100111; // enable } static inline void counter_shutdown(void) { LPTMR0_CSR = 0; } static inline uint16_t counter_read(void) { LPTMR0_CNR = 0; // writing cause sync with hardware return LPTMR0_CNR; } static inline uint8_t counter_overflow(void) { return (LPTMR0_CSR & 0x80) ? 1 : 0; } static inline void counter_overflow_reset(void) { LPTMR0_CSR = 0b10100111; } #elif defined(COUNTER_USE_QT4) static inline void counter_init(void) { CCM_CCGR6 |= CCM_CCGR6_QTIMER4(CCM_CCGR_ON); //enable QTMR4 IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_11 = 1; // QT4 Timer2 on pin 9 int cnt = 65536 ; // full cycle TMRx->CH[2].CTRL = 0; // stop TMRx->CH[2].CNTR = 0; TMRx->CH[2].LOAD = 0; // start val after compare TMRx->CH[2].COMP1 = cnt - 1; // count up to this val and start again TMRx->CH[2].CMPLD1 = cnt - 1; TMRx->CH[2].SCTRL = 0; TMRx->CH[3].CTRL = 0; // stop TMRx->CH[3].CNTR = 0; TMRx->CH[3].LOAD = 0; // start val after compare TMRx->CH[3].COMP1 = 0; TMRx->CH[3].CMPLD1 = 0; TMRx->CH[3].CTRL = TMR_CTRL_CM(7) | TMR_CTRL_PCS(6); //clock from clock 2 TMRx->CH[2].CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(2) | TMR_CTRL_LENGTH ; } #elif defined(COUNTER_USE_TIMER1) // 16 bit Timer 1 on Atmel AVR static uint8_t saveTCCR1A, saveTCCR1B; static inline void counter_init(void) { saveTCCR1A = TCCR1A; saveTCCR1B = TCCR1B; TCCR1B = 0; TCCR1A = 0; TCNT1 = 0; TIFR1 = (1<CH[2].CNTR | TMRx->CH[3].HOLD << 16; // atomic count_ready = 1; } static inline uint16_t timer_init(uint32_t usec) { itimer.begin(timer_callback, usec); //timer correction return usec; } static inline void timer_start(void) { } static inline void timer_shutdown(void) { } #elif defined(TIMER_USE_TIMER2) // 8 bit Timer 2 on Atmel AVR /* 1ms 2ms 4ms 8ms 16 MHz 128x125 256x125 256x250 1024x125 12 MHz 64x188 128x188 256x188 1024x94 //Not exact ms values: 2% error 8 MHz 64x125 128x125 256x125 256x250 4 MHz 32x125 64x125 128x125 256x125 2 MHz 8x250 32x125 64x125 128x125 1 MHz 8x125 8x250 32x125 64x125 */ #if F_CPU == 16000000L #define TIMER2_OCR2A_1MS_VAL 124 // div 125 #define TIMER2_TCCR2B_1MS_VAL (1<> 3; OCR2A = TIMER2_OCR2A_8MS_VAL; startTCCR2B = TIMER2_TCCR2B_8MS_VAL; } else if ((msec & 3) == 0) { gate_len = msec >> 2; OCR2A = TIMER2_OCR2A_4MS_VAL; startTCCR2B = TIMER2_TCCR2B_4MS_VAL; } else if ((msec & 1) == 0) { gate_len = msec >> 1; OCR2A = TIMER2_OCR2A_2MS_VAL; startTCCR2B = TIMER2_TCCR2B_2MS_VAL; } else { gate_len = msec; OCR2A = TIMER2_OCR2A_1MS_VAL; startTCCR2B = TIMER2_TCCR2B_1MS_VAL; } TIFR2 = (1<: 2 326: 1f 92 push r1 2 328: 0f 92 push r0 1 32a: 0f b6 in r0, 0x3f ; 63 2 32c: 0f 92 push r0 1 32e: 11 24 eor r1, r1 2 330: ef 92 push r14 2 332: ff 92 push r15 2 334: 0f 93 push r16 2 336: 1f 93 push r17 2 338: 2f 93 push r18 2 33a: 3f 93 push r19 2 33c: 4f 93 push r20 2 33e: 5f 93 push r21 2 340: 8f 93 push r24 2 342: 9f 93 push r25 2 344: af 93 push r26 2 346: bf 93 push r27 */ #define TIMER_LATENCY_CYCLES 34 #elif defined(TIMER_USE_TIMER4H) // 10 bit "high speed" Timer 4 on Atmel AVR #define TIMER4H_OCR4C_VAL 124 // always div 125 #if F_CPU == 16000000L #define TIMER4H_TCCR4B_1MS_VAL (1<> 3; startTCCR4B = TIMER4H_TCCR4B_8MS_VAL | (1<> 2; startTCCR4B = TIMER4H_TCCR4B_4MS_VAL | (1<> 1; startTCCR4B = TIMER4H_TCCR4B_2MS_VAL | (1<