aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--arch/attiny1616.c125
-rw-r--r--arch/attiny1616.h20
-rw-r--r--arch/avr32dd20.c37
-rw-r--r--arch/avr32dd20.h4
-rw-r--r--fsm/adc.c47
-rw-r--r--fsm/adc.h4
-rw-r--r--hw/sofirn/sp10-pro/hwdef.h4
-rw-r--r--hw/thefreeman/avr32dd20-devkit/hwdef.c16
-rw-r--r--hw/thefreeman/avr32dd20-devkit/hwdef.h6
-rw-r--r--hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h17
-rw-r--r--ui/anduril/anduril.c1
-rw-r--r--ui/anduril/aux-leds.c34
-rw-r--r--ui/anduril/config-default.h4
13 files changed, 207 insertions, 112 deletions
diff --git a/arch/attiny1616.c b/arch/attiny1616.c
index a3ead7e..330c809 100644
--- a/arch/attiny1616.c
+++ b/arch/attiny1616.c
@@ -7,36 +7,60 @@
////////// clock speed / delay stuff //////////
+inline void mcu_clock_speed() {
+ // TODO: allow hwdef to define a base clock speed
+ // set up the system clock to run at 10 MHz instead of the default 3.33 MHz
+ _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB,
+ CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm );
+}
+
///// clock dividers
// this should work, but needs further validation
inline void clock_prescale_set(uint8_t n) {
cli();
- CCP = CCP_IOREG_gc; // temporarily disable clock change protection
- CLKCTRL.MCLKCTRLB = n; // Set the prescaler
+ _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, n); // Set the prescaler
while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {} // wait for clock change to finish
sei();
}
+
////////// ADC voltage / temperature //////////
inline void mcu_set_admux_therm() {
+ // put the ADC in temperature mode
+ // attiny1616 datasheet section 30.3.2.6
+ VREF.CTRLA = (VREF.CTRLA & (~VREF_ADC0REFSEL_gm))
+ | VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V
ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc; // read temperature
+ ADC0.CTRLB = ADC_SAMPNUM_ACC4_gc; // 10-bit result + 4x oversampling
ADC0.CTRLC = ADC_SAMPCAP_bm
- | ADC_PRESC_DIV64_gc
+ | ADC_PRESC_DIV16_gc
| ADC_REFSEL_INTREF_gc; // Internal ADC reference
}
inline void mcu_set_admux_voltage() {
- #ifdef USE_VOLTAGE_DIVIDER // 1.1V / ADC input pin
- // verify that this is correct!!! untested
+ // 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;
+ #ifdef USE_VOLTAGE_DIVIDER // measure an arbitrary pin
+ // result = resolution * Vdiv / 1.1V
+ VREF.CTRLA = (VREF.CTRLA & (~VREF_ADC0REFSEL_gm))
+ | VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V
ADC0.MUXPOS = ADMUX_VOLTAGE_DIVIDER; // read the requested ADC pin
+ ADC0.CTRLB = ADC_SAMPNUM_ACC4_gc; // 12-bit result, 4x oversampling
ADC0.CTRLC = ADC_SAMPCAP_bm
- | ADC_PRESC_DIV64_gc
+ | ADC_PRESC_DIV16_gc
| ADC_REFSEL_INTREF_gc; // Use internal ADC reference
- #else // VCC / 1.1V reference
+ #else // measure VDD pin
+ // result = resolution * 1.5V / Vbat
+ VREF.CTRLA = (VREF.CTRLA & (~VREF_ADC0REFSEL_gm))
+ | VREF_ADC0REFSEL_1V5_gc; // Set Vbg ref to 1.5V
ADC0.MUXPOS = ADC_MUXPOS_INTREF_gc; // read internal reference
+ ADC0.CTRLB = ADC_SAMPNUM_ACC4_gc; // 12-bit result, 4x oversampling
ADC0.CTRLC = ADC_SAMPCAP_bm
- | ADC_PRESC_DIV64_gc
+ | ADC_PRESC_DIV16_gc
| ADC_REFSEL_VDDREF_gc; // Vdd (Vcc) be ADC reference
#endif
}
@@ -47,9 +71,10 @@ inline void mcu_adc_sleep_mode() {
inline void mcu_adc_start_measurement() {
ADC0.INTCTRL |= ADC_RESRDY_bm; // enable interrupt
- ADC0.COMMAND |= ADC_STCONV_bm; // Start the ADC conversions
+ ADC0.COMMAND |= ADC_STCONV_bm; // actually start measuring
}
+/*
inline void mcu_adc_on() {
VREF.CTRLA |= VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V
// Enabled, free-running (aka, auto-retrigger), run in standby
@@ -59,6 +84,7 @@ inline void mcu_adc_on() {
ADC0.CTRLD |= ADC_INITDLY_DLY16_gc;
hwdef_set_admux_voltage();
}
+*/
inline void mcu_adc_off() {
ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC
@@ -69,22 +95,69 @@ inline void mcu_adc_vect_clear() {
}
inline uint16_t mcu_adc_result_temp() {
- // Use the factory calibrated values in SIGROW.TEMPSENSE0 and
- // SIGROW.TEMPSENSE1 to calculate a temperature reading in Kelvin, then
- // left-align it.
- int8_t sigrow_offset = SIGROW.TEMPSENSE1; // Read signed value from signature row
- uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned value from signature row
- uint32_t temp = ADC0.RES - sigrow_offset;
- temp *= sigrow_gain; // Result might overflow 16 bit variable (10bit+8bit)
- temp += 0x80; // Add 1/2 to get correct rounding on division below
- //temp >>= 8; // Divide result to get Kelvin
- //return temp << 6; // left align it
- return temp >> 2; // left-aligned uint16_t
+ // just return left-aligned ADC result, don't convert to calibrated units
+ //return ADC0.RES << 6;
+ return ADC0.RES << 4;
}
inline uint16_t mcu_adc_result_volts() {
- // FIXME: set up ADC to use left-aligned values natively
- return ADC0.RES << 6; // voltage, force left-alignment
+ // ADC has no left-aligned mode, so left-align it manually
+ return ADC0.RES << 4;
+}
+
+inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement) {
+ // In : 65535 * 1.5 / Vbat
+ // Out: uint8_t: Vbat * 40
+ // 1.5 = ADC Vref
+ #if 0
+ // 1024 = how much ADC resolution we're using (10 bits)
+ // (12 bits available, but it costs an extra 84 bytes of ROM to calculate)
+ uint8_t vbat40 = (uint16_t)(40 * 1.5 * 1024) / (measurement >> 6);
+ #else
+ // ... spend the extra 84 bytes of ROM for better precision
+ // 4096 = how much ADC resolution we're using (12 bits)
+ uint8_t vbat40 = (uint32_t)(40 * 1.5 * 4096) / (measurement >> 4);
+ #endif
+ return vbat40;
+}
+
+#if 0 // fine voltage, 0 to 10.24V in 1/6400th V steps
+inline uint16_t mcu_vdd_raw2fine(uint16_t measurement) {
+ // In : 65535 * 1.5 / Vbat
+ // Out: 65535 * (Vbat / 10) / 1.024V
+ uint16_t voltage = ((uint32_t)(1.5 * 4096 * 100 * 64 * 16) / measurement;
+ return voltage;
+}
+#endif
+
+#ifdef USE_VOLTAGE_DIVIDER
+inline uint8_t mcu_vdivider_raw2cooked(uint16_t measurement) {
+ // In : 4095 * Vdiv / 1.1V
+ // Out: uint8_t: Vbat * 40
+ // Vdiv = Vbat / 4.3 (typically)
+ // 1.1 = ADC Vref
+ const uint16_t adc_per_volt =
+ (((uint16_t)ADC_44 << 4) - ((uint16_t)ADC_22 << 4))
+ / (4 * (44-22));
+ uint8_t result = measurement / adc_per_volt;
+ return result;
+}
+#endif
+
+inline uint16_t mcu_temp_raw2cooked(uint16_t measurement) {
+ // convert raw ADC values to calibrated temperature
+ // In: ADC raw temperature (16-bit, or 12-bit left-aligned)
+ // Out: Kelvin << 6
+ // Precision: 1/64th Kelvin (but noisy)
+ // attiny1616 datasheet section 30.3.2.6
+ uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // factory calibration data
+ int8_t sigrow_offset = SIGROW.TEMPSENSE1;
+ const uint32_t scaling_factor = 65536; // use all 16 bits of ADC data
+ uint32_t temp = measurement - (sigrow_offset << 6);
+ temp *= sigrow_gain; // 24-bit result
+ temp += scaling_factor / 8; // Add 1/8th K to get correct rounding on later divisions
+ temp = temp >> 8; // change (K << 14) to (K << 6)
+ return temp; // left-aligned uint16_t, 0 to 1023.98 Kelvin
}
inline uint8_t mcu_adc_lsb() {
@@ -98,13 +171,15 @@ inline uint8_t mcu_adc_lsb() {
inline void mcu_wdt_active() {
RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
- RTC.PITCTRLA = RTC_PERIOD_CYC512_gc | RTC_PITEN_bm; // Period = 16ms, enable the PI Timer
+ // Period = 16ms (64 Hz), enable the PI Timer
+ RTC.PITCTRLA = RTC_PERIOD_CYC512_gc | RTC_PITEN_bm;
}
inline void mcu_wdt_standby() {
RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
- RTC.PITCTRLA = (1<<6) | (STANDBY_TICK_SPEED<<3) | RTC_PITEN_bm; // Set period, enable the PI Timer
+ // Set period (64 Hz / STANDBY_TICK_SPEED = 8 Hz), enable the PI Timer
+ RTC.PITCTRLA = (1<<6) | (STANDBY_TICK_SPEED<<3) | RTC_PITEN_bm;
}
inline void mcu_wdt_stop() {
@@ -148,6 +223,6 @@ void reboot() {
inline void prevent_reboot_loop() {
// prevent WDT from rebooting MCU again
RSTCTRL.RSTFR &= ~(RSTCTRL_WDRF_bm); // reset status flag
- wdt_disable();
+ wdt_disable(); // from avr/wdt.h
}
diff --git a/arch/attiny1616.h b/arch/attiny1616.h
index b4e17fc..57b0023 100644
--- a/arch/attiny1616.h
+++ b/arch/attiny1616.h
@@ -9,9 +9,11 @@
////////// clock speed / delay stuff //////////
#define F_CPU 10000000UL
-#define BOGOMIPS (F_CPU/4700)
+#define BOGOMIPS (F_CPU/4350)
#define DELAY_ZERO_TIME 1020
+inline void mcu_clock_speed();
+
///// clock dividers
// this should work, but needs further validation
inline void clock_prescale_set(uint8_t n);
@@ -44,20 +46,30 @@ inline void mcu_adc_sleep_mode();
inline void mcu_adc_start_measurement();
-inline void mcu_adc_on();
+//inline void mcu_adc_on();
inline void mcu_adc_off();
#define ADC_vect ADC0_RESRDY_vect
inline void mcu_adc_vect_clear();
+//// both readings are left-aligned
+//inline uint16_t mcu_adc_result();
+
// read ADC differently for temperature and voltage
#define MCU_ADC_RESULT_PER_TYPE
-
inline uint16_t mcu_adc_result_temp();
-
inline uint16_t mcu_adc_result_volts();
+// return Volts * 40, range 0 to 6.375V
+#define voltage_raw2cooked mcu_vdd_raw2cooked
+inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement);
+inline uint8_t mcu_vdivider_raw2cooked(uint16_t measurement);
+
+// return (temp in Kelvin << 6)
+#define temp_raw2cooked mcu_temp_raw2cooked
+inline uint16_t mcu_temp_raw2cooked(uint16_t measurement);
+
inline uint8_t mcu_adc_lsb();
diff --git a/arch/avr32dd20.c b/arch/avr32dd20.c
index 998e9f6..2ac3526 100644
--- a/arch/avr32dd20.c
+++ b/arch/avr32dd20.c
@@ -1,8 +1,10 @@
-// arch/avr32dd20.h: avr32dd20 support header
+// arch/avr32dd20.h: avr32dd20 support functions
// Copyright (C) 2023 Selene ToyKeeper
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
+#include "arch/avr32dd20.h"
+
////////// clock speed / delay stuff //////////
inline void mcu_clock_speed() {
@@ -137,12 +139,22 @@ inline uint16_t mcu_adc_result() {
return ADC0.RES;
}
-inline uint16_t mcu_vdd_raw2cooked(uint16_t measurement) {
+inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement) {
+ // In : 65535 * (Vbat / 10) / 1.024V
+ // Out: uint8_t: Vbat * 40
+ // (add 80 to round up near a boundary)
+ uint8_t vbat40 = (uint16_t)(measurement + 80) / 160;
+ return vbat40;
+}
+
+#if 0
+inline uint16_t mcu_vdd_raw2fine(uint16_t measurement) {
// In : 65535 * (Vbat / 10) / 1.024V
// Out: 65535 * (Vbat / 10) / 1.024V
// This MCU's native format is already correct
return measurement;
}
+#endif
inline uint16_t mcu_temp_raw2cooked(uint16_t measurement) {
// convert raw ADC values to calibrated temperature
@@ -164,29 +176,10 @@ inline uint16_t mcu_temp_raw2cooked(uint16_t measurement) {
}
inline uint8_t mcu_adc_lsb() {
- // temp is right-aligned, voltage is 16-bit, both have a useful LSB
+ // volts and temp are both 16-bit, so the LSB is useful as-is
return ADC0_RESL;
}
-#ifdef USE_VOLTAGE_VDD
-uint8_t calc_voltage(uint16_t measurement) {
- // calculate actual voltage: volts * 10
- // FIXME
- // ADC = 1.1 * 1024 / volts
- // volts = 1.1 * 1024 / ADC
- result = ((uint16_t)(2*1.1*1024*10)/(measurement>>6)
- + VOLTAGE_FUDGE_FACTOR
- #ifdef USE_VOLTAGE_CORRECTION
- + VOLT_CORR - 7
- #endif
- ) >> 1;
- return result;
-}
-#elif defined(USE_VOLTAGE_VDDIO2)
-#elif defined(USE_VOLTAGE_VDDIO2)
-#else
-// hwdef must supply its own function
-#endif
////////// WDT //////////
// this uses the RTC PIT interrupt instead of WDT,
diff --git a/arch/avr32dd20.h b/arch/avr32dd20.h
index 3ebb05a..82951de 100644
--- a/arch/avr32dd20.h
+++ b/arch/avr32dd20.h
@@ -58,9 +58,9 @@ inline uint16_t mcu_adc_result();
//inline uint16_t mcu_adc_result_temp();
//inline uint16_t mcu_adc_result_volts();
-// return (centiVolts << 6), range 0 to 10.24V
+// return Volts * 40, range 0 to 6.375V
#define voltage_raw2cooked mcu_vdd_raw2cooked
-inline uint16_t mcu_vdd_raw2cooked(uint16_t measurement);
+inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement);
// return (temp in Kelvin << 6)
#define temp_raw2cooked mcu_temp_raw2cooked
diff --git a/fsm/adc.c b/fsm/adc.c
index 73e282d..97dfc93 100644
--- a/fsm/adc.c
+++ b/fsm/adc.c
@@ -209,10 +209,16 @@ static inline void ADC_voltage_handler() {
#endif
else measurement = adc_smooth[0];
- // convert raw ADC value to FSM voltage units: (V * 100) << 6
- // 0 .. 65535 = 0.0V .. 10.24V
- measurement = voltage_raw2cooked(measurement) / (10 << 5);
-
+ // convert raw ADC value to FSM voltage units: Volts * 40
+ // 0 .. 200 = 0.0V .. 5.0V
+ voltage = voltage_raw2cooked(measurement)
+ + (VOLTAGE_FUDGE_FACTOR << 1)
+ #ifdef USE_VOLTAGE_CORRECTION
+ + ((VOLT_CORR - 7) << 1)
+ #endif
+ ;
+
+ /*
// calculate actual voltage: volts * 10
// TODO: should be (volts * 40) for extra precision
voltage = (measurement + VOLTAGE_FUDGE_FACTOR
@@ -220,6 +226,7 @@ static inline void ADC_voltage_handler() {
+ VOLT_CORR - 7
#endif
) >> 1;
+ */
#if 0
// values stair-step between intervals of 64, with random variations
@@ -433,33 +440,37 @@ static inline void ADC_temperature_handler() {
#ifdef USE_BATTCHECK
#ifdef BATTCHECK_4bars
PROGMEM const uint8_t voltage_blinks[] = {
- 30, 35, 38, 40, 42, 99,
+ 4*30, 4*35, 4*38, 4*40, 4*42, 255,
};
#endif
#ifdef BATTCHECK_6bars
PROGMEM const uint8_t voltage_blinks[] = {
- 30, 34, 36, 38, 40, 41, 43, 99,
+ 4*30, 4*34, 4*36, 4*38, 4*40, 4*41, 4*43, 255,
};
#endif
#ifdef BATTCHECK_8bars
PROGMEM const uint8_t voltage_blinks[] = {
- 30, 33, 35, 37, 38, 39, 40, 41, 42, 99,
+ 4*30, 4*33, 4*35, 4*37, 4*38, 4*39, 4*40, 4*41, 4*42, 255,
};
#endif
void battcheck() {
#ifdef BATTCHECK_VpT
- blink_num(voltage);
- #else
- uint8_t i;
- for(i=0;
- voltage >= pgm_read_byte(voltage_blinks + i);
- i++) {}
- #ifdef DONT_DELAY_AFTER_BATTCHECK
- blink_digit(i);
+ blink_num(voltage / 4);
+ #ifdef USE_EXTRA_BATTCHECK_DIGIT
+ // 0 1 2 3 --> 0 2 5 7, representing x.x00 x.x25 x.x50 x.x75
+ blink_num(((voltage % 4)<<1) + ((voltage % 4)>>1));
+ #endif
#else
- if (blink_digit(i))
- nice_delay_ms(1000);
- #endif
+ uint8_t i;
+ for(i=0;
+ voltage >= pgm_read_byte(voltage_blinks + i);
+ i++) {}
+ #ifdef DONT_DELAY_AFTER_BATTCHECK
+ blink_digit(i);
+ #else
+ if (blink_digit(i))
+ nice_delay_ms(1000);
+ #endif
#endif
}
#endif
diff --git a/fsm/adc.h b/fsm/adc.h
index 65d7d6c..0c0a9e5 100644
--- a/fsm/adc.h
+++ b/fsm/adc.h
@@ -17,11 +17,11 @@ volatile uint8_t adc_reset = 2;
#endif
// low-battery threshold in volts * 10
#ifndef VOLTAGE_LOW
-#define VOLTAGE_LOW 29
+#define VOLTAGE_LOW (4*29)
#endif
// battery is low but not critical
#ifndef VOLTAGE_RED
-#define VOLTAGE_RED 33
+#define VOLTAGE_RED (4*33)
#endif
// MCU sees voltage 0.X volts lower than actual, add X/2 to readings
#ifndef VOLTAGE_FUDGE_FACTOR
diff --git a/hw/sofirn/sp10-pro/hwdef.h b/hw/sofirn/sp10-pro/hwdef.h
index cb1271d..047758b 100644
--- a/hw/sofirn/sp10-pro/hwdef.h
+++ b/hw/sofirn/sp10-pro/hwdef.h
@@ -62,8 +62,8 @@ enum CHANNEL_MODES {
// Voltage divider battLVL
#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is regulated
-#define DUAL_VOLTAGE_FLOOR 21 // for AA/14500 boost drivers, don't indicate low voltage if below this level
-#define DUAL_VOLTAGE_LOW_LOW 7 // the lower voltage range's danger zone 0.7 volts (NiMH)
+#define DUAL_VOLTAGE_FLOOR (4*21) // for AA/14500 boost drivers, don't indicate low voltage if below this level
+#define DUAL_VOLTAGE_LOW_LOW (4*7) // the lower voltage range's danger zone 0.7 volts (NiMH)
#define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN9_gc // which ADC channel to read
// Raw ADC readings at 4.4V and 2.2V
diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.c b/hw/thefreeman/avr32dd20-devkit/hwdef.c
index 133baca..3e5dd79 100644
--- a/hw/thefreeman/avr32dd20-devkit/hwdef.c
+++ b/hw/thefreeman/avr32dd20-devkit/hwdef.c
@@ -104,15 +104,15 @@ bool gradual_tick_main(uint8_t gt) {
}
-uint16_t voltage_raw2cooked(uint16_t measurement) {
- // In : 65535 * BATTLVL pin / 1.024 Vref
- // Out: 65535 * (Vbat / 10) / 1.024V (i.e. FSM Volt units)
+uint8_t voltage_raw2cooked(uint16_t measurement) {
+ // In : 65535 * BATTLVL / 1.024V
+ // Out: uint8_t: Vbat * 40
// BATTLVL = Vbat * (100.0/(330+100)) = Vbat / 4.3
- // So, Out = In * 4.3 / 10.24
- // (plus 1.5% based on measured hardware)
- // (plus a fudge factor of +0.04V to round up to nearest 1/10th Volt)
- uint16_t result = ((uint32_t)measurement * 436 / 1024)
- + (65535 * 4 / 1024);
+ // So, Out = In * 4.3 / 1600
+ // (plus a bit of fudging to fix the slope and offset,
+ // based on measuring actual hardware)
+ uint8_t result = (uint32_t)(measurement + (65535 * 4 / 1024))
+ * 43 / 16128;
return result;
}
diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h
index 7e1ad3d..a5b37a9 100644
--- a/hw/thefreeman/avr32dd20-devkit/hwdef.h
+++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h
@@ -111,11 +111,11 @@ enum CHANNEL_MODES {
// AVR datasheet table 3.1 I/O Multiplexing, PA6 ADC0 = AIN26
#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is regulated
#define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN26_gc
-#define DUAL_VOLTAGE_FLOOR 21 // for AA/14500 boost drivers, don't indicate low voltage if below this level
-#define DUAL_VOLTAGE_LOW_LOW 7 // the lower voltage range's danger zone 0.7 volts (NiMH)
+#define DUAL_VOLTAGE_FLOOR (4*21) // for AA/14500 boost drivers, don't indicate low voltage if below this level
+#define DUAL_VOLTAGE_LOW_LOW (4*7) // the lower voltage range's danger zone 0.7 volts (NiMH)
// convert BATT LVL pin readings to FSM volt units
#undef voltage_raw2cooked
-uint16_t voltage_raw2cooked(uint16_t measurement);
+uint8_t voltage_raw2cooked(uint16_t measurement);
// average drop across diode on this hardware
diff --git a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h
index 095aea0..45c02de 100644
--- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h
+++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h
@@ -103,21 +103,20 @@ enum CHANNEL_MODES {
// Voltage divider battLVL
#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is regulated
-#define DUAL_VOLTAGE_FLOOR 21 // for AA/14500 boost drivers, don't indicate low voltage if below this level
-#define DUAL_VOLTAGE_LOW_LOW 7 // the lower voltage range's danger zone 0.7 volts (NiMH)
+#define DUAL_VOLTAGE_FLOOR (4*21) // for AA/14500 boost drivers, don't indicate low voltage if below this level
+#define DUAL_VOLTAGE_LOW_LOW (4*7) // the lower voltage range's danger zone 0.7 volts (NiMH)
#define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN2_gc // which ADC channel to read
+#undef voltage_raw2cooked
+#define voltage_raw2cooked mcu_vdivider_raw2cooked
+
// Raw ADC readings at 4.4V and 2.2V
// calibrate the voltage readout here
// estimated / calculated values are:
-// (voltage - D1) * (R2/(R2+R1) * 1024 / 1.1)
+// (voltage - D1) * (R2/(R2+R1) * 4096 / 1.1)
// Resistors are 330k and 100k
-#ifndef ADC_44
-#define ADC_44 951 // raw value at 4.40V
-#endif
-#ifndef ADC_22
-#define ADC_22 476 // raw value at 2.20V
-#endif
+#define ADC_44 3810 // raw value at 4.40V
+#define ADC_22 1905 // raw value at 2.20V
// this driver allows for aux LEDs under the optic
#define AUXLED_R_PIN PIN3_bp
diff --git a/ui/anduril/anduril.c b/ui/anduril/anduril.c
index c434518..1cdb8d0 100644
--- a/ui/anduril/anduril.c
+++ b/ui/anduril/anduril.c
@@ -316,6 +316,7 @@ void loop() {
#ifdef USE_BATTCHECK
else if (state == battcheck_state) {
+ nice_delay_ms(1000); // wait a moment for a more accurate reading
battcheck();
#ifdef USE_SIMPLE_UI
// in simple mode, turn off after one readout
diff --git a/ui/anduril/aux-leds.c b/ui/anduril/aux-leds.c
index dce8d26..fd184fc 100644
--- a/ui/anduril/aux-leds.c
+++ b/ui/anduril/aux-leds.c
@@ -58,27 +58,27 @@ void indicator_led_update(uint8_t mode, uint8_t tick) {
uint8_t voltage_to_rgb() {
static const uint8_t levels[] = {
// voltage, color
- 0, 0, // black
+ 0, 0, // black
#ifdef DUAL_VOLTAGE_FLOOR
// AA / NiMH voltages
- 9, 1, // R
- 10, 2, // R+G
- 11, 3, // G
- 12, 4, // G+B
- 13, 5, // B
- 14, 6, // R + B
- 16, 7, // R+G+B
- 20, 0, // black
+ 4* 9, 1, // R
+ 4*10, 2, // R+G
+ 4*11, 3, // G
+ 4*12, 4, // G+B
+ 4*13, 5, // B
+ 4*14, 6, // R + B
+ 4*16, 7, // R+G+B
+ 4*20, 0, // black
#endif
// li-ion voltages
- 29, 1, // R
- 33, 2, // R+G
- 35, 3, // G
- 37, 4, // G+B
- 39, 5, // B
- 41, 6, // R + B
- 44, 7, // R+G+B // skip; looks too similar to G+B
- 255, 7, // R+G+B
+ 4*29, 1, // R
+ 4*33, 2, // R+G
+ 4*35, 3, // G
+ 4*37, 4, // G+B
+ 4*39, 5, // B
+ 4*41, 6, // R + B
+ 4*44, 7, // R+G+B // skip; looks too similar to G+B
+ 255, 7, // R+G+B
};
uint8_t volts = voltage;
//if (volts < VOLTAGE_LOW) return 0;
diff --git a/ui/anduril/config-default.h b/ui/anduril/config-default.h
index cd25b52..1b34e8c 100644
--- a/ui/anduril/config-default.h
+++ b/ui/anduril/config-default.h
@@ -143,6 +143,10 @@
#define BATTCHECK_VpT
//#define BATTCHECK_8bars // FIXME: breaks build
//#define BATTCHECK_4bars // FIXME: breaks build
+#if ROM_SIZE > 10000
+ // battcheck displays 1.25V instead of 1.2V
+ #define USE_EXTRA_BATTCHECK_DIGIT
+#endif
// allow the user to calibrate the voltage readings?
// (adjust in 0.05V increments from -0.30V to +0.30V)
// (1 = -0.30V, 2 = -0.25V, ... 7 = 0V, ... 13 = +0.30V)
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.