From dbe0aaf636ccb78a3cc1281b6a1ea6c662af6756 Mon Sep 17 00:00:00 2001 From: Gabriel Hart Date: Fri, 18 Dec 2020 15:23:31 -0600 Subject: Add AVR 1-Series and t1616 board and scripts --- bin/build.sh | 5 +- bin/flash-tiny1616.sh | 3 + hwdef-gchart-fet1-t16.h | 101 ++++++++++++++++++++++++ spaghetti-monster/anduril/BRANDS | 1 + spaghetti-monster/anduril/MODELS | 1 + spaghetti-monster/anduril/cfg-gchart-fet1-t16.h | 39 +++++++++ spaghetti-monster/anduril/version.h | 5 +- spaghetti-monster/fsm-adc.c | 53 ++++++++++++- spaghetti-monster/fsm-main.c | 9 ++- spaghetti-monster/fsm-misc.c | 54 +++++++++++++ spaghetti-monster/fsm-pcint.c | 9 +++ spaghetti-monster/fsm-wdt.c | 20 +++++ tk-attiny.h | 28 +++++++ 13 files changed, 320 insertions(+), 8 deletions(-) create mode 100755 bin/flash-tiny1616.sh create mode 100644 hwdef-gchart-fet1-t16.h create mode 100644 spaghetti-monster/anduril/cfg-gchart-fet1-t16.h 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-gchart-fet1-t16.h b/hwdef-gchart-fet1-t16.h new file mode 100644 index 0000000..3a79586 --- /dev/null +++ b/hwdef-gchart-fet1-t16.h @@ -0,0 +1,101 @@ +#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 + +#define PWM_CHANNELS 2 + +#ifndef SWITCH_PIN +#define SWITCH_PIN 2 +#define SWITCH_PORT VPORTB.IN +#define SWITCH_ISC_REG PORTB.PIN2CTRL +#define SWITCH_VECT PORTB_PORT_vect +#define SWITCH_INTFLG VPORTB.INTFLAGS +//#define SWITCH_ISC_REG _SFR_MEM8(&PORTB + 0x10 + SWITCH_PIN) +#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_bm +#define AUXLED_PORT PORTB +#define AUXLED_CTRL PIN3CTRL +#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 84d6795..4ad4635 100644 --- a/spaghetti-monster/anduril/MODELS +++ b/spaghetti-monster/anduril/MODELS @@ -36,5 +36,6 @@ Model numbers: 0611 blf-q8 0612 sofirn-sp36 0621 blf-lantern +1618 gchart-fet1-t16 Duplicates: Missing: 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..42333a4 --- /dev/null +++ b/spaghetti-monster/anduril/cfg-gchart-fet1-t16.h @@ -0,0 +1,39 @@ +// 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 + +// battery readout style (pick one) +#define BATTCHECK_VpT +//#define BATTCHECK_8bars // FIXME: breaks build +//#define BATTCHECK_4bars // FIXME: breaks build + +//#undef USE_DYNAMIC_UNDERCLOCKING +#define USE_DYNAMIC_UNDERCLOCKING + +// 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 \ No newline at end of file diff --git a/spaghetti-monster/anduril/version.h b/spaghetti-monster/anduril/version.h index 8cf3c90..5ecfc65 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 "20201218" diff --git a/spaghetti-monster/fsm-adc.c b/spaghetti-monster/fsm-adc.c index 71ecf65..2818731 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<>= 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 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< #include +// *** 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< 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< 0) {} // make sure the register is ready to be updated + RTC.PITCTRLA = RTC_PERIOD_CYC16384_gc | RTC_PITEN_bm; // Period = 0.5s, 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 -- cgit v1.2.3