idfxx 1.0.0
Modern C++23 components for ESP-IDF
Loading...
Searching...
No Matches
adc.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 Chris Leishman
3
4#pragma once
5
31#include <idfxx/error>
32#include <idfxx/gpio>
33
34#include <chrono>
35#include <cstddef>
36#include <cstdint>
37#include <electro/electro>
38#include <frequency/frequency>
39#include <memory>
40#include <optional>
41#include <span>
42#include <vector>
43
48namespace idfxx::adc {
49
57enum class attenuation : uint8_t {
58 db_0,
59 db_2_5,
60 db_6,
61 db_12,
62};
63
73 int num = 1;
74 int den = 1;
75
79 [[nodiscard]] constexpr bool operator==(const divider_ratio&) const noexcept = default;
80};
81
93class input {
94public:
99 struct config {
106
110 [[nodiscard]] constexpr bool operator==(const config&) const noexcept = default;
111 };
112
113#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
125 [[nodiscard]] explicit input(config config);
126#endif
127
139 [[nodiscard]] static result<input> make(config config);
140
142
143 input(const input&) = delete;
144 input& operator=(const input&) = delete;
145 input(input&& other) noexcept;
146 input& operator=(input&& other) noexcept;
147
149 [[nodiscard]] idfxx::gpio pin() const noexcept;
150
152 [[nodiscard]] enum attenuation attenuation() const noexcept;
153
155 [[nodiscard]] divider_ratio divider() const noexcept;
156
158 [[nodiscard]] bool calibrated() const noexcept;
159
160#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
167 [[nodiscard]] int read_raw() { return unwrap(try_read_raw()); }
168
181 [[nodiscard]] electro::millivolts read_voltage() { return unwrap(try_read_voltage()); }
182#endif
183
188 [[nodiscard]] result<int> try_read_raw();
189
201
202private:
204 struct state;
205 explicit input(std::unique_ptr<state> s) noexcept;
207
208 std::unique_ptr<state> _state;
209};
210
234class sampler {
235public:
240 struct config {
242 std::vector<idfxx::gpio> pins{};
247 freq::hertz sample_rate{20'000};
249 size_t frame_samples = 256;
252 size_t buffer_samples = 1024;
253
257 [[nodiscard]] bool operator==(const config&) const noexcept = default;
258 };
259
264 struct sample {
266 int raw = 0;
267
271 [[nodiscard]] constexpr bool operator==(const sample&) const noexcept = default;
272 };
273
274#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
288 [[nodiscard]] explicit sampler(config config);
289#endif
290
306 [[nodiscard]] static result<sampler> make(config config);
307
312
313 sampler(const sampler&) = delete;
314 sampler& operator=(const sampler&) = delete;
315 sampler(sampler&& other) noexcept;
316 sampler& operator=(sampler&& other) noexcept;
317
319 [[nodiscard]] std::span<const idfxx::gpio> pins() const noexcept;
320
322 [[nodiscard]] enum attenuation attenuation() const noexcept;
323
325 [[nodiscard]] freq::hertz sample_rate() const noexcept;
326
328 [[nodiscard]] bool running() const noexcept;
329
331 [[nodiscard]] bool calibrated() const noexcept;
332
342 [[nodiscard]] size_t overruns() const noexcept;
343
344#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
355 void start() { unwrap(try_start()); }
356
365 void stop() { unwrap(try_stop()); }
366#endif
367
377 [[nodiscard]] result<void> try_start();
378
388
389#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
404 [[nodiscard]] size_t read(std::span<sample> out) { return unwrap(try_read(out)); }
405
423 template<typename Rep, typename Period>
424 [[nodiscard]] size_t read(std::span<sample> out, const std::chrono::duration<Rep, Period>& timeout) {
425 return unwrap(try_read(out, timeout));
426 }
427
445 [[nodiscard]] size_t read(std::span<electro::millivolts> out) { return unwrap(try_read(out)); }
446
465 template<typename Rep, typename Period>
466 [[nodiscard]] size_t read(std::span<electro::millivolts> out, const std::chrono::duration<Rep, Period>& timeout) {
467 return unwrap(try_read(out, timeout));
468 }
469#endif
470
484 [[nodiscard]] result<size_t> try_read(std::span<sample> out) { return _try_read(out, std::nullopt); }
485
503 template<typename Rep, typename Period>
504 [[nodiscard]] result<size_t> try_read(std::span<sample> out, const std::chrono::duration<Rep, Period>& timeout) {
505 return _try_read(out, std::chrono::ceil<std::chrono::milliseconds>(timeout));
506 }
507
526 [[nodiscard]] result<size_t> try_read(std::span<electro::millivolts> out) {
527 return _read_voltage(out, std::nullopt);
528 }
529
547 template<typename Rep, typename Period>
548 [[nodiscard]] result<size_t>
549 try_read(std::span<electro::millivolts> out, const std::chrono::duration<Rep, Period>& timeout) {
550 return _read_voltage(out, std::chrono::ceil<std::chrono::milliseconds>(timeout));
551 }
552
553#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
565 [[nodiscard]] electro::millivolts to_voltage(const sample& s) const { return unwrap(try_to_voltage(s)); }
566
582 [[nodiscard]] electro::millivolts to_voltage(int raw) const { return unwrap(try_to_voltage(raw)); }
583
599 void to_voltage(std::span<const sample> in, std::span<electro::millivolts> out) const {
600 unwrap(try_to_voltage(in, out));
601 }
602#endif
603
614 [[nodiscard]] result<electro::millivolts> try_to_voltage(const sample& s) const;
615
629 [[nodiscard]] result<electro::millivolts> try_to_voltage(int raw) const;
630
644 [[nodiscard]] result<void> try_to_voltage(std::span<const sample> in, std::span<electro::millivolts> out) const;
645
646private:
648 struct state;
649 explicit sampler(std::unique_ptr<state> s) noexcept;
650 // A nullopt timeout means wait forever.
651 [[nodiscard]] result<size_t> _try_read(std::span<sample> out, std::optional<std::chrono::milliseconds> timeout);
652 [[nodiscard]] result<size_t>
653 _read_voltage(std::span<electro::millivolts> out, std::optional<std::chrono::milliseconds> timeout);
655
656 std::unique_ptr<state> _state;
657};
658
// end of idfxx_adc
660
661} // namespace idfxx::adc
A one-shot analog input on a single pin.
Definition adc.hpp:93
input & operator=(const input &)=delete
input(config config)
Constructs a one-shot analog input.
static result< input > make(config config)
Creates a one-shot analog input.
int read_raw()
Reads the raw ADC conversion value.
Definition adc.hpp:167
result< electro::millivolts > try_read_voltage()
Reads the input voltage.
bool calibrated() const noexcept
Returns true when factory calibration is active for this input.
input(const input &)=delete
result< int > try_read_raw()
Reads the raw ADC conversion value.
input(input &&other) noexcept
idfxx::gpio pin() const noexcept
Returns the configured pin.
divider_ratio divider() const noexcept
Returns the configured external voltage-divider ratio.
input & operator=(input &&other) noexcept
electro::millivolts read_voltage()
Reads the input voltage.
Definition adc.hpp:181
A continuous sampler over one or more analog pins.
Definition adc.hpp:234
result< size_t > try_read(std::span< sample > out, const std::chrono::duration< Rep, Period > &timeout)
Reads samples, blocking until at least one is available or the timeout expires.
Definition adc.hpp:504
size_t read(std::span< sample > out, const std::chrono::duration< Rep, Period > &timeout)
Reads samples, blocking until at least one is available or the timeout expires.
Definition adc.hpp:424
bool calibrated() const noexcept
Returns true when factory calibration is active for every configured pin.
result< size_t > try_read(std::span< electro::millivolts > out, const std::chrono::duration< Rep, Period > &timeout)
Reads samples as calibrated voltages, blocking until at least one is available or the timeout expires...
Definition adc.hpp:549
static result< sampler > make(config config)
Creates a continuous sampler.
void to_voltage(std::span< const sample > in, std::span< electro::millivolts > out) const
Converts a batch of samples to voltages using factory calibration.
Definition adc.hpp:599
bool running() const noexcept
Returns true while the sampler is started.
electro::millivolts to_voltage(int raw) const
Converts a raw conversion value from a single-pin sampler to a voltage.
Definition adc.hpp:582
freq::hertz sample_rate() const noexcept
Returns the configured total sample rate across all pins.
void start()
Starts continuous conversion.
Definition adc.hpp:355
result< void > try_stop()
Stops continuous conversion.
size_t overruns() const noexcept
Returns the number of dropped-data events since the last start.
~sampler()
Destroys the sampler, stopping conversion and releasing ADC1.
sampler(config config)
Constructs a continuous sampler.
std::span< const idfxx::gpio > pins() const noexcept
Returns the configured pins in conversion order.
size_t read(std::span< electro::millivolts > out)
Reads samples as calibrated voltages, blocking until at least one is available.
Definition adc.hpp:445
result< void > try_start()
Starts continuous conversion.
result< void > try_to_voltage(std::span< const sample > in, std::span< electro::millivolts > out) const
Converts a batch of samples to voltages using factory calibration.
sampler(const sampler &)=delete
sampler & operator=(sampler &&other) noexcept
sampler & operator=(const sampler &)=delete
result< electro::millivolts > try_to_voltage(int raw) const
Converts a raw conversion value from a single-pin sampler to a voltage.
sampler(sampler &&other) noexcept
size_t read(std::span< electro::millivolts > out, const std::chrono::duration< Rep, Period > &timeout)
Reads samples as calibrated voltages, blocking until at least one is available or the timeout expires...
Definition adc.hpp:466
result< size_t > try_read(std::span< electro::millivolts > out)
Reads samples as calibrated voltages, blocking until at least one is available.
Definition adc.hpp:526
electro::millivolts to_voltage(const sample &s) const
Converts a sample to a voltage using factory calibration.
Definition adc.hpp:565
result< electro::millivolts > try_to_voltage(const sample &s) const
Converts a sample to a voltage using factory calibration.
result< size_t > try_read(std::span< sample > out)
Reads samples, blocking until at least one is available.
Definition adc.hpp:484
size_t read(std::span< sample > out)
Reads samples, blocking until at least one is available.
Definition adc.hpp:404
void stop()
Stops continuous conversion.
Definition adc.hpp:365
A GPIO pin.
Definition gpio.hpp:62
static constexpr gpio nc()
Returns a GPIO representing "not connected".
Definition gpio.hpp:255
attenuation
Input attenuation, which sets the measurable voltage range.
Definition adc.hpp:57
@ db_2_5
~0–1250 mV.
@ db_12
~0–3100 mV (full range).
@ db_0
No attenuation (~0–950 mV typical range).
ADC classes and utilities.
Definition adc.hpp:48
T unwrap(result< T > result)
Throws a std::system_error if the result is an error.
Definition error.hpp:307
@ timeout
Operation timed out.
std::expected< T, std::error_code > result
result type wrapping a value or error code.
Definition error.hpp:120
External voltage-divider ratio between a source and an ADC pin.
Definition adc.hpp:72
int num
Ratio numerator (source = pin × num / den); must be positive.
Definition adc.hpp:73
int den
Ratio denominator; must be positive.
Definition adc.hpp:74
constexpr bool operator==(const divider_ratio &) const noexcept=default
Compares two divider ratios for equality.
Configuration for a one-shot analog input.
Definition adc.hpp:99
constexpr bool operator==(const config &) const noexcept=default
Compares two configurations for equality.
divider_ratio divider
External voltage-divider ratio between the source and the pin.
Definition adc.hpp:105
idfxx::gpio pin
ADC-capable GPIO (required).
Definition adc.hpp:100
Configuration for a continuous sampler.
Definition adc.hpp:240
bool operator==(const config &) const noexcept=default
Compares two configurations for equality.
freq::hertz sample_rate
Total conversion rate across all pins; each pin samples at this rate divided by the pin count.
Definition adc.hpp:247
size_t frame_samples
Samples delivered per driver transfer — the read granularity.
Definition adc.hpp:249
size_t buffer_samples
Internal pool capacity in samples (at least frame_samples). Reads must drain the pool faster than it ...
Definition adc.hpp:252
std::vector< idfxx::gpio > pins
ADC1-capable GPIOs, converted round-robin in this order (required, no duplicates).
Definition adc.hpp:242
A single conversion result.
Definition adc.hpp:264
constexpr bool operator==(const sample &) const noexcept=default
Compares two conversion results for equality.
int raw
Raw conversion value (chip bit-width dependent).
Definition adc.hpp:266
idfxx::gpio pin
The pin this conversion was taken from.
Definition adc.hpp:265