mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
251 lines
4.3 KiB
C++
251 lines
4.3 KiB
C++
//
|
|
// FILE: PCA9551.cpp
|
|
// AUTHOR: Rob Tillaart
|
|
// DATE: 2023-07-17
|
|
// VERSION: 0.1.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;
|
|
}
|
|
|
|
|
|
#if defined (ESP8266) || defined(ESP32)
|
|
bool PCA9551::begin(int sda, int scl)
|
|
{
|
|
if ((sda < 255) && (scl < 255))
|
|
{
|
|
_wire->begin(sda, scl);
|
|
} else {
|
|
_wire->begin();
|
|
}
|
|
if (! isConnected()) return false;
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
|
|
bool PCA9551::begin()
|
|
{
|
|
_wire->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::pinMode(uint8_t pin, uint8_t mode)
|
|
{
|
|
if (mode != OUTPUT) setOutputMode(pin, PCA9551_MODE_HIGH);
|
|
}
|
|
|
|
|
|
void PCA9551::digitalWrite(uint8_t pin, uint8_t val)
|
|
{
|
|
if (val == LOW) setOutputMode(pin, PCA9551_MODE_LOW);
|
|
else setOutputMode(pin, PCA9551_MODE_HIGH);
|
|
}
|
|
|
|
|
|
uint8_t PCA9551::digitalRead(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 --
|
|
|