diff --git a/DCCTimer.h b/DCCTimer.h index 34b2d91..7864d70 100644 --- a/DCCTimer.h +++ b/DCCTimer.h @@ -93,4 +93,15 @@ private: }; +class Adc { +public: + static void reg(uint8_t pin); + static int read(uint8_t pin); +private: + static void scan(); + static void begin(); + static uint16_t usedpins; + static int *analogvals; + friend class DCCWaveform; + }; #endif diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index dfdbeee..8dbe00b 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -26,7 +26,6 @@ // Please refer to DCCTimer.h for general comments about how this class works // This is to avoid repetition and duplication. #ifdef ARDUINO_ARCH_AVR - #include #include #include "DCCTimer.h" @@ -45,12 +44,6 @@ INTERRUPT_CALLBACK interruptHandler=0; void DCCTimer::begin(INTERRUPT_CALLBACK callback) { interruptHandler=callback; noInterrupts(); - // ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time - // Set up ADC for free running mode - ADMUX=(1< NUM_ADC_INPUTS) + return; + if (analogvals == NULL) + analogvals = (int *)calloc(NUM_ADC_INPUTS+1, sizeof(int)); + usedpins |= (1<setBrake(0); + waiting = false; + id++; + mask = mask << 1; + if (id == NUM_ADC_INPUTS+1) { + id = 0; + mask = 1; + } + } + if (!waiting) { + if (usedpins == 0) // otherwise we would loop forever + return; + // look for a valid track to sample or until we are around + while (true) { + if (mask & usedpins) { + // start new ADC aquire on id + ADMUX=(1<setBrake(1); + waiting = true; + return; + } + id++; + mask = mask << 1; + if (id == NUM_ADC_INPUTS+1) { + id = 0; + mask = 1; + } + } + } +} +#pragma GCC pop_options + +void Adc::begin() { + noInterrupts(); + // ADCSRA = (ADCSRA & 0b11111000) | 0b00000100; // speed up analogRead sample time + // Set up ADC for free running mode + ADMUX=(1< */ LOW}; void DCCWaveform::begin() { + Adc::begin(); DCCTimer::begin(DCCWaveform::interruptHandler); } @@ -82,7 +83,8 @@ void DCCWaveform::interruptHandler() { TrackManager::setPROGSignal(sigProg); #ifdef ANALOG_READ_INTERRUPT - TrackManager::sampleCurrent(); + //TrackManager::sampleCurrent(); + Adc::scan(); #endif // Move on in the state engine diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 1a645ec..4edf059 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -117,6 +117,9 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i senseOffset = adc1_get_raw(pinToADC1Channel(currentPin)); #else pinMode(currentPin, INPUT); + Adc::reg(currentPin); + // run analogRead as Adc::read() does not have any values before + // the waveform has been started. senseOffset=analogRead(currentPin); // value of sensor at zero current #endif } @@ -209,7 +212,7 @@ bool MotorDriver::canMeasureCurrent() { /* * Return the current reading as pin reading 0 to 1023. If the fault * pin is activated return a negative current to show active fault pin. - * As there is no -0, create a little and return -1 in that case. + * As there is no -0, cheat a little and return -1 in that case. * * senseOffset handles the case where a shield returns values above or below * a central value depending on direction. @@ -224,9 +227,10 @@ int MotorDriver::getCurrentRaw(bool fromISR) { current = local_adc1_get_raw(pinToADC1Channel(currentPin))-senseOffset; #else #ifdef ANALOG_READ_INTERRUPT - current = sampleCurrent-senseOffset; - if ((millis() - sampleCurrentTimestamp) > 3) - DIAG(F("Current sample old %d"), millis() - sampleCurrentTimestamp); + current = Adc::read(currentPin)-senseOffset; + //current = sampleCurrent-senseOffset; + //if ((millis() - sampleCurrentTimestamp) > 3) + // DIAG(F("Current sample old %d"), millis() - sampleCurrentTimestamp); #else if (!fromISR) noInterrupts(); current = analogRead(currentPin)-senseOffset;