Skip to content

Commit

Permalink
[driver] ADC ADS816X
Browse files Browse the repository at this point in the history
  • Loading branch information
rleh committed Dec 21, 2021
1 parent 5a9ad25 commit c1b1dd0
Show file tree
Hide file tree
Showing 4 changed files with 310 additions and 12 deletions.
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,86 +593,87 @@ you specific needs.
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ad7928">AD7928</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-adns9800">ADNS9800</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ads7843">ADS7843</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ads816x">ADS816X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ams5915">AMS5915</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-apa102">APA102</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-apa102">APA102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-block-device-spi-flash">SPI-FLASH</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bme280">BME280</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bmp085">BMP085</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-bno055">BNO055</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-cat24aa">CAT24AA</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-drv832x_spi">DRV832X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1302">DS1302</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds1631">DS1631</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ds18b20">DS18B20</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ea_dog">EA-DOG</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input">ENCODER-INPUT</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input-bitbang">ENCODER-INPUT-BITBANG</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_input-bitbang">ENCODER-INPUT-BITBANG</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-encoder_output-bitbang">ENCODER-OUTPUT-BITBANG</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft245">FT245</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ft6x06">FT6X06</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-gpio_sampler">GPIO-SAMPLER</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hclax">HCLAx</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hd44780">HD44780</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hd44780">HD44780</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc58x">HMC58x</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hmc6343">HMC6343</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-hx711">HX711</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-i2c-eeprom">I2C-EEPROM</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ili9341">ILI9341</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-is31fl3733">IS31FL3733</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-is31fl3733">IS31FL3733</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-itg3200">ITG3200</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-l3gd20">L3GD20</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lan8720a">LAN8720A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lawicel">LAWICEL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis302dl">LIS302DL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3dsh">LIS3DSH</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3dsh">LIS3DSH</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lis3mdl">LIS3MDL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lm75">LM75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lp503x">LP503X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm303a">LSM303A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-lsm6ds33">LSM6DS33</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ltc2984">LTC2984</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ltc2984">LTC2984</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max6966">MAX6966</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-max7219">MAX7219</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp23x17">MCP23X17</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp2515">MCP2515</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mcp7941x">MCP7941X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mmc5603">MMC5603</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-mmc5603">MMC5603</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nokia5110">NOKIA5110</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-nrf24">NRF24</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-parallel_tft_display">TFT-DISPLAY</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pat9125el">PAT9125EL</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca8574">PCA8574</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9535">PCA9535</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9535">PCA9535</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9548a">PCA9548A</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-pca9685">PCA9685</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sh1106">SH1106</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s65">SIEMENS-S65</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-siemens_s75">SIEMENS-S75</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk6812">SK6812</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sk9822">SK9822</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-ssd1306">SSD1306</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-st7586s">ST7586S</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stts22h">STTS22H</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-stusb4500">STUSB4500</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-sx1276">SX1276</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3414">TCS3414</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tcs3472">TCS3472</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tlc594x">TLC594X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp102">TMP102</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp12x">TMP12X</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-tmp175">TMP175</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-touch2046">TOUCH2046</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl53l0">VL53L0</a></td>
<td align="center"><a href="https://modm.io/reference/module/modm-driver-vl6180">VL6180</a></td>
Expand Down
123 changes: 123 additions & 0 deletions src/modm/driver/adc/ads816x.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// coding: utf-8
// ----------------------------------------------------------------------------
/*
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_ADS816X_HPP
#define MODM_ADS816X_HPP

#include <array>
#include <modm/architecture/interface/spi_device.hpp>
#include <modm/architecture/interface/gpio.hpp>
#include <modm/processing/resumable.hpp>
#include <modm/processing/timer/timeout.hpp>

namespace modm
{

/// @ingroup modm_driver_ads816x
struct ads816x
{
enum class
Register : uint16_t
{
REG_ACCESS = 0x000,
PD_CNTL = 0x004,
SDI_CNTL = 0x008,
SDO_CNTL1 = 0x00C,
SDO_CNTL2 = 0x00D,
SDO_CNTL3 = 0x00E,
SDO_CNTL4 = 0x00F,
DATA_CNTL = 0x010,
PARITY_CNTL = 0x011,

OFST_CAL = 0x018,
REF_MRG1 = 0x019,
REF_MRG2 = 0x01A,
REFby2_MRG = 0x01B,

AIN_CFG = 0x024,
COM_CFG = 0x027,

DEVICE_CFG = 0x01C,
CHANNEL_ID = 0x01D,
SEQ_START = 0x01E,
SEQ_STOP = 0x01F,
ON_THE_FLY_CFG = 0x02A,
AUTO_SEQ_CFG1 = 0x080,
AUTO_SEQ_CFG2 = 0x082,

// Alert, etc...
};

enum class
Command : uint8_t
{
NoOperation = 0b00000 << 3,
Write = 0b00001 << 3,
Read = 0b00010 << 3,
SetBits = 0b00011 << 3,
ClearBits = 0b00100 << 3,
};

enum class
Mode : uint8_t
{
Manual = 0b00,
OnTheFly = 0b01,
AutoSequence = 0b10,
CustomSequence = 0b11,
};
};

/**
* @tparam SpiMaster SpiMaster interface
* @tparam Cs Chip-select pin
*
* @author Raphael Lehmann
* @ingroup modm_driver_ads816x
*/
template <typename SpiMaster, typename Cs>
class Ads816x : public ads816x, public modm::SpiDevice<SpiMaster>, protected modm::NestedResumable<3>
{
public:
Ads816x() = default;

/// Call this function before using the device or to change operation mode
modm::ResumableResult<void>
initialize(Mode mode);

/// Initiate a single conversion and return the result of the conversion
/// Simultanously the channel for the next conversion will be set
modm::ResumableResult<uint16_t>
manualModeConversion(uint8_t nextChannel);

/// Start a "auto sequence" conversion.
/// The device will automatically cycle through the specified channels in
/// the bitmask.
modm::ResumableResult<void>
autoSequenceConversion(uint8_t channelsBitmask, std::array<uint16_t, 8>& result);

private:
modm::ResumableResult<uint8_t>
registerAccess(Command command, Register reg, uint8_t value = 0);

uint8_t buffer[3];
uint8_t buffer2[3];

modm::ShortPreciseTimeout timeout;
};

} // namespace modm

