aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--hwdef-Emisar_D4v2.h97
-rw-r--r--hwdef-Sofirn_LT1S-Pro.c67
-rw-r--r--hwdef-Sofirn_LT1S-Pro.h109
3 files changed, 208 insertions, 65 deletions
diff --git a/hwdef-Emisar_D4v2.h b/hwdef-Emisar_D4v2.h
index e118ed5..51e30f8 100644
--- a/hwdef-Emisar_D4v2.h
+++ b/hwdef-Emisar_D4v2.h
@@ -1,7 +1,8 @@
-#ifndef HWDEF_EMISAR_D4V2_H
-#define HWDEF_EMISAR_D4V2_H
+#pragma once
-/* Emisar D4v2 driver layout (attiny1634)
+/* hwdef for Emisar D4v2 (attiny1634)
+ * Copyright (C) 2019 Selene ToyKeeper
+ * SPDX-License-Identifier: GPL-3.0-or-later
*
* Pin / Name / Function
* 1 PA6 FET PWM (PWM1B)
@@ -33,6 +34,16 @@
#define ATTINY 1634
#include <avr/io.h>
+// TODO: add aux red and aux blue as disabled channel modes,
+// so they can be used for the police strobe?
+#define NUM_CHANNEL_MODES 1
+#define DEFAULT_CHANNEL_MODE 0
+#define SET_LEVEL_MODES set_level_2ch_stacked
+#define GRADUAL_TICK_MODES gradual_tick_2ch_stacked
+// no special handlers needed, can use common handlers
+#define USE_SET_LEVEL_2CH_STACKED
+#define USE_GRADUAL_TICK_2CH_STACKED
+
#define PWM_CHANNELS 2
#define SWITCH_PIN PA2 // pin 5
@@ -41,12 +52,17 @@
#define SWITCH_PCMSK PCMSK0 // PCMSK0 is for PCINT[7:0]
#define SWITCH_PORT PINA // PINA or PINB or PINC
-#define PWM1_PIN PB3 // pin 16, 1x7135 PWM
-#define PWM1_LVL OCR1A // OCR1A is the output compare register for PB3
+#define LOW_PWM_PIN PB3 // pin 16, 1x7135 PWM
+#define LOW_PWM_LVL OCR1A // OCR1A is the output compare register for PB3
+#define PWM1_BITS 8
-#define PWM2_PIN PA6 // pin 1, FET PWM
-#define PWM2_LVL OCR1B // OCR1B is the output compare register for PB1
+#define HIGH_PWM_PIN PA6 // pin 1, FET PWM
+#define HIGH_PWM_LVL OCR1B // OCR1B is the output compare register for PB1
+#define PWM2_BITS 8
+// only using 8-bit on this light
+#define PWM_GET PWM_GET8
+#define PWM_DATATYPE uint8_t
#define ADC_PRSCL 0x07 // clk/128
@@ -68,37 +84,46 @@
#define BUTTON_LED_DDR DDRA // for all "PA" pins
#define BUTTON_LED_PUE PUEA // for all "PA" pins
-// with so many pins, doing this all with #ifdefs gets awkward...
-// ... so just hardcode it in each hwdef file instead
+// this light has three aux LED channels: R, G, B
+#define USE_AUX_RGB_LEDS
+// it also has an independent LED in the button
+#define USE_BUTTON_LED
+// the aux LEDs are front-facing, so turn them off while main LEDs are on
+// TODO: the whole "indicator LED" thing needs to be refactored into
+// "aux LED(s)" and "button LED(s)" since they work a bit differently
+#ifdef USE_INDICATOR_LED_WHILE_RAMPING
+#undef USE_INDICATOR_LED_WHILE_RAMPING
+#endif
+
inline void hwdef_setup() {
- // enable output ports
- // 7135
- DDRB = (1 << PWM1_PIN);
- // FET, aux R/G/B, button LED
- DDRA = (1 << PWM2_PIN)
- | (1 << AUXLED_R_PIN)
- | (1 << AUXLED_G_PIN)
- | (1 << AUXLED_B_PIN)
- | (1 << BUTTON_LED_PIN)
- ;
-
- // configure PWM
- // Setup PWM. F_pwm = F_clkio / 2 / N / TOP, where N = prescale factor, TOP = top of counter
- // pre-scale for timer: N = 1
- TCCR1A = (0<<WGM11) | (1<<WGM10) // 8-bit (TOP=0xFF) (DS table 12-5)
- | (1<<COM1A1) | (0<<COM1A0) // PWM 1A in normal direction (DS table 12-4)
- | (1<<COM1B1) | (0<<COM1B0) // PWM 1B in normal direction (DS table 12-4)
- ;
- TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10) // clk/1 (no prescaling) (DS table 12-6)
- | (0<<WGM13) | (0<<WGM12) // phase-correct PWM (DS table 12-5)
- ;
-
- // set up e-switch
- //PORTA = (1 << SWITCH_PIN); // TODO: configure PORTA / PORTB / PORTC?
- PUEA = (1 << SWITCH_PIN); // pull-up for e-switch
- SWITCH_PCMSK = (1 << SWITCH_PCINT); // enable pin change interrupt
+ // enable output ports
+ // 7135
+ DDRB = (1 << LOW_PWM_PIN);
+ // FET, aux R/G/B, button LED
+ DDRA = (1 << HIGH_PWM_PIN)
+ | (1 << AUXLED_R_PIN)
+ | (1 << AUXLED_G_PIN)
+ | (1 << AUXLED_B_PIN)
+ | (1 << BUTTON_LED_PIN)
+ ;
+
+ // configure PWM
+ // Setup PWM. F_pwm = F_clkio / 2 / N / TOP, where N = prescale factor, TOP = top of counter
+ // pre-scale for timer: N = 1
+ TCCR1A = (0<<WGM11) | (1<<WGM10) // 8-bit (TOP=0xFF) (DS table 12-5)
+ | (1<<COM1A1) | (0<<COM1A0) // PWM 1A in normal direction (DS table 12-4)
+ | (1<<COM1B1) | (0<<COM1B0) // PWM 1B in normal direction (DS table 12-4)
+ ;
+ TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10) // clk/1 (no prescaling) (DS table 12-6)
+ | (0<<WGM13) | (0<<WGM12) // phase-correct PWM (DS table 12-5)
+ ;
+
+ // set up e-switch
+ //PORTA = (1 << SWITCH_PIN); // TODO: configure PORTA / PORTB / PORTC?
+ PUEA = (1 << SWITCH_PIN); // pull-up for e-switch
+ SWITCH_PCMSK = (1 << SWITCH_PCINT); // enable pin change interrupt
}
+
#define LAYOUT_DEFINED
-#endif
diff --git a/hwdef-Sofirn_LT1S-Pro.c b/hwdef-Sofirn_LT1S-Pro.c
new file mode 100644
index 0000000..3c31c96
--- /dev/null
+++ b/hwdef-Sofirn_LT1S-Pro.c
@@ -0,0 +1,67 @@
+// BLF LT1S Pro hwdef functions
+// Copyright (C) 2023 Selene ToyKeeper
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+
+// "auto tint" channel mode
+void set_level_auto_3ch_blend(uint8_t level) {
+ BLEND_PWM_DATATYPE vpwm;
+
+ if (level == 0) {
+ vpwm = 0;
+ } else {
+ level --; // PWM array index = level - 1
+ vpwm = PWM_GET(blend_pwm_levels, level);
+ }
+
+ // tint goes from 0 (red) to 127 (warm white) to 255 (cool white)
+ uint8_t mytint;
+ mytint = 255 * (uint16_t)level / RAMP_SIZE;
+
+ BLEND_PWM_DATATYPE a, b, c;
+
+ // red is high at 0, low at 255
+ a = (((PWM_DATATYPE2)(255 - mytint)
+ * (PWM_DATATYPE2)vpwm) + 127) / 255;
+ // warm white is low at 0 and 255, high at 127
+ b = (((PWM_DATATYPE2)triangle_wave(mytint)
+ * (PWM_DATATYPE2)vpwm) + 127) / 255;
+ // cool white is low at 0, high at 255
+ c = (((PWM_DATATYPE2)mytint
+ * (PWM_DATATYPE2)vpwm) + 127) / 255;
+
+ RED_PWM_LVL = a;
+ WARM_PWM_LVL = b;
+ COOL_PWM_LVL = c;
+}
+
+
+// "white + red" channel mode
+void set_level_red_white_blend(uint8_t level) {
+ // set the warm+cool white LEDs first
+ channel_mode = CM_WHITE;
+ set_level_2ch_blend(level);
+ channel_mode = CM_WHITE_RED;
+
+ BLEND_PWM_DATATYPE vpwm;
+
+ // set the red LED as a ratio of the white output level
+ if (level == 0) {
+ vpwm = 0;
+ } else {
+ level --; // PWM array index = level - 1
+ vpwm = PWM_GET(blend_pwm_levels, level);
+ }
+
+ // 0 = no red
+ // 255 = red at 100% of white channel PWM
+ uint8_t ratio = channel_mode_args[channel_mode];
+
+ PWM_DATATYPE red_pwm;
+ red_pwm = (((PWM_DATATYPE2)ratio * (PWM_DATATYPE2)vpwm) + 127) / 255;
+
+ RED_PWM_LVL = red_pwm;
+}
+
diff --git a/hwdef-Sofirn_LT1S-Pro.h b/hwdef-Sofirn_LT1S-Pro.h
index ce6ee3a..c52364f 100644
--- a/hwdef-Sofirn_LT1S-Pro.h
+++ b/hwdef-Sofirn_LT1S-Pro.h
@@ -1,6 +1,3 @@
-#ifndef HWDEF_SOFIRN_LT1S_PRO_H
-#define HWDEF_SOFIRN_LT1S_PRO_H
-
/* BLF LT1S Pro driver layout using the Attiny1616
Driver pinout:
@@ -13,8 +10,10 @@ Driver pinout:
*/
+#pragma once
-#define LAYOUT_DEFINED
+
+#define HWDEF_C_FILE hwdef-Sofirn_LT1S-Pro.c
#ifdef ATTINY
#undef ATTINY
@@ -22,40 +21,85 @@ Driver pinout:
#define ATTINY 1616
#include <avr/io.h>
+// channel modes:
+// * 0. warm/cool white blend
+// * 1. auto 3ch blend (red -> warm -> cool by ramp level)
+// * 2. red only
+// * 3. red + white blend
+#define NUM_CHANNEL_MODES 4
+//#define CHANNEL_MODES_ENABLED 1,1,1,1
+#define CHANNEL_MODES_ENABLED 0b00001111
+#define CM_WHITE 0
+#define CM_AUTO 1
+#define CM_RED 2
+#define CM_WHITE_RED 3
+
+// TODO: blend mode should enable this automatically?
+#define USE_CHANNEL_MODES
+// TODO: blend mode should enable this automatically?
+#define USE_CHANNEL_MODE_ARGS
+// TODO: or maybe if args are defined, the USE_ should be auto-set?
+#define CHANNEL_MODE_ARGS 128,0,0,255
+#define SET_LEVEL_MODES set_level_2ch_blend, \
+ set_level_auto_3ch_blend, \
+ set_level_1ch, \
+ set_level_red_white_blend
+// TODO: gradual ticking for thermal regulation
+#define GRADUAL_TICK_MODES gradual_tick_2ch_blend, \
+ gradual_tick_auto_3ch_blend, \
+ gradual_tick_1ch, \
+ gradual_tick_red_white_blend
+// can use some of the common handlers
+#define USE_SET_LEVEL_2CH_BLEND
+//#define USE_SET_LEVEL_AUTO_3CH_BLEND
+#define USE_SET_LEVEL_1CH
+//#define USE_SET_LEVEL_RED_WHITE_BLEND
+// TODO:
+//#define USE_GRADUAL_TICK_2CH_BLEND
+//#define USE_GRADUAL_TICK_AUTO_3CH_BLEND
+//#define USE_GRADUAL_TICK_1CH
+//#define USE_GRADUAL_TICK_RED_WHITE_BLEND
+
+#define DEFAULT_CHANNEL_MODE CM_AUTO
+
+#define FACTORY_RESET_WARN_CHANNEL CM_RED
+#define FACTORY_RESET_SUCCESS_CHANNEL CM_WHITE
+
+#define POLICE_COLOR_STROBE_CH1 CM_RED
+#define POLICE_COLOR_STROBE_CH2 CM_WHITE
+
+// TODO: remove this as soon as it's not needed
#define PWM_CHANNELS 1
-#ifndef SWITCH_PIN
#define SWITCH_PIN PIN5_bp
#define SWITCH_PORT VPORTA.IN
#define SWITCH_ISC_REG PORTA.PIN2CTRL
#define SWITCH_VECT PORTA_PORT_vect
#define SWITCH_INTFLG VPORTA.INTFLAGS
-#endif
-
-// usually PWM1_LVL would be a hardware register, but we need to abstract
-// it out to a soft brightness value, in order to handle tint ramping
-// (this allows smooth thermal regulation to work, and makes things
-// otherwise simpler and easier)
-uint8_t PWM1_LVL;
// warm tint channel
-#ifndef PWM1_PIN
-#define PWM1_PIN PB0 //
-#define TINT1_LVL TCA0.SINGLE.CMP0 // CMP1 is the output compare register for PB0
-#endif
+#define WARM_PWM_PIN PB0
+#define WARM_PWM_LVL TCA0.SINGLE.CMP0 // CMP1 is the output compare register for PB0
// cold tint channel
-#ifndef PWM2_PIN
-#define PWM2_PIN PB1 //
-#define TINT2_LVL TCA0.SINGLE.CMP1 // CMP0 is the output compare register for PB1
-#endif
+#define COOL_PWM_PIN PB1
+#define COOL_PWM_LVL TCA0.SINGLE.CMP1 // CMP0 is the output compare register for PB1
// red channel
-#ifndef PWM3_PIN
-#define PWM3_PIN PB0 //
-#define PWM3_LVL TCA0.SINGLE.CMP2 // CMP2 is the output compare register for PB2
-#endif
+#define RED_PWM_PIN PB0 //
+#define RED_PWM_LVL TCA0.SINGLE.CMP2 // CMP2 is the output compare register for PB2
+
+// translate cfg names to FSM names
+#define LOW_PWM_LEVELS RED_PWM_LEVELS
+#define LOW_PWM_LVL RED_PWM_LVL
+#define LOW_PWM_PIN RED_PWM_PIN
+
+// only using 8-bit on this light
+#define PWM_GET PWM_GET8
+#define PWM_DATATYPE uint8_t
+#define BLEND_PWM_DATATYPE uint8_t
+
// average drop across diode on this hardware
#ifndef VOLTAGE_FUDGE_FACTOR
@@ -64,14 +108,20 @@ uint8_t PWM1_LVL;
// lighted button
-#ifndef AUXLED_PIN
#define AUXLED_PIN PIN5_bp
#define AUXLED_PORT PORTB
-#endif
+
+// the button lights up
+#define USE_INDICATOR_LED
+// the button is visible while main LEDs are on
+#define USE_INDICATOR_LED_WHILE_RAMPING
+
+
+// custom channel modes
+void set_level_auto_3ch_blend(uint8_t level);
+void set_level_red_white_blend(uint8_t level);
-// with so many pins, doing this all with #ifdefs gets awkward...
-// ... so just hardcode it in each hwdef file instead
inline void hwdef_setup() {
// set up the system clock to run at 10 MHz instead of the default 3.33 MHz
@@ -111,4 +161,5 @@ inline void hwdef_setup() {
}
-#endif
+#define LAYOUT_DEFINED
+
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.