2021-01-29 06:31:58 -05:00
|
|
|
//
|
|
|
|
// FILE: AD520X.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
|
|
|
// DATE: 2020-07-24
|
2024-05-23 14:06:36 -04:00
|
|
|
// VERSION: 0.5.1
|
2022-10-15 13:46:24 -04:00
|
|
|
// PURPOSE: Arduino library for AD5204 and AD5206 digital potentiometers
|
|
|
|
// (+ AD8400, AD8402, AD8403)
|
2021-01-29 06:31:58 -05:00
|
|
|
// URL: https://github.com/RobTillaart/AD520X
|
2023-01-10 14:37:57 -05:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
|
|
|
|
#include "AD520X.h"
|
|
|
|
|
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
// HARDWARE SPI
|
|
|
|
AD520X::AD520X(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 6;
|
|
|
|
_select = select;
|
|
|
|
_reset = reset;
|
|
|
|
_shutdown = shutdown;
|
|
|
|
_dataOut = 255;
|
|
|
|
_clock = 255;
|
|
|
|
_hwSPI = true;
|
|
|
|
_mySPI = mySPI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// SOFTWARE SPI
|
2021-01-29 06:31:58 -05:00
|
|
|
AD520X::AD520X(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
{
|
|
|
|
_pmCount = 6;
|
|
|
|
_select = select;
|
|
|
|
_reset = reset;
|
|
|
|
_shutdown = shutdown;
|
2023-11-26 11:07:23 -05:00
|
|
|
_dataOut = dataOut;
|
|
|
|
_clock = clock;
|
|
|
|
_hwSPI = false;
|
|
|
|
_mySPI = NULL;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2021-10-16 14:58:54 -04:00
|
|
|
// initializes the pins and starts SPI in case of hardware SPI
|
2021-01-29 06:31:58 -05:00
|
|
|
void AD520X::begin(uint8_t value)
|
|
|
|
{
|
|
|
|
pinMode(_select, OUTPUT);
|
|
|
|
digitalWrite(_select, HIGH);
|
|
|
|
pinMode(_reset, OUTPUT);
|
2022-10-15 13:46:24 -04:00
|
|
|
digitalWrite(_reset, HIGH);
|
2021-01-29 06:31:58 -05:00
|
|
|
pinMode(_shutdown, OUTPUT);
|
2022-10-15 13:46:24 -04:00
|
|
|
digitalWrite(_shutdown, HIGH);
|
2021-01-29 06:31:58 -05:00
|
|
|
|
2022-10-15 13:46:24 -04:00
|
|
|
_spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0);
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
if(_hwSPI)
|
|
|
|
{
|
2024-01-19 07:42:51 -05:00
|
|
|
// _mySPI->end();
|
|
|
|
// _mySPI->begin();
|
|
|
|
// delay(1);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-08-22 04:47:15 -04:00
|
|
|
pinMode(_dataOut, OUTPUT);
|
|
|
|
pinMode(_clock, OUTPUT);
|
|
|
|
digitalWrite(_dataOut, LOW);
|
|
|
|
digitalWrite(_clock, LOW);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
reset(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AD520X::reset(uint8_t value)
|
|
|
|
{
|
|
|
|
digitalWrite(_reset, LOW);
|
|
|
|
digitalWrite(_reset, HIGH);
|
2021-01-29 06:31:58 -05:00
|
|
|
setAll(value);
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// SET VALUE
|
|
|
|
//
|
2021-10-16 14:58:54 -04:00
|
|
|
bool AD520X::setValue(uint8_t pm, uint8_t value)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2021-10-16 14:58:54 -04:00
|
|
|
if (pm >= _pmCount) return false;
|
2021-01-29 06:31:58 -05:00
|
|
|
_value[pm] = value;
|
2022-09-19 04:24:53 -04:00
|
|
|
updateDevice(pm, value);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
|
|
|
|
uint8_t AD520X::getValue(uint8_t pm)
|
|
|
|
{
|
|
|
|
if (pm >= _pmCount) return 0;
|
|
|
|
return _value[pm];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-19 04:24:53 -04:00
|
|
|
// STEREO same value
|
|
|
|
bool AD520X::setValue(uint8_t pmA, uint8_t pmB, uint8_t value)
|
|
|
|
{
|
|
|
|
if ((pmA >= _pmCount) || (pmB >= _pmCount)) return false;
|
|
|
|
_value[pmA] = value;
|
|
|
|
updateDevice(pmA, value);
|
|
|
|
_value[pmB] = value;
|
|
|
|
updateDevice(pmB, value);
|
2021-10-16 14:58:54 -04:00
|
|
|
return true;
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
void AD520X::setAll(uint8_t value)
|
|
|
|
{
|
2022-09-19 04:24:53 -04:00
|
|
|
for (uint8_t pm = 0; pm < _pmCount; pm++ )
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2022-09-19 04:24:53 -04:00
|
|
|
_value[pm] = value;
|
|
|
|
updateDevice(pm, value);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
void AD520X::setGroupValue(uint8_t mask, uint8_t value)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2023-01-10 14:37:57 -05:00
|
|
|
uint8_t m = 0x01;
|
|
|
|
for (uint8_t pm = 0; pm < _pmCount; pm++ )
|
|
|
|
{
|
|
|
|
if (mask & m)
|
|
|
|
{
|
|
|
|
_value[pm] = value;
|
|
|
|
updateDevice(pm, value);
|
|
|
|
}
|
|
|
|
m <<= 1;
|
|
|
|
}
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// SET PERCENTAGE
|
|
|
|
//
|
2021-10-16 14:58:54 -04:00
|
|
|
bool AD520X::setPercentage(uint8_t pm, float percentage)
|
|
|
|
{
|
|
|
|
if ((percentage < 0) || (percentage > 100.0)) return false;
|
|
|
|
return setValue(pm, round(percentage * (255.0 / 100.0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
float AD520X::getPercentage(uint8_t pm)
|
|
|
|
{
|
|
|
|
if (pm >= _pmCount) return 0;
|
|
|
|
uint8_t v = _value[pm];
|
|
|
|
if (v == 0) return 0.0;
|
|
|
|
return (100.0 / 255.0) * v;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-19 04:24:53 -04:00
|
|
|
// STEREO same percentage
|
|
|
|
bool AD520X::setPercentage(uint8_t pmA, uint8_t pmB, float percentage)
|
|
|
|
{
|
|
|
|
if ((percentage < 0) || (percentage > 100.0)) return false;
|
|
|
|
return setValue(pmA, pmB, round(percentage * (255.0 / 100.0)));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
void AD520X::setGroupPercentage(uint8_t mask, float percentage)
|
2021-10-16 14:58:54 -04:00
|
|
|
{
|
2023-01-10 14:37:57 -05:00
|
|
|
uint8_t m = 0x01;
|
|
|
|
for (uint8_t pm = 0; pm < _pmCount; pm++ )
|
|
|
|
{
|
|
|
|
if (mask & m)
|
|
|
|
{
|
|
|
|
setValue(pm, round(percentage * (255.0 / 100.0)));
|
|
|
|
}
|
|
|
|
m <<= 1;
|
|
|
|
}
|
2021-10-16 14:58:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// OTHER
|
|
|
|
//
|
|
|
|
uint8_t AD520X::pmCount()
|
|
|
|
{
|
|
|
|
return _pmCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AD520X::powerOn()
|
|
|
|
{
|
|
|
|
digitalWrite(_shutdown, HIGH);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AD520X::powerOff()
|
|
|
|
{
|
|
|
|
digitalWrite(_shutdown, LOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool AD520X::isPowerOn()
|
|
|
|
{
|
|
|
|
return digitalRead(_shutdown) == HIGH;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// SPI
|
|
|
|
//
|
2021-08-22 04:47:15 -04:00
|
|
|
void AD520X::setSPIspeed(uint32_t speed)
|
|
|
|
{
|
|
|
|
_SPIspeed = speed;
|
2022-10-15 13:46:24 -04:00
|
|
|
_spi_settings = SPISettings(_SPIspeed, MSBFIRST, SPI_MODE0);
|
2021-08-22 04:47:15 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-01-10 14:37:57 -05:00
|
|
|
uint32_t AD520X::getSPIspeed()
|
|
|
|
{
|
|
|
|
return _SPIspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool AD520X::usesHWSPI()
|
|
|
|
{
|
|
|
|
return _hwSPI;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2023-01-10 14:37:57 -05:00
|
|
|
// PROTECTED
|
2021-08-22 04:47:15 -04:00
|
|
|
//
|
2022-09-19 04:24:53 -04:00
|
|
|
void AD520X::updateDevice(uint8_t pm, uint8_t value)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2021-08-22 04:47:15 -04:00
|
|
|
digitalWrite(_select, LOW);
|
2021-01-29 06:31:58 -05:00
|
|
|
if (_hwSPI)
|
|
|
|
{
|
2023-11-26 11:07:23 -05:00
|
|
|
_mySPI->beginTransaction(_spi_settings);
|
|
|
|
_mySPI->transfer(pm);
|
|
|
|
_mySPI->transfer(value);
|
|
|
|
_mySPI->endTransaction();
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
2021-10-16 14:58:54 -04:00
|
|
|
else // Software SPI
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
|
|
|
swSPI_transfer(pm);
|
2022-09-19 04:24:53 -04:00
|
|
|
swSPI_transfer(value);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
2021-08-22 04:47:15 -04:00
|
|
|
digitalWrite(_select, HIGH);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2021-10-16 14:58:54 -04:00
|
|
|
// simple one mode version
|
2021-08-22 04:47:15 -04:00
|
|
|
void AD520X::swSPI_transfer(uint8_t val)
|
2021-01-29 06:31:58 -05:00
|
|
|
{
|
2021-08-22 04:47:15 -04:00
|
|
|
uint8_t clk = _clock;
|
|
|
|
uint8_t dao = _dataOut;
|
2021-01-29 06:31:58 -05:00
|
|
|
for (uint8_t mask = 0x80; mask; mask >>= 1)
|
|
|
|
{
|
2021-08-22 04:47:15 -04:00
|
|
|
digitalWrite(dao,(val & mask));
|
|
|
|
digitalWrite(clk, HIGH);
|
|
|
|
digitalWrite(clk, LOW);
|
2021-01-29 06:31:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
2021-08-22 04:47:15 -04:00
|
|
|
//
|
2021-10-16 14:58:54 -04:00
|
|
|
// DERIVED CLASSES
|
2021-08-22 04:47:15 -04:00
|
|
|
//
|
2023-11-26 11:07:23 -05:00
|
|
|
AD5206::AD5206(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
: AD520X(select, reset, shutdown, mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
AD5206::AD5206(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
: AD520X(select, reset, shutdown, dataOut, clock)
|
|
|
|
{
|
|
|
|
_pmCount = 6;
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
AD5204::AD5204(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
: AD520X(select, reset, shutdown, mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
AD5204::AD5204(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
: AD520X(select, reset, shutdown, dataOut, clock)
|
|
|
|
{
|
|
|
|
_pmCount = 4;
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
AD8403::AD8403(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
: AD520X(select, reset, shutdown, mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
AD8403::AD8403(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
: AD520X(select, reset, shutdown, dataOut, clock)
|
|
|
|
{
|
|
|
|
_pmCount = 4;
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
AD8402::AD8402(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
: AD520X(select, reset, shutdown, mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
AD8402::AD8402(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
: AD520X(select, reset, shutdown, dataOut, clock)
|
|
|
|
{
|
|
|
|
_pmCount = 2;
|
|
|
|
}
|
|
|
|
|
2021-08-22 04:47:15 -04:00
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
AD8400::AD8400(uint8_t select, uint8_t reset, uint8_t shutdown, __SPI_CLASS__ * mySPI)
|
|
|
|
: AD520X(select, reset, shutdown, mySPI)
|
|
|
|
{
|
|
|
|
_pmCount = 1;
|
|
|
|
}
|
|
|
|
|
2021-01-29 06:31:58 -05:00
|
|
|
AD8400::AD8400(uint8_t select, uint8_t reset, uint8_t shutdown, uint8_t dataOut, uint8_t clock)
|
|
|
|
: AD520X(select, reset, shutdown, dataOut, clock)
|
|
|
|
{
|
|
|
|
_pmCount = 1;
|
|
|
|
}
|
|
|
|
|
2023-11-26 11:07:23 -05:00
|
|
|
|
|
|
|
// -- END OF FILE --
|
|
|
|
|