Kevin Santo Cappuccio 009eeced7a sonofabitch
2025-05-29 20:36:34 -07:00

183 lines
5.3 KiB
C++

/*!
* @file Adafruit_MCP4728.cpp
*
* @mainpage Adafruit MCP4728 4-Channel 12-Bit I2C DAC library
*
* @section intro_sec Introduction
*
* I2C Driver for the Adafruit MCP4728 4-Channel 12-Bit I2C DAC library
*
* This is a library for the Adafruit MCP4728 breakout:
* https://www.adafruit.com/product/4470
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
* @section dependencies Dependencies
* This library depends on the Adafruit BusIO library
*
*
* @section author Author
*
* Bryan Siepert for Adafruit Industries
*
* @section license License
*
* BSD (see license.txt)
*
* @section HISTORY
*
* v1.0 - First release
*/
#include "Adafruit_MCP4728.h"
#include "Arduino.h"
#include <Wire.h>
/*!
* @brief Instantiates a new MCP4728 class
*/
Adafruit_MCP4728::Adafruit_MCP4728(void) {}
/*!
* @brief Sets up the hardware and initializes I2C
* @param i2c_address
* The I2C address to be used.
* @param wire
* The Wire object to be used for I2C connections.
* @return True if initialization was successful, otherwise false.
*/
boolean Adafruit_MCP4728::begin(uint8_t i2c_address, TwoWire *wire) {
i2c_dev = new Adafruit_I2CDevice(i2c_address, wire);
if (!i2c_dev->begin()) {
return false;
}
return true;
}
/**
* @brief Sets the input register for a given channel to the specified settings
*
* @param channel The channel to update
* @param new_value The new value to assign
* @param new_vref Optional vref setting - Defaults to `MCP4728_VREF_VDD`
* @param new_gain Optional gain setting - Defaults to `MCP4728_GAIN_1X`
* @param new_pd_mode Optional power down mode setting - Defaults to
* `MCP4728_PD_MOOE_NORMAL`
* @param udac Optional UDAC setting - Defaults to `false`, latching
* immediately. Set to `true` to latch when the LDAC pin is pulled low
*
* @return true if the write was successful
* @return false if there was an error with I2C communication between the MCU
* and the DAC
*/
bool Adafruit_MCP4728::setChannelValue(
MCP4728_channel_t channel, uint16_t new_value, MCP4728_vref_t new_vref,
MCP4728_gain_t new_gain, MCP4728_pd_mode_t new_pd_mode, bool udac) {
uint8_t output_buffer[3];
// build the setter header/ "address"
// 0 1 0 0 0 DAC1 DAC0 UDAC[A]
uint8_t sequential_write_cmd = MCP4728_MULTI_IR_CMD;
sequential_write_cmd |= (channel << 1);
sequential_write_cmd |= udac;
output_buffer[0] = sequential_write_cmd;
// VREF PD1 PD0 Gx D11 D10 D9 D8 [A] D7 D6 D5 D4 D3 D2 D1 D0 [A]
new_value |= (new_vref << 15);
new_value |= (new_pd_mode << 13);
new_value |= (new_gain << 12);
output_buffer[1] = new_value >> 8;
output_buffer[2] = new_value & 0xFF;
if (!i2c_dev->write(output_buffer, 3)) {
return false;
}
return true;
}
/**
* @brief Set the values of all four channels simultaneously with minimal delay
* or configuration
*
* @param channel_a_value The value to assign to channel A
* @param channel_b_value The value to assign to channel B
* @param channel_c_value The value to assign to channel C
* @param channel_d_value The value to assign to channel D
* @return true if the write was successful
* @return false if there was an error with I2C communication between the MCU
* and the DAC
*/
bool Adafruit_MCP4728::fastWrite(uint16_t channel_a_value,
uint16_t channel_b_value,
uint16_t channel_c_value,
uint16_t channel_d_value) {
uint8_t output_buffer[8];
output_buffer[0] = channel_a_value >> 8;
output_buffer[1] = channel_a_value & 0xFF;
output_buffer[2] = channel_b_value >> 8;
output_buffer[3] = channel_b_value & 0xFF;
output_buffer[4] = channel_c_value >> 8;
output_buffer[5] = channel_c_value & 0xFF;
output_buffer[6] = channel_d_value >> 8;
output_buffer[7] = channel_d_value & 0xFF;
if (!i2c_dev->write(output_buffer, 8)) {
return false;
}
return true;
}
/**
* @brief Saves the DAC's input register settings to the internal EEPROM,
* makeing them the default values when the ADC is powered on
*
* @return true if the write was successful
* @return false if there was an error with I2C communication between the MCU
* and the DAC */
bool Adafruit_MCP4728::saveToEEPROM(void) {
uint8_t input_buffer[24];
uint8_t output_buffer[9];
i2c_dev->read(input_buffer, 24);
// build header byte 0 1 0 1 0 DAC1 DAC0 UDAC [A]
uint8_t eeprom_write_cmd = MCP4728_MULTI_EEPROM_CMD; // 0 1 0 1 0 xxx
eeprom_write_cmd |=
(MCP4728_CHANNEL_A << 1); // DAC1 DAC0, start at channel A obvs
eeprom_write_cmd |= 0; // UDAC ; yes, latch please
// First byte is the write command+options
output_buffer[0] = eeprom_write_cmd;
// copy the incoming input register bytes to the outgoing buffer
// Channel A
output_buffer[1] = input_buffer[1];
output_buffer[2] = input_buffer[2];
// Channel B
output_buffer[3] = input_buffer[7];
output_buffer[4] = input_buffer[8];
// Channel C
output_buffer[5] = input_buffer[13];
output_buffer[6] = input_buffer[14];
// Channel D
output_buffer[7] = input_buffer[19];
output_buffer[8] = input_buffer[20];
if (!i2c_dev->write(output_buffer, 9)) {
return false;
}
delay(15);
return true;
}