26#include <util/crc16.h>
37 : spiSlave(bus, cs, spiConfig), config(config)
45 bool resetSuccess =
reset();
54 uint8_t data[FULL_FRAME_SIZE] = {0};
55 sendCommand(transaction, Command::RESET, data);
63 uint16_t response = transaction.
read24() >> 8;
66 if (response != RESET_CMD_RESPONSE)
69 LOG_ERR(logger,
"Reset command failed, response was {:X}", response);
78 for (
int i = 0; i < CHANNELS_NUM; i++)
83 enableGlobalChopMode();
85 disableGlobalChopMode();
88 this->config = config;
103 applyChannelConfig(channel, calibrationConfig);
106 int32_t averageValue = 0;
107 int realSampleCount = 0;
108 for (
int i = 0; i < CALIBRATION_SAMPLES; i++)
114 int32_t rawValues[CHANNELS_NUM];
115 if (!readSamples(rawValues))
121 averageValue += rawValues[
static_cast<int>(channel)];
126 if (realSampleCount == 0)
128 LOG_ERR(logger,
"Calibration failed, no valid samples");
133 averageValue /= realSampleCount;
134 LOG_INFO(logger,
"Channel {} average offset: {}",
135 static_cast<int>(channel),
136 averageValue * getLSBSizeFromGain(calibrationConfig.pga));
139 if (averageValue != 0)
147 applyChannelConfig(channel,
162 for (
int i = 0; i < CHANNELS_NUM; i++)
164 applyChannelConfig(
static_cast<Channel>(i), selfTestConfig);
165 setChannelInput(
static_cast<Channel>(i), Input::POSITIVE_DC_TEST);
167 setOversamplingRatio(OversamplingRatio::OSR_16256);
168 disableGlobalChopMode();
171 int32_t averageValues[CHANNELS_NUM] = {0};
172 int realSampleCount = 0;
173 for (
int i = 0; i < SELF_TEST_SAMPLES; i++)
179 int32_t rawValues[CHANNELS_NUM];
180 if (!readSamples(rawValues))
186 for (
int j = 0; j < CHANNELS_NUM; j++)
187 averageValues[j] += rawValues[j];
192 if (realSampleCount == 0)
195 "Failed self test with positive DC signal, no valid samples");
201 for (
int i = 0; i < CHANNELS_NUM; i++)
204 averageValues[i] /= realSampleCount;
208 averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
211 if (volts < V_REF * TEST_SIGNAL_FACTOR - TEST_SIGNAL_SLACK)
215 "Self test failed on channel {} on positive test signal, "
222 averageValues[i] = 0;
227 for (
int i = 0; i < CHANNELS_NUM; i++)
228 setChannelInput(
static_cast<Channel>(i), Input::NEGATIVE_DC_TEST);
232 for (
int i = 0; i < SELF_TEST_SAMPLES; i++)
238 int32_t rawValues[CHANNELS_NUM];
239 if (!readSamples(rawValues))
245 for (
int j = 0; j < CHANNELS_NUM; j++)
246 averageValues[j] += rawValues[j];
251 if (realSampleCount == 0)
254 "Failed self test with positive DC signal, no valid samples");
260 for (
int i = 0; i < CHANNELS_NUM; i++)
263 averageValues[i] /= realSampleCount;
267 averageValues[i] * getLSBSizeFromGain(selfTestConfig.pga);
270 if (volts > -V_REF * TEST_SIGNAL_FACTOR + TEST_SIGNAL_SLACK)
274 "Self test failed on channel {} on negative test signal, "
283 for (
int i = 0; i < CHANNELS_NUM; i++)
284 setChannelInput(
static_cast<Channel>(i), Input::DEFAULT);
296 int32_t rawValues[CHANNELS_NUM];
297 if (!readSamples(rawValues))
306 for (
int i = 0; i < CHANNELS_NUM; i++)
315void ADS131M08::applyChannelConfig(
Channel channel,
316 Config::ChannelConfig config)
320 setChannelPGA(channel, config.pga);
321 setChannelOffset(channel, config.offset);
322 setChannelGain(channel, config.gain);
323 enableChannel(channel);
327 disableChannel(channel);
333 changeRegister(Register::REG_CLOCK,
static_cast<uint16_t
>(ratio),
337void ADS131M08::setChannelPGA(
Channel channel,
PGA gain)
339 if (channel <= Channel::CHANNEL_3)
341 int shift =
static_cast<int>(channel) * 4;
342 changeRegister(Register::REG_GAIN_1,
343 static_cast<uint16_t
>(gain) << shift,
348 int shift = (
static_cast<int>(channel) - 4) * 4;
349 changeRegister(Register::REG_GAIN_2,
350 static_cast<uint16_t
>(gain) << shift,
355void ADS131M08::setChannelOffset(
Channel channel, int32_t offset)
369 writeRegister(getChannelOffsetRegisterMSB(channel), offset >> 8);
370 writeRegister(getChannelOffsetRegisterLSB(channel), offset << 8);
373void ADS131M08::setChannelGain(
Channel channel,
double gain)
389 uint32_t rawGain = gain * (1 << 23);
403 writeRegister(getChannelGainRegisterMSB(channel), rawGain >> 8);
404 writeRegister(getChannelGainRegisterLSB(channel), rawGain << 8);
407void ADS131M08::enableChannel(
Channel channel)
409 changeRegister(Register::REG_CLOCK, 1 << (
static_cast<int>(channel) + 8),
410 1 << (
static_cast<int>(channel) + 8));
413void ADS131M08::disableChannel(
Channel channel)
415 changeRegister(Register::REG_CLOCK, 0,
416 1 << (
static_cast<int>(channel) + 8));
419void ADS131M08::enableGlobalChopMode()
425void ADS131M08::disableGlobalChopMode()
430void ADS131M08::setChannelInput(
Channel channel,
Input input)
432 Register reg = getChannelConfigRegister(channel);
438 switch (
static_cast<int>(channel))
441 return Register::REG_CH0_CFG;
443 return Register::REG_CH1_CFG;
445 return Register::REG_CH2_CFG;
447 return Register::REG_CH3_CFG;
449 return Register::REG_CH4_CFG;
451 return Register::REG_CH5_CFG;
453 return Register::REG_CH6_CFG;
455 return Register::REG_CH7_CFG;
461 switch (
static_cast<int>(channel))
464 return Register::REG_CH0_OCAL_MSB;
466 return Register::REG_CH1_OCAL_MSB;
468 return Register::REG_CH2_OCAL_MSB;
470 return Register::REG_CH3_OCAL_MSB;
472 return Register::REG_CH4_OCAL_MSB;
474 return Register::REG_CH5_OCAL_MSB;
476 return Register::REG_CH6_OCAL_MSB;
478 return Register::REG_CH7_OCAL_MSB;
484 switch (
static_cast<int>(channel))
487 return Register::REG_CH0_OCAL_LSB;
489 return Register::REG_CH1_OCAL_LSB;
491 return Register::REG_CH2_OCAL_LSB;
493 return Register::REG_CH3_OCAL_LSB;
495 return Register::REG_CH4_OCAL_LSB;
497 return Register::REG_CH5_OCAL_LSB;
499 return Register::REG_CH6_OCAL_LSB;
501 return Register::REG_CH7_OCAL_LSB;
507 switch (
static_cast<int>(channel))
510 return Register::REG_CH0_GCAL_MSB;
512 return Register::REG_CH1_GCAL_MSB;
514 return Register::REG_CH2_GCAL_MSB;
516 return Register::REG_CH3_GCAL_MSB;
518 return Register::REG_CH4_GCAL_MSB;
520 return Register::REG_CH5_GCAL_MSB;
522 return Register::REG_CH6_GCAL_MSB;
524 return Register::REG_CH7_GCAL_MSB;
530 switch (
static_cast<int>(channel))
533 return Register::REG_CH0_GCAL_LSB;
535 return Register::REG_CH1_GCAL_LSB;
537 return Register::REG_CH2_GCAL_LSB;
539 return Register::REG_CH3_GCAL_LSB;
541 return Register::REG_CH4_GCAL_LSB;
543 return Register::REG_CH5_GCAL_LSB;
545 return Register::REG_CH6_GCAL_LSB;
547 return Register::REG_CH7_GCAL_LSB;
551bool ADS131M08::readSamples(int32_t rawValues[CHANNELS_NUM])
554 uint8_t data[FULL_FRAME_SIZE] = {0};
556 data[0] = (
static_cast<uint16_t
>(Command::NULL_CMD) & 0xff00) >> 8;
557 data[1] = (
static_cast<uint16_t
>(Command::NULL_CMD) & 0x00ff);
560 transaction.transfer(data,
sizeof(data));
564 static_cast<uint16_t
>(data[27]) << 8 |
static_cast<uint16_t
>(data[28]);
567 if (dataCrc != calculatedCrc)
570 LOG_ERR(logger,
"Failed CRC check during sensor sampling");
577 for (
int i = 0; i < CHANNELS_NUM; i++)
579 rawValues[i] =
static_cast<uint32_t
>(data[i * 3 + 3]) << 16 |
580 static_cast<uint32_t
>(data[i * 3 + 4]) << 8 |
581 static_cast<uint32_t
>(data[i * 3 + 5]);
591uint16_t ADS131M08::readRegister(
Register reg)
593 uint8_t data[3] = {0};
596 data[0] =
static_cast<uint16_t
>(Command::RREG) >> 8 |
597 static_cast<uint16_t
>(reg) >> 1;
598 data[1] =
static_cast<uint16_t
>(reg) << 7;
601 transaction.write(data,
sizeof(data));
602 transaction.read(data,
sizeof(data));
604 return data[0] << 8 | data[1];
607void ADS131M08::writeRegister(
Register reg, uint16_t data)
611 uint8_t writeCommand[6] = {0};
614 writeCommand[0] =
static_cast<uint16_t
>(Command::WREG) >> 8 |
615 static_cast<uint16_t
>(reg) >> 1;
616 writeCommand[1] =
static_cast<uint16_t
>(reg) << 7;
617 writeCommand[3] = data >> 8;
618 writeCommand[4] = data;
621 transaction.write(writeCommand,
sizeof(writeCommand));
624 uint16_t response = transaction.read24() >> 8;
625 if (response != (WRITE_CMD_RESPONSE | (
static_cast<uint16_t
>(reg) << 7)))
628 LOG_ERR(logger,
"Write command failed, response was {:X}", response);
632void ADS131M08::changeRegister(
Register reg, uint16_t newValue, uint16_t mask)
635 uint16_t regValue = readRegister(reg);
641 regValue |= newValue;
644 writeRegister(reg, regValue);
648 uint8_t data[FULL_FRAME_SIZE])
655 data[0] = (
static_cast<uint16_t
>(command) & 0xff00) >> 8;
656 data[1] = (
static_cast<uint16_t
>(command) & 0x00ff);
658 transaction.
write(data, FULL_FRAME_SIZE);
661float ADS131M08::getLSBSizeFromGain(
PGA gain)
#define LOG_INFO(logger,...)
#define LOG_ERR(logger,...)
bool selfTest() override
The self test samples internally connects each channel to known test signals and verifies if the samp...
ADS131M08(SPIBusInterface &bus, miosix::GpioPin cs, SPIBusConfig spiConfig, const Config &config)
void applyConfig(Config config)
Overwrites the sensor settings.
bool init() override
Initialize the sensor.
void calibrateOffset(ADS131M08Defs::Channel channel)
Samples each channel, averages the samples and applies offset compensation in the device.
ADS131M08Data sampleImpl() override
Read a data sample from the sensor. In case of errors, the method should return the last available co...
Interface for low level access of a SPI bus as a master.
Provides high-level access to the SPI Bus for a single transaction.
void write(uint8_t data)
Writes a single byte to the bus.
virtual uint32_t read24()
Reads 24 bits from the bus.
constexpr uint16_t CFG_MUX
constexpr uint16_t PGA_GAIN_0
OversamplingRatio
ADC's oversampling ratio configurations.
constexpr float PGA_LSB_SIZE[8]
const auto crc16
CRC-16/CCITT-FALSE.
@ MODE_1
CPOL = 1, CPHA = 0 -> Clock high when idle, sample on first edge.
uint64_t getTimestamp()
Returns the current timer value in microseconds.
This file includes all the types the logdecoder script will decode.
ChannelConfig channelsConfig[ADS131M08Defs::CHANNELS_NUM]
ADS131M08Defs::OversamplingRatio oversamplingRatio
bool globalChopModeEnabled
SPI Bus configuration for a specific slave.
SPI::Mode mode
MSBit or LSBit first.