aboutsummaryrefslogtreecommitdiff
path: root/fsm/adc.c
diff options
context:
space:
mode:
authorSelene ToyKeeper2023-11-10 21:34:40 -0700
committerSelene ToyKeeper2023-11-10 21:34:40 -0700
commit3d12b7066d27b591e0283e20ed066bc66e29fbe4 (patch)
tree08a0ed41a4b0baa7f7f5ea4eed6ee10ac250250c /fsm/adc.c
parentadded md5sum to build-all.sh output per target (diff)
downloadanduril-3d12b7066d27b591e0283e20ed066bc66e29fbe4.tar.gz
anduril-3d12b7066d27b591e0283e20ed066bc66e29fbe4.tar.bz2
anduril-3d12b7066d27b591e0283e20ed066bc66e29fbe4.zip
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...
Diffstat (limited to '')
-rw-r--r--fsm/adc.c159
1 files changed, 20 insertions, 139 deletions
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<<ADEN); //ADC off
- #endif
-}
+#define ADC_on mcu_adc_on
+// stop the ADC
+#define ADC_off mcu_adc_off
#ifdef USE_VOLTAGE_DIVIDER
static inline uint8_t calc_voltage_divider(uint16_t value) {
@@ -171,15 +68,11 @@ 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
+ // clear the interrupt flag
+ mcu_adc_vect_clear();
if (adc_sample_count) {
@@ -188,22 +81,12 @@ 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
-
+ #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;