From c47e9b79ca50842427a1041e19475104e4921b01 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 2 Oct 2022 00:43:46 +0200 Subject: [PATCH] do analogRead without need for noInterrupt - first test --- DCCTimerAVR.cpp | 11 +++++++++-- DCCWaveform.cpp | 2 +- MotorDriver.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++---- MotorDriver.h | 4 ++++ TrackManager.cpp | 34 +++++++++++++++++++++++++++++++++ TrackManager.h | 7 ++++--- 6 files changed, 97 insertions(+), 10 deletions(-) diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index f5a3562..c82afe5 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -44,8 +44,15 @@ INTERRUPT_CALLBACK interruptHandler=0; void DCCTimer::begin(INTERRUPT_CALLBACK callback) { interruptHandler=callback; - noInterrupts(); - ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time + noInterrupts(); + // ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time + // Set up ADC for free running mode + ADMUX=(1< 3) + DIAG(F("Current sample old %d"), millis() - sampleCurrentTimestamp); + //interrupts(); #endif if (current<0) current=0-current; if ((faultPin != UNUSED_PIN) && isLOW(fastFaultPin) && powerMode==POWERMODE::ON) @@ -233,6 +237,42 @@ int MotorDriver::getCurrentRaw() { return current; } +/* + * This should only be called in interrupt context + * Copies current value from HW to cached value in + * Motordriver. + */ +#pragma GCC push_options +#pragma GCC optimize ("-O3") +bool MotorDriver::sampleCurrentFromHW() { +#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) + const byte mask = 7; +#else + const byte mask = 31; +#endif + byte low, high; + //if (!bit_is_set(ADCSRA, ADIF)) + if (bit_is_set(ADCSRA, ADSC)) + return false; + // if ((ADMUX & mask) != (currentPin - A0)) + // return false; + low = ADCL; //must read low before high + high = ADCH; + bitSet(ADCSRA, ADIF); + sampleCurrent = (high << 8) | low; + sampleCurrentTimestamp = millis(); + return true; +} +void MotorDriver::startCurrentFromHW() { +#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) + const byte mask = 7; +#else + const byte mask = 31; +#endif + ADMUX=(1<sampleCurrentFromHW()) { + return; // no result, continue to wait + } + // found value, advance at least one track + waiting = false; + tr++; + if (tr >= MAX_TRACKS) tr = 0; + } + if (!waiting) { + // look for a valid track to sample or until we are around + while (count) { + if (trackMode[tr] & ( TRACK_MODE_MAIN|TRACK_MODE_PROG|TRACK_MODE_DC|TRACK_MODE_DCX|TRACK_MODE_EXT )) { + track[tr]->startCurrentFromHW(); + waiting = true; + break; + } + tr++; + if (tr >= MAX_TRACKS) tr = 0; + count--; + } + if (count == 0) { + DIAG(F("WRONG")); + } + } +} // The setup call is done this way so that the tracks can be in a list // from the config... the tracks default to NULL in the declaration diff --git a/TrackManager.h b/TrackManager.h index 45325f9..90a9345 100644 --- a/TrackManager.h +++ b/TrackManager.h @@ -27,8 +27,9 @@ #include "MotorDriver.h" // Virtualised Motor shield multi-track hardware Interface -enum TRACK_MODE : byte {TRACK_MODE_OFF, TRACK_MODE_MAIN, TRACK_MODE_PROG, - TRACK_MODE_DC, TRACK_MODE_DCX, TRACK_MODE_EXT}; +// use powers of two so we can do logical and/or on the track modes in if clauses. +enum TRACK_MODE : byte {TRACK_MODE_OFF = 1, TRACK_MODE_MAIN = 2, TRACK_MODE_PROG = 4, + TRACK_MODE_DC = 8, TRACK_MODE_DCX = 16, TRACK_MODE_EXT = 32}; // These constants help EXRAIL macros say SET_TRACK(2,mode) OR SET_TRACK(C,mode) etc. const byte TRACK_NUMBER_0=0, TRACK_NUMBER_A=0; @@ -75,10 +76,10 @@ class TrackManager { static void setJoin(bool join); static bool isJoined() { return progTrackSyncMain;} static void setJoinRelayPin(byte joinRelayPin); + static void sampleCurrent(); static int16_t joinRelay; static bool progTrackSyncMain; // true when prog track is a siding switched to main static bool progTrackBoosted; // true when prog track is not current limited - private: static void addTrack(byte t, MotorDriver* driver);