aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2019-11-14 18:00:54 -0700
committerSelene ToyKeeper2019-11-14 18:00:54 -0700
commitae082e6331d75c2cbe339290fbce4e79c2aa2ede (patch)
treebec03d8c14d8036cb88bc61f4fb1beae9bff880e /spaghetti-monster
parentstarted refactoring ADC code to split voltage and temperature into their own ... (diff)
downloadanduril-ae082e6331d75c2cbe339290fbce4e79c2aa2ede.tar.gz
anduril-ae082e6331d75c2cbe339290fbce4e79c2aa2ede.tar.bz2
anduril-ae082e6331d75c2cbe339290fbce4e79c2aa2ede.zip
fixed ADC code; measures and behaves correctly now, and is easier to read...
... but factory reset's auto-calibrate still doesn't get the right values for some reason (manual calibration works, but not auto)
Diffstat (limited to 'spaghetti-monster')
-rw-r--r--spaghetti-monster/fsm-adc.c76
-rw-r--r--spaghetti-monster/fsm-adc.h4
-rw-r--r--spaghetti-monster/fsm-wdt.c2
3 files changed, 41 insertions, 41 deletions
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index ddf4c65..d447189 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -30,6 +30,7 @@ inline void set_admux_therm() {
#else
#error Unrecognized MCU type
#endif
+ adc_channel = 1;
}
inline void set_admux_voltage() {
@@ -52,6 +53,7 @@ inline void set_admux_voltage() {
#else
#error Unrecognized MCU type
#endif
+ adc_channel = 0;
}
inline void ADC_start_measurement() {
@@ -115,38 +117,37 @@ static inline uint8_t calc_voltage_divider(uint16_t value) {
#endif
#ifdef USE_THERMAL_REGULATION
-#define ADC_STEPS 4
-#else
#define ADC_STEPS 2
+#else
+#define ADC_STEPS 1
#endif
-// save the measurement result, set a flag to show something happened,
-// and count how many times we've triggered since last counter reset
+// happens every time the ADC sampler finishes a measurement
ISR(ADC_vect) {
- #if 0 // the fancy method is probably not even needed
- // count up but wrap around from 255 to 128; not 255 to 0
- // TODO: find a way to do this faster if possible
- uint8_t val = irq_adc; // cache volatile value
- irq_adc = (val + 1) | (val & 0b10000000);
- #else
- irq_adc ++;
+ #ifdef USE_PSEUDO_RAND
+ // real-world entropy makes this a true random, not pseudo
+ pseudo_rand_seed += ADCL;
#endif
- adc_value = ADC; // save this for later use
+
+ if (irq_adc_stable) { // skip first result; it's junk
+ adc_values[adc_channel] = ADC; // save this for later use
+ irq_adc = 1; // a value was saved, so trigger deferred logic
+ }
+ irq_adc_stable = 1;
+
+ // start another measurement
+ // (is explicit because it otherwise doesn't seem to happen during standby mode)
+ ADC_start_measurement();
}
void ADC_inner() {
- // ignore the first measurement; the docs say it's junk
- if (irq_adc < 2) {
- ADC_start_measurement(); // start a second measurement
- return;
- }
+ irq_adc = 0; // event handled
// the ADC triggers repeatedly when it's on, but we only want one value
// (so ignore everything after the first value, until it's manually reset)
if (! adcint_enable) return;
- // if we're actually runnning, reset the status flags / counters
- irq_adc = 0;
+ // disable after one iteration
adcint_enable = 0;
#ifdef TICK_DURING_STANDBY
@@ -156,41 +157,37 @@ void ADC_inner() {
if (go_to_standby) ADC_off();
#endif
- // what is being measured? 0/1 = battery voltage, 2/3 = temperature
+ // what is being measured? 0 = battery voltage, 1 = temperature
static uint8_t adc_step = 0;
- #ifdef USE_PSEUDO_RAND
- // real-world entropy makes this a true random, not pseudo
- pseudo_rand_seed += adc_value;
- #endif
-
- #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP)
- // only measure battery voltage while asleep
- if (go_to_standby) adc_step = 1;
- else
- #endif
-
- adc_step = (adc_step + 1) & (ADC_STEPS-1);
-
#ifdef USE_LVP
- if (adc_step == 1) { // voltage
+ if (0 == adc_step) { // voltage
ADC_voltage_handler();
}
#endif
#ifdef USE_THERMAL_REGULATION
- else if (adc_step == 3) { // temperature
+ else if (1 == adc_step) { // temperature
ADC_temperature_handler();
}
#endif
+ #if defined(TICK_DURING_STANDBY) && defined(USE_SLEEP_LVP)
+ // only measure battery voltage while asleep
+ if (go_to_standby) adc_step = 0;
+ else
+ #endif
+
+ adc_step = (adc_step + 1) & (ADC_STEPS-1);
+
// set the correct type of measurement for next time
#ifdef USE_THERMAL_REGULATION
#ifdef USE_LVP
- if (adc_step < 2) set_admux_voltage();
+ if (0 == adc_step) set_admux_voltage();
else set_admux_therm();
#else
- set_admux_therm();
+ //set_admux_therm();
+ #error "USE_THERMAL_REGULATION set without USE_LVP"
#endif
#else
#ifdef USE_LVP
@@ -198,6 +195,7 @@ void ADC_inner() {
#endif
#endif
+ irq_adc_stable = 0; // first result is unstable
}
@@ -213,7 +211,7 @@ static inline void ADC_voltage_handler() {
#define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings
#define LVP_LOWPASS_STRENGTH ADC_CYCLES_PER_SECOND // lowpass for one second
- uint16_t measurement = adc_value; // latest 10-bit ADC reading
+ uint16_t measurement = adc_values[0]; // latest 10-bit ADC reading
#ifdef USE_LVP_AVG
// prime on first execution
@@ -293,7 +291,7 @@ static inline void ADC_temperature_handler() {
#define OVERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds
#define UNDERHEAT_LOWPASS_STRENGTH (ADC_CYCLES_PER_SECOND*2) // lowpass for 2 seconds
- uint16_t measurement = adc_value; // latest 10-bit ADC reading
+ uint16_t measurement = adc_values[1]; // latest 10-bit ADC reading
// Convert ADC units to Celsius (ish)
int16_t temp = measurement - 275 + THERM_CAL_OFFSET + (int16_t)therm_cal_offset;
diff --git a/spaghetti-monster/fsm-adc.h b/spaghetti-monster/fsm-adc.h
index 5f4d0c8..6e39750 100644
--- a/spaghetti-monster/fsm-adc.h
+++ b/spaghetti-monster/fsm-adc.h
@@ -40,7 +40,9 @@
#endif
volatile uint8_t irq_adc = 0; // ADC interrupt happened?
-uint16_t adc_value; // last ADC measurement
+volatile uint8_t irq_adc_stable = 0; // have we passed the 1st junk value yet?
+uint8_t adc_channel = 0; // 0=voltage, 1=temperature
+uint16_t adc_values[2]; // last ADC measurements (0=voltage, 1=temperature)
uint8_t adcint_enable = 0; // is the current ADC result needed?
void ADC_inner(); // do the actual ADC-related calculations
diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c
index 3cb7d86..beab1a2 100644
--- a/spaghetti-monster/fsm-wdt.c
+++ b/spaghetti-monster/fsm-wdt.c
@@ -185,7 +185,7 @@ void WDT_inner() {
if (go_to_standby) ADC_on();
#endif
ADC_start_measurement();
- irq_adc = 0;
+ irq_adc_stable = 0;
adcint_enable = 1;
}
#endif