Adafruit_DACX578/Adafruit_DACX578.cpp
2025-02-14 17:06:24 -05:00

245 lines
7.8 KiB
C++

#include "Adafruit_DACX578.h"
/*!
* @brief Constructor for Adafruit_DACX578
* @param resolution The DAC resolution in bits (8, 10, or 12). Defaults to 8 if
* invalid.
*/
Adafruit_DACX578::Adafruit_DACX578(uint8_t resolution) {
if (resolution == 10 || resolution == 12) {
_resolution_bits = resolution;
} else {
_resolution_bits = 8; // Default to 8 bits if invalid resolution is provided
}
}
/*!
* @brief Destructor for Adafruit_DACX578
*/
Adafruit_DACX578::~Adafruit_DACX578() {
if (_i2c_dev) {
delete _i2c_dev;
_i2c_dev = nullptr;
}
}
/*!
* @brief Initializes the DAC7578 and checks if the device is connected.
* @param i2c_addr The I2C address of the DAC (default: 0x47).
* @param wire Pointer to the I2C bus instance (default: &Wire).
* @return True if initialization was successful, otherwise false.
*/
bool Adafruit_DACX578::begin(uint8_t i2c_addr, TwoWire *wire) {
if (_i2c_dev) {
delete _i2c_dev; // Clean up if already allocated
_i2c_dev = nullptr;
}
_i2c_addr = i2c_addr;
_wire = wire;
_i2c_dev = new Adafruit_I2CDevice(_i2c_addr, _wire);
if (!_i2c_dev->begin()) {
return false;
}
return true;
}
/*!
* @brief Resets the DAC using the software reset command.
* @return True if the command was successfully sent, otherwise false.
*/
bool Adafruit_DACX578::reset(void) {
uint8_t reset_cmd = DACX578_CMD_RESET;
return _i2c_dev->write(&reset_cmd, 1);
}
/*!
* @brief Writes a value to the input register of a specific DAC channel.
* @param channel The DAC channel to write to (0-7 or
* DACX578_CHANNEL_BROADCAST).
* @param value The 8/10/12-bit value to write to the DAC.
* @return True if the write was successful, otherwise false.
*/
bool Adafruit_DACX578::writeChannelValue(uint8_t channel, uint16_t value) {
if (channel > 7 && channel != DACX578_CHANNEL_BROADCAST) {
return false; // Invalid channel
}
return commandWrite(DACX578_CMD_WRITE | (channel & 0xF), value);
}
/*!
* @brief Updates the DAC output with the written register value from before.
* @param channel The DAC channel to update (0-7 or DACX578_CHANNEL_BROADCAST).
* @return True if the update was successful, otherwise false.
*/
bool Adafruit_DACX578::updateChannel(uint8_t channel) {
if (channel > 7 && channel != DACX578_CHANNEL_BROADCAST) {
return false; // Invalid channel
}
return commandWrite(DACX578_CMD_UPDATE | (channel & 0xF), 0x0);
}
/*!
* @brief Writes a value to the input register and updates the DAC output for a
* specific channel.
* @param channel The DAC channel to write and update (0-7 or
* DACX578_CHANNEL_BROADCAST).
* @param value The 8/10/12-bit value to write and update the DAC with.
* @return True if the operation was successful, otherwise false.
*/
bool Adafruit_DACX578::writeAndUpdateChannelValue(uint8_t channel,
uint16_t value) {
if (channel > 7 && channel != DACX578_CHANNEL_BROADCAST) {
return false; // Invalid channel
}
return commandWrite(DACX578_CMD_WRITE_UPDATE | (channel & 0xF), value);
}
/*!
* @brief Writes a value to the input register and performs a global update of
* all DAC outputs.
* @param channel The DAC channel to write to (0-7 or
* DACX578_CHANNEL_BROADCAST).
* @param value The 8/10/12-bit value to write before the global update.
* @return True if the operation was successful, otherwise false.
*/
bool Adafruit_DACX578::writeAndGlobalUpdateChannelValue(uint8_t channel,
uint16_t value) {
if (channel > 7 && channel != DACX578_CHANNEL_BROADCAST) {
return false; // Invalid channel
}
return commandWrite(DACX578_CMD_WRITE_GLOBAL_UPDATE | (channel & 0xF), value);
}
/*!
* @brief Reads the value from the input register of a specific DAC channel.
* @param channel The DAC channel to read from (0-7).
* @param value Pointer to store the read 8/10/12-bit value.
* @return True if the read was successful, otherwise false.
*/
bool Adafruit_DACX578::readInputChannelValue(uint8_t channel, uint16_t *value) {
if (channel > 7) {
return false; // Invalid channel
}
return commandRead(DACX578_CMD_WRITE | (channel & 0xF), value);
}
/*!
* @brief Reads the value from the DAC register (current output) of a specific
* DAC channel.
* @param channel The DAC channel to read from (0-7).
* @param value Pointer to store the read 8/10/12-bit value.
* @return True if the read was successful, otherwise false.
*/
bool Adafruit_DACX578::readChannelValue(uint8_t channel, uint16_t *value) {
if (channel > 7) {
return false; // Invalid channel
}
return commandRead(DACX578_CMD_UPDATE | (channel & 0xF), value);
}
/*!
* @brief Writes the LDAC mask to the DAC to control which channels respond to
* LDAC.
* @param ldac_mask The 8-bit LDAC mask, where each bit corresponds to a channel
* (0-7).
* @return True if the operation was successful, otherwise false.
*/
bool Adafruit_DACX578::writeLDAC(uint8_t ldac_mask) {
uint8_t buffer[3];
buffer[0] = DACX578_CMD_LDAC_MASK;
buffer[1] = ldac_mask;
buffer[2] = 0;
return _i2c_dev->write(buffer, 3);
}
/*!
* @brief Reads the current LDAC mask from the DAC.
* @return The 8-bit LDAC mask, where each bit corresponds to a channel (0-7).
*/
uint8_t Adafruit_DACX578::readLDAC(void) {
uint8_t buffer[2] = {0, 0};
uint8_t command = DACX578_CMD_LDAC_MASK;
if (!_i2c_dev->write_then_read(&command, 1, buffer, 2)) {
return 0;
}
return buffer[1];
}
/*!
* @brief Sets the clear code register to determine what value the DAC outputs
* on a clear event.
* @param clear_code The desired clear code (zero, midscale, full scale, or no
* operation).
* @return True if the operation was successful, otherwise false.
*/
bool Adafruit_DACX578::setClearCode(dacx578_clear_code_t clear_code) {
if (clear_code > DACX578_CLEAR_CODE_NOP) {
return false; // Invalid clear code
}
uint8_t buffer[3];
buffer[0] =
(DACX578_CMD_RESET); // Command byte (0x5 << 4 already pre-shifted)
buffer[1] = 0x00; // Upper 8 bits of DNC
buffer[2] = clear_code & 0x03; // Lower 2 bits of the clear code
return _i2c_dev->write(buffer, 3);
}
/*!
* @brief Reads the current clear code register value.
* @return The 2-bit clear code (zero, midscale, full scale, or no operation).
* Returns DACX578_CLEAR_CODE_NOP on failure.
*/
dacx578_clear_code_t Adafruit_DACX578::getClearCode(void) {
uint8_t cmd = DACX578_CMD_RESET; // Command byte to read clear code register
uint8_t buffer[3];
if (!_i2c_dev->write_then_read(&cmd, 1, buffer, 3)) {
return DACX578_CLEAR_CODE_NOP; // Return NOP on failure
}
return (dacx578_clear_code_t)(buffer[2] &
0x03); // Extract and return lower 2 bits
}
/*!
* @brief Writes a command and a 16-bit value to the DAC.
* @param command The command to write (pre-shifted upper nibble with channel
* info).
* @param value The 8/10/12-bit value to write, shifted based on the resolution.
* @return True if the write was successful, otherwise false.
*/
bool Adafruit_DACX578::commandWrite(uint8_t command, uint16_t value) {
uint8_t shift_amount = 16 - _resolution_bits;
value <<= shift_amount;
uint8_t buffer[3];
buffer[0] = command;
buffer[1] = (value >> 8) & 0xFF;
buffer[2] = value & 0xFF;
return _i2c_dev->write(buffer, 3);
}
/*!
* @brief Reads a 16-bit value from the DAC after issuing a command.
* @param command The command to send (pre-shifted upper nibble with channel
* info).
* @param value Pointer to store the read value, shifted down based on the
* resolution.
* @return True if the read was successful, otherwise false.
*/
bool Adafruit_DACX578::commandRead(uint8_t command, uint16_t *value) {
uint8_t buffer[2];
if (!_i2c_dev->write_then_read(&command, 1, buffer, 2)) {
return false;
}
*value = (((uint16_t)buffer[0] << 8) | (uint16_t)buffer[1]) >>
(16 - _resolution_bits);
return true;
}