From fbcac59563c32f14de4861449c1b267c247b5b78 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sun, 16 Apr 2023 18:21:29 -0600
Subject: reduced ROM by ~600 bytes by moving all eeprom config values to a
"cfg" struct (this also made some parts of the code cleaner)
---
spaghetti-monster/fsm-adc.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
(limited to 'spaghetti-monster/fsm-adc.c')
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 60eb843..9dc8866 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -149,7 +149,7 @@ static inline uint8_t calc_voltage_divider(uint16_t value) {
uint8_t result = ((value / adc_per_volt)
+ VOLTAGE_FUDGE_FACTOR
#ifdef USE_VOLTAGE_CORRECTION
- + voltage_correction - 7
+ + VOLT_CORR - 7
#endif
) >> 1;
return result;
@@ -349,7 +349,7 @@ static inline void ADC_voltage_handler() {
voltage = ((uint16_t)(2*1.1*1024*10)/(measurement>>6)
+ VOLTAGE_FUDGE_FACTOR
#ifdef USE_VOLTAGE_CORRECTION
- + voltage_correction - 7
+ + VOLT_CORR - 7
#endif
) >> 1;
#endif
@@ -428,10 +428,10 @@ static inline void ADC_temperature_handler() {
// Convert ADC units to Celsius (ish)
#ifndef USE_EXTERNAL_TEMP_SENSOR
// onboard sensor for attiny25/45/85/1634
- temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset - 275;
+ temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275;
#else
// external sensor
- temperature = EXTERN_TEMP_FORMULA(measurement>>1) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset;
+ temperature = EXTERN_TEMP_FORMULA(measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL;
#endif
// how much has the temperature changed between now and a few seconds ago?
@@ -447,10 +447,10 @@ static inline void ADC_temperature_handler() {
pt = measurement + (diff * THERM_LOOKAHEAD);
// convert temperature limit from C to raw 16-bit ADC units
- // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + therm_cal_offset;
+ // C = (ADC>>6) - 275 + THERM_CAL_OFFSET + TH_CAL;
// ... so ...
- // (C + 275 - THERM_CAL_OFFSET - therm_cal_offset) << 6 = ADC;
- uint16_t ceil = (therm_ceil + 275 - therm_cal_offset - THERM_CAL_OFFSET) << 1;
+ // (C + 275 - THERM_CAL_OFFSET - TH_CAL) << 6 = ADC;
+ uint16_t ceil = (TH_CEIL + 275 - TH_CAL - THERM_CAL_OFFSET) << 1;
int16_t offset = pt - ceil;
// bias small errors toward zero, while leaving large errors mostly unaffected
--
cgit v1.2.3
From 583854e37efde7f461e073e735a1736b02d28c70 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Mon, 17 Apr 2023 00:08:32 -0600
Subject: switched the rest of FSM + Anduril to use SPDX license headers
instead of full GPL headers (or all too often, nothing at all)
There are a few "FIXME" entries where I'm not sure about the correct copyright.
---
spaghetti-monster/fsm-adc.c | 27 +++++----------------------
1 file changed, 5 insertions(+), 22 deletions(-)
(limited to 'spaghetti-monster/fsm-adc.c')
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 9dc8866..5b238aa 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -1,24 +1,8 @@
-/*
- * fsm-adc.c: ADC (voltage, temperature) functions for SpaghettiMonster.
- *
- * Copyright (C) 2017 Selene ToyKeeper
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef FSM_ADC_C
-#define FSM_ADC_C
+// fsm-adc.c: ADC (voltage, temperature) functions for SpaghettiMonster.
+// Copyright (C) 2017-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
// override onboard temperature sensor definition, if relevant
#ifdef USE_EXTERNAL_TEMP_SENSOR
@@ -557,4 +541,3 @@ void battcheck() {
}
#endif
-#endif
--
cgit v1.2.3
From 847485ca96a6ef99abd19984ec025cf1d6841d3d Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Tue, 25 Apr 2023 23:28:30 -0600
Subject: fixed bug behind K93_LOCKOUT_KLUDGE which could exit lockout in solid
aux mode (also reduced avg standby power by about 15 uA) (also fixed
oscillating voltage mode colors, I think)
The bug happened because sometimes sleep LVP would get triggered, because the
ADC would read zero under some conditions.
This in turn happened because the ADC needs the MCU to be at least partially
awake in order to finish a measurement. So in standby mode, with the MCU only
waking up very briefly to send a sleep tick and go back to sleep, the ADC
required several cycles (like 375ms to 625ms) to finish a single measurement.
This varied depending on how many instructions the MCU executed while it was
awake. In the single-color mode, so few instructions were being executed that
the ADC seemed to time out and abort its measurement, returning a zero. Then a
low voltage warning was sent, which knocked the light back into "Off" mode.
Adding no-op instructions inside the single-color clause was sufficient to
prevent the ADC from timing out, because it kept the MCU awake just barely long
enough. But it was a kludge, and it still took like half a second to finish a
measurement, and the measurements were noisy. It also used more power, because
it required keeping the ADC powered on far too long.
This fix puts the MCU into "ADC Noise Reduction" mode instead, when a voltage
measurement is needed during sleep. It reduces noise to make measurements more
stable... but more importantly, it lets the measurement finish in like 0.5ms
instead of 500ms. So it uses less power and isn't dependent on the number of
calculations the MCU does during each "sleep tick".
As a bonus, this can also measure voltage much more often, while still using
less total energy than before. It was once every 8 seconds, and now it's once
per second.
Avg power use in aux low mode, on a D4Sv2: (avg of 30k samples each)
- before: 101 uA
- after: 86 uA
---
spaghetti-monster/fsm-adc.c | 2 ++
1 file changed, 2 insertions(+)
(limited to 'spaghetti-monster/fsm-adc.c')
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 5b238aa..0b79767 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -244,6 +244,8 @@ void adc_deferred() {
// (and the usual standby level is only ~20 uA)
if (go_to_standby) {
ADC_off();
+ // if any measurements were in progress, they're done now
+ adc_active_now = 0;
// also, only check the battery while asleep, not the temperature
adc_channel = 0;
}
--
cgit v1.2.3
From aa4c627377b07cc07cd1e904f9f7d2f24c1155a4 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Wed, 26 Apr 2023 01:34:53 -0600
Subject: made sleep voltage work on attiny1616 again (oops, it has no "ADC
Noise Reduction" mode... needs different setup code)
---
spaghetti-monster/fsm-adc.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
(limited to 'spaghetti-monster/fsm-adc.c')
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 0b79767..a196b7b 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -12,6 +12,8 @@
#define ADMUX_THERM ADMUX_THERM_EXTERNAL_SENSOR
#endif
+#include
+
static inline void set_admux_therm() {
#if (ATTINY == 1634)
@@ -70,6 +72,29 @@ inline void set_admux_voltage() {
ADC_start_measurement();
}
+
+#ifdef TICK_DURING_STANDBY
+inline void adc_sleep_mode() {
+ // needs a special sleep mode to get accurate measurements quickly
+ // ... full power-down ends up using more power overall, and causes
+ // some weird issues when the MCU doesn't stay awake enough cycles
+ // to complete a reading
+ #ifdef SLEEP_MODE_ADC
+ // attiny1634
+ set_sleep_mode(SLEEP_MODE_ADC);
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ // set the RUNSTDBY bit so ADC will run in standby mode
+ ADC0.CTRLA |= 1;
+ // set a INITDLY value because the AVR manual says so
+ // (section 30.3.5)
+ ADC0.CTRLD |= (1 << 5);
+ set_sleep_mode(SLEEP_MODE_STANDBY);
+ #else
+ #error No ADC sleep mode defined for this hardware.
+ #endif
+}
+#endif
+
inline void ADC_start_measurement() {
#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 841) || (ATTINY == 1634)
ADCSRA |= (1 << ADSC) | (1 << ADIE);
--
cgit v1.2.3
From 7400cbf6a1370035400607c22d57366c54304fb9 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 8 Jul 2023 03:55:02 -0600
Subject: Fixed spurious voltage warnings in attiny1616 sleep mode. Fixed by
SammysHP.
https://budgetlightforum.com/t/anduril-2-feature-change-suggestions/218045/467
I was never able to reproduce the issue here, but the fix seems good and others
tested it successfully.
---
spaghetti-monster/fsm-adc.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
(limited to 'spaghetti-monster/fsm-adc.c')
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index a196b7b..d11cca8 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -83,11 +83,6 @@ inline void adc_sleep_mode() {
// attiny1634
set_sleep_mode(SLEEP_MODE_ADC);
#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
- // set the RUNSTDBY bit so ADC will run in standby mode
- ADC0.CTRLA |= 1;
- // set a INITDLY value because the AVR manual says so
- // (section 30.3.5)
- ADC0.CTRLD |= (1 << 5);
set_sleep_mode(SLEEP_MODE_STANDBY);
#else
#error No ADC sleep mode defined for this hardware.
@@ -133,10 +128,13 @@ inline void ADC_on()
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL;
//ADCSRA |= (1 << ADSC); // start measuring
#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
- set_admux_voltage();
VREF.CTRLA |= VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V
- ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm; // Enabled, free-running (aka, auto-retrigger)
- ADC0.COMMAND |= ADC_STCONV_bm; // Start the ADC conversions
+ // Enabled, free-running (aka, auto-retrigger), run in standby
+ ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm | ADC_RUNSTBY_bm;
+ // set a INITDLY value because the AVR manual says so (section 30.3.5)
+ // (delay 1st reading until Vref is stable)
+ ADC0.CTRLD |= ADC_INITDLY_DLY16_gc;
+ set_admux_voltage();
#else
#error Unrecognized MCU type
#endif
@@ -144,7 +142,7 @@ inline void ADC_on()
inline void ADC_off() {
#ifdef AVRXMEGA3 // ATTINY816, 817, etc
- ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC
+ ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC
#else
ADCSRA &= ~(1< v) { v += 64; }
+ // fixed-rate lowpass, stable but very slow
+ // (move by only 0.5 ADC units per measurement, 1 ADC unit = 64)
+ if (r < s) { s -= 32; }
+ if (r > s) { s += 32; }
+ #elif 1
+ // 1/8th proportional lowpass, faster but less stable
+ int16_t diff = (r/8) - (s/8);
+ s += diff;
#else
- // weighted lowpass, faster but less stable
- v = (m>>1) + (v>>1);
+ // 50% proportional lowpass, fastest but least stable
+ s = (r>>1) + (s>>1);
#endif
- adc_smooth[0] = v;
- measurement = v;
+ adc_smooth[0] = s;
+ measurement = s;
}
#endif
else measurement = adc_smooth[0];
--
cgit v1.2.3