GY-63_MS5611/libraries/PCA9551/PCA9551.cpp
2024-01-05 15:57:22 +01:00

235 lines
4.0 KiB
C++

//
// FILE: PCA9551.cpp
// AUTHOR: Rob Tillaart
// DATE: 2023-07-17
// VERSION: 0.3.1
// PURPOSE: Arduino library for for I2C PCA9551 8 channel PWM
// URL: https://github.com/RobTillaart/PCA9551
#include "PCA9551.h"
//////////////////////////////////////////////////////////////
//
// Constructor
//
PCA9551::PCA9551(const uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_outputCount = 8;
_error = PCA9551_OK;
}
bool PCA9551::begin()
{
if (! isConnected()) return false;
return true;
}
bool PCA9551::isConnected()
{
_wire->beginTransmission(_address);
_error = _wire->endTransmission();
return (_error == 0);
}
uint8_t PCA9551::reset()
{
// not most efficient
setPrescaler(0, 0); // 44 Hz
setPrescaler(1, 0); // 44 Hz
setPWM(0, 128); // 50%
setPWM(1, 128); // 50%
for (int pin = 0; pin < _outputCount; pin++)
{
setOutputMode(pin, 0); // LOW
}
return PCA9551_OK;
}
uint8_t PCA9551::getAddress()
{
return _address;
}
uint8_t PCA9551::outputCount()
{
return _outputCount;
}
/////////////////////////////////////////////////////
//
// GPIO
//
uint8_t PCA9551::getInput()
{
return readReg(PCA9551_INPUT);
}
void PCA9551::pinMode1(uint8_t pin, uint8_t mode)
{
if (mode != OUTPUT) setOutputMode(pin, PCA9551_MODE_HIGH);
}
void PCA9551::write1(uint8_t pin, uint8_t val)
{
if (val == LOW) setOutputMode(pin, PCA9551_MODE_LOW);
else setOutputMode(pin, PCA9551_MODE_HIGH);
}
uint8_t PCA9551::read1(uint8_t pin)
{
uint8_t value = readReg(PCA9551_INPUT);
if ((value >> pin) & 0x01) return HIGH;
return LOW;
}
/////////////////////////////////////////////////////
//
// PRESCALERS
//
void PCA9551::setPrescaler(uint8_t gen, uint8_t psc)
{
if (gen == 0) writeReg(PCA9551_PSC0, psc);
else writeReg(PCA9551_PSC1, psc);
}
uint8_t PCA9551::getPrescaler(uint8_t gen)
{
if (gen == 0) return readReg(PCA9551_PSC0);
else return readReg(PCA9551_PSC1);
}
/////////////////////////////////////////////////////
//
// PWM
//
void PCA9551::setPWM(uint8_t gen, uint8_t pwm)
{
if (gen == 0) writeReg(PCA9551_PWM0, pwm);
else writeReg(PCA9551_PWM1, pwm);
}
uint8_t PCA9551::getPWM(uint8_t gen)
{
if (gen == 0) return readReg(PCA9551_PWM0);
else return readReg(PCA9551_PWM1);
}
/////////////////////////////////////////////////////
//
// OUTPUT MODE - MUX SELECTION
//
uint8_t PCA9551::setOutputMode(uint8_t pin, uint8_t mode)
{
if (pin >= _outputCount)
{
_error = PCA9551_ERR_CHAN;
return _error;
}
if (mode > 3)
{
_error = PCA9551_ERR_MODE;
return _error;
}
uint8_t reg = PCA9551_LS0;
if (pin > 3)
{
reg = PCA9551_LS1;
pin -= 4;
}
uint8_t ledSelect = readReg(reg);
ledSelect &= ~(0x03 << (pin * 2));
ledSelect |= (mode << (pin * 2));
return writeReg(reg, ledSelect);
}
uint8_t PCA9551::getOutputMode(uint8_t pin)
{
if (pin >= _outputCount)
{
_error = PCA9551_ERR_CHAN;
return _error;
}
uint8_t reg = PCA9551_LS0;
if (pin > 3)
{
reg = PCA9551_LS1;
pin -= 4;
}
uint8_t ledSelect = readReg(reg);
uint8_t mode = (ledSelect >> (pin * 2)) & 0x03;
return mode;
}
uint8_t PCA9551::getLastError()
{
uint8_t e = _error;
_error = PCA9551_OK;
return e;
}
/////////////////////////////////////////////////////
//
// PRIVATE
//
uint8_t PCA9551::writeReg(uint8_t reg, uint8_t value)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->write(value);
_error = _wire->endTransmission();
if (_error == 0) _error = PCA9551_OK;
else _error = PCA9551_ERROR;
return _error;
}
uint8_t PCA9551::readReg(uint8_t reg)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_error = _wire->endTransmission();
if (_error == 0) _error = PCA9551_OK;
else
{
_error = PCA9551_ERR_I2C;
return 0;
}
if (_wire->requestFrom(_address, (uint8_t)1) != 1)
{
_error = PCA9551_ERROR;
return 0;
}
_error = PCA9551_OK;
return _wire->read();
}
// -- END OF FILE --