1
0
mirror of https://github.com/DCC-EX/CommandStation-EX.git synced 2025-07-30 19:03:44 +02:00

Compare commits

...

6 Commits

Author SHA1 Message Date
Harald Barth
f6f5c22bbd more random bits there 2022-11-26 00:15:09 +01:00
Harald Barth
fc3a28143d move multiplicaton factor to macro for better optimization 2022-11-25 10:53:00 +01:00
Harald Barth
96f47bf44f protect analogvals read from interrupt 2022-11-25 10:48:18 +01:00
Harald Barth
9b04cd791b scan ADC pins with id array improved 2022-11-24 21:12:45 +01:00
Harald Barth
37b679ae2c better pseudo random 2022-11-24 20:24:15 +01:00
Harald Barth
3e4d6863bb scan ADC pins with id array 2022-11-23 23:20:23 +01:00
5 changed files with 47 additions and 50 deletions

View File

@@ -124,6 +124,8 @@ private:
static uint16_t usedpins; static uint16_t usedpins;
// 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

@@ -120,13 +120,14 @@ void DCCTimer::reset() {
} }
#if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) #if defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560)
#define NUM_ADC_INPUTS 15 #define NUM_ADC_INPUTS 16
#else #else
#define NUM_ADC_INPUTS 7 #define NUM_ADC_INPUTS 8
#endif #endif
uint16_t ADCee::usedpins = 0; uint16_t ADCee::usedpins = 0;
int * ADCee::analogvals = NULL; int * ADCee::analogvals = NULL;
bool ADCusesHighPort = false; byte *ADCee::idarr = NULL;
static bool ADCusesHighPort = false;
/* /*
* Register a new pin to be scanned * Register a new pin to be scanned
@@ -135,16 +136,28 @@ 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;
if (id > NUM_ADC_INPUTS) byte n;
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+1, sizeof(int)); analogvals = (int *)calloc(NUM_ADC_INPUTS, sizeof(int));
analogvals[id] = value; for (n=0 ; n < NUM_ADC_INPUTS; n++) // set unreasonable value at startup as marker
usedpins |= (1<<id); 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;
}
}
return value; return value;
} }
int16_t ADCee::ADCmax() { int16_t ADCee::ADCmax() {
@@ -156,11 +169,13 @@ int16_t ADCee::ADCmax() {
int ADCee::read(uint8_t pin, bool fromISR) { int ADCee::read(uint8_t pin, bool fromISR) {
(void)fromISR; // AVR does ignore this arg (void)fromISR; // AVR does ignore this arg
uint8_t id = pin - A0; uint8_t id = pin - A0;
if ((usedpins & (1<<id) ) == 0) int a;
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
return analogvals[id]; noInterrupts();
a = analogvals[id];
interrupts();
return a;
} }
/* /*
* Scan function that is called from interrupt * Scan function that is called from interrupt
@@ -168,8 +183,7 @@ 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 id = 0; // id and mask are the same thing but it is faster to static byte num = 0; // index into id array
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) {
@@ -181,45 +195,26 @@ 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[id] = (high << 8) | low; analogvals[idarr[num]] = (high << 8) | low;
// advance at least one track
// for scope debug TrackManager::track[1]->setBrake(0);
waiting = false; waiting = false;
id++;
mask = mask << 1;
if (id == NUM_ADC_INPUTS+1) {
id = 0;
mask = 1;
}
} }
if (!waiting) { if (!waiting) {
if (usedpins == 0) // otherwise we would loop forever // cycle around in-use analogue pins
return; num++;
// look for a valid track to sample or until we are around if (idarr[num] == 255)
while (true) { num = 0;
if (mask & usedpins) { // start new ADC aquire on id
// 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 (id > 7) // if we use a high ADC pin if (idarr[num] > 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
ADMUX=(1<<REFS0)|(id & 0x07); //select AVCC as reference and set MUX
bitSet(ADCSRA,ADSC); // start conversion
// for scope debug TrackManager::track[1]->setBrake(1);
waiting = true;
return;
}
id++;
mask = mask << 1;
if (id == NUM_ADC_INPUTS+1) {
id = 0;
mask = 1;
}
} }
#endif
ADMUX = (1 << REFS0) | (idarr[num] & 0x07); // select AVCC as reference and set MUX
bitSet(ADCSRA, ADSC); // start conversion
waiting = true;
} }
} }
#pragma GCC pop_options #pragma GCC pop_options

View File

@@ -727,7 +727,7 @@ void RMFT2::loop2() {
break; break;
case OPCODE_IFRANDOM: // do block on random percentage case OPCODE_IFRANDOM: // do block on random percentage
skipIf=(int16_t)(micros()%100) >= operand; skipIf= ((uint8_t)((uint16_t)micros()>>4)) >= operand;
break; break;
case OPCODE_IFRESERVE: // do block if we successfully RERSERVE case OPCODE_IFRESERVE: // do block if we successfully RERSERVE

View File

@@ -256,7 +256,7 @@ const FLASH int16_t RMFT2::SignalDefinitions[] = {
#define IFGTE(sensor_id,value) OPCODE_IFGTE,V(sensor_id),OPCODE_PAD,V(value), #define IFGTE(sensor_id,value) OPCODE_IFGTE,V(sensor_id),OPCODE_PAD,V(value),
#define IFLT(sensor_id,value) OPCODE_IFLT,V(sensor_id),OPCODE_PAD,V(value), #define IFLT(sensor_id,value) OPCODE_IFLT,V(sensor_id),OPCODE_PAD,V(value),
#define IFNOT(sensor_id) OPCODE_IFNOT,V(sensor_id), #define IFNOT(sensor_id) OPCODE_IFNOT,V(sensor_id),
#define IFRANDOM(percent) OPCODE_IFRANDOM,V(percent), #define IFRANDOM(percent) OPCODE_IFRANDOM,V(percent*255/100),
#define IFRED(signal_id) OPCODE_IFRED,V(signal_id), #define IFRED(signal_id) OPCODE_IFRED,V(signal_id),
#define IFRESERVE(block) OPCODE_IFRESERVE,V(block), #define IFRESERVE(block) OPCODE_IFRESERVE,V(block),
#define IFTHROWN(turnout_id) OPCODE_IFTHROWN,V(turnout_id), #define IFTHROWN(turnout_id) OPCODE_IFTHROWN,V(turnout_id),

View File

@@ -1 +1 @@
#define GITHUB_SHA "devel-202211181919Z" #define GITHUB_SHA "devel-202211242012Z"