From 3d12b7066d27b591e0283e20ed066bc66e29fbe4 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Fri, 10 Nov 2023 21:34:40 -0700 Subject: refactor checkpoint: splitting MCU-specific code into arch/$MCU.[ch] Phew, that's a lot of changes! And there's still a lot more to do... --- fsm/adc.c | 159 ++++++------------------------------------------ fsm/adc.h | 12 ++-- fsm/main.c | 62 +------------------ fsm/misc.c | 22 ------- fsm/misc.h | 4 -- fsm/pcint.c | 54 +--------------- fsm/pcint.h | 6 +- fsm/spaghetti-monster.h | 9 ++- fsm/wdt.c | 78 +----------------------- fsm/wdt.h | 7 ++- 10 files changed, 47 insertions(+), 366 deletions(-) (limited to 'fsm') diff --git a/fsm/adc.c b/fsm/adc.c index 31b250f..6d4eeb1 100644 --- a/fsm/adc.c +++ b/fsm/adc.c @@ -16,57 +16,14 @@ static inline void set_admux_therm() { - #if (ATTINY == 1634) - ADMUX = ADMUX_THERM; - #elif (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - ADMUX = ADMUX_THERM | (1 << ADLAR); - #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 + hwdef_set_admux_therm(); adc_channel = 1; adc_sample_count = 0; // first result is unstable ADC_start_measurement(); } inline void set_admux_voltage() { - #if (ATTINY == 1634) - #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 - ADMUX = ADMUX_VOLTAGE_DIVIDER; - #else // VCC / 1.1V reference - ADMUX = ADMUX_VCC; - #endif - #elif (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 - ADMUX = ADMUX_VOLTAGE_DIVIDER | (1 << ADLAR); - #else // VCC / 1.1V reference - ADMUX = ADMUX_VCC | (1 << ADLAR); - #endif - #elif (ATTINY == 841) // FIXME: not tested - #ifdef USE_VOLTAGE_DIVIDER // 1.1V / pin7 - ADMUXA = ADMUXA_VOLTAGE_DIVIDER; - ADMUXB = ADMUXB_VOLTAGE_DIVIDER; - #else // VCC / 1.1V reference - 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 + hwdef_set_admux_voltage(); adc_channel = 0; adc_sample_count = 0; // first result is unstable ADC_start_measurement(); @@ -74,79 +31,19 @@ inline void set_admux_voltage() { #ifdef TICK_DURING_STANDBY -inline void adc_sleep_mode() { // needs a special sleep mode to get accurate measurements quickly // ... full power-down ends up using more power overall, and causes // some weird issues when the MCU doesn't stay awake enough cycles // to complete a reading - #ifdef SLEEP_MODE_ADC - // attiny1634 - set_sleep_mode(SLEEP_MODE_ADC); - #elif defined(AVRXMEGA3) // ATTINY816, 817, etc - set_sleep_mode(SLEEP_MODE_STANDBY); - #else - #error No ADC sleep mode defined for this hardware. - #endif -} + #define adc_sleep_mode mcu_adc_sleep_mode #endif -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 -} +#define ADC_start_measurement mcu_adc_start_measurement // set up ADC for reading battery voltage -inline void ADC_on() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) || (ATTINY == 1634) - set_admux_voltage(); - #ifdef USE_VOLTAGE_DIVIDER - // disable digital input on divider pin to reduce power consumption - VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); - #else - // disable digital input on VCC pin to reduce power consumption - //VOLTAGE_ADC_DIDR |= (1 << VOLTAGE_ADC); // FIXME: unsure how to handle for VCC pin - #endif - #if (ATTINY == 1634) - //ACSRA |= (1 << ACD); // turn off analog comparator to save power - ADCSRB |= (1 << ADLAR); // left-adjust flag is here instead of ADMUX - #endif - // enable, start, auto-retrigger, prescale - ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | ADC_PRSCL; - // end tiny25/45/85 - #elif (ATTINY == 841) // FIXME: not tested, missing left-adjust - ADCSRB = 0; // Right adjusted, auto trigger bits cleared. - //ADCSRA = (1 << ADEN ) | 0b011; // ADC on, prescaler division factor 8. - set_admux_voltage(); - // 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 - VREF.CTRLA |= VREF_ADC0REFSEL_1V1_gc; // Set Vbg ref to 1.1V - // Enabled, free-running (aka, auto-retrigger), run in standby - ADC0.CTRLA = ADC_ENABLE_bm | ADC_FREERUN_bm | ADC_RUNSTBY_bm; - // set a INITDLY value because the AVR manual says so (section 30.3.5) - // (delay 1st reading until Vref is stable) - ADC0.CTRLD |= ADC_INITDLY_DLY16_gc; - set_admux_voltage(); - #else - #error Unrecognized MCU type - #endif -} - -inline void ADC_off() { - #ifdef AVRXMEGA3 // ATTINY816, 817, etc - ADC0.CTRLA &= ~(ADC_ENABLE_bm); // disable the ADC - #else - ADCSRA &= ~(1<>= 8; // Divide result to get Kelvin - m = (temp << 6); // left align it - } - else { m = (ADC0.RES << 6); } // voltage, force left-alignment - + #ifdef MCU_ADC_RESULT_PER_TYPE + // thermal, convert ADC reading to left-aligned Kelvin + if (channel) m = mcu_adc_result_temp(); + else m = mcu_adc_result_volts(); #else - m = ADC; + m = mcu_adc_result(); #endif adc_raw[channel] = m; @@ -235,11 +118,7 @@ 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 + pseudo_rand_seed += mcu_adc_lsb(); #endif // the ADC triggers repeatedly when it's on, but we only need to run the @@ -373,9 +252,9 @@ 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 + #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 @@ -440,6 +319,8 @@ static inline void ADC_temperature_handler() { // let the UI see the current temperature in C // Convert ADC units to Celsius (ish) + // FIXME: call something in arch/$mcu.h or hwdef.h + // instead of calculating this here #ifndef USE_EXTERNAL_TEMP_SENSOR // onboard sensor for attiny25/45/85/1634 temperature = (measurement>>1) + THERM_CAL_OFFSET + (int16_t)TH_CAL - 275; diff --git a/fsm/adc.h b/fsm/adc.h index 1bb67ed..e4046a4 100644 --- a/fsm/adc.h +++ b/fsm/adc.h @@ -102,11 +102,15 @@ static inline void ADC_temperature_handler(); #endif // ifdef USE_THERMAL_REGULATION -inline void ADC_on(); -inline void ADC_off(); -inline void ADC_start_measurement(); +//inline void ADC_on(); +#define ADC_on mcu_adc_on +//inline void ADC_off(); +#define ADC_off mcu_adc_off +//inline void ADC_start_measurement(); +#define ADC_start_measurement mcu_adc_start_measurement #ifdef TICK_DURING_STANDBY -inline void adc_sleep_mode(); + //inline void adc_sleep_mode(); + #define adc_sleep_mode mcu_adc_sleep_mode #endif diff --git a/fsm/main.c b/fsm/main.c index 0524115..1c01878 100644 --- a/fsm/main.c +++ b/fsm/main.c @@ -23,66 +23,6 @@ ISR(TIMER1_COMPA_vect) { } #endif -// FIXME: hw_setup() shouldn't be here ... move it entirely to hwdef files -#if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) -static inline void hw_setup() { - #if !defined(USE_GENERIC_HWDEF_SETUP) - hwdef_setup(); - #else - // configure PWM channels - #if PWM_CHANNELS >= 1 - DDRB |= (1 << PWM1_PIN); - TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...) - TCCR0A = PHASE; - #if (PWM1_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - // tint ramping needs second channel enabled, - // despite PWM_CHANNELS being only 1 - #if (PWM_CHANNELS >= 2) || defined(USE_TINT_RAMPING) - DDRB |= (1 << PWM2_PIN); - #if (PWM2_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - #if PWM_CHANNELS >= 3 - DDRB |= (1 << PWM3_PIN); - #if (PWM3_PIN == PB4) // Second PWM counter is ... weird - TCCR1 = _BV (CS10); - GTCCR = _BV (COM1B1) | _BV (PWM1B); - OCR1C = 255; // Set ceiling value to maximum - #endif - #endif - #if PWM_CHANNELS >= 4 - // 4th PWM channel is ... not actually supported in hardware :( - DDRB |= (1 << PWM4_PIN); - //OCR1C = 255; // Set ceiling value to maximum - TCCR1 = 1< -#include +#include "arch/mcu.h" // include project definitions to help with recognizing symbols #include "fsm/events.h" @@ -39,6 +38,10 @@ #include "arch/delay.h" #endif +////////// include all the .c files ////////// + +#include "arch/mcu.c" + #ifdef USE_DEBUG_BLINK #define DEBUG_FLASH PWM1_LVL = 64; delay_4ms(2); PWM1_LVL = 0; void debug_blink(uint8_t num) { diff --git a/fsm/wdt.c b/fsm/wdt.c index 64f006e..1095d44 100644 --- a/fsm/wdt.c +++ b/fsm/wdt.c @@ -7,85 +7,9 @@ #include #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) - // interrupt every 16ms - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - WDTCR |= (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 -} - -#ifdef TICK_DURING_STANDBY -inline void WDT_slow() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - // interrupt slower - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - WDTCR |= (1< 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 -} -#endif - -inline void WDT_off() -{ - #if (ATTINY == 25) || (ATTINY == 45) || (ATTINY == 85) - //cli(); // Disable interrupts - wdt_reset(); // Reset the WDT - MCUSR &= ~(1< 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 + mcu_wdt_vect_clear(); irq_wdt = 1; // WDT event happened } diff --git a/fsm/wdt.h b/fsm/wdt.h index abf34c5..98eaf25 100644 --- a/fsm/wdt.h +++ b/fsm/wdt.h @@ -6,8 +6,11 @@ #define TICKS_PER_SECOND 62 -void WDT_on(); -inline void WDT_off(); +//void WDT_on(); +//inline void WDT_off(); +#define WDT_on mcu_wdt_active +#define WDT_slow mcu_wdt_standby +#define WDT_off mcu_wdt_stop volatile uint8_t irq_wdt = 0; // WDT interrupt happened? -- cgit v1.2.3