Files
wheel_rfm69_counter/avr_code/adc.c
T
thebears bbdcc1e623 Refactor firmware for clarity; no functional changes
- main.c: file-header comment describing the hardware and operation, logic
  split into named phases (sleep_until_interrupt, wake_peripheral_rails,
  take_counts_snapshot, send_wheel_counts_report, handle_minute_alarm,
  init_all_hardware); shared state renamed to say what it is and made static.
- rfm69.c: reorganized into six labeled sections; cond_1/2/3 and hash scratch
  globals replaced by a reply_acknowledges() helper with clear locals; packet
  layout and every init register write documented.
- LOG() macro (compiled out when DO_UART is off) replaces the #if DO_UART
  blocks that obscured the logic.
- Drivers: file-header comments; named RTC_REG_*/RTC_ALM_MASK_BIT constants;
  EEPROM spool scheme documented; ADC_CHANNEL_BANDGAP named; repeated pin
  if/else helpers collapsed to SET_PIN_TO().
- Removed unused globals/buffers and commented-out code; ran clang-format
  with the project style.

Register writes and radio protocol are byte-identical. Builds clean under
-Wall -Wextra on gnu17 and c23; flash 13028 -> 12830 B, static RAM
1038 -> 999 B.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YVJKatfeMJjAmuH9KYiLuv
2026-08-31 23:04:00 -04:00

73 lines
1.9 KiB
C

#include "adc.h"
#define ADC_CONVERSION_TIMEOUT 1000U
// The ADC needs a 50-200 kHz clock. At F_CPU = 8 MHz that is a /64 prescaler
// (125 kHz); the old /2 ran it at 4 MHz, far out of spec.
#define ADC_PRESCALER_64 ((1 << ADPS2) | (1 << ADPS1))
// The 1.1 V bandgap reference needs time to settle after the mux is switched.
#define ADC_SETTLE_US 200
int8_t adc_Initialize(void)
{
// REFS VAL_0x01; ADLAR disabled; MUX adc0;
ADMUX = 0x40;
// ACME disabled; ADTS VAL_0x00;
ADCSRB = 0x00;
ADCSRA = (1 << ADEN) | ADC_PRESCALER_64;
return 0;
}
void adc_Disable(void) { ADCSRA &= ~(1 << ADEN); }
void adc_Enable(void) { ADCSRA |= (1 << ADEN); }
void adc_StartConversion(uint8_t channel)
{
if (channel == 0) {
ADMUX = 0b01000000;
} else if (channel == ADC_CHANNEL_BANDGAP) {
// ADMUX=0b01001110;
ADMUX = (0x01 << REFS0) | (0 << ADLAR) | (0x0e << MUX0);
} else {
ADMUX &= ~0x0f;
ADMUX |= channel;
}
_delay_us(ADC_SETTLE_US);
ADCSRA |= (1 << ADSC);
}
bool adc_IsConversionDone(void) { return ((ADCSRA & (1 << ADIF))); }
uint16_t adc_GetConversionResult(void)
{
// ADC reads ADCL then ADCH in the right order. Reading the two volatile
// registers in one expression leaves the order unspecified, and taking ADCH
// first breaks the data-register lock and corrupts the result.
return ADC;
}
uint16_t adc_GetConversion(uint8_t channel)
{
adc_StartConversion(channel);
// A conversion is 13 ADC clocks (~104 us at 125 kHz); bail out rather than
// hang if the ADC is disabled or its clock is gated off.
uint16_t attempts = 0;
while (!adc_IsConversionDone()) {
if (++attempts > ADC_CONVERSION_TIMEOUT) {
return 0;
}
_delay_us(10);
}
uint16_t res = adc_GetConversionResult();
ADCSRA |= (1 << ADIF);
return res;
}