1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2024-11-25 00:56:13 +01:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Harald Barth
d5dad767a4 version 4.2.55 2023-06-19 00:09:27 +02:00
Harald Barth
56fcb4e5f7 Optimize DCCTimerARV.cpp 2023-06-19 00:06:04 +02:00
Harald Barth
7783837545 Back out this as it is bigger and slower
This reverts commit efb2666060.
2023-06-18 21:08:52 +02:00
Harald Barth
0266936875 STM32: Use mask as loop variable 2023-06-18 20:22:53 +02:00
Harald Barth
befb41ce98 check ADCee::init() return value 2023-06-18 20:20:58 +02:00
7 changed files with 101 additions and 62 deletions

View File

@ -105,9 +105,14 @@ private:
// that an offset can be initialized. // that an offset can be initialized.
class ADCee { class ADCee {
public: 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 // 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); static int init(uint8_t pin);
// read does read the pin value from the scanned cache or directly // 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 // if this is a platform that does not scan. fromISR is a hint if
@ -116,19 +121,15 @@ public:
static int read(uint8_t pin, bool fromISR=false); static int read(uint8_t pin, bool fromISR=false);
// returns possible max value that the ADC can return // returns possible max value that the ADC can return
static int16_t ADCmax(); static int16_t ADCmax();
// begin is called for any setup that must be done before
// scan can be called.
static void begin();
private: private:
// On platforms that scan, it is called from waveform ISR // On platforms that scan, it is called from waveform ISR
// only on a regular basis. // only on a regular basis.
static void scan(); static void scan();
// bit array of used pins (max 16) // bit array of used pins (max 16)
static uint16_t usedpins; static uint16_t usedpins;
static uint8_t highestPin;
// cached analog values (malloc:ed to actual number of ADC channels) // cached analog values (malloc:ed to actual number of ADC channels)
static int *analogvals; static int *analogvals;
// ids to scan (new way)
static byte *idarr;
// friend so that we can call scan() and begin() // friend so that we can call scan() and begin()
friend class DCCWaveform; friend class DCCWaveform;
}; };

View File

