aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2021-04-01 16:30:16 -0600
committerSelene ToyKeeper2021-04-01 16:30:16 -0600
commitbc281fdece8f3913c9ae13503f6d049e8879e0ce (patch)
treed96db6041a308caed35ee693389434263c901dd7
parentupdated MODELS file with missing K9.3-nofet build target (diff)
parentMerge TKs changes from 2021-01-25 (diff)
downloadanduril-bc281fdece8f3913c9ae13503f6d049e8879e0ce.tar.gz
anduril-bc281fdece8f3913c9ae13503f6d049e8879e0ce.tar.bz2
anduril-bc281fdece8f3913c9ae13503f6d049e8879e0ce.zip
merged gchart's Tiny1 series branch for tiny1616 support
-rwxr-xr-xbin/build.sh5
-rwxr-xr-xbin/flash-tiny1616.sh3
-rw-r--r--hwdef-BLF_Q8-T1616.h100
-rw-r--r--hwdef-Sofirn_SP10S.h122
-rw-r--r--hwdef-gchart-fet1-t16.h99
-rw-r--r--spaghetti-monster/anduril/BRANDS1
-rw-r--r--spaghetti-monster/anduril/MODELS5
-rw-r--r--spaghetti-monster/anduril/cfg-blf-lantern-t1616.h90
-rw-r--r--spaghetti-monster/anduril/cfg-blf-q8-t1616.h43
-rw-r--r--spaghetti-monster/anduril/cfg-gchart-fet1-t16.h34
-rw-r--r--spaghetti-monster/anduril/cfg-sofirn-sp10s.h28
-rw-r--r--spaghetti-monster/anduril/cfg-sofirn-sp36-t1616.h33
-rw-r--r--spaghetti-monster/anduril/version.h5
-rw-r--r--spaghetti-monster/fsm-adc.c57
-rw-r--r--spaghetti-monster/fsm-main.c9
-rw-r--r--spaghetti-monster/fsm-misc.c75
-rw-r--r--spaghetti-monster/fsm-pcint.c9
-rw-r--r--spaghetti-monster/fsm-wdt.c20
-rw-r--r--tk-attiny.h28
19 files changed, 758 insertions, 8 deletions
diff --git a/bin/build.sh b/bin/build.sh
index 3992c38..6c21e30 100755
--- a/bin/build.sh
+++ b/bin/build.sh
@@ -12,10 +12,11 @@ fi
export ATTINY=$1 ; shift
export PROGRAM=$1 ; shift
export MCU=attiny$ATTINY
+export DFP=~/avr/attiny_dfp
export CC=avr-gcc
export OBJCOPY=avr-objcopy
-export CFLAGS="-Wall -g -Os -mmcu=$MCU -c -std=gnu99 -fgnu89-inline -fwhole-program -DATTINY=$ATTINY -I.. -I../.. -I../../.. -fshort-enums"
-export OFLAGS="-Wall -g -Os -mmcu=$MCU"
+export CFLAGS="-Wall -g -Os -mmcu=$MCU -c -std=gnu99 -fgnu89-inline -fwhole-program -DATTINY=$ATTINY -I.. -I../.. -I../../.. -fshort-enums -B $DFP/gcc/dev/$MCU/ -I $DFP/include/"
+export OFLAGS="-Wall -g -Os -mmcu=$MCU -B $DFP/gcc/dev/$MCU/ -I $DFP/include/"
export LDFLAGS="-fgnu89-inline"
export OBJCOPYFLAGS='--set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0 --no-change-warnings -O ihex'
export OBJS=$PROGRAM.o
diff --git a/bin/flash-tiny1616.sh b/bin/flash-tiny1616.sh
new file mode 100755
index 0000000..31c8406
--- /dev/null
+++ b/bin/flash-tiny1616.sh
@@ -0,0 +1,3 @@
+#/bin/sh
+FIRMWARE=$1
+avrdude -c jtag2updi -P /dev/ttyUSB0 -p t1616 -u -Uflash:w:$FIRMWARE \ No newline at end of file
diff --git a/hwdef-BLF_Q8-T1616.h b/hwdef-BLF_Q8-T1616.h
new file mode 100644
index 0000000..6dfb4ab
--- /dev/null
+++ b/hwdef-BLF_Q8-T1616.h
@@ -0,0 +1,100 @@
+#ifndef HWDEF_BLF_Q8_T1616_H
+#define HWDEF_BLF_Q8_T1616_H
+
+/* BLF Q8 driver layout using the Attiny1616
+
+Driver pinout:
+ * eSwitch: PA5
+ * Aux LED: PB5
+ * PWM FET: PB0 (TCA0 WO0)
+ * PWM 1x7135: PB1 (TCA0 WO1)
+ * Voltage: VCC
+
+*/
+
+
+#define LAYOUT_DEFINED
+
+#ifdef ATTINY
+#undef ATTINY
+#endif
+#define ATTINY 1616
+#include <avr/io.h>
+
+#define PWM_CHANNELS 2
+
+#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
+
+
+// 7135 channel
+#ifndef PWM1_PIN
+#define PWM1_PIN PB1 //
+#define PWM1_LVL TCA0.SINGLE.CMP1 // CMP1 is the output compare register for PB1
+#endif
+
+// FET channel
+#ifndef PWM2_PIN
+#define PWM2_PIN PB0 //
+#define PWM2_LVL TCA0.SINGLE.CMP0 // CMP0 is the output compare register for PB0
+#endif
+
+// average drop across diode on this hardware
+#ifndef VOLTAGE_FUDGE_FACTOR
+#define VOLTAGE_FUDGE_FACTOR 7 // add 0.35V
+#endif
+
+
+// lighted button
+#ifndef AUXLED_PIN
+#define AUXLED_PIN PIN5_bp
+#define AUXLED_PORT PORTB
+#endif
+
+
+// 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 5 MHz instead of the default 3.33 MHz
+ _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm );
+
+ //VPORTA.DIR = ...;
+ VPORTB.DIR = PIN0_bm | PIN1_bm | PIN5_bm; // Outputs: Aux LED and PWMs
+ //VPORTC.DIR = ...;
+
+ // enable pullups on the unused pins to reduce power
+ PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN3CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN4CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN5CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc; // eSwitch
+ PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN7CTRL = PORT_PULLUPEN_bm;
+
+ //PORTB.PIN0CTRL = PORT_PULLUPEN_bm; // FET channel
+ //PORTB.PIN1CTRL = PORT_PULLUPEN_bm; // 7135 channel
+ PORTB.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTB.PIN3CTRL = PORT_PULLUPEN_bm;
+ PORTB.PIN4CTRL = PORT_PULLUPEN_bm;
+ //PORTB.PIN5CTRL = PORT_PULLUPEN_bm; // Aux LED
+
+ PORTC.PIN0CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN3CTRL = PORT_PULLUPEN_bm;
+
+ // set up the PWM
+ TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_CMP1EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
+ TCA0.SINGLE.PER = 255;
+ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm;
+}
+
+
+#endif
diff --git a/hwdef-Sofirn_SP10S.h b/hwdef-Sofirn_SP10S.h
new file mode 100644
index 0000000..75d79a1
--- /dev/null
+++ b/hwdef-Sofirn_SP10S.h
@@ -0,0 +1,122 @@
+#ifndef HWDEF_SOFIRN_SP10S_H
+#define HWDEF_SOFIRN_SP10S_H
+
+/* gChart's PIC12 to ATTINY1616 v1 adapter for the SP10S
+https://oshpark.com/shared_projects/b4IZEGSy
+
+PIC12 Pinout:
+1 - VDD
+2 - No Connect
+3 - Low Channel FET (series 4.7K Ohms)
+4 - Switch
+5 - High Channel FET (main PWM)
+6 - Voltage Divider (300K:100K Ohms)
+7 - Boost chip enable
+8 - GND
+
+ATTINY1616 Mapping:
+2 - PA5 : (no connect)
+3 - PB5 : TCA0 - WO2 Alternate MUX
+4 - PB3 : (switch)
+5 - PB0 : TCA0 - WO0
+6 - PB4 : ADC0 - AIN9
+7 - PA1 : (boost enable)
+
+*/
+
+
+#define LAYOUT_DEFINED
+
+#ifdef ATTINY
+#undef ATTINY
+#endif
+#define ATTINY 1616
+#include <avr/io.h>
+
+#ifndef SWITCH_PIN
+#define SWITCH_PIN 3
+#define SWITCH_PORT VPORTB.IN
+#define SWITCH_ISC_REG PORTB.PIN3CTRL
+#define SWITCH_VECT PORTB_PORT_vect
+#define SWITCH_INTFLG VPORTB.INTFLAGS
+#endif
+
+#define PWM_CHANNELS 2
+
+// Small channel
+#ifndef PWM1_PIN
+#define PWM1_PIN PB5
+#define PWM1_LVL TCA0.SINGLE.CMP2 // PB5 is Alternate MUX for TCA Compare 2
+#endif
+
+// Big channel
+#ifndef PWM2_PIN
+#define PWM2_PIN PB0
+#define PWM2_LVL TCA0.SINGLE.CMP0 // PB0 is TCA Compare 0
+#endif
+
+#define LED_ENABLE_PIN PIN1_bp
+#define LED_ENABLE_PORT PORTA_OUT
+
+#define USE_VOLTAGE_DIVIDER // use a dedicated pin, not VCC, because VCC input is flattened
+#define DUAL_VOLTAGE_FLOOR 20 // for AA/14500 boost drivers, don't indicate low voltage if below this level
+#define DUAL_VOLTAGE_LOW_LOW 07 // the lower voltage range's danger zone 0.7 volts
+#define ADMUX_VOLTAGE_DIVIDER ADC_MUXPOS_AIN9_gc // which ADC channel to read
+
+// Raw ADC readings at 4.4V and 2.2V
+// calibrate the voltage readout here
+// estimated / calculated values are:
+// (voltage - D1) * (R2/(R2+R1) * 1024 / 1.1)
+// Resistors are 300,000 and 100,000
+#ifndef ADC_44
+#define ADC_44 1023 // raw value at 4.40V
+#endif
+#ifndef ADC_22
+#define ADC_22 512 // raw value at 2.20V
+#endif
+
+
+
+// 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 5 MHz instead of the default 3.33 MHz
+ _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm );
+
+ VPORTA.DIR = PIN1_bm; // Boost enable pin
+ VPORTB.DIR = PIN0_bm | PIN5_bm; // PWM pins as output
+ //VPORTC.DIR = ...;
+
+
+ // enable pullups on the input pins to reduce power
+ PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
+ //PORTA.PIN1CTRL = PORT_PULLUPEN_bm; // Boost enable pin
+ PORTA.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN3CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN4CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN5CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN7CTRL = PORT_PULLUPEN_bm;
+
+ //PORTB.PIN0CTRL = PORT_PULLUPEN_bm; // Big PWM channel
+ PORTB.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTB.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTB.PIN3CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc; // Switch
+ //PORTB.PIN4CTRL = PORT_PULLUPEN_bm; // Voltage divider
+ //PORTB.PIN5CTRL = PORT_PULLUPEN_bm; // Small PWM channel
+
+ //PORTC.PIN0CTRL = PORT_PULLUPEN_bm; connected to the ADC via airwire
+ PORTC.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN3CTRL = PORT_PULLUPEN_bm;
+
+ // set up the PWM
+ PORTMUX.CTRLC = PORTMUX_TCA02_ALTERNATE_gc; // Use alternate pin for TCA0:WO2
+ TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
+ TCA0.SINGLE.PER = 255;
+ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm;
+}
+
+
+#endif
diff --git a/hwdef-gchart-fet1-t16.h b/hwdef-gchart-fet1-t16.h
new file mode 100644
index 0000000..e8fd11c
--- /dev/null
+++ b/hwdef-gchart-fet1-t16.h
@@ -0,0 +1,99 @@
+#ifndef HWDEF_GCH_FET1_T16_H
+#define HWDEF_GCH_FET1_T16_H
+
+/* gChart's custom FET+1 driver layout
+
+PB0 - PWM for FET (TCA - WO0)
+PB1 - PWM for 7135 (TCA - WO1)
+PB2 - Switch pin, internal pullup
+PB3 - Aux LED with 4700 Ohm series resistor
+Read voltage from VCC pin, has diode with ~0.4v drop
+
+*/
+
+
+#define LAYOUT_DEFINED
+
+#ifdef ATTINY
+#undef ATTINY
+#endif
+#define ATTINY 1616
+#include <avr/io.h>
+
+#define PWM_CHANNELS 2
+
+#ifndef SWITCH_PIN
+#define SWITCH_PIN PIN2_bp
+#define SWITCH_PORT VPORTB.IN
+#define SWITCH_ISC_REG PORTB.PIN2CTRL
+#define SWITCH_VECT PORTB_PORT_vect
+#define SWITCH_INTFLG VPORTB.INTFLAGS
+#endif
+
+
+// 7135 channel
+#ifndef PWM1_PIN
+#define PWM1_PIN PB1 //
+#define PWM1_LVL TCA0.SINGLE.CMP1 // CMP1 is the output compare register for PB1
+#endif
+
+// FET channel
+#ifndef PWM2_PIN
+#define PWM2_PIN PB0 //
+#define PWM2_LVL TCA0.SINGLE.CMP0 // CMP0 is the output compare register for PB0
+#endif
+
+// average drop across diode on this hardware
+#ifndef VOLTAGE_FUDGE_FACTOR
+#define VOLTAGE_FUDGE_FACTOR 8 // 4 = add 0.20V
+#endif
+
+
+// lighted button
+#ifndef AUXLED_PIN
+#define AUXLED_PIN PIN3_bp
+#define AUXLED_PORT PORTB
+#endif
+
+
+// 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 5 MHz instead of the default 3.33 MHz
+ _PROTECTED_WRITE( CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm );
+
+ //VPORTA.DIR = 0b00000010;
+ VPORTB.DIR = PIN0_bm | PIN1_bm | PIN3_bm;
+ //VPORTC.DIR = 0b00000000;
+
+ // enable pullups on the input pins to reduce power
+ PORTA.PIN0CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN3CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN4CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN5CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
+ PORTA.PIN7CTRL = PORT_PULLUPEN_bm;
+
+ //PORTB.PIN0CTRL = PORT_PULLUPEN_bm; // FET channel
+ //PORTB.PIN1CTRL = PORT_PULLUPEN_bm; // 7135 channel
+ PORTB.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc; // switch
+ //PORTB.PIN3CTRL = PORT_PULLUPEN_bm; // Aux LED
+ PORTB.PIN4CTRL = PORT_PULLUPEN_bm;
+ PORTB.PIN5CTRL = PORT_PULLUPEN_bm;
+
+ PORTC.PIN0CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN1CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN2CTRL = PORT_PULLUPEN_bm;
+ PORTC.PIN3CTRL = PORT_PULLUPEN_bm;
+
+ // set up the PWM
+ TCA0.SINGLE.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_CMP1EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
+ TCA0.SINGLE.PER = 255;
+ TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | TCA_SINGLE_ENABLE_bm;
+}
+
+
+#endif
diff --git a/spaghetti-monster/anduril/BRANDS b/spaghetti-monster/anduril/BRANDS
index b74ddab..acd385e 100644
--- a/spaghetti-monster/anduril/BRANDS
+++ b/spaghetti-monster/anduril/BRANDS
@@ -7,3 +7,4 @@ Lumintop 0300 - 0399
Fireflies 0400 - 0499
Mateminco 0500 - 0599
Sofirn 0600 - 0699
+gChart 1600 - 1699 \ No newline at end of file
diff --git a/spaghetti-monster/anduril/MODELS b/spaghetti-monster/anduril/MODELS
index 52fa200..4dda62f 100644
--- a/spaghetti-monster/anduril/MODELS
+++ b/spaghetti-monster/anduril/MODELS
@@ -38,5 +38,10 @@ Model numbers:
0611 blf-q8
0612 sofirn-sp36
0621 blf-lantern
+0622 sofirn-sp10s
+0631 blf-q8-t1616
+0632 sofirn-sp36-t1616
+0633 blf-lantern-t1616
+1618 gchart-fet1-t16
Duplicates:
Missing:
diff --git a/spaghetti-monster/anduril/cfg-blf-lantern-t1616.h b/spaghetti-monster/anduril/cfg-blf-lantern-t1616.h
new file mode 100644
index 0000000..7905eee
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-blf-lantern-t1616.h
@@ -0,0 +1,90 @@
+// BLF Lantern config options for Anduril using the Attiny1616
+#define MODEL_NUMBER "0633"
+/* BLF Lantern pinout
+ * PB0 is 5000K channel
+ * PB1 is 3000K channel
+ */
+
+// basically the same as a Q8... sort of
+#include "hwdef-BLF_Q8-T1616.h"
+// ATTINY: 1616
+
+// the button lights up
+#define USE_INDICATOR_LED
+// the button is visible while main LEDs are on
+#define USE_INDICATOR_LED_WHILE_RAMPING
+// enable blinking indicator LED while off
+#define TICK_DURING_STANDBY
+#define STANDBY_TICK_SPEED 3 // every 0.128 s
+#define USE_FANCIER_BLINKING_INDICATOR
+// off mode: high (2)
+// lockout: blinking (3)
+#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2)
+
+// the lantern has two PWM channels, but they drive different sets of emitters
+// (one channel for warm emitters, one channel for cold)
+// so enable a special ramping mode which changes tint instead of brightness
+#define USE_TINT_RAMPING
+// how much to increase total brightness at middle tint
+// (0 = 100% brightness, 64 = 200% brightness)
+//#define TINT_RAMPING_CORRECTION 26 // prototype, 140%
+#define TINT_RAMPING_CORRECTION 10 // production model, 115%
+
+#ifdef RAMP_LENGTH
+#undef RAMP_LENGTH
+#endif
+
+// level_calc.py 1 150 7135 1 30 800
+#define RAMP_LENGTH 150
+#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,11,11,12,13,13,14,15,15,16,17,18,18,19,20,21,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,43,44,45,46,48,49,50,51,53,54,56,57,58,60,61,63,64,66,67,69,70,72,74,75,77,79,80,82,84,85,87,89,91,93,95,97,98,100,102,104,106,108,111,113,115,117,119,121,124,126,128,130,133,135,137,140,142,145,147,150,152,155,157,160,163,165,168,171,173,176,179,182,185,188,190,193,196,199,202,205,209,212,215,218,221,224,228,231,234,238,241,245,248,251,255
+#define MAX_1x7135 65
+#define HALFSPEED_LEVEL 14
+#define QUARTERSPEED_LEVEL 5
+
+// the default of 26 looks a bit flat, so increase it
+#define CANDLE_AMPLITUDE 40
+
+// override default ramp style
+#undef RAMP_STYLE
+#define RAMP_STYLE 1 // 0 = smooth, 1 = stepped
+// set floor and ceiling as far apart as possible
+// because this lantern isn't overpowered
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 150
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 5
+
+// LT1 can handle heat well, so don't limit simple mode
+#define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR
+#define SIMPLE_UI_CEIL RAMP_DISCRETE_CEIL
+#define SIMPLE_UI_STEPS RAMP_DISCRETE_STEPS
+
+#define USE_SOS_MODE
+#define USE_SOS_MODE_IN_BLINKY_GROUP
+
+// the sensor (attiny85) is nowhere near the emitters
+// so thermal regulation can't work
+#ifdef USE_THERMAL_REGULATION
+#undef USE_THERMAL_REGULATION
+#endif
+
+// also, the set_level_gradually() thing isn't compatible with tint ramping
+// (but unsetting it here doesn't actually do anything, because the thermal
+// regulation define enables it later... so this is mostly just a note to
+// make this compatibility issue explicit)
+#ifdef USE_SET_LEVEL_GRADUALLY
+#undef USE_SET_LEVEL_GRADUALLY
+#endif
+
+// don't blink while ramping
+#ifdef BLINK_AT_RAMP_MIDDLE
+#undef BLINK_AT_RAMP_MIDDLE
+#endif
+#ifdef BLINK_AT_RAMP_FLOOR
+#undef BLINK_AT_RAMP_FLOOR
+#endif
+// except the top... blink at the top
+#ifndef BLINK_AT_RAMP_CEIL
+#define BLINK_AT_RAMP_CEIL
+#endif
diff --git a/spaghetti-monster/anduril/cfg-blf-q8-t1616.h b/spaghetti-monster/anduril/cfg-blf-q8-t1616.h
new file mode 100644
index 0000000..e1e1598
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-blf-q8-t1616.h
@@ -0,0 +1,43 @@
+// BLF Q8 config options for Anduril using the Attiny1616
+#define MODEL_NUMBER "0631"
+#include "hwdef-BLF_Q8-T1616.h"
+// ATTINY: 1616
+
+// the button lights up
+#define USE_INDICATOR_LED
+// the button is visible while main LEDs are on
+#define USE_INDICATOR_LED_WHILE_RAMPING
+// enable blinking indicator LED while off
+#define TICK_DURING_STANDBY
+#define STANDBY_TICK_SPEED 3 // every 0.128 s
+#define USE_FANCIER_BLINKING_INDICATOR
+// off mode: high (2)
+// lockout: blinking (3)
+#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 2)
+
+// copied from Emisar D4 ramp
+// ../../bin/level_calc.py 1 65 7135 1 0.8 150
+// ... mixed with this:
+// ../../bin/level_calc.py 2 150 7135 4 0.33 150 FET 1 10 1500
+#define RAMP_LENGTH 150
+#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
+#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255
+#define MAX_1x7135 65
+#define HALFSPEED_LEVEL 14
+#define QUARTERSPEED_LEVEL 5
+
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 120
+// 10 28 46 [65] 83 101 120
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
+
+// safe limit ~50% power
+#define SIMPLE_UI_FLOOR RAMP_DISCRETE_FLOOR
+#define SIMPLE_UI_CEIL RAMP_DISCRETE_CEIL
+#define SIMPLE_UI_STEPS 5
+
+// stop panicking at ~75% power or ~3000 lm, this light has high thermal mass
+#define THERM_FASTER_LEVEL (RAMP_SIZE*9/10) // throttle back faster when high
+
diff --git a/spaghetti-monster/anduril/cfg-gchart-fet1-t16.h b/spaghetti-monster/anduril/cfg-gchart-fet1-t16.h
new file mode 100644
index 0000000..a6434b8
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-gchart-fet1-t16.h
@@ -0,0 +1,34 @@
+// gChart's custom FET+1 driver config options for Anduril
+#define MODEL_NUMBER "1618" // Golden Ratio... because I can
+#include "hwdef-gchart-fet1-t16.h"
+// ATTINY: 1616
+
+// the button lights up
+#define USE_INDICATOR_LED
+// the button is visible while main LEDs are on
+#define USE_INDICATOR_LED_WHILE_RAMPING
+// enable blinking indicator LED while off
+#define TICK_DURING_STANDBY
+
+#undef BLINK_AT_RAMP_MIDDLE
+
+// Mostly borrowed from the D4 for now
+#define RAMP_LENGTH 150
+#define PWM1_LEVELS 1,1,2,2,3,3,4,4,5,6,7,8,9,10,12,13,14,15,17,19,20,22,24,26,29,31,34,36,39,42,45,48,51,55,59,62,66,70,75,79,84,89,93,99,104,110,115,121,127,134,140,147,154,161,168,176,184,192,200,209,217,226,236,245,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
+#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,4,5,7,8,9,11,12,14,15,17,19,20,22,24,25,27,29,31,33,35,37,39,41,43,45,48,50,52,55,57,59,62,64,67,70,72,75,78,81,84,87,90,93,96,99,102,105,109,112,115,119,122,126,129,133,137,141,144,148,152,156,160,165,169,173,177,182,186,191,195,200,205,209,214,219,224,229,234,239,244,250,255
+#define MAX_1x7135 65
+#define HALFSPEED_LEVEL 14
+#define QUARTERSPEED_LEVEL 6
+
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 120
+// 10, 28, 46, [65], 83, 101, 120
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
+
+// stop panicking at ~30% power
+#define THERM_FASTER_LEVEL 105
+
+// enable 2 click turbo
+#define USE_2C_MAX_TURBO
diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp10s.h b/spaghetti-monster/anduril/cfg-sofirn-sp10s.h
new file mode 100644
index 0000000..054b1db
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-sofirn-sp10s.h
@@ -0,0 +1,28 @@
+// gChart's custom SP10S driver config options for Anduril
+#define MODEL_NUMBER "0622"
+#include "hwdef-Sofirn_SP10S.h"
+// ATTINY: 1616
+
+#undef BLINK_AT_RAMP_MIDDLE
+
+#define USE_DYNAMIC_UNDERCLOCKING
+
+#define RAMP_LENGTH 150
+#define PWM1_LEVELS 20,30,41,54,69,87,106,128,152,179,209,242,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,0
+#define PWM2_LEVELS 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,10,10,11,12,12,13,14,14,15,16,17,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,33,34,35,36,38,39,41,42,43,45,46,48,50,51,53,55,56,58,60,62,64,66,68,70,72,74,76,78,80,83,85,87,90,92,94,97,99,102,105,107,110,113,116,119,121,124,127,130,133,137,140,143,146,150,153,156,160,164,167,171,174,178,182,186,190,194,198,202,206,210,214,219,223,227,232,236,241,246,250,255
+
+#define MAX_1x7135 13
+#define HALFSPEED_LEVEL 14
+#define QUARTERSPEED_LEVEL 6
+
+#define RAMP_SMOOTH_FLOOR 1
+#define RAMP_SMOOTH_CEIL 120
+#define RAMP_DISCRETE_FLOOR 10
+#define RAMP_DISCRETE_CEIL RAMP_SMOOTH_CEIL
+#define RAMP_DISCRETE_STEPS 7
+
+// stop panicking at ~30% power
+#define THERM_FASTER_LEVEL 105
+
+// enable 2 click turbo
+#define USE_2C_MAX_TURBO
diff --git a/spaghetti-monster/anduril/cfg-sofirn-sp36-t1616.h b/spaghetti-monster/anduril/cfg-sofirn-sp36-t1616.h
new file mode 100644
index 0000000..8eb7a5d
--- /dev/null
+++ b/spaghetti-monster/anduril/cfg-sofirn-sp36-t1616.h
@@ -0,0 +1,33 @@
+// Sofirn SP36 (small Q8) config options for Anduril using the Attiny1616
+// same as the BLF Q8, mostly
+#include "cfg-blf-q8-t1616.h"
+#undef MODEL_NUMBER
+#define MODEL_NUMBER "0632"
+// ATTINY: 1616
+
+// voltage readings were a little high with the Q8 value
+#undef VOLTAGE_FUDGE_FACTOR
+#define VOLTAGE_FUDGE_FACTOR 5 // add 0.25V, not 0.35V
+
+// the high button LED mode on this light uses too much power
+// off mode: low (1)
+// lockout: blinking (3)
+#ifdef INDICATOR_LED_DEFAULT_MODE
+#undef INDICATOR_LED_DEFAULT_MODE
+#define INDICATOR_LED_DEFAULT_MODE ((3<<2) + 1)
+#endif
+
+// don't blink during the ramp; the button LED brightness is sufficient
+// to indicate which power channel(s) are being used
+#ifdef BLINK_AT_RAMP_MIDDLE
+#undef BLINK_AT_RAMP_MIDDLE
+#endif
+#ifdef BLINK_AT_RAMP_CEIL
+#undef BLINK_AT_RAMP_CEIL
+#endif
+
+// stop panicking at ~60% power or ~3000 lm
+#ifdef THERM_FASTER_LEVEL
+#undef THERM_FASTER_LEVEL
+#endif
+#define THERM_FASTER_LEVEL 130
diff --git a/spaghetti-monster/anduril/version.h b/spaghetti-monster/anduril/version.h
index 8cf3c90..14502aa 100644
--- a/spaghetti-monster/anduril/version.h
+++ b/spaghetti-monster/anduril/version.h
@@ -1,4 +1 @@
-// this file is replaced automatically by the build script
-// set your own date here if you're not using the build script
-// otherwise, default to first human contact with the moon
-#define VERSION_NUMBER "19690720"
+#define VERSION_NUMBER "20210201"
diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c
index 71ecf65..975d12e 100644
--- a/spaghetti-monster/fsm-adc.c
+++ b/spaghetti-monster/fsm-adc.c
@@ -37,6 +37,9 @@ static inline void set_admux_therm() {
#elif (ATTINY == 841) // FIXME: not tested
ADMUXA = ADMUXA_THERM;
ADMUXB = ADMUXB_THERM;
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ ADC0.MUXPOS = ADC_MUXPOS_TEMPSENSE_gc; // read temperature
+ ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_PRESC_DIV64_gc | ADC_REFSEL_INTREF_gc; // Internal ADC reference
#else
#error Unrecognized MCU type
#endif
@@ -66,6 +69,15 @@ inline void set_admux_voltage() {
ADMUXA = ADMUXA_VCC;
ADMUXB = ADMUXB_VCC;
#endif
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ #ifdef USE_VOLTAGE_DIVIDER // 1.1V / ADC input pin
+ // verify that this is correct!!! untested
+ ADC0.MUXPOS = ADMUX_VOLTAGE_DIVIDER; // read the requested ADC pin
+ ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_PRESC_DIV64_gc | ADC_REFSEL_INTREF_gc; // Use internal ADC reference
+ #else // VCC / 1.1V reference
+ ADC0.MUXPOS = ADC_MUXPOS_INTREF_gc; // read internal reference
+ ADC0.CTRLC = ADC_SAMPCAP_bm | ADC_PRESC_DIV64_gc | ADC_REFSEL_VDDREF_gc; // Vdd (Vcc) be ADC reference
+ #endif
#else
#error Unrecognized MCU type
#endif
@@ -77,6 +89,9 @@ inline void set_admux_voltage() {
inline void ADC_start_measurement() {
#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 841) || (ATTINY == 1634)
ADCSRA |= (1 << ADSC) | (1 << ADIE);
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ ADC0.INTCTRL |= ADC_RESRDY_bm; // enable interrupt
+ ADC0.COMMAND |= ADC_STCONV_bm; // Start the ADC conversions
#else
#error unrecognized MCU type
#endif
@@ -108,13 +123,22 @@ inline void ADC_on()
// enable, start, auto-retrigger, prescale
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL;
//ADCSRA |= (1 << ADSC); // start measuring
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ set_admux_voltage();
+ VREF.CTRLA |= VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V
+ ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm; // Enabled, free-running (aka, auto-retrigger)
+ ADC0.COMMAND |= ADC_STCONV_bm; // Start the ADC conversions
#else
#error Unrecognized MCU type
#endif
}
inline void ADC_off() {
- ADCSRA &= ~(1<<ADEN); //ADC off
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC
+ #else
+ ADCSRA &= ~(1<<ADEN); //ADC off
+ #endif
}
#ifdef USE_VOLTAGE_DIVIDER
@@ -140,9 +164,16 @@ static inline uint8_t calc_voltage_divider(uint16_t value) {
#define ADC_CYCLES_PER_SECOND 2
#endif
+#ifdef AVRXMEGA3 // ATTINY816, 817, etc
+#define ADC_vect ADC0_RESRDY_vect
+#endif
// happens every time the ADC sampler finishes a measurement
ISR(ADC_vect) {
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ ADC0.INTFLAGS = ADC_RESRDY_bm; // clear the interrupt
+ #endif
+
if (adc_sample_count) {
uint16_t m; // latest measurement
@@ -150,7 +181,23 @@ ISR(ADC_vect) {
uint8_t channel = adc_channel;
// update the latest value
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ // Use the factory calibrated values in SIGROW.TEMPSENSE0 and SIGROW.TEMPSENSE1
+ // to calculate a temperature reading in Kelvin, then left-align it.
+ if (channel == 1) { // thermal, convert ADC reading to left-aligned Kelvin
+ int8_t sigrow_offset = SIGROW.TEMPSENSE1; // Read signed value from signature row
+ uint8_t sigrow_gain = SIGROW.TEMPSENSE0; // Read unsigned value from signature row
+ uint32_t temp = ADC0.RES - sigrow_offset;
+ temp *= sigrow_gain; // Result might overflow 16 bit variable (10bit+8bit)
+ temp += 0x80; // Add 1/2 to get correct rounding on division below
+ temp >>= 8; // Divide result to get Kelvin
+ m = (temp << 6); // left align it
+ }
+ else { m = (ADC0.RES << 6); } // voltage, force left-alignment
+
+ #else
m = ADC;
+ #endif
adc_raw[channel] = m;
// lowpass the value
@@ -181,8 +228,12 @@ void adc_deferred() {
// real-world entropy makes this a true random, not pseudo
// Why here instead of the ISR? Because it makes the time-critical ISR
// code a few cycles faster and we don't need crypto-grade randomness.
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ pseudo_rand_seed += ADC0.RESL; // right aligned, not left... so should be equivalent?
+ #else
pseudo_rand_seed += (ADCL >> 6) + (ADCH << 2);
#endif
+ #endif
// the ADC triggers repeatedly when it's on, but we only need to run the
// voltage and temperature regulation stuff once in a while...so disable
@@ -290,7 +341,11 @@ static inline void ADC_voltage_handler() {
if (lvp_timer) {
lvp_timer --;
} else { // it has been long enough since the last warning
+ #ifdef DUAL_VOLTAGE_FLOOR
+ if (((voltage < VOLTAGE_LOW) && (voltage > DUAL_VOLTAGE_FLOOR)) || (voltage < DUAL_VOLTAGE_LOW_LOW)) {
+ #else
if (voltage < VOLTAGE_LOW) {
+ #endif
// send out a warning
emit(EV_voltage_low, 0);
// reset rate-limit counter
diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c
index b96bce8..f3c319c 100644
--- a/spaghetti-monster/fsm-main.c
+++ b/spaghetti-monster/fsm-main.c
@@ -23,6 +23,9 @@
#include "fsm-main.h"
#if PWM_CHANNELS == 4
+#ifdef AVRXMEGA3 // ATTINY816, 817, etc
+#error 4-channel PWM not currently set up for the AVR 1-Series
+#endif
// 4th PWM channel requires manually turning the pin on/off via interrupt :(
ISR(TIMER1_OVF_vect) {
//bitClear(PORTB, 3);
@@ -68,7 +71,7 @@ static inline void hw_setup() {
PORTB = (1 << SWITCH_PIN); // e-switch is the only input
PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin
}
-#elif (ATTINY == 1634)
+#elif (ATTINY == 1634) || defined(AVRXMEGA3) // ATTINY816, 817, etc
static inline void hw_setup() {
// this gets tricky with so many pins...
// ... so punt it to the hwdef file
@@ -82,7 +85,11 @@ static inline void hw_setup() {
//#ifdef USE_REBOOT
static inline void prevent_reboot_loop() {
// prevent WDT from rebooting MCU again
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ RSTCTRL.RSTFR &= ~(RSTCTRL_WDRF_bm); // reset status flag
+ #else
MCUSR &= ~(1<<WDRF); // reset status flag
+ #endif
wdt_disable();
}
//#endif
diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c
index 15cb659..edd982a 100644
--- a/spaghetti-monster/fsm-misc.c
+++ b/spaghetti-monster/fsm-misc.c
@@ -110,6 +110,35 @@ uint8_t blink_num(uint8_t num) {
#ifdef USE_INDICATOR_LED
void indicator_led(uint8_t lvl) {
switch (lvl) {
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ case 0: // indicator off
+ AUXLED_PORT.DIRSET = (1 << AUXLED_PIN); // set as output
+ AUXLED_PORT.OUTCLR = (1 << AUXLED_PIN); // set output low
+ #ifdef AUXLED2_PIN // second LED mirrors the first
+ AUXLED2_PORT.DIRSET = (1 << AUXLED2_PIN); // set as output
+ AUXLED2_PORT.OUTCLR = (1 << AUXLED2_PIN); // set output low
+ #endif
+ break;
+ case 1: // indicator low
+ AUXLED_PORT.DIRCLR = (1 << AUXLED_PIN); // set as input
+ // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
+ *((uint8_t *)&AUXLED_PORT + 0x10 + AUXLED_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
+ #ifdef AUXLED2_PIN // second LED mirrors the first
+ AUXLED2_PORT.DIRCLR = (1 << AUXLED2_PIN); // set as input
+ // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
+ *((uint8_t *)&AUXLED2_PORT + 0x10 + AUXLED2_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
+ #endif
+ break;
+ default: // indicator high
+ AUXLED_PORT.DIRSET = (1 << AUXLED_PIN); // set as output
+ AUXLED_PORT.OUTSET = (1 << AUXLED_PIN); // set as high
+ #ifdef AUXLED2_PIN // second LED mirrors the first
+ AUXLED2_PORT.DIRSET = (1 << AUXLED2_PIN); // set as output
+ AUXLED2_PORT.OUTSET = (1 << AUXLED2_PIN); // set as high
+ #endif
+ break;
+
+ #else
case 0: // indicator off
DDRB &= 0xff ^ (1 << AUXLED_PIN);
PORTB &= 0xff ^ (1 << AUXLED_PIN);
@@ -134,6 +163,8 @@ void indicator_led(uint8_t lvl) {
PORTB |= (1 << AUXLED2_PIN);
#endif
break;
+
+ #endif
}
}
@@ -150,6 +181,24 @@ void indicator_led_auto() {
// TODO: Refactor this and RGB LED function to merge code and save space
void button_led_set(uint8_t lvl) {
switch (lvl) {
+
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ case 0: // LED off
+ BUTTON_LED_PORT.DIRSET = (1 << BUTTON_LED_PIN); // set as output
+ BUTTON_LED_PORT.OUTCLR = (1 << BUTTON_LED_PIN); // set output low
+ break;
+ case 1: // LED low
+ BUTTON_LED_PORT.DIRCLR = (1 << BUTTON_LED_PIN); // set as input
+ // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
+ *((uint8_t *)&BUTTON_LED_PORT + 0x10 + BUTTON_LED_PIN) = PORT_PULLUPEN_bm; // enable internal pull-up
+ break;
+ default: // LED high
+ BUTTON_LED_PORT.DIRSET = (1 << BUTTON_LED_PIN); // set as output
+ BUTTON_LED_PORT.OUTSET = (1 << BUTTON_LED_PIN); // set as high
+ break;
+
+ #else
+
case 0: // LED off
BUTTON_LED_DDR &= 0xff ^ (1 << BUTTON_LED_PIN);
BUTTON_LED_PUE &= 0xff ^ (1 << BUTTON_LED_PIN);
@@ -165,6 +214,8 @@ void button_led_set(uint8_t lvl) {
BUTTON_LED_PUE |= (1 << BUTTON_LED_PIN);
BUTTON_LED_PORT |= (1 << BUTTON_LED_PIN);
break;
+
+ #endif
}
}
#endif
@@ -177,6 +228,24 @@ void rgb_led_set(uint8_t value) {
uint8_t lvl = (value >> (i<<1)) & 0x03;
uint8_t pin = pins[i];
switch (lvl) {
+
+ #ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ case 0: // LED off
+ AUXLED_RGB_PORT.DIRSET = (1 << pin); // set as output
+ AUXLED_RGB_PORT.OUTCLR = (1 << pin); // set output low
+ break;
+ case 1: // LED low
+ AUXLED_RGB_PORT.DIRCLR = (1 << pin); // set as input
+ // this resolves to PORTx.PINxCTRL = PORT_PULLUPEN_bm;
+ *((uint8_t *)&AUXLED_RGB_PORT + 0x10 + pin) = PORT_PULLUPEN_bm; // enable internal pull-up
+ break;
+ default: // LED high
+ AUXLED_RGB_PORT.DIRSET = (1 << pin); // set as output
+ AUXLED_RGB_PORT.OUTSET = (1 << pin); // set as high
+ break;
+
+ #else
+
case 0: // LED off
AUXLED_RGB_DDR &= 0xff ^ (1 << pin);
AUXLED_RGB_PUE &= 0xff ^ (1 << pin);
@@ -192,6 +261,9 @@ void rgb_led_set(uint8_t value) {
AUXLED_RGB_PUE |= (1 << pin);
AUXLED_RGB_PORT |= (1 << pin);
break;
+
+ #endif
+
}
}
}
@@ -217,6 +289,9 @@ void reboot() {
// reset (WDIF + WDE), no WDIE, fastest (16ms) timing (0000)
// (DS section 8.5.2 and table 8-4)
WDTCSR = 0b10001000;
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ CCP = CCP_IOREG_gc; // temporarily disable change protection
+ WDT.CTRLA = WDT_PERIOD_8CLK_gc; // Enable, timeout 8ms
#endif
sei();
wdt_reset();
diff --git a/spaghetti-monster/fsm-pcint.c b/spaghetti-monster/fsm-pcint.c
index 24cc82c..4a3c193 100644
--- a/spaghetti-monster/fsm-pcint.c
+++ b/spaghetti-monster/fsm-pcint.c
@@ -46,6 +46,8 @@ inline void PCINT_on() {
#else
GIMSK |= (1 << SWITCH_PCIE);
#endif
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ SWITCH_ISC_REG |= PORT_ISC_BOTHEDGES_gc;
#else
#error Unrecognized MCU type
#endif
@@ -58,6 +60,8 @@ inline void PCINT_off() {
#elif (ATTINY == 1634)
// disable all pin-change interrupts
GIMSK &= ~(1 << SWITCH_PCIE);
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ SWITCH_ISC_REG &= ~(PORT_ISC_gm);
#else
#error Unrecognized MCU type
#endif
@@ -73,6 +77,11 @@ ISR(PCINT0_vect) {
#endif
irq_pcint = 1;
}
+#elif defined(AVRXMEGA3) // ATTINY816, 817, etc)
+ISR(SWITCH_VECT) {
+ SWITCH_INTFLG |= (1 << SWITCH_PIN); // Write a '1' to clear the interrupt flag
+ irq_pcint = 1;
+}
#else
#error Unrecognized MCU type
#endif
diff --git a/spaghetti-monster/fsm-wdt.c b/spaghetti-monster/fsm-wdt.c
index 9e8d9af..ea2efac 100644
--- a/spaghetti-monster/fsm-wdt.c
+++ b/spaghetti-monster/fsm-wdt.c
@@ -23,6 +23,10 @@
#include <avr/interrupt.h>
#include <avr/wdt.h>
+// *** Note for the AVRXMEGA3 (1-Series, eg 816 and 817), the WDT
+// is not used for time-based interrupts. A new peripheral, the
+// Periodic Interrupt Timer ("PIT") is used for this purpose.
+
void WDT_on()
{
#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85)
@@ -35,6 +39,10 @@ void WDT_on()
#elif (ATTINY == 1634)
wdt_reset(); // Reset the WDT
WDTCSR = (1<<WDIE); // Enable interrupt every 16ms
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
+ while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
+ RTC.PITCTRLA = RTC_PERIOD_CYC512_gc | RTC_PITEN_bm; // Period = 16ms, enable the PI Timer
#else
#error Unrecognized MCU type
#endif
@@ -53,6 +61,10 @@ inline void WDT_slow()
#elif (ATTINY == 1634)
wdt_reset(); // Reset the WDT
WDTCSR = (1<<WDIE) | STANDBY_TICK_SPEED;
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ RTC.PITINTCTRL = RTC_PI_bm; // enable the Periodic Interrupt
+ while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
+ RTC.PITCTRLA = (1<<6) | (STANDBY_TICK_SPEED<<3) | RTC_PITEN_bm; // Set period, enable the PI Timer
#else
#error Unrecognized MCU type
#endif
@@ -75,13 +87,21 @@ inline void WDT_off()
CCP = 0xD8; // enable config changes
WDTCSR = 0; // disable and clear all WDT settings
sei();
+ #elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ while (RTC.PITSTATUS > 0) {} // make sure the register is ready to be updated
+ RTC.PITCTRLA = 0; // Disable the PI Timer
#else
#error Unrecognized MCU type
#endif
}
// clock tick -- this runs every 16ms (62.5 fps)
+#ifdef AVRXMEGA3 // ATTINY816, 817, etc
+ISR(RTC_PIT_vect) {
+ RTC.PITINTFLAGS = RTC_PI_bm; // clear the PIT interrupt flag
+#else
ISR(WDT_vect) {
+#endif
irq_wdt = 1; // WDT event happened
}
diff --git a/tk-attiny.h b/tk-attiny.h
index 49f1195..441f177 100644
--- a/tk-attiny.h
+++ b/tk-attiny.h
@@ -71,6 +71,12 @@
#define DELAY_ZERO_TIME 1020
//#define SWITCH_PORT PINA // set this in hwdef
//#define VOLTAGE_ADC_DIDR DIDR0 // set this in hwdef
+#elif (ATTINY == 412) || (ATTINY == 416) || (ATTINY == 417) || (ATTINY == 816) || (ATTINY == 817) || (ATTINY == 1616) || (ATTINY == 1617) || (ATTINY == 3216) || (ATTINY == 3217)
+ #define AVRXMEGA3
+ #define F_CPU 5000000UL
+ #define BOGOMIPS (F_CPU/4000)
+ #define EEPSIZE 128
+ #define DELAY_ZERO_TIME 1020
#else
#error Hey, you need to define ATTINY.
#endif
@@ -138,6 +144,28 @@
clock_div_256 = 8
} clock_div_t;
+#elif defined(AVRXMEGA3) // ATTINY816, 817, etc
+ // this should work, but needs further validation
+ inline void clock_prescale_set(uint8_t n) {
+ cli();
+ CCP = CCP_IOREG_gc; // temporarily disable clock change protection
+ CLKCTRL.MCLKCTRLB = n; // Set the prescaler
+ while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {} // wait for clock change to finish
+ sei();
+ }
+ typedef enum
+ {
+ // Actual clock is 20 MHz, but assume that 5 MHz is the top speed and work from there
+ clock_div_1 = (CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm), // 5 MHz
+ clock_div_2 = (CLKCTRL_PDIV_8X_gc | CLKCTRL_PEN_bm), // 2.5 MHz
+ clock_div_4 = (CLKCTRL_PDIV_16X_gc | CLKCTRL_PEN_bm), // 1.25 MHz
+ clock_div_8 = (CLKCTRL_PDIV_32X_gc | CLKCTRL_PEN_bm), // 625 kHz
+ clock_div_16 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz, max without changing to the 32 kHz ULP
+ clock_div_32 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz
+ clock_div_64 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz
+ clock_div_128 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm), // 312 kHz
+ clock_div_256 = (CLKCTRL_PDIV_64X_gc | CLKCTRL_PEN_bm) // 312 kHz
+ } clock_div_t;
#else
#error Unable to define MCU macros.
#endif
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.