Skip to content

Commit

Permalink
Merge pull request #6 from RobTillaart/develop
Browse files Browse the repository at this point in the history
fix #5 + minor refactor + isConnected()
  • Loading branch information
RobTillaart authored Jul 30, 2020
2 parents a72fcd4 + dab3480 commit 42140b0
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 32 deletions.
44 changes: 25 additions & 19 deletions PCF8575.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
// FILE: PCF8575.cpp
// AUTHOR: Rob Tillaart
// DATE: 2020-07-20
// VERSION: 0.0.2
// VERSION: 0.0.3
// PURPOSE: Arduino library for PCF8575 - 16 channel I2C IO expander
// URL: https://github.com/RobTillaart/PCF8575
//
// HISTORY:
// 0.0.1 2020-07-20 initial version
// 0.0.2 2020-07-21 fix reverse(); refactor;
// 0.0.3 2020-07-29 fix #5 reverse() + refactor.

#include "PCF8575.h"

Expand Down Expand Up @@ -36,6 +37,12 @@ void PCF8575::begin(uint16_t val)
PCF8575::write16(val);
}

bool PCF8575::isConnected()
{
Wire.beginTransmission(_address);
return Wire.endTransmission() == 0;
}

uint16_t PCF8575::read16()
{
if (Wire.requestFrom(_address, (uint8_t)2) != 2)
Expand Down Expand Up @@ -98,63 +105,62 @@ void PCF8575::toggle(const uint8_t pin)

void PCF8575::toggleMask(const uint16_t mask)
{
_dataOut ^= mask;
PCF8575::write16(_dataOut);
PCF8575::write16(_dataOut ^ mask);
}

void PCF8575::shiftRight(const uint8_t n)
{
if ((n == 0) || (_dataOut == 0)) return;
if (n > 15) _dataOut = 0; // shift 8++ clears all, valid...
if (_dataOut != 0) _dataOut >>= n; // only shift if there are bits set
if (n > 15) _dataOut = 0; // shift 8++ clears all, valid...
else _dataOut >>= n; // only shift if there are bits set
PCF8575::write16(_dataOut);
}

void PCF8575::shiftLeft(const uint8_t n)
{
if ((n == 0) || (_dataOut == 0)) return;
if (n > 15) _dataOut = 0; // shift 8++ clears all, valid...
if (_dataOut != 0) _dataOut <<= n; // only shift if there are bits set
if (n > 15) _dataOut = 0; // shift 8++ clears all, valid...
else _dataOut <<= n; // only shift if there are bits set
PCF8575::write16(_dataOut);
}

int PCF8575::lastError()
{
int e = _error;
_error = PCF8575_OK;
_error = PCF8575_OK; // reset error after read, is this wise?
return e;
}

void PCF8575::rotateRight(const uint8_t n)
{
if ((n % 16) == 0) return;
uint8_t r = n & 15;
if (r == 0) return;
_dataOut = (_dataOut >> r) | (_dataOut << (15 - r));
PCF8575::write16(_dataOut);
}

void PCF8575::rotateLeft(const uint8_t n)
{
rotateRight(16- (n & 15));
rotateRight(16 - (n & 15));
}

void PCF8575::reverse() // quite fast
{
uint8_t x = _dataOut;
x = (((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1));
x = (((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2));
x = (((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4));
x = (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8));
void PCF8575::reverse() // quite fast
{ // 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
PCF8575::write16(x);
}

//added 0.1.07/08 Septillion
uint16_t PCF8575::readButton16(const uint16_t mask)
{
uint16_t temp = _dataOut;
PCF8575::write16(mask | _dataOut);
PCF8575::write16(mask | _dataOut); // read only selected lines
PCF8575::read16();
PCF8575::write16(temp);
PCF8575::write16(temp); // restore
return _dataIn;
}

Expand Down
18 changes: 11 additions & 7 deletions PCF8575.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
// FILE: PCF8575.h
// AUTHOR: Rob Tillaart
// DATE: 2020-07-20
// VERSION: 0.0.2
// VERSION: 0.0.3
// PURPOSE: Arduino library for PCF8575 - 16 channel I2C IO expander
// URL: https://github.com/RobTillaart/PCF8575
//
// HISTORY:
// based upon PCF8574 library
//
// see PCF8575.cpp file
//

#include "Arduino.h"
#include "Wire.h"

#define PCF8575_LIB_VERSION "0.0.2"
#define PCF8575_LIB_VERSION "0.0.3"

#ifndef PCF8575_INITIAL_VALUE
#define PCF8575_INITIAL_VALUE 0xFFFF
#endif


#define PCF8575_OK 0x00
#define PCF8575_PIN_ERROR 0x81
Expand All @@ -30,9 +33,10 @@ class PCF8575
explicit PCF8575(const uint8_t deviceAddress);

#if defined (ESP8266) || defined(ESP32)
void begin(uint8_t sda, uint8_t scl, uint16_t val = 0xFFFF);
void begin(uint8_t sda, uint8_t scl, uint16_t val = PCF8575_INITIAL_VALUE);
#endif
void begin(uint16_t val = 0xFFFF);
void begin(uint16_t val = PCF8575_INITIAL_VALUE);
bool isConnected();

uint16_t read16();
uint8_t read(uint8_t pin);
Expand All @@ -48,7 +52,7 @@ class PCF8575
uint8_t readButton(const uint8_t pin);
void setButtonMask(uint16_t mask) { _buttonMask = mask; };

// rotate, shift, toggle, reverse expect all lines are output
// rotate, shift, toggle, reverse expect all lines are output
void toggle(const uint8_t pin);
void toggleMask(const uint16_t mask = 0xFFFF); // default invertAll()
void shiftRight(const uint8_t n = 1);
Expand Down
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ The library allows to read and write both single pins or 16 pins at once.
Furthermore some additional functions are implemented that are a little more
playfull but still are useful.

## I2C Clock

Testing showed that the PCF8575 still works at 600 KHz and failed at 800 KHz.
These values are outside the specs of the datasheet so they are not recommendend.
However when performance is neede you can try to overclock the chip.

## Interface

- **PCF8575(deviceAddress)** Constructor with device address as parameter.
- **begin(val = 0xFF)** set the initial value for the pins and masks.
- **begin(sda, scl, val = 0xFFFF)** idem, for the ESP32 where one can choose the I2C pins
**PCF8575_INITIAL_VALUE** is a define that can be set compile time or before
the include of "pcf8575.h" to overrule the default value used with the
**begin()** call.

- **PCF8575(deviceAddress)** Constructor with I2C device address as parameter.
- **begin(val = PCF8575_INITIAL_VALUE)** set the initial value for the pins and masks.
- **begin(sda, scl, val = PCF8575_INITIAL_VALUE)** idem, for the ESP32 where one can choose the I2C pins
What needs to be added in the future is a parameter to choose another Wire interface
as some processors have multiple hardware Wire interfaces.
- **read16()** reads all 16 pins at once. This one does the actual reading.
Expand All @@ -52,6 +61,12 @@ Fills the lower lines with zero's.
- **rotateLeft(n = 1)** rotates output channels to left, moving highest line to lowest line.
- **reverse()** revers the "bit pattern" of the lines, high to low and vice versa.

## Testing

Testing the initial library is done by Colin Mackay (thanks!).

Platforms used for testing include: Nano, ESP32 and Seeed Xiao


## Operation

Expand Down
32 changes: 32 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Syntax Coloring Map For PCF8575

# Datatypes (KEYWORD1)
PCF8575 KEYWORD1

# Methods and Functions (KEYWORD2)
begin KEYWORD2
isConnected KEYWORD2

read16 KEYWORD2
read KEYWORD2
value KEYWORD2

write16 KEYWORD2
write KEYWORD2
valueOut KEYWORD2

readButton16 KEYWORD2
readButton KEYWORD2
setButtonMask KEYWORD2

toggle KEYWORD2
toggleMask KEYWORD2
shiftRight KEYWORD2
shiftLeft KEYWORD2
rotateRight KEYWORD2
rotateLeft KEYWORD2
reverse KEYWORD2
lastError KEYWORD2

# Constants (LITERAL1)

4 changes: 2 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "PCF8575",
"keywords": "I2C, PCF8575, 16 channel, IO, I/O, shift, rotate",
"keywords": "I2C, PCF8575, 16 channel, IO, I/O, shift, rotate, readButton, toggle, reverse",
"description": "Arduino library for PCF8575 - 16 channel I2C IO expander, implements shift rotate.",
"authors":
[
Expand All @@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/PCF8575.git"
},
"version":"0.0.2",
"version":"0.0.3",
"frameworks": "arduino",
"platforms": "*"
}
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=PCF8575
version=0.0.2
version=0.0.3
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for PCF8575 - 16 channel I2C IO expander
Expand Down

0 comments on commit 42140b0

Please sign in to comment.