Rewrite on libavr
Same controller: thermistor on ADC0 averaged over 1000 free-running conversions, 50 kHz fan PWM on OC0B, 115200 Bd console with the full command set, EEPROM temperature histogram, watchdog-reset path into the boot section. The Steinhart-Hart math and the libm log are gone — the Beta equation and the cubic fan curve are consteval-evaluated into flash tables; the firmware never does floating point. Byte-identical .text in both libavr modes. Legacy stays on master. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
68
src/board.hpp
Normal file
68
src/board.hpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <libavr/libavr.hpp>
|
||||
|
||||
// The board composition: every peripheral of the fan controller in one
|
||||
// place. ATmega328P at 16 MHz — thermistor divider on ADC0 (PC0), fan on
|
||||
// OC0B (PD5) at 50 kHz, console on the hardware UART.
|
||||
namespace app {
|
||||
|
||||
using namespace avr::literals;
|
||||
|
||||
using dev = avr::device<{.clock = 16_MHz}>;
|
||||
|
||||
// Millisecond uptime from timer2 CTC (the fan owns timer0).
|
||||
class uptime {
|
||||
static inline volatile std::uint64_t ms = 0;
|
||||
|
||||
public:
|
||||
using ticker = dev::timer2<{.frequency = 1_kHz, .on_compare = [] { ms = ms + 1; }}>;
|
||||
|
||||
static std::uint64_t millis()
|
||||
{
|
||||
avr::irq::atomic_guard lock;
|
||||
return ms;
|
||||
}
|
||||
};
|
||||
|
||||
// 1000-sample averaging window fed by the conversion interrupt.
|
||||
class sampler {
|
||||
static inline volatile std::uint32_t sum = 0;
|
||||
static inline volatile std::uint16_t count = 0;
|
||||
static inline volatile std::uint16_t window = 0;
|
||||
static inline volatile bool ready = false;
|
||||
|
||||
static constexpr std::uint16_t samples = 1000;
|
||||
|
||||
public:
|
||||
using input = dev::adc<{.input = avr::adc::input_pin(0),
|
||||
.trigger = avr::adc::trigger::free_running,
|
||||
.on_conversion = [](std::uint16_t value) {
|
||||
sum = sum + value;
|
||||
count = count + 1;
|
||||
if (count >= samples) {
|
||||
window = static_cast<std::uint16_t>(sum / samples);
|
||||
sum = 0;
|
||||
count = 0;
|
||||
ready = true;
|
||||
}
|
||||
}}>;
|
||||
|
||||
// The finished average (raw 10-bit), once per window.
|
||||
static bool take(std::uint16_t &value)
|
||||
{
|
||||
avr::irq::atomic_guard lock;
|
||||
if (!ready)
|
||||
return false;
|
||||
value = window;
|
||||
ready = false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
using fan = dev::pwm<avr::pd5, {.frequency = 50_kHz}>;
|
||||
|
||||
using serial_t = dev::uart0<{.baud = 115200_Bd, .rx_buffer = 32, .max_baud_error = 2.5_pct}>;
|
||||
inline constexpr serial_t serial{};
|
||||
|
||||
} // namespace app
|
||||
Reference in New Issue
Block a user