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

270 lines
4.9 KiB
C++
Raw Normal View History

2021-01-29 06:31:58 -05:00
//
// FILE: PCF8575.cpp
// AUTHOR: Rob Tillaart
// DATE: 2020-07-20
2024-04-16 15:55:19 -04:00
// VERSION: 0.2.3
2021-01-29 06:31:58 -05:00
// PURPOSE: Arduino library for PCF8575 - 16 channel I2C IO expander
// URL: https://github.com/RobTillaart/PCF8575
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
#include "PCF8575.h"
PCF8575::PCF8575(const uint8_t deviceAddress, TwoWire *wire)
{
_address = deviceAddress;
_wire = wire;
_dataIn = 0;
_dataOut = 0xFFFF;
_buttonMask = 0xFFFF;
_error = PCF8575_OK;
}
2021-07-09 07:02:35 -04:00
2021-12-23 07:53:35 -05:00
bool PCF8575::begin(uint16_t value)
2021-01-29 06:31:58 -05:00
{
if (! isConnected()) return false;
2021-12-23 07:53:35 -05:00
PCF8575::write16(value);
2021-01-29 06:31:58 -05:00
return true;
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
bool PCF8575::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
2021-07-09 07:02:35 -04:00
bool PCF8575::setAddress(const uint8_t deviceAddress)
{
2023-12-29 10:04:42 -05:00
if ((deviceAddress < 0x20) || (deviceAddress > 0x27)) return false;
2021-07-09 07:02:35 -04:00
_address = deviceAddress;
return isConnected();
}
uint8_t PCF8575::getAddress()
{
return _address;
}
2021-01-29 06:31:58 -05:00
uint16_t PCF8575::read16()
{
if (_wire->requestFrom(_address, (uint8_t)2) != 2)
{
_error = PCF8575_I2C_ERROR;
2023-02-04 13:21:27 -05:00
return _dataIn; // last value
2021-01-29 06:31:58 -05:00
}
2023-02-04 13:21:27 -05:00
_dataIn = _wire->read(); // low 8 bits
_dataIn |= (_wire->read() << 8); // high 8 bits
2021-01-29 06:31:58 -05:00
return _dataIn;
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
uint8_t PCF8575::read(const uint8_t pin)
{
if (pin > 15)
{
_error = PCF8575_PIN_ERROR;
return 0;
}
PCF8575::read16();
return (_dataIn & (1 << pin)) > 0;
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
uint16_t PCF8575::value()
{
return _dataIn;
};
void PCF8575::write16(const uint16_t value)
{
_dataOut = value;
_wire->beginTransmission(_address);
2023-02-04 13:21:27 -05:00
_wire->write(_dataOut & 0xFF); // low 8 bits
_wire->write(_dataOut >> 8); // high 8 bits
2022-11-21 14:26:00 -05:00
_error = _wire->endTransmission();
}
2021-01-29 06:31:58 -05:00
void PCF8575::write(const uint8_t pin, const uint8_t value)
{
if (pin > 15)
{
_error = PCF8575_PIN_ERROR;
return;
}
if (value == LOW)
{
_dataOut &= ~(1 << pin);
}
else
{
_dataOut |= (1 << pin);
}
2023-12-29 10:04:42 -05:00
PCF8575::write16(_dataOut);
2021-01-29 06:31:58 -05:00
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
uint16_t PCF8575::valueOut()
{
return _dataOut;
}
2021-01-29 06:31:58 -05:00
void PCF8575::toggle(const uint8_t pin)
{
if (pin > 15)
{
_error = PCF8575_PIN_ERROR;
return;
}
toggleMask(1 << pin);
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
void PCF8575::toggleMask(const uint16_t mask)
{
_dataOut ^= mask;
PCF8575::write16(_dataOut);
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
void PCF8575::shiftRight(const uint8_t n)
{
if ((n == 0) || (_dataOut == 0)) return;
2023-02-04 13:21:27 -05:00
if (n > 15) _dataOut = 0; // shift 15++ clears all, valid...
if (_dataOut != 0) _dataOut >>= n; // only shift if there are bits set
2021-01-29 06:31:58 -05:00
PCF8575::write16(_dataOut);
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
void PCF8575::shiftLeft(const uint8_t n)
{
if ((n == 0) || (_dataOut == 0)) return;
2023-02-04 13:21:27 -05:00
if (n > 15) _dataOut = 0; // shift 15++ clears all, valid...
if (_dataOut != 0) _dataOut <<= n; // only shift if there are bits set
2021-01-29 06:31:58 -05:00
PCF8575::write16(_dataOut);
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
void PCF8575::rotateRight(const uint8_t n)
{
uint8_t r = n & 15;
if (r == 0) return;
_dataOut = (_dataOut >> r) | (_dataOut << (15 - r));
PCF8575::write16(_dataOut);
}
2021-07-09 07:02:35 -04:00
2021-01-29 06:31:58 -05:00
void PCF8575::rotateLeft(const uint8_t n)
{
rotateRight(16 - (n & 15));
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
void PCF8575::reverse() // quite fast
2023-02-04 13:21:27 -05:00
{ // 1 char === 1 bit
uint16_t x = _dataOut; // x = 0123456789ABCDEF
x = (((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1)); // x = 1032547698BADCFE
x = (((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2)); // x = 32107654BA98FEDC
x = (((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4)); // x = 76543210FEDCBA98
x = (x >> 8) | ( x << 8); // x = FEDCBA9876543210
2021-01-29 06:31:58 -05:00
PCF8575::write16(x);
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
//////////////////////////////////////////////////
//
// added 0.1.07/08 Septillion
//
2021-01-29 06:31:58 -05:00
uint16_t PCF8575::readButton16(const uint16_t mask)
{
uint16_t temp = _dataOut;
2023-02-04 13:21:27 -05:00
PCF8575::write16(mask | _dataOut); // read only selected lines
2021-01-29 06:31:58 -05:00
PCF8575::read16();
2023-02-04 13:21:27 -05:00
PCF8575::write16(temp); // restore
2021-01-29 06:31:58 -05:00
return _dataIn;
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
uint16_t PCF8575::readButton16()
{
return readButton16(_buttonMask);
}
2021-01-29 06:31:58 -05:00
uint8_t PCF8575::readButton(const uint8_t pin)
{
if (pin > 15)
{
_error = PCF8575_PIN_ERROR;
return 0;
}
uint16_t temp = _dataOut;
PCF8575::write(pin, HIGH);
uint8_t rtn = PCF8575::read(pin);
PCF8575::write16(temp);
return rtn;
}
2021-07-09 07:02:35 -04:00
2022-11-21 14:26:00 -05:00
void PCF8575::setButtonMask(uint16_t mask)
2023-02-04 13:21:27 -05:00
{
2022-11-21 14:26:00 -05:00
_buttonMask = mask;
};
2023-02-04 13:21:27 -05:00
uint16_t PCF8575::getButtonMask()
{
return _buttonMask;
2022-11-21 14:26:00 -05:00
};
//////////////////////////////////////////////////
//
2023-02-04 13:21:27 -05:00
// SELECT
2022-11-21 14:26:00 -05:00
//
2022-06-19 04:49:56 -04:00
void PCF8575::select(const uint8_t pin)
{
uint16_t n = 0x0000;
if (pin < 16) n = 1L << pin;
2023-12-29 10:04:42 -05:00
PCF8575::write16(n);
2022-06-19 04:49:56 -04:00
};
2022-11-21 14:26:00 -05:00
void PCF8575::selectN(const uint8_t pin)
2022-06-19 04:49:56 -04:00
{
uint16_t n = 0xFFFF;
if (pin < 16) n = (2L << pin) - 1;
2023-12-29 10:04:42 -05:00
PCF8575::write16(n);
2022-06-19 04:49:56 -04:00
};
2022-11-21 14:26:00 -05:00
void PCF8575::selectNone()
{
2023-12-29 10:04:42 -05:00
PCF8575::write16(0x0000);
2022-11-21 14:26:00 -05:00
};
void PCF8575::selectAll()
{
2023-12-29 10:04:42 -05:00
PCF8575::write16(0xFFFF);
2022-11-21 14:26:00 -05:00
};
int PCF8575::lastError()
{
int e = _error;
2023-02-04 13:21:27 -05:00
_error = PCF8575_OK; // reset error after read, is this wise?
2022-11-21 14:26:00 -05:00
return e;
}
2022-06-19 04:49:56 -04:00
2022-11-21 14:26:00 -05:00
// -- END OF FILE --
2021-12-23 07:53:35 -05:00