aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-11-24 06:29:56 -0700
committerSelene ToyKeeper2023-11-24 06:29:56 -0700
commit8c237206aba74f9096d85f90209ac6b7dc238b1b (patch)
tree529b22b5dec28bdab1029016dde9d85d80039c57
parentavr32dd20-devkit: make the defaults a bit more dev friendly (diff)
downloadanduril-8c237206aba74f9096d85f90209ac6b7dc238b1b.tar.gz
anduril-8c237206aba74f9096d85f90209ac6b7dc238b1b.tar.bz2
anduril-8c237206aba74f9096d85f90209ac6b7dc238b1b.zip
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)
Diffstat (limited to '')
-rw-r--r--arch/attiny1616.c9
-rw-r--r--arch/attiny1616.h24
-rw-r--r--arch/avr32dd20.h13
-rw-r--r--hw/thefreeman/avr32dd20-devkit/anduril.h25
-rw-r--r--hw/thefreeman/avr32dd20-devkit/hwdef.h20
-rw-r--r--hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/anduril.h23
-rw-r--r--hw/thefreeman/boost-fwaa-mp3432-hdr-dac-rgb/hwdef.h37
-rw-r--r--hw/thefreeman/boost21-mp3431-hdr-dac-argb/anduril.h24
-rw-r--r--hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.c14
-rw-r--r--hw/thefreeman/boost21-mp3431-hdr-dac-argb/hwdef.h34
-rw-r--r--hw/thefreeman/lin16dac/anduril.h22
-rw-r--r--hw/thefreeman/lin16dac/hwdef.c15
-rw-r--r--hw/thefreeman/lin16dac/hwdef.h33
13 files changed, 136 insertions, 157 deletions
diff --git a/arch/attiny1616.c b/arch/attiny1616.c
index 330c809..2770d06 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 57b0023..940973e 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 82951de..09b4096 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 ee3765a..02d5de3 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 a5b37a9..f1b6095 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 33583df..d1b1661 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 45c02de..bc1d9a7 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 a6a111c..8319d13 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 97f5fc9..573ec2f 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 d030516..d83aa46 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 8ca8b9f..8f9d6e4 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 191444e..89700d7 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 dc4377a..a68d9c2 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
}