#include "ads816x_impl.hpp"

#endif // MODM_ADS816X_HPP
41 changes: 41 additions & 0 deletions src/modm/driver/adc/ads816x.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021, Raphael Lehmann
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------


def init(module):
module.name = ":driver:ads816x"
module.description = """\
# ADS816x ADC
The ADS8166/ADS8167/ADS8168 are, 16 bit analog-digital converters with, sample
rates of 1 MSPS (ADS8168), 500 kSPS (ADS8167), and 250 kSPS (ADS8166).
The conversion time is determined by the chip select signal.
A maximum Spi clock of 70 MHz is supported.
This driver only implements the _manual mode_ and _auto sequence mode_ using
the SPI interface.
"""


def prepare(module, options):
module.depends(
":architecture:gpio",
":architecture:spi.device",
":io",
":processing:resumable",
":processing:timer")
return True

def build(env):
env.outbasepath = "modm/src/modm/driver/adc"
env.copy("ads816x.hpp")
env.copy("ads816x_impl.hpp")
133 changes: 133 additions & 0 deletions src/modm/driver/adc/ads816x_impl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// coding: utf-8
// ----------------------------------------------------------------------------
/*
* Copyright (c) 2021, Raphael Lehmann
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_ADS816X_HPP
# error "Don't include this file directly! Use 'ads816x.hpp' instead."
#endif

#include <bit>

namespace modm
{

template <typename SpiMaster, typename Cs>
ResumableResult<void>
Ads816x<SpiMaster, Cs>::initialize(Mode mode)
{
RF_BEGIN();

// Unlock register access
RF_CALL(registerAccess(Command::Write, Register::REG_ACCESS, 0b1010'1010));

timeout.restart(4us);
RF_WAIT_UNTIL(timeout.isExpired());

// Set mode
RF_CALL(registerAccess(Command::Write, Register::DEVICE_CFG, uint8_t(mode)));

RF_END();
}

template <typename SpiMaster, typename Cs>
ResumableResult<uint16_t>
Ads816x<SpiMaster, Cs>::manualModeConversion(uint8_t nextChannel)
{
RF_BEGIN();

RF_WAIT_UNTIL(this->acquireMaster());
Cs::reset();

buffer[0] = uint8_t(Command::Write) | (uint16_t(Register::CHANNEL_ID) >> 8);
buffer[1] = uint16_t(Register::CHANNEL_ID);
buffer[2] = (nextChannel & 0b0000'0111);

RF_CALL(SpiMaster::transfer(buffer, buffer2, 3));

if (this->releaseMaster()) {
Cs::set();
}

RF_END_RETURN( static_cast<uint16_t>((static_cast<uint16_t>(buffer2[0]) << 8) | buffer2[1]) );
}

template <typename SpiMaster, typename Cs>
ResumableResult<void>
Ads816x<SpiMaster, Cs>::autoSequenceConversion(uint8_t channelsBitmask, std::array<uint16_t, 8>& result)
{
using namespace std::chrono_literals;
RF_BEGIN();

// Write channel bitmask config (AUTO_SEQ_CH)
RF_CALL(registerAccess(Command::Write, Register::AUTO_SEQ_CFG1, channelsBitmask));

timeout.restart(4us);
RF_WAIT_UNTIL(timeout.isExpired());

// Set SEQ_START (0b1 << 0) bit
RF_CALL(registerAccess(Command::SetBits, Register::SEQ_START, 0b1));

// Read conversion results
for (buffer2[0] = 0; buffer2[0] < std::popcount(channelsBitmask); buffer2[0]++) {
timeout.restart(4us);
RF_WAIT_UNTIL(timeout.isExpired());

RF_WAIT_UNTIL(this->acquireMaster());
Cs::reset();

RF_CALL(SpiMaster::transfer(nullptr, buffer, 2));

if (this->releaseMaster()) {
Cs::set();
}

result[buffer2[0]] = buffer[0] << 8 | buffer[1];
}

RF_END();
}

template <typename SpiMaster, typename Cs>
modm::ResumableResult<uint8_t>
Ads816x<SpiMaster, Cs>::registerAccess(Command command, Register reg, uint8_t value)
{
using namespace std::chrono_literals;
RF_BEGIN();

buffer[0] = uint8_t(command) | (uint16_t(reg) >> 8);
buffer[1] = uint16_t(reg);
buffer[2] = value;

RF_WAIT_UNTIL(this->acquireMaster());
Cs::reset();

RF_CALL(SpiMaster::transfer(buffer, nullptr, 3));

if (command == Command::Read) {
Cs::set();
timeout.restart(4us);
RF_WAIT_UNTIL(timeout.isExpired());

// To retrieve the result of the read command we issue another 3 byte
// transfer, nullptr instead of manual NoOperation (= 0b000...) command
Cs::reset();
RF_CALL(SpiMaster::transfer(nullptr, buffer, 3));
}

if (this->releaseMaster()) {
Cs::set();
}

RF_END_RETURN(buffer[0]);
}

} // namespace modm

0 comments on commit c1b1dd0

Please sign in to comment.