2021-05-26 06:02:17 -04:00
|
|
|
//
|
|
|
|
// FILE: AD5144A.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
2021-12-11 09:52:48 -05:00
|
|
|
// VERSION: 0.1.4
|
2021-05-26 06:02:17 -04:00
|
|
|
// PURPOSE: I2C digital potentiometer AD5144A
|
|
|
|
// DATE: 2021-04-30
|
|
|
|
// URL: https://github.com/RobTillaart/AD5144A
|
|
|
|
//
|
|
|
|
// HISTORY
|
|
|
|
// 0.1.0 2021-04-30 initial version
|
|
|
|
// 0.1.1 2021-05-12 add topScale() and bottomScale()
|
|
|
|
// 0.1.2 2021-05-12 add increment() and decrement() functions
|
2021-10-17 05:16:21 -04:00
|
|
|
// 0.1.3 2021-10-17 update build-ci, improve readme.md
|
2021-12-11 09:52:48 -05:00
|
|
|
// 0.1.4 2021-12-10 remove experimental from version string.
|
|
|
|
// add headers to library.json,
|
|
|
|
// minor edits readme, license,
|
|
|
|
// add check for maxValue in code.
|
2021-05-26 06:02:17 -04:00
|
|
|
|
|
|
|
|
|
|
|
#include "AD5144A.h"
|
|
|
|
|
|
|
|
|
|
|
|
// Commands page 29 datasheet
|
|
|
|
//
|
|
|
|
// not implemented (yet)
|
|
|
|
// 0 NOP
|
|
|
|
// 4 5 linear RDAC in/decrement
|
|
|
|
// 6 7 6dB RDAC in/decrement
|
2021-12-11 09:52:48 -05:00
|
|
|
// 12 13 top scale bottom scale ???
|
2021-05-26 06:02:17 -04:00
|
|
|
|
|
|
|
|
|
|
|
AD51XX::AD51XX(const uint8_t address, TwoWire *wire)
|
|
|
|
{
|
|
|
|
_address = address;
|
|
|
|
_wire = wire;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (ESP8266) || defined(ESP32)
|
|
|
|
bool AD51XX::begin(uint8_t dataPin, uint8_t clockPin)
|
|
|
|
{
|
|
|
|
_wire = &Wire;
|
|
|
|
if ((dataPin < 255) && (clockPin < 255))
|
|
|
|
{
|
|
|
|
_wire->begin(dataPin, clockPin);
|
|
|
|
} else {
|
|
|
|
_wire->begin();
|
|
|
|
}
|
|
|
|
if (! isConnected()) return false;
|
|
|
|
reset();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
bool AD51XX::begin()
|
|
|
|
{
|
|
|
|
_wire->begin();
|
|
|
|
if (! isConnected()) return false;
|
|
|
|
midScaleAll(); // is this what we want?
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool AD51XX::isConnected()
|
|
|
|
{
|
|
|
|
_wire->beginTransmission(_address);
|
|
|
|
return ( _wire->endTransmission() == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::reset()
|
|
|
|
{
|
|
|
|
// COMMAND 14 - page 29
|
|
|
|
return send(0xB0, 0x00); // to be tested
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::writeAll(const uint8_t value)
|
|
|
|
{
|
2021-12-11 09:52:48 -05:00
|
|
|
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
|
2021-05-26 06:02:17 -04:00
|
|
|
// COMMAND 1 - page 29
|
|
|
|
for (uint8_t pm = 0; pm < _potCount; pm++)
|
|
|
|
{
|
|
|
|
_lastValue[pm] = value;
|
|
|
|
}
|
|
|
|
uint8_t cmd = 0x18;
|
|
|
|
return send(cmd, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::write(const uint8_t rdac, const uint8_t value)
|
|
|
|
{
|
|
|
|
// COMMAND 1 - page 29
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
2021-12-11 09:52:48 -05:00
|
|
|
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
|
2021-05-26 06:02:17 -04:00
|
|
|
_lastValue[rdac] = value;
|
|
|
|
uint8_t cmd = 0x10 | rdac;
|
|
|
|
return send(cmd, _lastValue[rdac]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::storeEEPROM(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 9 - page 29
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x70 | rdac;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::recallEEPROM(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 10 - page 29
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
_lastValue[rdac] = readBackEEPROM(rdac);
|
|
|
|
uint8_t cmd = 0x70 | rdac;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::storeEEPROM(const uint8_t rdac, const uint8_t value)
|
|
|
|
{
|
|
|
|
// COMMAND 11 - page 29
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
2021-12-11 09:52:48 -05:00
|
|
|
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
|
2021-05-26 06:02:17 -04:00
|
|
|
uint8_t cmd = 0x80 | rdac;
|
|
|
|
return send(cmd, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
uint8_t AD51XX::setTopScale(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 12
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x90 | rdac;
|
|
|
|
return send(cmd, 0x81);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::clrTopScale(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 12
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x90 | rdac;
|
|
|
|
return send(cmd, 0x80);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::setTopScaleAll()
|
|
|
|
{
|
|
|
|
// COMMAND 12
|
|
|
|
uint8_t cmd = 0x98;
|
|
|
|
return send(cmd, 0x81);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::clrTopScaleAll()
|
|
|
|
{
|
|
|
|
// COMMAND 12
|
|
|
|
uint8_t cmd = 0x98;
|
|
|
|
return send(cmd, 0x80);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::setBottomScale(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 13
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x90 | rdac;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::clrBottomScale(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 13
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x90 | rdac;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::setBottomScaleAll()
|
|
|
|
{
|
|
|
|
// COMMAND 13
|
|
|
|
uint8_t cmd = 0x98;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::clrBottomScaleAll()
|
|
|
|
{
|
|
|
|
// COMMAND 13
|
|
|
|
uint8_t cmd = 0x98;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
uint8_t AD51XX::setLinearMode(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 3
|
|
|
|
uint8_t mask = readBack(rdac, 0x02);
|
|
|
|
// COMMAND 16 - page 29
|
|
|
|
uint8_t cmd = 0xD0;
|
|
|
|
return send(cmd, mask | 0x04);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::setPotentiometerMode(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 3
|
|
|
|
uint8_t mask = readBack(rdac, 0x02);
|
|
|
|
// COMMAND 16 - page 29
|
|
|
|
uint8_t cmd = 0xD0;
|
|
|
|
return send(cmd, mask & (~0x04));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::getOperationalMode(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
uint8_t mask = readBack(rdac, 0x02);
|
|
|
|
return ((mask & 0x04) > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::incrementLinear(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 4
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x40 | rdac;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::incrementLinearAll()
|
|
|
|
{
|
|
|
|
// COMMAND 4
|
|
|
|
uint8_t cmd = 0x48;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::decrementLineair(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 4
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x40 | rdac;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::decrementLineairAll()
|
|
|
|
{
|
|
|
|
// COMMAND 4
|
|
|
|
uint8_t cmd = 0x48;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::increment6dB(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 5
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x50 | rdac;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::increment6dBAll()
|
|
|
|
{
|
|
|
|
// COMMAND 5
|
|
|
|
uint8_t cmd = 0x58;
|
|
|
|
return send(cmd, 0x01);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::decrement6dB(const uint8_t rdac)
|
|
|
|
{
|
|
|
|
// COMMAND 5
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
|
|
|
uint8_t cmd = 0x50 | rdac;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::decrement6dBAll()
|
|
|
|
{
|
|
|
|
// COMMAND 5
|
|
|
|
uint8_t cmd = 0x58;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
uint8_t AD51XX::preload(const uint8_t rdac, const uint8_t value)
|
|
|
|
{
|
|
|
|
// COMMAND 2 - page 29
|
|
|
|
if (rdac >= _potCount) return AD51XXA_INVALID_POT;
|
2021-12-11 09:52:48 -05:00
|
|
|
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
|
2021-05-26 06:02:17 -04:00
|
|
|
_lastValue[rdac] = value;
|
|
|
|
uint8_t cmd = 0x20 | rdac;
|
|
|
|
return send(cmd, _lastValue[rdac]);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::preloadAll(const uint8_t value)
|
|
|
|
{
|
2021-12-11 09:52:48 -05:00
|
|
|
if (value > _maxValue) return AD51XXA_INVALID_VALUE;
|
2021-05-26 06:02:17 -04:00
|
|
|
// COMMAND 2 - page 29
|
|
|
|
uint8_t cmd = 0x28;
|
|
|
|
return send(cmd, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::sync(const uint8_t mask)
|
|
|
|
{
|
|
|
|
// COMMAND 8 - page 29
|
|
|
|
uint8_t cmd = 0x60 | mask;
|
|
|
|
return send(cmd, 0x00);
|
|
|
|
// keep cache correct.
|
|
|
|
uint8_t m = 0x01;
|
|
|
|
for (uint8_t rdac = 0; rdac < _potCount; rdac++)
|
|
|
|
{
|
|
|
|
if (mask & m)
|
|
|
|
{
|
|
|
|
_lastValue[rdac] = readBackRDAC(rdac);
|
|
|
|
m <<= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::shutDown()
|
|
|
|
{
|
|
|
|
// COMMAND 15 - table 29
|
|
|
|
return send(0xC8, 0x01); // to be tested
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::writeControlRegister(uint8_t mask)
|
|
|
|
{
|
|
|
|
// COMMAND 16 - page 29
|
|
|
|
uint8_t cmd = 0xD0;
|
|
|
|
return send(cmd, mask);
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// PRIVATE
|
|
|
|
//
|
2021-10-17 05:16:21 -04:00
|
|
|
//
|
|
|
|
// _wire->endTransmission
|
|
|
|
// returns description
|
|
|
|
// 0: success
|
|
|
|
// 1: data too long to fit in transmit buffer
|
|
|
|
// 2: received NACK on transmit of address
|
|
|
|
// 3: received NACK on transmit of data
|
|
|
|
// 4: other error
|
|
|
|
//
|
2021-05-26 06:02:17 -04:00
|
|
|
uint8_t AD51XX::send(const uint8_t cmd, const uint8_t value)
|
|
|
|
{
|
|
|
|
// COMMAND 1 - page 20
|
|
|
|
_wire->beginTransmission(_address); // returns nothing.
|
|
|
|
_wire->write(cmd); // returns bytes written
|
|
|
|
_wire->write(value); // returns bytes written
|
2021-10-17 05:16:21 -04:00
|
|
|
return _wire->endTransmission(); // returns status of actual write
|
2021-05-26 06:02:17 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t AD51XX::readBack(const uint8_t rdac, const uint8_t mask)
|
|
|
|
{
|
|
|
|
// COMMAND 3 - page 20
|
|
|
|
_wire->beginTransmission(_address);
|
|
|
|
int a = _wire->write(0x30 | rdac);
|
|
|
|
// Serial.print("READBACK cmd: ");
|
|
|
|
// Serial.print(a);
|
|
|
|
a = _wire->write(mask);
|
|
|
|
// Serial.print(" val: ");
|
|
|
|
// Serial.print(a);
|
|
|
|
a = _wire->endTransmission();
|
|
|
|
// Serial.print(" TX: ");
|
|
|
|
// Serial.println(a);
|
|
|
|
|
|
|
|
a = _wire->requestFrom(_address, (uint8_t)1);
|
|
|
|
Serial.print(" RF: ");
|
|
|
|
Serial.println(a);
|
|
|
|
return _wire->read();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
//////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// DERIVED CLASSES
|
|
|
|
//
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5123::AD5123(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 4;
|
|
|
|
_maxValue = 127;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5124::AD5124(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 4;
|
|
|
|
_maxValue = 127;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5143::AD5143(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 4;
|
|
|
|
_maxValue = 255;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5144::AD5144(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 4;
|
|
|
|
_maxValue = 255;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5144A::AD5144A(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 4;
|
|
|
|
_maxValue = 255;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5122A::AD5122A(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 2;
|
2021-12-11 09:52:48 -05:00
|
|
|
_maxValue = 127;
|
2021-05-26 06:02:17 -04:00
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5142A::AD5142A(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 2;
|
|
|
|
_maxValue = 255;
|
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5121::AD5121(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 1;
|
2021-12-11 09:52:48 -05:00
|
|
|
_maxValue = 127;
|
2021-05-26 06:02:17 -04:00
|
|
|
}
|
|
|
|
|
2021-10-17 05:16:21 -04:00
|
|
|
|
2021-05-26 06:02:17 -04:00
|
|
|
AD5141::AD5141(const uint8_t address, TwoWire *wire) : AD51XX(address, wire)
|
|
|
|
{
|
|
|
|
_potCount = 1;
|
|
|
|
_maxValue = 255;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -- END OF FILE --
|