123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #pragma once
- #include <kinetis.h>
- #include <core_pins.h>
- namespace TeensyStepFTM
- {
- //==========================================================================
- // Available timer modules for the Teensy XX boards. Please note that those
- // timers are also used by the core libraries for PWM and AnalogWrite.
- // Therefore, choose a timer which isn't attached to the pins you need for
- // PWM or AnalogWrite. (TEENSY LC not yet supported)
- //
- // D: Default, X: available
- //
- // TIMER | Channels| Timer is available for |
- // | | T-LC | T3.0 | T3.1 | T3.2 | T3.5 | T3.6|
- //----------------------|---------|------|------|-------|------|------|-----|
- #define TIMER_FTM0 1 //| 8 | | D | D | D | D | D |
- #define TIMER_FTM1 2 //| 2 | | X | X | X | X | X |
- #define TIMER_FTM2 3 //| 2 | | | X | X | X | X |
- #define TIMER_FTM3 4 //| 8 | | | | | X | X |
- #define TIMER_TPM0 5 //| 6 | | | | | | |
- #define TIMER_TPM1 6 //| 2 | | | | | | X |
- #define TIMER_TPM2 7 //| 2 | | | | | | X |
- #define TIMER_DEFAULT -1
- // If you need a special timer, please replace "TIMER_DEFAULT" by a timer from the list above
- #define USE_TIMER TIMER_DEFAULT
- //==========================================================================
- // Nothing to be changed below here
- //==========================================================================
- #if USE_TIMER == TIMER_DEFAULT
- #undef USE_TIMER
- #if defined __MKL26Z64__
- #define USE_TIMER TIMER_TPM0
- #else
- #define USE_TIMER TIMER_FTM0
- #endif
- #endif
- constexpr unsigned selTimer = USE_TIMER - 1;
- constexpr bool isFTM = selTimer <= 3;
- //================================================
- // Which board do we use
- enum class _boards
- {
- T_LC, T_30, T31_2, T_35, T_36
- };
- #if defined __MKL26Z64__
- constexpr _boards board = _boards::T_LC;
- #elif defined __MK20DX128__
- constexpr _boards board = _boards::T_30;
- #elif defined __MK20DX256__
- constexpr _boards board = _boards::T31_2;
- #elif defined __MK64FX512__
- constexpr _boards board = _boards::T_35;
- #elif defined __MK66FX1M0__
- constexpr _boards board = _boards::T_36;
- #endif
- //====================================================================
- // Memory layout of register banks for FTM and TPM timers
- typedef struct // FTM & TPM Channels
- {
- uint32_t SC;
- uint32_t CV;
- } FTM_CH_t;
- typedef struct // FTM register block (this layout is compatible to a TPM register block)
- {
- uint32_t SC;
- uint32_t CNT;
- uint32_t MOD;
- FTM_CH_t CH[8];
- uint32_t CNTIN;
- uint32_t STATUS;
- uint32_t MODE;
- uint32_t SYNC;
- uint32_t OUTINIT;
- uint32_t OUTMASK;
- uint32_t COMBINE;
- uint32_t DEADTIME;
- uint32_t EXTTRIG;
- uint32_t POL;
- uint32_t FMS;
- uint32_t FILTER;
- uint32_t FLTCTRL;
- uint32_t QDCTRL;
- uint32_t CONF;
- uint32_t FLTPOL;
- uint32_t SYNCONF;
- uint32_t INVCTRL;
- uint32_t SWOCTRL;
- uint32_t PWMLOAD;
- }FTM_t;
- //-----------------------------------------------------------------------------------
- // Definition of base address for register block, number of channels and IRQ number
- //
- constexpr uintptr_t TimerBaseAddr[][7] =
- { // FTM0 FTM1 FTM2 FTM3 TPM0 TMP1 TMP2
- { 0, 0, 0, 0, 0, 0, 0 }, // Teensy LC not yet supported
- { 0x40038000, 0x40039000, 0, 0, 0, 0, 0, }, // Teensy 3.0
- { 0x40038000, 0x40039000, 0x400B8000, 0, 0, 0, 0, }, // Teensy 3.1/3.2
- { 0x40038000, 0x40039000, 0x400B8000, 0x400B9000, 0, 0, 0, }, // Teensy 3.5
- { 0x40038000, 0x40039000, 0x400B8000, 0x400B9000, 0, 0x400C9000, 0x400CA000 }, // Teensy 3.6
- };
- constexpr int IRQ_Number[][7]
- {
- // FTM0 FTM1 FTM2 FTM3 TPM0 TPM1 TPM2
- { 0, 0, 0, 0, 0, 0, 0 }, // Teensy LC
- { 25, 26, 0, 0, 0, 0, 0 }, // Teensy 3.0
- { 62, 63, 64, 0, 0, 0, 0 }, // Teensy 3.1/3.2
- { 42, 43, 44, 71, 0, 0, 0 }, // Teensy 3.5
- { 42, 43, 44, 71, 0, 88, 89 }, // Teensy 3.6
- };
- constexpr int _nrOfChannels[]
- {
- 8, // FTM0
- 2, // FTM1
- 2, // FTM2
- 8, // FTM3
- 6, // TPM0
- 2, // TPM1
- 2, // TPM2
- };
- constexpr uintptr_t timerAddr = TimerBaseAddr[(int)board][selTimer];
- constexpr volatile FTM_t* timer = __builtin_constant_p((FTM_t*)timerAddr) ? (FTM_t*)timerAddr : (FTM_t*)timerAddr; // base address for register block of selected timer
- constexpr unsigned irq = IRQ_Number[(int)board][selTimer]; // IRQ number of selected timer
- constexpr unsigned maxChannel = _nrOfChannels[selTimer]; // Number of channels for selected timer
- static_assert(timer != nullptr && irq != 0, "Board does not support choosen timer"); //Generate compiler error in case the board does not support the selected timer
- //-----------------------------------------------------------------------------------
- //Frequency dependent settings
- constexpr unsigned _timer_frequency = isFTM ? F_BUS : 16000000; // FTM timers are clocked with F_BUS, the TPM timers are clocked with OSCERCLK (16MHz for all teensies)
- // Choose prescaler such that one timer cycle corresponds to about 1µs
- constexpr unsigned prescale =
- _timer_frequency > 120000000 ? 0b111 :
- _timer_frequency > 60000000 ? 0b110 :
- _timer_frequency > 30000000 ? 0b101 :
- _timer_frequency > 15000000 ? 0b100 :
- _timer_frequency > 8000000 ? 0b011 :
- _timer_frequency > 4000000 ? 0b010 :
- _timer_frequency > 2000000 ? 0b001 : 0b000;
- // Calculates required reload value to get a delay of mu microseconds.
- // this will be completely evaluated by the compiler as long as mu is known at compile time
- constexpr int microsToReload(const float mu)
- {
- return mu * 1E-6 * _timer_frequency / (1 << prescale) + 0.5;
- }
- }
|