aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEddy Pedroni <epedroni@pm.me>2026-10-25 17:18:09 +0100
committerEddy Pedroni <epedroni@pm.me>2026-10-25 17:18:09 +0100
commit7b0108f3ec40e9dd92737cc4a537042582e1161e (patch)
tree4a2a6b706e485bb9a799a42dd9ef2ac1d938633b
parent6bae8cbfeecafa43c5fc65985bbd98ea09220abd (diff)
Implement ADC without hysteresis, not tested
-rw-r--r--firmware/src/adc.hpp68
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;
}
}