From 1d57e4a89ebe628ef8bcf9e324c9d1c2070d3685 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 10 Dec 2023 17:47:50 -0700 Subject: 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 cd06c6a..852e1c4 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 -- cgit v1.2.3 From 0c498d9715fc9da9017d03b6e8212ef79593e034 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Mon, 11 Dec 2023 17:37:36 -0700 Subject: 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 3847217..9dcc644 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. -- cgit v1.2.3 From 8572911b9a8902d25480ed08a9c6b6486b8735ba Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 15 Dec 2023 04:45:51 -0700 Subject: 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 02d5de3..3152183 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 3715f34..9144b28 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 0f2992a..b259a6e 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(); -- cgit v1.2.3 From 0725045fc2d6f974f50d59755f9bbecd0c33ee23 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 15 Dec 2023 04:55:40 -0700 Subject: 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 d044ca5..ed0a837 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 -- cgit v1.2.3 From 21ef87919046d0d9bd8932b2635251eff22f7563 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 17 Dec 2023 00:17:32 -0700 Subject: 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 ef280fa..a77b178 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 0000000..ab9b87f --- /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 0000000..e53e038 --- /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 0000000..b3c33af --- /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 + -- cgit v1.2.3 From 312f7442c31d72dd36f108de9542f81960526658 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 17 Dec 2023 00:18:14 -0700 Subject: 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 190cd0e..d155eba 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 + -- cgit v1.2.3 From 76ce3c5e70bf415fbf28597db994ca04416e7ed3 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 10 Jan 2024 05:46:49 -0700 Subject: added "emisar-2ch-fet-joined" build, for D4S w/ lighted switch (it's an odd case with a 2 channel driver which only uses 1 set of LEDs) --- MODELS | 1 + hw/hank/emisar-2ch/fet/joined/README.md | 25 +++++ hw/hank/emisar-2ch/fet/joined/anduril.h | 113 +++++++++++++++++++ hw/hank/emisar-2ch/fet/joined/hwdef.c | 181 ++++++++++++++++++++++++++++++ hw/hank/emisar-2ch/fet/joined/hwdef.h | 191 ++++++++++++++++++++++++++++++++ hw/hank/emisar-2ch/fet/joined/model | 1 + 6 files changed, 512 insertions(+) create mode 100644 hw/hank/emisar-2ch/fet/joined/README.md create mode 100644 hw/hank/emisar-2ch/fet/joined/anduril.h create mode 100644 hw/hank/emisar-2ch/fet/joined/hwdef.c create mode 100644 hw/hank/emisar-2ch/fet/joined/hwdef.h create mode 100644 hw/hank/emisar-2ch/fet/joined/model diff --git a/MODELS b/MODELS index a77b178..0a8c244 100644 --- a/MODELS +++ b/MODELS @@ -18,6 +18,7 @@ Model MCU Name 0134 attiny1634 hank-emisar-d4sv2-219 0135 attiny1634 hank-emisar-2ch 0136 attiny1634 hank-emisar-2ch-fet +0137 attiny1634 hank-emisar-2ch-fet-joined 0141 attiny85 hank-emisar-d18 0142 attiny85 hank-emisar-d18-219 0143 attiny1634 hank-noctigon-m44 diff --git a/hw/hank/emisar-2ch/fet/joined/README.md b/hw/hank/emisar-2ch/fet/joined/README.md new file mode 100644 index 0000000..a8b0456 --- /dev/null +++ b/hw/hank/emisar-2ch/fet/joined/README.md @@ -0,0 +1,25 @@ +# Emisar 2-channel driver connected to only 1 set of LEDs + +The default Emisar D4S driver doesn't support a lighted switch, so for lights +built with one of those, Hank puts in a 2-channel driver instead... but he only +connects 1 set of LEDs. + +This is an odd hardware configuration used only for special orders, I think. + +The driver itself has 3 power channels: + + 1. Linear regulator 1 + 2. Linear regulator 2 + 3. Direct-drive FET + +Channels 1 and 3 are connected to the main LEDs, while channel 2 is not +physically wired up to anything. + +Two channel modes are included: + + 1. Linear only + 2. Linear + DD FET + +Channel mode 2 is default, and the only mode enabled after a factory reset. +Channel mode 1 is included in case anyone wants to turn off the DD FET. + diff --git a/hw/hank/emisar-2ch/fet/joined/anduril.h b/hw/hank/emisar-2ch/fet/joined/anduril.h new file mode 100644 index 0000000..d9b36f9 --- /dev/null +++ b/hw/hank/emisar-2ch/fet/joined/anduril.h @@ -0,0 +1,113 @@ +// Anduril config for Emisar 2ch+FET-joined-into-1-channel +// Copyright (C) 2024 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +// This is mostly just used on the Emisar D4S w/ lighted switch, +// which uses a 2-channel driver but only actually uses 1 set of LEDs +// (so instead of the usual 2ch or 2ch-fet firmware, it needs something else) + +#define HWDEF_H hank/emisar-2ch/fet/joined/hwdef.h +#include "hank/anduril.h" + +// this light has three aux LED channels: R, G, B +#define USE_AUX_RGB_LEDS +// the aux LEDs are front-facing, so turn them off while main LEDs are on +// it also has an independent LED in the button +#define USE_BUTTON_LED +// enabling this option breaks the button LED +#ifdef USE_INDICATOR_LED_WHILE_RAMPING +#undef USE_INDICATOR_LED_WHILE_RAMPING +#endif + +// channel modes... +// CM_CH1 -- linear ch1 only +// CM_CH1_FET -- linear ch1 + DD FET +#define DEFAULT_CHANNEL_MODE CM_CH1_FET + +#define USE_CONFIG_COLORS + +// strobes on this light should use the same channel as the ramp +#undef USE_CHANNEL_PER_STROBE + +// blink numbers on the main LEDs by default (but allow user to change it) +#define DEFAULT_BLINK_CHANNEL CM_CH1_FET + +#define POLICE_COLOR_STROBE_CH1 CM_AUXRED +#define POLICE_COLOR_STROBE_CH2 CM_AUXBLU + +#define RAMP_SIZE 150 + +// Output estimates: +// - linear ch1 only: 2500 lm +// - ch1 + DD FET: 3500 lm +// (tested on a D4S with Osram W2 LEDs, with a mediocre battery at 3.7V) +// (LuxWad estimated 6000 lm (uncalibrated) on a full high-amp cell) +// (I picked 4500 lm as a rough realistic estimate) +// - linear ch2 only: 0 (not connected) +// - moon: 0.7 lm at PWM 1/4096, 0.15 lm at DSM 0/32640 + +// delta-sigma modulated PWM (0b0HHHHHHHHLLLLLLL = 0, 8xHigh, 7xLow bits) +// (max is (255 << 7), because it's 8-bit PWM plus 7 bits of DSM) +// +// linear ch1 only (copied from noctigon-m44 ramp) +// level_calc.py 5.01 1 150 7135 0 0.2 2000 --pwm 32640 +#define PWM1_LEVELS 0,1,2,3,4,5,6,7,9,10,12,14,17,19,22,25,28,32,36,41,45,50,56,62,69,76,84,92,101,110,121,132,143,156,169,184,199,215,232,251,270,291,313,336,360,386,414,442,473,505,539,574,612,651,693,736,782,829,880,932,987,1045,1105,1168,1233,1302,1374,1449,1527,1608,1693,1781,1873,1969,2068,2172,2279,2391,2507,2628,2753,2883,3018,3158,3303,3454,3609,3771,3938,4111,4289,4475,4666,4864,5068,5280,5498,5724,5957,6197,6445,6701,6965,7237,7518,7808,8106,8413,8730,9056,9392,9737,10093,10459,10835,11223,11621,12031,12452,12884,13329,13786,14255,14737,15232,15741,16262,16798,17347,17911,18489,19082,19691,20314,20954,21609,22281,22969,23674,24397,25137,25895,26671,27465,28279,29111,29963,30835,31727,32640 +// +// linear+FET linear ch1 segment +// level_calc.py 4.85 2 150 7135 0 0.5 2500 FET 1 10 4500 --pwm 32640 +#define PWM2_LEVELS 0,2,3,5,7,9,11,14,17,20,24,28,33,38,44,50,57,64,72,81,91,101,112,125,138,152,167,184,201,220,241,263,286,311,337,365,395,427,461,497,535,575,618,663,711,761,814,870,929,992,1057,1126,1198,1274,1353,1437,1524,1616,1712,1812,1917,2027,2141,2261,2386,2516,2652,2794,2941,3095,3255,3422,3595,3775,3962,4156,4358,4568,4785,5011,5245,5487,5738,5999,6268,6548,6837,7135,7445,7764,8095,8437,8790,9154,9531,9919,10321,10735,11162,11602,12056,12524,13006,13503,14015,14542,15085,15643,16218,16810,17419,18045,18688,19350,20031,20730,21448,22186,22944,23722,24521,25342,26184,27048,27935,28844,29777,30733,31714,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,32640,0 +// +// linear+FET DD FET segment +// level_calc.py 4.85 2 150 7135 0 0.5 2500 FET 1 10 4500 --pwm 255 +#define PWM3_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,10,20,31,42,53,65,76,88,101,113,126,139,152,166,180,194,209,224,239,255 + +#define DEFAULT_LEVEL 70 +#define MIN_THERM_STEPDOWN 50 +#define MAX_REGULATED 130 +#define MAX_1x7135 MAX_REGULATED +#define MAX_Nx7135 MAX_REGULATED +#define HALFSPEED_LEVEL 20 +#define QUARTERSPEED_LEVEL 10 + +#define RAMP_SMOOTH_FLOOR 1 +#define RAMP_SMOOTH_CEIL 150 +// 10, 30, 50, [70], 90, 110, [130] +#define RAMP_DISCRETE_FLOOR 10 +#define RAMP_DISCRETE_CEIL MAX_REGULATED +#define RAMP_DISCRETE_STEPS 7 + +// safe limit highest regulated power (no FET or turbo) +// 10, 40, [70], 100, [130] +#define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR +#define SIMPLE_UI_CEIL RAMP_DISCRETE_CEIL +#define SIMPLE_UI_STEPS 5 + +// stop panicking at ~2500 lm +#define THERM_FASTER_LEVEL MAX_REGULATED + +#define USE_POLICE_COLOR_STROBE_MODE +#undef TACTICAL_LEVELS +#define TACTICAL_LEVELS MAX_REGULATED,30,(RAMP_SIZE+3) // high, low, police strobe + +// use the brightest setting for strobe +#define STROBE_BRIGHTNESS MAX_LEVEL +// slow down party strobe; this driver can't pulse for less than 1ms +// (in linear-only mode ... but FET mode can pulse a much shorter time) +#define PARTY_STROBE_ONTIME 1 + +// the default of 26 looks a bit flat, so increase it +#define CANDLE_AMPLITUDE 33 + +// the power regulator is a bit slow, so push it harder for a quick response from off +#define DEFAULT_JUMP_START_LEVEL 22 +#define BLINK_BRIGHTNESS 45 +#define BLINK_ONCE_TIME 12 // longer blink, since main LEDs are slow + +#define THERM_CAL_OFFSET 5 + +// don't blink while ramping +#ifdef BLINK_AT_RAMP_MIDDLE +#undef BLINK_AT_RAMP_MIDDLE +#endif + diff --git a/hw/hank/emisar-2ch/fet/joined/hwdef.c b/hw/hank/emisar-2ch/fet/joined/hwdef.c new file mode 100644 index 0000000..5785149 --- /dev/null +++ b/hw/hank/emisar-2ch/fet/joined/hwdef.c @@ -0,0 +1,181 @@ +// Emisar 2-channel-plus-FET-joined-into-1-channel +// Copyright (C) 2024 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +#include "fsm/chan-rgbaux.c" + + +void set_level_zero(); + +void set_level_ch1(uint8_t level); +void set_level_ch1_fet(uint8_t level); + +bool gradual_tick_ch1(uint8_t gt); +bool gradual_tick_ch1_fet(uint8_t gt); + + +Channel channels[] = { + { // channel 1 only + .set_level = set_level_ch1, + .gradual_tick = gradual_tick_ch1, + // .has_args = 0 + }, + { // channel 1 + DD FET + .set_level = set_level_ch1_fet, + .gradual_tick = gradual_tick_ch1_fet, + // .has_args = 0 + }, + RGB_AUX_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; + //ch2_dsm_lvl = 0; + CH1_PWM = 0; + CH2_PWM = 0; + CH3_PWM = 0; + PWM_CNT = 0; // reset phase + CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp + CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp +} + + +// wrap setting the dsm vars, to get a faster response +// (just setting *_dsm_lvl doesn't work well for strobes) +// set new values for both channels, +// handling any possible combination +// and any before/after state +void set_hw_levels(PWM1_DATATYPE ch1, + //PWM2_DATATYPE ch2, + PWM3_DATATYPE ch3 + //, bool ch1_on, bool ch2_on + ) { + + //bool was_on = (CH1_PWM>0) || (CH2_PWM>0) + // || ( CH1_ENABLE_PORT & (1 << CH1_ENABLE_PIN) ) + // || ( CH2_ENABLE_PORT & (1 << CH2_ENABLE_PIN) ); + + //if (ch1 || ch1_on) + CH1_ENABLE_PORT |= (1 << CH1_ENABLE_PIN); // enable opamp + //else + // CH1_ENABLE_PORT &= ~(1 << CH1_ENABLE_PIN); // disable opamp + + //if (ch2 || ch2_on) + // CH2_ENABLE_PORT |= (1 << CH2_ENABLE_PIN); // enable opamp + //else + // CH2_ENABLE_PORT &= ~(1 << CH2_ENABLE_PIN); // disable opamp + + // set delta-sigma soft levels + ch1_dsm_lvl = ch1; + //ch2_dsm_lvl = ch2; + + // set hardware PWM levels and init dsm loop + CH1_PWM = ch1_pwm = ch1 >> 7; + //CH2_PWM = ch2_pwm = ch2 >> 7; + CH3_PWM = ch3; + + // enable timer overflow interrupt so DSM can work + DSM_INTCTRL |= DSM_OVF_bm; + + // reset phase when turning on + if (! prev_level) PWM_CNT = 0; + +} + +// 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; + //CH2_PWM = ch2_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; + + // repeat for other channels + + //ch2_dsm += (ch2_dsm_lvl & 0x007f); + //ch2_pwm = (ch2_dsm_lvl >> 7) + (ch2_dsm > 0x7f); + //ch2_dsm &= 0x7f; +} + + +void set_level_ch1(uint8_t level) { + PWM1_DATATYPE pwm1 = PWM1_GET(level); + set_hw_levels(pwm1, 0); +} + +void set_level_ch1_fet(uint8_t level) { + PWM2_DATATYPE pwm2 = PWM2_GET(level); + PWM3_DATATYPE pwm3 = PWM3_GET(level); + set_hw_levels(pwm2, pwm3); +} + + +///// bump each channel toward a target value ///// +bool gradual_adjust(PWM1_DATATYPE ch1, + //PWM2_DATATYPE ch2, + PWM3_DATATYPE ch3) { + + // instant 0 to TOP change, and TOP to 0 + if (((DSM_TOP == ch1_dsm_lvl) && (0 == ch1)) || + ((DSM_TOP == ch1) && (0 == ch1_dsm_lvl))) + ch1_dsm_lvl = ch1; + + // bump the DD FET multiple steps + // (it only has 255 steps, but the effect is small + // compared to the linear channel it's stacked on, + // so smaller steps tend to overheat on turbo) + for (uint8_t i=0; i<4; i++) + GRADUAL_ADJUST_SIMPLE(ch3, CH3_PWM); + + // if DSM changed by less than 100%, + // 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); + + //steps = ch2_dsm_lvl >> shift; + ////for (uint8_t i=0; i<=steps; i++) + //// GRADUAL_ADJUST_SIMPLE(ch2, ch2_dsm_lvl); + + if ((ch1 == ch1_dsm_lvl) + //&& (ch2 == ch2_dsm_lvl) + && (ch3 == CH3_PWM) ) { + return true; // done + } + return false; // not done yet +} + +bool gradual_tick_ch1(uint8_t gt) { + PWM1_DATATYPE pwm1 = PWM1_GET(gt); + return gradual_adjust(pwm1, 0); +} + +bool gradual_tick_ch1_fet(uint8_t gt) { + PWM2_DATATYPE pwm2 = PWM2_GET(gt); + PWM3_DATATYPE pwm3 = PWM3_GET(gt); + return gradual_adjust(pwm2, pwm3); +} + diff --git a/hw/hank/emisar-2ch/fet/joined/hwdef.h b/hw/hank/emisar-2ch/fet/joined/hwdef.h new file mode 100644 index 0000000..f260743 --- /dev/null +++ b/hw/hank/emisar-2ch/fet/joined/hwdef.h @@ -0,0 +1,191 @@ +// Emisar 2-channel-plus-FET-joined-into-1-channel +// Copyright (C) 2024 Selene ToyKeeper +// SPDX-License-Identifier: GPL-3.0-or-later +#pragma once + +/* + * Pin / Name / Function + * 1 PA6 ch2 LED PWM (linear) (PWM1B) (unused) + * 2 PA5 R: red aux LED (PWM0B) + * 3 PA4 G: green aux LED + * 4 PA3 B: blue aux LED + * 5 PA2 button LED + * 6 PA1 Opamp 2 enable (channel 2 LEDs) (unused) + * 7 PA0 Opamp 1 enable (channel 1 LEDs) + * 8 GND GND + * 9 VCC VCC + * 10 PC5 (none) + * 11 PC4 (none) + * 12 PC3 RESET + * 13 PC2 (none) + * 14 PC1 SCK + * 15 PC0 ch1 LED PWM (FET) (PWM0A, 8-bit) + * 16 PB3 ch1 LED PWM (linear) (PWM1A) + * 17 PB2 MISO + * 18 PB1 MOSI / battery voltage (ADC6) + * 19 PB0 (none) + * 20 PA7 e-switch (PCINT7) + * ADC12 thermal sensor + * + * This is used for lights with only 1 set of main LEDs, when using the + * 2-channel driver internally. This allows the D4S to have a lighted button. + * Hank typically connects only linear ch1 and sometimes the DD FET + * to the main LEDs, leaving linear ch2 completely unused. Support is + * included in an extra channel mode in case modders decide to use it. + * It can raise the maximum regulated level. + */ + +#define HWDEF_C hank/emisar-2ch/fet/joined/hwdef.c + +// allow using aux LEDs as extra channel modes +#include "fsm/chan-rgbaux.h" + +// channel modes: +// * 0. linear (ch1) only +// * 1. linear (ch1) + DD FET <-- Hank's primary config, as far as I can tell +// x 2. linear (both) + DD FET (not used) +#define NUM_CHANNEL_MODES (2 + NUM_RGB_AUX_CHANNEL_MODES) +enum channel_modes_e { + CM_CH1 = 0, + CM_CH1_FET, // <-- default + //CM_BOTH_FET, + RGB_AUX_ENUMS +}; + +// right-most bit first, modes are in fedcba9876543210 order +#define CHANNEL_MODES_ENABLED 0b0000000000000010 +//#define USE_CHANNEL_MODE_ARGS +// _, _, _, 128=middle CCT, 0=warm-to-cool +//#define CHANNEL_MODE_ARGS 0,0,0,RGB_AUX_CM_ARGS + +#define PWM_CHANNELS 3 // old, remove this + +#define PWM_BITS 16 // 0 to 32640 (0 to 255 PWM + 0 to 127 DSM) +#define PWM_GET PWM_GET16 +#define PWM_DATATYPE uint16_t +// linear-only ramp +#define PWM1_DATATYPE uint16_t +#define PWM1_GET(l) PWM_GET16(pwm1_levels, l) +// linear part of linear+FET ramp +#define PWM2_DATATYPE uint16_t +#define PWM2_GET(l) PWM_GET16(pwm2_levels, l) +// DD FET part of linear+FET ramp +#define PWM3_DATATYPE uint8_t +#define PWM3_GET(l) PWM_GET8(pwm3_levels, l) + +// PWM parameters of both channels are tied together because they share a counter +#define PWM_TOP ICR1 // holds the TOP value for for variable-resolution PWM +#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< DUAL_VOLTAGE_FLOOR) + BST_BYPASS_PORT &= ~(1 << BST_BYPASS_PIN); // low = bypass + else // turn off bypass in AA/NiMH mode + BST_BYPASS_PORT |= (1 << BST_BYPASS_PIN); // high = boost + #endif + // 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; diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h index f1b6095..231f74a 100644 --- a/hw/thefreeman/avr32dd20-devkit/hwdef.h +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h @@ -28,6 +28,7 @@ * 18 PA1 G: aux green * 19 PA2 B: aux blue * 20 PA3 CH: detect charging + * or BBY: boost bypass PFET * * BST EN enable the boost regulator and Op-Amp * DAC sets the current, max current depends on Vset voltage divider and Rsense @@ -35,6 +36,8 @@ * 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 + * BBY routes power around the boost converter in li-ion 3V mode + * (pin low = bypass, pin high = boost) * BATT LVL : Vbat * (100.0/(330+100)) * LVB is for OTSM firmware, not used here */ @@ -77,6 +80,11 @@ enum CHANNEL_MODES { #define BST_ENABLE_PIN PIN5_bp #define BST_ENABLE_PORT PORTD_OUT +// BST bypass +#define USE_BST_BYPASS +#define BST_BYPASS_PIN PIN3_bp +#define BST_BYPASS_PORT PORTA_OUT + // HDR // turns on HDR FET for the high current range #define HDR_ENABLE_PIN PIN7_bp @@ -133,7 +141,9 @@ inline void hwdef_setup() { VPORTA.DIR = PIN0_bm // R | PIN1_bm // G | PIN2_bm // B - //| PIN3_bm // CH + #ifdef USE_BST_BYPASS + | PIN3_bm // BBY + #endif | PIN7_bm; // HDR VPORTD.DIR = PIN5_bm // EN | PIN6_bm // DAC @@ -143,7 +153,9 @@ inline void hwdef_setup() { //PORTA.PIN0CTRL = PORT_PULLUPEN_bm; // R //PORTA.PIN1CTRL = PORT_PULLUPEN_bm; // G //PORTA.PIN2CTRL = PORT_PULLUPEN_bm; // B - //PORTA.PIN3CTRL = PORT_PULLUPEN_bm; // CH + #ifdef USE_BST_BYPASS + PORTA.PIN3CTRL = PORT_PULLUPEN_bm; // BBY + #endif PORTA.PIN4CTRL = PORT_PULLUPEN_bm; PORTA.PIN5CTRL = PORT_PULLUPEN_bm; //PORTA.PIN6CTRL = PORT_PULLUPEN_bm; // BATT LVL @@ -177,6 +189,12 @@ inline void hwdef_setup() { // to generate a zero without spending power on the DAC // (and do this in set_level_zero() too) + // TCA/TCB/TCD aren't being used, so turn them off + TCA0.SINGLE.CTRLA = 0; + TCB0.CTRLA = 0; + TCB1.CTRLA = 0; + TCD0.CTRLA = 0; + } -- cgit v1.2.3 From d5149d654a0e6e53d41e41c9adae92523276e720 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 2 Feb 2024 23:24:50 -0700 Subject: thefreeman-avr32dd20-devkit: enable boost bypass at boot, so AA/NiMH can boot --- hw/thefreeman/avr32dd20-devkit/hwdef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/thefreeman/avr32dd20-devkit/hwdef.h b/hw/thefreeman/avr32dd20-devkit/hwdef.h index 231f74a..38b508d 100644 --- a/hw/thefreeman/avr32dd20-devkit/hwdef.h +++ b/hw/thefreeman/avr32dd20-devkit/hwdef.h @@ -155,6 +155,7 @@ inline void hwdef_setup() { //PORTA.PIN2CTRL = PORT_PULLUPEN_bm; // B #ifdef USE_BST_BYPASS PORTA.PIN3CTRL = PORT_PULLUPEN_bm; // BBY + BST_BYPASS_PORT |= (1 << BST_BYPASS_PIN); #endif PORTA.PIN4CTRL = PORT_PULLUPEN_bm; PORTA.PIN5CTRL = PORT_PULLUPEN_bm; -- cgit v1.2.3 From bb5bb049a713034d5f2b75daccfc8431c1e63bf9 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 2 Feb 2024 23:40:20 -0700 Subject: enabled eeprom read/write stabilization by default on recent MCUs, to prevent corrupt data This was enabled on more build targets before, but the *_ENABLE_PIN definition names changed and the eeprom code didn't, so it was not compiled in for a few months on some lights which probably needed it. To fix that, it's now enabled by default on everything bigger than attiny85, since it doesn't really hurt anything if it's enabled when not needed. --- fsm/eeprom.c | 8 ++++---- fsm/eeprom.h | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/fsm/eeprom.c b/fsm/eeprom.c index 8f8bd67..436a736 100644 --- a/fsm/eeprom.c +++ b/fsm/eeprom.c @@ -14,7 +14,7 @@ uint8_t eeprom[EEPROM_BYTES]; #endif uint8_t load_eeprom() { - #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN) + #ifdef USE_EEP_DELAY delay_4ms(2); // wait for power to stabilize #endif @@ -32,7 +32,7 @@ uint8_t load_eeprom() { } void save_eeprom() { - #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN) + #ifdef USE_EEP_DELAY delay_4ms(2); // wait for power to stabilize #endif @@ -54,7 +54,7 @@ uint8_t eeprom_wl[EEPROM_WL_BYTES]; uint8_t * eep_wl_prev_offset; uint8_t load_eeprom_wl() { - #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN) + #ifdef USE_EEP_DELAY delay_4ms(2); // wait for power to stabilize #endif @@ -83,7 +83,7 @@ uint8_t load_eeprom_wl() { } void save_eeprom_wl() { - #if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN) + #ifdef USE_EEP_DELAY delay_4ms(2); // wait for power to stabilize #endif diff --git a/fsm/eeprom.h b/fsm/eeprom.h index 1e10fd2..d5f0363 100644 --- a/fsm/eeprom.h +++ b/fsm/eeprom.h @@ -55,3 +55,11 @@ // if this marker isn't found, the eeprom is assumed to be blank #define EEP_MARKER 0b10100101 +// wait a few ms before eeprom operations, to wait for power to stabilize +// (otherwise reads or writes can get corrupt data) +// (not necessary on some hardware, +// but enabled by default when there's space) +#if defined(LED_ENABLE_PIN) || defined(LED2_ENABLE_PIN) || (ROM_SIZE > 10000) + #define USE_EEP_DELAY +#endif + -- cgit v1.2.3