From 1db145f1142a2557555a46fb8ec643aa0f21342d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 7 Nov 2023 14:11:41 -0700 Subject: [PATCH 01/57] oops, missed a venv name change in the readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6cb0f02c..3690cb30 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ source .venv/bin/activate pip install pymcuprog ``` -You'll need to `source env/bin/activate` every time you start a fresh shell, +You'll need to `source .venv/bin/activate` every time you start a fresh shell, if you want to use pymcuprog. The activation lasts until the shell is closed or until you run `deactivate`. From b0def630e3489f0e2a78dd27a1c0bb4b77663c6e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 7 Nov 2023 15:01:31 -0700 Subject: [PATCH 02/57] added a Makefile, so either `make` or `./make` can be used for most tasks `make` doesn't always work, like when the user tries to do certain types of CLI args, but it's handy to have as a convenience sometimes. What works: - make - make clean - make hank boost - make me a sandwich What doesn't work: - make foo --bar - make foo BAR=1 The `make` program eats some types of arguments. --- Makefile | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2f3aaedb --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +# Tiny Makefile to simply "exec ./make $*" +# Copyright (C) 2023 Selene ToyKeeper +# SPDX-License-Identifier: GPL-3.0-or-later + +# Note: Does not pass args in the form "-a", "--arg", or "VAR=value" +# because 'make' does not put those into $MAKECMDGOALS +# but this is still helpful in case the user forgets the './' before 'make' + +# for 'make foo bar baz', don't run 3 times +# (generate no-op rules for args 2+) +ARGS := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS)) +$(eval $(ARGS):;@:) + +# handle the case with no args +all: + @./make + +# catch everything else and parse the command line ourselves +.PHONY: % +%: + @./make $(MAKECMDGOALS) + +# handle targets with the same name as a dir, +# because 'make' skips those otherwise +.PHONY: docs +docs: + @./make docs + From cd77624256328b1924c49158b08f9d8c454fb637 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Nov 2023 14:52:41 -0700 Subject: [PATCH 03/57] added md5sum to build-all.sh output per target (to make it easier to detect when builds did or didn't change) --- bin/build-all.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index 130923fe..df72ad51 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -52,8 +52,11 @@ for TARGET in hw/*/*/**/"$UI".h ; do # try to compile, track result, and rename compiled files if bin/build.sh "$TARGET" ; then - mv -f "ui/$UI/$UI".hex "hex/$UI.$NAME.hex" - echo " > hex/$UI.$NAME.hex" + HEX_OUT="hex/$UI.$NAME.hex" + mv -f "ui/$UI/$UI".hex "$HEX_OUT" + MD5=$(md5sum "$HEX_OUT" | cut -d ' ' -f 1) + echo " # $MD5" + echo " > $HEX_OUT" PASS=$((PASS + 1)) PASSED="$PASSED $NAME" else From 3d12b7066d27b591e0283e20ed066bc66e29fbe4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Nov 2023 21:34:40 -0700 Subject: [PATCH 04/57] refactor checkpoint: splitting MCU-specific code into arch/$MCU.[ch] Phew, that's a lot of changes! And there's still a lot more to do... --- arch/attiny1616.c | 147 +++++++++++++++ arch/attiny1616.h | 96 ++++++++++ arch/attiny1634.c | 125 +++++++++++++ arch/attiny1634.h | 98 ++++++++++ arch/attiny85.c | 167 ++++++++++++++++++ arch/attiny85.h | 91 ++++++++++ arch/mcu.c | 10 ++ arch/mcu.h | 147 ++------------- bin/detect-mcu.sh | 4 +- fsm/adc.c | 159 +++-------------- fsm/adc.h | 12 +- fsm/main.c | 62 +------ fsm/misc.c | 22 --- fsm/misc.h | 4 - fsm/pcint.c | 54 +----- fsm/pcint.h | 6 +- fsm/spaghetti-monster.h | 9 +- fsm/wdt.c | 78 +------- fsm/wdt.h | 7 +- hw/gchart/fet1-t1616/hwdef.h | 4 +- hw/hank/emisar-2ch/fet/hwdef.h | 6 +- hw/hank/emisar-2ch/hwdef.h | 6 +- hw/hank/emisar-d18/hwdef.h | 4 +- hw/hank/emisar-d4/hwdef.h | 4 +- hw/hank/emisar-d4k-3ch/hwdef.h | 6 +- hw/hank/emisar-d4sv2/hwdef.h | 6 +- hw/hank/emisar-d4v2/hwdef.h | 8 +- hw/hank/emisar-d4v2/nofet/anduril.h | 2 +- hw/hank/noctigon-dm11/boost/hwdef.h | 6 +- hw/hank/noctigon-dm11/hwdef.h | 8 +- hw/hank/noctigon-dm11/nofet/anduril.h | 2 +- hw/hank/noctigon-k1/boost/hwdef.h | 6 +- hw/hank/noctigon-k1/hwdef.h | 8 +- hw/hank/noctigon-k1/sbt90/hwdef.h | 6 +- hw/hank/noctigon-kr4/2ch/hwdef.h | 4 +- hw/hank/noctigon-kr4/boost/hwdef.h | 4 +- hw/hank/noctigon-kr4/hwdef.h | 8 +- hw/hank/noctigon-kr4/nofet/anduril.h | 2 +- hw/hank/noctigon-m44/hwdef.h | 6 +- hw/lumintop/blf-gt/hwdef.h | 4 +- hw/lumintop/fw3a/hwdef.h | 4 +- hw/lumintop/fw3x-lume1/hwdef.h | 6 +- hw/mateminco/mf01-mini/hwdef.h | 4 +- hw/mateminco/mf01s/hwdef.h | 4 +- hw/mateminco/mt35-mini/hwdef.h | 4 +- hw/sofirn/blf-lt1-t1616/hwdef.h | 4 +- hw/sofirn/blf-lt1/hwdef.h | 4 +- hw/sofirn/blf-q8-t1616/hwdef.h | 4 +- hw/sofirn/lt1s-pro/hwdef.h | 4 +- hw/sofirn/sp10-pro/hwdef.h | 6 +- .../boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h | 6 +- .../boost21-mp3431-hdr-dac-argb/hwdef.h | 6 +- hw/thefreeman/lin16dac/hwdef.h | 4 +- hw/wurkkos/ts10/hwdef.h | 6 +- hw/wurkkos/ts25/hwdef.h | 6 +- ui/anduril/anduril.c | 18 +- ui/anduril/config-default.h | 6 +- 57 files changed, 862 insertions(+), 642 deletions(-) create mode 100644 arch/attiny1616.c create mode 100644 arch/attiny1616.h create mode 100644 arch/attiny1634.c create mode 100644 arch/attiny1634.h create mode 100644 arch/attiny85.c create mode 100644 arch/attiny85.h create mode 100644 arch/mcu.c diff --git a/arch/attiny1616.c b/arch/attiny1616.c new file mode 100644 index 00000000..3b170bbd --- /dev/null +++ b/arch/attiny1616.c @@ -0,0 +1,147 @@ +// arch/attiny1616.c: attiny1616 support functions +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "arch/attiny1616.h" + +////////// clock speed / delay stuff ////////// + +///// 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 + while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {} // wait for clock change to finish + sei(); +} + +////////// ADC voltage / temperature ////////// + +inline void mcu_set_admux_therm() { + ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc; // read temperature + ADC0.CTRLC = ADC_SAMPCAP_bm + | ADC_PRESC_DIV64_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 + ADC0.MUXPOS = ADMUX_VOLTAGE_DIVIDER; // read the requested ADC pin + ADC0.CTRLC = ADC_SAMPCAP_bm + | ADC_PRESC_DIV64_gc + | ADC_REFSEL_INTREF_gc; // Use internal ADC reference + #else // VCC / 1.1V reference + ADC0.MUXPOS = ADC_MUXPOS_INTREF_gc; // read internal reference + ADC0.CTRLC = ADC_SAMPCAP_bm + | ADC_PRESC_DIV64_gc + | ADC_REFSEL_VDDREF_gc; // Vdd (Vcc) be ADC reference + #endif +} + +inline void mcu_adc_sleep_mode() { + set_sleep_mode(SLEEP_MODE_STANDBY); +} + +inline void mcu_adc_start_measurement() { + ADC0.INTCTRL |= ADC_RESRDY_bm; // enable interrupt + ADC0.COMMAND |= ADC_STCONV_bm; // Start the ADC conversions +} + +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 + 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; + hwdef_set_admux_voltage(); +} + +inline void mcu_adc_off() { + ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC +} + +inline void mcu_adc_vect_clear() { + ADC0.INTFLAGS = ADC_RESRDY_bm; // clear the interrupt +} + +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 +} + +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 +} + +inline uint8_t mcu_adc_lsb() { + //return (ADCL >> 6) + (ADCH << 2); + return ADC0.RESL; // right aligned, not left... so should be equivalent? +} + + +////////// WDT ////////// + +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 +} + +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 +} + +inline void mcu_wdt_stop() { + while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated + RTC.PITCTRLA = 0; // Disable the PI Timer +} + +inline void mcu_wdt_vect_clear() { + RTC.PITINTFLAGS = RTC_PI_bm; // clear the PIT interrupt flag +} + + +////////// PCINT - pin change interrupt (e-switch) ////////// + +inline void mcu_switch_vect_clear() { + // Write a '1' to clear the interrupt flag + SWITCH_INTFLG |= (1 << SWITCH_PIN); +} + +inline void mcu_pcint_on() { + SWITCH_ISC_REG |= PORT_ISC_BOTHEDGES_gc; +} + +inline void mcu_pcint_off() { + SWITCH_ISC_REG &= ~(PORT_ISC_gm); +} + + +////////// misc ////////// + +void reboot() { + // put the WDT in hard reset mode, then trigger it + cli(); + CCP = CCP_IOREG_gc; // temporarily disable change protection + WDT.CTRLA = WDT_PERIOD_8CLK_gc; // Enable, timeout 8ms + sei(); + wdt_reset(); + while (1) {} +} + diff --git a/arch/attiny1616.h b/arch/attiny1616.h new file mode 100644 index 00000000..59897854 --- /dev/null +++ b/arch/attiny1616.h @@ -0,0 +1,96 @@ +// arch/attiny1616.h: attiny1616 support header +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +// FIXME: remove this +#define AVRXMEGA3 + +////////// clock speed / delay stuff ////////// + +#define F_CPU 10000000UL +#define BOGOMIPS (F_CPU/4700) +#define DELAY_ZERO_TIME 1020 + +///// clock dividers +// this should work, but needs further validation +inline void clock_prescale_set(uint8_t n); + +typedef enum +{ + // Actual clock is 20 MHz, but assume that 10 MHz is the top speed and work from there + // TODO: measure PWM speed and power use at 1.25/2.5/5/10 MHz, to determine which speeds are optimal + clock_div_1 = (CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm), // 10 MHz + clock_div_2 = (CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm), // 5 MHz + clock_div_4 = (CLKCTRL_PDIV_8X_gc | CLKCTRL_PEN_bm), // 2.5 MHz + clock_div_8 = (CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm), // 1.25 MHz + clock_div_16 = (CLKCTRL_PDIV_32X_gc | CLKCTRL_PEN_bm), // 625 kHz + clock_div_32 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz, max without changing to the 32 kHz ULP + clock_div_64 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz + clock_div_128 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz + clock_div_256 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm) // 312 kHz +} clock_div_t; + + +////////// ADC voltage / temperature ////////// + +#define hwdef_set_admux_therm mcu_set_admux_therm +inline void mcu_set_admux_therm(); + +#define hwdef_set_admux_voltage mcu_set_admux_voltage +inline void mcu_set_admux_voltage(); + +inline void mcu_adc_sleep_mode(); + +inline void mcu_adc_start_measurement(); + +inline void mcu_adc_on(); + +inline void mcu_adc_off(); + +#define ADC_vect ADC0_RESRDY_vect +inline void mcu_adc_vect_clear(); + +// 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(); + +inline uint8_t mcu_adc_lsb(); + + +////////// WDT ////////// + +inline void mcu_wdt_active(); + +inline void mcu_wdt_standby(); + +inline void mcu_wdt_stop(); + +// *** Note for the AVRXMEGA3 (1-Series, eg 816 and 817), the WDT +// is not used for time-based interrupts. A new peripheral, the +// Periodic Interrupt Timer ("PIT") is used for this purpose. + +#define WDT_vect RTC_PIT_vect +inline void mcu_wdt_vect_clear(); + + +////////// PCINT - pin change interrupt (e-switch) ////////// + +// set these in hwdef +//#define SWITCH_PORT PINA +//#define SWITCH_VECT PCINT0_vect + +inline void mcu_switch_vect_clear(); + +inline void mcu_pcint_on(); + +inline void mcu_pcint_off(); + + +////////// misc ////////// + +void reboot(); + diff --git a/arch/attiny1634.c b/arch/attiny1634.c new file mode 100644 index 00000000..d4b37676 --- /dev/null +++ b/arch/attiny1634.c @@ -0,0 +1,125 @@ +// arch/attiny1634.c: attiny85 support functions +// Copyright (C) 2014-2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "arch/attiny1634.h" + +////////// clock speed / delay stuff ////////// + +///// clock dividers +// make it a NOP for now +// FIXME +//#define clock_prescale_set(x) ((void)0) +//#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();} +//#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();} +inline void clock_prescale_set(uint8_t n) { + cli(); + CCP = 0xD8; + CLKPR = n; + sei(); +} + +////////// default hw_setup() ////////// + + +////////// ADC voltage / temperature ////////// + +inline void mcu_set_admux_therm() { + ADMUX = ADMUX_THERM; +} + +inline void mcu_set_admux_voltage() { + #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 + ADMUX = ADMUX_VOLTAGE_DIVIDER; + #else // VCC / 1.1V reference + ADMUX = ADMUX_VCC; + #endif +} + +inline void mcu_adc_sleep_mode() { + set_sleep_mode(SLEEP_MODE_ADC); +} + +inline void mcu_adc_start_measurement() { + ADCSRA |= (1 << ADSC) | (1 << ADIE); +} + +inline void mcu_adc_on() { + hwdef_set_admux_voltage(); + #ifdef USE_VOLTAGE_DIVIDER + // disable digital input on divider pin to reduce power consumption + VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); + #else + // disable digital input on VCC pin to reduce power consumption + //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin + #endif + //ACSRA |= (1 << ACD); // turn off analog comparator to save power + ADCSRB |= (1 << ADLAR); // left-adjust flag is here instead of ADMUX + // enable, start, auto-retrigger, prescale + ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL; +} + +inline void mcu_adc_off() { + ADCSRA &= ~(1<> 6) + (ADCH << 2); } + + +////////// WDT ////////// + +inline void mcu_wdt_active() { + wdt_reset(); // Reset the WDT + WDTCSR = (1<= 1 + DDRB |= (1 << PWM1_PIN); + TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...) + TCCR0A = PHASE; + #if (PWM1_PIN == PB4) // Second PWM counter is ... weird + TCCR1 = _BV (CS10); + GTCCR = _BV (COM1B1) | _BV (PWM1B); + OCR1C = 255; // Set ceiling value to maximum + #endif + #endif + // tint ramping needs second channel enabled, + // despite PWM_CHANNELS being only 1 + #if (PWM_CHANNELS >= 2) || defined(USE_TINT_RAMPING) + DDRB |= (1 << PWM2_PIN); + #if (PWM2_PIN == PB4) // Second PWM counter is ... weird + TCCR1 = _BV (CS10); + GTCCR = _BV (COM1B1) | _BV (PWM1B); + OCR1C = 255; // Set ceiling value to maximum + #endif + #endif + #if PWM_CHANNELS >= 3 + DDRB |= (1 << PWM3_PIN); + #if (PWM3_PIN == PB4) // Second PWM counter is ... weird + TCCR1 = _BV (CS10); + GTCCR = _BV (COM1B1) | _BV (PWM1B); + OCR1C = 255; // Set ceiling value to maximum + #endif + #endif + #if PWM_CHANNELS >= 4 + // 4th PWM channel is ... not actually supported in hardware :( + DDRB |= (1 << PWM4_PIN); + //OCR1C = 255; // Set ceiling value to maximum + TCCR1 = 1<> 6) + (ADCH << 2); } + + +////////// WDT ////////// + +inline void mcu_wdt_active() { + // interrupt every 16ms + //cli(); // Disable interrupts + wdt_reset(); // Reset the WDT + WDTCR |= (1< #include +#include +#include +#include +#include -/******************** I/O pin and register layout ************************/ -#ifdef HWDEFFILE -#include "fsm/tk.h" -#include incfile(HWDEFFILE) -#endif - -#if 0 // placeholder - -#elif defined(NANJG_LAYOUT) -#include "hwdef-nanjg.h" -#elif defined(FET_7135_LAYOUT) -#include "hwdef-FET_7135.h" +// for consistency, ROM_SIZE + EEPROM_SIZE +#define ROM_SIZE PROGMEM_SIZE -#elif defined(TRIPLEDOWN_LAYOUT) -#include "hwdef-Tripledown.h" - -#elif defined(FERRERO_ROCHER_LAYOUT) -#include "hwdef-Ferrero_Rocher.h" - -#endif // no more recognized driver types - -#ifndef LAYOUT_DEFINED -#error Hey, you need to define an I/O pin layout. -#endif - -#if (ATTINY==13) - // no changes needed -#elif (ATTINY==25) || (ATTINY==45) || (ATTINY==85) - // use clock_prescale_set(n) instead; it's safer - //#define CLOCK_DIVIDER_SET(n) {CLKPR = 1<>= 8; // Divide result to get Kelvin - m = (temp << 6); // left align it - } - else { m = (ADC0.RES << 6); } // voltage, force left-alignment - + #ifdef MCU_ADC_RESULT_PER_TYPE + // thermal, convert ADC reading to left-aligned Kelvin + if (channel) m = mcu_adc_result_temp(); + else m = mcu_adc_result_volts(); #else - m = ADC; + m = mcu_adc_result(); #endif adc_raw[channel] = m; @@ -235,11 +118,7 @@ void adc_deferred() { // real-world entropy makes this a true random, not pseudo // Why here instead of the ISR? Because it makes the time-critical ISR // code a few cycles faster and we don't need crypto-grade randomness. - #ifdef AVRXMEGA3 // ATTINY816, 817, etc - pseudo_rand_seed += ADC0.RESL; // right aligned, not left... so should be equivalent? - #else - pseudo_rand_seed += (ADCL >> 6) + (ADCH << 2); - #endif + pseudo_rand_seed += mcu_adc_lsb(); #endif // the ADC triggers repeatedly when it's on, but we only need to run the @@ -373,9 +252,9 @@ static inline void ADC_voltage_handler() { if (lvp_timer) { lvp_timer --; } else { // it has been long enough since the last warning - #ifdef DUAL_VOLTAGE_FLOOR - if (((voltage < VOLTAGE_LOW) && (voltage > DUAL_VOLTAGE_FLOOR)) || (voltage < DUAL_VOLTAGE_LOW_LOW)) { - #else + #ifdef DUAL_VOLTAGE_FLOOR + if (((voltage < VOLTAGE_LOW) && (voltage > DUAL_VOLTAGE_FLOOR)) || (voltage < DUAL_VOLTAGE_LOW_LOW)) { + #else if (voltage < VOLTAGE_LOW) { #endif // send out a warning @@ -440,6 +319,8 @@ static inline void ADC_temperature_handler() { // let the UI see the current temperature in C // Convert ADC units to Celsius (ish) + // FIXME: call something in arch/$mcu.h or hwdef.h + // instead of calculating this here #ifndef USE_EXTERNAL_TEMP_SENSOR // onboard sensor for attiny25/45/85/1634 temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275; diff --git a/fsm/adc.h b/fsm/adc.h index 1bb67ed2..e4046a41 100644 --- a/fsm/adc.h +++ b/fsm/adc.h @@ -102,11 +102,15 @@ static inline void ADC_temperature_handler(); #endif // ifdef USE_THERMAL_REGULATION -inline void ADC_on(); -inline void ADC_off(); -inline void ADC_start_measurement(); +//inline void ADC_on(); +#define ADC_on mcu_adc_on +//inline void ADC_off(); +#define ADC_off mcu_adc_off +//inline void ADC_start_measurement(); +#define ADC_start_measurement mcu_adc_start_measurement #ifdef TICK_DURING_STANDBY -inline void adc_sleep_mode(); + //inline void adc_sleep_mode(); + #define adc_sleep_mode mcu_adc_sleep_mode #endif diff --git a/fsm/main.c b/fsm/main.c index 05241153..1c01878f 100644 --- a/fsm/main.c +++ b/fsm/main.c @@ -23,66 +23,6 @@ ISR(TIMER1_COMPA_vect) { } #endif -// FIXME: hw_setup() shouldn't be here ... move it entirely to hwdef files -#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) -static inline void hw_setup() { - #if !defined(USE_GENERIC_HWDEF_SETUP) - hwdef_setup(); - #else - // configure PWM channels - #if PWM_CHANNELS >= 1 - DDRB |= (1 << PWM1_PIN); - TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...) - TCCR0A = PHASE; - #if (PWM1_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - // tint ramping needs second channel enabled, - // despite PWM_CHANNELS being only 1 - #if (PWM_CHANNELS >= 2) || defined(USE_TINT_RAMPING) - DDRB |= (1 << PWM2_PIN); - #if (PWM2_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - #if PWM_CHANNELS >= 3 - DDRB |= (1 << PWM3_PIN); - #if (PWM3_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - #if PWM_CHANNELS >= 4 - // 4th PWM channel is ... not actually supported in hardware :( - DDRB |= (1 << PWM4_PIN); - //OCR1C = 255; // Set ceiling value to maximum - TCCR1 = 1< -#include +#include "arch/mcu.h" // include project definitions to help with recognizing symbols #include "fsm/events.h" @@ -39,6 +38,10 @@ #include "arch/delay.h" #endif +////////// include all the .c files ////////// + +#include "arch/mcu.c" + #ifdef USE_DEBUG_BLINK #define DEBUG_FLASH PWM1_LVL = 64; delay_4ms(2); PWM1_LVL = 0; void debug_blink(uint8_t num) { diff --git a/fsm/wdt.c b/fsm/wdt.c index 64f006e5..1095d448 100644 --- a/fsm/wdt.c +++ b/fsm/wdt.c @@ -7,85 +7,9 @@ #include #include -// *** Note for the AVRXMEGA3 (1-Series, eg 816 and 817), the WDT -// is not used for time-based interrupts. A new peripheral, the -// Periodic Interrupt Timer ("PIT") is used for this purpose. - -void WDT_on() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - // interrupt every 16ms - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - WDTCR |= (1< 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 - #else - #error Unrecognized MCU type - #endif -} - -#ifdef TICK_DURING_STANDBY -inline void WDT_slow() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - // interrupt slower - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - WDTCR |= (1< 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 - #else - #error Unrecognized MCU type - #endif -} -#endif - -inline void WDT_off() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - MCUSR &= ~(1< 0) {} // make sure the register is ready to be updated - RTC.PITCTRLA = 0; // Disable the PI Timer - #else - #error Unrecognized MCU type - #endif -} - // clock tick -- this runs every 16ms (62.5 fps) -#ifdef AVRXMEGA3 // ATTINY816, 817, etc -ISR(RTC_PIT_vect) { - RTC.PITINTFLAGS = RTC_PI_bm; // clear the PIT interrupt flag -#else ISR(WDT_vect) { -#endif + mcu_wdt_vect_clear(); irq_wdt = 1; // WDT event happened } diff --git a/fsm/wdt.h b/fsm/wdt.h index abf34c5e..98eaf25e 100644 --- a/fsm/wdt.h +++ b/fsm/wdt.h @@ -6,8 +6,11 @@ #define TICKS_PER_SECOND 62 -void WDT_on(); -inline void WDT_off(); +//void WDT_on(); +//inline void WDT_off(); +#define WDT_on mcu_wdt_active +#define WDT_slow mcu_wdt_standby +#define WDT_off mcu_wdt_stop volatile uint8_t irq_wdt = 0; // WDT interrupt happened? diff --git a/hw/gchart/fet1-t1616/hwdef.h b/hw/gchart/fet1-t1616/hwdef.h index ac4fd538..40083fc5 100644 --- a/hw/gchart/fet1-t1616/hwdef.h +++ b/hw/gchart/fet1-t1616/hwdef.h @@ -11,11 +11,9 @@ * Read voltage from VCC pin, has diode with ~0.4v drop */ -#include - // nearly all t1616-based FET+1 drivers work pretty much the same // (this one has single-color aux like the TS10) -#define HWDEF_C_FILE wurkkos/ts10/hwdef.c +#define HWDEF_C wurkkos/ts10/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-aux.h" diff --git a/hw/hank/emisar-2ch/fet/hwdef.h b/hw/hank/emisar-2ch/fet/hwdef.h index 0778e101..06dfeb8b 100644 --- a/hw/hank/emisar-2ch/fet/hwdef.h +++ b/hw/hank/emisar-2ch/fet/hwdef.h @@ -32,9 +32,7 @@ * The first channel also has a direct-drive FET for turbo. */ -#include - -#define HWDEF_C_FILE hank/emisar-2ch/fet/hwdef.c +#define HWDEF_C hank/emisar-2ch/fet/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -106,7 +104,7 @@ enum channel_modes_e { #define SWITCH_PCMSK PCMSK0 // PCMSK1 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #endif #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened diff --git a/hw/hank/emisar-2ch/hwdef.h b/hw/hank/emisar-2ch/hwdef.h index e3707c78..7fbac8ef 100644 --- a/hw/hank/emisar-2ch/hwdef.h +++ b/hw/hank/emisar-2ch/hwdef.h @@ -31,9 +31,7 @@ * and one pin to control the Opamp power level. */ -#include - -#define HWDEF_C_FILE hank/emisar-2ch/hwdef.c +#define HWDEF_C hank/emisar-2ch/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -103,7 +101,7 @@ enum channel_modes_e { #define SWITCH_PCMSK PCMSK0 // PCMSK1 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #endif #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened diff --git a/hw/hank/emisar-d18/hwdef.h b/hw/hank/emisar-d18/hwdef.h index 86c97c27..a0d3cd03 100644 --- a/hw/hank/emisar-d18/hwdef.h +++ b/hw/hank/emisar-d18/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE lumintop/fw3a/hwdef.c +#define HWDEF_C lumintop/fw3a/hwdef.c // channel modes // * 0. FET+N+1 stacked diff --git a/hw/hank/emisar-d4/hwdef.h b/hw/hank/emisar-d4/hwdef.h index 55ef72ef..6257ddb6 100644 --- a/hw/hank/emisar-d4/hwdef.h +++ b/hw/hank/emisar-d4/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE hank/emisar-d4/hwdef.c +#define HWDEF_C hank/emisar-d4/hwdef.c // allow using aux LEDs as extra channel modes (when they exist) //#ifdef AUXLED_PIN diff --git a/hw/hank/emisar-d4k-3ch/hwdef.h b/hw/hank/emisar-d4k-3ch/hwdef.h index 7cfe6991..002804c6 100644 --- a/hw/hank/emisar-d4k-3ch/hwdef.h +++ b/hw/hank/emisar-d4k-3ch/hwdef.h @@ -35,9 +35,7 @@ * So this code should support both wire layouts. */ -#include - -#define HWDEF_C_FILE hank/emisar-d4k-3ch/hwdef.c +#define HWDEF_C hank/emisar-d4k-3ch/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -132,7 +130,7 @@ uint8_t led4_pwm, led4_dsm; #define SWITCH_PCMSK PCMSK0 // PCMSK1 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #endif #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened diff --git a/hw/hank/emisar-d4sv2/hwdef.h b/hw/hank/emisar-d4sv2/hwdef.h index d1e04528..121593a0 100644 --- a/hw/hank/emisar-d4sv2/hwdef.h +++ b/hw/hank/emisar-d4sv2/hwdef.h @@ -30,9 +30,7 @@ * ADC12 thermal sensor */ -#include - -#define HWDEF_C_FILE hank/emisar-d4sv2/hwdef.c +#define HWDEF_C hank/emisar-d4sv2/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -89,7 +87,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define ADC_PRSCL 0x07 // clk/128 diff --git a/hw/hank/emisar-d4v2/hwdef.h b/hw/hank/emisar-d4v2/hwdef.h index 9e3f755a..1c100043 100644 --- a/hw/hank/emisar-d4v2/hwdef.h +++ b/hw/hank/emisar-d4v2/hwdef.h @@ -28,10 +28,8 @@ * ADC12 thermal sensor */ -#include - -#ifndef HWDEF_C_FILE -#define HWDEF_C_FILE hank/emisar-d4v2/hwdef.c +#ifndef HWDEF_C +#define HWDEF_C hank/emisar-d4v2/hwdef.c #endif // allow using aux LEDs as extra channel modes @@ -84,7 +82,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define ADC_PRSCL 0x07 // clk/128 diff --git a/hw/hank/emisar-d4v2/nofet/anduril.h b/hw/hank/emisar-d4v2/nofet/anduril.h index b5f9304e..e05fb2e8 100644 --- a/hw/hank/emisar-d4v2/nofet/anduril.h +++ b/hw/hank/emisar-d4v2/nofet/anduril.h @@ -4,7 +4,7 @@ #pragma once // switch to 1-channel support functions -#define HWDEF_C_FILE hank/emisar-d4v2/nofet/hwdef.c +#define HWDEF_C hank/emisar-d4v2/nofet/hwdef.c #include "hank/emisar-d4v2/anduril.h" diff --git a/hw/hank/noctigon-dm11/boost/hwdef.h b/hw/hank/noctigon-dm11/boost/hwdef.h index 5ac2dafd..bef409f0 100644 --- a/hw/hank/noctigon-dm11/boost/hwdef.h +++ b/hw/hank/noctigon-dm11/boost/hwdef.h @@ -36,9 +36,7 @@ * not to change brightness. */ -#include - -#define HWDEF_C_FILE hank/noctigon-dm11/boost/hwdef.c +#define HWDEF_C hank/noctigon-dm11/boost/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -101,7 +99,7 @@ uint8_t ch1_pwm, ch1_dsm; #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened #define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6 diff --git a/hw/hank/noctigon-dm11/hwdef.h b/hw/hank/noctigon-dm11/hwdef.h index cd21eae3..11cf3a02 100644 --- a/hw/hank/noctigon-dm11/hwdef.h +++ b/hw/hank/noctigon-dm11/hwdef.h @@ -37,10 +37,8 @@ * Some models also have a direct-drive FET for turbo. */ -#include - -#ifndef HWDEF_C_FILE -#define HWDEF_C_FILE hank/noctigon-kr4/hwdef.c +#ifndef HWDEF_C +#define HWDEF_C hank/noctigon-kr4/hwdef.c #endif // allow using aux LEDs as extra channel modes @@ -95,7 +93,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened diff --git a/hw/hank/noctigon-dm11/nofet/anduril.h b/hw/hank/noctigon-dm11/nofet/anduril.h index 12336f17..c13f4ab9 100644 --- a/hw/hank/noctigon-dm11/nofet/anduril.h +++ b/hw/hank/noctigon-dm11/nofet/anduril.h @@ -4,7 +4,7 @@ #pragma once // same support functions as a KR4 -#define HWDEF_C_FILE hank/noctigon-kr4/nofet/hwdef.c +#define HWDEF_C hank/noctigon-kr4/nofet/hwdef.c #include "hank/noctigon-dm11/anduril.h" // turn off the DD FET diff --git a/hw/hank/noctigon-k1/boost/hwdef.h b/hw/hank/noctigon-k1/boost/hwdef.h index 951932a7..e0a314c2 100644 --- a/hw/hank/noctigon-k1/boost/hwdef.h +++ b/hw/hank/noctigon-k1/boost/hwdef.h @@ -34,9 +34,7 @@ * not to change brightness. */ -#include - -#define HWDEF_C_FILE hank/noctigon-dm11/boost/hwdef.c +#define HWDEF_C hank/noctigon-dm11/boost/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -99,7 +97,7 @@ uint8_t ch1_pwm, ch1_dsm; #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened #define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6 diff --git a/hw/hank/noctigon-k1/hwdef.h b/hw/hank/noctigon-k1/hwdef.h index 9a68401d..822b9591 100644 --- a/hw/hank/noctigon-k1/hwdef.h +++ b/hw/hank/noctigon-k1/hwdef.h @@ -36,10 +36,8 @@ * not to change brightness. */ -#include - -#ifndef HWDEF_C_FILE -#define HWDEF_C_FILE hank/noctigon-k1/hwdef.c +#ifndef HWDEF_C +#define HWDEF_C hank/noctigon-k1/hwdef.c #endif // allow using aux LEDs as extra channel modes @@ -88,7 +86,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened diff --git a/hw/hank/noctigon-k1/sbt90/hwdef.h b/hw/hank/noctigon-k1/sbt90/hwdef.h index 8186b49b..4c56bc06 100644 --- a/hw/hank/noctigon-k1/sbt90/hwdef.h +++ b/hw/hank/noctigon-k1/sbt90/hwdef.h @@ -37,9 +37,7 @@ * Also has a direct-drive FET for turbo. */ -#include - -#define HWDEF_C_FILE hank/noctigon-kr4/hwdef.c +#define HWDEF_C hank/noctigon-kr4/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -93,7 +91,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK1 // PCMSK1 is for PCINT[11:8] #define SWITCH_PORT PINB // PINA or PINB or PINC #define SWITCH_PUE PUEB // pullup group B -#define PCINT_vect PCINT1_vect // ISR for PCINT[11:8] +#define SWITCH_VECT PCINT1_vect // ISR for PCINT[11:8] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened #define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6 diff --git a/hw/hank/noctigon-kr4/2ch/hwdef.h b/hw/hank/noctigon-kr4/2ch/hwdef.h index b23c7ccd..28a686d6 100644 --- a/hw/hank/noctigon-kr4/2ch/hwdef.h +++ b/hw/hank/noctigon-kr4/2ch/hwdef.h @@ -30,8 +30,6 @@ * ADC12 thermal sensor */ -#include - // move the switch to a different pin #define SWITCH_PIN PB2 // pin 17 #define SWITCH_PCINT PCINT10 // pin 17 pin change interrupt @@ -39,7 +37,7 @@ #define SWITCH_PCMSK PCMSK1 // PCMSK1 is for PCINT[11:8] #define SWITCH_PORT PINB // PINA or PINB or PINC #define SWITCH_PUE PUEB // pullup group B -#define PCINT_vect PCINT1_vect // ISR for PCINT[11:8] +#define SWITCH_VECT PCINT1_vect // ISR for PCINT[11:8] // the rest of the config is the same as the generic Emisar 2ch build #include "hank/emisar-2ch/hwdef.h" diff --git a/hw/hank/noctigon-kr4/boost/hwdef.h b/hw/hank/noctigon-kr4/boost/hwdef.h index f17d2636..b923b307 100644 --- a/hw/hank/noctigon-kr4/boost/hwdef.h +++ b/hw/hank/noctigon-kr4/boost/hwdef.h @@ -46,12 +46,12 @@ #undef SWITCH_PCMSK #undef SWITCH_PORT #undef SWITCH_PUE -#undef PCINT_vect +#undef SWITCH_VECT #define SWITCH_PIN PB2 // pin 17 #define SWITCH_PCINT PCINT10 // pin 17 pin change interrupt #define SWITCH_PCIE PCIE1 // PCIE1 is for PCINT[11:8] #define SWITCH_PCMSK PCMSK1 // PCMSK1 is for PCINT[11:8] #define SWITCH_PORT PINB // PINA or PINB or PINC #define SWITCH_PUE PUEB // pullup group B -#define PCINT_vect PCINT1_vect // ISR for PCINT[11:8] +#define SWITCH_VECT PCINT1_vect // ISR for PCINT[11:8] diff --git a/hw/hank/noctigon-kr4/hwdef.h b/hw/hank/noctigon-kr4/hwdef.h index 586f8489..be165bd2 100644 --- a/hw/hank/noctigon-kr4/hwdef.h +++ b/hw/hank/noctigon-kr4/hwdef.h @@ -35,10 +35,8 @@ * Some models also have a direct-drive FET for turbo. */ -#include - -#ifndef HWDEF_C_FILE -#define HWDEF_C_FILE hank/noctigon-kr4/hwdef.c +#ifndef HWDEF_C +#define HWDEF_C hank/noctigon-kr4/hwdef.c #endif // allow using aux LEDs as extra channel modes @@ -93,7 +91,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK1 // PCMSK1 is for PCINT[11:8] #define SWITCH_PORT PINB // PINA or PINB or PINC #define SWITCH_PUE PUEB // pullup group B -#define PCINT_vect PCINT1_vect // ISR for PCINT[11:8] +#define SWITCH_VECT PCINT1_vect // ISR for PCINT[11:8] // the button tends to short out the voltage divider, // so ignore voltage while the button is being held diff --git a/hw/hank/noctigon-kr4/nofet/anduril.h b/hw/hank/noctigon-kr4/nofet/anduril.h index 4522cded..ad3f0125 100644 --- a/hw/hank/noctigon-kr4/nofet/anduril.h +++ b/hw/hank/noctigon-kr4/nofet/anduril.h @@ -5,7 +5,7 @@ // (and Noctigon KR1) // (and Emisar D4v2 E21A, a.k.a. "D4v2.5") -#define HWDEF_C_FILE hank/noctigon-kr4/nofet/hwdef.c +#define HWDEF_C hank/noctigon-kr4/nofet/hwdef.c #include "hank/noctigon-kr4/anduril.h" // brightness w/ SST-20 4000K LEDs: diff --git a/hw/hank/noctigon-m44/hwdef.h b/hw/hank/noctigon-m44/hwdef.h index af942d9b..6bdcef2e 100644 --- a/hw/hank/noctigon-m44/hwdef.h +++ b/hw/hank/noctigon-m44/hwdef.h @@ -28,9 +28,7 @@ * ADC12 thermal sensor */ -#include - -#define HWDEF_C_FILE hank/noctigon-m44/hwdef.c +#define HWDEF_C hank/noctigon-m44/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -110,7 +108,7 @@ uint8_t ch2_pwm, ch2_dsm; #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened #define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6 diff --git a/hw/lumintop/blf-gt/hwdef.h b/hw/lumintop/blf-gt/hwdef.h index bf3790d6..dbaf18e3 100644 --- a/hw/lumintop/blf-gt/hwdef.h +++ b/hw/lumintop/blf-gt/hwdef.h @@ -16,9 +16,7 @@ * and its output gets PWM'd by pin 5. */ -#include - -#define HWDEF_C_FILE hank/emisar-d4/hwdef.c +#define HWDEF_C hank/emisar-d4/hwdef.c // channel modes // * 0. main LEDs diff --git a/hw/lumintop/fw3a/hwdef.h b/hw/lumintop/fw3a/hwdef.h index 649dc19c..7809fa9d 100644 --- a/hw/lumintop/fw3a/hwdef.h +++ b/hw/lumintop/fw3a/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE lumintop/fw3a/hwdef.c +#define HWDEF_C lumintop/fw3a/hwdef.c // channel modes // * 0. FET+7+1 stacked diff --git a/hw/lumintop/fw3x-lume1/hwdef.h b/hw/lumintop/fw3x-lume1/hwdef.h index 943921fa..ca412cc9 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.h +++ b/hw/lumintop/fw3x-lume1/hwdef.h @@ -34,9 +34,7 @@ * Another pin is used for DD FET control. */ -#include - -#define HWDEF_C_FILE lumintop/fw3x-lume1/hwdef.c +#define HWDEF_C lumintop/fw3x-lume1/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -95,7 +93,7 @@ enum CHANNEL_MODES { #define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0] #define SWITCH_PORT PINA // PINA or PINB or PINC #define SWITCH_PUE PUEA // pullup group A -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] +#define SWITCH_VECT PCINT0_vect // ISR for PCINT[7:0] #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened #define VOLTAGE_PIN PB0 // Pin 19 PB0 ADC5 diff --git a/hw/mateminco/mf01-mini/hwdef.h b/hw/mateminco/mf01-mini/hwdef.h index f2450428..82dafb20 100644 --- a/hw/mateminco/mf01-mini/hwdef.h +++ b/hw/mateminco/mf01-mini/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE lumintop/fw3a/hwdef.c +#define HWDEF_C lumintop/fw3a/hwdef.c // channel modes // * 0. FET+N+1 stacked diff --git a/hw/mateminco/mf01s/hwdef.h b/hw/mateminco/mf01s/hwdef.h index 12451d79..fef50505 100644 --- a/hw/mateminco/mf01s/hwdef.h +++ b/hw/mateminco/mf01s/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE hank/emisar-d4/hwdef.c +#define HWDEF_C hank/emisar-d4/hwdef.c // channel modes // * 0. small FET + big FET stacked diff --git a/hw/mateminco/mt35-mini/hwdef.h b/hw/mateminco/mt35-mini/hwdef.h index aec4eaf6..ac7bf073 100644 --- a/hw/mateminco/mt35-mini/hwdef.h +++ b/hw/mateminco/mt35-mini/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE hank/emisar-d4/hwdef.c +#define HWDEF_C hank/emisar-d4/hwdef.c // channel modes // * 0. FET+7135 stacked diff --git a/hw/sofirn/blf-lt1-t1616/hwdef.h b/hw/sofirn/blf-lt1-t1616/hwdef.h index 66575def..c9ae1ea8 100644 --- a/hw/sofirn/blf-lt1-t1616/hwdef.h +++ b/hw/sofirn/blf-lt1-t1616/hwdef.h @@ -12,9 +12,7 @@ * Voltage: VCC */ -#include - -#define HWDEF_C_FILE sofirn/blf-lt1-t1616/hwdef.c +#define HWDEF_C sofirn/blf-lt1-t1616/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-aux.h" diff --git a/hw/sofirn/blf-lt1/hwdef.h b/hw/sofirn/blf-lt1/hwdef.h index 03f35684..a57b1c4a 100644 --- a/hw/sofirn/blf-lt1/hwdef.h +++ b/hw/sofirn/blf-lt1/hwdef.h @@ -12,9 +12,7 @@ * ---- */ -#include - -#define HWDEF_C_FILE sofirn/blf-lt1/hwdef.c +#define HWDEF_C sofirn/blf-lt1/hwdef.c // channel modes: // * 0. channel 1 only diff --git a/hw/sofirn/blf-q8-t1616/hwdef.h b/hw/sofirn/blf-q8-t1616/hwdef.h index 29c2ffaa..638a2c15 100644 --- a/hw/sofirn/blf-q8-t1616/hwdef.h +++ b/hw/sofirn/blf-q8-t1616/hwdef.h @@ -15,11 +15,9 @@ * Voltage: VCC */ -#include - // nearly all t1616-based FET+1 drivers work pretty much the same // (this one has single-color aux like the TS10) -#define HWDEF_C_FILE wurkkos/ts10/hwdef.c +#define HWDEF_C wurkkos/ts10/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-aux.h" diff --git a/hw/sofirn/lt1s-pro/hwdef.h b/hw/sofirn/lt1s-pro/hwdef.h index cd4dd4e1..7708631f 100644 --- a/hw/sofirn/lt1s-pro/hwdef.h +++ b/hw/sofirn/lt1s-pro/hwdef.h @@ -13,9 +13,7 @@ * Voltage: VCC */ -#include - -#define HWDEF_C_FILE sofirn/lt1s-pro/hwdef.c +#define HWDEF_C sofirn/lt1s-pro/hwdef.c // channel modes: // * 0. warm/cool white blend diff --git a/hw/sofirn/sp10-pro/hwdef.h b/hw/sofirn/sp10-pro/hwdef.h index a52166d7..cb1271de 100644 --- a/hw/sofirn/sp10-pro/hwdef.h +++ b/hw/sofirn/sp10-pro/hwdef.h @@ -12,9 +12,7 @@ * PA1 : Boost Enable */ -#include - -#define HWDEF_C_FILE sofirn/sp10-pro/hwdef.c +#define HWDEF_C sofirn/sp10-pro/hwdef.c // channel modes: // * 0. low+high PWM stacked @@ -61,8 +59,6 @@ enum CHANNEL_MODES { #define SWITCH_ISC_REG PORTB.PIN3CTRL #define SWITCH_VECT PORTB_PORT_vect #define SWITCH_INTFLG VPORTB.INTFLAGS -#define SWITCH_PCINT PCINT0 -#define PCINT_vect PCINT0_vect // ISR for PCINT[7:0] // Voltage divider battLVL #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is regulated 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 cd883fa7..90fede32 100644 --- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h +++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h @@ -36,9 +36,7 @@ * IN- NFET : pull up after BST enable to eliminate startup flash, pull down otherwise */ -#include - -#define HWDEF_C_FILE thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c +#define HWDEF_C thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -99,8 +97,6 @@ enum CHANNEL_MODES { #define SWITCH_ISC_REG PORTC.PIN3CTRL #define SWITCH_VECT PORTC_PORT_vect #define SWITCH_INTFLG VPORTC.INTFLAGS -#define SWITCH_PCINT PCINT0 -#define PCINT_vect PCINT0_vect #endif // Voltage divider battLVL diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h index 3f64287b..72aa7b04 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h @@ -37,9 +37,7 @@ * IN- NFET : pull up after BST enable to eliminate startup flash, pull down otherwise */ -#include - -#define HWDEF_C_FILE thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c +#define HWDEF_C thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -100,8 +98,6 @@ enum CHANNEL_MODES { #define SWITCH_ISC_REG PORTC.PIN2CTRL #define SWITCH_VECT PORTC_PORT_vect #define SWITCH_INTFLG VPORTC.INTFLAGS -#define SWITCH_PCINT PCINT0 -#define PCINT_vect PCINT0_vect #endif // average drop across diode on this hardware diff --git a/hw/thefreeman/lin16dac/hwdef.h b/hw/thefreeman/lin16dac/hwdef.h index 2066d043..dc4377a6 100644 --- a/hw/thefreeman/lin16dac/hwdef.h +++ b/hw/thefreeman/lin16dac/hwdef.h @@ -12,9 +12,7 @@ * Read voltage from VCC pin, has PFET so no drop */ -#include - -#define HWDEF_C_FILE thefreeman/lin16dac/hwdef.c +#define HWDEF_C thefreeman/lin16dac/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-aux.h" diff --git a/hw/wurkkos/ts10/hwdef.h b/hw/wurkkos/ts10/hwdef.h index b1239b8e..92898fb3 100644 --- a/hw/wurkkos/ts10/hwdef.h +++ b/hw/wurkkos/ts10/hwdef.h @@ -13,9 +13,7 @@ * Voltage: VCC */ -#include - -#define HWDEF_C_FILE wurkkos/ts10/hwdef.c +#define HWDEF_C wurkkos/ts10/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-aux.h" @@ -60,12 +58,10 @@ enum CHANNEL_MODES { // e-switch #define SWITCH_PIN PIN5_bp -//#define SWITCH_PCINT PCINT0 #define SWITCH_PORT VPORTA.IN #define SWITCH_ISC_REG PORTA.PIN2CTRL #define SWITCH_VECT PORTA_PORT_vect #define SWITCH_INTFLG VPORTA.INTFLAGS -//#define PCINT_vect PCINT0_vect // average drop across diode on this hardware #ifndef VOLTAGE_FUDGE_FACTOR diff --git a/hw/wurkkos/ts25/hwdef.h b/hw/wurkkos/ts25/hwdef.h index 024a18d9..ac1e5740 100644 --- a/hw/wurkkos/ts25/hwdef.h +++ b/hw/wurkkos/ts25/hwdef.h @@ -14,9 +14,7 @@ * Aux Blue: PC1 */ -#include - -#define HWDEF_C_FILE wurkkos/ts25/hwdef.c +#define HWDEF_C wurkkos/ts25/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -61,12 +59,10 @@ enum CHANNEL_MODES { // e-switch #define SWITCH_PIN PIN5_bp -//#define SWITCH_PCINT PCINT0 #define SWITCH_PORT VPORTA.IN #define SWITCH_ISC_REG PORTA.PIN2CTRL #define SWITCH_VECT PORTA_PORT_vect #define SWITCH_INTFLG VPORTA.INTFLAGS -//#define PCINT_vect PCINT0_vect // average drop across diode on this hardware #ifndef VOLTAGE_FUDGE_FACTOR diff --git a/ui/anduril/anduril.c b/ui/anduril/anduril.c index e72c3b51..c4345183 100644 --- a/ui/anduril/anduril.c +++ b/ui/anduril/anduril.c @@ -34,16 +34,19 @@ * as possible. These are mostly "USE" flags. */ +/********* load up MCU info, like ROM size and such *********/ +#include "arch/mcu.h" + /********* User-configurable options *********/ #include "anduril/config-default.h" /********* specific settings for known driver types *********/ -// Anduril config file name (set it here or define it at the gcc command line) -//#define CFG_H cfg-blf-q8.h -#include "fsm/tk.h" #include incfile(CFG_H) +#ifdef HWDEF_H +#include incfile(HWDEF_H) +#endif /********* Include headers which need to be before FSM *********/ @@ -77,11 +80,12 @@ #include "fsm/spaghetti-monster.h" /********* does this build target have special code to include? *********/ -#ifdef HWDEF_C_FILE -#include incfile(HWDEF_C_FILE) +#ifdef CFG_C +#include incfile(CFG_C) #endif -#ifdef CFG_C_FILE -#include incfile(CFG_C_FILE) + +#ifdef HWDEF_C +#include incfile(HWDEF_C) #endif diff --git a/ui/anduril/config-default.h b/ui/anduril/config-default.h index 899bc4ad..04fc9565 100644 --- a/ui/anduril/config-default.h +++ b/ui/anduril/config-default.h @@ -20,7 +20,7 @@ // overheat protection #define USE_THERMAL_REGULATION -#if (ATTINY==85) || (ATTINY==1634) +#if (MCU==0x85) || (MCU==0x1634) // sloppy temperature sensor needs bigger error margin #define DEFAULT_THERM_CEIL 45 // try not to get hotter than this (in C) #else @@ -185,7 +185,7 @@ // if the aux LEDs oscillate between "full battery" and "empty battery" // while in "voltage" mode, enable this to reduce the amplitude of // those oscillations -#if (ATTINY==1616) || (ATTINY==1634) +#if (ROM_SIZE > 10000) #define USE_LOWPASS_WHILE_ASLEEP #endif @@ -195,7 +195,7 @@ // Use "smooth steps" to soften on/off and step changes // on MCUs with enough room for extra stuff like this -#if (ATTINY==1616) || (ATTINY==1634) +#if (ROM_SIZE > 10000) #define USE_SMOOTH_STEPS #endif // 0 = none, 1 = smooth, 2+ = undefined From a4d96f08a017ce9d475b2575c597e741c6e8af1e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:42:33 -0700 Subject: [PATCH 05/57] version check: allow hex digits --- ui/anduril/version-check-mode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/anduril/version-check-mode.c b/ui/anduril/version-check-mode.c index eebe59b6..1cd69688 100644 --- a/ui/anduril/version-check-mode.c +++ b/ui/anduril/version-check-mode.c @@ -15,7 +15,10 @@ uint8_t version_check_state(Event event, uint16_t arg) { inline void version_check_iter() { for (uint8_t i=0; i ? + if (digit < 16) blink_digit(digit); else { // "buzz" for non-numeric characters for(uint8_t frame=0; frame<25; frame++) { set_level((frame&1) << 5); From 95d931dc167ae01d6af1973ea68496584fe03541 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:44:35 -0700 Subject: [PATCH 06/57] ramp-mode: allow hwdef to adjust gradual tick speed The gradual tick frequency was written for 8-bit PWM, but it can be too slow on hardware with more bits. The hwdef can compensate by using larger steps, but that makes adjustments more visible... So this provides an option to increase speed without visibility. --- ui/anduril/config-default.h | 6 ++++++ ui/anduril/ramp-mode.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ui/anduril/config-default.h b/ui/anduril/config-default.h index 04fc9565..cd25b528 100644 --- a/ui/anduril/config-default.h +++ b/ui/anduril/config-default.h @@ -113,6 +113,12 @@ // timer is available in regular ramp mode and candle mode #define USE_SUNSET_TIMER +// optionally make gradual ticks happen faster +// Affects: thermal regulation speed, sunset mode, maybe other features +// (default is calibrated for 8-bit PWM, +// but 10-bit should set this value to 4 instead of 1) +#define GRADUAL_ADJUST_SPEED 1 + ///// What to do when power is connected ///// // factory reset function erases user's runtime configuration in eeprom diff --git a/ui/anduril/ramp-mode.c b/ui/anduril/ramp-mode.c index 9e19025c..4c535b4c 100644 --- a/ui/anduril/ramp-mode.c +++ b/ui/anduril/ramp-mode.c @@ -287,7 +287,7 @@ uint8_t steady_state(Event event, uint16_t arg) { static uint16_t ticks_since_adjust = 0; ticks_since_adjust++; if (diff) { - uint16_t ticks_per_adjust = 256; + uint16_t ticks_per_adjust = 256 / GRADUAL_ADJUST_SPEED; if (diff < 0) { //diff = -diff; if (actual_level > THERM_FASTER_LEVEL) { From ed5e1dde6181ce71da96d7e920950830c0b869cb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:45:13 -0700 Subject: [PATCH 07/57] missed a "include -> HWDEF_H" conversion earlier --- hw/wurkkos/ts25/anduril.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/wurkkos/ts25/anduril.h b/hw/wurkkos/ts25/anduril.h index 722bc5d3..ecf0db19 100644 --- a/hw/wurkkos/ts25/anduril.h +++ b/hw/wurkkos/ts25/anduril.h @@ -3,7 +3,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later #pragma once -#include "wurkkos/ts25/hwdef.h" +//#include "wurkkos/ts25/hwdef.h" +#define HWDEF_H wurkkos/ts25/hwdef.h #include "wurkkos/anduril.h" // this light has three aux LED channels: R, G, B From 66b15ad887c2ae74bc7019c006549ac451557a6d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:46:34 -0700 Subject: [PATCH 08/57] temporary fix for aux LEDs on avrdd; needs proper refactoring --- fsm/misc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fsm/misc.c b/fsm/misc.c index 5d58f52c..fa8ddd73 100644 --- a/fsm/misc.c +++ b/fsm/misc.c @@ -118,7 +118,8 @@ uint8_t blink_num(uint8_t num) { #ifdef USE_INDICATOR_LED void indicator_led(uint8_t lvl) { switch (lvl) { - #ifdef AVRXMEGA3 // ATTINY816, 817, etc + // FIXME: move this logic to arch/* + #if (MCU==0x1616) || (MCU==0x32dd20) // ATTINY816, 817, etc case 0: // indicator off AUXLED_PORT.DIRSET = (1 << AUXLED_PIN); // set as output @@ -192,7 +193,8 @@ void indicator_led_auto() { void button_led_set(uint8_t lvl) { switch (lvl) { - #ifdef AVRXMEGA3 // ATTINY816, 817, etc + // FIXME: move this logic to arch/* + #if (MCU==0x1616) || (MCU==0x32dd20) // ATTINY816, 817, etc case 0: // LED off BUTTON_LED_PORT.DIRSET = (1 << BUTTON_LED_PIN); // set as output @@ -240,7 +242,8 @@ void rgb_led_set(uint8_t value) { uint8_t pin = pins[i]; switch (lvl) { - #ifdef AVRXMEGA3 // ATTINY816, 817, etc + // FIXME: move this logic to arch/* + #if (MCU==0x1616) || (MCU==0x32dd20) // ATTINY816, 817, etc case 0: // LED off AUXLED_RGB_PORT.DIRSET = (1 << pin); // set as output From e6909adcb1d44797e097dcf93ee7459276a4516a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:47:40 -0700 Subject: [PATCH 09/57] moved prevent_reboot_loop() and some other junk out of fsm/main.c --- arch/attiny1616.c | 6 ++++++ arch/attiny1616.h | 2 ++ arch/attiny1634.c | 6 ++++++ arch/attiny1634.h | 2 ++ arch/attiny85.c | 21 ++++++++++++++++++++ arch/attiny85.h | 2 ++ fsm/main.c | 50 +++-------------------------------------------- 7 files changed, 42 insertions(+), 47 deletions(-) diff --git a/arch/attiny1616.c b/arch/attiny1616.c index 3b170bbd..a3ead7e2 100644 --- a/arch/attiny1616.c +++ b/arch/attiny1616.c @@ -145,3 +145,9 @@ void reboot() { while (1) {} } +inline void prevent_reboot_loop() { + // prevent WDT from rebooting MCU again + RSTCTRL.RSTFR &= ~(RSTCTRL_WDRF_bm); // reset status flag + wdt_disable(); +} + diff --git a/arch/attiny1616.h b/arch/attiny1616.h index 59897854..b4e17fca 100644 --- a/arch/attiny1616.h +++ b/arch/attiny1616.h @@ -94,3 +94,5 @@ inline void mcu_pcint_off(); void reboot(); +inline void prevent_reboot_loop(); + diff --git a/arch/attiny1634.c b/arch/attiny1634.c index d4b37676..0737a810 100644 --- a/arch/attiny1634.c +++ b/arch/attiny1634.c @@ -123,3 +123,9 @@ void reboot() { while (1) {} } +inline void prevent_reboot_loop() { + // prevent WDT from rebooting MCU again + MCUSR &= ~(1<= 1 - PWM1_LVL = 0; - #endif - #if PWM_CHANNELS >= 2 - PWM2_LVL = 0; - #endif - #if PWM_CHANNELS >= 3 - PWM3_LVL = 0; - #endif - #if PWM_CHANNELS >= 4 - PWM4_LVL = 255; // inverted :( - #endif - #endif standby_mode(); } From 79c1d9ebfed691b1048205ebdfd91d33cfcfc8a1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:48:50 -0700 Subject: [PATCH 10/57] thefreeman/boost*: define Vref values more explicitly without magic numbers --- .../boost-fwaa-mp3432-hdr-dac-rgb/anduril.h | 8 ++++---- hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h | 12 +++++++----- hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h | 8 ++++---- hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h | 12 +++++++----- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h index eea8887d..33583df5 100644 --- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h +++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h @@ -24,10 +24,10 @@ 14, 15, 17, 18, 19, 20, 22, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81, 86, 90, 95, 99,104,109,114,120,126,131,138,144,150,157,164,171,179,187,195,203,212,221,230,239,249, \ 57, 59, 61, 64, 66, 69, 72, 74, 77, 80, 83, 86, 90, 93, 96,100,103,107,111,115,119,123,127,132,136,141,145,150,155,160,166,171,176,182,188,194,200,206,213,219,226,233,240,247,255 // PWM Tops: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) -#define PWM_TOPS 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, \ - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 +#define PWM_TOPS V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 #define MAX_1x7135 50 #define DEFAULT_LEVEL 44 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 90fede32..095aea04 100644 --- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h +++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h @@ -69,11 +69,13 @@ enum CHANNEL_MODES { #define DAC_VREF VREF.CTRLA // 0.55V or 2.5V #define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) // Vref values -#define V055 16 -#define V11 17 -#define V25 18 -#define V43 19 -#define V15 20 +// (1.1V ADC + variable DAC) +#define V05 V055 +#define V055 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_0V55_gc) +#define V11 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V1_gc) +#define V25 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_2V5_gc) +#define V43 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_4V34_gc) +#define V15 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V5_gc) // BST enable #define BST_ENABLE_PIN PIN4_bp diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h index 64da638f..a6a111c6 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h @@ -24,10 +24,10 @@ 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 40, 42, 45, 47, 50, 53, 56, 59, 62, 66, 69, 73, 77, 81, 85, 90, 94, 99,104,109,114,120,126,132,138,144,151,158,165,173,180,188,196,205,214,223,232,242,252, \ 57, 60, 62, 65, 67, 70, 73, 76, 78, 82, 85, 88, 91, 95, 98,102,105,109,113,117,121,126,130,135,139,144,149,154,159,164,170,175,181,187,193,199,206,212,219,225,232,240,247,255 // PWM Tops: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) -#define PWM_TOPS 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, \ - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 +#define PWM_TOPS V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 #define MAX_1x7135 44 #define DEFAULT_LEVEL 44 diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h index 72aa7b04..d030516a 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h @@ -70,11 +70,13 @@ enum CHANNEL_MODES { #define DAC_VREF VREF.CTRLA // 0.55V or 2.5V #define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) // Vref values -#define V055 16 -#define V11 17 -#define V25 18 -#define V43 19 -#define V15 20 +// (1.1V ADC + variable DAC) +#define V05 V055 +#define V055 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_0V55_gc) +#define V11 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V1_gc) +#define V25 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_2V5_gc) +#define V43 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_4V34_gc) +#define V15 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V5_gc) // BST enable #define BST_ENABLE_PIN PIN0_bp From 486dd5543653b342fe64c0e5b1fcd342f0a02dbb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:53:59 -0700 Subject: [PATCH 11/57] added *unfinished* support for avr32dd20, plus a build target for a dev kit ADC doesn't work yet. No voltage, no temperature. I need to do a lot of refactoring on the ADC code. :( --- arch/avr32dd20.c | 263 +++++++++++++++++++++++ arch/avr32dd20.h | 93 ++++++++ bin/flash-avr32dd20.sh | 13 ++ hw/thefreeman/avr32dd20-devkit/anduril.h | 138 ++++++++++++ hw/thefreeman/avr32dd20-devkit/arch | 1 + hw/thefreeman/avr32dd20-devkit/hwdef.c | 105 +++++++++ hw/thefreeman/avr32dd20-devkit/hwdef.h | 208 ++++++++++++++++++ hw/thefreeman/avr32dd20-devkit/model | 1 + 8 files changed, 822 insertions(+) create mode 100644 arch/avr32dd20.c create mode 100644 arch/avr32dd20.h create mode 100755 bin/flash-avr32dd20.sh create mode 100644 hw/thefreeman/avr32dd20-devkit/anduril.h create mode 100644 hw/thefreeman/avr32dd20-devkit/arch create mode 100644 hw/thefreeman/avr32dd20-devkit/hwdef.c create mode 100644 hw/thefreeman/avr32dd20-devkit/hwdef.h create mode 100644 hw/thefreeman/avr32dd20-devkit/model diff --git a/arch/avr32dd20.c b/arch/avr32dd20.c new file mode 100644 index 00000000..45923a8f --- /dev/null +++ b/arch/avr32dd20.c @@ -0,0 +1,263 @@ +// arch/avr32dd20.h: avr32dd20 support header +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +////////// clock speed / delay stuff ////////// + +inline void mcu_clock_speed() { + // TODO: allow hwdef to define a base clock speed + // run the internal clock at 12 MHz, not the default 4 MHz + _PROTECTED_WRITE( CLKCTRL.OSCHFCTRLA, + CLKCTRL_FRQSEL_12M_gc | CLKCTRL_AUTOTUNE_bm ); + // (another option is to use 20 MHz / 2, like attiny1616 does) + // divide 20 MHz to run at 10 MHz to match attiny1616 + //_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(); + _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, n); // Set the prescaler + while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {} // wait for clock change to finish + sei(); +} + + +////////// ADC voltage / temperature ////////// + +// ADC0.CTRLA bits: +// RUNSTDBY, -, CONVMODE, LEFTADJ, RESSEL[1:0], FREERUN, ENABLE +// CTRLB bits: -, -, -, -, -, SAMPNUM[2:0] +// CTRLC bits: -, -, -, -, PRESC[3:0] +// CTRLD bits: INITDLY[2:0], -, SAMPDLY[3:0] +// CTRLE bits: -, -, -, -, -, WINCM[2:0] +// SAMPCTRL: 8 bits +// MUXPOS, MUXNEG: 7 bits each +// COMMAND: -, -, -, -, -, -, SPCONV, STCONV + +inline void mcu_set_admux_therm() { + // ADC init: Datasheet section 33.3.2 + // Temperature mode: Datasheet section 33.3.3.8 + // measurements should be 12-bit right-adjusted single-ended conversion + // set Vref to 2.048V for temperature mode + VREF.ADC0REF = VREF_REFSEL_2V048_gc; + // set temp sensor as input + ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc; + // configure init delay to >= 25 us * Fclk_adc (no sample delay needed) + ADC0.CTRLD = ADC_INITDLY_DLY32_gc | ADC_SAMPDLY_DLY0_gc; + // configure ADC sample length to >= 28 us * Fclk_adc + ADC0.SAMPCTRL = 32; + // set single-ended or differential + // set resolution to 12 bits + // set left- or right-adjust (right) + // set free-running mode or not (yes) + ADC0.CTRLA = ADC_CONVMODE_SINGLEENDED_gc + | ADC_RESSEL_12BIT_gc + //| ADC_LEFTADJ_bm // not in temperature mode + | ADC_FREERUN_bm; + // set number of samples (requires adjustment in formula too) + ADC0.CTRLB = ADC_SAMPNUM_NONE_gc; + // TODO: accumulate more samples for more resolution + // (and probably set the prescale faster too) + //ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; // 16 samples per result + // set a clock prescaler + ADC0.CTRLC = ADC_PRESC_DIV64_gc; + // enable the ADC + ADC0.CTRLA |= ADC_ENABLE_bm; + // actually start measuring (happens in another function) + //ADC0.COMMAND |= ADC_STCONV_bm; + // for each measurement: + // process according to sigrow data + formula +} + +inline void mcu_set_admux_voltage() { + // ADC init: Datasheet section 33.3.2 + // set Vref + VREF.ADC0REF = VREF_REFSEL_1V024_gc; + // set single-ended or differential + // set resolution to 12 bits + // set left- or right-adjust (right) + // set free-running mode or not (yes) + ADC0.CTRLA = ADC_CONVMODE_SINGLEENDED_gc + | ADC_RESSEL_12BIT_gc + | ADC_LEFTADJ_bm // has no effect when 16+ samples taken + | ADC_FREERUN_bm + | ADC_RUNSTBY_bm // allow voltage sense in standby mode + ; + // set number of samples + ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; // 16 samples per result + // set a clock prescaler + ADC0.CTRLC = ADC_PRESC_DIV16_gc; // not too fast, not too slow + // select the positive ADC input with MUXPOS + #ifdef USE_VOLTAGE_DIVIDER // external voltage divider + // ADC input pin / Vref + ADC0.MUXPOS = ADMUX_VOLTAGE_DIVIDER; // external pin + #elif defined (USE_VOLTAGE_VDDIO2) // internal voltage divider + // (Vbat / 10) / Vref + ADC0.MUXPOS = ADC_MUXPOS_VDDIO2DIV10_gc; + #else // measure directly on VDD/VCC pin + // (Vbat / 10) / Vref + ADC0.MUXPOS = ADC_MUXPOS_VDDDIV10_gc; + #endif + // enable the ADC + ADC0.CTRLA |= ADC_ENABLE_bm; + // actually start measuring (happens in another function) + //ADC0.COMMAND |= ADC_STCONV_bm; +} + +inline void mcu_adc_sleep_mode() { + set_sleep_mode(SLEEP_MODE_STANDBY); +} + +inline void mcu_adc_start_measurement() { + // FIXME: enable this after getting ADC stuff fixed + #if 0 + ADC0.INTCTRL |= ADC_RESRDY_bm; // enable interrupt + ADC0.COMMAND |= ADC_STCONV_bm; // actually start measuring + #endif +} + +/* +void mcu_adc_on() { + hwdef_set_admux_voltage(); + mcu_adc_start_measurement(); +} +*/ + +inline void mcu_adc_off() { + ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC +} + +inline void mcu_adc_vect_clear() { + ADC0.INTFLAGS = ADC_RESRDY_bm; // clear the interrupt +} + +inline uint16_t mcu_adc_result_temp() { + // FIXME: better math, higher precision + // 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 +} + +inline uint16_t mcu_adc_result_volts() { + // voltage is 12-bit right-aligned + 16x oversampling = 16 bits total + return ADC0.RES; +} + +inline uint8_t mcu_adc_lsb() { + // temp is right-aligned, voltage is 16-bit, both have a useful LSB + 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, +// as recommended on AVR 0/1-series and later: +// https://github.com/SpenceKonde/DxCore/blob/master/megaavr/extras/PowerSave.md#using-the-real-time-counter-rtcpit +// The PIT runs even in power-down mode, unlike RTC, +// and its cycles are relative to the AVR's internal 32768 Hz ULP oscillator +// AVR datasheet sections 26, 26.5, 26.9, 26.12, 26.13.12 + +// PIT tick speeds: +// 0 (none) +// 1 8192 Hz (CYC4) +// 2 4096 Hz +// 3 2048 Hz +// 4 1024 Hz (CYC32) +// 5 512 Hz +// 6 256 Hz +// 7 128 Hz +// 8 64 Hz (default) (CYC512) +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 + // Period = 16ms (64 Hz), enable the PI Timer + RTC.PITCTRLA = RTC_PERIOD_CYC512_gc | RTC_PITEN_bm; +} + +// STANDBY_TICK_SPEED: +// 0 64 Hz +// 1 32 Hz +// 2 16 Hz +// 3 8 Hz (default) +// 4 4 Hz +// 5 2 Hz +// 6 1 Hz +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 + // Set period (64 Hz / STANDBY_TICK_SPEED = 8 Hz), enable the PI Timer + RTC.PITCTRLA = ((8+STANDBY_TICK_SPEED)<<3) | RTC_PITEN_bm; +} + +inline void mcu_wdt_stop() { + while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated + RTC.PITCTRLA = 0; // Disable the PI Timer +} + +inline void mcu_wdt_vect_clear() { + RTC.PITINTFLAGS = RTC_PI_bm; // clear the PIT interrupt flag +} + + +////////// PCINT - pin change interrupt (e-switch) ////////// + +inline void mcu_switch_vect_clear() { + // Write a '1' to clear the interrupt flag + SWITCH_INTFLG |= (1 << SWITCH_PIN); +} + +inline void mcu_pcint_on() { + SWITCH_ISC_REG |= PORT_ISC_BOTHEDGES_gc; +} + +inline void mcu_pcint_off() { + SWITCH_ISC_REG &= ~(PORT_ISC_gm); +} + + +////////// misc ////////// + +void reboot() { + // request a reboot (software reset) + _PROTECTED_WRITE(RSTCTRL.SWRR, RSTCTRL_SWRST_bm); +} + +inline void prevent_reboot_loop() { + // if previous reset was a crash (WDT time-out), + // prevent it from happening again immediately + //RSTCTRL.RSTFR &= ~(RSTCTRL_WDRF_bm); // reset wdt flag only + RSTCTRL.RSTFR = 0; // reset all reset status flags (maybe unneeded?) + wdt_disable(); // from avr/wdt.h +} + diff --git a/arch/avr32dd20.h b/arch/avr32dd20.h new file mode 100644 index 00000000..7a6b8f11 --- /dev/null +++ b/arch/avr32dd20.h @@ -0,0 +1,93 @@ +// arch/avr32dd20.h: avr32dd20 support header +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +////////// clock speed / delay stuff ////////// + +#define F_CPU 12000000UL +#define BOGOMIPS (F_CPU/3800) +#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); + +// TODO: allow hwdef to define a base clock speed, +// and adjust these values accordingly +typedef enum +{ + // Actual clock is 12 MHz + clock_div_1 = (0), // 12 MHz + clock_div_2 = (CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm), // 6 MHz + clock_div_4 = (CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm), // 3 MHz + clock_div_8 = (CLKCTRL_PDIV_8X_gc | CLKCTRL_PEN_bm), // 1.5 MHz + clock_div_16 = (CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm), // 0.75 MHz + clock_div_32 = (CLKCTRL_PDIV_32X_gc | CLKCTRL_PEN_bm), // 375 kHz + clock_div_64 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 187.5 kHz +} clock_div_t; + + +////////// ADC voltage / temperature ////////// + +#define hwdef_set_admux_therm mcu_set_admux_therm +inline void mcu_set_admux_therm(); + +#define hwdef_set_admux_voltage mcu_set_admux_voltage +inline void mcu_set_admux_voltage(); + +inline void mcu_adc_sleep_mode(); + +inline void mcu_adc_start_measurement(); + +//#define mcu_adc_on hwdef_set_admux_voltage +//void mcu_adc_on(); + +inline void mcu_adc_off(); + +#define ADC_vect ADC0_RESRDY_vect +inline void mcu_adc_vect_clear(); + +// 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(); + +inline uint8_t mcu_adc_lsb(); + + +////////// WDT ////////// + +inline void mcu_wdt_active(); + +inline void mcu_wdt_standby(); + +inline void mcu_wdt_stop(); + +#define WDT_vect RTC_PIT_vect +inline void mcu_wdt_vect_clear(); + + +////////// PCINT - pin change interrupt (e-switch) ////////// + +// set these in hwdef +//#define SWITCH_PORT VPORTD.IN +//#define SWITCH_VECT PORTD_PORT_vect + +inline void mcu_switch_vect_clear(); + +inline void mcu_pcint_on(); + +inline void mcu_pcint_off(); + + +////////// misc ////////// + +void reboot(); + +inline void prevent_reboot_loop(); + diff --git a/bin/flash-avr32dd20.sh b/bin/flash-avr32dd20.sh new file mode 100755 index 00000000..ef8b0f3c --- /dev/null +++ b/bin/flash-avr32dd20.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +[[ -z "$1" ]] && echo "No .hex file specified." && exit 1 +HEX="$1" + +#pymcuprog ping -t uart -u /dev/ttyUSB2 -d avr32dd20 +#pymcuprog erase -t uart -u /dev/ttyUSB2 -d avr32dd20 +#pymcuprog write verify -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" +#pymcuprog verify -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" + +pymcuprog write --erase --verify --timing -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" diff --git a/hw/thefreeman/avr32dd20-devkit/anduril.h b/hw/thefreeman/avr32dd20-devkit/anduril.h new file mode 100644 index 00000000..97e9e109 --- /dev/null +++ b/hw/thefreeman/avr32dd20-devkit/anduril.h @@ -0,0 +1,138 @@ +// thefreeman's BST21 BST20-FWxA (no button LED) +// Copyright (C) 2023 TBD (thefreeman), Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#define HWDEF_H thefreeman/avr32dd20-devkit/hwdef.h + +// HPRsense : 1.7+0.3+5 = 7mR (DMN22M5UFG+trace resistance+5mR) +// Vsense=42.46mV, R1= 191k +// LPRsense : 1R +// transition DAC level 8, ramp level 45 +// fifth power ramp 0.1mA to 6066mA + +#define RAMP_SIZE 150 + +// 4 ramp segments: +// - low 1.024V +// - low 2.5 V +// - high 1.024V +// - high 2.5 V +// HDR ratio: 160 +// PWM1: DAC Data +#if 1 +// level_calc.py 4.3287 1 150 7135 5 0.01 1400 --pwm 400000 +// top level for each "gear": 30 40 120 150 +#define PWM1_LEVELS \ + 6, 7, 9, 11, 14, 18, 23, 30, 37, 46, 56, 69, 83, 100, 120, 142, 168, 196, 229, 266, 307, 353, 403, 460, 522, 591, 667, 750, 840, 939, \ + 428, 476, 528, 584, 645, 710, 780, 856, 937,1023, \ + 17, 18, 20, 21, 23, 25, 27, 29, 32, 34, 37, 40, 42, 46, 49, 52, 56, 60, 64, 68, 72, 77, 81, 86, 92, 97, 103, 109, 115, 122, 128, 136, 143, 151, 159, 167, 176, 185, 194, 204, 214, 224, 235, 246, 258, 270, 283, 295, 309, 323, 337, 352, 367, 383, 399, 416, 434, 452, 470, 489, 509, 529, 550, 572, 594, 617, 640, 664, 689, 715, 741, 768, 796, 824, 854, 884, 915, 947, 979,1013, \ + 429, 443, 458, 473, 489, 505, 521, 538, 555, 572, 590, 609, 628, 647, 667, 687, 708, 729, 751, 773, 796, 819, 843, 867, 891, 917, 943, 969, 996,1023 +#define PWM2_LEVELS \ + V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ + V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, \ + V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ + V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25 +#define MAX_1x7135 40 +#define HDR_ENABLE_LEVEL_MIN 41 +#define DEFAULT_LEVEL 50 +#else +// level_calc.py 9.21 1 150 7135 5 0.2 1400 --pwm 400000 +// (plus dac-scale.py post-processing to get values for HDR+Vref ranges) +// top level for each "gear": 35 48 127 150 +#define PWM1_LEVELS \ + 5, 11, 18, 25, 33, 41, 50, 60, 71, 83, 96, 110, 125, 141, 158, 177, 198, 220, 244, 269, 297, 326, 358, 392, 429, 469, 511, 556, 605, 657, 713, 772, 836, 904, 976, \ + 431, 465, 501, 539, 580, 624, 670, 720, 772, 828, 887, 950,1017, \ + 16, 17, 18, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 64, 68, 72, 76, 80, 85, 90, 95, 100, 106, 112, 118, 124, 131, 138, 145, 153, 161, 170, 179, 188, 198, 208, 219, 230, 242, 254, 266, 280, 294, 308, 323, 339, 355, 373, 391, 409, 429, 449, 470, 492, 515, 539, 564, 589, 616, 644, 673, 704, 735, 768, 802, 837, 874, 912, 952, 993, \ + 424, 442, 461, 480, 501, 522, 544, 566, 590, 614, 640, 666, 693, 721, 750, 780, 811, 844, 877, 912, 948, 985,1023 +// Vref selector (V10, V20, V25, V40 = 1.024V, 2.048V, 2.5V, 4.096V) +#define PWM2_LEVELS \ + V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ + V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, \ + V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ + V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25 + +#define MAX_1x7135 48 +#define DEFAULT_LEVEL 48 +#define HDR_ENABLE_LEVEL_MIN 49 // when HDR FET turns ON +#endif + +// no PWM, so MCU clock speed can be slow +#define HALFSPEED_LEVEL 41 +#define QUARTERSPEED_LEVEL 40 // seems to run fine at 10kHz/4, try reducing more + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 130 // 50% / 3A / 1000 lm +// 1 22 [44] 65 87 108 130 +#define RAMP_DISCRETE_FLOOR 1 +#define RAMP_DISCRETE_CEIL 130 +#define RAMP_DISCRETE_STEPS 7 + +// 20 [45] 70 95 120 +#define SIMPLE_UI_FLOOR 20 +#define SIMPLE_UI_CEIL 120 // ~2.25A / ~750 lm +#define SIMPLE_UI_STEPS 5 + +// don't blink mid-ramp +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + +// thermal config + +// temperature limit +#define THERM_FASTER_LEVEL 130 // stop panicking at 50%/3A +#define MIN_THERM_STEPDOWN MAX_1x7135 + + +// UI + +//#define SIMPLE_UI_ACTIVE 0 // advanced UI by default + +// allow Aux Config and Strobe Modes in Simple UI +//#define USE_EXTENDED_SIMPLE_UI + +// Allow 3C in Simple UI for switching between smooth and stepped ramping +#define USE_SIMPLE_UI_RAMPING_TOGGLE + +#define DEFAULT_2C_STYLE 1 // enable 2 click turbo + + +// AUX + +//#define USE_BUTTON_LED + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS + +// show each channel while it scroll by in the menu +#define USE_CONFIG_COLORS + +// blink numbers on the main LEDs by default +#define DEFAULT_BLINK_CHANNEL CM_MAIN + +// use aux red + aux blue for police strobe +#define USE_POLICE_COLOR_STROBE_MODE +#define POLICE_STROBE_USES_AUX +#define POLICE_COLOR_STROBE_CH1 CM_AUXRED +#define POLICE_COLOR_STROBE_CH2 CM_AUXBLU + +// the aux LEDs are front-facing, so turn them off while main LEDs are on +#ifdef USE_INDICATOR_LED_WHILE_RAMPING +#undef USE_INDICATOR_LED_WHILE_RAMPING +#endif + + +// Misc + +#define PARTY_STROBE_ONTIME 1 // slow down party strobe +#define STROBE_OFF_LEVEL 1 // keep the regulator chip on between pulses + +// smoother candle mode with bigger oscillations +#define CANDLE_AMPLITUDE 40 + +// enable 13H factory reset so it can be used on tail e-switch lights +#define USE_SOFT_FACTORY_RESET + +// TODO: disable lowpass while asleep; the MCU oversamples + diff --git a/hw/thefreeman/avr32dd20-devkit/arch b/hw/thefreeman/avr32dd20-devkit/arch new file mode 100644 index 00000000..bcf4552b --- /dev/null +++ b/hw/thefreeman/avr32dd20-devkit/arch @@ -0,0 +1 @@ +avr32dd20 diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.c b/hw/thefreeman/avr32dd20-devkit/hwdef.c new file mode 100644 index 00000000..e5b347f5 --- /dev/null +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.c @@ -0,0 +1,105 @@ +// thefreeman boost driver 2.1 output helper functions +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "fsm/chan-rgbaux.c" + +void set_level_zero(); + +void set_level_main(uint8_t level); +bool gradual_tick_main(uint8_t gt); + + +Channel channels[] = { + { // main LEDs + .set_level = set_level_main, + .gradual_tick = gradual_tick_main + }, + RGB_AUX_CHANNELS +}; + + +void set_level_zero() { + DAC_LVL = 0; // DAC off + DAC_VREF = V10; // low Vref + HDR_ENABLE_PORT &= ~(1 << HDR_ENABLE_PIN); // HDR off + + // prevent post-off flash + IN_NFET_ENABLE_PORT |= (1 << IN_NFET_ENABLE_PIN); + delay_4ms(IN_NFET_DELAY_TIME/4); + IN_NFET_ENABLE_PORT &= ~(1 << IN_NFET_ENABLE_PIN); + + // turn off boost last + BST_ENABLE_PORT &= ~(1 << BST_ENABLE_PIN); // BST off +} + +// single set of LEDs with 1 regulated power channel +// and low/high HDR plus low/high Vref as different "gears" +void set_level_main(uint8_t level) { + uint8_t noflash = 0; + + // when turning on from off, use IN_NFET to prevent a flash + if ((! actual_level) && (level < HDR_ENABLE_LEVEL_MIN)) { + noflash = 1; + IN_NFET_ENABLE_PORT |= (1 << IN_NFET_ENABLE_PIN); + } + + // BST on first, to give it a few extra microseconds to spin up + BST_ENABLE_PORT |= (1 << BST_ENABLE_PIN); + + // pre-load ramp data so it can be assigned faster later + // DAC level register is left-aligned + PWM1_DATATYPE dac_lvl = PWM1_GET(level) << 6; + PWM2_DATATYPE dac_vref = PWM2_GET(level); + + // enable HDR on top half of ramp + if (level >= (HDR_ENABLE_LEVEL_MIN-1)) + HDR_ENABLE_PORT |= (1 << HDR_ENABLE_PIN); + else + HDR_ENABLE_PORT &= ~(1 << HDR_ENABLE_PIN); + + // set these in successive clock cycles to avoid getting out of sync + // (minimizes ramp bumps when changing gears) + DAC_LVL = dac_lvl; + DAC_VREF = dac_vref; + + if (noflash) { + // wait for flash prevention to finish + delay_4ms(IN_NFET_DELAY_TIME/4); + IN_NFET_ENABLE_PORT &= ~(1 << IN_NFET_ENABLE_PIN); + } +} + +bool gradual_tick_main(uint8_t gt) { + // if HDR and Vref "engine gear" is the same, do a small adjustment... + // otherwise, simply jump to the next ramp level + // and let set_level() handle any gear changes + + // different gear = full adjustment + PWM2_DATATYPE vref_next = PWM2_GET(gt); + if (vref_next != DAC_VREF) return true; // let parent set_level() for us + + // same gear = small adjustment + PWM1_DATATYPE dac_now = DAC_LVL >> 6; // register is left-aligned + PWM1_DATATYPE dac_next = PWM1_GET(gt); + + // adjust multiple times based on how far until the next level + // (so it adjusts faster/coarser for big steps) + + int16_t diff = (dac_next - dac_now); + if (diff < 0) diff = -diff; + + // ~70 max DAC levels per ramp step, 1 + (70 >> 3) = max 10 + uint8_t steps; + steps = 1 + (diff >> 3); + for (uint8_t i=0; i<=steps; i++) + GRADUAL_ADJUST_SIMPLE(dac_next, dac_now); + + DAC_LVL = dac_now << 6; + + if (dac_next == dac_now) return true; // done + + return false; // not done yet +} + diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h new file mode 100644 index 00000000..7e093f94 --- /dev/null +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h @@ -0,0 +1,208 @@ +// hwdef for thefreeman's avr32dd20 dev kit +// Copyright (C) 2023 thefreeman, Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +/* thefreeman’s avr32dd20 dev kit + * Boost driver based on MP3431(?) + * with high dynamic range and DAC control + aux RGB + * + * Pin Name Function + * 1 PA4 - + * 2 PA5 LVB (unused) + * 3 PA6 BATT LVL (voltage divider) + * 4 PA7 HDR: high/low Rsense range + * 5 PC1 - + * 6 PC2 - + * 7 PC3 - + * 8 VDDIO2 VCC2 (unused) + * 9 PD4 e-switch + * 10 PD5 EN: boost enable + * 11 PD6 DAC: control voltage out + * 12 PD7 IN- NFET: absorb startup flash + * 13 VDD VCC + * 14 GND GND + * 15 PF6 RESET + * 16 PF7 UPDI + * 17 PA0 R: aux red + * 18 PA1 G: aux green + * 19 PA2 B: aux blue + * 20 PA3 CH: detect charging + * + * BST EN enable the boost regulator and Op-Amp + * DAC sets the current, max current depends on Vset voltage divider and Rsense + * HDR FET switches between high value Rsense (low current range, pin low), + * and low value Rsense (high current range, pin high) + * IN- NFET : pull up after BST enable to eliminate startup flash, pull down otherwise + * CH senses the status of the onboard charger + * LVL : ??? (unused?) + * LVB is for OTSM firmware, not used here + */ + +#define HWDEF_C thefreeman/avr32dd20-devkit/hwdef.c + +// allow using aux LEDs as extra channel modes +#include "fsm/chan-rgbaux.h" + +// channel modes: +// * 0. main LEDs +// * 1+. aux RGB +#define NUM_CHANNEL_MODES (1 + NUM_RGB_AUX_CHANNEL_MODES) +enum CHANNEL_MODES { + CM_MAIN = 0, + RGB_AUX_ENUMS +}; + +#define DEFAULT_CHANNEL_MODE CM_MAIN + +// right-most bit first, modes are in fedcba9876543210 order +#define CHANNEL_MODES_ENABLED 0b0000000000000001 + + +#define PWM_CHANNELS 1 // old, remove this + +#undef GRADUAL_ADJUST_SPEED +#define GRADUAL_ADJUST_SPEED 4 + +#define PWM_BITS 16 // 10-bit DAC +#define PWM_DATATYPE uint16_t +#define PWM_DATATYPE2 uint32_t // only needs 32-bit if ramp values go over 255 +#define PWM1_DATATYPE uint16_t // main LED ramp +#define PWM1_GET(l) PWM_GET16(pwm1_levels, l) +#define PWM2_DATATYPE uint8_t // DAC Vref table +#define PWM2_GET(l) PWM_GET8(pwm2_levels, l) + +// main LED outputs +#define DAC_LVL DAC0_DATA // 0 to 255, for 0V to Vref +#define DAC_VREF VREF_DAC0REF // 1.024V, 2.048V, 4.096V, or 2.5V +//#define DAC_VREF VREF.ADC0REF // 1.024V, 2.048V, 4.096V, or 2.5V +#define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) +// Vref values +#define V10 VREF_REFSEL_1V024_gc +#define V20 VREF_REFSEL_2V048_gc +#define V25 VREF_REFSEL_2V500_gc +#define V40 VREF_REFSEL_4V096_gc + +// BST enable +#define BST_ENABLE_PIN PIN5_bp +#define BST_ENABLE_PORT PORTD_OUT + +// HDR +// turns on HDR FET for the high current range +#define HDR_ENABLE_PIN PIN7_bp +#define HDR_ENABLE_PORT PORTA_OUT + +// IN- NFET +// pull high to force output to zero to eliminate the startup flash +#define IN_NFET_DELAY_TIME 12 // (ms) +#define IN_NFET_ENABLE_PIN PIN7_bp +#define IN_NFET_ENABLE_PORT PORTD_OUT + +// e-switch +#ifndef SWITCH_PIN +#define SWITCH_PIN PIN4_bp +#define SWITCH_PORT VPORTD.IN +#define SWITCH_ISC_REG PORTD.PIN4CTRL +#define SWITCH_VECT PORTD_PORT_vect +#define SWITCH_INTFLG VPORTD.INTFLAGS +#endif + +// TODO: define stuff for the voltage divider +// 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 + +// average drop across diode on this hardware +#ifndef VOLTAGE_FUDGE_FACTOR +#define VOLTAGE_FUDGE_FACTOR 0 // using a PFET so no appreciable drop +#endif + +// this driver allows for aux LEDs under the optic +#define AUXLED_R_PIN PIN0_bp +#define AUXLED_G_PIN PIN1_bp +#define AUXLED_B_PIN PIN2_bp +#define AUXLED_RGB_PORT PORTA + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS + + +inline void hwdef_setup() { + + // TODO? for this DAC controlled-light, try to decrease the clock speed + mcu_clock_speed(); + + VPORTA.DIR = PIN0_bm // R + | PIN1_bm // G + | PIN2_bm // B + //| PIN3_bm // CH + | PIN7_bm; // HDR + VPORTD.DIR = PIN5_bm // EN + | PIN6_bm // DAC + | PIN7_bm; // IN- NFET + + // enable pullups on the unused and input pins to reduce power + //PORTA.PIN0CTRL = PORT_PULLUPEN_bm; // R + //PORTA.PIN1CTRL = PORT_PULLUPEN_bm; // G + //PORTA.PIN2CTRL = PORT_PULLUPEN_bm; // B + //PORTA.PIN3CTRL = PORT_PULLUPEN_bm; // CH + PORTA.PIN4CTRL = PORT_PULLUPEN_bm; + PORTA.PIN5CTRL = PORT_PULLUPEN_bm; + PORTA.PIN6CTRL = PORT_PULLUPEN_bm; + //PORTA.PIN7CTRL = PORT_PULLUPEN_bm; // HDR + + //PORTC.PIN0CTRL = PORT_PULLUPEN_bm; // doesn't exist + PORTC.PIN1CTRL = PORT_PULLUPEN_bm; + PORTC.PIN2CTRL = PORT_PULLUPEN_bm; + PORTC.PIN3CTRL = PORT_PULLUPEN_bm; + //PORTC.PIN4CTRL = PORT_PULLUPEN_bm; // doesn't exist + //PORTC.PIN5CTRL = PORT_PULLUPEN_bm; // doesn't exist + + //PORTD.PIN0CTRL = PORT_PULLUPEN_bm; // doesn't exist + //PORTD.PIN1CTRL = PORT_PULLUPEN_bm; // doesn't exist + //PORTD.PIN2CTRL = PORT_PULLUPEN_bm; // doesn't exist + //PORTD.PIN3CTRL = PORT_PULLUPEN_bm; // doesn't exist + PORTD.PIN4CTRL = PORT_PULLUPEN_bm + | PORT_ISC_BOTHEDGES_gc; // e-switch + //PORTD.PIN5CTRL = PORT_PULLUPEN_bm; // EN + // AVR datasheet 34.3.1 #2, DAC pin must have input disable set + PORTD.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; // DAC + //PORTD.PIN7CTRL = PORT_PULLUPEN_bm; // IN- NFET + + // set up the DAC + // DAC ranges from 0V to (255 * Vref) / 256 + DAC_VREF = V10; + // TODO: try DAC_RUNSTDBY_bm for extra-efficient moon + DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; + DAC_LVL = 0; // set the output voltage (off at boot) + // TODO: instead of enabling the DAC at boot, pull pin down + // to generate a zero without spending power on the DAC + // (and do this in set_level_zero() too) + +} + + +// set fuses, these carry over to the ELF file +// we need this for enabling BOD in Active Mode from the factory. +// settings can be verified / dumped from the ELF file using this +// command: avr-objdump -d -S -j .fuse anduril.elf +FUSES = { + .WDTCFG = FUSE_WDTCFG_DEFAULT, // Watchdog Configuration + + // enable BOD (continuous) in active mode + .BODCFG = ACTIVE_ENABLE_gc, // BOD Configuration + + .OSCCFG = FUSE_OSCCFG_DEFAULT, // Oscillator Configuration + .SYSCFG0 = FUSE_SYSCFG0_DEFAULT, // System Configuration 0 + + // enable MVIO because VDDIO2 pin isn't connected + // set startup time to 64ms to allow power to stabilize + .SYSCFG1 = MVSYSCFG_DUAL_gc | SUT_64MS_gc, + + .CODESIZE = FUSE_CODESIZE_DEFAULT, + .BOOTSIZE = FUSE_BOOTSIZE_DEFAULT, +}; + + +#define LAYOUT_DEFINED + diff --git a/hw/thefreeman/avr32dd20-devkit/model b/hw/thefreeman/avr32dd20-devkit/model new file mode 100644 index 00000000..216403c9 --- /dev/null +++ b/hw/thefreeman/avr32dd20-devkit/model @@ -0,0 +1 @@ +1632==20 From 957a40fab65553842743f3c178afadcb5bb5c698 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:55:01 -0700 Subject: [PATCH 12/57] added dac-scale.py: short script to calculate avrdd DAC+Vref values from level_calc.py ramp data --- bin/dac-scale.py | 89 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100755 bin/dac-scale.py diff --git a/bin/dac-scale.py b/bin/dac-scale.py new file mode 100755 index 00000000..d57f8c94 --- /dev/null +++ b/bin/dac-scale.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# +# Calculates DAC values and Vref values from a list of raw intensity values +# Usage: dac-scale.py 5,11,18,25,...,370474,384985,400000 +# Output: #defines suitable for use in hw/*/anduril.h +# Assumptions: +# - DAC data range is 0 to 1023 +# - DAC Vrefs are 1.024V and 2.5V +# - HDR is available and has 2 steps +# - HDR channel ratio is "highest_ramp_value / 2500" +# +# Output values thus have 4 "engine gears": +# - HDR low , 1.024V Vref +# - HDR low , 2.5 V Vref +# - HDR high, 1.024V Vref +# - HDR high, 2.5 V Vref +# + +def main(args): + max_pwm = 1023 + raw_pwm = [int(x) for x in args[0].split(',')] + ratio = raw_pwm[-1] / 2500.0 + cooked = [[]] + + def limit(p): + return min(max_pwm, int(p)) + + phase = 0 + for raw in raw_pwm: + if 0 == phase: + if raw <= 1023: + cooked[-1].append(limit(raw)) + else: + phase += 1 + cooked.append([]) + if 1 == phase: + if raw <= int(2500): + cooked[-1].append(limit(raw * 1.024 / 2.5)) + else: + phase += 1 + cooked.append([]) + if 2 == phase: + if raw <= int(1024 * ratio): + cooked[-1].append(limit(raw / ratio)) + else: + phase += 1 + cooked.append([]) + if 3 == phase: + cooked[-1].append(limit(raw * 1.024 / 2.5 / ratio)) + + # "gear change" boundaries + b1 = len(cooked[0]) + b2 = b1 + len(cooked[1]) + b3 = b2 + len(cooked[2]) + b4 = b3 + len(cooked[3]) + + #print(','.join(['%4i' % n for n in cooked])) + + def fmt_pwms(l): + return ','.join(['%4i' % n for n in l]) + + def fmt_tops(v, l): + return ','.join([' %s' % v for n in l]) + + lines = [] + + lines.append('// top level for each "gear": %i %i %i %i' % (b1, b2, b3, b4)) + + lines.append('#define PWM1_LEVELS \\') + lines.append(' ' + fmt_pwms(cooked[0]) + ', \\') + lines.append(' ' + fmt_pwms(cooked[1]) + ', \\') + lines.append(' ' + fmt_pwms(cooked[2]) + ', \\') + lines.append(' ' + fmt_pwms(cooked[3])) + lines.append('#define PWM2_LEVELS \\') + lines.append(' ' + fmt_tops('V10', cooked[0]) + ', \\') + lines.append(' ' + fmt_tops('V25', cooked[1]) + ', \\') + lines.append(' ' + fmt_tops('V10', cooked[2]) + ', \\') + lines.append(' ' + fmt_tops('V25', cooked[3])) + + lines.append('#define MAX_1x7135 %3i' % b2) + lines.append('#define HDR_ENABLE_LEVEL_MIN %3i' % (b2+1)) + + print('\n'.join(lines)) + +if __name__ == "__main__": + import sys + main(sys.argv[1:]) + From 76db685f66baa7787ad94ce91585e7cba8b94cfb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 19 Nov 2023 01:56:17 -0700 Subject: [PATCH 13/57] started refactoring fsm/adc.*, but need a checkpoint before continuing --- fsm/adc.c | 23 ++++------------------- fsm/adc.h | 15 ++++++++++----- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/fsm/adc.c b/fsm/adc.c index 6d4eeb1f..13a76b6c 100644 --- a/fsm/adc.c +++ b/fsm/adc.c @@ -15,14 +15,14 @@ #include -static inline void set_admux_therm() { +static inline void adc_therm_mode() { hwdef_set_admux_therm(); adc_channel = 1; adc_sample_count = 0; // first result is unstable ADC_start_measurement(); } -inline void set_admux_voltage() { +void adc_voltage_mode() { hwdef_set_admux_voltage(); adc_channel = 0; adc_sample_count = 0; // first result is unstable @@ -30,21 +30,6 @@ inline void set_admux_voltage() { } -#ifdef TICK_DURING_STANDBY - // 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 - #define adc_sleep_mode mcu_adc_sleep_mode -#endif - -#define ADC_start_measurement mcu_adc_start_measurement - -// set up ADC for reading battery voltage -#define ADC_on mcu_adc_on -// stop the ADC -#define ADC_off mcu_adc_off - #ifdef USE_VOLTAGE_DIVIDER static inline uint8_t calc_voltage_divider(uint16_t value) { // use 9.7 fixed-point to get sufficient precision @@ -160,7 +145,7 @@ void adc_deferred() { ADC_voltage_handler(); #ifdef USE_THERMAL_REGULATION // set the correct type of measurement for next time - if (! go_to_standby) set_admux_therm(); + if (! go_to_standby) adc_therm_mode(); #endif } #endif @@ -170,7 +155,7 @@ void adc_deferred() { ADC_temperature_handler(); #ifdef USE_LVP // set the correct type of measurement for next time - set_admux_voltage(); + adc_voltage_mode(); #endif } #endif diff --git a/fsm/adc.h b/fsm/adc.h index e4046a41..65d7d6c3 100644 --- a/fsm/adc.h +++ b/fsm/adc.h @@ -32,6 +32,9 @@ volatile uint8_t adc_reset = 2; #endif #endif + +void adc_voltage_mode(); + #ifdef TICK_DURING_STANDBY volatile uint8_t adc_active_now = 0; // sleep LVP needs a different sleep mode #endif @@ -103,14 +106,16 @@ static inline void ADC_temperature_handler(); //inline void ADC_on(); -#define ADC_on mcu_adc_on +#define ADC_on adc_voltage_mode //inline void ADC_off(); #define ADC_off mcu_adc_off //inline void ADC_start_measurement(); #define ADC_start_measurement mcu_adc_start_measurement -#ifdef TICK_DURING_STANDBY - //inline void adc_sleep_mode(); - #define adc_sleep_mode mcu_adc_sleep_mode -#endif +// 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 +//inline void adc_sleep_mode(); +#define adc_sleep_mode mcu_adc_sleep_mode From 8bc6e16569474487efcee3eaee7b6af9738585b8 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 21 Nov 2023 02:44:11 -0700 Subject: [PATCH 14/57] 1.55V AA battery should not show as "white" voltage color, only purple --- ui/anduril/aux-leds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/anduril/aux-leds.c b/ui/anduril/aux-leds.c index 1b30d34e..dce8d264 100644 --- a/ui/anduril/aux-leds.c +++ b/ui/anduril/aux-leds.c @@ -67,7 +67,7 @@ uint8_t voltage_to_rgb() { 12, 4, // G+B 13, 5, // B 14, 6, // R + B - 15, 7, // R+G+B + 16, 7, // R+G+B 20, 0, // black #endif // li-ion voltages From fdb47b96e86924bf81852205b2b3078b8b21d040 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 21 Nov 2023 02:52:00 -0700 Subject: [PATCH 15/57] got ADC voltage+temp working on avrdd... but broke all other builds/MCUs This patch changes the ADC code to use two internal standard units, and everything else must convert to these units: - FSM Volts: centiVolts << 6 (range 0 to 10.24 V per cell) - FSM Kelvin: Kelvin << 6 (range 0 to 1024 K) UI-level voltage is still "Volts * 10", and temperature is still Celsius. FSM expects functions to be provided, to convert from the hardware's raw ADC measurements to these internal units: `voltage_raw2cooked()` and `temp_raw2cooked()`. Defaults will be provided by arch/*.[ch] for each MCU type, or the hwdef can make its own. Anyway, gotta go fix all the other MCUs and builds now. :( --- arch/avr32dd20.c | 60 +++++++++++++++----------- arch/avr32dd20.h | 15 +++++-- fsm/adc.c | 31 ++++++++++++- hw/thefreeman/avr32dd20-devkit/hwdef.c | 13 ++++++ hw/thefreeman/avr32dd20-devkit/hwdef.h | 12 ++++-- 5 files changed, 97 insertions(+), 34 deletions(-) diff --git a/arch/avr32dd20.c b/arch/avr32dd20.c index 45923a8f..998e9f6f 100644 --- a/arch/avr32dd20.c +++ b/arch/avr32dd20.c @@ -52,19 +52,19 @@ inline void mcu_set_admux_therm() { ADC0.SAMPCTRL = 32; // set single-ended or differential // set resolution to 12 bits - // set left- or right-adjust (right) + // set left- or right-adjust // set free-running mode or not (yes) ADC0.CTRLA = ADC_CONVMODE_SINGLEENDED_gc | ADC_RESSEL_12BIT_gc - //| ADC_LEFTADJ_bm // not in temperature mode + | ADC_LEFTADJ_bm | ADC_FREERUN_bm; // set number of samples (requires adjustment in formula too) ADC0.CTRLB = ADC_SAMPNUM_NONE_gc; - // TODO: accumulate more samples for more resolution - // (and probably set the prescale faster too) - //ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; // 16 samples per result + // accumulate more samples for more resolution + ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; // 16 samples per result // set a clock prescaler - ADC0.CTRLC = ADC_PRESC_DIV64_gc; + //ADC0.CTRLC = ADC_PRESC_DIV64_gc; // use this when no accumulation + ADC0.CTRLC = ADC_PRESC_DIV4_gc; // measure faster when oversampling // enable the ADC ADC0.CTRLA |= ADC_ENABLE_bm; // actually start measuring (happens in another function) @@ -90,7 +90,7 @@ inline void mcu_set_admux_voltage() { // set number of samples ADC0.CTRLB = ADC_SAMPNUM_ACC16_gc; // 16 samples per result // set a clock prescaler - ADC0.CTRLC = ADC_PRESC_DIV16_gc; // not too fast, not too slow + ADC0.CTRLC = ADC_PRESC_DIV4_gc; // measure faster when oversampling // select the positive ADC input with MUXPOS #ifdef USE_VOLTAGE_DIVIDER // external voltage divider // ADC input pin / Vref @@ -113,11 +113,8 @@ inline void mcu_adc_sleep_mode() { } inline void mcu_adc_start_measurement() { - // FIXME: enable this after getting ADC stuff fixed - #if 0 ADC0.INTCTRL |= ADC_RESRDY_bm; // enable interrupt ADC0.COMMAND |= ADC_STCONV_bm; // actually start measuring - #endif } /* @@ -135,24 +132,35 @@ inline void mcu_adc_vect_clear() { ADC0.INTFLAGS = ADC_RESRDY_bm; // clear the interrupt } -inline uint16_t mcu_adc_result_temp() { - // FIXME: better math, higher precision - // 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 +inline uint16_t mcu_adc_result() { + // value is 12-bit left-aligned + 16x oversampling = 16 bits total + return ADC0.RES; } -inline uint16_t mcu_adc_result_volts() { - // voltage is 12-bit right-aligned + 16x oversampling = 16 bits total - return ADC0.RES; +inline uint16_t mcu_vdd_raw2cooked(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; +} + +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) + // AVR DD datasheet section 33.3.3.8 + uint16_t sigrow_slope = SIGROW.TEMPSENSE0; // factory calibration data + uint16_t sigrow_offset = SIGROW.TEMPSENSE1; // 12-bit value + //const uint32_t scaling_factor = 4096; // use top 12 bits of ADC data + //uint32_t temp = sigrow_offset - (measurement >> 4); + const uint32_t scaling_factor = 65536; // use all 16 bits of ADC data + uint32_t temp = (sigrow_offset << 4) - measurement; + temp *= sigrow_slope; // 24-bit result + temp += scaling_factor / 8; // Add 1/8th K to get correct rounding on later divisions + //temp = temp >> 6; // change (K << 12) to (K << 6) + temp = temp >> 10; // change (K << 16) to (K << 6) + return temp; // left-aligned uint16_t, 0 to 1023.98 Kelvin } inline uint8_t mcu_adc_lsb() { diff --git a/arch/avr32dd20.h b/arch/avr32dd20.h index 7a6b8f11..3ebb05a0 100644 --- a/arch/avr32dd20.h +++ b/arch/avr32dd20.h @@ -50,12 +50,21 @@ 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 +//#define MCU_ADC_RESULT_PER_TYPE +//inline uint16_t mcu_adc_result_temp(); +//inline uint16_t mcu_adc_result_volts(); -inline uint16_t mcu_adc_result_temp(); +// return (centiVolts << 6), range 0 to 10.24V +#define voltage_raw2cooked mcu_vdd_raw2cooked +inline uint16_t mcu_vdd_raw2cooked(uint16_t measurement); -inline uint16_t mcu_adc_result_volts(); +// 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/fsm/adc.c b/fsm/adc.c index 13a76b6c..73e282d3 100644 --- a/fsm/adc.c +++ b/fsm/adc.c @@ -30,6 +30,7 @@ void adc_voltage_mode() { } +#if 0 #ifdef USE_VOLTAGE_DIVIDER static inline uint8_t calc_voltage_divider(uint16_t value) { // use 9.7 fixed-point to get sufficient precision @@ -44,6 +45,7 @@ static inline uint8_t calc_voltage_divider(uint16_t value) { return result; } #endif +#endif // Each full cycle runs ~2X per second with just voltage enabled, // or ~1X per second with voltage and temperature. @@ -67,7 +69,6 @@ ISR(ADC_vect) { // update the latest value #ifdef MCU_ADC_RESULT_PER_TYPE - // thermal, convert ADC reading to left-aligned Kelvin if (channel) m = mcu_adc_result_temp(); else m = mcu_adc_result_volts(); #else @@ -208,6 +209,19 @@ 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); + + // calculate actual voltage: volts * 10 + // TODO: should be (volts * 40) for extra precision + voltage = (measurement + VOLTAGE_FUDGE_FACTOR + #ifdef USE_VOLTAGE_CORRECTION + + VOLT_CORR - 7 + #endif + ) >> 1; + + #if 0 // values stair-step between intervals of 64, with random variations // of 1 or 2 in either direction, so if we chop off the last 6 bits // it'll flap between N and N-1... but if we add half an interval, @@ -231,6 +245,7 @@ static inline void ADC_voltage_handler() { #endif ) >> 1; #endif + #endif // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N seconds since last call) @@ -290,8 +305,14 @@ static inline void ADC_temperature_handler() { } // latest 16-bit ADC reading - uint16_t measurement = adc_smooth[1]; + // convert raw ADC value to Kelvin << 6 + // 0 .. 65535 = 0 K .. 1024 K + uint16_t measurement = temp_raw2cooked(adc_smooth[1]); + // (Kelvin << 6) to Celsius + temperature = (measurement>>6) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275; + + #if 0 // values stair-step between intervals of 64, with random variations // of 1 or 2 in either direction, so if we chop off the last 6 bits // it'll flap between N and N-1... but if we add half an interval, @@ -313,6 +334,12 @@ static inline void ADC_temperature_handler() { // external sensor temperature = EXTERN_TEMP_FORMULA(measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL; #endif + #endif + + // instead of (K << 6), use (K << 1) now + // TODO: use more precision, if it can be done without overflow in 16 bits + // (and still work on attiny85 without increasing ROM size) + measurement = measurement >> 5; // how much has the temperature changed between now and a few seconds ago? int16_t diff; diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.c b/hw/thefreeman/avr32dd20-devkit/hwdef.c index e5b347f5..133baca5 100644 --- a/hw/thefreeman/avr32dd20-devkit/hwdef.c +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.c @@ -103,3 +103,16 @@ bool gradual_tick_main(uint8_t gt) { return false; // not done yet } + +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) + // 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); + return result; +} + diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h index 7e093f94..7e1ad3d7 100644 --- a/hw/thefreeman/avr32dd20-devkit/hwdef.h +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h @@ -35,7 +35,7 @@ * and low value Rsense (high current range, pin high) * IN- NFET : pull up after BST enable to eliminate startup flash, pull down otherwise * CH senses the status of the onboard charger - * LVL : ??? (unused?) + * BATT LVL : Vbat * (100.0/(330+100)) * LVB is for OTSM firmware, not used here */ @@ -109,8 +109,14 @@ enum CHANNEL_MODES { // TODO: define stuff for the voltage divider // 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 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) +// convert BATT LVL pin readings to FSM volt units +#undef voltage_raw2cooked +uint16_t voltage_raw2cooked(uint16_t measurement); + // average drop across diode on this hardware #ifndef VOLTAGE_FUDGE_FACTOR @@ -148,7 +154,7 @@ inline void hwdef_setup() { //PORTA.PIN3CTRL = PORT_PULLUPEN_bm; // CH PORTA.PIN4CTRL = PORT_PULLUPEN_bm; PORTA.PIN5CTRL = PORT_PULLUPEN_bm; - PORTA.PIN6CTRL = PORT_PULLUPEN_bm; + //PORTA.PIN6CTRL = PORT_PULLUPEN_bm; // BATT LVL //PORTA.PIN7CTRL = PORT_PULLUPEN_bm; // HDR //PORTC.PIN0CTRL = PORT_PULLUPEN_bm; // doesn't exist From baaa035cf93340b8f2c626bdba47e8066cf40067 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 Nov 2023 05:34:26 -0700 Subject: [PATCH 16/57] ADC voltage: battcheck 3 digits, fixed t1616, switched back to 8-bit internal volt unit Before this branch, `voltage` was 6 bits: Volts * 10 A couple patches ago, I upgraded it to 16 bits: 65535 * Volts / 10.24 That costs too much extra ROM on attiny85 though, for extra precision it doesn't even use... so I switched back to an 8-bit value. It's still more precise than before though: Volts * 40 ... and battcheck displays an extra digit now, on devices with ROM for it. ... and battcheck waits a second to get a more accurate measurement before displaying the first value. It has *much* less variation between first and later readings now. Also: - got t1616 builds working again (tested fc13 and thefreeman-boost-fwaa) - upgraded t1616 voltage and temp to 12-bit (10 bits + 4x oversampling) - removed expensive temp conversion from t1616 ADC interrupt - recalibrated t1616 bogomips again; runs faster after interrupt fix - increased t1616 internal VDD measurement resolution by 36% (1.5V Vref, not 1.1V) - fixed sloppy setting of Vref bits I still need to test / update other t1616 builds, and fix all the t85 + t1634 code and build targets. --- arch/attiny1616.c | 125 ++++++++++++++---- arch/attiny1616.h | 20 ++- arch/avr32dd20.c | 37 +++--- arch/avr32dd20.h | 4 +- fsm/adc.c | 47 ++++--- fsm/adc.h | 4 +- hw/sofirn/sp10-pro/hwdef.h | 4 +- hw/thefreeman/avr32dd20-devkit/hwdef.c | 16 +-- hw/thefreeman/avr32dd20-devkit/hwdef.h | 6 +- .../boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h | 17 ++- ui/anduril/anduril.c | 1 + ui/anduril/aux-leds.c | 34 ++--- ui/anduril/config-default.h | 4 + 13 files changed, 207 insertions(+), 112 deletions(-) diff --git a/arch/attiny1616.c b/arch/attiny1616.c index a3ead7e2..330c809d 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 b4e17fca..57b00233 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 998e9f6f..2ac3526c 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 3ebb05a0..82951dee 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 73e282d3..97dfc934 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 65d7d6c3..0c0a9e5a 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 cb1271de..047758b2 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 133baca5..3e5dd797 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 7e1ad3d7..a5b37a94 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 095aea04..45c02dea 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 c4345183..1cdb8d00 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 dce8d264..fd184fc3 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 cd25b528..1b34e8c0 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) From 5f8453b34550c2b26629d0e3690ff4338a967dea Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 22 Nov 2023 05:35:14 -0700 Subject: [PATCH 17/57] avr32dd20-devkit: make the defaults a bit more dev friendly (realtime voltage colors, and no simple UI by default) --- hw/thefreeman/avr32dd20-devkit/anduril.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/thefreeman/avr32dd20-devkit/anduril.h b/hw/thefreeman/avr32dd20-devkit/anduril.h index 97e9e109..ee3765a5 100644 --- a/hw/thefreeman/avr32dd20-devkit/anduril.h +++ b/hw/thefreeman/avr32dd20-devkit/anduril.h @@ -87,7 +87,7 @@ // UI -//#define SIMPLE_UI_ACTIVE 0 // advanced UI by default +#define SIMPLE_UI_ACTIVE 0 // advanced UI by default, because it's a dev board // allow Aux Config and Strobe Modes in Simple UI //#define USE_EXTENDED_SIMPLE_UI @@ -104,6 +104,10 @@ // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS +// turn on the aux LEDs while main LEDs are on +// because this is a dev board and it's useful to see that +#define USE_AUX_RGB_LEDS_WHILE_ON 20 +#define USE_INDICATOR_LED_WHILE_RAMPING // show each channel while it scroll by in the menu #define USE_CONFIG_COLORS From 8c237206aba74f9096d85f90209ac6b7dc238b1b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 24 Nov 2023 06:29:56 -0700 Subject: [PATCH 18/57] more ADC / DAC / MCU progress... - fixed t1616 Vref values getting clobbered sometimes, wrapped setting those in a #define'd function for ease and consistency - moved some DAC definitions from hw/ to arch/ to reduce repetition - fixed thefreeman's other builds - switched from PWM_TOPS to PWM2_LEVELS (I'm trying to phase out _TOPS) --- arch/attiny1616.c | 9 ++--- arch/attiny1616.h | 24 ++++++++++++ arch/avr32dd20.h | 13 +++++++ hw/thefreeman/avr32dd20-devkit/anduril.h | 25 +------------ hw/thefreeman/avr32dd20-devkit/hwdef.h | 20 +++------- .../boost-fwaa-mp3432-hdr-dac-rgb/anduril.h | 23 +++++++----- .../boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h | 37 +++++++------------ .../boost21-mp3431-hdr-dac-argb/anduril.h | 24 ++++++------ .../boost21-mp3431-hdr-dac-argb/hwdef.c | 14 +++---- .../boost21-mp3431-hdr-dac-argb/hwdef.h | 34 ++++++----------- hw/thefreeman/lin16dac/anduril.h | 22 ++++++----- hw/thefreeman/lin16dac/hwdef.c | 15 ++++---- hw/thefreeman/lin16dac/hwdef.h | 33 ++++++----------- 13 files changed, 136 insertions(+), 157 deletions(-) diff --git a/arch/attiny1616.c b/arch/attiny1616.c index 330c809d..2770d06b 100644 --- a/arch/attiny1616.c +++ b/arch/attiny1616.c @@ -29,8 +29,7 @@ inline void clock_prescale_set(uint8_t n) { 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 + mcu_set_adc0_vref(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 @@ -46,8 +45,7 @@ inline void mcu_set_admux_voltage() { 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 + mcu_set_adc0_vref(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 @@ -55,8 +53,7 @@ inline void mcu_set_admux_voltage() { | ADC_REFSEL_INTREF_gc; // Use internal ADC 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 + mcu_set_adc0_vref(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 diff --git a/arch/attiny1616.h b/arch/attiny1616.h index 57b00233..940973ee 100644 --- a/arch/attiny1616.h +++ b/arch/attiny1616.h @@ -18,6 +18,8 @@ inline void mcu_clock_speed(); // this should work, but needs further validation inline void clock_prescale_set(uint8_t n); +// TODO: allow hwdef to define a base clock speed, +// and adjust these values accordingly typedef enum { // Actual clock is 20 MHz, but assume that 10 MHz is the top speed and work from there @@ -34,8 +36,30 @@ typedef enum } clock_div_t; +////////// DAC controls ////////// + +#define DAC_LVL DAC0.DATA // 0 to 255, for 0V to Vref +#define DAC_VREF VREF.CTRLA // 0.55V, 1.1V, 1.5V, 2.5V, or 4.3V + +// set only the relevant bits of the Vref register +#define mcu_set_dac_vref(x) \ + VREF.CTRLA = x | (VREF.CTRLA & (~VREF_DAC0REFSEL_gm)); + +// Vref values +// (for the DAC bits, not the ADC bits) +#define V05 V055 +#define V055 VREF_DAC0REFSEL_0V55_gc +#define V11 VREF_DAC0REFSEL_1V1_gc +#define V25 VREF_DAC0REFSEL_2V5_gc +#define V43 VREF_DAC0REFSEL_4V34_gc +#define V15 VREF_DAC0REFSEL_1V5_gc + ////////// ADC voltage / temperature ////////// +// set only the relevant bits of the Vref register +#define mcu_set_adc0_vref(x) \ + VREF.CTRLA = x | (VREF.CTRLA & (~VREF_ADC0REFSEL_gm)); + #define hwdef_set_admux_therm mcu_set_admux_therm inline void mcu_set_admux_therm(); diff --git a/arch/avr32dd20.h b/arch/avr32dd20.h index 82951dee..09b4096b 100644 --- a/arch/avr32dd20.h +++ b/arch/avr32dd20.h @@ -30,6 +30,19 @@ typedef enum } clock_div_t; +////////// DAC controls ////////// + +// main LED outputs +#define DAC_LVL DAC0_DATA // 0 to 1023, for 0V to Vref +#define DAC_VREF VREF_DAC0REF // 1.024V, 2.048V, 4.096V, or 2.5V + +// Vref values (suitable for DAC and ADC0) +#define V10 VREF_REFSEL_1V024_gc +#define V20 VREF_REFSEL_2V048_gc +#define V25 VREF_REFSEL_2V500_gc +#define V40 VREF_REFSEL_4V096_gc + + ////////// ADC voltage / temperature ////////// #define hwdef_set_admux_therm mcu_set_admux_therm diff --git a/hw/thefreeman/avr32dd20-devkit/anduril.h b/hw/thefreeman/avr32dd20-devkit/anduril.h index ee3765a5..02d5de37 100644 --- a/hw/thefreeman/avr32dd20-devkit/anduril.h +++ b/hw/thefreeman/avr32dd20-devkit/anduril.h @@ -1,5 +1,5 @@ -// thefreeman's BST21 BST20-FWxA (no button LED) -// Copyright (C) 2023 TBD (thefreeman), Selene ToyKeeper +// thefreeman's avr32dd20 devkit board +// Copyright (C) 2023 thefreeman, Selene ToyKeeper // SPDX-License-Identifier: GPL-3.0-or-later #pragma once @@ -20,7 +20,6 @@ // - high 2.5 V // HDR ratio: 160 // PWM1: DAC Data -#if 1 // level_calc.py 4.3287 1 150 7135 5 0.01 1400 --pwm 400000 // top level for each "gear": 30 40 120 150 #define PWM1_LEVELS \ @@ -36,26 +35,6 @@ #define MAX_1x7135 40 #define HDR_ENABLE_LEVEL_MIN 41 #define DEFAULT_LEVEL 50 -#else -// level_calc.py 9.21 1 150 7135 5 0.2 1400 --pwm 400000 -// (plus dac-scale.py post-processing to get values for HDR+Vref ranges) -// top level for each "gear": 35 48 127 150 -#define PWM1_LEVELS \ - 5, 11, 18, 25, 33, 41, 50, 60, 71, 83, 96, 110, 125, 141, 158, 177, 198, 220, 244, 269, 297, 326, 358, 392, 429, 469, 511, 556, 605, 657, 713, 772, 836, 904, 976, \ - 431, 465, 501, 539, 580, 624, 670, 720, 772, 828, 887, 950,1017, \ - 16, 17, 18, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 64, 68, 72, 76, 80, 85, 90, 95, 100, 106, 112, 118, 124, 131, 138, 145, 153, 161, 170, 179, 188, 198, 208, 219, 230, 242, 254, 266, 280, 294, 308, 323, 339, 355, 373, 391, 409, 429, 449, 470, 492, 515, 539, 564, 589, 616, 644, 673, 704, 735, 768, 802, 837, 874, 912, 952, 993, \ - 424, 442, 461, 480, 501, 522, 544, 566, 590, 614, 640, 666, 693, 721, 750, 780, 811, 844, 877, 912, 948, 985,1023 -// Vref selector (V10, V20, V25, V40 = 1.024V, 2.048V, 2.5V, 4.096V) -#define PWM2_LEVELS \ - V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ - V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, \ - V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, V10, \ - V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25, V25 - -#define MAX_1x7135 48 -#define DEFAULT_LEVEL 48 -#define HDR_ENABLE_LEVEL_MIN 49 // when HDR FET turns ON -#endif // no PWM, so MCU clock speed can be slow #define HALFSPEED_LEVEL 41 diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h index a5b37a94..f1b60953 100644 --- a/hw/thefreeman/avr32dd20-devkit/hwdef.h +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h @@ -39,7 +39,7 @@ * LVB is for OTSM firmware, not used here */ -#define HWDEF_C thefreeman/avr32dd20-devkit/hwdef.c +#define HWDEF_C thefreeman/avr32dd20-devkit/hwdef.c // allow using aux LEDs as extra channel modes #include "fsm/chan-rgbaux.h" @@ -59,8 +59,6 @@ enum CHANNEL_MODES { #define CHANNEL_MODES_ENABLED 0b0000000000000001 -#define PWM_CHANNELS 1 // old, remove this - #undef GRADUAL_ADJUST_SPEED #define GRADUAL_ADJUST_SPEED 4 @@ -73,15 +71,7 @@ enum CHANNEL_MODES { #define PWM2_GET(l) PWM_GET8(pwm2_levels, l) // main LED outputs -#define DAC_LVL DAC0_DATA // 0 to 255, for 0V to Vref -#define DAC_VREF VREF_DAC0REF // 1.024V, 2.048V, 4.096V, or 2.5V -//#define DAC_VREF VREF.ADC0REF // 1.024V, 2.048V, 4.096V, or 2.5V -#define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) -// Vref values -#define V10 VREF_REFSEL_1V024_gc -#define V20 VREF_REFSEL_2V048_gc -#define V25 VREF_REFSEL_2V500_gc -#define V40 VREF_REFSEL_4V096_gc +// (DAC_LVL + DAC_VREF + Vref values are defined in arch/*.h) // BST enable #define BST_ENABLE_PIN PIN5_bp @@ -113,6 +103,7 @@ enum CHANNEL_MODES { #define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN26_gc #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) +// don't use the default VDD converter // convert BATT LVL pin readings to FSM volt units #undef voltage_raw2cooked uint8_t voltage_raw2cooked(uint16_t measurement); @@ -135,7 +126,8 @@ uint8_t voltage_raw2cooked(uint16_t measurement); inline void hwdef_setup() { - // TODO? for this DAC controlled-light, try to decrease the clock speed + // TODO: for this DAC controlled-light, try to decrease the clock speed + // to reduce overall system power mcu_clock_speed(); VPORTA.DIR = PIN0_bm // R @@ -180,7 +172,7 @@ inline void hwdef_setup() { DAC_VREF = V10; // TODO: try DAC_RUNSTDBY_bm for extra-efficient moon DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; - DAC_LVL = 0; // set the output voltage (off at boot) + DAC_LVL = 0; // turn off output at boot // TODO: instead of enabling the DAC at boot, pull pin down // to generate a zero without spending power on the DAC // (and do this in set_level_zero() too) diff --git a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h index 33583df5..d1b16619 100644 --- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h +++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h @@ -19,15 +19,17 @@ // - high 0.55V // - high 2.5V // PWM1: DAC Data -#define PWM1_LEVELS 2, 3, 4, 5, 6, 8, 9, 11, 14, 16, 19, 23, 26, 31, 35, 41, 47, 54, 61, 69, 78, 89,100,112,125,140,155,173,191,212,234, \ - 56, 62, 68, 74, 82, 89, 97,106,115,125,136,147,159,172,186,200,215,232,249, \ - 14, 15, 17, 18, 19, 20, 22, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81, 86, 90, 95, 99,104,109,114,120,126,131,138,144,150,157,164,171,179,187,195,203,212,221,230,239,249, \ - 57, 59, 61, 64, 66, 69, 72, 74, 77, 80, 83, 86, 90, 93, 96,100,103,107,111,115,119,123,127,132,136,141,145,150,155,160,166,171,176,182,188,194,200,206,213,219,226,233,240,247,255 -// PWM Tops: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) -#define PWM_TOPS V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ - V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ - V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ - V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 +#define PWM1_LEVELS \ + 2, 3, 4, 5, 6, 8, 9, 11, 14, 16, 19, 23, 26, 31, 35, 41, 47, 54, 61, 69, 78, 89,100,112,125,140,155,173,191,212,234, \ + 56, 62, 68, 74, 82, 89, 97,106,115,125,136,147,159,172,186,200,215,232,249, \ + 14, 15, 17, 18, 19, 20, 22, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81, 86, 90, 95, 99,104,109,114,120,126,131,138,144,150,157,164,171,179,187,195,203,212,221,230,239,249, \ + 57, 59, 61, 64, 66, 69, 72, 74, 77, 80, 83, 86, 90, 93, 96,100,103,107,111,115,119,123,127,132,136,141,145,150,155,160,166,171,176,182,188,194,200,206,213,219,226,233,240,247,255 +// PWM2: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) +#define PWM2_LEVELS \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 #define MAX_1x7135 50 #define DEFAULT_LEVEL 44 @@ -39,6 +41,7 @@ #define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 130 // ~50% power, ~??? mA / ??? lm +// 1 22 [44] 65 87 108 130 #define RAMP_DISCRETE_FLOOR 1 #define RAMP_DISCRETE_CEIL 130 #define RAMP_DISCRETE_STEPS 7 @@ -70,7 +73,7 @@ //#define SIMPLE_UI_ACTIVE 0 // advanced UI by default // allow Aux Config and Strobe Modes in Simple UI -#define USE_EXTENDED_SIMPLE_UI +//#define USE_EXTENDED_SIMPLE_UI // Allow 3C in Simple UI for switching between smooth and stepped ramping #define USE_SIMPLE_UI_RAMPING_TOGGLE 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 45c02dea..bc1d9a7a 100644 --- a/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h +++ b/hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h @@ -56,26 +56,16 @@ enum CHANNEL_MODES { #define CHANNEL_MODES_ENABLED 0b0000000000000001 -#define PWM_CHANNELS 1 // old, remove this - #define PWM_BITS 8 // 8-bit DAC -#define PWM_GET PWM_GET8 #define PWM_DATATYPE uint8_t #define PWM_DATATYPE2 uint16_t // only needs 32-bit if ramp values go over 255 #define PWM1_DATATYPE uint8_t // main LED ramp +#define PWM1_GET(l) PWM_GET8(pwm1_levels, l) +#define PWM2_DATATYPE uint8_t // DAC Vref table +#define PWM2_GET(l) PWM_GET8(pwm2_levels, l) // main LED outputs -#define DAC_LVL DAC0.DATA // 0 to 255, for 0V to Vref -#define DAC_VREF VREF.CTRLA // 0.55V or 2.5V -#define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) -// Vref values -// (1.1V ADC + variable DAC) -#define V05 V055 -#define V055 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_0V55_gc) -#define V11 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V1_gc) -#define V25 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_2V5_gc) -#define V43 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_4V34_gc) -#define V15 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V5_gc) +// (DAC_LVL + DAC_VREF + Vref values are defined in arch/*.h) // BST enable #define BST_ENABLE_PIN PIN4_bp @@ -103,9 +93,10 @@ enum CHANNEL_MODES { // Voltage divider battLVL #define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is regulated +#define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN2_gc // which ADC channel to read #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 +// don't use the default VDD converter #undef voltage_raw2cooked #define voltage_raw2cooked mcu_vdivider_raw2cooked @@ -130,10 +121,9 @@ enum CHANNEL_MODES { inline void hwdef_setup() { - // TODO: for this DAC controlled-light, try to decrease the clock speed or use the ULP - // set up the system clock to run at 10 MHz to match other attiny1616 lights - _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, - CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm ); + // TODO: for this DAC controlled-light, try to decrease the clock speed + // to reduce overall system power + mcu_clock_speed(); VPORTA.DIR = PIN4_bm // BST EN | PIN5_bm // HDR @@ -170,11 +160,10 @@ inline void hwdef_setup() { // set up the DAC // https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny1614-16-17-DataSheet-DS40002204A.pdf // DAC ranges from 0V to (255 * Vref) / 256 - // also VREF_DAC0REFSEL_0V55_gc and VREF_DAC0REFSEL_1V1_gc and VREF_DAC0REFSEL_2V5_gc - VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc; - VREF.CTRLB |= VREF_DAC0REFEN_bm; - DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; - DAC0.DATA = 255; // set the output voltage + mcu_set_dac_vref(V05); // boot at lowest Vref setting + VREF.CTRLB |= VREF_DAC0REFEN_bm; // enable DAC Vref + DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; // enable DAC + DAC_LVL = 0; // turn off output at boot } diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h index a6a111c6..8319d138 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h @@ -3,7 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later #pragma once -#include "thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h" +#define HWDEF_H thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h // HPRsense : 1.7+0.3+5 = 7mR (DMN22M5UFG+trace resistance+5mR) // Vsense=42.46mV, R1= 191k @@ -19,15 +19,17 @@ // - high 0.55V // - high 2.5V // PWM1: DAC Data -#define PWM1_LEVELS 2, 3, 4, 5, 7, 9, 11, 13, 16, 19, 23, 28, 33, 39, 45, 53, 61, 71, 81, 93,106,121,137,155,175,196,220,246, \ - 60, 67, 74, 82, 91,100,110,121,133,146,159,174,190,207,224,244, \ - 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 40, 42, 45, 47, 50, 53, 56, 59, 62, 66, 69, 73, 77, 81, 85, 90, 94, 99,104,109,114,120,126,132,138,144,151,158,165,173,180,188,196,205,214,223,232,242,252, \ - 57, 60, 62, 65, 67, 70, 73, 76, 78, 82, 85, 88, 91, 95, 98,102,105,109,113,117,121,126,130,135,139,144,149,154,159,164,170,175,181,187,193,199,206,212,219,225,232,240,247,255 -// PWM Tops: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) -#define PWM_TOPS V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ - V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ - V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ - V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 +#define PWM1_LEVELS \ + 2, 3, 4, 5, 7, 9, 11, 13, 16, 19, 23, 28, 33, 39, 45, 53, 61, 71, 81, 93,106,121,137,155,175,196,220,246, \ + 60, 67, 74, 82, 91,100,110,121,133,146,159,174,190,207,224,244, \ + 8, 9, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 27, 29, 31, 33, 35, 37, 40, 42, 45, 47, 50, 53, 56, 59, 62, 66, 69, 73, 77, 81, 85, 90, 94, 99,104,109,114,120,126,132,138,144,151,158,165,173,180,188,196,205,214,223,232,242,252, \ + 57, 60, 62, 65, 67, 70, 73, 76, 78, 82, 85, 88, 91, 95, 98,102,105,109,113,117,121,126,130,135,139,144,149,154,159,164,170,175,181,187,193,199,206,212,219,225,232,240,247,255 +// PWM2: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) +#define PWM2_LEVELS \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 #define MAX_1x7135 44 #define DEFAULT_LEVEL 44 @@ -71,7 +73,7 @@ //#define SIMPLE_UI_ACTIVE 0 // advanced UI by default // allow Aux Config and Strobe Modes in Simple UI -#define USE_EXTENDED_SIMPLE_UI +//#define USE_EXTENDED_SIMPLE_UI // Allow 3C in Simple UI for switching between smooth and stepped ramping #define USE_SIMPLE_UI_RAMPING_TOGGLE diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c index 97f5fc9d..573ec2fb 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c @@ -22,7 +22,7 @@ Channel channels[] = { void set_level_zero() { DAC_LVL = 0; // DAC off - DAC_VREF = V055; // low Vref + mcu_set_dac_vref(V055); // low Vref HDR_ENABLE_PORT &= ~(1 << HDR_ENABLE_PIN); // HDR off // prevent post-off flash @@ -49,8 +49,8 @@ void set_level_main(uint8_t level) { BST_ENABLE_PORT |= (1 << BST_ENABLE_PIN); // pre-load ramp data so it can be assigned faster later - PWM_DATATYPE dac_lvl = PWM_GET(pwm1_levels, level); - PWM_DATATYPE dac_vref = PWM_GET(pwm_tops, level); + PWM1_DATATYPE dac_lvl = PWM1_GET(level); + PWM2_DATATYPE dac_vref = PWM2_GET(level); // enable HDR on top half of ramp if (level >= (HDR_ENABLE_LEVEL_MIN-1)) @@ -61,7 +61,7 @@ void set_level_main(uint8_t level) { // set these in successive clock cycles to avoid getting out of sync // (minimizes ramp bumps when changing gears) DAC_LVL = dac_lvl; - DAC_VREF = dac_vref; + mcu_set_dac_vref(dac_vref); if (noflash) { // wait for flash prevention to finish @@ -75,11 +75,11 @@ bool gradual_tick_main(uint8_t gt) { // otherwise, simply jump to the next ramp level // and let set_level() handle any gear changes - PWM_DATATYPE dac_next = PWM_GET(pwm1_levels, gt); - PWM_DATATYPE vref_next = PWM_GET(pwm_tops, gt); + PWM1_DATATYPE dac_next = PWM1_GET(gt); + PWM2_DATATYPE vref_next = PWM2_GET(gt); // different gear = full adjustment - if (vref_next != DAC_VREF) return true; // let parent set_level() for us + if (vref_next != (DAC_VREF & VREF_DAC0REFSEL_gm)) return true; // let parent set_level() for us // same gear = small adjustment GRADUAL_ADJUST_SIMPLE(dac_next, DAC_LVL); diff --git a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h index d030516a..d83aa462 100644 --- a/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h +++ b/hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h @@ -57,26 +57,16 @@ enum CHANNEL_MODES { #define CHANNEL_MODES_ENABLED 0b0000000000000001 -#define PWM_CHANNELS 1 // old, remove this - #define PWM_BITS 8 // 8-bit DAC -#define PWM_GET PWM_GET8 #define PWM_DATATYPE uint8_t #define PWM_DATATYPE2 uint16_t // only needs 32-bit if ramp values go over 255 #define PWM1_DATATYPE uint8_t // main LED ramp +#define PWM1_GET(l) PWM_GET8(pwm1_levels, l) +#define PWM2_DATATYPE uint8_t // DAC Vref table +#define PWM2_GET(l) PWM_GET8(pwm2_levels, l) // main LED outputs -#define DAC_LVL DAC0.DATA // 0 to 255, for 0V to Vref -#define DAC_VREF VREF.CTRLA // 0.55V or 2.5V -#define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) -// Vref values -// (1.1V ADC + variable DAC) -#define V05 V055 -#define V055 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_0V55_gc) -#define V11 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V1_gc) -#define V25 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_2V5_gc) -#define V43 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_4V34_gc) -#define V15 (VREF_ADC0REFSEL_1V1_gc|VREF_DAC0REFSEL_1V5_gc) +// (DAC_LVL + DAC_VREF + Vref values are defined in arch/*.h) // BST enable #define BST_ENABLE_PIN PIN0_bp @@ -125,10 +115,9 @@ enum CHANNEL_MODES { inline void hwdef_setup() { - // TODO: for this DAC controlled-light, try to decrease the clock speed or use the ULP - // set up the system clock to run at 10 MHz to match other attiny1616 lights - _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, - CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm ); + // TODO: for this DAC controlled-light, try to decrease the clock speed + // to reduce overall system power + mcu_clock_speed(); VPORTA.DIR = PIN6_bm; // DAC VPORTB.DIR = PIN1_bm // R @@ -165,11 +154,10 @@ inline void hwdef_setup() { // set up the DAC // https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny1614-16-17-DataSheet-DS40002204A.pdf // DAC ranges from 0V to (255 * Vref) / 256 - // also VREF_DAC0REFSEL_0V55_gc and VREF_DAC0REFSEL_1V1_gc and VREF_DAC0REFSEL_2V5_gc - VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc; - VREF.CTRLB |= VREF_DAC0REFEN_bm; - DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; - DAC0.DATA = 255; // set the output voltage + mcu_set_dac_vref(V05); // boot at lowest Vref setting + VREF.CTRLB |= VREF_DAC0REFEN_bm; // enable DAC Vref + DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; // enable DAC + DAC_LVL = 0; // turn off output at boot } diff --git a/hw/thefreeman/lin16dac/anduril.h b/hw/thefreeman/lin16dac/anduril.h index 8ca8b9f0..8f9d6e4f 100644 --- a/hw/thefreeman/lin16dac/anduril.h +++ b/hw/thefreeman/lin16dac/anduril.h @@ -3,7 +3,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later #pragma once -#include "thefreeman/lin16dac/hwdef.h" +#define HWDEF_H thefreeman/lin16dac/hwdef.h // the button lights up #define USE_INDICATOR_LED @@ -24,15 +24,17 @@ // PWM1: DAC Data // FIXME: ramp stalls with 8 duplicate levels in a row // (maybe use 1.1V Vref during that part of the ramp?) -#define PWM1_LEVELS 25, 25, 33, 41, 41, 50, 58, 66, 75, 83, 92,108,117,133,150,167,192,209,234, \ - 58, 64, 71, 80, 90, 99,110,121,134,149,163,180,198,218,241, \ - 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 23, 25, 26, 28, 30, 32, 34, 36, 39, 41, 44, 47, 50, 53, 56, 59, 63, 67, 71, 75, 79, 84, 89, 94,100,105,112,118,124,131,139,146,154,163,172,181,191,201,212,223,234,246, \ - 57, 60, 63, 66, 69, 73, 76, 80, 84, 88, 93, 97,102,107,112,117,123,129,135,141,147,154,161,169,176,184,193,201,210,220,229,239,250,255 -// PWM Tops: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) -#define PWM_TOPS 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, \ - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, \ - 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 +#define PWM1_LEVELS \ + 25, 25, 33, 41, 41, 50, 58, 66, 75, 83, 92,108,117,133,150,167,192,209,234, \ + 58, 64, 71, 80, 90, 99,110,121,134,149,163,180,198,218,241, \ + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 13, 14, 15, 16, 18, 19, 20, 22, 23, 25, 26, 28, 30, 32, 34, 36, 39, 41, 44, 47, 50, 53, 56, 59, 63, 67, 71, 75, 79, 84, 89, 94,100,105,112,118,124,131,139,146,154,163,172,181,191,201,212,223,234,246, \ + 57, 60, 63, 66, 69, 73, 76, 80, 84, 88, 93, 97,102,107,112,117,123,129,135,141,147,154,161,169,176,184,193,201,210,220,229,239,250,255 +// PWM2: VREF selector (0.55V=16,1.1V=17, 2.5V=18, 4.3V=19, 1.5V=20) +#define PWM2_LEVELS \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25, \ + V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05,V05, \ + V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25,V25 #define MAX_1x7135 34 #define HDR_ENABLE_LEVEL_MIN 35 // bottom level of top half of the ramp diff --git a/hw/thefreeman/lin16dac/hwdef.c b/hw/thefreeman/lin16dac/hwdef.c index 191444ee..89700d7d 100644 --- a/hw/thefreeman/lin16dac/hwdef.c +++ b/hw/thefreeman/lin16dac/hwdef.c @@ -22,7 +22,7 @@ Channel channels[] = { void set_level_zero() { DAC_LVL = 0; // DAC off - DAC_VREF = V055; // low Vref + mcu_set_dac_vref(V055); // low Vref HDR_ENABLE_PORT &= ~(1 << HDR_ENABLE_PIN); // HDR off // prevent post-off flash @@ -50,8 +50,8 @@ void set_level_main(uint8_t level) { OPAMP_ENABLE_PORT |= (1 << OPAMP_ENABLE_PIN); // pre-load ramp data so it can be assigned faster later - PWM_DATATYPE dac_lvl = PWM_GET(pwm1_levels, level); - PWM_DATATYPE dac_vref = PWM_GET(pwm_tops, level); + PWM1_DATATYPE dac_lvl = PWM1_GET(level); + PWM2_DATATYPE dac_vref = PWM2_GET(level); // enable HDR on top half of ramp if (level >= (HDR_ENABLE_LEVEL_MIN-1)) @@ -69,7 +69,8 @@ void set_level_main(uint8_t level) { // set these in successive clock cycles to avoid getting out of sync // (minimizes ramp bumps when changing gears) DAC_LVL = dac_lvl; - DAC_VREF = dac_vref; + mcu_set_dac_vref(dac_vref); + } bool gradual_tick_main(uint8_t gt) { @@ -77,11 +78,11 @@ bool gradual_tick_main(uint8_t gt) { // otherwise, simply jump to the next ramp level // and let set_level() handle any gear changes - PWM_DATATYPE dac_next = PWM_GET(pwm1_levels, gt); - PWM_DATATYPE vref_next = PWM_GET(pwm_tops, gt); + PWM1_DATATYPE dac_next = PWM1_GET(gt); + PWM2_DATATYPE vref_next = PWM2_GET(gt); // different gear = full adjustment - if (vref_next != DAC_VREF) return true; // let parent set_level() for us + if (vref_next != (DAC_VREF & VREF_DAC0REFSEL_gm)) return true; // let parent set_level() for us // same gear = small adjustment GRADUAL_ADJUST_SIMPLE(dac_next, DAC_LVL); diff --git a/hw/thefreeman/lin16dac/hwdef.h b/hw/thefreeman/lin16dac/hwdef.h index dc4377a6..a68d9c2b 100644 --- a/hw/thefreeman/lin16dac/hwdef.h +++ b/hw/thefreeman/lin16dac/hwdef.h @@ -32,24 +32,16 @@ enum CHANNEL_MODES { #define CHANNEL_MODES_ENABLED 0b0000000000000001 -#define PWM_CHANNELS 1 // old, remove this - #define PWM_BITS 8 // 8-bit DAC -#define PWM_GET PWM_GET8 #define PWM_DATATYPE uint8_t #define PWM_DATATYPE2 uint16_t // only needs 32-bit if ramp values go over 255 #define PWM1_DATATYPE uint8_t // main LED ramp +#define PWM1_GET(l) PWM_GET8(pwm1_levels, l) +#define PWM2_DATATYPE uint8_t // DAC Vref table +#define PWM2_GET(l) PWM_GET8(pwm2_levels, l) // main LED outputs -#define DAC_LVL DAC0.DATA // 0 to 255, for 0V to Vref -#define DAC_VREF VREF.CTRLA // 0.55V or 2.5V -#define PWM_TOP_INIT 255 // highest value used in top half of ramp (unused?) -// Vref values -#define V055 16 -#define V11 17 -#define V25 18 -#define V43 19 -#define V15 20 +// (DAC_LVL + DAC_VREF + Vref values are defined in arch/*.h) // Opamp enable // For turning on and off the op-amp @@ -84,11 +76,9 @@ enum CHANNEL_MODES { inline void hwdef_setup() { - // set up the system clock to run at 10 MHz instead of the default 3.33 MHz - // (it'll get underclocked to 2.5 MHz later) - // TODO: maybe run even slower? - _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, - CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm ); + // TODO: for this DAC controlled-light, try to decrease the clock speed + // to reduce overall system power + mcu_clock_speed(); VPORTA.DIR = PIN6_bm // DAC | PIN7_bm; // Opamp @@ -121,11 +111,10 @@ inline void hwdef_setup() { // set up the DAC // https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny1614-16-17-DataSheet-DS40002204A.pdf // DAC ranges from 0V to (255 * Vref) / 256 - // also VREF_DAC0REFSEL_0V55_gc and VREF_DAC0REFSEL_1V1_gc and VREF_DAC0REFSEL_2V5_gc - VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc; - VREF.CTRLB |= VREF_DAC0REFEN_bm; - DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; - DAC0.DATA = 255; // set the output voltage + mcu_set_dac_vref(V05); // boot at lowest Vref setting + VREF.CTRLB |= VREF_DAC0REFEN_bm; // enable DAC Vref + DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm; // enable DAC + DAC_LVL = 0; // turn off output at boot } From 1b6f40863b4f08365e39236496d687ab7806ed11 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Nov 2023 07:31:56 -0700 Subject: [PATCH 19/57] fixed ADC on attiny1634 and related builds --- arch/attiny1634.c | 129 +++++++++++++++++++++++----- arch/attiny1634.h | 40 ++++++--- hw/hank/emisar-2ch/fet/hwdef.h | 30 +------ hw/hank/emisar-2ch/hwdef.h | 30 +------ hw/hank/emisar-d4k-3ch/hwdef.h | 30 +------ hw/hank/noctigon-dm11/boost/hwdef.h | 30 +------ hw/hank/noctigon-dm11/hwdef.h | 30 +------ hw/hank/noctigon-k1/boost/hwdef.h | 30 +------ hw/hank/noctigon-k1/hwdef.h | 30 +------ hw/hank/noctigon-k1/sbt90/hwdef.h | 31 +------ hw/hank/noctigon-kr4/hwdef.h | 30 +------ hw/hank/noctigon-m44/hwdef.h | 30 +------ hw/hank/vdivider-1634.h | 39 +++++++++ 13 files changed, 181 insertions(+), 328 deletions(-) create mode 100644 hw/hank/vdivider-1634.h diff --git a/arch/attiny1634.c b/arch/attiny1634.c index 0737a810..e29d1c3e 100644 --- a/arch/attiny1634.c +++ b/arch/attiny1634.c @@ -7,14 +7,26 @@ ////////// clock speed / delay stuff ////////// +inline void mcu_clock_speed() { + // TODO? + // (or not; clock speed is set by the fuses) + // attiny1634 datasheet 6.5 + // CLKSR = [OSCRDY, CSTR, CKOUT_IO, SUT, CKSEL3/2/1/0] + // default 8MHz calibrated internal clock: SUT=0, CKSEL=0b0010 + #if 0 + cli(); + CCP = 0xD8; + CLKSR = 0b01000010; + CCP = 0xD8; + CLKPR = 0; // CLK / 1 = full speed, 8 MHz + sei(); + #endif +} + ///// clock dividers -// make it a NOP for now -// FIXME -//#define clock_prescale_set(x) ((void)0) -//#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();} -//#define clock_prescale_set(n) {cli(); CCP = 0xD8; CLKPR = n; sei();} inline void clock_prescale_set(uint8_t n) { cli(); + // _PROTECTED_WRITE(CLKPR, n); CCP = 0xD8; CLKPR = n; sei(); @@ -26,15 +38,33 @@ inline void clock_prescale_set(uint8_t n) { ////////// ADC voltage / temperature ////////// inline void mcu_set_admux_therm() { + // put the ADC in temperature mode + // DS table 19-3, 19-4, internal sensor / 1.1V ref + // [refs1, refs0, refen, adc0en, mux3, mux2, mux1, mux0] + // refs=0b10 : internal 1.1V ref + // mux=0b1110 : internal temperature sensor + //#define ADMUX_THERM 0b10001110 ADMUX = ADMUX_THERM; + // other stuff is already set, so no need to re-set it } inline void mcu_set_admux_voltage() { + // put the ADC in battery voltage measurement mode + // TODO: avr datasheet references #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 ADMUX = ADMUX_VOLTAGE_DIVIDER; + // disable digital input on divider pin to reduce power consumption + // TODO: this should be in hwdef init, not here + VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); #else // VCC / 1.1V reference ADMUX = ADMUX_VCC; + // disable digital input on VCC pin to reduce power consumption + //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin #endif + //ACSRA |= (1 << ACD); // turn off analog comparator to save power + // ADCSRB: [VDEN, VDPD, -, -, ADLAR, ADTS2, ADTS1, ADTS0] + ADCSRB = (1 << ADLAR); // left-adjust, free-running + //ADCSRB = 0; // right-adjust, free-running } inline void mcu_adc_sleep_mode() { @@ -42,31 +72,82 @@ inline void mcu_adc_sleep_mode() { } inline void mcu_adc_start_measurement() { - ADCSRA |= (1 << ADSC) | (1 << ADIE); -} - -inline void mcu_adc_on() { - hwdef_set_admux_voltage(); - #ifdef USE_VOLTAGE_DIVIDER - // disable digital input on divider pin to reduce power consumption - VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); - #else - // disable digital input on VCC pin to reduce power consumption - //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin - #endif - //ACSRA |= (1 << ACD); // turn off analog comparator to save power - ADCSRB |= (1 << ADLAR); // left-adjust flag is here instead of ADMUX - // enable, start, auto-retrigger, prescale - ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL; + // [ADEN, ADSC, ADATE, adif, ADIE, ADPS2, ADPS1, ADPS0] + ADCSRA = (1 << ADEN) // enable + | (1 << ADSC) // start + | (1 << ADATE) // auto-retrigger + | (1 << ADIE) // interrupt enable + | ADC_PRSCL; // prescale } inline void mcu_adc_off() { ADCSRA &= ~(1<> 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.1 * 4096) / (measurement >> 4); + #endif + return vbat40; +} -inline uint8_t mcu_adc_lsb() { return (ADCL >> 6) + (ADCH << 2); } + +#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 left-aligned) + // Out: Kelvin << 6 + // Precision: 1/64th Kelvin (but noisy) + // attiny1634 datasheet section 19.12 + // nothing to do; input value is already "cooked" + return measurement; +} + +inline uint8_t mcu_adc_lsb() { + // left-adjusted mode: + return (ADCL >> 6) + (ADCH << 2); + // right-adjusted mode: + // datasheet 19.13.3.2: + // "When ADCL is read, the ADC Data Register is not updated + // until ADCH is read. ... ADCL must be read first, then ADCH." + // So... gotta read it even if not needed? + // (the value doesn't matter here, the lower bits are only used + // for generating some random seed data) + //return ADCL + ADCH; +} ////////// WDT ////////// @@ -85,6 +166,7 @@ inline void mcu_wdt_stop() { cli(); // needed because CCP, below wdt_reset(); // Reset the WDT MCUSR &= ~(1< Date: Mon, 27 Nov 2023 08:47:37 -0700 Subject: [PATCH 20/57] fixed ADC on attiny85 and related builds (also enabled smooth steps on BLF GT, but had to remove stuff to make room) --- arch/attiny85.c | 67 ++++++++++++++++++++++++++++-------- arch/attiny85.h | 13 ++++--- hw/lumintop/blf-gt/anduril.h | 7 ++++ hw/lumintop/blf-gt/hwdef.h | 8 +++-- hw/mateminco/mf01s/hwdef.h | 8 +++-- 5 files changed, 80 insertions(+), 23 deletions(-) diff --git a/arch/attiny85.c b/arch/attiny85.c index 0d2d7feb..9e298cc0 100644 --- a/arch/attiny85.c +++ b/arch/attiny85.c @@ -64,14 +64,21 @@ static inline void hwdef_setup() { ////////// ADC voltage / temperature ////////// inline void mcu_set_admux_therm() { + // put the ADC in temperature mode ADMUX = ADMUX_THERM | (1 << ADLAR); } inline void mcu_set_admux_voltage() { + // put the ADC in battery voltage measurement mode + // TODO: avr datasheet references #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 ADMUX = ADMUX_VOLTAGE_DIVIDER | (1 << ADLAR); + // disable digital input on divider pin to reduce power consumption + VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); #else // VCC / 1.1V reference ADMUX = ADMUX_VCC | (1 << ADLAR); + // disable digital input on VCC pin to reduce power consumption + //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin #endif } @@ -80,29 +87,59 @@ inline void mcu_adc_sleep_mode() { } inline void mcu_adc_start_measurement() { - ADCSRA |= (1 << ADSC) | (1 << ADIE); -} - -inline void mcu_adc_on() { - hwdef_set_admux_voltage(); - #ifdef USE_VOLTAGE_DIVIDER - // disable digital input on divider pin to reduce power consumption - VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); - #else - // disable digital input on VCC pin to reduce power consumption - //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin - #endif - // enable, start, auto-retrigger, prescale - ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL; + ADCSRA = (1 << ADEN) // enable + | (1 << ADSC) // start + | (1 << ADATE) // auto-retrigger + | (1 << ADIE) // interrupt enable + | ADC_PRSCL; // prescale } inline void mcu_adc_off() { ADCSRA &= ~(1<> 6) + (ADCH << 2); } +inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement) { + // In : 65535 * 1.1 / Vbat + // Out: uint8_t: Vbat * 40 + // 1.1 = ADC Vref + // 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.1 * 1024) / (measurement >> 6); + return vbat40; +} + + +#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 left-aligned) + // Out: Kelvin << 6 + // Precision: 1/64th Kelvin (but noisy) + // attiny1634 datasheet section 19.12 + // nothing to do; input value is already "cooked" + return measurement; +} + +inline uint8_t mcu_adc_lsb() { + // left-adjusted mode: + return (ADCL >> 6) + (ADCH << 2); +} ////////// WDT ////////// diff --git a/arch/attiny85.h b/arch/attiny85.h index 2753fd75..3f6ffcbf 100644 --- a/arch/attiny85.h +++ b/arch/attiny85.h @@ -21,8 +21,6 @@ ////////// default hw_setup() ////////// -// FIXME: fsm/main should call hwdef_setup(), not hw_setup, -// and this function should be hwdef_setup #ifdef USE_GENERIC_HWDEF_SETUP static inline void hwdef_setup(); #endif @@ -48,8 +46,6 @@ inline void mcu_adc_sleep_mode(); inline void mcu_adc_start_measurement(); -inline void mcu_adc_on(); - inline void mcu_adc_off(); // NOP because interrupt flag clears itself @@ -57,6 +53,15 @@ inline void mcu_adc_off(); inline uint16_t mcu_adc_result(); +// 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/hw/lumintop/blf-gt/anduril.h b/hw/lumintop/blf-gt/anduril.h index 2fc359e5..cc2f9406 100644 --- a/hw/lumintop/blf-gt/anduril.h +++ b/hw/lumintop/blf-gt/anduril.h @@ -54,7 +54,14 @@ #undef BLINK_AT_RAMP_MIDDLE #undef BLINK_AT_RAMP_FLOOR +#define USE_SMOOTH_STEPS + // too big, turn off extra features //#undef USE_TACTICAL_MODE #undef USE_SOS_MODE +#undef USE_BEACON_MODE +#undef USE_RAMP_AFTER_MOON_CONFIG +//#undef USE_RAMP_SPEED_CONFIG +//#undef USE_VOLTAGE_CORRECTION +#undef USE_2C_STYLE_CONFIG diff --git a/hw/lumintop/blf-gt/hwdef.h b/hw/lumintop/blf-gt/hwdef.h index dbaf18e3..68197acb 100644 --- a/hw/lumintop/blf-gt/hwdef.h +++ b/hw/lumintop/blf-gt/hwdef.h @@ -67,14 +67,18 @@ enum CHANNEL_MODES { //#define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | (1 << ADLAR) | VOLTAGE_CHANNEL) // 1.1V reference, no left-adjust, ADC1/PB2 #define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | VOLTAGE_CHANNEL) + +#undef voltage_raw2cooked +#define voltage_raw2cooked mcu_vdivider_raw2cooked + #define ADC_PRSCL 0x07 // clk/128 // Raw ADC readings at 4.4V and 2.2V (in-between, we assume values form a straight line) #ifndef ADC_44 -#define ADC_44 (184*4) +#define ADC_44 (184*4*4) #endif #ifndef ADC_22 -#define ADC_22 (92*4) +#define ADC_22 (92*4*4) #endif #define FAST 0xA3 // fast PWM both channels diff --git a/hw/mateminco/mf01s/hwdef.h b/hw/mateminco/mf01s/hwdef.h index fef50505..21ea1fd3 100644 --- a/hw/mateminco/mf01s/hwdef.h +++ b/hw/mateminco/mf01s/hwdef.h @@ -67,14 +67,18 @@ enum CHANNEL_MODES { // 1.1V reference, no left-adjust, ADC1/PB2 #define ADMUX_VOLTAGE_DIVIDER ((1 << V_REF) | VOLTAGE_CHANNEL) #endif + +#undef voltage_raw2cooked +#define voltage_raw2cooked mcu_vdivider_raw2cooked + #define ADC_PRSCL 0x07 // clk/128 // Raw ADC readings at 4.4V and 2.2V (in-between, we assume values form a straight line) #ifndef ADC_44 -#define ADC_44 (234*4) +#define ADC_44 (234*4*4) #endif #ifndef ADC_22 -#define ADC_22 (117*4) +#define ADC_22 (117*4*4) #endif #define FAST 0xA3 // fast PWM both channels From c86ab86da7763e4d88c2c6865f916873af02742d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Nov 2023 09:00:32 -0700 Subject: [PATCH 21/57] fixed ADC on sp10-pro --- hw/sofirn/sp10-pro/hwdef.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/sofirn/sp10-pro/hwdef.h b/hw/sofirn/sp10-pro/hwdef.h index 047758b2..f220318f 100644 --- a/hw/sofirn/sp10-pro/hwdef.h +++ b/hw/sofirn/sp10-pro/hwdef.h @@ -66,16 +66,19 @@ enum CHANNEL_MODES { #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 +#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) // Resistors are 300,000 and 100,000 #ifndef ADC_44 -#define ADC_44 1023 // raw value at 4.40V +#define ADC_44 (4*1023) // raw value at 4.40V #endif #ifndef ADC_22 -#define ADC_22 512 // raw value at 2.20V +#define ADC_22 (4*512) // raw value at 2.20V #endif From 62e9337211eea3583daa24e84ce9fda5db5a35e7 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Nov 2023 14:45:00 -0700 Subject: [PATCH 22/57] fw3x: fixed swapped red+blue, fixed battery measurements, added police color strobe --- hw/lumintop/fw3x-lume1/anduril.h | 27 ++++++++++++++++++++------- hw/lumintop/fw3x-lume1/hwdef.h | 15 +++++++++------ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/hw/lumintop/fw3x-lume1/anduril.h b/hw/lumintop/fw3x-lume1/anduril.h index b208fbc9..5cde5e9e 100644 --- a/hw/lumintop/fw3x-lume1/anduril.h +++ b/hw/lumintop/fw3x-lume1/anduril.h @@ -11,7 +11,7 @@ * - 85: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf */ -#include "lumintop/fw3x-lume1/hwdef.h" +#define HWDEF_H lumintop/fw3x-lume1/hwdef.h // set this light for 50C thermal ceiling #undef DEFAULT_THERM_CEIL @@ -46,11 +46,6 @@ #undef USE_DYNAMIC_UNDERCLOCKING #endif -// the entire ramp is regulated except turbo; don't blink halfway up -#ifdef BLINK_AT_RAMP_MIDDLE -#undef BLINK_AT_RAMP_MIDDLE -#endif - #define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 149 // turn on BuckBoost from level 1 to 149, but not 150 @@ -59,21 +54,39 @@ #define LED_ENABLE_PIN_LEVEL_MAX 149 // 10 33 56 79 102 125 [149] #define RAMP_DISCRETE_FLOOR 10 -#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL +#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL #define RAMP_DISCRETE_STEPS 7 #define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR #define SIMPLE_UI_CEIL 120 #define SIMPLE_UI_STEPS 5 +// show each channel while it scroll by in the menu +#define USE_CONFIG_COLORS + +// blink numbers on the main LEDs by default (but allow user to change it) +#define DEFAULT_BLINK_CHANNEL CM_MAIN + // slow down party strobe; this driver can't pulse for too short a time #define PARTY_STROBE_ONTIME 4 +// use aux red + aux blue for police strobe +#define USE_POLICE_COLOR_STROBE_MODE +#define POLICE_STROBE_USES_AUX +#define POLICE_COLOR_STROBE_CH1 CM_AUXRED +#define POLICE_COLOR_STROBE_CH2 CM_AUXBLU + // stop panicking at ~85% regulated power or ~750 lm #define THERM_FASTER_LEVEL 140 #define THERM_CAL_OFFSET 0 // not needed due to external sensor +// don't blink while ramping +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + + // can't reset the normal way because power is connected before the button #define USE_SOFT_FACTORY_RESET diff --git a/hw/lumintop/fw3x-lume1/hwdef.h b/hw/lumintop/fw3x-lume1/hwdef.h index ca412cc9..e50d8b1b 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.h +++ b/hw/lumintop/fw3x-lume1/hwdef.h @@ -8,9 +8,9 @@ * * Pin / Name / Function in Lume1 Rev B * 1 PA6 Regulated PWM (PWM1B) - * 2 PA5 R: red aux LED (PWM0B) + * 2 PA5 B: blue aux LED (PWM0B) * 3 PA4 G: green aux LED - * 4 PA3 B: blue aux LED + * 4 PA3 R: red aux LED * 5 PA2 e-switch (PCINT2) * 6 PA1 Jumper 1 * 7 PA0 Jumper 2 @@ -111,16 +111,19 @@ enum CHANNEL_MODES { #define ADMUX_VOLTAGE_DIVIDER 0b00000101 #define ADC_PRSCL 0x06 // clk/64 +#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: // [(Vbatt)*(R2/(R2+R1)) / 2.5V] * 1023 // R1 = R2 = 100kR #ifndef ADC_44 -#define ADC_44 900 +#define ADC_44 (4*900) #endif #ifndef ADC_22 -#define ADC_22 450 +#define ADC_22 (4*450) #endif // Default ADMUX_THERM for Temperature is: 0b10001110 in arch/mcu.h @@ -139,9 +142,9 @@ enum CHANNEL_MODES { #define EXTERN_TEMP_FORMULA(m) (((m)-205)/4.09) // this driver allows for aux LEDs under the optic -#define AUXLED_R_PIN PA5 // pin 2 +#define AUXLED_R_PIN PA3 // pin 2 #define AUXLED_G_PIN PA4 // pin 3 -#define AUXLED_B_PIN PA3 // pin 4 +#define AUXLED_B_PIN PA5 // pin 4 #define AUXLED_RGB_PORT PORTA // PORTA or PORTB or PORTC #define AUXLED_RGB_DDR DDRA // DDRA or DDRB or DDRC #define AUXLED_RGB_PUE PUEA // PUEA or PUEB or PUEC From 6cb18249d33f57acaf8e78734f4d155ebfd72165 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 27 Nov 2023 16:08:11 -0700 Subject: [PATCH 23/57] FW3X: multiple upgrades... - upgraded to DSM: lower lows, *much* smoother ramp - made lows more efficient with underclocking - fixed party strobe being too blurry - calibrated UI speed / bogomips multiplier - added readme to document this hardware's multiple quirks --- hw/lumintop/fw3x-lume1/README.md | 26 ++++++++++++ hw/lumintop/fw3x-lume1/anduril.h | 32 +++++---------- hw/lumintop/fw3x-lume1/hwdef.c | 68 +++++++++++++++++++++++++++----- hw/lumintop/fw3x-lume1/hwdef.h | 60 +++++++++++++++++----------- 4 files changed, 132 insertions(+), 54 deletions(-) create mode 100644 hw/lumintop/fw3x-lume1/README.md diff --git a/hw/lumintop/fw3x-lume1/README.md b/hw/lumintop/fw3x-lume1/README.md new file mode 100644 index 00000000..8609c499 --- /dev/null +++ b/hw/lumintop/fw3x-lume1/README.md @@ -0,0 +1,26 @@ +# Lumintop FW3X Lume1 + +A BLF FW3A with a new driver from LoneOceans. The new driver adds efficient +constant-current power regulation, RGB aux LEDs, and an upgraded temperature +sensor. + +## Notes of interest + +**Flashing firmware**: The MOSI and MISO pin are swapped, compared to a Hanklight. +LoneOceans sent a fixed driver design to Lumintop, but the new design didn't +get produced. So to flash firmware, swap the wires for those two pins first. + +**RGB mixup**: Lumintop seems to have swapped the wires for aux R and aux B. +This was fixed in firmware in 2023-12, but some lights were fixed in hardware +before that, so the firmware fix might cause the colors to be swapped again. + +**Turbo**: The driver uses regulation for levels 1 to 149, and level 150 is a +direct-drive FET. This is by design, and the FET cannot be ramped smoothly up +and down. Turbo is a single level at the top of the ramp, with a big sudden +drop to the next level. + +**Moon**: This light has a pretty bright preflash at moon level, and the +output is unstable so there is very visible ripple. The user can either raise +the ramp floor to a level high enough to avoid these issues, or learn to live +with the ripple and preflash. + diff --git a/hw/lumintop/fw3x-lume1/anduril.h b/hw/lumintop/fw3x-lume1/anduril.h index 5cde5e9e..b7dbc823 100644 --- a/hw/lumintop/fw3x-lume1/anduril.h +++ b/hw/lumintop/fw3x-lume1/anduril.h @@ -8,7 +8,6 @@ * For more information: www.loneoceans.com/labs/ * Datasheets: * - 1634: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8303-8-bit-AVR-Microcontroller-tinyAVR-ATtiny1634_Datasheet.pdf - * - 85: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf */ #define HWDEF_H lumintop/fw3x-lume1/hwdef.h @@ -20,38 +19,25 @@ // this light has three aux LED channels: R, G, B #define USE_AUX_RGB_LEDS -// it has no independent LED in the button unlike emisar d4 -//#define USE_BUTTON_LED - // the aux LEDs are front-facing, so turn them off while main LEDs are on #ifdef USE_INDICATOR_LED_WHILE_RAMPING #undef USE_INDICATOR_LED_WHILE_RAMPING #endif -// ../../bin/level_calc.py cube 1 149 7135 0 0.5 1000, with 0 appended to the end. -// for FET PWM (PWM2), all values are 0, except for last value of 1023 -// (with max_pwm set to 1023) #define RAMP_SIZE 150 -//#define PWM1_LEVELS 0,0,0,0,1,1,1,1,2,2,2,3,3,4,4,5,5,6,7,7,8,9,10,11,12,13,14,15,16,17,19,20,22,23,25,26,28,30,32,34,36,38,40,42,45,47,49,52,55,58,60,63,66,70,73,76,80,83,87,91,94,98,102,107,111,115,120,124,129,134,139,144,150,155,160,166,172,178,184,190,196,203,209,216,223,230,237,244,252,259,267,275,283,291,299,308,316,325,334,343,353,362,372,382,392,402,412,423,433,444,455,466,478,489,501,513,525,538,550,563,576,589,602,616,630,644,658,672,687,701,716,731,747,762,778,794,810,827,844,861,878,895,913,930,948,967,985,1004,1023,0 -#define PWM1_LEVELS 1,1,1,1,2,2,2,2,3,3,3,4,4,5,5,6,6,7,8,8,9,10,11,12,13,14,15,16,17,18,20,21,23,24,26,27,29,31,33,35,37,39,41,43,45,48,50,53,56,58,61,64,67,70,74,77,80,84,88,91,95,99,103,108,112,116,121,125,130,135,140,145,150,156,161,167,173,178,184,191,197,203,210,217,223,230,238,245,252,260,268,275,283,292,300,308,317,326,335,344,353,363,372,382,392,402,413,423,434,445,456,467,478,490,502,514,526,538,551,563,576,589,603,616,630,644,658,672,687,702,717,732,747,763,778,794,811,827,844,861,878,895,913,931,949,967,985,1004,1023,0 -#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1023 + +// level_calc.py 5.01 1 149 7135 0 0.2 2000 --pwm 32640 +// regulated channel: 16-bit PWM+DSM for low lows and very smooth ramp +#define PWM1_LEVELS 0,1,2,3,4,5,6,7,9,10,12,14,17,19,22,25,29,33,37,41,46,51,57,63,70,77,85,93,103,112,123,134,146,159,172,187,203,219,237,256,276,297,319,343,368,394,422,452,483,516,551,587,625,666,708,753,799,848,900,954,1010,1069,1131,1195,1263,1333,1407,1483,1563,1647,1734,1825,1919,2017,2119,2226,2336,2451,2571,2694,2823,2957,3095,3239,3388,3542,3702,3868,4040,4217,4401,4591,4788,4992,5202,5419,5644,5876,6115,6362,6617,6880,7152,7432,7721,8018,8325,8641,8967,9302,9647,10003,10369,10745,11133,11531,11941,12363,12796,13241,13699,14169,14652,15148,15657,16180,16717,17268,17834,18414,19009,19620,20246,20888,21546,22221,22913,23621,24348,25091,25853,26634,27433,28251,29089,29946,30823,31721,32640,0 +// DD FET: 8-bit PWM (but hardware can only handle 0 and MAX) +#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255 #define DEFAULT_LEVEL 56 #define MAX_1x7135 149 -// TODO: test if underclocking works on lume1 -//#define HALFSPEED_LEVEL 14 -//#define QUARTERSPEED_LEVEL 5 -// don't slow down at low levels; this isn't that sort of light -// (it needs to stay at full speed for the 10-bit PWM to work) -#ifdef USE_DYNAMIC_UNDERCLOCKING -#undef USE_DYNAMIC_UNDERCLOCKING -#endif +#define HALFSPEED_LEVEL 21 +#define QUARTERSPEED_LEVEL 11 #define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 149 -// turn on BuckBoost from level 1 to 149, but not 150 -// Level 150 is when BuckBoost is off and FET is ON 100% -#define LED_ENABLE_PIN_LEVEL_MIN 1 -#define LED_ENABLE_PIN_LEVEL_MAX 149 // 10 33 56 79 102 125 [149] #define RAMP_DISCRETE_FLOOR 10 #define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL @@ -68,7 +54,7 @@ #define DEFAULT_BLINK_CHANNEL CM_MAIN // slow down party strobe; this driver can't pulse for too short a time -#define PARTY_STROBE_ONTIME 4 +#define PARTY_STROBE_ONTIME 1 // use aux red + aux blue for police strobe #define USE_POLICE_COLOR_STROBE_MODE diff --git a/hw/lumintop/fw3x-lume1/hwdef.c b/hw/lumintop/fw3x-lume1/hwdef.c index 71cd7990..0a8a62ed 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.c +++ b/hw/lumintop/fw3x-lume1/hwdef.c @@ -1,10 +1,11 @@ -// FW3X Lume1 PWM helper functions +// FW3X Lume1 helper functions // Copyright (C) 2023 Selene ToyKeeper // SPDX-License-Identifier: GPL-3.0-or-later #pragma once #include "fsm/chan-rgbaux.c" + void set_level_zero(); void set_level_main(uint8_t level); @@ -21,6 +22,12 @@ Channel channels[] = { void set_level_zero() { + // disable timer overflow interrupt + // (helps improve button press handling from Off state) + DSM_INTCTRL &= ~DSM_OVF_bm; + + // turn off all LEDs + ch1_dsm_lvl = 0; CH1_PWM = 0; CH2_PWM = 0; PWM_CNT = 0; // reset phase @@ -29,19 +36,49 @@ void set_level_zero() { // single set of LEDs with 2 stacked power channels, regulated + DD FET void set_level_main(uint8_t level) { - CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN); // enable regulator + if (level == actual_level - 1) return; // prevent flicker on no-op - PWM_DATATYPE ch1_pwm = PWM_GET(pwm1_levels, level); - PWM_DATATYPE ch2_pwm = PWM_GET(pwm2_levels, level); + PWM1_DATATYPE ch1 = PWM1_GET(level); + PWM2_DATATYPE ch2 = PWM2_GET(level); - CH1_PWM = ch1_pwm; - CH2_PWM = ch2_pwm; + // set delta-sigma soft levels + ch1_dsm_lvl = ch1; + + // set hardware PWM levels and init dsm loop + CH1_PWM = ch1_pwm = ch1 >> 7; + CH2_PWM = ch2; + + // enable timer overflow interrupt so DSM can work + DSM_INTCTRL |= DSM_OVF_bm; // force reset phase when turning on from zero // (for faster, more consistent initial response) if (! actual_level) PWM_CNT = 0; + + // don't enable ch1 and ch2 at the same time + if (ch2) CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable regulator + else CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN); // enable regulator +} + +// delta-sigma modulation of PWM outputs +// happens on each Timer overflow (every 512 cpu clock cycles) +// uses 8-bit pwm w/ 7-bit dsm (0b 0PPP PPPP PDDD DDDD) +ISR(DSM_vect) { + // set new hardware values first, + // for best timing (reduce effect of interrupt jitter) + CH1_PWM = ch1_pwm; + + // calculate next values, now that timing matters less + + // accumulate error + ch1_dsm += (ch1_dsm_lvl & 0x007f); + // next PWM = base PWM value + carry bit + ch1_pwm = (ch1_dsm_lvl >> 7) + (ch1_dsm > 0x7f); + // clear carry bit + ch1_dsm &= 0x7f; } + bool gradual_tick_main(uint8_t gt) { // 150/150 is full FET + zero regulated, // 149/150 is zero FET + full regulated, @@ -51,10 +88,23 @@ bool gradual_tick_main(uint8_t gt) { return true; } - PWM_DATATYPE pwm1 = PWM_GET(pwm1_levels, gt); - GRADUAL_ADJUST_SIMPLE(pwm1, CH1_PWM); + PWM1_DATATYPE ch1 = PWM1_GET(gt); - if (pwm1 == CH1_PWM) return true; // done + // adjust multiple times based on current brightness + // (so it adjusts faster/coarser when bright, slower/finer when dim) + + // higher shift = slower/finer adjustments + const uint8_t shift = 9; // ((255 << 7) >> 9) = 63 max + uint8_t steps; + + steps = ch1_dsm_lvl >> shift; + for (uint8_t i=0; i<=steps; i++) + GRADUAL_ADJUST_SIMPLE(ch1, ch1_dsm_lvl); + + if ((ch1 == ch1_dsm_lvl) + ) { + return true; // done + } return false; // not done yet } diff --git a/hw/lumintop/fw3x-lume1/hwdef.h b/hw/lumintop/fw3x-lume1/hwdef.h index e50d8b1b..bee98dbe 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.h +++ b/hw/lumintop/fw3x-lume1/hwdef.h @@ -8,9 +8,9 @@ * * Pin / Name / Function in Lume1 Rev B * 1 PA6 Regulated PWM (PWM1B) - * 2 PA5 B: blue aux LED (PWM0B) + * 2 PA5 B: blue aux LED (PWM0B) (or red) * 3 PA4 G: green aux LED - * 4 PA3 R: red aux LED + * 4 PA3 R: red aux LED (or blue) * 5 PA2 e-switch (PCINT2) * 6 PA1 Jumper 1 * 7 PA0 Jumper 2 @@ -54,29 +54,38 @@ enum CHANNEL_MODES { #define CHANNEL_MODES_ENABLED 0b0000000000000001 -#define PWM_CHANNELS 2 // old, remove this - -// Added for Lume1 Buck Boost Driver -#define PWM_BITS 16 // 0 to 1023 at 3.9 kHz, not 0 to 255 at 15.6 kHz -#define PWM_GET PWM_GET16 +#define PWM_BITS 16 // 0 to 32640 (0 to 255 PWM + 0 to 127 DSM) at constant kHz #define PWM_DATATYPE uint16_t #define PWM_DATATYPE2 uint32_t // only needs 32-bit if ramp values go over 255 #define PWM1_DATATYPE uint16_t // regulated ramp -#define PWM2_DATATYPE uint16_t // DD FET ramp +#define PWM1_GET(x) PWM_GET16(pwm1_levels, x) +#define PWM2_DATATYPE uint8_t // DD FET ramp +#define PWM2_GET(x) PWM_GET8(pwm2_levels, x) // PWM parameters of both channels are tied together because they share a counter #define PWM_TOP ICR1 // holds the TOP value for variable-resolution PWM -#define PWM_TOP_INIT 1023 -#define PWM_CNT TCNT1 // for dynamic PWM, reset phase +#define PWM_TOP_INIT 255 +#define PWM_CNT TCNT1 // for checking / resetting phase +// (max is (255 << 7), because it's 8-bit PWM plus 7 bits of DSM) +#define DSM_TOP (255<<7) // 15-bit resolution leaves 1 bit for carry + +// timer interrupt for DSM +#define DSM_vect TIMER1_OVF_vect +#define DSM_INTCTRL TIMSK +#define DSM_OVF_bm (1< Date: Tue, 28 Nov 2023 10:30:04 -0700 Subject: [PATCH 24/57] FW3X: fixed external temperature sensor (the MCU's internal sensor works too, but external is a bit better I guess?) --- hw/lumintop/fw3x-lume1/hwdef.c | 32 ++++++++++++++++++++++++++++++++ hw/lumintop/fw3x-lume1/hwdef.h | 16 +++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/hw/lumintop/fw3x-lume1/hwdef.c b/hw/lumintop/fw3x-lume1/hwdef.c index 0a8a62ed..791a0809 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.c +++ b/hw/lumintop/fw3x-lume1/hwdef.c @@ -108,3 +108,35 @@ bool gradual_tick_main(uint8_t gt) { return false; // not done yet } +////////// external temperature sensor ////////// + +void hwdef_set_admux_therm() { + // put the ADC in temperature mode + // ADCSRB: [VDEN, VDPD, -, -, ADLAR, ADTS2, ADTS1, ADTS0] + ADCSRB = (1 << ADLAR); // left-adjust, free-running + // DS table 19-3, 19-4 + // [refs1, refs0, refen, adc0en, mux3, mux2, mux1, mux0] + // refs=0b00 : VCC (2.5V) + // mux=0b1011 : ADC11 (pin PC2) + ADMUX = ADMUX_THERM_EXTERNAL_SENSOR; + // other stuff is already set, so no need to re-set it +} + +uint16_t temp_raw2cooked(uint16_t measurement) { + // In: (raw ADC average) << 6 + // Out: Kelvin << 6 + /* notes from old versions of the code... + // Used for Lume1 Driver: MCP9700 - T_Celsius = 100*(VOUT - 0.5V) + // ADC is 2.5V reference, 0 to 1023 + // due to floating point, this calculation takes 916 extra bytes + // (should use an integer equivalent instead) + //#define EXTERN_TEMP_FORMULA(m) (((m)-205)/4.09) + //int16_t celsius = (((measurement-205)/4.09)) + THERM_CAL_OFFSET + (int16_t)therm_cal_offset; + */ + + // this formula could probably be simplified... but meh, it works + uint16_t k6 = ((uint32_t)(measurement - (205 << 6)) * 100 / 409) + + (273 << 6); // convert back from C to K + return k6; +} + diff --git a/hw/lumintop/fw3x-lume1/hwdef.h b/hw/lumintop/fw3x-lume1/hwdef.h index bee98dbe..92a177fc 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.h +++ b/hw/lumintop/fw3x-lume1/hwdef.h @@ -142,13 +142,15 @@ uint8_t ch1_pwm, ch1_dsm; // Modified fsm-adc.c to use different ADMUX and ADC_temperature_handler() // based on USE_EXTERNAL_TEMP_SENSOR // See line 34 and line 209 -#define USE_EXTERNAL_TEMP_SENSOR -#define ADMUX_THERM_EXTERNAL_SENSOR 0b00001011 // VCC reference (2.5V), Channel PC2 -// Used for Lume1 Driver: MCP9700 - T_Celsius = 100*(VOUT - 0.5V) -// ADC is 2.5V reference, 0 to 1023 -// FIXME: due to floating point, this calculation takes 916 extra bytes -// (should use an integer equivalent instead) -#define EXTERN_TEMP_FORMULA(m) (((m)-205)/4.09) +//#define USE_EXTERNAL_TEMP_SENSOR + +// override the default temperature sensor code +#undef hwdef_set_admux_therm +void hwdef_set_admux_therm(); +#undef temp_raw2cooked +uint16_t temp_raw2cooked(uint16_t measurement); +// VCC reference (2.5V), Channel PC2 +#define ADMUX_THERM_EXTERNAL_SENSOR 0b00001011 // this driver allows for aux LEDs under the optic #define AUXLED_R_PIN PA3 // pin 2 From 04198bbe232cb8b4a86551da3c738a0fb2bc06f5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 28 Nov 2023 10:30:48 -0700 Subject: [PATCH 25/57] fsm/adc: removed dead code --- fsm/adc.c | 89 ++++++++++++++++++++----------------------------------- 1 file changed, 32 insertions(+), 57 deletions(-) diff --git a/fsm/adc.c b/fsm/adc.c index 97dfc934..93f9a1a6 100644 --- a/fsm/adc.c +++ b/fsm/adc.c @@ -218,42 +218,6 @@ static inline void ADC_voltage_handler() { #endif ; - /* - // calculate actual voltage: volts * 10 - // TODO: should be (volts * 40) for extra precision - voltage = (measurement + VOLTAGE_FUDGE_FACTOR - #ifdef USE_VOLTAGE_CORRECTION - + VOLT_CORR - 7 - #endif - ) >> 1; - */ - - #if 0 - // values stair-step between intervals of 64, with random variations - // of 1 or 2 in either direction, so if we chop off the last 6 bits - // it'll flap between N and N-1... but if we add half an interval, - // the values should be really stable after right-alignment - // (instead of 99.98, 100.00, and 100.02, it'll hit values like - // 100.48, 100.50, and 100.52... which are stable when truncated) - //measurement += 32; - //measurement = (measurement + 16) >> 5; - measurement = (measurement + 16) & 0xffe0; // 1111 1111 1110 0000 - - #ifdef USE_VOLTAGE_DIVIDER - voltage = calc_voltage_divider(measurement); - #else - // calculate actual voltage: volts * 10 - // ADC = 1.1 * 1024 / volts - // volts = 1.1 * 1024 / ADC - voltage = ((uint16_t)(2*1.1*1024*10)/(measurement>>6) - + VOLTAGE_FUDGE_FACTOR - #ifdef USE_VOLTAGE_CORRECTION - + VOLT_CORR - 7 - #endif - ) >> 1; - #endif - #endif - // if low, callback EV_voltage_low / EV_voltage_critical // (but only if it has been more than N seconds since last call) if (lvp_timer) { @@ -316,10 +280,17 @@ static inline void ADC_temperature_handler() { // 0 .. 65535 = 0 K .. 1024 K uint16_t measurement = temp_raw2cooked(adc_smooth[1]); + // let the UI see the current temperature in C // (Kelvin << 6) to Celsius + // Why 275? Because Atmel's docs use 275 instead of 273. temperature = (measurement>>6) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275; - #if 0 + // instead of (K << 6), use (K << 1) now + // TODO: use more precision, if it can be done without overflow in 16 bits + // (and still work on attiny85 without increasing ROM size) + #if 1 + measurement = measurement >> 5; + #else // TODO: is this still needed? // values stair-step between intervals of 64, with random variations // of 1 or 2 in either direction, so if we chop off the last 6 bits // it'll flap between N and N-1... but if we add half an interval, @@ -329,24 +300,7 @@ static inline void ADC_temperature_handler() { //measurement += 32; measurement = (measurement + 16) >> 5; //measurement = (measurement + 16) & 0xffe0; // 1111 1111 1110 0000 - - // let the UI see the current temperature in C - // Convert ADC units to Celsius (ish) - // FIXME: call something in arch/$mcu.h or hwdef.h - // instead of calculating this here - #ifndef USE_EXTERNAL_TEMP_SENSOR - // onboard sensor for attiny25/45/85/1634 - 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)TH_CAL; #endif - #endif - - // instead of (K << 6), use (K << 1) now - // TODO: use more precision, if it can be done without overflow in 16 bits - // (and still work on attiny85 without increasing ROM size) - measurement = measurement >> 5; // how much has the temperature changed between now and a few seconds ago? int16_t diff; @@ -440,17 +394,38 @@ static inline void ADC_temperature_handler() { #ifdef USE_BATTCHECK #ifdef BATTCHECK_4bars PROGMEM const uint8_t voltage_blinks[] = { - 4*30, 4*35, 4*38, 4*40, 4*42, 255, + 4*30, + 4*35, + 4*38, + 4*40, + 4*42, + 255, }; #endif #ifdef BATTCHECK_6bars PROGMEM const uint8_t voltage_blinks[] = { - 4*30, 4*34, 4*36, 4*38, 4*40, 4*41, 4*43, 255, + 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[] = { - 4*30, 4*33, 4*35, 4*37, 4*38, 4*39, 4*40, 4*41, 4*42, 255, + 4*30, + 4*33, + 4*35, + 4*37, + 4*38, + 4*39, + 4*40, + 4*41, + 4*42, + 255, }; #endif void battcheck() { From 56370218c5ca1b542a967e72b134f43a82f69ddc Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 28 Nov 2023 12:36:39 -0700 Subject: [PATCH 26/57] fixed incorrect temperature history for a few seconds after waking (it used raw ADC units instead of cooked Kelvin units ... ... which was only noticeable on hardware which has different ADC units) --- fsm/adc.c | 20 +++++++++----------- fsm/adc.h | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/fsm/adc.c b/fsm/adc.c index 93f9a1a6..fbe84a1f 100644 --- a/fsm/adc.c +++ b/fsm/adc.c @@ -166,7 +166,7 @@ void adc_deferred() { #ifdef USE_LVP -static inline void ADC_voltage_handler() { +static void ADC_voltage_handler() { // rate-limit low-voltage warnings to a max of 1 per N seconds static uint8_t lvp_timer = 0; #define LVP_TIMER_START (VOLTAGE_WARNING_SECONDS*ADC_CYCLES_PER_SECOND) // N seconds between LVP warnings @@ -240,7 +240,7 @@ static inline void ADC_voltage_handler() { #ifdef USE_THERMAL_REGULATION // generally happens once per second while awake -static inline void ADC_temperature_handler() { +static void ADC_temperature_handler() { // coarse adjustment #ifndef THERM_LOOKAHEAD #define THERM_LOOKAHEAD 4 @@ -265,15 +265,7 @@ static inline void ADC_temperature_handler() { static uint16_t temperature_history[NUM_TEMP_HISTORY_STEPS]; static int8_t warning_threshold = 0; - if (adc_reset) { // wipe out old data - // ignore average, use latest sample - uint16_t foo = adc_raw[1]; - adc_smooth[1] = foo; - - // forget any past measurements - for(uint8_t i=0; i> 5; - } + if (adc_reset) adc_smooth[1] = adc_raw[1]; // latest 16-bit ADC reading // convert raw ADC value to Kelvin << 6 @@ -302,6 +294,12 @@ static inline void ADC_temperature_handler() { //measurement = (measurement + 16) & 0xffe0; // 1111 1111 1110 0000 #endif + if (adc_reset) { // wipe out old data after waking up + // forget any past measurements + for(uint8_t i=0; i Date: Tue, 28 Nov 2023 12:40:16 -0700 Subject: [PATCH 27/57] fixed FW3X thermal regulation It had no minimum thermal stepdown defined, so it used MAX_7135 by default, which was level 149/150 ... thus virtually no regulation. I also made it easier to switch between internal and external temperature sensors by just commenting out a few lines in the hwdef.h. --- hw/lumintop/fw3x-lume1/anduril.h | 1 + hw/lumintop/fw3x-lume1/hwdef.c | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/lumintop/fw3x-lume1/anduril.h b/hw/lumintop/fw3x-lume1/anduril.h index b7dbc823..cd06c6a2 100644 --- a/hw/lumintop/fw3x-lume1/anduril.h +++ b/hw/lumintop/fw3x-lume1/anduril.h @@ -33,6 +33,7 @@ #define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255 #define DEFAULT_LEVEL 56 #define MAX_1x7135 149 +#define MIN_THERM_STEPDOWN 50 #define HALFSPEED_LEVEL 21 #define QUARTERSPEED_LEVEL 11 diff --git a/hw/lumintop/fw3x-lume1/hwdef.c b/hw/lumintop/fw3x-lume1/hwdef.c index 791a0809..306a58c9 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.c +++ b/hw/lumintop/fw3x-lume1/hwdef.c @@ -83,10 +83,8 @@ bool gradual_tick_main(uint8_t gt) { // 150/150 is full FET + zero regulated, // 149/150 is zero FET + full regulated, // so don't try to gradually adjust between - if ((RAMP_SIZE == actual_level) || (gt >= RAMP_SIZE-1)) { - set_level(gt + 1); - return true; - } + // if target is in the top 2 levels, just let the parent handle it + if (gt >= RAMP_SIZE-2) return true; PWM1_DATATYPE ch1 = PWM1_GET(gt); @@ -110,6 +108,8 @@ bool gradual_tick_main(uint8_t gt) { ////////// external temperature sensor ////////// +#ifdef ADMUX_THERM_EXTERNAL_SENSOR + void hwdef_set_admux_therm() { // put the ADC in temperature mode // ADCSRB: [VDEN, VDPD, -, -, ADLAR, ADTS2, ADTS1, ADTS0] @@ -140,3 +140,5 @@ uint16_t temp_raw2cooked(uint16_t measurement) { return k6; } +#endif + From 538e5029dc426bfd61eb3c6b9e2891b3cec355b7 Mon Sep 17 00:00:00 2001 From: Shane Synan Date: Tue, 28 Nov 2023 14:57:41 -0500 Subject: [PATCH 28/57] bikeflash: Cap default brightness to max, define Cap fallback default bike flasher brightness to stay below MAX_BIKING_LEVEL, fixing noFET/boost driver builds where MAX_1x7135 is above MAX_BIKING_LEVEL. Add the optional define DEFAULT_BIKING_LEVEL to set the default bike flasher brightness. This is NOT checked against MAX_BIKING_LEVEL, for simplicity. Alternatively, strobe-modes.c could be updated to check if the value exceeds MAX_BIKING_LEVEL at runtime. However, that might take up more flash space. Migrated from https://code.launchpad.net/~digitalcircuit/flashlight-firmware/anduril2_fix_nofet_bikeflash/+merge/408124 --- ui/anduril/load-save-config.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ui/anduril/load-save-config.h b/ui/anduril/load-save-config.h index 514fcbb9..eb6d798e 100644 --- a/ui/anduril/load-save-config.h +++ b/ui/anduril/load-save-config.h @@ -118,7 +118,15 @@ Config cfg = { .strobe_delays = { 41, 67 }, #endif #ifdef USE_BIKE_FLASHER_MODE - .bike_flasher_brightness = MAX_1x7135, + #ifndef DEFAULT_BIKING_LEVEL + #if MAX_1x7135 > MAX_BIKING_LEVEL + // Make sure fallback default doesn't exceed maximum (e.g. noFET) + #define DEFAULT_BIKING_LEVEL MAX_BIKING_LEVEL + #else + #define DEFAULT_BIKING_LEVEL MAX_1x7135 + #endif + #endif + .bike_flasher_brightness = DEFAULT_BIKING_LEVEL, #endif #ifdef USE_BEACON_MODE // beacon timing From 4373ed25154fb77f44d3b0ba6d3f5cc78127cc45 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 28 Nov 2023 13:12:05 -0700 Subject: [PATCH 29/57] prevent future issues like the FW3X had 1/3rd of the ramp size is probably a more reliable default than MAX_1x7135. The 7135-based reference points need to eventually be removed entirely and replaced by something more universal, but for now at least don't fail when a thermal stepdown isn't defined. --- ui/anduril/ramp-mode.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/anduril/ramp-mode.h b/ui/anduril/ramp-mode.h index 59c8db04..1392981c 100644 --- a/ui/anduril/ramp-mode.h +++ b/ui/anduril/ramp-mode.h @@ -4,14 +4,15 @@ #pragma once -#ifndef RAMP_LENGTH -#define RAMP_LENGTH 150 // default, if not overridden in a driver cfg file +#ifndef RAMP_SIZE +#define RAMP_SIZE 150 // default, if not overridden in a driver cfg file #endif +// TODO: Replace MAX_Xx7135 with MAX_CH1, MAX_CH2, MAX_REGULATED, etc + // thermal properties, if not defined per-driver #ifndef MIN_THERM_STEPDOWN -// TODO: Replace MAX_Xx7135 with MAX_CH1, MAX_CH2, MAX_REGULATED, etc -#define MIN_THERM_STEPDOWN MAX_1x7135 // lowest value it'll step down to +#define MIN_THERM_STEPDOWN (RAMP_SIZE/3) // lowest value it'll step down to #endif #ifndef THERM_FASTER_LEVEL #ifdef MAX_Nx7135 From 1153a7c8b4130abb62654476bc958399d687cbf2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 08:44:31 -0700 Subject: [PATCH 30/57] added a build target for FW3X with manually-fixed RGB aux wiring --- hw/lumintop/fw3x-lume1/hwdef.h | 12 +++++++++--- hw/lumintop/fw3x-lume1/rgbswap/anduril.h | 11 +++++++++++ hw/lumintop/fw3x-lume1/rgbswap/model | 1 + 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 hw/lumintop/fw3x-lume1/rgbswap/anduril.h create mode 100644 hw/lumintop/fw3x-lume1/rgbswap/model diff --git a/hw/lumintop/fw3x-lume1/hwdef.h b/hw/lumintop/fw3x-lume1/hwdef.h index 92a177fc..021c4cf9 100644 --- a/hw/lumintop/fw3x-lume1/hwdef.h +++ b/hw/lumintop/fw3x-lume1/hwdef.h @@ -153,9 +153,15 @@ uint16_t temp_raw2cooked(uint16_t measurement); #define ADMUX_THERM_EXTERNAL_SENSOR 0b00001011 // this driver allows for aux LEDs under the optic -#define AUXLED_R_PIN PA3 // pin 2 -#define AUXLED_G_PIN PA4 // pin 3 -#define AUXLED_B_PIN PA5 // pin 4 +#ifdef FW3X_RGB_SWAP // wiring fixed by end user + #define AUXLED_R_PIN PA5 // pin 2 + #define AUXLED_G_PIN PA4 // pin 3 + #define AUXLED_B_PIN PA3 // pin 4 +#else // Lumintop's factory wiring + #define AUXLED_R_PIN PA3 // pin 4 + #define AUXLED_G_PIN PA4 // pin 3 + #define AUXLED_B_PIN PA5 // pin 2 +#endif #define AUXLED_RGB_PORT PORTA // PORTA or PORTB or PORTC #define AUXLED_RGB_DDR DDRA // DDRA or DDRB or DDRC #define AUXLED_RGB_PUE PUEA // PUEA or PUEB or PUEC diff --git a/hw/lumintop/fw3x-lume1/rgbswap/anduril.h b/hw/lumintop/fw3x-lume1/rgbswap/anduril.h new file mode 100644 index 00000000..2fba7ff7 --- /dev/null +++ b/hw/lumintop/fw3x-lume1/rgbswap/anduril.h @@ -0,0 +1,11 @@ +// FW3X (RGB aux swapped) config options for Anduril +// Copyright (C) 2023 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +// Lumintop swapped red and blue wires. Some people fixed the wiring. +// Then the firmware fixed the pinouts to match Lumintop's wiring. +// This firmware exists for people who fixed their wiring. +#define FW3X_RGB_SWAP +#include "lumintop/fw3x-lume1/anduril.h" + diff --git a/hw/lumintop/fw3x-lume1/rgbswap/model b/hw/lumintop/fw3x-lume1/rgbswap/model new file mode 100644 index 00000000..44505ce2 --- /dev/null +++ b/hw/lumintop/fw3x-lume1/rgbswap/model @@ -0,0 +1 @@ +0315 From fdac6fcf22cd658785480c88c28243eeae62bcd0 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 09:16:13 -0700 Subject: [PATCH 31/57] made the avr32dd20 flashing script more universal --- bin/flash-avr32dd20.sh | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/bin/flash-avr32dd20.sh b/bin/flash-avr32dd20.sh index ef8b0f3c..dcd49674 100755 --- a/bin/flash-avr32dd20.sh +++ b/bin/flash-avr32dd20.sh @@ -1,13 +1,40 @@ #!/usr/bin/env bash +# AVR firmware flashing script, a wrapper for other tools +# Copyright (C) 2023 Selene ToyKeeper +# SPDX-License-Identifier: GPL-3.0-or-later + +# Usage: flash-MCUTYPE.sh hex/foo.hex +# (where the script name specifies the type of MCU chip, +# and the first parameter is the path to a .hex file) +# Example: +# ./bin/flash-avr32dd20.sh hex/anduril.thefreeman-avr32dd20-devkit.hex set -e +# Get the path to a .hex file [[ -z "$1" ]] && echo "No .hex file specified." && exit 1 HEX="$1" -#pymcuprog ping -t uart -u /dev/ttyUSB2 -d avr32dd20 -#pymcuprog erase -t uart -u /dev/ttyUSB2 -d avr32dd20 -#pymcuprog write verify -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" -#pymcuprog verify -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" +# assume the highest-numbered USB serial device is the correct one, +# since it was probably the most recently plugged in +TTYUSB=$(ls -1 /dev/tty* | grep -i usb | tail -1) + +# figure out the MCU type... +# TODO: find the relevant hw/*/arch file and use that to get MCU type +# use $2 if it exists, and use the name of this script maybe +MCUTYPE="unset" +[[ -n "$2" ]] && MCUTYPE="$2" +#MCUTYPE=$(echo "$0" | sed 's/.*flash-\(.*\).sh.*/\1/') +[[ "$0" =~ flash-(.*).sh ]] && MCUTYPE="${BASH_REMATCH[1]}" + +# Do the actual flashing +echo "Flashing $MCUTYPE MCU on port $TTYUSB: $HEX" +echo pymcuprog write \ + --erase \ + --verify \ + --timing \ + -t uart \ + -u "$TTYUSB" \ + -d "$MCUTYPE" \ + -f "$HEX" -pymcuprog write --erase --verify --timing -t uart -u /dev/ttyUSB2 -d avr32dd20 -f "$HEX" From 3fde090a8e55163288148b37e172b11cdeb3cc50 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 09:17:46 -0700 Subject: [PATCH 32/57] eliminated direct CCP register access from arch/attiny1616 (the protected write macro exists for a reason, and should be used instead) --- arch/attiny1616.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/attiny1616.c b/arch/attiny1616.c index 2770d06b..c5499ddc 100644 --- a/arch/attiny1616.c +++ b/arch/attiny1616.c @@ -210,8 +210,8 @@ inline void mcu_pcint_off() { void reboot() { // put the WDT in hard reset mode, then trigger it cli(); - CCP = CCP_IOREG_gc; // temporarily disable change protection - WDT.CTRLA = WDT_PERIOD_8CLK_gc; // Enable, timeout 8ms + // Enable, timeout 8ms + _PROTECTED_WRITE(WDT.CTRLA, WDT_PERIOD_8CLK_gc); sei(); wdt_reset(); while (1) {} From ba976c05f34814c81a6db90362ecf23f64852a30 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 09:22:44 -0700 Subject: [PATCH 33/57] minor documentation updates --- docs/anduril-manual.md | 12 ++++++------ docs/which-hex-file.md | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/anduril-manual.md b/docs/anduril-manual.md index 830ecdeb..93c64288 100644 --- a/docs/anduril-manual.md +++ b/docs/anduril-manual.md @@ -36,12 +36,12 @@ Button presses Button presses are abbreviated using a simple notation: - - `1C`: One click. Press and then quickly release the button. - - `1H`: Hold. Press the button, but keep holding it. - - `2C`: Two clicks. Press and release quickly, twice. - - `2H`: Click, hold. Click two times, but hold the second press. - - `3C`: Three clicks. Press and release quickly, three times. - - `3H`: Click, click, hold. Click three times, but hold the final press. + - `1C`: **One click.** Press and then quickly release the button. + - `1H`: **Hold.** Press the button, but keep holding it. + - `2C`: **Two clicks.** Press and release quickly, twice. + - `2H`: **Click, hold.** Click two times, but hold the second press. + - `3C`: **Three clicks.** Press and release quickly, three times. + - `3H`: **Click, click, hold.** Click three times, but hold the final press. The same pattern is used with higher numbers too. For example, `10C` means ten clicks... and `10H` means ten clicks but hold the final press. diff --git a/docs/which-hex-file.md b/docs/which-hex-file.md index 88cc1d29..d59c6bdc 100644 --- a/docs/which-hex-file.md +++ b/docs/which-hex-file.md @@ -4,10 +4,11 @@ which flavor of the firmware the light has installed. **WRITE THIS DOWN.** -2. Look up the model number in the MODELS file, to get the name and MCU type: - https://toykeeper.net/torches/fsm/anduril2/MODELS +2. Look up the model number in the [MODELS file](../MODELS), + to get the name and MCU type. 3. Find the newest firmware for that model. + https://github.com/ToyKeeper/anduril/releases https://toykeeper.net/torches/fsm/anduril2/?C=M;O=D If the version doesn't include a model number, you may be able to find From a32338a22bdf0e8b86d7860a04f0ae4a7cc4c2ab Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 09:24:14 -0700 Subject: [PATCH 34/57] sofirn-lt1s-pro: disable memory timer and extended simple UI by default (users complained, and extended simple UI probably needs to be off by default in all factory builds anyway) --- hw/sofirn/lt1s-pro/anduril.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/sofirn/lt1s-pro/anduril.h b/hw/sofirn/lt1s-pro/anduril.h index 1840b589..578afde0 100644 --- a/hw/sofirn/lt1s-pro/anduril.h +++ b/hw/sofirn/lt1s-pro/anduril.h @@ -86,13 +86,13 @@ #define USE_SIMPLE_UI_RAMPING_TOGGLE // allow Aux Config and Strobe Modes in Simple UI -#define USE_EXTENDED_SIMPLE_UI +//#define USE_EXTENDED_SIMPLE_UI // turn on at med-low brightness by default (level 50/150, or ramp step 3/7) // (also sets lockout mode 2H to a useful level) -#define DEFAULT_MANUAL_MEMORY 50 +//#define DEFAULT_MANUAL_MEMORY 50 // reset to default after being off for 10 minutes -#define DEFAULT_MANUAL_MEMORY_TIMER 10 +//#define DEFAULT_MANUAL_MEMORY_TIMER 10 // enable 2 click turbo (Anduril 1 style) #define DEFAULT_2C_STYLE 1 From 04f1ae1127affc884d1e73879664af1ad9442ec2 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 10:42:15 -0700 Subject: [PATCH 35/57] saner defaults for the default biking level - set DEFAULT_BIKING_LEVEL in bike mode's header file - use RAMP_SIZE/3 by default - limit to MAX_BIKING_LEVEL if necessary - get rid of any ties to MAX_1x7135 because it's kind of an obsolete symbol --- ui/anduril/load-save-config.h | 8 -------- ui/anduril/strobe-modes.h | 12 +++++++++--- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ui/anduril/load-save-config.h b/ui/anduril/load-save-config.h index eb6d798e..3ad477cd 100644 --- a/ui/anduril/load-save-config.h +++ b/ui/anduril/load-save-config.h @@ -118,14 +118,6 @@ Config cfg = { .strobe_delays = { 41, 67 }, #endif #ifdef USE_BIKE_FLASHER_MODE - #ifndef DEFAULT_BIKING_LEVEL - #if MAX_1x7135 > MAX_BIKING_LEVEL - // Make sure fallback default doesn't exceed maximum (e.g. noFET) - #define DEFAULT_BIKING_LEVEL MAX_BIKING_LEVEL - #else - #define DEFAULT_BIKING_LEVEL MAX_1x7135 - #endif - #endif .bike_flasher_brightness = DEFAULT_BIKING_LEVEL, #endif #ifdef USE_BEACON_MODE diff --git a/ui/anduril/strobe-modes.h b/ui/anduril/strobe-modes.h index 058cea5e..1890b8c1 100644 --- a/ui/anduril/strobe-modes.h +++ b/ui/anduril/strobe-modes.h @@ -55,9 +55,15 @@ inline void lightning_storm_iter(); // bike mode config options #ifdef USE_BIKE_FLASHER_MODE -#define MAX_BIKING_LEVEL 120 // should be 127 or less -inline void bike_flasher_iter(); -#endif + #if !defined(DEFAULT_BIKING_LEVEL) + #define DEFAULT_BIKING_LEVEL (RAMP_SIZE/3) + #elif DEFAULT_BIKING_LEVEL > MAX_BIKING_LEVEL + #undef DEFAULT_BIKING_LEVEL + #define DEFAULT_BIKING_LEVEL MAX_BIKING_LEVEL + #endif + #define MAX_BIKING_LEVEL 120 // should be 127 or less + inline void bike_flasher_iter(); +#endif // ifdef USE_BIKE_FLASHER_MODE #ifdef USE_CANDLE_MODE #include "anduril/candle-mode.h" From 449e90c6d5ad25705931ff8c2253c398aebff67e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 10:45:42 -0700 Subject: [PATCH 36/57] oops, flashing script should actually flash ... not just echo a command --- bin/flash-avr32dd20.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/flash-avr32dd20.sh b/bin/flash-avr32dd20.sh index dcd49674..a4faab81 100755 --- a/bin/flash-avr32dd20.sh +++ b/bin/flash-avr32dd20.sh @@ -29,7 +29,7 @@ MCUTYPE="unset" # Do the actual flashing echo "Flashing $MCUTYPE MCU on port $TTYUSB: $HEX" -echo pymcuprog write \ +pymcuprog write \ --erase \ --verify \ --timing \ From e33111d38f729b47e03e9699eeb5b73637a92496 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 13:37:23 -0700 Subject: [PATCH 37/57] fixed RGB aux turning on in momentary mode when post-off voltage was enabled --- ui/anduril/momentary-mode.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/ui/anduril/momentary-mode.c b/ui/anduril/momentary-mode.c index 94f6bc24..327302ac 100644 --- a/ui/anduril/momentary-mode.c +++ b/ui/anduril/momentary-mode.c @@ -47,14 +47,17 @@ uint8_t momentary_state(Event event, uint16_t arg) { } else { #endif + // turn off lighted button + #ifdef USE_INDICATOR_LED + indicator_led(0); + #elif defined(USE_AUX_RGB_LEDS) + rgb_led_set(0); + #endif + #ifdef USE_BUTTON_LED + button_led_set(0); + #endif if (arg > TICKS_PER_SECOND*5) { // sleep after 5 seconds go_to_standby = 1; // sleep while light is off - // turn off lighted button - #ifdef USE_INDICATOR_LED - indicator_led(0); - #elif defined(USE_AUX_RGB_LEDS) - rgb_led_update(0, 0); - #endif } #ifdef USE_STROBE_STATE } From 2dc1d19e67e2ad1606470bb14ca44e9f8c684d2b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 17:45:46 -0700 Subject: [PATCH 38/57] changed version number to use the latest release tag instead of build date Before: 2023-11-30 (build date) After: 2023-10-31-98.1 (latest release tag + number of commits since + dirty flag) --- .gitignore | 2 ++ bin/build-all.sh | 20 ++++++++++++++++---- bin/build.sh | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 965a3e37..d420e340 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.build/ .env/ .venv/ .*.swo @@ -7,6 +8,7 @@ env/ hex/ ignore/ old/ +releases/ venv/ *~ *.cpp diff --git a/bin/build-all.sh b/bin/build-all.sh index df72ad51..27209ca4 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -21,9 +21,21 @@ UI=anduril mkdir -p hex -# TODO: use a git tag for the version, instead of build date -# TODO: use build/version.h instead of $UI/version.h ? -date '+#define VERSION_NUMBER "%Y-%m-%d"' > ui/$UI/version.h +# old: version = build date +#date '+#define VERSION_NUMBER "%Y-%m-%d"' > ui/$UI/version.h + +# version = git tag + revs since + dirty flag +REV=$(git describe --tags --dirty --abbrev=8 --match='r2*') +# reformatting this would be easier with a perl one-liner, +# but I'm trying to avoid extra build dependencies +REV="${REV:1}" # strip the leading 'r' +# strip rev hash (git won't give "commits since tag" without the rev hash) +REV="${REV/-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/}" +REV="${REV/-dirty/.1}" # convert '-dirty' to '.1' +# save the version name to version.h +mkdir -p ".build/$UI" +echo '#define VERSION_NUMBER "'"$REV"'"' > ".build/$UI/version.h" + PASS=0 FAIL=0 @@ -48,7 +60,7 @@ for TARGET in hw/*/*/**/"$UI".h ; do if [ 1 = $SKIP ]; then continue ; fi # announce what we're going to build - echo "===== $UI : $NAME =====" + echo "===== $UI $REV : $NAME =====" # try to compile, track result, and rename compiled files if bin/build.sh "$TARGET" ; then diff --git a/bin/build.sh b/bin/build.sh index 9b4b0b38..d044ca55 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -49,7 +49,7 @@ export CPP=avr-cpp export OBJCOPY=avr-objcopy export DFPFLAGS="-B $DFPPATH/gcc/dev/$MCUNAME/ -I $DFPPATH/include/" # TODO: include $user/ first so it can override other stuff -INCLUDES="-I ui -I hw -I. -I.. -I../.. -I../../.." +INCLUDES="-I .build -I ui -I hw -I. -I.. -I../.. -I../../.." export CFLAGS=" -Wall -g -Os -mmcu=$MCUNAME -c -std=gnu99 -fgnu89-inline -fwhole-program $MCUFLAGS $INCLUDES -fshort-enums $DFPFLAGS" export CPPFLAGS="-Wall -g -Os -mmcu=$MCUNAME -C -std=gnu99 -fgnu89-inline -fwhole-program $MCUFLAGS $INCLUDES -fshort-enums $DFPFLAGS" export OFLAGS="-Wall -g -Os -mmcu=$MCUNAME -mrelax $DFPFLAGS" From c01068bc2258a479227851dd6f2bca8d8a806205 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Thu, 30 Nov 2023 17:48:24 -0700 Subject: [PATCH 39/57] build-all.sh: re-indented, started organizing code into functions (still needs a proper rewrite, but at least the version.h code is in a separate function now) --- bin/build-all.sh | 159 +++++++++++++++++++++++++---------------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/bin/build-all.sh b/bin/build-all.sh index 27209ca4..444809e4 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -9,80 +9,89 @@ # enable "**" for recursive glob (requires bash) shopt -s globstar -if [ "$#" -gt 0 ]; then - # multiple search terms with "AND" - SEARCH=( "$@" ) - # memes - [ "$1" = "me" ] && shift && shift && echo "Make your own $*." && exit 1 -fi - -# TODO: detect UI from $0 and/or $* -UI=anduril - -mkdir -p hex - -# old: version = build date -#date '+#define VERSION_NUMBER "%Y-%m-%d"' > ui/$UI/version.h - -# version = git tag + revs since + dirty flag -REV=$(git describe --tags --dirty --abbrev=8 --match='r2*') -# reformatting this would be easier with a perl one-liner, -# but I'm trying to avoid extra build dependencies -REV="${REV:1}" # strip the leading 'r' -# strip rev hash (git won't give "commits since tag" without the rev hash) -REV="${REV/-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/}" -REV="${REV/-dirty/.1}" # convert '-dirty' to '.1' -# save the version name to version.h -mkdir -p ".build/$UI" -echo '#define VERSION_NUMBER "'"$REV"'"' > ".build/$UI/version.h" - - -PASS=0 -FAIL=0 -PASSED='' -FAILED='' - -# build targets are hw/$vendor/$model/**/$ui.h -for TARGET in hw/*/*/**/"$UI".h ; do - - # friendly name for this build - NAME=$(echo "$TARGET" | perl -ne 's|/|-|g; /hw-(.*)-'"$UI"'.h/ && print "$1\n";') - - # limit builds to searched patterns, if given - SKIP=0 - if [ ${#SEARCH[@]} -gt 0 ]; then - for text in "${SEARCH[@]}" ; do - if ! echo "$NAME $TARGET" | grep -i -- "$text" > /dev/null ; then - SKIP=1 +function main { + + if [ "$#" -gt 0 ]; then + # multiple search terms with "AND" + SEARCH=( "$@" ) + # memes + [ "$1" = "me" ] && shift && shift && echo "Make your own $*." && exit 1 + fi + + # TODO: detect UI from $0 and/or $* + UI=anduril + + mkdir -p hex + + make-version-h # generate a version.h file + + PASS=0 + FAIL=0 + PASSED='' + FAILED='' + + # build targets are hw/$vendor/$model/**/$ui.h + for TARGET in hw/*/*/**/"$UI".h ; do + + # friendly name for this build + NAME=$(echo "$TARGET" | perl -ne 's|/|-|g; /hw-(.*)-'"$UI"'.h/ && print "$1\n";') + + # limit builds to searched patterns, if given + SKIP=0 + if [ ${#SEARCH[@]} -gt 0 ]; then + for text in "${SEARCH[@]}" ; do + if ! echo "$NAME $TARGET" | grep -i -- "$text" > /dev/null ; then + SKIP=1 + fi + done + fi + if [ 1 = $SKIP ]; then continue ; fi + + # announce what we're going to build + echo "===== $UI $REV : $NAME =====" + + # try to compile, track result, and rename compiled files + if bin/build.sh "$TARGET" ; then + HEX_OUT="hex/$UI.$NAME.hex" + mv -f "ui/$UI/$UI".hex "$HEX_OUT" + MD5=$(md5sum "$HEX_OUT" | cut -d ' ' -f 1) + echo " # $MD5" + echo " > $HEX_OUT" + PASS=$((PASS + 1)) + PASSED="$PASSED $NAME" + else + echo "ERROR: build failed" + FAIL=$((FAIL + 1)) + FAILED="$FAILED $NAME" fi + done - fi - if [ 1 = $SKIP ]; then continue ; fi - - # announce what we're going to build - echo "===== $UI $REV : $NAME =====" - - # try to compile, track result, and rename compiled files - if bin/build.sh "$TARGET" ; then - HEX_OUT="hex/$UI.$NAME.hex" - mv -f "ui/$UI/$UI".hex "$HEX_OUT" - MD5=$(md5sum "$HEX_OUT" | cut -d ' ' -f 1) - echo " # $MD5" - echo " > $HEX_OUT" - PASS=$((PASS + 1)) - PASSED="$PASSED $NAME" - else - echo "ERROR: build failed" - FAIL=$((FAIL + 1)) - FAILED="$FAILED $NAME" - fi - -done - -# summary -echo "===== $PASS builds succeeded, $FAIL failed =====" -#echo "PASS: $PASSED" -if [ 0 != $FAIL ]; then - echo "FAIL:$FAILED" - exit 1 -fi + + # summary + echo "===== $PASS builds succeeded, $FAIL failed =====" + #echo "PASS: $PASSED" + if [ 0 != $FAIL ]; then + echo "FAIL:$FAILED" + exit 1 + fi +} + +function make-version-h { + # old: version = build date + #date '+#define VERSION_NUMBER "%Y-%m-%d"' > ui/$UI/version.h + + # version = git tag + revs since + dirty flag + REV=$(git describe --tags --dirty --abbrev=8 --match='r2*') + # reformatting this would be easier with a perl one-liner, + # but I'm trying to avoid extra build dependencies + REV="${REV:1}" # strip the leading 'r' + # strip rev hash (git won't give "commits since tag" without the rev hash) + REV="${REV/-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/}" + REV="${REV/-dirty/.1}" # convert '-dirty' to '.1' + # save the version name to version.h + mkdir -p ".build/$UI" + echo '#define VERSION_NUMBER "'"$REV"'"' > ".build/$UI/version.h" +} + +main "$@" + From c1542a1dce5c40afc36148a1c1ddbd559fcc3014 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 1 Dec 2023 18:21:55 -0700 Subject: [PATCH 40/57] added bin/make-release.sh to generate a .zip file ready for release --- bin/make-release.sh | 55 +++++++++++++++++++++++++++++++++++++++++++++ make | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 bin/make-release.sh diff --git a/bin/make-release.sh b/bin/make-release.sh new file mode 100755 index 00000000..da985d12 --- /dev/null +++ b/bin/make-release.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Create a release file for Anduril .hex files. +# Copyright (C) 2023 Selene ToyKeeper +# SPDX-License-Identifier: GPL-3.0-or-later + +set -e # abort on error + +# run from repo root +REPODIR=$(dirname "$0")/.. +cd "$REPODIR" + +# get rid of 1st arg if it's "release" passed from 'make' +[[ "$1" = "release" ]] && shift + +# try to get the repo ready for a release +# (or not; probably better to do these steps manually) +#make clean +#make + +# release name +#REV=$(date +'%Y-%m-%d') +REV=$(git describe --tags --dirty --match='r2*') +REV="${REV:1}" # convert 'r2023-...' to '2023-...' +# allow manually specifying a release name +[[ -n "$1" ]] && REV="$1" + +# releases are named "$project.$revision" +RELNAME="anduril.$REV" + +# release directory +RELDIR="releases/$RELNAME" +mkdir -p "$RELDIR" "$RELDIR/hex" + +# add documentation and stuff +cp -a \ + ChangeLog.md \ + LICENSE \ + MODELS \ + README.md \ + docs/anduril-manual.md \ + docs/battery-rainbow.png \ + docs/which-hex-file.md \ + "$RELDIR" + +# add the .hex files +rename -f 's|hex/anduril.|'"$RELDIR/hex/$RELNAME"'.|;' hex/*.hex + +# make a .zip file +cd releases +mkdir -p zip +ZPATH=zip/"$RELNAME".zip +zip -q -r "$ZPATH" "$RELNAME" +cd .. +ls -l "releases/$ZPATH" + diff --git a/make b/make index c50219d2..d34a4b8d 100755 --- a/make +++ b/make @@ -73,7 +73,7 @@ function main() { cat MODELS ;; release) - echo "Not implemented yet." + ./bin/make-release.sh "$@" ;; todo) grep -E 'TODO:|FIXME:' -- **/*.[ch] **/*.md From 6559665e242a52fd99b4b25ac973104d134f30fb Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 1 Dec 2023 18:22:22 -0700 Subject: [PATCH 41/57] added docs/battery-rainbow.png from old repo, since it's still relevant --- docs/battery-rainbow.png | Bin 0 -> 2920 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/battery-rainbow.png diff --git a/docs/battery-rainbow.png b/docs/battery-rainbow.png new file mode 100644 index 0000000000000000000000000000000000000000..499866dcc821479fae98fb6a3f8e7754a230cca1 GIT binary patch literal 2920 zcmZ9O2UJtZ8pnx92~7zuB@|IX6bPU}N(^NYL{N#+BA_5r1tCh2OYgc!i7bdhNDvW_ zr56ogLJ2CMkbu&=f{94W5(rX+cX8i4=e>7k?wOf8bMMUe`~EZEBweyH7ZrjF@$m47 zTAVYr21{EW9>_z%Jz%X_peF__cmqu=Yy|}cM?Yhxz$WzeIfpq@knv<%;+8ZI%UGoD{qOlIlK9@scC7AwHg-LG$|+a$g%L_i|#kV z!if#a53#nk=&tVHgc`_rd~I#5LxE-X-9s1a>UdAa5C~AYy%_dCIZQ}bm%O#LH8^=# zL!$!OrsF^MgTQ(@Pg}Y`&_O6FKBZFG$w^5`%|R`Vjg6aYOQ%t&X9iyM+{*=LU+R}N zHEp-X3q)>m%}%SUmr-5Eg$=c|ZqI%!gaMAb@ewn9D95FAGW2< zn)_|6t(TXVYiesR3tMA+e0-b(m6VmU#enGOow&F?+5rIpmpFEIcHUBwk|RSyKQ=Zj zCH7vnwzjslo%#M94ujngoI*si9=962zPn(;J2pKtlko0SF{a?zv**;)A&YzY-n6&- zwx8FIntmrbr5naJ2te6(KG)KLA!D;4eDl1dh)00khsP)Vr;X9@OVusDW{d?A}qdl(jm+Q*Iw=2d<5i__H9%mdA7iri!}@^JqC zVqS|ZmXwT4Qa|MVXZGhd7|`-C?MV6yll&h48!?h-dg+2D0`V5&BsRAPFfgDdj#k&! zBIW+dAWb-aXSrV?XXnt#Dd|6Yv0G9`{CwL+o;w4wKw>t!^lbh?x6Z8fup<)Id^j4<_A`@5L*#qwcNC_(ESEh1RMr~LYzzVku z&7yS1k@w3`dQi9oG5l`t0kFYXm|bw-W}+;KTG?bt84BMoqjtwHAf$AT3X|~F=K%0y zG}R!Ol;G8v%~JFEZyOr_--cqc*Kh{=Sg^K!Q72b5wv|xI$B#>xOjkMrOmC(sSrXB^ zl=GpOw>2uClOC^wzKrrpa1-3t0(mVFK= zB8C#%ujJs8$Ff9kejUv|8*Y9{`Y2#_nsCi`E2z>n7Gw)kfa0@RVWbJtlmk}@ZApa2 zvhwm^|ClFn2wdq!oTegR_zrdotaty?Rx!v0RM$G@LkDOdjHH#lRN~2e+eHzN`u)$8 zDZ9h**j=T5@n~{(XT#H5bwOh~LHd`!dk1*q8me6X?XWuX)uF2SRB6iJKQS7aC|4vX z+}%W*bL=|-vU3mrj+XzmzFb{1Hnw=#XLyO9m)Br1=Ad>ikr*EzFCYq63ci<+006+1D-kDp0SfHn*Un`nwmKI`uO+_Lba zw>H^-d}Cu(4W62ss%Br-;(RgiDmBb*W4zXjVQH|vz3ues)^Rnp41Sk}0FU>X#}N_= z^78VsvZFmcF*fZ{$xog<_-kAEaW+!HR3XK4KzSR@I)}@cI6_-)3iLM@nh(l&GI56nF$r&&{a?r%9gxgQgg< z{?tbc4<5V_WkAjwYj6Ku#CY{f#Cc_M3%YZs_xNUAU0Q|cr8|R*6V%a~z`23)`VbO{WQ5qH`#>w^UAn7#qsfHKBR-L=Sz)V6T~aHN)8PTd1p*^8XvVHqE3Y_&$P4{mk6ks ze7;(L8}e9{KrgtoGc0#*>Ha>Wkih!2Ct!pPviob`0g*^7M{aW$Mt{g5J-aGlI?H9Y zs=9t7N`4hC%}v-!=lVzEHv;H+Mn-qOm}=8#w7TH!(%89Av+2^Zm$|fKq<%ma?l@UA zP#w8>H^p>W_tp>(ch-F*`on|?H99AYyC-C!C6*T^J~TRt8-3-szWnw20|^zYIyw8R zS4A}DC!3q=piX?iV@;QP(?0ql+CeMddY?X3?7FLEWP4U2qZYhwP$-nfM$~@i34E;Y zqYGBv-roNH8q$lP&Shj|zCol9oU^i`SGl$+jttp3Itmq+d4zXB(vtYa4wpEFhBlDN zWcsj_#??QrJ(ZS*9N=T>=v-#$mC-vOy!=x_ty`$ILbq2tNo37q$6{L5RaJec!bIyw zv@YXyaBs$QOR<&gB;VkW5CJsXNWJ*yIM%pB;fn5TKF>|?PNtl=WOBVfp&) Date: Sat, 2 Dec 2023 13:08:39 -0700 Subject: [PATCH 42/57] fetch tags on CI checkout, so 'git describe' can work --- .github/workflows/compile.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 893eb412..e695a3a2 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -14,6 +14,9 @@ jobs: - name: Checkout uses: actions/checkout@master + # allow 'git describe' to work, by fetching tags + with: + fetch-tags: true - name: Stop committing version.h # reject commit if version.h was changed From 1ca7e77cec953cb4cce5868336c24042ec3cf800 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 2 Dec 2023 13:09:08 -0700 Subject: [PATCH 43/57] run CI on all branches, not just on trunk --- .github/workflows/compile.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index e695a3a2..3f03c403 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -1,10 +1,13 @@ name: build all on: - push: - branches: [ "trunk" ] - pull_request: - branches: [ "trunk" ] + # all branches: + [ push, pull_request ] + # trunk only: + #push: + # branches: [ "trunk" ] + #pull_request: + # branches: [ "trunk" ] jobs: compile: From dcbacb61bb3e04872927008a394524ed9208c740 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 2 Dec 2023 13:30:42 -0700 Subject: [PATCH 44/57] build-all: handle the case where "git describe" can't get any tags Resulting revision is "$MODEL-0.$HASH" where the hash is the commit short ID --- bin/build-all.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bin/build-all.sh b/bin/build-all.sh index 444809e4..f239217d 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -88,6 +88,11 @@ function make-version-h { # strip rev hash (git won't give "commits since tag" without the rev hash) REV="${REV/-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/}" REV="${REV/-dirty/.1}" # convert '-dirty' to '.1' + # handle an empty name (happens during github action runs) + if [[ -z "$REV" ]]; then + HASH=$(git describe --always) + REV="0.$HASH" + fi # save the version name to version.h mkdir -p ".build/$UI" echo '#define VERSION_NUMBER "'"$REV"'"' > ".build/$UI/version.h" From 73d1f3e156296642bdc35aed2ffa16458e321d2d Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 2 Dec 2023 13:35:59 -0700 Subject: [PATCH 45/57] github CI: fetch history too, to allow detection of version tags It needs history to determine which tag precedes the current commit. This could be expensive on large repos, but for Anduril it seems to only increase the checkout size by about 40% or so. (11 MiB -> 15 MiB) --- .github/workflows/compile.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index 3f03c403..2ba771fc 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -17,8 +17,9 @@ jobs: - name: Checkout uses: actions/checkout@master - # allow 'git describe' to work, by fetching tags + # allow 'git describe' to work, by fetching tags and history with: + fetch-depth: 0 fetch-tags: true - name: Stop committing version.h From 258d63de644159254597610bceb45dce13462d87 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 3 Dec 2023 14:52:18 -0700 Subject: [PATCH 46/57] fw3x: document how it ships with the wrong fuse values, and how to fix it --- hw/lumintop/fw3x-lume1/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/lumintop/fw3x-lume1/README.md b/hw/lumintop/fw3x-lume1/README.md index 8609c499..190cd0ef 100644 --- a/hw/lumintop/fw3x-lume1/README.md +++ b/hw/lumintop/fw3x-lume1/README.md @@ -10,6 +10,11 @@ sensor. LoneOceans sent a fixed driver design to Lumintop, but the new design didn't get produced. So to flash firmware, swap the wires for those two pins first. +**Fuses**: Lumintop seems to have shipped the FW3X with the wrong fuse values, +so it has the MCU severely underclocked and everything runs much slower than it +should. Use [flash-tiny1634-fuses.sh](../../../bin/flash-tiny1634-fuses.sh) to +fix those fuse values and get it running at the correct speed. + **RGB mixup**: Lumintop seems to have swapped the wires for aux R and aux B. This was fixed in firmware in 2023-12, but some lights were fixed in hardware before that, so the firmware fix might cause the colors to be swapped again. From 8e86d66238572c1d97cd54a592da0573a51892a1 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 3 Dec 2023 17:47:36 -0700 Subject: [PATCH 47/57] updated MODELS, bin/models.py, and hw/BRANDS... - changed column order to (model, mcu, name) - changed column sizes (auto-sized w/ 2 spaces between columns) - made it handle hex digits in model numbers - reserved 1900 to 2199 for years only, not model numbers - noted gChart and thefreeman sharing a brand ID --- MODELS | 154 +++++++++++++++++++++++++------------------------- bin/models.py | 33 +++++++++-- hw/BRANDS | 6 +- 3 files changed, 112 insertions(+), 81 deletions(-) diff --git a/MODELS b/MODELS index 87987dd8..ef280fa3 100644 --- a/MODELS +++ b/MODELS @@ -1,80 +1,82 @@ -Models: 70 +Models: 72 -Model Name MCU ------ ---- --- -0111 hank-emisar-d4 attiny85 -0112 hank-emisar-d4-219 attiny85 -0113 hank-emisar-d4v2 attiny1634 -0114 hank-emisar-d4v2-219 attiny1634 -0115 hank-emisar-d4v2-nofet attiny1634 -0121 hank-emisar-d1 attiny85 -0122 hank-emisar-d1s attiny85 -0123 hank-emisar-d1v2-7135-fet attiny1634 -0124 hank-emisar-d1v2-linear-fet attiny1634 -0125 hank-emisar-d1v2-nofet attiny1634 -0131 hank-emisar-d4s attiny85 -0132 hank-emisar-d4s-219 attiny85 -0133 hank-emisar-d4sv2 attiny1634 -0134 hank-emisar-d4sv2-219 attiny1634 -0135 hank-emisar-2ch attiny1634 -0136 hank-emisar-2ch-fet attiny1634 -0141 hank-emisar-d18 attiny85 -0142 hank-emisar-d18-219 attiny85 -0143 hank-noctigon-m44 attiny1634 -0151 hank-emisar-d4k-3ch attiny1634 -0211 hank-noctigon-kr4 attiny1634 -0212 hank-noctigon-kr4-nofet attiny1634 -0213 hank-noctigon-kr4-219 attiny1634 -0214 hank-noctigon-kr4-219b attiny1634 -0215 hank-noctigon-kr4-2ch attiny1634 -0216 hank-noctigon-kr4-boost attiny1634 -0251 hank-noctigon-k1 attiny1634 -0252 hank-noctigon-k1-sbt90 attiny1634 -0253 hank-noctigon-k1-boost attiny1634 -0261 hank-noctigon-k9.3 attiny1634 -0262 hank-noctigon-k9.3-nofet attiny1634 -0263 hank-noctigon-k9.3-219 attiny1634 -0265 noctigon-k9.3-tintramp-nofet attiny1634 (old, use 0262) -0266 noctigon-k9.3-tintramp-fet attiny1634 (old, use 0261) -0267 noctigon-k9.3-tintramp-219 attiny1634 (old, use 0263) -0271 hank-noctigon-dm11 attiny1634 -0272 hank-noctigon-dm11-nofet attiny1634 -0273 hank-noctigon-dm11-boost attiny1634 -0274 hank-noctigon-dm11-sbt90 attiny1634 -0311 lumintop-fw3a attiny85 -0312 lumintop-fw3a-219 attiny85 -0313 lumintop-fw3a-nofet attiny85 -0314 lumintop-fw3x-lume1 attiny1634 -0321 lumintop-blf-gt attiny85 -0322 lumintop-blf-gt-mini attiny85 -0411 fireflies-rot66 attiny85 -0412 fireflies-rot66-219 attiny85 -0413 fireflies-rot66g2 attiny85 -0421 fireflies-pl47 attiny85 -0422 fireflies-pl47-219 attiny85 -0423 fireflies-pl47g2 attiny85 -0441 fireflies-e01 attiny85 -0511 mateminco-mf01s attiny85 -0521 mateminco-mf01-mini attiny85 -0531 mateminco-mt35-mini attiny85 -0611 sofirn-blf-q8 attiny85 -0612 sofirn-sp36 attiny85 -0613 sofirn-blf-q8-t1616 attiny1616 -0614 sofirn-sp36-t1616 attiny1616 -0621 sofirn-blf-lt1 attiny85 -0622 sofirn-blf-lt1-t1616 attiny1616 -0623 sofirn-lt1s-pro attiny1616 -0631 sofirn-sp10-pro attiny1616 -0632 sofirn-sc21-pro attiny1616 -0713 wurkkos-ts10-rgbaux attiny1616 -0714 wurkkos-ts10 attiny1616 -0715 wurkkos-ts25 attiny1616 -0716 wurkkos-fc13 attiny1616 -0717 wurkkos-ts11 attiny1616 -1618 gchart-fet1-t1616 attiny1616 -1630 thefreeman-lin16dac attiny1616 -1631 thefreeman-boost21-6a attiny1616 -1632 thefreeman-boost-fwaa attiny1616 +Model MCU Name +----- --- ---- +0111 attiny85 hank-emisar-d4 +0112 attiny85 hank-emisar-d4-219 +0113 attiny1634 hank-emisar-d4v2 +0114 attiny1634 hank-emisar-d4v2-219 +0115 attiny1634 hank-emisar-d4v2-nofet +0121 attiny85 hank-emisar-d1 +0122 attiny85 hank-emisar-d1s +0123 attiny1634 hank-emisar-d1v2-7135-fet +0124 attiny1634 hank-emisar-d1v2-linear-fet +0125 attiny1634 hank-emisar-d1v2-nofet +0131 attiny85 hank-emisar-d4s +0132 attiny85 hank-emisar-d4s-219 +0133 attiny1634 hank-emisar-d4sv2 +0134 attiny1634 hank-emisar-d4sv2-219 +0135 attiny1634 hank-emisar-2ch +0136 attiny1634 hank-emisar-2ch-fet +0141 attiny85 hank-emisar-d18 +0142 attiny85 hank-emisar-d18-219 +0143 attiny1634 hank-noctigon-m44 +0151 attiny1634 hank-emisar-d4k-3ch +0211 attiny1634 hank-noctigon-kr4 +0212 attiny1634 hank-noctigon-kr4-nofet +0213 attiny1634 hank-noctigon-kr4-219 +0214 attiny1634 hank-noctigon-kr4-219b +0215 attiny1634 hank-noctigon-kr4-2ch +0216 attiny1634 hank-noctigon-kr4-boost +0251 attiny1634 hank-noctigon-k1 +0252 attiny1634 hank-noctigon-k1-sbt90 +0253 attiny1634 hank-noctigon-k1-boost +0261 attiny1634 hank-noctigon-k9.3 +0262 attiny1634 hank-noctigon-k9.3-nofet +0263 attiny1634 hank-noctigon-k9.3-219 +0265 attiny1634 noctigon-k9.3-tintramp-nofet (old, use 0262) +0266 attiny1634 noctigon-k9.3-tintramp-fet (old, use 0261) +0267 attiny1634 noctigon-k9.3-tintramp-219 (old, use 0263) +0271 attiny1634 hank-noctigon-dm11 +0272 attiny1634 hank-noctigon-dm11-nofet +0273 attiny1634 hank-noctigon-dm11-boost +0274 attiny1634 hank-noctigon-dm11-sbt90 +0311 attiny85 lumintop-fw3a +0312 attiny85 lumintop-fw3a-219 +0313 attiny85 lumintop-fw3a-nofet +0314 attiny1634 lumintop-fw3x-lume1 +0315 attiny1634 lumintop-fw3x-lume1-rgbswap +0321 attiny85 lumintop-blf-gt +0322 attiny85 lumintop-blf-gt-mini +0411 attiny85 fireflies-rot66 +0412 attiny85 fireflies-rot66-219 +0413 attiny85 fireflies-rot66g2 +0421 attiny85 fireflies-pl47 +0422 attiny85 fireflies-pl47-219 +0423 attiny85 fireflies-pl47g2 +0441 attiny85 fireflies-e01 +0511 attiny85 mateminco-mf01s +0521 attiny85 mateminco-mf01-mini +0531 attiny85 mateminco-mt35-mini +0611 attiny85 sofirn-blf-q8 +0612 attiny85 sofirn-sp36 +0613 attiny1616 sofirn-blf-q8-t1616 +0614 attiny1616 sofirn-sp36-t1616 +0621 attiny85 sofirn-blf-lt1 +0622 attiny1616 sofirn-blf-lt1-t1616 +0623 attiny1616 sofirn-lt1s-pro +0631 attiny1616 sofirn-sp10-pro +0632 attiny1616 sofirn-sc21-pro +0713 attiny1616 wurkkos-ts10-rgbaux +0714 attiny1616 wurkkos-ts10 +0715 attiny1616 wurkkos-ts25 +0716 attiny1616 wurkkos-fc13 +0717 attiny1616 wurkkos-ts11 +1618 attiny1616 gchart-fet1-t1616 +1630 attiny1616 thefreeman-lin16dac +1631 attiny1616 thefreeman-boost21-mp3431-hdr-dac-argb +1632 attiny1616 thefreeman-boost-fwaa-mp3432-hdr-dac-rgb +1632dd20 avr32dd20 thefreeman-avr32dd20-devkit Duplicates: diff --git a/bin/models.py b/bin/models.py index 8e54d1ca..1a1152e5 100755 --- a/bin/models.py +++ b/bin/models.py @@ -24,12 +24,18 @@ def main(args): foo.sort() models = [x[-1] for x in foo] + colsizes = [ + max(len(m.model) for m in models), + max(len(m.mcu) for m in models), + max(len(m.name) for m in models), + ] + print('Models: %i\n' % len(models)) - fmt = '%s\t%-30s\t%s' - print(fmt % ('Model', 'Name', 'MCU')) - print(fmt % ('-----', '----', '---')) + fmt = '%%-%is %%-%is %%s' % (colsizes[0], colsizes[1]) + print(fmt % ('Model', 'MCU', 'Name')) + print(fmt % ('-----', '---', '----')) for m in models: - print(fmt % (m.model, m.name, m.mcu)) + print(fmt % (m.model, m.mcu, m.name)) print('\nDuplicates:') for i, m in enumerate(models): @@ -56,6 +62,7 @@ def load_model(path): m.name = path.replace('hw/','').replace('/', '-') m.mcu = inherit(path, 'arch') m.model = inherit(path, 'model') + if m.model: m.model = model_translate(m.model) return m @@ -73,6 +80,24 @@ def inherit(path, field): return None +def model_translate(m): + """Convert raw ordinal hex codes into human-friendly a-f digits. + """ + m = str(m) + replace = { + chr(ord('0') + 10): 'a', + chr(ord('0') + 11): 'b', + chr(ord('0') + 12): 'c', + chr(ord('0') + 13): 'd', + chr(ord('0') + 14): 'e', + chr(ord('0') + 15): 'f', + } + for s, r in replace.items(): + m = m.replace(s, r) + + return m + + if __name__ == "__main__": import sys main(sys.argv[1:]) diff --git a/hw/BRANDS b/hw/BRANDS index 059f3119..b55c5694 100644 --- a/hw/BRANDS +++ b/hw/BRANDS @@ -8,4 +8,8 @@ Fireflies 0400 - 0499 Mateminco 0500 - 0599 Sofirn 0600 - 0699 Wurkkos 0700 - 0799 -gChart 1600 - 1699 +... +gChart 1600 - 1699 (also thefreeman, since he picked 163X) +... +reserved 1900 - 2199 (to ensure no overlap between years and model numbers) + (assumes this project won't be relevant in the year 2200 or later) From 6589bea67429f8837fd555f06ab933b8950cdf38 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 3 Dec 2023 17:49:25 -0700 Subject: [PATCH 48/57] docs: expanded / reorganized info on Version Check formats --- docs/anduril-manual.md | 65 +++++++++++++++++++++++++++++++++--------- docs/which-hex-file.md | 42 +++++++-------------------- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/docs/anduril-manual.md b/docs/anduril-manual.md index 93c64288..68c577ca 100644 --- a/docs/anduril-manual.md +++ b/docs/anduril-manual.md @@ -728,26 +728,63 @@ Version Check Mode ------------------ This allows people to see which version of the firmware is installed on -their light. The format for this is (usually) 12 digits -- a model -number and a date. `BBPP.YYYY-MM-DD` +their light. The format for this is usually a model number and a date. +`MODEL.YYYY-MM-DD` - - `BB`: Brand ID - - `PP`: Product ID + - `MODEL`: Model number + (usually `BBPP` where BB is the brand ID, and PP is the product ID) - `YYYY`: Year - `MM`: Month - `DD`: Day -Versions before 2023-05-30 used `YYYYMMDDBBPP` format. -Anduril 1 used only `YYYYMMDD` format, or none at all. +The version number format has changed a few times, so write down the version +info and check it against the formats below. -The date is when the firmware was compiled. If the vendor did not set -this value, it defaults to 1969-07-20, the date of first human contact -with the moon. However, it might not be a date at all; some vendors may -specify a completely different type of value here. +The model number is very important when flashing new firmware. Make sure +the new firmware has the same model number as the old firmware. More details +on this are in [Which Hex File](which-hex-file.md). Use the +[MODELS](../MODELS) file to map a model number to the name of a .hex file. -The brand/product values are also known as the model number. These are -hard-coded in the source code for each light's build target, and can be -looked up in the "MODELS" file or by using the "make models" command. +## Version Check Formats + +The Version Check function should blink out a series of numbers in one of +several formats: + + - `MODEL-YYYY-MM-DD-SINCE-DIRTY` + Anduril 2 from 2023-12 or later. "SINCE" and "DIRTY" may be omitted. + Punctuation makes a "buzz" between sections. + - `MODEL`: model number + - `YYYY-MM-DD`: Year, month, day. This uses the most recent release tag + from git, not the build date. + - `SINCE`: How many commits since the last official release tag? + - `DIRTY`: Adds a "-1" to the end if the repository was locally modified + without committing changes. + + - `NNNN-YYYY-MM-DD` + Anduril 2 from 2023-05 or later. + It's a model number and build date, + with "buzz" flashes between sections. + - `NNNN`: model number + - `YYYY`: year + - `MM`: month + - `DD`: day + + - `YYYYMMDDNNNN` + Anduril 2 from 2023-05 or earlier. + It's a build date and model number. + +- `YYYYMMDD` + This is an old Anduril 1 version. It's just a build date. + If the model name isn't obvious, try looking it up in the PRODUCTS file. + +- `1969-07-20` + The date of first human contact with the moon. This value indicates that + the person who built the firmware probably made some sort of error. + +If the version doesn't include a model number, you may be able to find +the model in the PRODUCTS file to see which firmware model it probably uses: + + https://bazaar.launchpad.net/~toykeeper/flashlight-firmware/anduril2/view/head:/PRODUCTS Protection Features @@ -811,6 +848,8 @@ In voltage mode, the colors follow the same sequence, in the same order as a rainbow... with red indicating a low battery and purple indicating a full battery. +![battery charge colors](battery-rainbow.png) + For lights with a button LED, the button LED typically stays on while the main emitters are on. Its brightness level is set in a way which mirrors the main LED -- off, low, or high. diff --git a/docs/which-hex-file.md b/docs/which-hex-file.md index d59c6bdc..38472170 100644 --- a/docs/which-hex-file.md +++ b/docs/which-hex-file.md @@ -1,41 +1,21 @@ # How to figure out which .hex file to use -1. Use the version check function (15 or more clicks from Off) to find out +The name of a product is **not** enough information to find the right .hex +file. Ask the light what firmware it needs! + +1. Use the Version Check function (15 or more clicks from Off) to find out which flavor of the firmware the light has installed. **WRITE THIS DOWN.** 2. Look up the model number in the [MODELS file](../MODELS), to get the name and MCU type. -3. Find the newest firmware for that model. - https://github.com/ToyKeeper/anduril/releases - https://toykeeper.net/torches/fsm/anduril2/?C=M;O=D - -If the version doesn't include a model number, you may be able to find -the model in the PRODUCTS file to see which version it probably uses: - - https://bazaar.launchpad.net/~toykeeper/flashlight-firmware/anduril2/view/head:/PRODUCTS - - -## Version Check Formats - -The Version Check function should blink out a series of numbers in one of -several formats: - - - `NNNN-YYYY-MM-DD` - Anduril 2 from 2023-05 or later. - It's a model number and build date, - with "buzz" flashes between sections. - - `NNNN`: model number - - `YYYY`: year - - `MM`: month - - `DD`: day - - - `YYYYMMDDNNNN` - Anduril 2 from 2023-05 or earlier. - It's a build date and model number. +3. Find (or build) the newest firmware for that model. + https://github.com/ToyKeeper/anduril/releases -- `YYYYMMDD` - This is an old Anduril 1 version. It's just a build date. - If the model name isn't obvious, try looking it up in the PRODUCTS file. +The Version Check format has changed a few times. Use +[this section of the manual](anduril-manual.md#Version_Check_Formats) +to learn about those formats and how to use them. In most cases, it should +have a model number and a date... and you need the model number to find the +correct .hex file. From bc0b4625a1618d9322ea6a5f0bb402f8ddc0aad6 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 3 Dec 2023 18:31:04 -0700 Subject: [PATCH 49/57] ChangeLog: added 2023-12-03 release notes, converted @modelname to &modelname (because the @ was causing people to get tagged when their username happened to be the same as a brand or model name) --- ChangeLog.md | 167 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 115 insertions(+), 52 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 0aaa392d..eb0d0624 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -10,10 +10,73 @@ formats: - Removed - Changed - Documented - - @brand-model: Hardware-specific change (NNNN, NNNN, ...) + - &brand-model: Hardware-specific change (NNNN, NNNN, ...) # Next +# 2023-12-03 + +This release is somewhat higher risk than usual, because so many large things +changed deep in the code. I did major restructuring and refactoring across the +entire project. It should work fine, but be on the lookout for any weird +problems. + +General: + +- Moved from Bzr + Launchpad to **Git + GitHub**, by popular request. +- **Completely reorganized the project** files. Really, a *massive* amount of + restructuring. The flashlight end-user interface is still the same, but + expect to have to learn the code layout from scratch. Read the [README.md] + for info about getting started with the new project layout. +- Added support for AVR DD MCUs like **avr32dd20**. This is the recommended + MCU to use in new flashlights. +- Added ability to use turbo in momentary mode. +- Upgraded **battery voltage resolution** from 0.1V steps to **0.025V** steps. + Battery check has an extra digit which can be 0, 2, 5, or 7 (for example, for + 3.70V, 3.725V, .3.75V, and 3.775V). +- Re-calibrated timing on each MCU type, so a 1-second beacon flasher should be + closer to 1 actual second now... mostly. Timing still varies significantly + from one light to another. +- Fixed default bike flasher brightness on some builds. It was sometimes way + too high. +- Fixed RGB aux turning on during momentary mode sometimes. +- Converted documentation to markdown format, and rewrote a lot of it. +- Fixed some build issues with specific compile-time options. +- Changed the format of **version numbers**. It now uses the most recent + release tag instead of the build date, and **may have additional numbers at + the end** to indicate distance from the last official release, and whether + the repo was clean or dirty. Today's release is `MODEL-2023-12-03`. A + derivative built 52 commits later in a dirty repo would look like + `MODEL-2023-12-03-52-1`. + +New lights: + +- Added &thefreeman-avr32dd20-devkit. It's only used for development purposes, + but otherwise it's pretty neat. It'll be the basis for many new lights in + the future. (model 1632dd20) + +Hardware-specific changes: + +- Improved idle efficiency on attiny1616, which was spending entirely too much + time doing math it didn't actually need. +- &hank-\*-boost: Fixed flicker while holding button at moon level. Reduced + ripple on low modes. (0216, 0253, 0273) +- &lumintop-blf-gt: Added smooth steps. Removed a couple other things to make + room. (0321) +- &lumintop-fw3x: Multiple fixes and upgrades... (0314, 0315) + - Fixed thermal regulation. Also fixed the external temperature sensor. + - Made moon much lower, and made ramp much smoother, by upgrading to DSM. + - Fixed the aux RGB pinouts because Lumintop got the wiring backward. + - Added a second build target for people who fixed the wires manually. + - Added red/blue police color strobe. + - Made low modes more efficient with underclocking. Moon should run at least + 4X as long as it did before. + - Fixed party strobe being blurry. + - Added documentation for the FW3X's multiple, uh, quirks. +- &sofirn-lt1s-pro: Disabled manual memory, memory timer, and extended simple + UI by default. Simple mode is simpler, and the factory settings should be + more consistent with other lights now. (0623) + # 2023-10-31 General: @@ -37,30 +100,30 @@ General: New lights: -- @thefreeman-boost21-6a: Added. (1631) +- &thefreeman-boost21-6a: Added. (1631) (very nice HDR boost driver which fits into a FW3A) -- @thefreeman-boost-fwaa: Added. (1632) +- &thefreeman-boost-fwaa: Added. (1632) (very nice AA/li-ion HDR boost driver which fits into a FWAA) Hardware-specific changes: - Upgraded several builds to use delta-sigma modulation (DSM), for lower lows and smoother ramping with less flicker or ripple: - - @blf-lt1 (0621) - - @blf-lt1-t1616 (0622) - - @emisar-d4k-3ch (0151) + - &blf-lt1 (0621) + - &blf-lt1-t1616 (0622) + - &emisar-d4k-3ch (0151) (**dramatically** improves resolution and low modes on its 8-bit channel) - - @noctigon-dm11-boost (0273) - - @noctigon-kr4-boost (0216) - - @noctigon-k1-boost (0253) - - @noctigon-m44 (0143) + - &noctigon-dm11-boost (0273) + - &noctigon-kr4-boost (0216) + - &noctigon-k1-boost (0253) + - &noctigon-m44 (0143) - Upgraded some builds to use dynamic PWM, for lower lows and smoother ramping: - - @blf-q8-t1616, @sofirn-sp36-t1616 (0613, 0614) - - @gchart-fet1-t1616 (1618) - - @noctigon-k1-sbt90 (0252) + - &blf-q8-t1616, &sofirn-sp36-t1616 (0613, 0614) + - &gchart-fet1-t1616 (1618) + - &noctigon-k1-sbt90 (0252) -- @wurkkos-ts10, @wurkkos-ts10-rgbaux: Fixed too-high default ceiling. (0713, 0714) +- &wurkkos-ts10, &wurkkos-ts10-rgbaux: Fixed too-high default ceiling. (0713, 0714) # 2023-10-01 @@ -75,42 +138,42 @@ General: - Fixed some minor post-off voltage display bugs. - Made RGB button brightness update faster in blinky modes. - Fixed bug: Wrong channel after colored factory reset. -- @attiny1616, @attiny1634: Partially fixed oscillating aux LED voltage +- &attiny1616, &attiny1634: Partially fixed oscillating aux LED voltage colors while off. Better than before, but can still happen in some cases. -- @attiny1616: Fixed spurious voltage warnings in sleep mode. (it could +- &attiny1616: Fixed spurious voltage warnings in sleep mode. (it could sometimes go from Lockout mode to Off mode by itself) - Lots of internal refactoring. New lights: -- @emisar-2ch-fet: Added. (0136) -- @emisar-d4k-3ch: Added. (0151) -- @noctigon-m44: Added. (0143) -- @wurkkos-ts10-rgbaux: Added. (0713) +- &emisar-2ch-fet: Added. (0136) +- &emisar-d4k-3ch: Added. (0151) +- &noctigon-m44: Added. (0143) +- &wurkkos-ts10-rgbaux: Added. (0713) Hardware-specific changes: -- @ff-e01, @ff-pl47, @ff-pl47g2: Enabled smooth steps instead of SOS mode. +- &ff-e01, &ff-pl47, &ff-pl47g2: Enabled smooth steps instead of SOS mode. (0421, 0422, 0423, 0441) -- @emisar-2ch, @noctigon-m44: Added RGB aux channel modes. (0135, 0143) -- @emisar-2ch-fet, @noctigon-k9.3: New ramps with better-calibrated shape. +- &emisar-2ch, &noctigon-m44: Added RGB aux channel modes. (0135, 0143) +- &emisar-2ch-fet, &noctigon-k9.3: New ramps with better-calibrated shape. (0136, 0261) -- @emisar-d4v2-nofet: New ramp table. (0115) -- @emisar-d4sv2-tintramp: Removed / renamed. (0135, 0136) -- @noctigon-k9.3: Fixed years-old mess. Merged builds, converted to +- &emisar-d4v2-nofet: New ramp table. (0115) +- &emisar-d4sv2-tintramp: Removed / renamed. (0135, 0136) +- &noctigon-k9.3: Fixed years-old mess. Merged builds, converted to multi-channel, removed old builds, generally got K9.3 working quite a bit better. (0261, 0262, 0263, 0265, 0266, 0267) -- @noctigon-m44: Lower moon, and greatly reduced flicker. (0143) -- @sofirn-lt1s-pro: Allow configuring the blink channel. (0623) -- @wurkkos: Raised default temperature limit to 50 C. (07xx) -- @wurkkos-ts10: Better / smoother ramp. (0713, 0714) +- &noctigon-m44: Lower moon, and greatly reduced flicker. (0143) +- &sofirn-lt1s-pro: Allow configuring the blink channel. (0623) +- &wurkkos: Raised default temperature limit to 50 C. (07xx) +- &wurkkos-ts10: Better / smoother ramp. (0713, 0714) # 2023-06-29 - Fixed red aux blink on 1st frame of post-off voltage display - Removed Harry Potter references because its author (J.K. Rowling) spreads hate -- @noctigon-kr4: Fixed thermal regulation (0211, 0212, 0213, 0214, 0215, 0216) +- &noctigon-kr4: Fixed thermal regulation (0211, 0212, 0213, 0214, 0215, 0216) # 2023-05-30 @@ -126,18 +189,18 @@ Hardware-specific changes: help ensure it works on all lights. - Minor code changes with no runtime impact - Documented new version check format -- @wurkkos: Added red+blue police strobe (0715, 0716, 0717) -- @noctigon-kr4: Broke thermal regulation (oops) (0211, 0212, 0213, 0214, +- &wurkkos: Added red+blue police strobe (0715, 0716, 0717) +- &noctigon-kr4: Broke thermal regulation (oops) (0211, 0212, 0213, 0214, 0215, 0216) -- @noctigon-kr4: Use 7 aux channel modes instead of 3 (0211, 0212, 0213, 0214, +- &noctigon-kr4: Use 7 aux channel modes instead of 3 (0211, 0212, 0213, 0214, 0215, 0216) -- @emisar-d4v2: Changed number blinks from aux to main LEDs by default (0113, +- &emisar-d4v2: Changed number blinks from aux to main LEDs by default (0113, 0114, 0115, 0123) # 2023-05-17 -- @noctigon-dm11-12v: Renamed to noctigon-dm11-boost (0273) -- @noctigon-dm11-boost: Now supported in multi-channel branch (0273) +- &noctigon-dm11-12v: Renamed to noctigon-dm11-boost (0273) +- &noctigon-dm11-boost: Now supported in multi-channel branch (0273) # 2023-05-02 @@ -160,14 +223,14 @@ Hardware-specific changes: it to the value it saved, which was wrong) - Documented ramp 6C, ramp 4C, ramp 4H, lockout 3H, battcheck 3C, and post-off voltage display config -- @emisar-d4v2: Added the rest of the aux RGB colors as channel modes, and set +- &emisar-d4v2: Added the rest of the aux RGB colors as channel modes, and set aux "white" as the mode it uses to blink out numbers (0113, 0114, 0115, 0123) -- @wurkkos-ts10: Converted to multi-channel, and gave it a new ramp with +- &wurkkos-ts10: Converted to multi-channel, and gave it a new ramp with better low modes (0714) -- @wurkkos-ts25: Converted to multi-channel, and gave it a smoother ramp +- &wurkkos-ts25: Converted to multi-channel, and gave it a smoother ramp (0715) -- @wurkkos: Added Wurkkos FC13 and TS11 (0716, 0717) +- &wurkkos: Added Wurkkos FC13 and TS11 (0716, 0717) # 2023-04-29 @@ -178,13 +241,13 @@ Hardware-specific changes: - Made 3H+ use mem level instead of lowest moon (this is needed for making the channel discernible, and also helps make aux LED controls stand out more) -- @emisar, @noctigon: Added Extended Simple UI to Hank's config, so a few more +- &emisar, &noctigon: Added Extended Simple UI to Hank's config, so a few more features are allowed in simple mode -- @emisar-d4v2, @noctigon-kr4: Slightly smaller ROM size -- @emisar-d4sv2: Converted to multi-channel, and updated it to use dynamic PWM +- &emisar-d4v2, &noctigon-kr4: Slightly smaller ROM size +- &emisar-d4sv2: Converted to multi-channel, and updated it to use dynamic PWM for a smoother ramp with lower lows (0133, 0134) -- @noctigon-kr4: Converted to multi-channel (0211, 0212, 0213, 0214) -- @noctigon-kr4: Don't blink at top of regulated power (0211, 0213, 0214) +- &noctigon-kr4: Converted to multi-channel (0211, 0212, 0213, 0214) +- &noctigon-kr4: Don't blink at top of regulated power (0211, 0213, 0214) # 2023-04-28 @@ -196,8 +259,8 @@ Hardware-specific changes: default) - Changed tactical mode default config: only use 2-color strobe if it's on main LEDs, not aux LEDs -- @emisar-d4v2: Smoother ramp (0113, 0114) -- @emisar-d4v2: Added hidden channel modes for RGB aux LEDs (0113, 0114, 0115) +- &emisar-d4v2: Smoother ramp (0113, 0114) +- &emisar-d4v2: Added hidden channel modes for RGB aux LEDs (0113, 0114, 0115) # 2023-04-27 @@ -207,7 +270,7 @@ Hardware-specific changes: - Fixed unnecessary flickering when changing channel modes from/to the same value - Fixed sleep voltage measurement on attiny1616 -- @noctigon-kr4-tintramp: Converted to multi-channel, renamed to +- &noctigon-kr4-tintramp: Converted to multi-channel, renamed to noctigon-kr4-2ch (0215) # 2023-04-25 @@ -226,15 +289,15 @@ Hardware-specific changes: (this change was obsoleted soon by a better post-off voltage display) - Broke sleep voltage measurement on attiny1616 (oops) - Changed internal details for how gradual ramping works -- @emisar-d4sv2-tintramp: Converted to multi-channel, renamed to emisar-2ch. +- &emisar-d4sv2-tintramp: Converted to multi-channel, renamed to emisar-2ch. (0135) -- @sofirn-lt1s-pro: Updated to use today's new code internals (0623) +- &sofirn-lt1s-pro: Updated to use today's new code internals (0623) # 2023-04-19 - Added stepped tint ramping - Documented new channel modes system -- @sofirn-lt1s-pro: Added white-only auto-tint mode (0623) +- &sofirn-lt1s-pro: Added white-only auto-tint mode (0623) # Older: TODO From 2b6dbb0b839d6894745698f98d25e786e065ff7a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 5 Dec 2023 11:51:55 -0700 Subject: [PATCH 50/57] forgot one item in the ChangeLog --- ChangeLog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index eb0d0624..a70a3989 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -34,6 +34,8 @@ General: - Upgraded **battery voltage resolution** from 0.1V steps to **0.025V** steps. Battery check has an extra digit which can be 0, 2, 5, or 7 (for example, for 3.70V, 3.725V, .3.75V, and 3.775V). +- Made Battery Check more consistent, so it's less likely to give different + values on the 1st and 2nd readout. - Re-calibrated timing on each MCU type, so a 1-second beacon flasher should be closer to 1 actual second now... mostly. Timing still varies significantly from one light to another. From 7153149c99e416f6efad3b84e5b550c0abf56454 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Tue, 5 Dec 2023 11:54:54 -0700 Subject: [PATCH 51/57] moved version string calculation to bin/version-string.sh Also updated the format slightly, so this rev is: `2023-12-03+2#1` +N for commits since tag #1 for dirty --- bin/build-all.sh | 14 +---------- bin/version-string.sh | 58 +++++++++++++++++++++++++++++++++++++++++++ make | 4 +++ 3 files changed, 63 insertions(+), 13 deletions(-) create mode 100755 bin/version-string.sh diff --git a/bin/build-all.sh b/bin/build-all.sh index f239217d..f2420a7c 100755 --- a/bin/build-all.sh +++ b/bin/build-all.sh @@ -80,19 +80,7 @@ function make-version-h { # old: version = build date #date '+#define VERSION_NUMBER "%Y-%m-%d"' > ui/$UI/version.h - # version = git tag + revs since + dirty flag - REV=$(git describe --tags --dirty --abbrev=8 --match='r2*') - # reformatting this would be easier with a perl one-liner, - # but I'm trying to avoid extra build dependencies - REV="${REV:1}" # strip the leading 'r' - # strip rev hash (git won't give "commits since tag" without the rev hash) - REV="${REV/-g[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]/}" - REV="${REV/-dirty/.1}" # convert '-dirty' to '.1' - # handle an empty name (happens during github action runs) - if [[ -z "$REV" ]]; then - HASH=$(git describe --always) - REV="0.$HASH" - fi + REV=$(bin/version-string.sh c) # save the version name to version.h mkdir -p ".build/$UI" echo '#define VERSION_NUMBER "'"$REV"'"' > ".build/$UI/version.h" diff --git a/bin/version-string.sh b/bin/version-string.sh new file mode 100755 index 00000000..c1c51552 --- /dev/null +++ b/bin/version-string.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Print a version string for the currently-checked-out code. +# Copyright (C) 2023 Selene ToyKeeper +# SPDX-License-Identifier: GPL-3.0-or-later + +# Usage: version-string.sh [c|git|both] +# Prints in C or Git format. Defaults to both. + +function main { + # eat first arg if invoked via 'make' + [[ "version" = "$1" ]] && shift + + # default to showing both formats + ARGS="$*" + [[ -z "$ARGS" ]] && ARGS="both" + + for arg in $ARGS ; do + case "$arg" in + git|g) + git-describe + ;; + c|C) + c-version-string + ;; + *) + echo -n 'C: ' ; c-version-string + echo -n 'git: ' ; git-describe + ;; + esac + done +} + +function git-describe { + git describe --tags --dirty --match='r2*' +} + +function c-version-string { + # version = git tag + revs since + dirty flag + REV=$(git-describe) + # convert "r2020-01-01-158-g0abcdef-dirty" to "2020-01-01+158#1" + REV=$(echo "$REV" | + sed -E 's/^r//; + s/-dirty/#1/; + s/-g[0-9a-f]+//; + s/^([0-9]{4}-[0-9]{2}-[0-9]{2})-/\1+/; + ' + ) + # handle an empty name (can happen during github action runs) + if [[ -z "$REV" ]]; then + HASH=$(git describe --always) + REV="0.$HASH" + fi + # print the version string + echo "$REV" +} + +main "$@" + diff --git a/make b/make index d34a4b8d..ca3a84a4 100755 --- a/make +++ b/make @@ -27,6 +27,7 @@ Usage: ./make TASK docs Convert all .md files to .html models Generate the MODELS file release Zip up all .hex files to prep for publishing a release + version Show the current version string todo Show tasks noted in source code files ... or TASK can be the partial name of a build target. @@ -75,6 +76,9 @@ function main() { release) ./bin/make-release.sh "$@" ;; + version) + ./bin/version-string.sh "$@" + ;; todo) grep -E 'TODO:|FIXME:' -- **/*.[ch] **/*.md ;; From 1d57e4a89ebe628ef8bcf9e324c9d1c2070d3685 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 10 Dec 2023 17:47:50 -0700 Subject: [PATCH 52/57] fw3x: reduced pulsing on low modes --- hw/lumintop/fw3x-lume1/anduril.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/lumintop/fw3x-lume1/anduril.h b/hw/lumintop/fw3x-lume1/anduril.h index cd06c6a2..852e1c47 100644 --- a/hw/lumintop/fw3x-lume1/anduril.h +++ b/hw/lumintop/fw3x-lume1/anduril.h @@ -34,8 +34,8 @@ #define DEFAULT_LEVEL 56 #define MAX_1x7135 149 #define MIN_THERM_STEPDOWN 50 -#define HALFSPEED_LEVEL 21 -#define QUARTERSPEED_LEVEL 11 +#define HALFSPEED_LEVEL 11 +#define QUARTERSPEED_LEVEL 2 #define RAMP_SMOOTH_FLOOR 1 #define RAMP_SMOOTH_CEIL 149 From 0c498d9715fc9da9017d03b6e8212ef79593e034 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 11 Dec 2023 17:37:36 -0700 Subject: [PATCH 53/57] clarified which-hex-file.md a bit; make sure the model number matches --- docs/which-hex-file.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/which-hex-file.md b/docs/which-hex-file.md index 38472170..9dcc6443 100644 --- a/docs/which-hex-file.md +++ b/docs/which-hex-file.md @@ -1,7 +1,10 @@ # How to figure out which .hex file to use -The name of a product is **not** enough information to find the right .hex -file. Ask the light what firmware it needs! +Using the wrong firmware will make the light stop working, so when flashing +firmware, **be sure the model number matches**! + +The name of a product is *not* enough information to find the right .hex +file. Ask the light what firmware it needs: 1. Use the Version Check function (15 or more clicks from Off) to find out which flavor of the firmware the light has installed. @@ -16,6 +19,6 @@ file. Ask the light what firmware it needs! The Version Check format has changed a few times. Use [this section of the manual](anduril-manual.md#Version_Check_Formats) to learn about those formats and how to use them. In most cases, it should -have a model number and a date... and you need the model number to find the -correct .hex file. +have a model number and a date... and **you need the model number** to find +the correct .hex file. From 8572911b9a8902d25480ed08a9c6b6486b8735ba Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 15 Dec 2023 04:45:51 -0700 Subject: [PATCH 54/57] use BLIP_LEVEL instead of 0 for "blip"s This helps when using a regulator which doesn't like being turned off and back on quickly. --- hw/thefreeman/avr32dd20-devkit/anduril.h | 1 + ui/anduril/misc.c | 4 ++-- ui/anduril/misc.h | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/thefreeman/avr32dd20-devkit/anduril.h b/hw/thefreeman/avr32dd20-devkit/anduril.h index 02d5de37..3152183f 100644 --- a/hw/thefreeman/avr32dd20-devkit/anduril.h +++ b/hw/thefreeman/avr32dd20-devkit/anduril.h @@ -110,6 +110,7 @@ #define PARTY_STROBE_ONTIME 1 // slow down party strobe #define STROBE_OFF_LEVEL 1 // keep the regulator chip on between pulses +#define BLIP_LEVEL 1 // same // smoother candle mode with bigger oscillations #define CANDLE_AMPLITUDE 40 diff --git a/ui/anduril/misc.c b/ui/anduril/misc.c index 3715f341..9144b283 100644 --- a/ui/anduril/misc.c +++ b/ui/anduril/misc.c @@ -25,7 +25,7 @@ void blink_confirm(uint8_t num) { void blink_once() { uint8_t brightness = actual_level; uint8_t bump = brightness + BLINK_BRIGHTNESS; - if (bump > MAX_LEVEL) bump = 0; + if (bump > MAX_LEVEL) bump = BLIP_LEVEL; set_level(bump); delay_4ms(BLINK_ONCE_TIME/4); @@ -35,7 +35,7 @@ void blink_once() { // Just go dark for a moment to indicate to user that something happened void blip() { uint8_t temp = actual_level; - set_level(0); + set_level(BLIP_LEVEL); delay_4ms(3); set_level(temp); } diff --git a/ui/anduril/misc.h b/ui/anduril/misc.h index 0f2992a3..b259a6e4 100644 --- a/ui/anduril/misc.h +++ b/ui/anduril/misc.h @@ -4,6 +4,10 @@ #pragma once +#ifndef BLIP_LEVEL +#define BLIP_LEVEL 0 +#endif + //void blink_confirm(uint8_t num); // no longer used void blink_once(); void blip(); From 0725045fc2d6f974f50d59755f9bbecd0c33ee23 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 15 Dec 2023 04:55:40 -0700 Subject: [PATCH 55/57] build.sh: don't require DFPs, newer avr-libc doesn't need them --- bin/build.sh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bin/build.sh b/bin/build.sh index d044ca55..ed0a837e 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -37,12 +37,14 @@ else echo "Unrecognized MCU type: '$MCUNAME'" exit 1 fi -# ensure the DFP files exist -if [ ! -d "$DFPPATH" ]; then - echo "Atmel DFP files not found: '$DFPPATH'" - echo "Install DFP files with './make dfp'" - exit 1 -fi +# skip verification because newer avr-libc doesn't need DFPs, +# so the DFP shouldn't be mandatory +## ensure the DFP files exist +#if [ ! -d "$DFPPATH" ]; then +# echo "Atmel DFP files not found: '$DFPPATH'" +# echo "Install DFP files with './make dfp'" +# exit 1 +#fi export CC=avr-gcc export CPP=avr-cpp From 21ef87919046d0d9bd8932b2635251eff22f7563 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 17 Dec 2023 00:17:32 -0700 Subject: [PATCH 56/57] documented Wurkkos TS25/TS11/FC13 distinctions --- MODELS | 12 ++++++------ hw/wurkkos/fc13/README.md | 10 ++++++++++ hw/wurkkos/ts11/README.md | 8 ++++++++ hw/wurkkos/ts25/README.md | 20 ++++++++++++++++++++ 4 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 hw/wurkkos/fc13/README.md create mode 100644 hw/wurkkos/ts11/README.md create mode 100644 hw/wurkkos/ts25/README.md diff --git a/MODELS b/MODELS index ef280fa3..a77b178f 100644 --- a/MODELS +++ b/MODELS @@ -34,9 +34,9 @@ Model MCU Name 0261 attiny1634 hank-noctigon-k9.3 0262 attiny1634 hank-noctigon-k9.3-nofet 0263 attiny1634 hank-noctigon-k9.3-219 -0265 attiny1634 noctigon-k9.3-tintramp-nofet (old, use 0262) -0266 attiny1634 noctigon-k9.3-tintramp-fet (old, use 0261) -0267 attiny1634 noctigon-k9.3-tintramp-219 (old, use 0263) +0265 attiny1634 noctigon-k9.3-tintramp-nofet (old, use 0262) +0266 attiny1634 noctigon-k9.3-tintramp-fet (old, use 0261) +0267 attiny1634 noctigon-k9.3-tintramp-219 (old, use 0263) 0271 attiny1634 hank-noctigon-dm11 0272 attiny1634 hank-noctigon-dm11-nofet 0273 attiny1634 hank-noctigon-dm11-boost @@ -69,9 +69,9 @@ Model MCU Name 0632 attiny1616 sofirn-sc21-pro 0713 attiny1616 wurkkos-ts10-rgbaux 0714 attiny1616 wurkkos-ts10 -0715 attiny1616 wurkkos-ts25 -0716 attiny1616 wurkkos-fc13 -0717 attiny1616 wurkkos-ts11 +0715 attiny1616 wurkkos-ts25 (may need 0716 / 0717 on some models) +0716 attiny1616 wurkkos-fc13 (may ship with 0715) (also, TS30S Pro) +0717 attiny1616 wurkkos-ts11 (may ship with 0715) 1618 attiny1616 gchart-fet1-t1616 1630 attiny1616 thefreeman-lin16dac 1631 attiny1616 thefreeman-boost21-mp3431-hdr-dac-argb diff --git a/hw/wurkkos/fc13/README.md b/hw/wurkkos/fc13/README.md new file mode 100644 index 00000000..ab9b87fe --- /dev/null +++ b/hw/wurkkos/fc13/README.md @@ -0,0 +1,10 @@ +# Wurkkos FC13 + +Single LED 18650 torch with FET+1 driver and RGB button. Includes a built-in +charger / powerbank too, separate from the main torch circuit. + +The Wurkkos SP30S Pro also uses this firmware. + +Either torch may ship with the `0715` (wurkkos-ts25) firmware installed, but +the RGB button does not work fully until upgrading to this FC13 firmware. + diff --git a/hw/wurkkos/ts11/README.md b/hw/wurkkos/ts11/README.md new file mode 100644 index 00000000..e53e0386 --- /dev/null +++ b/hw/wurkkos/ts11/README.md @@ -0,0 +1,8 @@ +# Wurkkos TS11 + +Single LED 18350 / 18650 torch with FET+1 driver, RGB button, and RGB front +aux. Includes a built-in charger too, separate from the main torch circuit. + +May ship with the `0715` (wurkkos-ts25) firmware installed, but the RGB button +does not work fully until upgrading to this TS11 firmware. + diff --git a/hw/wurkkos/ts25/README.md b/hw/wurkkos/ts25/README.md new file mode 100644 index 00000000..b3c33afc --- /dev/null +++ b/hw/wurkkos/ts25/README.md @@ -0,0 +1,20 @@ +# Wurkkos TS25 + +A quad LED 21700 light with FET+1 driver and RGB front aux. A charge port is +built in too, but operates independently and is not visible to the main +firmware. + +Some other Wurkkos models may also ship with this firmware, and should be +upgraded to use a more specific build: + + - FC13: use wurkkos-fc13 + - TS11: use wurkkos-ts11 + - SP30S Pro: use wurkkos-fc13 + +These builds have different aux LED behavior. The difference is whether the +RGB aux is on the front, the side (button), or both. + + - Front: TS25 + - Side: FC13 + - Both: TS11 + From 312f7442c31d72dd36f108de9542f81960526658 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 17 Dec 2023 00:18:14 -0700 Subject: [PATCH 57/57] documented FW3X swapped pins better --- hw/lumintop/fw3x-lume1/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/lumintop/fw3x-lume1/README.md b/hw/lumintop/fw3x-lume1/README.md index 190cd0ef..d155ebad 100644 --- a/hw/lumintop/fw3x-lume1/README.md +++ b/hw/lumintop/fw3x-lume1/README.md @@ -6,9 +6,10 @@ sensor. ## Notes of interest -**Flashing firmware**: The MOSI and MISO pin are swapped, compared to a Hanklight. -LoneOceans sent a fixed driver design to Lumintop, but the new design didn't -get produced. So to flash firmware, swap the wires for those two pins first. +**Flashing firmware**: The MOSI and MISO pin are swapped on PCBs dated 01/20, +compared to a Hanklight. LoneOceans sent a fixed driver design (dated 06/20) +to Lumintop, but the new design didn't get produced. So to flash firmware, +swap the wires for those two pins first. **Fuses**: Lumintop seems to have shipped the FW3X with the wrong fuse values, so it has the MCU severely underclocked and everything runs much slower than it @@ -29,3 +30,6 @@ output is unstable so there is very visible ripple. The user can either raise the ramp floor to a level high enough to avoid these issues, or learn to live with the ripple and preflash. +LoneOceans has some extra notes here, which mostly apply only to older versions +of the code: https://budgetlightforum.com/t/anduril-2/62656/531 +