GY-63_MS5611/libraries/MCP4725/MCP4725.cpp

239 lines
5.7 KiB
C++
Raw Normal View History

//
// FILE: MCP4725.cpp
// AUTHOR: Rob Tillaart
2020-11-27 05:20:37 -05:00
// PURPOSE: Arduino library for 12 bit I2C DAC - MCP4725
// VERSION: 0.2.2
// URL: https://github.com/RobTillaart/MCP4725
//
// HISTORY:
// 0.1.00 - 2013-11-24 initial version
// 0.1.01 - 2013-11-30 added readDAC() & writeDAC (registerwrite)
// 0.1.02 - 2013-12-01 added readEEPROM() & RDY()
// 0.1.03 - 2013-12-01 added powerDownMode code
// 0.1.04 - 2013-12-04 improved the generalCall code (still experimental)
// 0.1.05 - 2015-03-06 refactoring, stricter interfaces
// 0.1.6 - 2017-04-19 refactor + remove timeout - https://github.com/RobTillaart/Arduino/issues/63
2017-04-20 03:20:26 -04:00
// 0.1.7 - 2017-04-20 refactor the removed timeout (Thanks to Koepel)
2018-10-24 10:55:52 -04:00
// 0.1.8 - 2018-10-24 fix read only var #115 (kudos to perl1234)
// 0.1.9 - 2019-10-14 replace AVR specific TWBR with Wire.setClock() #131
2020-11-27 05:20:37 -05:00
// 0.2.0 2020-06-20 #pragma; remove pre 1.0 support; refactor a lot
// RDY() -> ready()
// 0.2.1 2020-07-04 Add yield(); add getLastWriteEEPROM();
// update readme.md + keywords.txt
// 0.2.2 2020-07-05 add get/setPercentage();
#include "MCP4725.h"
2020-11-27 05:20:37 -05:00
// registerMode
#define MCP4725_DAC 0x40
#define MCP4725_DACEEPROM 0x60
// page 22
#define MCP4725_GC_RESET 0x06
#define MCP4725_GC_WAKEUP 0x09
MCP4725::MCP4725(const uint8_t deviceAddress)
{
_deviceAddress = deviceAddress;
_lastValue = 0;
_powerDownMode = 0;
2020-11-27 05:20:37 -05:00
_lastWriteEEPROM = 0;
}
2020-11-27 05:20:37 -05:00
#if defined(ESP8266) || defined(ESP32)
void MCP4725::begin(const uint8_t dataPin, const uint8_t clockPin)
{
Wire.begin(dataPin, clockPin);
2020-11-27 05:20:37 -05:00
// Wire.setClock(100000UL);
_lastValue = readDAC();
_powerDownMode = readPowerDownModeDAC();
}
#endif
2020-11-27 05:20:37 -05:00
void MCP4725::begin()
{
Wire.begin();
2020-11-27 05:20:37 -05:00
// Wire.setClock(100000UL);
_lastValue = readDAC();
_powerDownMode = readPowerDownModeDAC();
}
2020-11-27 05:20:37 -05:00
int MCP4725::setValue(const uint16_t value)
{
if (value == _lastValue) return 0;
if (value > MCP4725_MAXVALUE) return MCP4725_VALUE_ERROR;
2020-11-27 05:20:37 -05:00
int rv = _writeFastMode(value);
if (rv == 0) _lastValue = value;
return rv;
}
2020-11-27 05:20:37 -05:00
uint16_t MCP4725::getValue()
{
return _lastValue;
}
// unfortunately it is not possible to write a different value
// to the DAC and EEPROM simultaneously or write EEPROM only.
int MCP4725::writeDAC(const uint16_t value, const bool EEPROM)
{
if (value > MCP4725_MAXVALUE) return MCP4725_VALUE_ERROR;
2020-11-27 05:20:37 -05:00
while(!ready());
int rv = _writeRegisterMode(value, EEPROM ? MCP4725_DACEEPROM : MCP4725_DAC);
if (rv == 0) _lastValue = value;
return rv;
}
2020-11-27 05:20:37 -05:00
uint16_t MCP4725::readDAC()
{
2020-11-27 05:20:37 -05:00
while(!ready());
uint8_t buffer[3];
2020-11-27 05:20:37 -05:00
_readRegister(buffer, 3);
uint16_t value = buffer[1];
value = value << 4;
value = value + (buffer[2] >> 4);
return value;
}
2020-11-27 05:20:37 -05:00
uint16_t MCP4725::readEEPROM()
{
2020-11-27 05:20:37 -05:00
while(!ready());
uint8_t buffer[5];
2020-11-27 05:20:37 -05:00
_readRegister(buffer, 5);
uint16_t value = buffer[3] & 0x0F;
value = value << 8;
value = value + buffer[4];
return value;
}
// depending on bool EEPROM the value of PDM is written to
// (false) DAC or
// (true) DAC & EEPROM,
int MCP4725::writePowerDownMode(const uint8_t PDM, const bool EEPROM)
{
2020-11-27 05:20:37 -05:00
_powerDownMode = (PDM & 0x03); // mask pdm bits only (written later low level)
return writeDAC(_lastValue, EEPROM);
}
2020-11-27 05:20:37 -05:00
uint8_t MCP4725::readPowerDownModeEEPROM()
{
2020-11-27 05:20:37 -05:00
while(!ready());
uint8_t buffer[4];
2020-11-27 05:20:37 -05:00
_readRegister(buffer, 4);
uint8_t value = (buffer[3] >> 5) & 0x03;
return value;
}
2020-11-27 05:20:37 -05:00
uint8_t MCP4725::readPowerDownModeDAC()
{
2020-11-27 05:20:37 -05:00
while(!ready()); // TODO needed?
uint8_t buffer[1];
2020-11-27 05:20:37 -05:00
_readRegister(buffer, 1);
uint8_t value = (buffer[0] >> 1) & 0x03;
return value;
}
2020-11-27 05:20:37 -05:00
// PAGE 22 - experimental
// DAC value is reset to EEPROM value
// need to reflect this in cached value
int MCP4725::powerOnReset()
{
2020-11-27 05:20:37 -05:00
int rv = _generalCall(MCP4725_GC_RESET);
_lastValue = readDAC(); // update cache to actual value;
return rv;
}
2020-11-27 05:20:37 -05:00
// PAGE 22 - experimental
// _powerDownMode DAC resets to 0 -- pdm EEPROM stays same !!!
// need to reflect this in cached value
int MCP4725::powerOnWakeUp()
{
2020-11-27 05:20:37 -05:00
int rv = _generalCall(MCP4725_GC_WAKEUP);
_powerDownMode = readPowerDownModeDAC(); // update to actual value;
return rv;
}
// PAGE 18 DATASHEET
2020-11-27 05:20:37 -05:00
int MCP4725::_writeFastMode(const uint16_t value)
{
Wire.beginTransmission(_deviceAddress);
uint8_t h = ((value / 256) & 0x0F); // set C0 = C1 = 0, no PDmode
h = h | (_powerDownMode << 4);
uint8_t l = value & 0xFF;
2020-11-27 05:20:37 -05:00
Wire.write(h);
Wire.write(l);
return Wire.endTransmission();
}
2020-11-27 05:20:37 -05:00
// ready checks if the last write to EEPROM has been written.
// until ready all writes to the MCP4725 are ignored!
bool MCP4725::ready()
{
2020-11-27 05:20:37 -05:00
yield();
uint8_t buffer[1];
2020-11-27 05:20:37 -05:00
_readRegister(buffer, 1);
return ((buffer[0] & 0x80) > 0);
}
2020-11-27 05:20:37 -05:00
// PAGE 19 DATASHEET
// reg = MCP4725_DAC | MCP4725_EEPROM
2020-11-27 05:20:37 -05:00
int MCP4725::_writeRegisterMode(const uint16_t value, uint8_t reg)
{
2020-11-27 05:20:37 -05:00
if (reg & MCP4725_DACEEPROM)
{
_lastWriteEEPROM = millis();
}
uint8_t h = (value / 16);
uint8_t l = (value & 0x0F) << 4;
Wire.beginTransmission(_deviceAddress);
reg = reg | (_powerDownMode << 1);
2020-11-27 05:20:37 -05:00
Wire.write(reg);
Wire.write(h);
Wire.write(l);
return Wire.endTransmission();
}
2020-11-27 05:20:37 -05:00
// PAGE 20 DATASHEET
// typical 3 or 5 bytes
2020-11-27 05:20:37 -05:00
uint8_t MCP4725::_readRegister(uint8_t* buffer, const uint8_t length)
{
Wire.beginTransmission(_deviceAddress);
int rv = Wire.endTransmission();
if (rv != 0) return 0; // error
// readbytes will always be equal or smaller to length
uint8_t readBytes = Wire.requestFrom(_deviceAddress, length);
uint8_t cnt = 0;
while (cnt < readBytes)
{
2020-11-27 05:20:37 -05:00
buffer[cnt++] = Wire.read();
}
return readBytes;
}
2020-11-27 05:20:37 -05:00
// name comes from datasheet
int MCP4725::_generalCall(const uint8_t gc)
{
Wire.beginTransmission(0);
2020-11-27 05:20:37 -05:00
Wire.write(gc);
return Wire.endTransmission();
}
2020-11-27 05:20:37 -05:00
// -- END OF FILE --