mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-10-03 18:09:02 -04:00
241 lines
4.2 KiB
C++
241 lines
4.2 KiB
C++
//
|
|
// FILE: PCA9553.cpp
|
|
// AUTHOR: Rob Tillaart
|
|
// DATE: 2023-07-16
|
|
// VERSION: 0.2.1
|
|
// PURPOSE: Arduino library for for I2C PCA9553 4 channel PWM
|
|
// URL: https://github.com/RobTillaart/PCA9553
|
|
|
|
|
|
#include "PCA9553.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// Constructor
|
|
//
|
|
PCA9553::PCA9553(const uint8_t deviceAddress, TwoWire *wire)
|
|
{
|
|
_address = deviceAddress;
|
|
_wire = wire;
|
|
_outputCount = 4;
|
|
_error = PCA9553_OK;
|
|
}
|
|
|
|
|
|
#if defined (ESP8266) || defined(ESP32)
|
|
bool PCA9553::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 PCA9553::begin()
|
|
{
|
|
_wire->begin();
|
|
if (! isConnected()) return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
bool PCA9553::isConnected()
|
|
{
|
|
_wire->beginTransmission(_address);
|
|
_error = _wire->endTransmission();
|
|
return (_error == 0);
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::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 PCA9553_OK;
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::getAddress()
|
|
{
|
|
return _address;
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::outputCount()
|
|
{
|
|
return _outputCount;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// GPIO
|
|
//
|
|
uint8_t PCA9553::getInput()
|
|
{
|
|
return readReg(PCA9553_INPUT);
|
|
}
|
|
|
|
|
|
void PCA9553::pinMode(uint8_t pin, uint8_t mode)
|
|
{
|
|
if (mode != OUTPUT) setOutputMode(pin, PCA9553_MODE_HIGH);
|
|
}
|
|
|
|
|
|
void PCA9553::digitalWrite(uint8_t pin, uint8_t val)
|
|
{
|
|
if (val == LOW) setOutputMode(pin, PCA9553_MODE_LOW);
|
|
else setOutputMode(pin, PCA9553_MODE_HIGH);
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::digitalRead(uint8_t pin)
|
|
{
|
|
uint8_t value = readReg(PCA9553_INPUT);
|
|
if ((value >> pin) & 0x01) return HIGH;
|
|
return LOW;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// PRESCALERS
|
|
//
|
|
void PCA9553::setPrescaler(uint8_t gen, uint8_t psc)
|
|
{
|
|
if (gen == 0) writeReg(PCA9553_PSC0, psc);
|
|
else writeReg(PCA9553_PSC1, psc);
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::getPrescaler(uint8_t gen)
|
|
{
|
|
if (gen == 0) return readReg(PCA9553_PSC0);
|
|
else return readReg(PCA9553_PSC1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// PWM
|
|
//
|
|
void PCA9553::setPWM(uint8_t gen, uint8_t pwm)
|
|
{
|
|
if (gen == 0) writeReg(PCA9553_PWM0, pwm);
|
|
else writeReg(PCA9553_PWM1, pwm);
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::getPWM(uint8_t gen)
|
|
{
|
|
if (gen == 0) return readReg(PCA9553_PWM0);
|
|
else return readReg(PCA9553_PWM1);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// OUTPUT MODE - MUX SELECTION
|
|
//
|
|
uint8_t PCA9553::setOutputMode(uint8_t pin, uint8_t mode)
|
|
{
|
|
if (pin >= _outputCount)
|
|
{
|
|
_error = PCA9553_ERR_CHAN;
|
|
return _error;
|
|
}
|
|
if (mode > 3)
|
|
{
|
|
_error = PCA9553_ERR_MODE;
|
|
return _error;
|
|
}
|
|
|
|
uint8_t reg = PCA9553_LS0;
|
|
uint8_t ledSelect = readReg(reg);
|
|
ledSelect &= ~(0x03 << (pin * 2));
|
|
ledSelect |= (mode << (pin * 2));
|
|
|
|
return writeReg(reg, ledSelect);
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::getOutputMode(uint8_t pin)
|
|
{
|
|
if (pin >= _outputCount)
|
|
{
|
|
_error = PCA9553_ERR_CHAN;
|
|
return _error;
|
|
}
|
|
|
|
uint8_t reg = PCA9553_LS0;
|
|
uint8_t ledSelect = readReg(reg);
|
|
uint8_t mode = (ledSelect >> (pin * 2)) & 0x03;
|
|
return mode;
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::getLastError()
|
|
{
|
|
uint8_t e = _error;
|
|
_error = PCA9553_OK;
|
|
return e;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
//
|
|
// PRIVATE
|
|
//
|
|
uint8_t PCA9553::writeReg(uint8_t reg, uint8_t value)
|
|
{
|
|
_wire->beginTransmission(_address);
|
|
_wire->write(reg);
|
|
_wire->write(value);
|
|
_error = _wire->endTransmission();
|
|
|
|
if (_error == 0) _error = PCA9553_OK;
|
|
else _error = PCA9553_ERR_I2C;
|
|
return _error;
|
|
}
|
|
|
|
|
|
uint8_t PCA9553::readReg(uint8_t reg)
|
|
{
|
|
_wire->beginTransmission(_address);
|
|
_wire->write(reg);
|
|
_error = _wire->endTransmission();
|
|
if (_error == 0) _error = PCA9553_OK;
|
|
else
|
|
{
|
|
_error = PCA9553_ERR_I2C;
|
|
return 0;
|
|
}
|
|
if (_wire->requestFrom(_address, (uint8_t)1) != 1)
|
|
{
|
|
_error = PCA9553_ERR_I2C;
|
|
return 0;
|
|
}
|
|
_error = PCA9553_OK;
|
|
return _wire->read();
|
|
}
|
|
|
|
|
|
// -- END OF FILE --
|
|
|