diff options
| author | Eddy Pedroni <epedroni@pm.me> | 2026-10-25 17:18:09 +0100 |
|---|---|---|
| committer | Eddy Pedroni <epedroni@pm.me> | 2026-10-25 17:18:09 +0100 |
| commit | 7b0108f3ec40e9dd92737cc4a537042582e1161e (patch) | |
| tree | 4a2a6b706e485bb9a799a42dd9ef2ac1d938633b /firmware/src | |
| parent | 6bae8cbfeecafa43c5fc65985bbd98ea09220abd (diff) | |
Implement ADC without hysteresis, not tested
Diffstat (limited to 'firmware/src')
| -rw-r--r-- | firmware/src/adc.hpp | 68 |
1 files changed, 66 insertions, 2 deletions
diff --git a/firmware/src/adc.hpp b/firmware/src/adc.hpp index a3bd0b0..ef596bc 100644 --- a/firmware/src/adc.hpp +++ b/firmware/src/adc.hpp @@ -1,6 +1,54 @@ #include <array> #include <cstdint> +namespace +{ + +constexpr std::uint32_t base_address = 0x4004'c000u; +std::uint32_t volatile * const control_status_addr = reinterpret_cast<std::uint32_t*>(base_address + 0x0u); +std::uint32_t volatile * const result_addr = reinterpret_cast<std::uint32_t*>(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<std::uint32_t, 2> previous_samples { 0xffff'ffffu, 0xffff'ffffu }; + +} + namespace adc { @@ -13,13 +61,29 @@ struct Sample void init() { + enable(true); } std::array<Sample, 2> get_samples() { - // TODO: scale 12-bit range into MIDI 7-bit range with hysteresis - return std::array<Sample, 2>{{{}, {}}}; + while (!ready()); + + std::array<Sample, 2> 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; } } |
