#include #include namespace { constexpr std::uint32_t base_address = 0x4004'c000u; std::uint32_t volatile * const control_status_addr = reinterpret_cast(base_address + 0x0u); std::uint32_t volatile * const result_addr = reinterpret_cast(base_address + 0x4u); void select_input(std::uint32_t index) { constexpr std::uint32_t ainsel = 0x111u; *control_status_addr = (*control_status_addr & ~(ainsel << 12)) | ((index & ainsel) << 12); } bool ready() { return (*control_status_addr & 1u << 8) != 0u; } bool error() { return (*control_status_addr & 1u << 9) != 0u; } void start_once() { *control_status_addr |= (1u << 2); } void enable(bool en) { *control_status_addr |= en ? (1u << 2) : 0u; } std::uint32_t result() { return *result_addr & 0x0000'0fffu; } std::array previous_samples { 0xffff'ffffu, 0xffff'ffffu }; } namespace adc { struct Sample { std::uint8_t value {0}; bool changed {false}; }; void init() { enable(true); } std::array get_samples() { while (!ready()); std::array samples {}; for (std::size_t i = 0; i < samples.size(); i++) { select_input(i); start_once(); while (!ready()); std::uint32_t const measurement = result(); samples[i].changed = measurement != previous_samples[i]; previous_samples[i] = measurement; samples[i].value = measurement * 127u / 4095u; // TODO add hysteresis } return samples; } }