diff --git a/third-party/Synth_Dexed/examples/synth_dexed.ino b/third-party/Synth_Dexed/examples/synth_dexed.ino deleted file mode 100644 index e3132af..0000000 --- a/third-party/Synth_Dexed/examples/synth_dexed.ino +++ /dev/null @@ -1,69 +0,0 @@ -#include -#include "synth_dexed.h" - -uint8_t fmpiano_sysex[156] = { - 95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14, // OP6 eg_rate_1-4, level_1-4, kbd_lev_scl_brk_pt, kbd_lev_scl_lft_depth, kbd_lev_scl_rht_depth, kbd_lev_scl_lft_curve, kbd_lev_scl_rht_curve, kbd_rate_scaling, amp_mod_sensitivity, key_vel_sensitivity, operator_output_level, osc_mode, osc_freq_coarse, osc_freq_fine, osc_detune - 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00, // OP5 - 95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07, // OP4 - 95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 07, // OP3 - 95, 50, 35, 78, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 07, 58, 00, 14, 00, 07, // OP2 - 96, 25, 25, 67, 99, 75, 00, 00, 00, 00, 00, 00, 00, 03, 00, 02, 99, 00, 01, 00, 10, // OP1 - 94, 67, 95, 60, 50, 50, 50, 50, // 4 * pitch EG rates, 4 * pitch EG level - 04, 06, 00, // algorithm, feedback, osc sync - 34, 33, 00, 00, 00, 04, // lfo speed, lfo delay, lfo pitch_mod_depth, lfo_amp_mod_depth, lfo_sync, lfo_waveform - 03, 24, // pitch_mod_sensitivity, transpose - 70, 77, 45, 80, 73, 65, 78, 79, 00, 00 // 10 * char for name ("DEFAULT ") -}; // FM-Piano - -AudioSynthDexed dexed(4,SAMPLE_RATE); // 4 voices max -AudioOutputI2S i2s1; -AudioControlSGTL5000 sgtl5000_1; -AudioConnection patchCord1(dexed, 0, i2s1, 0); -AudioConnection patchCord2(dexed, 0, i2s1, 1); - -void setup() -{ - AudioMemory(32); - - sgtl5000_1.enable(); - sgtl5000_1.lineOutLevel(29); - sgtl5000_1.dacVolumeRamp(); - sgtl5000_1.dacVolume(1.0); - sgtl5000_1.unmuteHeadphone(); - sgtl5000_1.unmuteLineout(); - sgtl5000_1.volume(0.8, 0.8); // Headphone volume -} - -void loop() -{ - static uint8_t count; - - if (count % 2 == 0) - { - dexed.loadInitVoice(); - } - else - { - dexed.loadVoiceParameters(fmpiano_sysex); - dexed.setTranspose(36); - } - - Serial.println("Key-Down"); - dexed.keydown(48, 100); - delay(100); - dexed.keydown(52, 100); - delay(100); - dexed.keydown(55, 100); - delay(100); - dexed.keydown(60, 100); - delay(2000); - - Serial.println("Key-Up"); - dexed.keyup(48); - dexed.keyup(52); - dexed.keyup(55); - dexed.keyup(60); - delay(2000); - - count++; -} diff --git a/third-party/Synth_Dexed/keywords.txt b/third-party/Synth_Dexed/keywords.txt new file mode 100644 index 0000000..8c39eb2 --- /dev/null +++ b/third-party/Synth_Dexed/keywords.txt @@ -0,0 +1,165 @@ +####################################### +# Syntax Coloring Map For Synth_Dexed +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Dexed KEYWORD1 +AudioSynthDexed KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +# Global methods +activate KEYWORD2 +deactivate KEYWORD2 +getMonoMode KEYWORD2 +setMonoMode KEYWORD2 +setRefreshMode KEYWORD2 +setMaxNotes KEYWORD2 +getMaxNotes KEYWORD2 +doRefreshVoice KEYWORD2 +setOPAll KEYWORD2 +decodeVoice KEYWORD2 +encodeVoice KEYWORD2 +getVoiceData KEYWORD2 +setVoiceDataElement KEYWORD2 +getVoiceDataElement KEYWORD2 +loadInitVoice KEYWORD2 +loadVoiceParameters KEYWORD2 +getNumNotesPlaying KEYWORD2 +uint32_t getXRun KEYWORD2 +uint16_t getRenderTimeMax KEYWORD2 +resetRenderTimeMax KEYWORD2 +ControllersRefresh KEYWORD2 + +# Sound methods KEYWORD2 +keyup KEYWORD2 +keydown KEYWORD2 +setSustain KEYWORD2 +getSustain KEYWORD2 +panic KEYWORD2 +notesOff KEYWORD2 +resetControllers KEYWORD2 +setMasterTune KEYWORD2 +int8_t getMasterTune KEYWORD2 +setPortamentoMode KEYWORD2 +setPBController KEYWORD2 +setMWController KEYWORD2 +setFCController KEYWORD2 +setBCController KEYWORD2 +setATController KEYWORD2 +setModWheel KEYWORD2 +getModWheel KEYWORD2 +setBreathController KEYWORD2 +getBreathController KEYWORD2 +setFootController KEYWORD2 +getFootController KEYWORD2 +setAftertouch KEYWORD2 +getAftertouch KEYWORD2 +setPitchbend KEYWORD2 +getPitchbend KEYWORD2 +setPitchbendRange KEYWORD2 +getPitchbendRange KEYWORD2 +setPitchbendStep KEYWORD2 +getPitchbendStep KEYWORD2 +setModWheelRange KEYWORD2 +getModWheelRange KEYWORD2 +setModWheelTarget KEYWORD2 +getModWheelTarget KEYWORD2 +setFootControllerRange KEYWORD2 +getFootControllerRange KEYWORD2 +setFootControllerTarget KEYWORD2 +getFootControllerTarget KEYWORD2 +setBreathControllerRange KEYWORD2 +getBreathControllerRange KEYWORD2 +setBreathControllerTarget KEYWORD2 +getBreathControllerTarget KEYWORD2 +setAftertouchRange KEYWORD2 +getAftertouchRange KEYWORD2 +setAftertouchTarget KEYWORD2 +getAftertouchTarget KEYWORD2 +setFilterCutoff KEYWORD2 +float getFilterCutoff KEYWORD2 +setFilterResonance KEYWORD2 +float getFilterResonance KEYWORD2 +setGain KEYWORD2 +float getGain KEYWORD2 + +# Voice configuration methods KEYWORD2 +setOPRateAll KEYWORD2 +setOPLevelAll KEYWORD2 +setOPRateAllCarrier KEYWORD2 +setOPLevelAllCarrier KEYWORD2 +setOPRateAllModulator KEYWORD2 +setOPLevelAllModulator KEYWORD2 +setOPRate KEYWORD2 +getOPRate KEYWORD2 +setOPLevel KEYWORD2 +getOPLevel KEYWORD2 +setOPKeyboardLevelScalingBreakPoint KEYWORD2 +getOPKeyboardLevelScalingBreakPoint KEYWORD2 +setOPKeyboardLevelScalingDepthLeft KEYWORD2 +getOPKeyboardLevelScalingDepthLeft KEYWORD2 +setOPKeyboardLevelScalingDepthRight KEYWORD2 +getOPKeyboardLevelScalingDepthRight KEYWORD2 +setOPKeyboardLevelScalingCurveLeft KEYWORD2 +getOPKeyboardLevelScalingCurveLeft KEYWORD2 +setOPKeyboardLevelScalingCurveRight KEYWORD2 +getOPKeyboardLevelScalingCurveRight KEYWORD2 +setOPKeyboardRateScale KEYWORD2 +getOPKeyboardRateScale KEYWORD2 +setOPAmpModulationSensity KEYWORD2 +getOPAmpModulationSensity KEYWORD2 +setOPKeyboardVelocitySensity KEYWORD2 +getOPKeyboardVelocitySensity KEYWORD2 +setOPOutputLevel KEYWORD2 +getOPOutputLevel KEYWORD2 +setOPMode KEYWORD2 +getOPMode KEYWORD2 +setOPFrequencyCoarse KEYWORD2 +getOPFrequencyCoarse KEYWORD2 +setOPFrequencyFine KEYWORD2 +getOPFrequencyFine KEYWORD2 +setOPDetune KEYWORD2 +getOPDetune KEYWORD2 +setPitchRate KEYWORD2 +getPitchRate KEYWORD2 +setPitchLevel KEYWORD2 +getPitchLevel KEYWORD2 +setAlgorithm KEYWORD2 +getAlgorithm KEYWORD2 +setFeedback KEYWORD2 +getFeedback KEYWORD2 +setOscillatorSync KEYWORD2 +getOscillatorSync KEYWORD2 +setLFOSpeed KEYWORD2 +getLFOSpeed KEYWORD2 +setLFODelay KEYWORD2 +getLFODelay KEYWORD2 +setLFOPitchModulationDepth KEYWORD2 +getLFOPitchModulationDepth KEYWORD2 +setLFOAmpModulationDepth KEYWORD2 +getLFOAmpModulationDepth KEYWORD2 +setLFOSync KEYWORD2 +getLFOSync KEYWORD2 +setLFOWaveform KEYWORD2 +getLFOWaveform KEYWORD2 +setLFOPitchModulationSensitivity KEYWORD2 +getLFOPitchModulationSensitivity KEYWORD2 +setTranspose KEYWORD2 +getTranspose KEYWORD2 +setName KEYWORD2 +getName KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/third-party/Synth_Dexed/src/synth_dexed.cpp b/third-party/Synth_Dexed/src/synth_dexed.cpp index 74cc4a5..72cbd62 100644 --- a/third-party/Synth_Dexed/src/synth_dexed.cpp +++ b/third-party/Synth_Dexed/src/synth_dexed.cpp @@ -440,13 +440,14 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer) } } +#if defined(TEENSY3_5) || defined(TEENSY3_6) || defined(TEENSY4) fx.process(sumbuf, n_samples); // Needed for fx.Gain()!!! #ifdef USE_SIMPLE_COMPRESSOR // mild compression for (i = 0; i < n_samples; i++) { - s = abs(sumbuf[i]); + s = fabs(sumbuf[i]); if (s > vuSignal) vuSignal = s; //else if (vuSignal > 0.001f) @@ -460,6 +461,22 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer) //arm_scale_f32(sumbuf, 0.00015, sumbuf, AUDIO_BLOCK_SAMPLES); arm_float_to_q15(sumbuf, buffer, AUDIO_BLOCK_SAMPLES); } +#elif defined(USE_CIRCLE) +} + +void Dexed::getSamples(uint16_t n_samples, uint32_t* buffer) +{ + int16_t* i16_buffer=new (HEAP_DMA30) int16_t[n_samples]; + + if(i16_buffer) + { + getSamples(n_samples,i16_buffer); + for(uint8_t i=0;i> 39; - pmod_1 = abs(pmod_1); + pmod_1 = fabs(pmod_1); int32_t pmod_2 = (int32_t)(((int64_t)ctrls->pitch_mod * (int64_t)senslfo) >> 14); - pmod_2 = abs(pmod_2); + pmod_2 = fabs(pmod_2); int32_t pitch_mod = max(pmod_1, pmod_2); pitch_mod = pitchenv_.getsample() + (pitch_mod * (senslfo < 0 ? -1 : 1)); diff --git a/third-party/Synth_Dexed/src/synth_dexed.h b/third-party/Synth_Dexed/src/synth_dexed.h index e2567f8..bfee5a9 100644 --- a/third-party/Synth_Dexed/src/synth_dexed.h +++ b/third-party/Synth_Dexed/src/synth_dexed.h @@ -25,13 +25,91 @@ #pragma once +#include "teensy_board_detection.h" +#if defined(TEENSY3_5) || defined(TEENSY3_6) || defined(TEENSY4) #include #include -#include "teensy_board_detection.h" +#define SAMPLE_RATE 44100 +#else +// +// START DEFINITIONS FOR CIRCLE +// + +#define USE_CIRCLE + +// define only one +//#define USE_I2S +//#define USE_HDMI + +#ifdef USE_I2S + #include + #define SOUND_CLASS CI2SSoundBaseDevice + #define SAMPLE_RATE 192000 + #define CHUNK_SIZE 8192 + #define DAC_I2C_ADDRESS 0 // I2C slave address of the DAC (0 for auto probing) +#elif defined (USE_HDMI) + #include + #define SOUND_CLASS CHDMISoundBaseDevice + #define SAMPLE_RATE 48000 + #define CHUNK_SIZE (384 * 10) +#else + #include + #define SOUND_CLASS CPWMSoundBaseDevice + #define SAMPLE_RATE 48000 + #define CHUNK_SIZE 2048 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define constrain(amt, low, high) ({ \ + __typeof__(amt) _amt = (amt); \ + __typeof__(low) _low = (low); \ + __typeof__(high) _high = (high); \ + (_amt < _low) ? _low : ((_amt > _high) ? _high : _amt); \ +}) + +static inline int32_t signed_saturate_rshift(int32_t val, int bits, int rshift) +{ + int32_t out, max; + + out = val >> rshift; + max = 1 << (bits - 1); + if (out >= 0) + { + if (out > max - 1) out = max - 1; + } + else + { + if (out < -max) out = -max; + } + return out; +} + +unsigned millis (void) +{ + return CTimer::Get ()->GetClockTicks () / (CLOCKHZ / 1000); +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif +#define PROGMEM +// +// END DEFINITIONS FOR CIRCLE +// +#endif #define SYNTH_DEXED_VERSION "1.0.0" //#define DEBUG 1 -#define SAMPLE_RATE 44100 #define MIDI_CONTROLLER_MODE_MAX 2 #define TRANSPOSE_FIX 24 @@ -1294,20 +1372,31 @@ class Dexed Lfo lfo; FmCore* engineMsfa; void getSamples(uint16_t n_samples, int16_t* buffer); + void getSamples(uint16_t n_samples, uint32_t* buffer); }; //===================================================== /***************************************************** CODE: orig_code/synth_microdexed.h *****************************************************/ +#if defined(TEENSY3_5) || defined(TEENSY3_6) || defined(TEENSY4) class AudioSynthDexed : public AudioStream, public Dexed { public: - AudioSynthDexed(uint8_t max_notes, uint16_t sample_rate) : AudioStream(0, NULL), Dexed(max_notes,sample_rate) { }; + ~AudioSynthDexed(void) { }; protected: const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES); volatile bool in_update = false; void update(void); }; +#elif defined(USE_CIRCLE) +class AudioSynthDexed : public Dexed, public SOUND_CLASS +{ + public: + AudioSynthDexed(uint8_t max_notes,uint16_t sample_rate,CInterruptSystem *pInterrupt, CI2CMaster *pI2CMaster); + ~AudioSynthDexed(void); + unsigned GetChunk (u32 *pBuffer, unsigned nChunkSize); +}; +#endif diff --git a/third-party/TeensyTimerTool/examples/01_Basic/RTC_Timer/RTC_Timer.ino b/third-party/TeensyTimerTool/examples/01_Basic/RTC_Timer/RTC_Timer.ino new file mode 100644 index 0000000..b24ca2c --- /dev/null +++ b/third-party/TeensyTimerTool/examples/01_Basic/RTC_Timer/RTC_Timer.ino @@ -0,0 +1,33 @@ +// Uses the built in Real Time Clock (RTC) as timebase. +// The sketch calculates the relative drift of the main 24MHz crystal relative to the 32.768kHz RTC crystal. +// Requires a T4.x board + +#include "Arduino.h" +#include "TeensyTimerTool.h" +using namespace TeensyTimerTool; + +PeriodicTimer t1(TCK_RTC); + +constexpr uint32_t period = 500'000; //µs + +void callback() +{ + static uint32_t start = micros(); + static uint32_t idx = 0; + + uint32_t now = micros() - start; + uint32_t expected = idx++ * period; + int32_t delta = now - expected; + float drift = 1E6 * delta / expected; // ppm + + Serial.printf("t: %d µs, rel. drift: %.2f ppm\n", now, drift); +} + +void setup() +{ + t1.begin(callback, period); +} + +void loop() +{ +} diff --git a/third-party/TeensyTimerTool/library.json b/third-party/TeensyTimerTool/library.json index 0d38c39..daafd1e 100644 --- a/third-party/TeensyTimerTool/library.json +++ b/third-party/TeensyTimerTool/library.json @@ -9,13 +9,12 @@ }, "authors": { - "name": "Lutz Niggl", - "email": "lutz.niggl@lunoptics.com", + "name": "luni64", "url": "https://github.com/luni64", "maintainer": true }, "homepage": "https://github.com/luni64/TeensyTimerTool", - "version": "0.3.5", + "version": "0.4.3", "frameworks": "arduino", "platforms": "Teensy" } diff --git a/third-party/TeensyTimerTool/library.properties b/third-party/TeensyTimerTool/library.properties index 253b255..6110c25 100644 --- a/third-party/TeensyTimerTool/library.properties +++ b/third-party/TeensyTimerTool/library.properties @@ -1,9 +1,9 @@ name=TeensyTimerTool -version=0.3.5 -author=Lutz Niggl -maintainer=Lutz Niggl +version=0.4.3 +author=luni64 +maintainer=luni64 sentence=Generic Interface to Teensy Timers -paragraph= TeensyTimerTool is a library that provides a generic, easy to use interface to the hardware timers (FTM, GPT, QUAD, PIT) of the PJRC Teensy boards. In addition, it provides up to 20 highly efficient software timers that use the same interface. All timers can be used in periodic and one-shot mode. Currently the library supports the ARM T3.X and T4.0 boards. You can either pick a free timer from a pool or specify exactly which of the available hardware or software timer modules you want to use. +paragraph= TeensyTimerTool is a library that provides a generic, easy to use interface to the hardware timers (FTM, GPT, QUAD, PIT) of the PJRC Teensy boards. In addition, it provides up to 20 highly efficient software timers based on the cycle counter or the RTC (32 and 64bit) that use the same interface. All timers can be used in periodic and one-shot mode. Currently the library supports the ARM T3.X and T4.0 boards. You can either pick a free timer from a pool or specify exactly which of the available hardware or software timer modules you want to use. category=Timing url=https://github.com/luni64/TeensyTimerTool architectures=* diff --git a/third-party/TeensyTimerTool/src/API/Timer.cpp b/third-party/TeensyTimerTool/src/API/Timer.cpp new file mode 100644 index 0000000..f15b7ea --- /dev/null +++ b/third-party/TeensyTimerTool/src/API/Timer.cpp @@ -0,0 +1,10 @@ +#include "timer.h" +#include "config.h" + +namespace TeensyTimerTool +{ + Timer::Timer(TimerGenerator *generator) + : BaseTimer(generator, true) + { + } +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/API/baseTimer.cpp b/third-party/TeensyTimerTool/src/API/baseTimer.cpp new file mode 100644 index 0000000..2652c39 --- /dev/null +++ b/third-party/TeensyTimerTool/src/API/baseTimer.cpp @@ -0,0 +1,30 @@ +#include "baseTimer.h" +//#include "Arduino.h" +#include "types.h" + +namespace TeensyTimerTool +{ + + BaseTimer::BaseTimer(TimerGenerator *generator, bool periodic) + : timerGenerator(generator) + { + this->timerGenerator = generator; + this->timerChannel = nullptr; + this->isPeriodic = periodic; + } + + BaseTimer::~BaseTimer() + { + if (timerChannel != nullptr) + { + delete timerChannel; + } + } + + errorCode BaseTimer::setPrescaler(int psc) + { + this->prescaler = psc; + return errorCode::OK; + } + +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/baseTimer.h b/third-party/TeensyTimerTool/src/API/baseTimer.h similarity index 59% rename from third-party/TeensyTimerTool/src/baseTimer.h rename to third-party/TeensyTimerTool/src/API/baseTimer.h index de8c229..c8071f1 100644 --- a/third-party/TeensyTimerTool/src/baseTimer.h +++ b/third-party/TeensyTimerTool/src/API/baseTimer.h @@ -1,13 +1,15 @@ #pragma once -//#include "Arduino.h" +#include "Arduino.h" #include "ErrorHandling/error_codes.h" #include "ITimerChannel.h" +#include "helpers.h" #include #if defined(USE_TIME_LITERALS) -# include "frequency.h" -# include +#include "frequency.h" +#include +#include using namespace std::chrono_literals; using namespace std::chrono; #endif @@ -17,8 +19,8 @@ namespace TeensyTimerTool class BaseTimer { public: - template - inline errorCode begin(callback_t callback, T period, bool start = true); + template + inline errorCode begin(callback_t callback, period_t period, bool start = true); inline errorCode setPrescaler(int psc); inline errorCode end(); inline errorCode start(); @@ -27,38 +29,21 @@ namespace TeensyTimerTool inline float getMaxPeriod() const; protected: - - template ::value, int>* = nullptr> - T getPeriod(T v) { return v; } + BaseTimer(TimerGenerator *generator, bool periodic); + virtual ~BaseTimer(); - - BaseTimer(TimerGenerator* generator, bool periodic); - - TimerGenerator* timerGenerator; - ITimerChannel* timerChannel; + TimerGenerator *timerGenerator; + ITimerChannel *timerChannel; bool isPeriodic; uint32_t prescaler = 0; - -#if defined(USE_TIME_LITERALS) - public: - template - inline float getMaxDuration() const { return getMaxPeriod() * dur::period::den / dur::period::num; } - - protected: - template ::value, int>* = nullptr> - float getPeriod(T v) { return (duration_cast>(v).count()); } - - template ::value, int>* = nullptr> - float getPeriod(T v) { return 1'000'000 / duration_cast(v).count(); } -#endif }; // INLINE IMPLEMENTATION ================================================ - template - errorCode BaseTimer::begin(callback_t callback, T p, bool start) + template + errorCode BaseTimer::begin(callback_t callback, period_t p, bool start) { - auto period = getPeriod(p); + float period = period2us(p); // transform from any period type to microseconds (float) if (callback == nullptr) return postError(errorCode::callback); if (isPeriodic && period == 0) return postError(errorCode::reload); @@ -95,22 +80,26 @@ namespace TeensyTimerTool errorCode BaseTimer::start() { - timerChannel->start(); - return errorCode::OK; // hack, implement return value in timer interface + if (timerChannel) + return postError(timerChannel->start()); + + return postError(errorCode::notInitialized); } errorCode BaseTimer::stop() { - return postError(timerChannel->stop()); + if (timerChannel) + return postError(timerChannel->stop()); + + return postError(errorCode::notInitialized); } float BaseTimer::getMaxPeriod() const { if (timerChannel != nullptr) - { return timerChannel->getMaxPeriod(); - } + postError(errorCode::notInitialized); - return 0; + return NAN; } -} \ No newline at end of file +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/API/oneShotTimer.h b/third-party/TeensyTimerTool/src/API/oneShotTimer.h new file mode 100644 index 0000000..367c215 --- /dev/null +++ b/third-party/TeensyTimerTool/src/API/oneShotTimer.h @@ -0,0 +1,57 @@ +#pragma once + +#include "ErrorHandling/error_codes.h" +#include "baseTimer.h" +#include "type_traits" + +namespace TeensyTimerTool +{ + class OneShotTimer : public BaseTimer + { + public: + inline OneShotTimer(TimerGenerator *generator = nullptr); + + inline errorCode begin(callback_t cb); + template errorCode trigger(T delay); + template errorCode triggerDirect(T reload); + template errorCode getTriggerReload(float delay, T *reload); + }; + + // Implementation ================================================ + + OneShotTimer::OneShotTimer(TimerGenerator *generator) + : BaseTimer(generator, false) + {} + + errorCode OneShotTimer::begin(callback_t callback) + { + return BaseTimer::begin(callback, 0, false); + } + + template + errorCode OneShotTimer::trigger(period_t delay) + { + if (timerChannel) + return postError(timerChannel->trigger(period2us(delay))); + + return postError(errorCode::notInitialized); + } + + template + errorCode OneShotTimer::triggerDirect(T reload) + { + if (timerChannel) + return postError(timerChannel->triggerDirect(reload)); + + return postError(errorCode::notInitialized); + } + + template + errorCode OneShotTimer::getTriggerReload(float delay, T *reload) + { + if (timerChannel) + return postError(timerChannel->getTriggerReload(delay, reload)); + + return postError(errorCode::notInitialized); + } +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/API/periodicTimer.h b/third-party/TeensyTimerTool/src/API/periodicTimer.h new file mode 100644 index 0000000..921e020 --- /dev/null +++ b/third-party/TeensyTimerTool/src/API/periodicTimer.h @@ -0,0 +1,21 @@ +#pragma once + +#include "baseTimer.h" + +namespace TeensyTimerTool +{ + class PeriodicTimer : public BaseTimer + { + public: + PeriodicTimer(TimerGenerator *generator = nullptr) : BaseTimer(generator, true) {} + + template + inline errorCode setPeriod(period_t p) { return postError(timerChannel->setPeriod(period2us(p))); }; + + template + inline errorCode setNextPeriod(period_t p) { return postError(timerChannel->setNextPeriod(period2us(p))); }; + }; + + // IMPLEMENTATION ===================================================================== + +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/timer.h b/third-party/TeensyTimerTool/src/API/timer.h similarity index 79% rename from third-party/TeensyTimerTool/src/timer.h rename to third-party/TeensyTimerTool/src/API/timer.h index a6684ab..7cf3954 100644 --- a/third-party/TeensyTimerTool/src/timer.h +++ b/third-party/TeensyTimerTool/src/API/timer.h @@ -6,11 +6,10 @@ namespace TeensyTimerTool { - //class [[deprecated("Use PeriodicTimer or OneShotTimer instead")]] Timer : public BaseTimer - class Timer : public BaseTimer + class [[deprecated("Consider using PeriodicTimer or OneShotTimer instead")]] Timer : public BaseTimer { public: - Timer(TimerGenerator* gen = nullptr); + Timer(TimerGenerator *gen = nullptr); inline errorCode beginPeriodic(callback_t cb, uint32_t period) { @@ -31,4 +30,4 @@ namespace TeensyTimerTool { timerChannel->trigger(delay); } -} +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.cpp b/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.cpp deleted file mode 100644 index 29bbc2d..0000000 --- a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifdef ESP32 - -#include "../../TeensyTimerTool.h" - -#if defined(HAS_TCK) and defined(ESP32) - -namespace TeensyTimerTool -{ - bool TCK_t::isInitialized = false; - TckChannel* TCK_t::channels[maxTckChannels]; -} - -void yield() { TeensyTimerTool::TCK_t::tick(); } - -#endif - -#endif \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.h b/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.h deleted file mode 100644 index df9e86a..0000000 --- a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TCK.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "TckChannel.h" -#include -#include - -namespace TeensyTimerTool -{ - constexpr unsigned maxTckChannels = 20; - - class TCK_t - { - public: - static inline ITimerChannel* getTimer(); - static inline void removeTimer(TckChannel*); - static inline void tick(); - - protected: - static bool isInitialized; - static TckChannel* channels[maxTckChannels]; - }; - - // IMPLEMENTATION ================================================================== - - ITimerChannel* TCK_t::getTimer() - { - Serial.printf("TCK getTimer()\n"); - - if (!isInitialized) - { - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - channels[chNr] = nullptr; - } - isInitialized = true; - } - - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - if (channels[chNr] == nullptr) - { - channels[chNr] = new TckChannel(); - return channels[chNr]; - } - } - - return nullptr; - } - - void TCK_t::removeTimer(TckChannel* channel) - { - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - if (channels[chNr] == channel) - { - channels[chNr] = nullptr; - delete channel; - break; - } - } - } - - void TCK_t::tick() - { - digitalWriteFast(12,HIGH); - for(unsigned i = 0; i < maxTckChannels; i++) - { - if (channels[i] != nullptr ) - { - channels[i]->tick(); - } - } - digitalWriteFast(12,LOW); - } - - - constexpr TimerGenerator* TCK = TCK_t::getTimer; - -} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TckChannel.h b/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TckChannel.h deleted file mode 100644 index bd3089b..0000000 --- a/third-party/TeensyTimerTool/src/ESP32-dummy/TCK/TckChannel.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "../ITimerChannel.h" -#include "../types.h" -#include "Arduino.h" - -namespace TeensyTimerTool -{ - class TCK_t; - - class TckChannel : public ITimerChannel - { - public: - inline TckChannel() { triggered = false; } - inline virtual ~TckChannel(){}; - - inline void begin(callback_t cb, unsigned period, bool periodic) - { - Serial.println("begin"); - - triggered = false; - this->periodic = periodic; - this->period = period * (F_CPU / 1'000'000); - this->callback = cb; - - startCNT = ARM_DWT_CYCCNT; - } - - inline void start() - { - Serial.println("start"); - - this->startCNT = ARM_DWT_CYCCNT; - this->triggered = true; - } - - inline void stop() - { - this->triggered = false; - } - - // inline void setPeriod(uint32_t microSeconds); - inline uint32_t getPeriod(void); - - inline void trigger(uint32_t delay) // µs - { - this->startCNT = ARM_DWT_CYCCNT; - this->period = delay * (F_CPU / 1'000'000) - 68; - this->triggered = true; - } - - protected: - uint32_t startCNT, period; - callback_t callback; - bool triggered; - bool periodic; - - inline void tick(); - bool block = false; - - friend TCK_t; - }; - - // IMPLEMENTATION ============================================== - - void TckChannel::tick() - { - static bool lock = false; - - if (!lock && period != 0 && triggered && (ARM_DWT_CYCCNT - startCNT) >= period) - { - lock = true; - startCNT = ARM_DWT_CYCCNT; - triggered = periodic; // i.e., stays triggerd if periodic, stops if oneShot - callback(); - lock = false; - } - } - - // void TckChannel::setPeriod(uint32_t microSeconds) - // { - // period = microSeconds * (F_CPU / 1'000'000) ; - // } - uint32_t TckChannel::getPeriod() - { - return period * (1'000'000.0f / F_CPU); - } - -} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/ErrorHandling/error_codes.h b/third-party/TeensyTimerTool/src/ErrorHandling/error_codes.h index 500bdcb..a4c8aac 100644 --- a/third-party/TeensyTimerTool/src/ErrorHandling/error_codes.h +++ b/third-party/TeensyTimerTool/src/ErrorHandling/error_codes.h @@ -2,39 +2,37 @@ namespace TeensyTimerTool { - enum class errorCode - { - OK = 0, + enum class errorCode { + OK = 0, // Warnings - periodOverflow= -100, - wrongType= -101, - triggeredLate= -102, //warn if new setted period is shorter than elapsed time + periodOverflow = -100, + wrongType = -101, + triggeredLate = -102, //warn if new setted period is shorter than elapsed time //General errors - argument = 100, - callback= 101, - reload= 102, - noFreeModule = 103, - noFreeChannel = 104, // requested module has no free channel - notImplemented= 105, // timer does not support this feature - notInitialized= 106, - + argument = 100, + callback = 101, + reload = 102, + noFreeModule = 103, + noFreeChannel = 104, // requested module has no free channel + notImplemented = 105, // timer does not support this feature + notInitialized = 106, // GTP Errors - GTP_err = 200, - GTP_err2 = 201, + GTP_err = 200, + GTP_err2 = 201, //TMR Errors - TMR_err = 300, - TMR_err2 = 301, + TMR_err = 300, + TMR_err2 = 301, //FTM Errors - FTM_err = 400, - FTM_err2 = 401, + FTM_err = 400, + FTM_err2 = 401, //TCK Errors - TCK_err = 900, - TCK_err2 = 901, + TCK_err = 900, + TCK_err2 = 901, }; } \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.cpp b/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.cpp index 8eefa63..125ace2 100644 --- a/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.cpp +++ b/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.cpp @@ -4,14 +4,14 @@ namespace TeensyTimerTool { - ErrorHandler::ErrorHandler(Stream& s) : stream(s) + ErrorHandler::ErrorHandler(Stream &s) : stream(s) { pinMode(LED_BUILTIN, OUTPUT); } void ErrorHandler::operator()(errorCode code) const { - const char* txt; + const char *txt; switch (code) { @@ -21,7 +21,7 @@ namespace TeensyTimerTool // warnings case errorCode::periodOverflow: - txt = "Period overflow, set to maximum"; + txt = "Period overflow. Period was set to maximum value"; break; case errorCode::wrongType: txt = "Wrong parameter type"; @@ -41,7 +41,7 @@ namespace TeensyTimerTool txt = "Function not implemented for this timer"; break; case errorCode::notInitialized: - txt = "Timer not initialized or available"; + txt = "Timer not initialized or available. Did you call begin?"; break; default: @@ -76,4 +76,4 @@ namespace TeensyTimerTool errFunc = _errFunc; } -} \ No newline at end of file +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.h b/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.h index da7eedb..aac06e3 100644 --- a/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.h +++ b/third-party/TeensyTimerTool/src/ErrorHandling/error_handler.h @@ -1,17 +1,17 @@ #pragma once -#include "error_codes.h" #include "Stream.h" +#include "error_codes.h" namespace TeensyTimerTool { class ErrorHandler { public: - ErrorHandler(Stream& s); + ErrorHandler(Stream &s); void operator()(errorCode code) const; protected: - Stream& stream; + Stream &stream; }; -} \ No newline at end of file +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/ITimerChannel.h b/third-party/TeensyTimerTool/src/ITimerChannel.h index 1145c9c..e912008 100644 --- a/third-party/TeensyTimerTool/src/ITimerChannel.h +++ b/third-party/TeensyTimerTool/src/ITimerChannel.h @@ -8,34 +8,34 @@ namespace TeensyTimerTool { public: virtual errorCode begin(callback_t callback, float period, bool oneShot) = 0; - virtual errorCode trigger(float delay) = 0; - virtual errorCode triggerDirect(uint32_t reload){ return postError(errorCode::notImplemented); }; - virtual errorCode triggerDirect(uint64_t reload){ return postError(errorCode::notImplemented); }; - virtual errorCode getTriggerReload(float delay, uint32_t* reload) {return postError(errorCode::notImplemented);}; - virtual errorCode getTriggerReload(float delay, uint64_t* reload) {return postError(errorCode::notImplemented);}; + virtual errorCode trigger(float delay) = 0; + virtual errorCode triggerDirect(uint32_t reload) { return postError(errorCode::notImplemented); }; + virtual errorCode triggerDirect(uint64_t reload) { return postError(errorCode::notImplemented); }; + virtual errorCode getTriggerReload(float delay, uint32_t *reload) { return postError(errorCode::notImplemented); }; + virtual errorCode getTriggerReload(float delay, uint64_t *reload) { return postError(errorCode::notImplemented); }; virtual errorCode start() = 0; - virtual errorCode stop() = 0; + virtual errorCode stop() = 0; - virtual errorCode setPrescaler(int psc) { return postError(errorCode::notImplemented); } + virtual errorCode setPrescaler(int psc) { return postError(errorCode::notImplemented); } virtual float getMaxPeriod() const = 0; - //virtual errorCode setPeriod(uint32_t microSeconds) { return postError(errorCode::notImplemented); }; virtual errorCode setPeriod(float microSeconds) { return postError(errorCode::notImplemented); }; - //virtual errorCode setNextPeriod(uint32_t microSeconds) { return postError(errorCode::notImplemented); }; virtual errorCode setNextPeriod(float microSeconds) { return postError(errorCode::notImplemented); }; virtual uint32_t getPeriod() { return 0; } inline void setCallback(callback_t); + virtual ~ITimerChannel(){}; + protected: - inline ITimerChannel(callback_t* cbStorage = nullptr); - callback_t* pCallback; + inline ITimerChannel(callback_t *cbStorage = nullptr); + callback_t *pCallback; }; // IMPLEMENTATION ==================================================== - ITimerChannel::ITimerChannel(callback_t* cbStorage) + ITimerChannel::ITimerChannel(callback_t *cbStorage) { this->pCallback = cbStorage; } diff --git a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Info.h b/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Info.h deleted file mode 100644 index 76e1967..0000000 --- a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Info.h +++ /dev/null @@ -1,110 +0,0 @@ -#pragma once - -#include "boardDef.h" -#include - - // All information in this header is calculated at compile time. - // FTM_Info will not generate any code - -namespace TeensyTimerTool -{ - typedef struct // FTM & TPM Channels - { - volatile uint32_t SC; - volatile uint32_t CV; - } FTM_CH_t; - - typedef struct // FTM register block (this layout is compatible to a TPM register block) - { - volatile uint32_t SC; - volatile uint32_t CNT; - volatile uint32_t MOD; - FTM_CH_t CH[8]; - volatile uint32_t CNTIN; - volatile uint32_t STATUS; - volatile uint32_t MODE; - volatile uint32_t SYNC; - volatile uint32_t OUTINIT; - volatile uint32_t OUTMASK; - volatile uint32_t COMBINE; - volatile uint32_t DEADTIME; - volatile uint32_t EXTTRIG; - volatile uint32_t POL; - volatile uint32_t FMS; - volatile uint32_t FILTER; - volatile uint32_t FLTCTRL; - volatile uint32_t QDCTRL; - volatile uint32_t CONF; - volatile uint32_t FLTPOL; - volatile uint32_t SYNCONF; - volatile uint32_t INVCTRL; - volatile uint32_t SWOCTRL; - volatile uint32_t PWMLOAD; - } FTM_r_t; - - //======================================================================= - // using a static class instead of namespace here to reduce namespace pollution - // (anonymous namespace doesn't make sense for header only class) - - template - class FTM_Info - { - private: - #if defined(ARDUINO_TEENSYLC) - static constexpr unsigned boardNr = 0; - #elif defined(ARDUINO_TEENSY30) - static constexpr unsigned boardNr = 1; - #elif defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) - static constexpr unsigned boardNr = 2; - #elif defined(ARDUINO_TEENSY35) - static constexpr unsigned boardNr = 3; - #elif defined(ARDUINO_TEENSY36) - static constexpr unsigned boardNr = 4; - #else - #error Board not valid - #endif - - static constexpr int IRQ_Numbers[][4] - { //FTM0 FTM1 FTM2 FTM3 - { 0, 0, 0, 0 }, // Teensy LC - { 25, 26, 0, 0 }, // Teensy 3.0 - { 62, 63, 64, 0 }, // Teensy 3.1/3.2 - { 42, 43, 44, 71 }, // Teensy 3.5 - { 42, 43, 44, 71 }, // Teensy 3.6 - }; - - static constexpr int FTM_NrOfChannels[] - { - 8, // FTM0 - 2, // FTM1 - 2, // FTM2 - 8, // FTM3 - }; - - static constexpr uintptr_t FTM_BaseAdr[] // can't use defines from kinetis.h since, depending on board, not all are always defined. - { - 0x4003'8000, // FTM0 - 0x4003'9000, // FTM1 - 0x400B'8000, // FTM2 - 0x400B'9000, // FTM3 - }; - - static constexpr unsigned FTM_Prescale = - FTM_DEFAULT_PSC[module] < 0 || FTM_DEFAULT_PSC[module] > 7 ? // prescale value to roughly get 2 ticks per µs - ( - F_BUS > 120'000'000 ? 0b111 : - F_BUS > 60'000'000 ? 0b110 : - F_BUS > 30'000'000 ? 0b101 : - F_BUS > 15'000'000 ? 0b100 : - F_BUS > 8'000'000 ? 0b011 : - F_BUS > 4'000'000 ? 0b010 : - F_BUS > 2'000'000 ? 0b001 : 0b000 - ):FTM_DEFAULT_PSC[module]; - - public: - static constexpr uintptr_t baseAdr = FTM_BaseAdr[module]; - static constexpr IRQ_NUMBER_t irqNumber = (IRQ_NUMBER_t)IRQ_Numbers[boardNr][module]; - static constexpr unsigned nrOfChannels = FTM_NrOfChannels[module]; - static constexpr unsigned prescale = FTM_Prescale; - }; -} \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/PIT4/PITMap.h b/third-party/TeensyTimerTool/src/Teensy/PIT4/PITMap.h deleted file mode 100644 index 2e0336c..0000000 --- a/third-party/TeensyTimerTool/src/Teensy/PIT4/PITMap.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -namespace TeensyTimerTool -{ - // struct IMXRT_GPT_t - // { - // //51.7.1 GPT Control Register - // volatile uint32_t CR; - // //51.7.2 GPT Prescaler Register(GPTx_PR) - // volatile uint32_t PR; - // //51.7.3 GPT Status Register(GPTx_SR) - // volatile uint32_t SR; - // //51.7.4 GPT Interrupt Register(GPTx_IR) - // volatile uint32_t IR; - // //51.7.5 GPT Output Compare Register (GPTx_OCR1) - // volatile uint32_t OCR1; - // //51.7.6 GPT Output Compare Register (GPTx_OCR2) - // volatile uint32_t OCR2; - // //51.7.7 GPT Output Compare Register (GPTx_OCR3) - // volatile uint32_t OCR3; - // //51.7.8 GPT Input Capture Register 1 (GPTx_ICR1) - // volatile uint32_t ICR1; - // //51.7.9 GPT Input Capture Register 1 (GPTx_ICR2) - // volatile uint32_t ICR2; - // //51.7.10 GPT Counter Register (GPTx_CNT) - // volatile uint32_t CNT; - // }; - -} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/TCK/TCK.cpp b/third-party/TeensyTimerTool/src/Teensy/TCK/TCK.cpp deleted file mode 100644 index 3c3fc5e..0000000 --- a/third-party/TeensyTimerTool/src/Teensy/TCK/TCK.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "../../config.h" - -#if defined(TEENSYDUINO) - - #include "TCK.h" - namespace TeensyTimerTool - { - bool TCK_t::isInitialized = false; - TckChannelBase* TCK_t::channels[NR_OF_TCK_TIMERS]; - } - -//---------------------------------------------------------------------- - #if YIELD_TYPE == YIELD_OPTIMIZED - - void yield() - { - TeensyTimerTool::TCK_t::tick(); - } - -//---------------------------------------------------------------------- - #elif YIELD_TYPE == YIELD_STANDARD - - #include "EventResponder.h" - - namespace TeensyTimerTool - { - static EventResponder er; - - void initYieldHook() - { - er.attach([](EventResponderRef r) - { - TeensyTimerTool::TCK_t::tick(); - r.triggerEvent(); - }); - er.triggerEvent(); - } - } - #endif -#endif -//#endif \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/TCK/TckChannel.h b/third-party/TeensyTimerTool/src/Teensy/TCK/TckChannel.h deleted file mode 100644 index 784ba26..0000000 --- a/third-party/TeensyTimerTool/src/Teensy/TCK/TckChannel.h +++ /dev/null @@ -1,336 +0,0 @@ -#pragma once - -//#include "Arduino.h" -#include "ErrorHandling/error_codes.h" -#include "TckChannelBase.h" -#include "core_pins.h" - -namespace TeensyTimerTool -{ - class TCK_t; - -#if !defined(ARDUINO_TEENSYLC) // T-LC doesn't have a cycle counter, nees special treatment - - template - class TckChannel : public TckChannelBase - { - public: - TckChannel(); - virtual ~TckChannel(){}; //TBD - - inline errorCode begin(callback_t cb, float period, bool periodic) override; - inline errorCode start() override; - inline errorCode stop() override; - - inline errorCode trigger(float delay_us) override; - inline errorCode triggerDirect(CounterType reload) override; - inline errorCode getTriggerReload(float delay, CounterType* reload) override - { - *reload = microsecondToCycles(delay); - return errorCode::OK; - } - - float getMaxPeriod() const override { return getMaxMicros() / 1E6; } // seconds - - CounterType getCycleCounter() { postError(errorCode::wrongType); } - - // inline errorCode setPeriod(uint32_t microSeconds) override; - // inline errorCode setPeriod(uint32_t microSeconds) override; - // inline errorCode setNextPeriod(uint32_t microSeconds) override; - - protected: - inline CounterType microsecondToCycles(const float microSecond) const; - float getMaxMicros() const; - - inline bool tick(); - callback_t callback; - - bool periodic; - bool triggered; - - // bool block = false; - - CounterType startCnt, currentPeriod, nextPeriod; - - uint32_t lastCyCnt; - uint32_t curHIGH; - - float clock; - - friend TCK_t; - - // inline uint32_t CPUCyclesToMicroseond(const uint32_t cpuCycles); - // inline errorCode _setCurrentPeriod(const uint32_t period); - // inline void _setNextPeriod(const uint32_t period); - }; - - // IMPLEMENTATION ============================================== - - template - TckChannel::TckChannel() - { - triggered = false; - clock = F_CPU / 1'000'000.0f; - } - - template - errorCode TckChannel::begin(callback_t cb, float period, bool periodic) - { - this->triggered = false; - - this->periodic = periodic; - if (periodic) - { - this->currentPeriod = microsecondToCycles(period); - this->nextPeriod = this->currentPeriod; - } - this->callback = cb; - - return errorCode::OK; - } - - template - errorCode TckChannel::start() - { - this->startCnt = getCycleCounter(); - this->triggered = true; - return errorCode::OK; - } - - template - errorCode TckChannel::stop() - { - this->triggered = false; - return errorCode::OK; - } - - template - errorCode TckChannel::triggerDirect(CounterType reload) - { - this->startCnt = getCycleCounter(); - this->nextPeriod = reload; - this->currentPeriod = this->nextPeriod; - this->triggered = true; - return errorCode::OK; - } - - template - errorCode TckChannel::trigger(float delay) // µs - { - return triggerDirect(microsecondToCycles(delay)); - } - - template - bool TckChannel::tick() - { - static bool lock = false; - counter_t now = getCycleCounter(); - if (!lock && this->currentPeriod != 0 && this->triggered && (now - this->startCnt) >= this->currentPeriod) - { - lock = true; - //this->startCnt = now; - this->startCnt += currentPeriod; - this->triggered = this->periodic; // i.e., stays triggerd if periodic, stops if oneShot - callback(); - lock = false; - return true; - } else - { - return false; - } - } - - template - CounterType TckChannel::microsecondToCycles(float microSecond) const - { - if (microSecond > getMaxMicros()) - { - microSecond = getMaxMicros(); - postError(errorCode::periodOverflow); - } - return (CounterType)(microSecond * clock); - } - - // SPECIALIZATIONS ================================================================================= - // 32bit Counter ------------------------------------------------------------------------- - - template <> - inline uint32_t TckChannel::getCycleCounter() - { - return ARM_DWT_CYCCNT; //directly use the cycle counter for uint32_t - } - - template <> - inline float TckChannel::getMaxMicros() const - { - return 0xF000'0000 / clock; // don't use full range otherwise tick might miss the turnover for large periods - } - - // 64bit Counter ------------------------------------------------------------------------- - - template <> - inline uint64_t TckChannel::getCycleCounter() - { - uint32_t now = ARM_DWT_CYCCNT; // (extend the cycle counter to 64 bit) - if (now < lastCyCnt) - { - curHIGH++; - } - lastCyCnt = now; - return (((uint64_t)curHIGH << 32) | now); - } - - template <> - inline float TckChannel::getMaxMicros() const - { - return 0xFFFF'FFFF; // currently limited to 2^32 µs (71.6h). Could be extended to 2^64 but would require change of interface - } - - // template - // uint32_t TckChannel::CPUCyclesToMicroseond(const uint32_t cpuCycles) - // { - // return (1'000'000.0f / F_CPU) * cpuCycles; - // } - - // template - // void TckChannel::_setNextPeriod(const uint32_t period) - // { - // this->nextPeriod = period; - // } - - // template - // errorCode TckChannel::_setCurrentPeriod(const uint32_t period) - // { - // this->currentPeriod = period; - // const bool hasTicked = this->tick(); - - // if (hasTicked) - // { - // return errorCode::triggeredLate; - // } else - // { - // return errorCode::OK; - // } - // } - - // template - // errorCode TckChannel::setPeriod(uint32_t microSeconds) - // { - // const uint32_t period = microsecondToCPUCycles(microSeconds); - - // this->_setNextPeriod(period); - // return this->_setCurrentPeriod(period); - // } - - // template - // errorCode TckChannel::setPeriod(uint32_t microSeconds) - // { - // const uint32_t period = microsecondToCPUCycles(microSeconds); - // return this->_setCurrentPeriod(period); - // } - - // template - // errorCode TckChannel::setNextPeriod(uint32_t microSeconds) - // { - // const uint32_t period = microsecondToCPUCycles(microSeconds); - // this->_setNextPeriod(period); - // return errorCode::OK; - // } - -#else // TeensyLC - - // Quick hack only, needs to be improved - - template - class TckChannel : public TckChannelBase - { - public: - TckChannel() { triggered = false; } - virtual ~TckChannel(){}; - - errorCode begin(callback_t cb, float period, bool periodic) override - { - triggered = false; - this->periodic = periodic; - this->period = (uint32_t)period; - this->callback = cb; - - return errorCode::OK; - } - - errorCode start() - { - this->startCNT = micros(); - this->triggered = true; - return errorCode::OK; - } - - errorCode stop() - { - this->triggered = false; - return errorCode::OK; - } - - inline errorCode setPeriod(uint32_t microSeconds) override; - inline uint32_t getPeriod(void); - - inline errorCode trigger(float delay) // µs - { - this->startCNT = micros(); - this->period = (uint32_t)delay; - this->triggered = true; - return errorCode::OK; - } - - float getMaxPeriod() const override { return getMaxMicros() / 1E6; } // seconds - - protected: - static constexpr float clock = F_CPU / 1'000'000.0f; - float getMaxMicros() const { return 0xF000'0000 / clock; } // don't use full range otherwise tick might miss the turnover for large periods - - uint32_t startCNT, period; - callback_t callback; - bool triggered; - bool periodic; - - inline bool tick(); - bool block = false; - - friend TCK_t; - }; - - // IMPLEMENTATION ============================================== - - template - bool TckChannel::tick() - { - static bool lock = false; - - if (!lock && period != 0 && triggered && (micros() - startCNT) >= period) - { - lock = true; - startCNT = micros(); - triggered = periodic; // i.e., stays triggerd if periodic, stops if oneShot - callback(); - lock = false; - return true; - } - return false; - } - - template - errorCode TckChannel::setPeriod(uint32_t microSeconds) - { - period = microSeconds; - return errorCode::OK; - } - - template - uint32_t TckChannel::getPeriod() - { - return period; - } - -#endif - -} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/TeensyTimerTool.h b/third-party/TeensyTimerTool/src/TeensyTimerTool.h index c4cd898..d917c64 100644 --- a/third-party/TeensyTimerTool/src/TeensyTimerTool.h +++ b/third-party/TeensyTimerTool/src/TeensyTimerTool.h @@ -1,9 +1,9 @@ #pragma once -#include "config.h" -#include "timer.h" -#include "periodicTimer.h" -#include "oneShotTimer.h" +#include "API/oneShotTimer.h" +#include "API/periodicTimer.h" +#include "API/timer.h" #include "ErrorHandling/error_handler.h" +#include "config.h" static_assert(TEENSYDUINO >= 150, "This library requires Teensyduino > 1.5"); \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Timer.cpp b/third-party/TeensyTimerTool/src/Timer.cpp deleted file mode 100644 index 9518a39..0000000 --- a/third-party/TeensyTimerTool/src/Timer.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "timer.h" -#include "config.h" - -namespace TeensyTimerTool -{ - Timer::Timer(TimerGenerator* generator) - :BaseTimer(generator, true) - { - } -} diff --git a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM.h b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM.h similarity index 74% rename from third-party/TeensyTimerTool/src/Teensy/FTM/FTM.h rename to third-party/TeensyTimerTool/src/TimerModules/FTM/FTM.h index cba1870..32dbe47 100644 --- a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM.h +++ b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM.h @@ -8,14 +8,14 @@ namespace TeensyTimerTool class FTM_t { public: - inline static ITimerChannel* getTimer(); + inline static ITimerChannel *getTimer(); FTM_t() = delete; private: static bool isInitialized; inline static void isr() FASTRUN; - static constexpr FTM_r_t* r = (FTM_r_t*)FTM_Info::baseAdr; + static constexpr FTM_r_t *r = (FTM_r_t *)FTM_Info::baseAdr; static constexpr unsigned maxChannel = FTM_Info::nrOfChannels; static FTM_ChannelInfo channelInfo[maxChannel]; @@ -25,20 +25,20 @@ namespace TeensyTimerTool // IMPLEMENTATION ================================================================== template - ITimerChannel* FTM_t::getTimer() + ITimerChannel *FTM_t::getTimer() { if (!isInitialized) { - r->SC = FTM_SC_CLKS(0b00); // Disable clock - r->MOD = 0xFFFF; // Set full counter range + r->SC = FTM_SC_CLKS(0b00); // Disable clock + r->MOD = 0xFFFF; // Set full counter range r->CNT = 0; for (unsigned chNr = 0; chNr < maxChannel; chNr++) // init channels { - channelInfo[chNr].isReserved = false; - channelInfo[chNr].callback = nullptr; - channelInfo[chNr].chRegs = &r->CH[chNr]; - channelInfo[chNr].ticksPerMicrosecond = 1E-6f * F_BUS / (1 << FTM_Info::prescale); + channelInfo[chNr].isReserved = false; + channelInfo[chNr].callback = nullptr; + channelInfo[chNr].chRegs = &r->CH[chNr]; + channelInfo[chNr].ticksPerMicrosecond = 1E-6f * F_BUS / (1 << FTM_Info::prescale); r->CH[chNr].SC &= ~FTM_CSC_CHF; // FTM requires to clear flag by setting bit to 0 r->CH[chNr].SC &= ~FTM_CSC_CHIE; // Disable channel interupt @@ -66,8 +66,8 @@ namespace TeensyTimerTool { for (unsigned i = 0; i < maxChannel; i++) { - FTM_ChannelInfo* ci = &channelInfo[i]; // pre resolving the references turns out to be slightly faster - FTM_CH_t* cr = ci->chRegs; + FTM_ChannelInfo *ci = &channelInfo[i]; // pre resolving the references turns out to be slightly faster + FTM_CH_t *cr = ci->chRegs; if ((cr->SC & (FTM_CSC_CHIE | FTM_CSC_CHF)) == (FTM_CSC_CHIE | FTM_CSC_CHF)) // only handle if channel is active (CHIE set) and overflowed (CHF set) { if (ci->isPeriodic) @@ -76,7 +76,7 @@ namespace TeensyTimerTool cr->CV = r->CNT + ci->reload; // set compare value to 'reload' counts ahead of counter } else { - cr->SC &= ~FTM_CSC_CHIE; //disable interrupt in on shot mode + cr->SC &= ~FTM_CSC_CHIE; //disable interrupt in on shot mode } ci->callback(); } @@ -88,4 +88,4 @@ namespace TeensyTimerTool template bool FTM_t::isInitialized = false; -} +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Channel.h b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Channel.h similarity index 91% rename from third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Channel.h rename to third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Channel.h index d5e6889..68ed25a 100644 --- a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_Channel.h +++ b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Channel.h @@ -1,16 +1,16 @@ #pragma once -#include "../../ITimerChannel.h" #include "Arduino.h" #include "FTM_ChannelInfo.h" #include "FTM_Info.h" +#include "ITimerChannel.h" namespace TeensyTimerTool { class FTM_Channel : public ITimerChannel { public: - inline FTM_Channel(FTM_r_t* regs, FTM_ChannelInfo* ci); + inline FTM_Channel(FTM_r_t *regs, FTM_ChannelInfo *ci); inline virtual ~FTM_Channel(); inline float getMaxPeriod() const override; @@ -20,7 +20,7 @@ namespace TeensyTimerTool inline errorCode trigger(float tcnt) override FASTRUN; inline errorCode triggerDirect(uint32_t reload) override FASTRUN; - inline errorCode getTriggerReload(float delay, uint32_t* reload) override; + inline errorCode getTriggerReload(float delay, uint32_t *reload) override; inline errorCode start() override; inline errorCode stop() override; @@ -30,9 +30,9 @@ namespace TeensyTimerTool // inline void setPeriod(uint32_t) {} protected: - FTM_ChannelInfo* ci; - FTM_r_t* regs; - callback_t* pCallback = nullptr; + FTM_ChannelInfo *ci; + FTM_r_t *regs; + callback_t *pCallback = nullptr; template inline errorCode doBegin(callback_t cb, period_t period, bool periodic); @@ -40,7 +40,7 @@ namespace TeensyTimerTool // IMPLEMENTATION ============================================== - FTM_Channel::FTM_Channel(FTM_r_t* regs, FTM_ChannelInfo* channelInfo) + FTM_Channel::FTM_Channel(FTM_r_t *regs, FTM_ChannelInfo *channelInfo) : ITimerChannel(nullptr) { this->regs = regs; @@ -73,7 +73,7 @@ namespace TeensyTimerTool return errorCode::OK; } - errorCode FTM_Channel::getTriggerReload(float delay, uint32_t* reload) + errorCode FTM_Channel::getTriggerReload(float delay, uint32_t *reload) { *reload = ticksFromMicros(delay); return errorCode::OK; diff --git a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_ChannelInfo.h b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_ChannelInfo.h similarity index 76% rename from third-party/TeensyTimerTool/src/Teensy/FTM/FTM_ChannelInfo.h rename to third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_ChannelInfo.h index 0470f77..052cb96 100644 --- a/third-party/TeensyTimerTool/src/Teensy/FTM/FTM_ChannelInfo.h +++ b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_ChannelInfo.h @@ -1,7 +1,7 @@ #pragma once #include "FTM_Info.h" -#include "../../types.h" +#include "types.h" namespace TeensyTimerTool { @@ -11,7 +11,7 @@ namespace TeensyTimerTool bool isPeriodic; callback_t callback; uint32_t reload; - FTM_CH_t* chRegs; + FTM_CH_t *chRegs; float ticksPerMicrosecond; }; -} \ No newline at end of file +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Info.h b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Info.h new file mode 100644 index 0000000..a4beb2c --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/FTM/FTM_Info.h @@ -0,0 +1,109 @@ +#pragma once + +#include "boardDef.h" +#include + +// All information in this header is calculated at compile time. +// FTM_Info will not generate any code + +namespace TeensyTimerTool +{ + typedef struct // FTM & TPM Channels + { + volatile uint32_t SC; + volatile uint32_t CV; + } FTM_CH_t; + + typedef struct // FTM register block (this layout is compatible to a TPM register block) + { + volatile uint32_t SC; + volatile uint32_t CNT; + volatile uint32_t MOD; + FTM_CH_t CH[8]; + volatile uint32_t CNTIN; + volatile uint32_t STATUS; + volatile uint32_t MODE; + volatile uint32_t SYNC; + volatile uint32_t OUTINIT; + volatile uint32_t OUTMASK; + volatile uint32_t COMBINE; + volatile uint32_t DEADTIME; + volatile uint32_t EXTTRIG; + volatile uint32_t POL; + volatile uint32_t FMS; + volatile uint32_t FILTER; + volatile uint32_t FLTCTRL; + volatile uint32_t QDCTRL; + volatile uint32_t CONF; + volatile uint32_t FLTPOL; + volatile uint32_t SYNCONF; + volatile uint32_t INVCTRL; + volatile uint32_t SWOCTRL; + volatile uint32_t PWMLOAD; + } FTM_r_t; + + //======================================================================= + // using a static class instead of namespace here to reduce namespace pollution + // (anonymous namespace doesn't make sense for header only class) + + template + class FTM_Info + { + private: +#if defined(ARDUINO_TEENSYLC) + static constexpr unsigned boardNr = 0; +#elif defined(ARDUINO_TEENSY30) + static constexpr unsigned boardNr = 1; +#elif defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) + static constexpr unsigned boardNr = 2; +#elif defined(ARDUINO_TEENSY35) + static constexpr unsigned boardNr = 3; +#elif defined(ARDUINO_TEENSY36) + static constexpr unsigned boardNr = 4; +#else +#error Board not valid +#endif + + static constexpr int IRQ_Numbers[][4]{ + //FTM0 FTM1 FTM2 FTM3 + {0, 0, 0, 0}, // Teensy LC + {25, 26, 0, 0}, // Teensy 3.0 + {62, 63, 64, 0}, // Teensy 3.1/3.2 + {42, 43, 44, 71}, // Teensy 3.5 + {42, 43, 44, 71}, // Teensy 3.6 + }; + + static constexpr int FTM_NrOfChannels[]{ + 8, // FTM0 + 2, // FTM1 + 2, // FTM2 + 8, // FTM3 + }; + + static constexpr uintptr_t FTM_BaseAdr[] // can't use defines from kinetis.h since, depending on board, not all are always defined. + { + 0x4003'8000, // FTM0 + 0x4003'9000, // FTM1 + 0x400B'8000, // FTM2 + 0x400B'9000, // FTM3 + }; + + static constexpr unsigned FTM_Prescale = + FTM_DEFAULT_PSC[module] < 0 || FTM_DEFAULT_PSC[module] > 7 ? // prescale value to roughly get 2 ticks per µs + ( + F_BUS > 120'000'000 ? 0b111 : F_BUS > 60'000'000 ? 0b110 + : F_BUS > 30'000'000 ? 0b101 + : F_BUS > 15'000'000 ? 0b100 + : F_BUS > 8'000'000 ? 0b011 + : F_BUS > 4'000'000 ? 0b010 + : F_BUS > 2'000'000 ? 0b001 + : 0b000) + : FTM_DEFAULT_PSC[module]; + + public: + static constexpr uintptr_t baseAdr = FTM_BaseAdr[module]; + static constexpr IRQ_NUMBER_t irqNumber = (IRQ_NUMBER_t)IRQ_Numbers[boardNr][module]; + static constexpr unsigned nrOfChannels = FTM_NrOfChannels[module]; + static constexpr unsigned prescale = FTM_Prescale; + }; +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/GPT/GPT.h b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPT.h similarity index 81% rename from third-party/TeensyTimerTool/src/Teensy/GPT/GPT.h rename to third-party/TeensyTimerTool/src/TimerModules/GPT/GPT.h index 9963f82..1377536 100644 --- a/third-party/TeensyTimerTool/src/Teensy/GPT/GPT.h +++ b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPT.h @@ -1,6 +1,7 @@ #pragma once #include "GPTChannel.h" +//#include "Arduino.h" namespace TeensyTimerTool { @@ -8,27 +9,28 @@ namespace TeensyTimerTool class GPT_t { public: - static ITimerChannel* getTimer(); + static ITimerChannel *getTimer(); + static void end(); protected: static bool isInitialized; static void isr(); static callback_t callback; - static GptChannel* channel; + static GptChannel *channel; // the following is calculated at compile time static constexpr IRQ_NUMBER_t irq = moduleNr == 0 ? IRQ_GPT1 : IRQ_GPT2; - static IMXRT_GPT_t* const pGPT; + static IMXRT_GPT_t *const pGPT; static_assert(moduleNr < 2, "Wrong GPT Number"); }; // IMPLEMENTATION =========================================================================== template - IMXRT_GPT_t* const GPT_t::pGPT = reinterpret_cast(moduleNr == 0 ? &IMXRT_GPT1 : &IMXRT_GPT2); + IMXRT_GPT_t *const GPT_t::pGPT = reinterpret_cast(moduleNr == 0 ? &IMXRT_GPT1 : &IMXRT_GPT2); template - ITimerChannel* GPT_t::getTimer() + ITimerChannel *GPT_t::getTimer() { if (!isInitialized) { @@ -66,6 +68,16 @@ namespace TeensyTimerTool asm volatile("dsb"); // wait until register changes propagated through the cache } + template + void GPT_t::end() + { + //Serial.printf("end %d\n", tmoduleNr); + NVIC_DISABLE_IRQ(irq); + pGPT->CR = 0; + callback = nullptr; + isInitialized = false; + } + template bool GPT_t::isInitialized = false; @@ -73,5 +85,5 @@ namespace TeensyTimerTool callback_t GPT_t::callback = nullptr; template - GptChannel* GPT_t::channel = nullptr; -} \ No newline at end of file + GptChannel *GPT_t::channel = nullptr; +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.cpp b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.cpp new file mode 100644 index 0000000..e01ed69 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.cpp @@ -0,0 +1,24 @@ +#if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY_MICROMOD) + +#include "GPTChannel.h" +#include "GPT.h" +//#include "Arduino.h" + +namespace TeensyTimerTool +{ + GptChannel::~GptChannel() + { + stop(); + setCallback(nullptr); + + if (regs == (IMXRT_GPT_t *)&IMXRT_GPT1) + GPT_t<0>::end(); + + else if (regs == (IMXRT_GPT_t *)&IMXRT_GPT2) + GPT_t<1>::end(); + else + postError(errorCode::GTP_err); + } +} // namespace TeensyTimerTool + +#endif \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/GPT/GPTChannel.h b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.h similarity index 56% rename from third-party/TeensyTimerTool/src/Teensy/GPT/GPTChannel.h rename to third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.h index 6eabc3c..3ca482b 100644 --- a/third-party/TeensyTimerTool/src/Teensy/GPT/GPTChannel.h +++ b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTChannel.h @@ -1,7 +1,7 @@ #pragma once - -#include "../../ITimerChannel.h" +#include "Arduino.h" #include "GPTmap.h" +#include "ITimerChannel.h" #include "core_pins.h" namespace TeensyTimerTool @@ -9,8 +9,8 @@ namespace TeensyTimerTool class GptChannel : public ITimerChannel { public: - inline GptChannel(IMXRT_GPT_t*, callback_t*); - inline virtual ~GptChannel(); + inline GptChannel(IMXRT_GPT_t *, callback_t *); + virtual ~GptChannel(); inline errorCode begin(callback_t cb, float tcnt, bool periodic) override; inline errorCode start() override; @@ -18,26 +18,27 @@ namespace TeensyTimerTool inline errorCode trigger(float delay) override; inline errorCode triggerDirect(uint32_t delay) override; - inline errorCode getTriggerReload(float delay, uint32_t* reload) override; - - inline float getMaxPeriod() const override { return getMaxMicros() / 1E6; } + inline errorCode getTriggerReload(float delay, uint32_t *reload) override; + inline errorCode setNextPeriod(float us) override; + inline errorCode setPeriod(float us) override; + inline float getMaxPeriod() const override { return getMaxMicros() / 1E6; } bool periodic; + protected: - inline uint32_t microsecondToCycles(float micros) const; + inline uint32_t us2ticks(float micros) const; inline float getMaxMicros() const; - - IMXRT_GPT_t* regs; - uint32_t reload; + IMXRT_GPT_t *regs; + //uint32_t reload; float clock; }; // IMPLEMENTATION ============================================== - GptChannel::GptChannel(IMXRT_GPT_t* registers, callback_t* cbStorage) + GptChannel::GptChannel(IMXRT_GPT_t *registers, callback_t *cbStorage) : ITimerChannel(cbStorage), regs(registers) { clock = (CCM_CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL) ? 24 : (F_BUS_ACTUAL / 1000000); @@ -48,8 +49,7 @@ namespace TeensyTimerTool this->periodic = periodic; if (periodic) { - reload = microsecondToCycles(period); - regs->OCR1 = reload; + regs->OCR1 = us2ticks(period); } setCallback(cb); @@ -71,34 +71,28 @@ namespace TeensyTimerTool return errorCode::OK; } - GptChannel::~GptChannel() - { - stop(); - setCallback(nullptr); - } - errorCode GptChannel::trigger(float delay) //should be optimized somehow { - return triggerDirect(microsecondToCycles(delay)); + return triggerDirect(us2ticks(delay)); } errorCode GptChannel::triggerDirect(uint32_t reload) { - regs->SR = 0x3F; // clear all interupt flags - regs->IR = GPT_IR_OF1IE; // enable OF1 interrupt - regs->OCR1 = reload; // set overflow value - regs->CR |= GPT_CR_EN; // enable timer + regs->SR = 0x3F; // clear all interupt flags + regs->IR = GPT_IR_OF1IE; // enable OF1 interrupt + regs->OCR1 = reload; // set overflow value + regs->CR |= GPT_CR_EN; // enable timer return errorCode::OK; } - errorCode GptChannel::getTriggerReload(float delay, uint32_t* reload) + errorCode GptChannel::getTriggerReload(float delay, uint32_t *reload) { - *reload = microsecondToCycles(delay); + *reload = us2ticks(delay); return errorCode::OK; } - uint32_t GptChannel::microsecondToCycles(float micros) const + uint32_t GptChannel::us2ticks(float micros) const { if (micros > getMaxMicros()) { @@ -113,4 +107,23 @@ namespace TeensyTimerTool return (float)0xFFFF'FFFE / clock; } + errorCode GptChannel::setNextPeriod(float us) + { + return errorCode::notImplemented; + } + + errorCode GptChannel::setPeriod(float us) // not good, will generate one too long period if called before cnt == oldPeriod + { // need to redo the timing using free running timer to get setPeriod and setNewPeriod working correctly + uint32_t newPeriod = us2ticks(us); + // uint32_t now = regs->CNT; + + // if (now > newPeriod) + // { + // (*pCallback)(); // might generate reentrance issues, not a good idea... + // } + + regs->OCR1 = newPeriod; + return errorCode::OK; + } + } // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/GPT/GPTmap.h b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTmap.h similarity index 95% rename from third-party/TeensyTimerTool/src/Teensy/GPT/GPTmap.h rename to third-party/TeensyTimerTool/src/TimerModules/GPT/GPTmap.h index 63bdf94..cf62ea4 100644 --- a/third-party/TeensyTimerTool/src/Teensy/GPT/GPTmap.h +++ b/third-party/TeensyTimerTool/src/TimerModules/GPT/GPTmap.h @@ -1,7 +1,7 @@ #pragma once +#include "imxrt.h" #include -#include namespace TeensyTimerTool { diff --git a/third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.cpp b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.cpp similarity index 62% rename from third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.cpp rename to third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.cpp index 92c76d2..3229750 100644 --- a/third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.cpp +++ b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.cpp @@ -4,10 +4,10 @@ namespace TeensyTimerTool { - bool PIT_t::isInitialized = false; + bool PIT_t::isInitialized = false; PITChannel PIT_t::channel[4] = {{0}, {1}, {2}, {3}}; - uint32_t PITChannel::clockFactor = 1; -} + uint32_t PITChannel::clockFactor = 1; +} // namespace TeensyTimerTool #endif \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.h b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.h similarity index 93% rename from third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.h rename to third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.h index 1cb8600..50720cd 100644 --- a/third-party/TeensyTimerTool/src/Teensy/PIT4/PIT.h +++ b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PIT.h @@ -7,7 +7,7 @@ namespace TeensyTimerTool class PIT_t { public: - inline static ITimerChannel* getTimer(); + inline static ITimerChannel *getTimer(); protected: static bool isInitialized; @@ -17,7 +17,7 @@ namespace TeensyTimerTool // IMPLEMENTATION =========================================================================== - ITimerChannel* PIT_t::getTimer() + ITimerChannel *PIT_t::getTimer() { if (!isInitialized) { @@ -67,4 +67,4 @@ namespace TeensyTimerTool asm volatile("dsb"); //wait until register changes propagated through the cache } -} +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/Teensy/PIT4/PITChannel.h b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PITChannel.h similarity index 89% rename from third-party/TeensyTimerTool/src/Teensy/PIT4/PITChannel.h rename to third-party/TeensyTimerTool/src/TimerModules/PIT4/PITChannel.h index 5d688d7..a018990 100644 --- a/third-party/TeensyTimerTool/src/Teensy/PIT4/PITChannel.h +++ b/third-party/TeensyTimerTool/src/TimerModules/PIT4/PITChannel.h @@ -1,8 +1,7 @@ #pragma once -#include "../../ITimerChannel.h" #include "Arduino.h" -#include "PITMap.h" +#include "ITimerChannel.h" namespace TeensyTimerTool { @@ -34,8 +33,8 @@ namespace TeensyTimerTool inline void isr(); - PITChannel() = delete; - PITChannel(const PITChannel&) = delete; + PITChannel() = delete; + PITChannel(const PITChannel &) = delete; const unsigned chNr; callback_t callback = nullptr; @@ -50,19 +49,19 @@ namespace TeensyTimerTool PITChannel::PITChannel(unsigned nr) : ITimerChannel(nullptr), chNr(nr) { - callback = nullptr; + callback = nullptr; clockFactor = (CCM_CSCMR1 & CCM_CSCMR1_PERCLK_CLK_SEL) ? 24 : (F_BUS_ACTUAL / 1000000); } errorCode PITChannel::begin(callback_t cb, float micros, bool periodic) { isPeriodic = periodic; - callback = cb; + callback = cb; if (isPeriodic) { IMXRT_PIT_CHANNELS[chNr].TCTRL = 0; - IMXRT_PIT_CHANNELS[chNr].TFLG = 1; + IMXRT_PIT_CHANNELS[chNr].TFLG = 1; setNextPeriod(micros); // float tmp = micros * clockFactor; @@ -106,7 +105,7 @@ namespace TeensyTimerTool errorCode PITChannel::setPeriod(float us) { - stop(); // need to stop/start timer to change current period (see ch 53.9.5.4) + stop(); // need to stop/start timer to change current period (see ch 53.9.5.4) setNextPeriod(us); start(); return errorCode::OK; @@ -129,7 +128,7 @@ namespace TeensyTimerTool errorCode PITChannel::trigger(float delay) //should be optimized somehow { IMXRT_PIT_CHANNELS[chNr].TCTRL = 0; - IMXRT_PIT_CHANNELS[chNr].TFLG = 1; + IMXRT_PIT_CHANNELS[chNr].TFLG = 1; float tmp = delay * clockFactor; if (tmp > 0xFFFF'FFFF) diff --git a/third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.cpp b/third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.cpp new file mode 100644 index 0000000..a42bc77 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.cpp @@ -0,0 +1,40 @@ +#include "config.h" + +#if defined(TEENSYDUINO) + +#include "TCK.h" + +namespace TeensyTimerTool +{ + bool TCK_t::isInitialized = false; + TckChannelBase *TCK_t::channels[NR_OF_TCK_TIMERS]; +} // namespace TeensyTimerTool + +//---------------------------------------------------------------------- +#if YIELD_TYPE == YIELD_OPTIMIZED + +void yield() +{ + TeensyTimerTool::TCK_t::tick(); +} + +//---------------------------------------------------------------------- +#elif YIELD_TYPE == YIELD_STANDARD + +#include "EventResponder.h" + +namespace TeensyTimerTool +{ + static EventResponder er; + + void initYieldHook() + { + er.attach([](EventResponderRef r) { + TeensyTimerTool::TCK_t::tick(); + r.triggerEvent(); + }); + er.triggerEvent(); + } +} // namespace TeensyTimerTool +#endif +#endif diff --git a/third-party/TeensyTimerTool/src/Teensy/TCK/TCK.h b/third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.h similarity index 62% rename from third-party/TeensyTimerTool/src/Teensy/TCK/TCK.h rename to third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.h index c9eadc5..c697187 100644 --- a/third-party/TeensyTimerTool/src/Teensy/TCK/TCK.h +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/TCK.h @@ -1,6 +1,6 @@ #pragma once -//#include "TckChannelBase.h" +//#include "Arduino.h" #include "TckChannel.h" #include "core_pins.h" @@ -11,19 +11,20 @@ namespace TeensyTimerTool class TCK_t { public: - template static inline ITimerChannel* getTimer(); - static inline void removeTimer(TckChannelBase*); + template + static inline ITimerChannel *getTimer(); + static inline void removeTimer(TckChannelBase *); static inline void tick(); protected: static bool isInitialized; - static TckChannelBase* channels[NR_OF_TCK_TIMERS]; + static TckChannelBase *channels[NR_OF_TCK_TIMERS]; }; // IMPLEMENTATION ================================================================== - template - ITimerChannel* TCK_t::getTimer() + template + ITimerChannel *TCK_t::getTimer() { if (!isInitialized) { @@ -33,17 +34,19 @@ namespace TeensyTimerTool } isInitialized = true; - // enable the cycle counter - ARM_DEMCR |= ARM_DEMCR_TRCENA; - ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; + // start the cycle counter if not already running + if (ARM_DWT_CYCCNT == ARM_DWT_CYCCNT) + { + ARM_DEMCR |= ARM_DEMCR_TRCENA; + ARM_DWT_CTRL |= ARM_DWT_CTRL_CYCCNTENA; + } - // initialize the yield hook - #if defined(TEENSYDUINO) && YIELD_TYPE == YIELD_STANDARD - extern void initYieldHook(); - initYieldHook(); - #endif +// initialize the yield hook +#if defined(TEENSYDUINO) && YIELD_TYPE == YIELD_STANDARD + extern void initYieldHook(); + initYieldHook(); +#endif } - for (unsigned chNr = 0; chNr < NR_OF_TCK_TIMERS; chNr++) { if (channels[chNr] == nullptr) @@ -52,18 +55,16 @@ namespace TeensyTimerTool return channels[chNr]; } } - return nullptr; } - void TCK_t::removeTimer(TckChannelBase* channel) + void TCK_t::removeTimer(TckChannelBase *channel) { for (unsigned chNr = 0; chNr < NR_OF_TCK_TIMERS; chNr++) { if (channels[chNr] == channel) { channels[chNr] = nullptr; - delete channel; break; } } @@ -79,4 +80,4 @@ namespace TeensyTimerTool } } } -} +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannel.h b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannel.h new file mode 100644 index 0000000..0c6b7f7 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannel.h @@ -0,0 +1,144 @@ +#pragma once + +//#include "Arduino.h" +#include "ErrorHandling/error_codes.h" +#include "TckChannelBase.h" + +namespace TeensyTimerTool +{ + template // tckCounter is the underlying counter, e.g. 32bit cycle counter, RTC counter, micros counter etc + class TckChannel : public TckChannelBase + { + using counter_t = typename tckCounter::counter_t; // use the counter type (uint32_t, unit64_t...) of the used tckCounter class + + public: + TckChannel(); + + inline errorCode begin(callback_t cb, float period, bool periodic) override; + inline errorCode start() override; + inline errorCode stop() override; + + inline errorCode trigger(float delay_us) override; + inline errorCode triggerDirect(counter_t reload) override; + inline errorCode getTriggerReload(float delay, counter_t *reload) override; + + inline errorCode setNextPeriod(float us) override; + inline errorCode setPeriod(float us) override; + + float getMaxPeriod() const override { return tckCounter::getMaxMicros() / 1E6f; } // seconds + + protected: + inline bool tick(); + callback_t callback; + counter_t startCnt, currentPeriod, nextPeriod; + + bool periodic; + bool triggered; + }; + + // IMPLEMENTATION ============================================== + + template + TckChannel::TckChannel() + { + triggered = false; + } + + template + errorCode TckChannel::begin(callback_t cb, float period, bool periodic) + { + this->triggered = false; + + this->periodic = periodic; + if (periodic) + { + this->currentPeriod = tckCounter::us2ticks(period); + this->nextPeriod = this->currentPeriod; + } + this->callback = cb; + + return errorCode::OK; + } + + template + errorCode TckChannel::start() + { + this->startCnt = tckCounter::getCount(); + this->triggered = true; + return errorCode::OK; + } + + template + errorCode TckChannel::stop() + { + this->triggered = false; + return errorCode::OK; + } + + template + errorCode TckChannel::triggerDirect(counter_t reload) + { + this->startCnt = tckCounter::getCount(); + this->nextPeriod = reload; + this->currentPeriod = this->nextPeriod; + this->triggered = true; + return errorCode::OK; + } + + template + errorCode TckChannel::trigger(float delay) // µs + { + return triggerDirect(tckCounter::us2ticks(delay)); + } + + template + errorCode TckChannel::getTriggerReload(float delay, counter_t *reload) + { + *reload = tckCounter::us2ticks(delay); + return errorCode::OK; + } + + template + errorCode TckChannel::setNextPeriod(float us) + { + nextPeriod = tckCounter::us2ticks(us); + return errorCode::OK; + } + + template + errorCode TckChannel::setPeriod(float us) + { + counter_t newPeriod = tckCounter::us2ticks(us); + counter_t now = tckCounter::getCount(); + + if (now - startCnt >= newPeriod) // new period already expired + { // + startCnt = now; // -> restart cycle but, + callback(); // since expired, invoke callback now + } // + currentPeriod = newPeriod; // in any case next callback will + nextPeriod = newPeriod; // be invoked after newly set period + return errorCode::OK; + } + + template + bool TckChannel::tick() + { + static bool lock = false; + counter_t now = tckCounter::getCount(); + if (!lock && this->currentPeriod != 0 && this->triggered && (now - this->startCnt) >= this->currentPeriod) + { + lock = true; + this->startCnt += currentPeriod; + this->currentPeriod = nextPeriod; // update period if it was changed during current cycle. + this->triggered = this->periodic; // i.e., stays triggerd if periodic, stops if oneShot + callback(); + lock = false; + return true; + } else + { + return false; + } + } + +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.cpp b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.cpp new file mode 100644 index 0000000..0eeebe8 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.cpp @@ -0,0 +1,15 @@ +#if defined(TEENSYDUINO) + +#include "TckChannelBase.h" +#include "Arduino.h" +#include "TCK.h" + +namespace TeensyTimerTool +{ + TckChannelBase::~TckChannelBase() + { + TCK_t::removeTimer(this); + } +} // namespace TeensyTimerTool + +#endif \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/TCK/TckChannelBase.h b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.h similarity index 67% rename from third-party/TeensyTimerTool/src/Teensy/TCK/TckChannelBase.h rename to third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.h index 61990cd..79b834e 100644 --- a/third-party/TeensyTimerTool/src/Teensy/TCK/TckChannelBase.h +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/TckChannelBase.h @@ -8,8 +8,6 @@ namespace TeensyTimerTool { public: virtual bool tick() = 0; - virtual ~TckChannelBase() = 0; + virtual ~TckChannelBase(); }; - - inline TckChannelBase::~TckChannelBase() {} } \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.cpp b/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.cpp new file mode 100644 index 0000000..61610d2 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.cpp @@ -0,0 +1,108 @@ + +#include "tickCounters.h" +#include "Arduino.h" +#include "boardDef.h" + +#if defined(TTT_TEENSY4X) +#define TTT_F_CPU F_CPU_ACTUAL +#else +#define TTT_F_CPU F_CPU +#endif + +namespace TeensyTimerTool +{ + //--------------------------------------------------------------------- + // CycleCounter32 + + uint32_t CycleCounter32::getCount() + { + return ARM_DWT_CYCCNT; + } + + uint32_t CycleCounter32::us2ticks(float us) + { + return us * (TTT_F_CPU / 1E6f); + } + + float CycleCounter32::getMaxMicros() + { + return 5E6; //Can't use full 2^32 *1.66ns =7.2s range since we need some headroom to detect reaching target. This works if we call tick() at least once per 2 seconds + } + + //--------------------------------------------------------------------- + // CycleCounter64 + + uint64_t CycleCounter64::getCount() + { + static uint32_t lastCyCnt = ARM_DWT_CYCCNT; + static uint32_t curHIGH = 0; + + uint32_t now = ARM_DWT_CYCCNT; + if (now < lastCyCnt) + { + curHIGH++; + } + lastCyCnt = now; + return ((uint64_t)curHIGH << 32) | now; + } + + uint64_t CycleCounter64::us2ticks(float us) + { + return us * (TTT_F_CPU / 1E6f); + } + + float CycleCounter64::getMaxMicros() + { + return 2E16f; //~630 years can't use full 2^64 *1.66ns range since we need some headroom to detect reaching target. + } + + //------------------------------------------------------------------ + // MicrosCounter + + uint32_t MicrosCounter::getCount() + { + return micros(); + } + + uint32_t MicrosCounter::us2ticks(float us) + { + return us; + } + + float MicrosCounter::getMaxMicros() + { + return 70 * 60 * 1E6; // 70min, can't use full 2^32 µs = 72min range since we need some headroom to detect reaching target. This works if we call tick() at least once per 2min + } + +#if defined(TTT_TEENSY4X) + //------------------------------------------------------------------ + // RtcCounter + + uint64_t RtcCounter::getCount() + { + uint32_t hi1 = SNVS_HPRTCMR, lo1 = SNVS_HPRTCLR; + while (true) + { + uint32_t hi2 = SNVS_HPRTCMR, lo2 = SNVS_HPRTCLR; + if (lo1 == lo2 && hi1 == hi2) + { + return (uint64_t)hi2 << 32 | lo2; + } + hi1 = hi2; + lo1 = lo2; + } + } + + uint64_t RtcCounter::us2ticks(float us) + { + return us * (32'768 / 1E6f); + } + + float RtcCounter::getMaxMicros() + { + return 2E16f; // ~630 years + } + +#endif + +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.h b/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.h new file mode 100644 index 0000000..7a8b8b4 --- /dev/null +++ b/third-party/TeensyTimerTool/src/TimerModules/TCK/tickCounters.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +namespace TeensyTimerTool +{ + class CycleCounterBase + { + protected: + CycleCounterBase(); + }; + + //--------------------------------------------------------------------- + // Software counter based on the 32bit ARM cycle counter + // Resolution 1/FCPU_ACTUAL (1.66ns @600MHz) + // + struct CycleCounter32 : CycleCounterBase + { + using counter_t = uint32_t; + + static counter_t getCount(); + static uint32_t us2ticks(float us); + static float getMaxMicros(); + }; + + //--------------------------------------------------------------------- + // Software counter based on a 64bit extension of + // the ARM cycle counter + // Resolution 1/FCPU_ACTUAL (6.66ns @600MHz) + // + struct CycleCounter64 : CycleCounterBase + { + using counter_t = uint64_t; + + static uint64_t getCount(); + static uint64_t us2ticks(float us); + static float getMaxMicros(); + }; + + //------------------------------------------------------------------ + // Software counter based on the 64bit period counter + // of the built in real time clock (RTC). + // Resolution: 1/32768s (30.5 µs) + // + struct RtcCounter + { + using counter_t = uint64_t; + + static counter_t getCount(); + static counter_t us2ticks(float us); + static float getMaxMicros(); + }; + + //------------------------------------------------------------------ + // Fallback counter for boards without cycle counter + // E.g. Teensy LC + // Resolution: 1 µs + // + struct MicrosCounter + { + using counter_t = uint32_t; + + static counter_t getCount(); + static counter_t us2ticks(float us); + static float getMaxMicros(); + }; + +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/Teensy/TMR/TMR.h b/third-party/TeensyTimerTool/src/TimerModules/TMR/TMR.h similarity index 63% rename from third-party/TeensyTimerTool/src/Teensy/TMR/TMR.h rename to third-party/TeensyTimerTool/src/TimerModules/TMR/TMR.h index 57fac66..2e1e526 100644 --- a/third-party/TeensyTimerTool/src/Teensy/TMR/TMR.h +++ b/third-party/TeensyTimerTool/src/TimerModules/TMR/TMR.h @@ -9,7 +9,7 @@ namespace TeensyTimerTool class TMR_t { public: - static ITimerChannel* getTimer(); + static ITimerChannel *getTimer(); protected: static bool isInitialized; @@ -17,33 +17,37 @@ namespace TeensyTimerTool static callback_t callbacks[4]; // the following is calculated at compile time - static constexpr IRQ_NUMBER_t irq = moduleNr == 0 ? IRQ_QTIMER1 : moduleNr == 1 ? IRQ_QTIMER2 : moduleNr == 2 ? IRQ_QTIMER3 : IRQ_QTIMER4; - static IMXRT_TMR_t* const pTMR; - static IMXRT_TMR_CH_t* const pCH0; - static IMXRT_TMR_CH_t* const pCH1; - static IMXRT_TMR_CH_t* const pCH2; - static IMXRT_TMR_CH_t* const pCH3; + static constexpr IRQ_NUMBER_t irq = moduleNr == 0 ? IRQ_QTIMER1 : moduleNr == 1 ? IRQ_QTIMER2 + : moduleNr == 2 ? IRQ_QTIMER3 + : IRQ_QTIMER4; + static IMXRT_TMR_t *const pTMR; + static IMXRT_TMR_CH_t *const pCH0; + static IMXRT_TMR_CH_t *const pCH1; + static IMXRT_TMR_CH_t *const pCH2; + static IMXRT_TMR_CH_t *const pCH3; static_assert(moduleNr < 4, "Module number < 4 required"); }; // IMPLEMENTATION ================================================================== - template IMXRT_TMR_t* const TMR_t::pTMR = moduleNr == 0 ? &IMXRT_TMR1 : moduleNr == 1 ? &IMXRT_TMR2 : moduleNr == 2 ? &IMXRT_TMR3 : &IMXRT_TMR4; - template IMXRT_TMR_CH_t* const TMR_t::pCH0 = &pTMR->CH[0]; - template IMXRT_TMR_CH_t* const TMR_t::pCH1 = &pTMR->CH[1]; - template IMXRT_TMR_CH_t* const TMR_t::pCH2 = &pTMR->CH[2]; - template IMXRT_TMR_CH_t* const TMR_t::pCH3 = &pTMR->CH[3]; + template IMXRT_TMR_t *const TMR_t::pTMR = moduleNr == 0 ? &IMXRT_TMR1 : moduleNr == 1 ? &IMXRT_TMR2 + : moduleNr == 2 ? &IMXRT_TMR3 + : &IMXRT_TMR4; + template IMXRT_TMR_CH_t *const TMR_t::pCH0 = &pTMR->CH[0]; + template IMXRT_TMR_CH_t *const TMR_t::pCH1 = &pTMR->CH[1]; + template IMXRT_TMR_CH_t *const TMR_t::pCH2 = &pTMR->CH[2]; + template IMXRT_TMR_CH_t *const TMR_t::pCH3 = &pTMR->CH[3]; template - ITimerChannel* TMR_t::getTimer() + ITimerChannel *TMR_t::getTimer() { if (!isInitialized) { for (unsigned chNr = 0; chNr < 4; chNr++) { pTMR->CH[chNr].CTRL = 0x0000; - callbacks[chNr] = nullptr; + callbacks[chNr] = nullptr; } attachInterruptVector(irq, isr); // start NVIC_ENABLE_IRQ(irq); @@ -53,7 +57,7 @@ namespace TeensyTimerTool for (unsigned chNr = 0; chNr < 4; chNr++) { - IMXRT_TMR_CH_t* pCh = &pTMR->CH[chNr]; + IMXRT_TMR_CH_t *pCh = &pTMR->CH[chNr]; if (pCh->CTRL == 0x0000) { return new TMRChannel(pCh, &callbacks[chNr]); @@ -97,4 +101,4 @@ namespace TeensyTimerTool template callback_t TMR_t::callbacks[4]; -} +} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/Teensy/TMR/TMRChannel.h b/third-party/TeensyTimerTool/src/TimerModules/TMR/TMRChannel.h similarity index 55% rename from third-party/TeensyTimerTool/src/Teensy/TMR/TMRChannel.h rename to third-party/TeensyTimerTool/src/TimerModules/TMR/TMRChannel.h index 5ebbe06..0e45de9 100644 --- a/third-party/TeensyTimerTool/src/Teensy/TMR/TMRChannel.h +++ b/third-party/TeensyTimerTool/src/TimerModules/TMR/TMRChannel.h @@ -1,42 +1,43 @@ #pragma once #include "../../ITimerChannel.h" //#include "Arduino.h" -#include #include "ErrorHandling/error_codes.h" #include "config.h" #include "imxrt.h" +#include namespace TeensyTimerTool { class TMRChannel : public ITimerChannel { public: - inline TMRChannel(IMXRT_TMR_CH_t* regs, callback_t* cbStorage); + inline TMRChannel(IMXRT_TMR_CH_t *regs, callback_t *cbStorage); inline virtual ~TMRChannel(); - + inline errorCode begin(callback_t cb, float tcnt, bool periodic) override; inline errorCode start() override; inline errorCode stop() override; - + inline errorCode trigger(float tcnt) override; inline float getMaxPeriod() const override; inline errorCode setPeriod(float us) override; + inline errorCode setNextPeriod(float us) override; inline void setPrescaler(uint32_t psc); // psc 0..7 -> prescaler: 1..128 protected: - IMXRT_TMR_CH_t* regs; - callback_t** pCallback = nullptr; + IMXRT_TMR_CH_t *regs; + callback_t **pCallback = nullptr; float pscValue; uint32_t pscBits; - inline float_t microsecondToCounter(const float_t us) const; - inline float_t counterToMicrosecond(const float_t cnt) const; + errorCode us2Ticks(const float us, uint16_t *ticks) const; + inline float_t counterToMicrosecond(const float_t cnt) const; }; // IMPLEMENTATION ============================================== - TMRChannel::TMRChannel(IMXRT_TMR_CH_t* regs, callback_t* cbStorage) + TMRChannel::TMRChannel(IMXRT_TMR_CH_t *regs, callback_t *cbStorage) : ITimerChannel(cbStorage) { this->regs = regs; @@ -45,12 +46,13 @@ namespace TeensyTimerTool TMRChannel::~TMRChannel() { + regs->CTRL = 0x0000; // stop timer and mark it free } errorCode TMRChannel::start() { regs->CNTR = 0x0000; - + regs->CSCTRL &= ~TMR_CSCTRL_TCF1; regs->CSCTRL |= TMR_CSCTRL_TCF1EN; return errorCode::OK; @@ -62,25 +64,17 @@ namespace TeensyTimerTool return errorCode::OK; } - - errorCode TMRChannel::begin(callback_t cb, float tcnt, bool periodic) + errorCode TMRChannel::begin(callback_t cb, float period, bool periodic) { - const float_t t = microsecondToCounter(tcnt); uint16_t reload; - if (t > 0xFFFF) - { - postError(errorCode::periodOverflow); - reload = 0xFFFE; - } else - { - reload = (uint16_t)t - 1; - } + errorCode status = us2Ticks(period, &reload); - regs->CTRL = 0x0000; - regs->LOAD = 0x0000; - regs->COMP1 = reload; + regs->CTRL = 0x0000; + regs->LOAD = 0x0000; + regs->COMP1 = reload; regs->CMPLD1 = reload; - regs->CNTR = 0x0000; + regs->CNTR = 0x0000; + regs->CSCTRL = TMR_CSCTRL_CL1(1); setCallback(cb); if (!periodic) @@ -90,33 +84,35 @@ namespace TeensyTimerTool regs->CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(pscBits) | TMR_CTRL_LENGTH; start(); - return t > 0xFFFF ? errorCode::periodOverflow : errorCode::OK; + return status; } - - errorCode TMRChannel::trigger(float tcnt) // quick and dirty, should be optimized + errorCode TMRChannel::trigger(float us) // quick and dirty, should be optimized { - const float_t t = microsecondToCounter(tcnt); - uint16_t reload = t > 0xFFFF ? 0xFFFF : (uint16_t)t; + // const float_t t = us2Ticks(tcnt); + // uint16_t reload = t > 0xFFFF ? 0xFFFF : (uint16_t)t; - regs->CTRL = 0x0000; - regs->LOAD = 0x0000; - regs->COMP1 = reload; + uint16_t reload; + errorCode status = us2Ticks(us, &reload); + + regs->CTRL = 0x0000; + regs->LOAD = 0x0000; + regs->COMP1 = reload; regs->CMPLD1 = reload; - regs->CNTR = 0x0000; + regs->CNTR = 0x0000; regs->CSCTRL &= ~TMR_CSCTRL_TCF1; regs->CSCTRL |= TMR_CSCTRL_TCF1EN; regs->CTRL = TMR_CTRL_CM(1) | TMR_CTRL_PCS(pscBits) | TMR_CTRL_ONCE | TMR_CTRL_LENGTH; - return errorCode::OK; + return status; } void TMRChannel::setPrescaler(uint32_t psc) // psc 0..7 -> prescaler: 1..128 { pscValue = 1 << (psc & 0b0111); - pscBits = 0b1000 | (psc & 0b0111); + pscBits = 0b1000 | (psc & 0b0111); } float TMRChannel::getMaxPeriod() const @@ -124,10 +120,13 @@ namespace TeensyTimerTool return pscValue / 150'000'000.0f * 0xFFFE; } - // void TMRChannel::_setNextPeriod(const uint16_t cnt) - // { - // regs->CMPLD1 = cnt; - // } + errorCode TMRChannel::setNextPeriod(float us) + { + uint16_t reload; + errorCode status = us2Ticks(us, &reload); + regs->CMPLD1 = reload; + return status; + } // errorCode TMRChannel::_setCurrentPeriod(const uint16_t cnt) // { @@ -152,22 +151,33 @@ namespace TeensyTimerTool errorCode TMRChannel::setPeriod(float us) { - //const float_t t = microsecondToCounter(us); - - // if (t <= 0xFFFF) - // { - // return _setCurrentPeriod(t); - // } else - // { - // return errorCode::periodOverflow; - // } - return errorCode::notImplemented; + uint16_t newReload; + errorCode status = us2Ticks(us, &newReload); + + regs->CMPLD1 = newReload; // counter will load this value to COMP1 at next trigger + // + noInterrupts(); // interrupting this code could lead to wrong cntr settings + if (regs->CNTR > newReload) // already too late for new period + regs->CNTR = regs->COMP1; // -> force trigger; will also load COMP1 with value from CMPLD1 + else // not too late + regs->COMP1 = newReload; // -> change current compare value to new one (counter _might_ be > newReload in between.. watch and fix if necessary) + interrupts(); + + return status; } - - float_t TMRChannel::microsecondToCounter(const float_t us) const + errorCode TMRChannel::us2Ticks(const float us, uint16_t *ticks) const { - return us * 150.0f / pscValue; + constexpr uint16_t maxTicks = 0xFFFE; + + float tmpTicks = us * 150.0f / pscValue; + if (tmpTicks > maxTicks) + { + *ticks = maxTicks; + return errorCode::periodOverflow; + } + *ticks = (uint16_t)tmpTicks; + return errorCode::OK; } float_t TMRChannel::counterToMicrosecond(const float_t cnt) const diff --git a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.cpp b/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.cpp deleted file mode 100644 index dbb4cb6..0000000 --- a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.cpp +++ /dev/null @@ -1,14 +0,0 @@ -//#include "../../TeensyTimerTool.h" -#include "../../config.h" - -#if defined(HAS_TCK) and defined(UNO) - -namespace TeensyTimerTool -{ - bool TCK_t::isInitialized = false; - TckChannel* TCK_t::channels[maxTckChannels]; -} - -void yield() { TeensyTimerTool::TCK_t::tick(); } - -#endif diff --git a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.h b/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.h deleted file mode 100644 index aa64b60..0000000 --- a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TCK.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include "TckChannel.h" -#include -#include - -namespace TeensyTimerTool -{ - constexpr unsigned maxTckChannels = 20; - - class TCK_t - { - public: - static inline ITimerChannel* getTimer(); - static inline void removeTimer(TckChannel*); - static inline void tick(); - - protected: - static bool isInitialized; - static TckChannel* channels[maxTckChannels]; - }; - - // IMPLEMENTATION ================================================================== - - ITimerChannel* TCK_t::getTimer() - { - Serial.printf("TCK getTimer()\n"); - - if (!isInitialized) - { - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - channels[chNr] = nullptr; - } - isInitialized = true; - } - - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - if (channels[chNr] == nullptr) - { - channels[chNr] = new TckChannel(); - return channels[chNr]; - } - } - - return nullptr; - } - - void TCK_t::removeTimer(TckChannel* channel) - { - for (unsigned chNr = 0; chNr < maxTckChannels; chNr++) - { - if (channels[chNr] == channel) - { - channels[chNr] = nullptr; - delete channel; - break; - } - } - } - - void TCK_t::tick() - { - digitalWriteFast(12,HIGH); - for(unsigned i = 0; i < maxTckChannels; i++) - { - if (channels[i] != nullptr ) - { - channels[i]->tick(); - } - } - digitalWriteFast(12,LOW); - } - - - //constexpr TimerGenerator* TCK = TCK_t::getTimer; - -} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TckChannel.h b/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TckChannel.h deleted file mode 100644 index bd3089b..0000000 --- a/third-party/TeensyTimerTool/src/Uno-dummy/TCK/TckChannel.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include "../ITimerChannel.h" -#include "../types.h" -#include "Arduino.h" - -namespace TeensyTimerTool -{ - class TCK_t; - - class TckChannel : public ITimerChannel - { - public: - inline TckChannel() { triggered = false; } - inline virtual ~TckChannel(){}; - - inline void begin(callback_t cb, unsigned period, bool periodic) - { - Serial.println("begin"); - - triggered = false; - this->periodic = periodic; - this->period = period * (F_CPU / 1'000'000); - this->callback = cb; - - startCNT = ARM_DWT_CYCCNT; - } - - inline void start() - { - Serial.println("start"); - - this->startCNT = ARM_DWT_CYCCNT; - this->triggered = true; - } - - inline void stop() - { - this->triggered = false; - } - - // inline void setPeriod(uint32_t microSeconds); - inline uint32_t getPeriod(void); - - inline void trigger(uint32_t delay) // µs - { - this->startCNT = ARM_DWT_CYCCNT; - this->period = delay * (F_CPU / 1'000'000) - 68; - this->triggered = true; - } - - protected: - uint32_t startCNT, period; - callback_t callback; - bool triggered; - bool periodic; - - inline void tick(); - bool block = false; - - friend TCK_t; - }; - - // IMPLEMENTATION ============================================== - - void TckChannel::tick() - { - static bool lock = false; - - if (!lock && period != 0 && triggered && (ARM_DWT_CYCCNT - startCNT) >= period) - { - lock = true; - startCNT = ARM_DWT_CYCCNT; - triggered = periodic; // i.e., stays triggerd if periodic, stops if oneShot - callback(); - lock = false; - } - } - - // void TckChannel::setPeriod(uint32_t microSeconds) - // { - // period = microSeconds * (F_CPU / 1'000'000) ; - // } - uint32_t TckChannel::getPeriod() - { - return period * (1'000'000.0f / F_CPU); - } - -} // namespace TeensyTimerTool diff --git a/third-party/TeensyTimerTool/src/baseTimer.cpp b/third-party/TeensyTimerTool/src/baseTimer.cpp deleted file mode 100644 index 3a548dd..0000000 --- a/third-party/TeensyTimerTool/src/baseTimer.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "baseTimer.h" -#include "Arduino.h" -#include "types.h" - -namespace TeensyTimerTool -{ - - BaseTimer::BaseTimer(TimerGenerator* generator, bool periodic) - : timerGenerator(generator) - { - this->timerGenerator = generator; - this->timerChannel = nullptr; - this->isPeriodic = periodic; - } - - errorCode BaseTimer::setPrescaler(int psc) - { - this->prescaler = psc; - return errorCode::OK; - } - -} \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/boardDef.h b/third-party/TeensyTimerTool/src/boardDef.h index 48fcb99..115a3a4 100644 --- a/third-party/TeensyTimerTool/src/boardDef.h +++ b/third-party/TeensyTimerTool/src/boardDef.h @@ -8,6 +8,11 @@ namespace TeensyTimerTool // TEENSYDUINO ========================================================================== #if defined(TEENSYDUINO) + #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY_MICROMOD) + #define TTT_TEENSY4X + #elif defined(ARDUINO_TEENSY30) || defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) || defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) + #define TTT_TEENSY3X + #endif #if defined(ARDUINO_TEENSYLC) extern TimerGenerator *const TCK; @@ -29,11 +34,11 @@ namespace TeensyTimerTool extern TimerGenerator *const FTM0, *const FTM1, *const FTM2, *const FTM3, *const FTM4; extern TimerGenerator *const TCK, * const TCK32, * const TCK64; - #elif defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY_MICROMOD) + #elif defined(TTT_TEENSY4X) extern TimerGenerator *const TMR1, *const TMR2, *const TMR3, *const TMR4; extern TimerGenerator *const GPT1, *const GPT2; extern TimerGenerator *const PIT; - extern TimerGenerator *const TCK, * const TCK32, * const TCK64; + extern TimerGenerator *const TCK, * const TCK32, * const TCK64, *const TCK_RTC; #else #error BOARD NOT SUPPORTED @@ -56,10 +61,6 @@ namespace TeensyTimerTool extern void(* const tick)(); - // ESP32 ========================================================================== - #elif defined(ESP32) - //... - #else # error "Board not supported" #endif diff --git a/third-party/TeensyTimerTool/src/config.cpp b/third-party/TeensyTimerTool/src/config.cpp index 91e0237..d7b47f3 100644 --- a/third-party/TeensyTimerTool/src/config.cpp +++ b/third-party/TeensyTimerTool/src/config.cpp @@ -1,88 +1,88 @@ #include "config.h" +#include "TimerModules/TCK/TCK.h" +#include "TimerModules/TCK/tickCounters.h" #include "boardDef.h" -using tick_t = void (*) (); +using tick_t = void (*)(); #if defined(ARDUINO_TEENSY40) || defined(ARDUINO_TEENSY41) || defined(ARDUINO_TEENSY_MICROMOD) - #include "Teensy/TMR/TMR.h" - #include "Teensy/GPT/GPT.h" - #include "Teensy/PIT4/PIT.h" - #include "Teensy/TCK/TCK.h" - - namespace TeensyTimerTool - { - TimerGenerator* const TMR1 = TMR_t<0>::getTimer; - TimerGenerator* const TMR2 = TMR_t<1>::getTimer; - TimerGenerator* const TMR3 = TMR_t<2>::getTimer; - TimerGenerator* const TMR4 = TMR_t<3>::getTimer; - - TimerGenerator* const GPT1 = GPT_t<0>::getTimer; - TimerGenerator* const GPT2 = GPT_t<1>::getTimer; - - TimerGenerator* const PIT = PIT_t::getTimer; - - TimerGenerator* const TCK = TCK_t::getTimer; - TimerGenerator* const TCK32 = TCK_t::getTimer; // same as TCK - TimerGenerator* const TCK64 = TCK_t::getTimer; - - constexpr tick_t tick = &TCK_t::tick; - } - -#elif defined (ARDUINO_TEENSY35) || defined (ARDUINO_TEENSY36) - #include "Teensy/FTM/FTM.h" - #include "Teensy/TCK/TCK.h" - - namespace TeensyTimerTool - { - TimerGenerator* const TCK = TCK_t::getTimer; - TimerGenerator* const TCK32 = TCK_t::getTimer; // same as TCK - TimerGenerator* const TCK64 = TCK_t::getTimer; - - TimerGenerator* const FTM0 = FTM_t<0>::getTimer; - TimerGenerator* const FTM1 = FTM_t<1>::getTimer; - TimerGenerator* const FTM2 = FTM_t<2>::getTimer; - TimerGenerator* const FTM3 = FTM_t<3>::getTimer; - TimerGenerator* const FTM4 = FTM_t<3>::getTimer; - - constexpr tick_t tick = &TCK_t::tick; - } - -#elif defined(ARDUINO_TEENSY31) || defined (ARDUINO_TEENSY32) - #include "Teensy/FTM/FTM.h" - #include "Teensy/TCK/TCK.h" - - namespace TeensyTimerTool - { - TimerGenerator* const TCK = TCK_t::getTimer; - TimerGenerator* const TCK32 = TCK_t::getTimer; // same as TCK - TimerGenerator* const TCK64 = TCK_t::getTimer; - - TimerGenerator* const FTM0 = FTM_t<0>::getTimer; - TimerGenerator* const FTM1 = FTM_t<1>::getTimer; - TimerGenerator* const FTM2 = FTM_t<2>::getTimer; - constexpr tick_t tick = &TCK_t::tick; - } +#include "TimerModules/GPT/GPT.h" +#include "TimerModules/PIT4/PIT.h" +#include "TimerModules/TMR/TMR.h" + +namespace TeensyTimerTool +{ + TimerGenerator *const TMR1 = TMR_t<0>::getTimer; + TimerGenerator *const TMR2 = TMR_t<1>::getTimer; + TimerGenerator *const TMR3 = TMR_t<2>::getTimer; + TimerGenerator *const TMR4 = TMR_t<3>::getTimer; + + TimerGenerator *const GPT1 = GPT_t<0>::getTimer; + TimerGenerator *const GPT2 = GPT_t<1>::getTimer; + + TimerGenerator *const PIT = PIT_t::getTimer; + + TimerGenerator *const TCK = TCK_t::getTimer; + TimerGenerator *const TCK32 = TCK_t::getTimer; // same as TCK + TimerGenerator *const TCK64 = TCK_t::getTimer; + TimerGenerator *const TCK_RTC = TCK_t::getTimer; + + constexpr tick_t tick = &TCK_t::tick; +} // namespace TeensyTimerTool + +#elif defined(ARDUINO_TEENSY35) || defined(ARDUINO_TEENSY36) +#include "TimerModules/FTM/FTM.h" + +namespace TeensyTimerTool +{ + TimerGenerator *const TCK = TCK_t::getTimer; + TimerGenerator *const TCK32 = TCK_t::getTimer; // same as TCK + TimerGenerator *const TCK64 = TCK_t::getTimer; + + TimerGenerator *const FTM0 = FTM_t<0>::getTimer; + TimerGenerator *const FTM1 = FTM_t<1>::getTimer; + TimerGenerator *const FTM2 = FTM_t<2>::getTimer; + TimerGenerator *const FTM3 = FTM_t<3>::getTimer; + TimerGenerator *const FTM4 = FTM_t<3>::getTimer; + + constexpr tick_t tick = &TCK_t::tick; +} // namespace TeensyTimerTool + +#elif defined(ARDUINO_TEENSY31) || defined(ARDUINO_TEENSY32) +#include "TimerModules/FTM/FTM.h" + +namespace TeensyTimerTool +{ + TimerGenerator *const TCK = TCK_t::getTimer; + TimerGenerator *const TCK32 = TCK_t::getTimer; // same as TCK + TimerGenerator *const TCK64 = TCK_t::getTimer; + + TimerGenerator *const FTM0 = FTM_t<0>::getTimer; + TimerGenerator *const FTM1 = FTM_t<1>::getTimer; + TimerGenerator *const FTM2 = FTM_t<2>::getTimer; + constexpr tick_t tick = &TCK_t::tick; +} // namespace TeensyTimerTool #elif defined(ARDUINO_TEENSY30) - #include "Teensy/FTM/FTM.h" - #include "Teensy/TCK/TCK.h" +#include "TimerModules/FTM/FTM.h" - namespace TeensyTimerTool - { - TimerGenerator* const TCK = TCK_t::getTimer; +namespace TeensyTimerTool +{ + TimerGenerator *const TCK = TCK_t::getTimer; + TimerGenerator *const TCK32 = TCK_t::getTimer; // same as TCK + TimerGenerator *const TCK64 = TCK_t::getTimer; - TimerGenerator* const FTM0 = FTM_t<0>::getTimer; - TimerGenerator* const FTM1 = FTM_t<1>::getTimer; - constexpr tick_t tick = &TCK_t::tick; - } + TimerGenerator *const FTM0 = FTM_t<0>::getTimer; + TimerGenerator *const FTM1 = FTM_t<1>::getTimer; + constexpr tick_t tick = &TCK_t::tick; +} // namespace TeensyTimerTool #elif defined(ARDUINO_TEENSYLC) - #include "Teensy/TCK/TCK.h" - namespace TeensyTimerTool - { - TimerGenerator* const TCK = TCK_t::getTimer; - constexpr tick_t tick = &TCK_t::tick; - } +namespace TeensyTimerTool +{ + TimerGenerator *const TCK = TCK_t::getTimer; + constexpr tick_t tick = &TCK_t::tick; +} // namespace TeensyTimerTool #endif diff --git a/third-party/TeensyTimerTool/src/config.h b/third-party/TeensyTimerTool/src/config.h index 6dd2eff..d74a5dd 100644 --- a/third-party/TeensyTimerTool/src/config.h +++ b/third-party/TeensyTimerTool/src/config.h @@ -1,7 +1,7 @@ #pragma once #if __has_include("userConfig.h") - #include "userConfig.h" +#include "userConfig.h" #else - #include "defaultConfig.h" +#include "defaultConfig.h" #endif diff --git a/third-party/TeensyTimerTool/src/defaultConfig.h b/third-party/TeensyTimerTool/src/defaultConfig.h index 45e286a..917ce68 100644 --- a/third-party/TeensyTimerTool/src/defaultConfig.h +++ b/third-party/TeensyTimerTool/src/defaultConfig.h @@ -78,7 +78,7 @@ namespace TeensyTimerTool //-------------------------------------------------------------------------------------------- // Use c++14 time literals (e.g. 3.4s, 50ms, _kHz...) for time inputs. Periods without literals are -// interpreted as microseconds. +// interpreted as microseconds. // Comment the following line if you don't want this. #define USE_TIME_LITERALS diff --git a/third-party/TeensyTimerTool/src/helpers.h b/third-party/TeensyTimerTool/src/helpers.h new file mode 100644 index 0000000..cdedbad --- /dev/null +++ b/third-party/TeensyTimerTool/src/helpers.h @@ -0,0 +1,41 @@ +#pragma once + +#include "config.h" +#include + +#if defined(USE_TIME_LITERALS) +#include "frequency.h" +#include +#endif + +namespace TeensyTimerTool +{ + //-------------------------------------------------------------- + // Transform arithmetic, period and frequency values to float + // For constant inputs the transformations are calculated at compile time + + // Arithmetic types + template ::value, int> * = nullptr> + float constexpr period2us(period_t v) + { + return (float)v; + } + +#if defined(USE_TIME_LITERALS) + + // Duration types (s, ms, ns...) + template ::value, int> * = nullptr> + float constexpr period2us(period_t v) + { + return (duration_cast>(v).count()); + } + + // Frequency types (Hz, MHz...) + template ::value, int> * = nullptr> + float constexpr period2us(period_t v) + { + return 1'000'000 / duration_cast(v).count(); + } +#endif + +} // namespace TeensyTimerTool \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/oneShotTimer.h b/third-party/TeensyTimerTool/src/oneShotTimer.h deleted file mode 100644 index a218e93..0000000 --- a/third-party/TeensyTimerTool/src/oneShotTimer.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include "ErrorHandling/error_codes.h" -#include "baseTimer.h" -#include "type_traits" - -namespace TeensyTimerTool -{ - class OneShotTimer : public BaseTimer - { - public: - inline OneShotTimer(TimerGenerator* generator = nullptr); - - inline errorCode begin(callback_t cb); - template errorCode trigger(T delay); - template errorCode triggerDirect(T reload); - template errorCode getTriggerReload(float delay, T* reload); - - #if defined(USE_TIME_LITERALS) - template - errorCode trigger(duration _delay) - { - T delay = duration_cast(_delay).count(); - return trigger(delay); - } - #endif - }; - - // Implementation ================================================ - - OneShotTimer::OneShotTimer(TimerGenerator* generator) - : BaseTimer(generator, false) - {} - - errorCode OneShotTimer::begin(callback_t callback) - { - return BaseTimer::begin(callback, 0, false); - } - - template - errorCode OneShotTimer::trigger(T delay) - { - static_assert(std::is_integral() || std::is_floating_point(), "Only floating point or integral types allowed"); - - errorCode result; - - if (std::is_floating_point()) - result = timerChannel->trigger((float)delay); - else - result = timerChannel->trigger((uint32_t)delay); - - return result; - } - - template - errorCode OneShotTimer::triggerDirect(T reload) - { - return timerChannel->triggerDirect(reload); - } - - template - errorCode OneShotTimer::getTriggerReload(float delay, T* reload) - { - return timerChannel->getTriggerReload(delay, reload); - } -} \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/periodicTimer.h b/third-party/TeensyTimerTool/src/periodicTimer.h deleted file mode 100644 index 021d781..0000000 --- a/third-party/TeensyTimerTool/src/periodicTimer.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "baseTimer.h" - -namespace TeensyTimerTool -{ - class PeriodicTimer : public BaseTimer - { - public: - PeriodicTimer(TimerGenerator* generator = nullptr) - : BaseTimer(generator, true) {} - - template ::value, int>* = nullptr> - errorCode setPeriod(T p) { return postError(timerChannel->setPeriod((float)p)); } - - template ::value, int>* = nullptr> - errorCode setNextPeriod(T p) { return postError(timerChannel->setNextPeriod((float)p)); } - }; - - // IMPLEMENTATION ===================================================================== - -} \ No newline at end of file diff --git a/third-party/TeensyTimerTool/src/types.h b/third-party/TeensyTimerTool/src/types.h index 7157a5b..9ee1f34 100644 --- a/third-party/TeensyTimerTool/src/types.h +++ b/third-party/TeensyTimerTool/src/types.h @@ -4,27 +4,26 @@ #if not defined(PLAIN_VANILLA_CALLBACKS) - #include - inline void std::__throw_bad_function_call() - { - while (1) {} // do whatever you want to do instead of an exception - } - namespace TeensyTimerTool - { - using callback_t = std::function; - using errorFunc_t = std::function; +#include +inline void std::__throw_bad_function_call() +{ + while (1) {} // do whatever you want to do instead of an exception +} +namespace TeensyTimerTool +{ + using callback_t = std::function; + using errorFunc_t = std::function; - extern void attachErrFunc(errorFunc_t); - extern errorCode postError(errorCode); - } + extern void attachErrFunc(errorFunc_t); + extern errorCode postError(errorCode); +} // namespace TeensyTimerTool #else - namespace TeensyTimerTool - { - using callback_t = void (*)(); - using errorFunc_t = void (*)(errorCode); +namespace TeensyTimerTool +{ + using callback_t = void (*)(); + using errorFunc_t = void (*)(errorCode); - extern void attachErrFunc(errorFunc_t); - extern errorCode postError(errorCode); - } + extern void attachErrFunc(errorFunc_t); + extern errorCode postError(errorCode); +} // namespace TeensyTimerTool #endif -