@ -1,6 +1,6 @@
/* /*
* © 2021 Mike S * © 2021 Mike S
* © 2021-2022 Harald Barth * © 2021-2023 Harald Barth
* © 2021 Fred Decker * © 2021 Fred Decker
* © 2021 Chris Harlow * © 2021 Chris Harlow
* © 2021 David Cutting * © 2021 David Cutting
@ -29,6 +29,9 @@
#include <avr/boot.h> #include <avr/boot.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include "DCCTimer.h" #include "DCCTimer.h"
#ifdef DEBUG_ADC
#include "TrackManager.h"
#endif
INTERRUPT_CALLBACK interruptHandler=0; INTERRUPT_CALLBACK interruptHandler=0;
// Arduino nano, uno, mega etc // Arduino nano, uno, mega etc
@ -128,8 +131,8 @@ void DCCTimer::reset() {
#define NUM_ADC_INPUTS 8 #define NUM_ADC_INPUTS 8
#endif #endif
uint16_t ADCee::usedpins = 0; uint16_t ADCee::usedpins = 0;
uint8_t ADCee::highestPin = 0;
int * ADCee::analogvals = NULL; int * ADCee::analogvals = NULL;
byte *ADCee::idarr = NULL;
static bool ADCusesHighPort = false; static bool ADCusesHighPort = false;
/* /*
@ -139,28 +142,17 @@ static bool ADCusesHighPort = false;
*/ */
int ADCee::init(uint8_t pin) { int ADCee::init(uint8_t pin) {
uint8_t id = pin - A0; uint8_t id = pin - A0;
byte n;
if (id >= NUM_ADC_INPUTS) if (id >= NUM_ADC_INPUTS)
return -1023; return -1023;
if (id > 7) if (id > 7)
ADCusesHighPort = true; ADCusesHighPort = true;
pinMode(pin, INPUT); pinMode(pin, INPUT);
int value = analogRead(pin); int value = analogRead(pin);
if (analogvals == NULL) { if (analogvals == NULL)
analogvals = (int *)calloc(NUM_ADC_INPUTS, sizeof(int)); analogvals = (int *)calloc(NUM_ADC_INPUTS, sizeof(int));
for (n=0 ; n < NUM_ADC_INPUTS; n++) // set unreasonable value at startup as marker analogvals[id] = value;
analogvals[n] = -32768; // 16 bit int min value usedpins |= (1<<id);
idarr = (byte *)calloc(NUM_ADC_INPUTS+1, sizeof(byte)); // +1 for terminator value if (id > highestPin) highestPin = id;
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;
}
}
return value; return value;
} }
int16_t ADCee::ADCmax() { int16_t ADCee::ADCmax() {
@ -170,14 +162,14 @@ int16_t ADCee::ADCmax() {
* Read function ADCee::read(pin) to get value instead of analogRead(pin) * Read function ADCee::read(pin) to get value instead of analogRead(pin)
*/ */
int ADCee::read(uint8_t pin, bool fromISR) { int ADCee::read(uint8_t pin, bool fromISR) {
(void)fromISR; // AVR does ignore this arg
uint8_t id = pin - A0; uint8_t id = pin - A0;
int a; if ((usedpins & (1<<id) ) == 0)
return -1023;
// we do not need to check (analogvals == NULL) // we do not need to check (analogvals == NULL)
// because usedpins would still be 0 in that case // because usedpins would still be 0 in that case
noInterrupts(); if (!fromISR) noInterrupts();
a = analogvals[id]; int a = analogvals[id];
interrupts(); if (!fromISR) interrupts();
return a; return a;
} }
/* /*
@ -186,7 +178,8 @@ int ADCee::read(uint8_t pin, bool fromISR) {
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize ("-O3") #pragma GCC optimize ("-O3")
void ADCee::scan() { void ADCee::scan() {
static byte num = 0; // index into id array static byte id = 0; // id and mask are the same thing but it is faster to
static uint16_t mask = 1; // increment and shift instead to calculate mask from id
static bool waiting = false; static bool waiting = false;
if (waiting) { if (waiting) {
@ -198,26 +191,49 @@ void ADCee::scan() {
low = ADCL; //must read low before high low = ADCL; //must read low before high
high = ADCH; high = ADCH;
bitSet(ADCSRA, ADIF); bitSet(ADCSRA, ADIF);
analogvals[idarr[num]] = (high << 8) | low; analogvals[id] = (high << 8) | low;
// advance at least one track
#ifdef DEBUG_ADC
if (id == 1) TrackManager::track[1]->setBrake(0);
#endif
waiting = false; waiting = false;
id++;
mask = mask << 1;
if (id > highestPin) { // the 1 has been shifted out
id = 0;
mask = 1;
}
} }
if (!waiting) { if (!waiting) {
// cycle around in-use analogue pins if (usedpins == 0) // otherwise we would loop forever
num++; return;
if (idarr[num] == 255) // look for a valid track to sample or until we are around
num = 0; while (true) {
// start new ADC aquire on id if (mask & usedpins) {
// start new ADC aquire on id
#if defined(ADCSRB) && defined(MUX5) #if defined(ADCSRB) && defined(MUX5)
if (ADCusesHighPort) { // if we ever have started to use high pins) if (ADCusesHighPort) { // if we ever have started to use high pins)
if (idarr[num] > 7) // if we use a high ADC pin if (id > 7) // if we use a high ADC pin
bitSet(ADCSRB, MUX5); // set MUX5 bit bitSet(ADCSRB, MUX5); // set MUX5 bit
else else
bitClear(ADCSRB, MUX5); bitClear(ADCSRB, MUX5);
} }
#endif #endif
ADMUX = (1 << REFS0) | (idarr[num] & 0x07); // select AVCC as reference and set MUX ADMUX=(1<<REFS0)|(id & 0x07); //select AVCC as reference and set MUX
bitSet(ADCSRA, ADSC); // start conversion bitSet(ADCSRA,ADSC); // start conversion
waiting = true; #ifdef DEBUG_ADC
if (id == 1) TrackManager::track[1]->setBrake(1);
#endif
waiting = true;
return;
}
id++;
mask = mask << 1;
if (id > highestPin) {
id = 0;
mask = 1;
}
}
} }
} }
#pragma GCC pop_options #pragma GCC pop_options

View File

@ -30,6 +30,10 @@
#ifdef ARDUINO_ARCH_STM32 #ifdef ARDUINO_ARCH_STM32
#include "DCCTimer.h" #include "DCCTimer.h"
#ifdef DEBUG_ADC
#include "TrackManager.h"
#endif
#include "DIAG.h"
#if defined(ARDUINO_NUCLEO_F411RE) #if defined(ARDUINO_NUCLEO_F411RE)
// Nucleo-64 boards don't have Serial1 defined by default // Nucleo-64 boards don't have Serial1 defined by default
@ -307,6 +311,8 @@ int ADCee::init(uint8_t pin) {
analogchans[id] = adcchan; // Keep track of which ADC channel is used for reading this pin analogchans[id] = adcchan; // Keep track of which ADC channel is used for reading this pin
usedpins |= (1 << id); // This pin is now ready usedpins |= (1 << id); // This pin is now ready
DIAG(F("ADCee::init(): value=%d, channel=%d, id=%d"), value, adcchan, id);
return value; return value;
} }
@ -340,11 +346,13 @@ void ADCee::scan() {
// found value // found value
analogvals[id] = ADC1->DR; analogvals[id] = ADC1->DR;
// advance at least one track // advance at least one track
// for scope debug TrackManager::track[1]->setBrake(0); #ifdef DEBUG_ADC
if (id == 1) TrackManager::track[1]->setBrake(0);
#endif
waiting = false; waiting = false;
id++; id++;
mask = mask << 1; mask = mask << 1;
if (id == NUM_ADC_INPUTS+1) { if (mask == 0) { // the 1 has been shifted out
id = 0; id = 0;
mask = 1; mask = 1;
} }
@ -355,18 +363,20 @@ void ADCee::scan() {
// look for a valid track to sample or until we are around // look for a valid track to sample or until we are around
while (true) { while (true) {
if (mask & usedpins) { if (mask & usedpins) {
// start new ADC aquire on id // start new ADC aquire on id
ADC1->SQR3 = analogchans[id]; //1st conversion in regular sequence ADC1->SQR3 = analogchans[id]; //1st conversion in regular sequence
ADC1->CR2 |= (1 << 30); //Start 1st conversion SWSTART ADC1->CR2 |= (1 << 30); //Start 1st conversion SWSTART
// for scope debug TrackManager::track[1]->setBrake(1); #ifdef DEBUG_ADC
waiting = true; if (id == 1) TrackManager::track[1]->setBrake(1);
return; #endif
waiting = true;
return;
} }
id++; id++;
mask = mask << 1; mask = mask << 1;
if (id == NUM_ADC_INPUTS+1) { if (mask == 0) { // the 1 has been shifted out
id = 0; id = 0;
mask = 1; mask = 1;
} }
} }
} }

View File

@ -1 +1 @@
#define GITHUB_SHA "devel-202306031954Z" #define GITHUB_SHA "devel-202306182208Z"

View File

@ -108,8 +108,13 @@ MotorDriver::MotorDriver(int16_t power_pin, byte signal_pin, byte signal_pin2, i
} }
currentPin=current_pin; currentPin=current_pin;
if (currentPin!=UNUSED_PIN) if (currentPin!=UNUSED_PIN) {
ADCee::init(currentPin); int ret = ADCee::init(currentPin);
if (ret < -1010) { // XXX give value a name later
DIAG(F("ADCee::init error %d, disable current pin %d"), ret, currentPin);
currentPin = UNUSED_PIN;
}
}
senseOffset=0; // value can not be obtained until waveform is activated senseOffset=0; // value can not be obtained until waveform is activated
if (fault_pin != UNUSED_PIN) { if (fault_pin != UNUSED_PIN) {

View File

@ -84,7 +84,14 @@ class TrackManager {
static int16_t joinRelay; static int16_t joinRelay;
static bool progTrackSyncMain; // true when prog track is a siding switched to main static bool progTrackSyncMain; // true when prog track is a siding switched to main
static bool progTrackBoosted; // true when prog track is not current limited static bool progTrackBoosted; // true when prog track is not current limited
#ifdef DEBUG_ADC
public:
#else
private:
#endif
static MotorDriver* track[MAX_TRACKS];
private: private:
static void addTrack(byte t, MotorDriver* driver); static void addTrack(byte t, MotorDriver* driver);
@ -93,7 +100,6 @@ class TrackManager {
static POWERMODE mainPowerGuess; static POWERMODE mainPowerGuess;
static void applyDCSpeed(byte t); static void applyDCSpeed(byte t);
static MotorDriver* track[MAX_TRACKS];
static TRACK_MODE trackMode[MAX_TRACKS]; static TRACK_MODE trackMode[MAX_TRACKS];
static int16_t trackDCAddr[MAX_TRACKS]; // dc address if TRACK_MODE_DC or TRACK_MODE_DCX static int16_t trackDCAddr[MAX_TRACKS]; // dc address if TRACK_MODE_DC or TRACK_MODE_DCX
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32

View File

@ -4,7 +4,8 @@
#include "StringFormatter.h" #include "StringFormatter.h"
#define VERSION "4.2.54" #define VERSION "4.2.55"
// 4.2.55 - Optimize analog read for AVR
// 4.2.54 - EX8874 shield in config.example.h // 4.2.54 - EX8874 shield in config.example.h
// - Fix: Better warnings for pin number errors // - Fix: Better warnings for pin number errors
// - Fix: Default roster list possible in Withrottle and <jR> // - Fix: Default roster list possible in Withrottle and <jR>