diff --git a/DCCTimer.h b/DCCTimer.h index 7a9d940..29b8819 100644 --- a/DCCTimer.h +++ b/DCCTimer.h @@ -105,9 +105,14 @@ private: // that an offset can be initialized. class ADCee { public: - // init does add the pin to the list of scanned pins (if this + // begin is called for any setup that must be done before + // **init** can be called. On some architectures this involves ADC + // initialisation and clock routing, sampling times etc. + static void begin(); + // init adds the pin to the list of scanned pins (if this // platform's implementation scans pins) and returns the first - // read value. It is called before the regular scan is started. + // read value (which is why it required begin to have been called first!) + // It must be called before the regular scan is started. static int init(uint8_t pin); // read does read the pin value from the scanned cache or directly // if this is a platform that does not scan. fromISR is a hint if @@ -116,9 +121,6 @@ public: static int read(uint8_t pin, bool fromISR=false); // returns possible max value that the ADC can return static int16_t ADCmax(); - // begin is called for any setup that must be done before - // scan can be called. - static void begin(); private: // On platforms that scan, it is called from waveform ISR // only on a regular basis. @@ -127,8 +129,6 @@ private: static uint16_t usedpins; // cached analog values (malloc:ed to actual number of ADC channels) static int *analogvals; - // ids to scan (new way) - static byte *idarr; // friend so that we can call scan() and begin() friend class DCCWaveform; }; diff --git a/DCCTimerAVR.cpp b/DCCTimerAVR.cpp index 40ce0fb..9b16c47 100644 --- a/DCCTimerAVR.cpp +++ b/DCCTimerAVR.cpp @@ -123,14 +123,13 @@ void DCCTimer::reset() { } #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) -#define NUM_ADC_INPUTS 16 +#define NUM_ADC_INPUTS 15 #else -#define NUM_ADC_INPUTS 8 +#define NUM_ADC_INPUTS 7 #endif uint16_t ADCee::usedpins = 0; int * ADCee::analogvals = NULL; -byte *ADCee::idarr = NULL; -static bool ADCusesHighPort = false; +bool ADCusesHighPort = false; /* * Register a new pin to be scanned @@ -139,28 +138,16 @@ static bool ADCusesHighPort = false; */ int ADCee::init(uint8_t pin) { uint8_t id = pin - A0; - byte n; - if (id >= NUM_ADC_INPUTS) + if (id > NUM_ADC_INPUTS) return -1023; if (id > 7) ADCusesHighPort = true; pinMode(pin, INPUT); int value = analogRead(pin); - if (analogvals == NULL) { - analogvals = (int *)calloc(NUM_ADC_INPUTS, sizeof(int)); - for (n=0 ; n < NUM_ADC_INPUTS; n++) // set unreasonable value at startup as marker - analogvals[n] = -32768; // 16 bit int min value - idarr = (byte *)calloc(NUM_ADC_INPUTS+1, sizeof(byte)); // +1 for terminator value - for (n=0 ; n <= NUM_ADC_INPUTS; n++) - idarr[n] = 255; // set 255 as end of array marker - } - analogvals[id] = value; // store before enable by idarr[n] - for (n=0 ; n <= NUM_ADC_INPUTS; n++) { - if (idarr[n] == 255) { - idarr[n] = id; - break; - } - } + if (analogvals == NULL) + analogvals = (int *)calloc(NUM_ADC_INPUTS+1, sizeof(int)); + analogvals[id] = value; + usedpins |= (1<setBrake(0); waiting = false; + id++; + mask = mask << 1; + if (id == NUM_ADC_INPUTS+1) { + id = 0; + mask = 1; + } } if (!waiting) { - // cycle around in-use analogue pins - num++; - if (idarr[num] == 255) - num = 0; - // start new ADC aquire on id + 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 #if defined(ADCSRB) && defined(MUX5) - if (ADCusesHighPort) { // if we ever have started to use high pins) - if (idarr[num] > 7) // if we use a high ADC pin - bitSet(ADCSRB, MUX5); // set MUX5 bit - else - bitClear(ADCSRB, MUX5); - } + if (ADCusesHighPort) { // if we ever have started to use high pins) + if (id > 7) // if we use a high ADC pin + bitSet(ADCSRB, MUX5); // set MUX5 bit + else + bitClear(ADCSRB, MUX5); + } #endif - ADMUX = (1 << REFS0) | (idarr[num] & 0x07); // select AVCC as reference and set MUX - bitSet(ADCSRA, ADSC); // start conversion - waiting = true; + 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 @@ -231,4 +236,4 @@ void ADCee::begin() { //bitSet(ADCSRA, ADSC); //do not start the ADC yet. Done when we have set the MUX interrupts(); } -#endif \ No newline at end of file +#endif