aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--arch/attiny1634.c129
-rw-r--r--arch/attiny1634.h40
-rw-r--r--hw/hank/emisar-2ch/fet/hwdef.h30
-rw-r--r--hw/hank/emisar-2ch/hwdef.h30
-rw-r--r--hw/hank/emisar-d4k-3ch/hwdef.h30
-rw-r--r--hw/hank/noctigon-dm11/boost/hwdef.h30
-rw-r--r--hw/hank/noctigon-dm11/hwdef.h30
-rw-r--r--hw/hank/noctigon-k1/boost/hwdef.h30
-rw-r--r--hw/hank/noctigon-k1/hwdef.h30
-rw-r--r--hw/hank/noctigon-k1/sbt90/hwdef.h31
-rw-r--r--hw/hank/noctigon-kr4/hwdef.h30
-rw-r--r--hw/hank/noctigon-m44/hwdef.h30
-rw-r--r--hw/hank/vdivider-1634.h39
13 files changed, 181 insertions, 328 deletions
diff --git a/arch/attiny1634.c b/arch/attiny1634.c
index 0737a81..e29d1c3 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<<ADEN); //ADC off
}
+// left-adjusted mode:
inline uint16_t mcu_adc_result() { return ADC; }
+//inline uint16_t mcu_adc_result() { return (uint16_t)(ADCL | (ADCH << 8)); }
+// right-adjusted mode:
+/*
+inline uint16_t mcu_adc_result() {
+ uint16_t result = (ADCL | (ADCH << 8)) << 6;
+ return result;
+}
+*/
+
+inline uint8_t mcu_vdd_raw2cooked(uint16_t measurement) {
+ // In : 65535 * 1.1 / Vbat
+ // Out: uint8_t: Vbat * 40
+ // 1.1 = 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.1 * 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.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<<WDRF); // clear watchdog reset flag
+ // _PROTECTED_WRITE(WDTCSR, 0);
CCP = 0xD8; // enable config changes
WDTCSR = 0; // disable and clear all WDT settings
sei();
@@ -113,6 +195,7 @@ inline void mcu_pcint_off() {
void reboot() {
// put the WDT in hard reset mode, then trigger it
cli();
+ // _PROTECTED_WRITE(WDTCSR, 0b10001000);
// allow protected configuration changes for next 4 clock cycles
CCP = 0xD8; // magic number
// reset (WDIF + WDE), no WDIE, fastest (16ms) timing (0000)
@@ -126,6 +209,6 @@ void reboot() {
inline void prevent_reboot_loop() {
// prevent WDT from rebooting MCU again
MCUSR &= ~(1<<WDRF); // reset status flag
- wdt_disable();
+ wdt_disable(); // from avr/wdt.h
}
diff --git a/arch/attiny1634.h b/arch/attiny1634.h
index fb89fa8..559d04e 100644
--- a/arch/attiny1634.h
+++ b/arch/attiny1634.h
@@ -13,20 +13,25 @@
#define BOGOMIPS (F_CPU/4000)
#define DELAY_ZERO_TIME 1020
+inline void mcu_clock_speed();
+
///// clock dividers
inline void clock_prescale_set(uint8_t n);
+// TODO? allow hwdef to define a base clock speed,
+// and adjust these values accordingly
typedef enum
{
- clock_div_1 = 0,
- clock_div_2 = 1,
- clock_div_4 = 2,
- clock_div_8 = 3,
- clock_div_16 = 4,
- clock_div_32 = 5,
- clock_div_64 = 6,
- clock_div_128 = 7,
- clock_div_256 = 8
+ // datasheet 6.5.2, CLKPR - Clock Prescale Register
+ clock_div_1 = 0, // 8 MHz
+ clock_div_2 = 1, // 4 MHz
+ clock_div_4 = 2, // 2 MHz
+ clock_div_8 = 3, // 1 MHz
+ clock_div_16 = 4, // 500 kHz
+ clock_div_32 = 5, // 250 kHz
+ clock_div_64 = 6, // 125 kHz
+ clock_div_128 = 7, // 62.5 kHz
+ clock_div_256 = 8, // 31.75 kHz
} clock_div_t;
@@ -39,11 +44,11 @@ typedef enum
#define ADMUX_VCC 0b00001101
// (1 << V_REF) | (THERM_CHANNEL)
// 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
-
-
-
#define hwdef_set_admux_therm mcu_set_admux_therm
inline void mcu_set_admux_therm();
@@ -54,8 +59,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
@@ -63,6 +66,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/hank/emisar-2ch/fet/hwdef.h b/hw/hank/emisar-2ch/fet/hwdef.h
index 06dfeb8..33eef7e 100644
--- a/hw/hank/emisar-2ch/fet/hwdef.h
+++ b/hw/hank/emisar-2ch/fet/hwdef.h
@@ -107,35 +107,7 @@ enum channel_modes_e {
#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
-#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/emisar-2ch/hwdef.h b/hw/hank/emisar-2ch/hwdef.h
index 7fbac8e..28d1b45 100644
--- a/hw/hank/emisar-2ch/hwdef.h
+++ b/hw/hank/emisar-2ch/hwdef.h
@@ -104,35 +104,7 @@ enum channel_modes_e {
#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
-#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/emisar-d4k-3ch/hwdef.h b/hw/hank/emisar-d4k-3ch/hwdef.h
index 002804c..81206c2 100644
--- a/hw/hank/emisar-d4k-3ch/hwdef.h
+++ b/hw/hank/emisar-d4k-3ch/hwdef.h
@@ -133,35 +133,7 @@ uint8_t led4_pwm, led4_dsm;
#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
-#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-dm11/boost/hwdef.h b/hw/hank/noctigon-dm11/boost/hwdef.h
index bef409f..789eac9 100644
--- a/hw/hank/noctigon-dm11/boost/hwdef.h
+++ b/hw/hank/noctigon-dm11/boost/hwdef.h
@@ -101,35 +101,7 @@ uint8_t ch1_pwm, ch1_dsm;
#define SWITCH_PUE PUEA // pullup group A
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-dm11/hwdef.h b/hw/hank/noctigon-dm11/hwdef.h
index 11cf3a0..3e3d426 100644
--- a/hw/hank/noctigon-dm11/hwdef.h
+++ b/hw/hank/noctigon-dm11/hwdef.h
@@ -96,35 +96,7 @@ enum CHANNEL_MODES {
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-k1/boost/hwdef.h b/hw/hank/noctigon-k1/boost/hwdef.h
index e0a314c..db1584c 100644
--- a/hw/hank/noctigon-k1/boost/hwdef.h
+++ b/hw/hank/noctigon-k1/boost/hwdef.h
@@ -99,35 +99,7 @@ uint8_t ch1_pwm, ch1_dsm;
#define SWITCH_PUE PUEA // pullup group A
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-k1/hwdef.h b/hw/hank/noctigon-k1/hwdef.h
index 822b959..0d20871 100644
--- a/hw/hank/noctigon-k1/hwdef.h
+++ b/hw/hank/noctigon-k1/hwdef.h
@@ -89,35 +89,7 @@ enum CHANNEL_MODES {
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-k1/sbt90/hwdef.h b/hw/hank/noctigon-k1/sbt90/hwdef.h
index 4c56bc0..e2d04a9 100644
--- a/hw/hank/noctigon-k1/sbt90/hwdef.h
+++ b/hw/hank/noctigon-k1/sbt90/hwdef.h
@@ -93,36 +93,7 @@ enum CHANNEL_MODES {
#define SWITCH_PUE PUEB // pullup group B
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// TODO: calibrate this
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
#define TEMP_CHANNEL 0b00001111
diff --git a/hw/hank/noctigon-kr4/hwdef.h b/hw/hank/noctigon-kr4/hwdef.h
index be165bd..49e71fa 100644
--- a/hw/hank/noctigon-kr4/hwdef.h
+++ b/hw/hank/noctigon-kr4/hwdef.h
@@ -97,35 +97,7 @@ enum CHANNEL_MODES {
// so ignore voltage while the button is being held
//#define NO_LVP_WHILE_BUTTON_PRESSED
-#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened
-#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/noctigon-m44/hwdef.h b/hw/hank/noctigon-m44/hwdef.h
index 6bdcef2..a397212 100644
--- a/hw/hank/noctigon-m44/hwdef.h
+++ b/hw/hank/noctigon-m44/hwdef.h
@@ -110,35 +110,7 @@ uint8_t ch2_pwm, ch2_dsm;
#define SWITCH_PUE PUEA // pullup group A
#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
-// pin to ADC mappings are in DS table 19-4
-#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
-// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
-#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
-// DS tables 19-3, 19-4
-// Bit 7 6 5 4 3 2 1 0
-// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
-// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
-// divided by ...
-// REFS[1:0] = 1, 0 for internal 1.1V reference
-// other bits reserved
-#define ADMUX_VOLTAGE_DIVIDER 0b10000110
-#define ADC_PRSCL 0x07 // clk/128
-
-// 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)
-// D1, R1, R2 = 0, 330, 100
-#ifndef ADC_44
-//#define ADC_44 981 // raw value at 4.40V
-#define ADC_44 967 // manually tweaked so 4.16V will blink out 4.2
-#endif
-#ifndef ADC_22
-//#define ADC_22 489 // raw value at 2.20V
-#define ADC_22 482 // manually tweaked so 4.16V will blink out 4.2
-#endif
+#include "hank/vdivider-1634.h"
// this light has aux LEDs under the optic
#define AUXLED_R_PIN PA5 // pin 2
diff --git a/hw/hank/vdivider-1634.h b/hw/hank/vdivider-1634.h
new file mode 100644
index 0000000..171267d
--- /dev/null
+++ b/hw/hank/vdivider-1634.h
@@ -0,0 +1,39 @@
+// attiny1634 voltage divider common defs
+// Copyright (C) 2020-2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+#pragma once
+
+#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened
+#define VOLTAGE_PIN PB1 // Pin 18 / PB1 / ADC6
+// pin to ADC mappings are in DS table 19-4
+#define VOLTAGE_ADC ADC6D // digital input disable pin for PB1
+// DIDR0/DIDR1 mappings are in DS section 19.13.5, 19.13.6
+#define VOLTAGE_ADC_DIDR DIDR1 // DIDR channel for ADC6D
+// DS tables 19-3, 19-4
+// Bit 7 6 5 4 3 2 1 0
+// REFS1 REFS0 REFEN ADC0EN MUX3 MUX2 MUX1 MUX0
+// MUX[3:0] = 0, 1, 1, 0 for ADC6 / PB1
+// divided by ...
+// REFS[1:0] = 1, 0 for internal 1.1V reference
+// other bits reserved
+#define ADMUX_VOLTAGE_DIVIDER 0b10000110
+#undef voltage_raw2cooked
+#define voltage_raw2cooked mcu_vdivider_raw2cooked
+
+#define ADC_PRSCL 0x07 // clk/128
+
+// 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)
+// D1, R1, R2 = 0, 330, 100
+#ifndef ADC_44
+//#define ADC_44 (4*981) // raw value at 4.40V
+#define ADC_44 (4*967) // manually tweaked so 4.16V will blink out 4.2
+#endif
+#ifndef ADC_22
+//#define ADC_22 (4*489) // raw value at 2.20V
+#define ADC_22 (4*482) // manually tweaked so 4.16V will blink out 4.2
+#endif
+
+