44template <
typename SpiType>
50 two_vref_(2.0f * vref_),
51 active_vref_((initial_range ==
Range::TwoVref) ? two_vref_ : vref_),
52 range_(initial_range) {}
58template <
typename SpiType>
61 two_vref_ = 2.0f * vref_;
66template <
typename SpiType>
75template <
typename SpiType>
78 if (initialized_ && !force) {
85template <
typename SpiType>
93 if (!ProgramAuto1Channels(auto1_mask_)) {
98 if (!ProgramAuto2LastChannel(auto2_last_ch_)) {
103 if (!EnterAuto1Mode(
true)) {
115template <
typename SpiType>
129 const uint16_t ctrl = commonControlBits();
143 result.channel = channel;
144 if (!spiTransfer16(cmd)) {
149 manual_channel_ = channel;
154 if (!spiTransfer16(cont, &resp)) {
162 result.voltage = CountToVoltage(result.count);
168 result.channel = channel;
173template <
typename SpiType>
183 const uint16_t ctrl = commonControlBits();
184 const uint16_t target_mask = auto1_mask_ & 0x0FFF;
185 const uint8_t num_enabled = popcount16(target_mask);
187 if (num_enabled == 0) {
201 if (!spiTransfer16(cmd)) {
209 const uint8_t max_frames =
212 for (uint8_t i = 0; i < max_frames; ++i) {
214 if (!spiTransfer16(cont, &resp)) {
222 result.count[ch] = data;
223 result.voltage[ch] = CountToVoltage(data);
224 result.valid_mask |=
static_cast<uint16_t
>(1U << ch);
227 if (result.valid_mask == target_mask) {
242template <
typename SpiType>
245 return (
static_cast<float>(count) * active_vref_)
249template <
typename SpiType>
252 if (voltage <= 0.0f)
return 0;
253 float raw = (voltage / active_vref_) *
static_cast<float>(
reg::MAX_COUNT);
255 return static_cast<uint16_t
>(raw);
262template <
typename SpiType>
269 if (!spiTransfer16(cmd)) {
273 manual_channel_ = channel;
277template <
typename SpiType>
282 | commonControlBits();
283 if (!spiTransfer16(cmd)) {
290template <
typename SpiType>
295 | commonControlBits();
296 if (!spiTransfer16(cmd)) {
307template <
typename SpiType>
317 if (!spiTransfer16(channel_mask & 0x0FFF)) {
321 auto1_mask_ = channel_mask & 0x0FFF;
329template <
typename SpiType>
339 auto2_last_ch_ = last_channel;
347template <
typename SpiType>
353 if (config.reset_all_registers) {
358 if (config.gpio3_as_powerdown_input) {
363 if (config.gpio2_as_range_input) {
368 switch (config.alarm_mode) {
386 frame |=
static_cast<uint16_t
>(config.direction_mask & 0x0F);
388 return spiTransfer16(frame);
395template <
typename SpiType>
398 uint16_t threshold_12bit)
noexcept {
411 default:
return false;
415 if (!spiTransfer16(group_mode)) {
430 if (!spiTransfer16(alarm_frame)) {
438template <
typename SpiType>
441 float voltage)
noexcept {
449template <
typename SpiType>
450template <
typename Commit>
470 if (!spiTransfer16(cmd)) {
483template <
typename SpiType>
486 const uint16_t ctrl = (commonControlBits() & ~reg::RANGE_2VREF) |
488 return programControlBits(ctrl, [&] {
494template <
typename SpiType>
497 const uint16_t ctrl = (commonControlBits() & ~reg::POWER_DOWN) |
499 return programControlBits(ctrl, [&] { power_down_ = pd; });
506template <
typename SpiType>
509 const uint8_t state = gpio_state & 0x0F;
510 const uint16_t ctrl =
static_cast<uint16_t
>((commonControlBits() & ~0x000Fu) | state);
511 return programControlBits(ctrl, [&] { gpio_output_state_ = state; });
518template <
typename SpiType>
521 uint8_t n)
noexcept {
522 if (!initialized_ || out ==
nullptr || n == 0 ||
526 const uint16_t ctrl = commonControlBits();
532 manual_channel_ = channel;
534 for (uint8_t i = 1; i < n; ++i) {
535 if (!spiTransfer16(cont, &out[i])) {
546template <
typename SpiType>
550 static_cast<uint8_t
>((command >> 8) & 0xFF),
551 static_cast<uint8_t
>(command & 0xFF)};
552 uint8_t rx[2] = {0, 0};
558 if (response !=
nullptr) {
559 *response = ok ?
static_cast<uint16_t
>((
static_cast<uint16_t
>(rx[0]) << 8) | rx[1]) : 0;
564template <
typename SpiType>
566uint16_t ADS7952<SpiType>::commonControlBits() const noexcept {
577 bits |=
static_cast<uint16_t
>(gpio_output_state_ & 0x0F);
582template <
typename SpiType>
584constexpr uint8_t ADS7952<SpiType>::popcount16(uint16_t x)
noexcept {
585 x = x - ((x >> 1) & 0x5555);
586 x = (x & 0x3333) + ((x >> 2) & 0x3333);
587 return static_cast<uint8_t
>((((x + (x >> 4)) & 0x0F0F) * 0x0101) >> 8);
Main driver class for the ADS7952 ADC.
constexpr uint8_t READ_ALL_MAX_EXTRA_FRAMES
constexpr uint8_t MANUAL_READ_MAX_FRAMES
constexpr uint16_t VoltageToCount(float voltage, float vref) noexcept
Convert a voltage to a 12-bit ADC count.
float CountToVoltage(uint16_t count) const noexcept
Convert raw count to voltage using the currently active reference.
bool SetGPIOOutputs(uint8_t gpio_state) noexcept
Set GPIO output pin levels (for pins configured as outputs).
ChannelReadings ReadAllChannels() noexcept
Read all channels in the current Auto-1 sequence.
void SetVref(float vref) noexcept
Update the Vref value for voltage calculations.
bool ProgramAuto2LastChannel(uint8_t last_channel) noexcept
Program the Auto-2 last channel.
uint8_t RawManualFrames(uint8_t channel, uint16_t *out, uint8_t n) noexcept
Clock raw 16-bit frames and return every response word unparsed.
bool ProgramGPIO(const GPIOConfig &config) noexcept
Program GPIO pin functions, direction, and alarm routing.
bool ProgramAlarm(uint8_t channel, AlarmBound bound, uint16_t threshold_12bit) noexcept
Program an alarm threshold for a single channel (count-based).
bool ProgramAlarmVoltage(uint8_t channel, AlarmBound bound, float voltage) noexcept
Program an alarm threshold for a single channel (voltage-based).
void SetVA(float va) noexcept
Update the VA supply voltage value.
uint16_t VoltageToCount(float voltage) const noexcept
Convert a voltage to a 12-bit ADC count using the active reference.
bool SetPowerDown(PowerDown pd) noexcept
Set the power-down mode; in effect on the chip when this returns.
ReadResult ReadChannel(uint8_t channel) noexcept
Read a single ADC channel (switches to Manual mode).
bool EnterManualMode(uint8_t channel=0) noexcept
Enter Manual mode, selecting the given channel for conversion.
bool EnterAuto2Mode(bool reset_counter=true) noexcept
Enter Auto-2 mode (sequences channels 0 through last_channel).
bool EnterAuto1Mode(bool reset_counter=true) noexcept
Enter Auto-1 mode (sequences through programmed channel mask).
bool ProgramAuto1Channels(uint16_t channel_mask) noexcept
Program the Auto-1 channel sequence.
bool SetRange(Range range) noexcept
Set the input voltage range; in effect on the chip when this returns.
bool EnsureInitialized(bool force=false) noexcept
Ensure the driver is initialized — idempotent, safe to call repeatedly.
ADS7952(SpiType &spi, float vref=ADS7952_CFG::DEFAULT_VREF, float va=ADS7952_CFG::DEFAULT_VA, Range initial_range=ADS7952_CFG::DEFAULT_RANGE) noexcept
Construct a new ADS7952 driver instance.
constexpr uint16_t ChannelSelect(uint8_t ch) noexcept
Encode manual-mode channel selection bits DI[10:7].
constexpr uint16_t Auto2LastChannel(uint8_t ch) noexcept
Encode Auto-2 last-channel field DI[9:6].
@ GPIO0_HighAndLowAlarm
xx1: GPIO0 = combined high-or-low alarm output
@ GPIO0_HighAlarm
010: GPIO0 = high alarm output
@ GPIO
000: both as general-purpose I/O
@ GPIO1_LowAlarm
100: GPIO1 = low alarm output
@ GPIO1_LowAlarm_GPIO0_HighAlarm
@ PowerDown
Device enters power-down.
@ Auto2
Device sequences channels 0 to last_channel.
@ Auto1
Device sequences through programmed channel mask.
@ Manual
Host selects channel each frame.
@ TwoVref
0 to 2*Vref, clamped to VA (RANGE bit = 1)
@ High
High alarm threshold register.
@ SpiError
SPI transfer failure.
@ InvalidChannel
Channel number out of range (0-11)
@ NotInitialized
Driver not initialized.
@ Timeout
Operation timed out waiting for data.
bool Transfer(Port &port, const uint8_t *tx, uint8_t *rx, std::size_t len)
Call the port's transfer() and return its status.
constexpr uint16_t EXIT_NEXT_FRAME
constexpr uint16_t Threshold12To10(uint16_t adc_12bit) noexcept
Convert 12-bit ADC threshold to 10-bit alarm register format.
constexpr uint16_t HIGH_REGISTER
constexpr uint16_t ChannelInGroup(uint8_t ch_in_group) noexcept
Encode alarm channel index within a 4-channel group.
constexpr uint16_t GPIO0_HI_ALARM
constexpr uint16_t RESET_ALL_REGS
constexpr uint16_t GPIO1_LO_GPIO0_HI_ALARM
constexpr uint16_t GPIO1_LO_ALARM
constexpr uint16_t GPIO3_PWRDOWN_IN
constexpr uint16_t GPIO0_HI_LO_ALARM
constexpr uint16_t GPIO2_RANGE_IN
constexpr uint16_t AUTO_1
constexpr uint16_t AUTO_1_PROG
constexpr uint16_t ALARM_GROUP_0
constexpr uint16_t ALARM_GROUP_1
constexpr uint16_t CONTINUE
constexpr uint16_t GPIO_PROG
constexpr uint16_t AUTO_2_PROG
constexpr uint16_t ALARM_GROUP_2
constexpr uint16_t MANUAL
constexpr uint16_t AUTO_2
constexpr uint8_t GetChannel(uint16_t frame) noexcept
Extract channel descriptor from response frame DO[15:12].
constexpr uint16_t GetData(uint16_t frame) noexcept
Extract conversion data from response frame DO[11:0].
constexpr uint16_t POWER_NORMAL
constexpr uint16_t PROGRAM_RETAIN
constexpr uint16_t RANGE_2VREF
constexpr uint16_t NO_RESET_COUNTER
constexpr uint16_t PROGRAM_ENABLE
constexpr uint16_t RANGE_VREF
constexpr uint8_t NUM_CHANNELS
Number of ADC input channels.
constexpr uint16_t POWER_DOWN
constexpr uint16_t MAX_COUNT
Maximum 12-bit conversion value.
constexpr uint16_t RESET_COUNTER
constexpr uint8_t CHANNELS_PER_ALARM_GROUP
Channels per alarm group.
static constexpr uint8_t MAX_CHANNELS