0.2.0 refactor, added reverse()

This commit is contained in:
rob tillaart 2020-05-23 13:33:43 +02:00
parent 6c4edf512a
commit 8865401054
7 changed files with 217 additions and 91 deletions

21
libraries/PCF8574/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2013-2020 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -2,12 +2,18 @@
// FILE: PCF8574.cpp
// AUTHOR: Rob Tillaart
// DATE: 02-febr-2013
// VERSION: 0.1.9
// PURPOSE: I2C PCF8574 library for Arduino
// URL: http://forum.arduino.cc/index.php?topic=184800
// VERSION: 0.2.0
// PURPOSE: Arduino library for PCF8574 - I2C IO expander
// URL: https://github.com/RobTillaart/PCF8574
// http://forum.arduino.cc/index.php?topic=184800
//
// HISTORY:
// 0.1.9 fix warning about return in readButton8()
// 0.2.0 2020-05-22 #pragma once; refactor;
// removed pre 1.0 support
// added begin(dsa, scl) for ESP32
// added reverse()
//
// 0.1.9 2017-02-27 fix warning about return in readButton8()
// 0.1.08 2016-05-20 Merged work of Septillion
// Fix/refactor ButtonRead8() - see https://github.com/RobTillaart/Arduino/issues/38
// missing begin() => mask parameter
@ -35,6 +41,7 @@
#include <Wire.h>
PCF8574::PCF8574(const uint8_t deviceAddress)
{
_address = deviceAddress;
@ -44,6 +51,14 @@ PCF8574::PCF8574(const uint8_t deviceAddress)
_error = PCF8574_OK;
}
#if defined (ESP8266) || defined(ESP32)
void PCF8574::begin(uint8_t sda, uint8_t scl, uint8_t val)
{
Wire.begin(sda, scl);
PCF8574::write8(val);
}
#endif
void PCF8574::begin(uint8_t val)
{
Wire.begin();
@ -62,11 +77,7 @@ uint8_t PCF8574::read8()
_error = PCF8574_I2C_ERROR;
return _dataIn; // last value
}
#if (ARDUINO < 100)
_dataIn = Wire.receive();
#else
_dataIn = Wire.read();
#endif
return _dataIn;
}
@ -125,15 +136,17 @@ void PCF8574::toggleMask(const uint8_t mask)
void PCF8574::shiftRight(const uint8_t n)
{
if (n == 0 || n > 7) return;
_dataOut >>= n;
if ((n == 0) || (_dataOut == 0)) return;
if (n > 7) _dataOut = 0; // shift 8++ clears all, valid...
if (_dataOut != 0) _dataOut >>= n;
PCF8574::write8(_dataOut);
}
void PCF8574::shiftLeft(const uint8_t n)
{
if (n == 0 || n > 7) return;
_dataOut <<= n;
if ((n == 0) || (_dataOut == 0)) return;
if (n > 7) _dataOut = 0; // shift 8++ clears all, valid...
if (_dataOut != 0) _dataOut <<= n; // only shift if there are bits set
PCF8574::write8(_dataOut);
}
@ -146,8 +159,9 @@ int PCF8574::lastError()
void PCF8574::rotateRight(const uint8_t n)
{
if ((n % 8) == 0) return;
uint8_t r = n & 7;
_dataOut = (_dataOut >> r) | (_dataOut << (8-r));
_dataOut = (_dataOut >> r) | (_dataOut << (8 - r));
PCF8574::write8(_dataOut);
}
@ -156,6 +170,15 @@ void PCF8574::rotateLeft(const uint8_t n)
rotateRight(8- (n & 7));
}
void PCF8574::reverse() // quite fast: 14 shifts, 3 or, 3 assignment.
{
uint8_t x = _dataOut;
x = (((x & 0xaa) >> 1) | ((x & 0x55) << 1));
x = (((x & 0xcc) >> 2) | ((x & 0x33) << 2));
x = ((x >> 4) | (x << 4));
PCF8574::write8(x);
}
//added 0.1.07/08 Septillion
uint8_t PCF8574::readButton8(const uint8_t mask)
{
@ -181,11 +204,4 @@ uint8_t PCF8574::readButton(const uint8_t pin)
return rtn;
}
//added 0.1.08 Septillion
void PCF8574::setButtonMask(uint8_t mask){
_buttonMask = mask;
}
//
// END OF FILE
//
// -- END OF FILE --

View File

@ -1,25 +1,20 @@
#pragma once
//
// FILE: PCF8574.H
// AUTHOR: Rob Tillaart
// DATE: 02-febr-2013
// VERSION: 0.1.9
// PURPOSE: I2C PCF8574 library for Arduino
// URL: http://forum.arduino.cc/index.php?topic=184800
// VERSION: 0.2.0
// PURPOSE: Arduino library for PCF8574 - I2C IO expander
// URL: https://github.com/RobTillaart/PCF8574
// http://forum.arduino.cc/index.php?topic=184800
//
// HISTORY:
// see PCF8574.cpp file
//
#ifndef _PCF8574_H
#define _PCF8574_H
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define PCF8574_LIB_VERSION "0.1.9"
#define PCF8574_LIB_VERSION "0.2.0"
#define PCF8574_OK 0x00
#define PCF8574_PIN_ERROR 0x81
@ -31,29 +26,33 @@ class PCF8574
public:
explicit PCF8574(const uint8_t deviceAddress);
void begin(uint8_t val=0xFF);
#if defined (ESP8266) || defined(ESP32)
void begin(uint8_t sda, uint8_t scl, uint8_t val = 0xFF);
#endif
void begin(uint8_t val = 0xFF);
uint8_t read8();
uint8_t read(uint8_t pin);
uint8_t value() const { return _dataIn; };
void write8(const uint8_t value);
void write(const uint8_t pin, const uint8_t value);
void write8(const uint8_t value);
void write(const uint8_t pin, const uint8_t value);
uint8_t valueOut() const { return _dataOut; }
//added 0.1.07/08 Septillion
inline uint8_t readButton8(){ return PCF8574::readButton8(_buttonMask);}
uint8_t readButton8(const uint8_t mask=0xFF);
uint8_t readButton(const uint8_t pin);
void setButtonMask(uint8_t mask);
inline uint8_t readButton8() { return PCF8574::readButton8(_buttonMask); }
uint8_t readButton8(const uint8_t mask = 0xFF);
uint8_t readButton(const uint8_t pin);
inline void setButtonMask(uint8_t mask) { _buttonMask = mask; };
// rotate, shift, toggle expect all lines are output
void toggle(const uint8_t pin);
void toggleMask(const uint8_t mask); // invertAll() = toggleMask(0xFF)
void shiftRight(const uint8_t n=1);
void shiftLeft(const uint8_t n=1);
void rotateRight(const uint8_t n=1);
void rotateLeft(const uint8_t n=1);
// rotate, shift, toggle, reverse expect all lines are output
void toggle(const uint8_t pin);
void toggleMask(const uint8_t mask = 0xFF); // default 0xFF ==> invertAll()
void shiftRight(const uint8_t n = 1);
void shiftLeft(const uint8_t n = 1);
void rotateRight(const uint8_t n = 1);
void rotateLeft(const uint8_t n = 1);
void reverse();
int lastError();
@ -62,10 +61,8 @@ private:
uint8_t _dataIn;
uint8_t _dataOut;
uint8_t _buttonMask;
int _error;
int _error;
};
#endif
//
// END OF FILE
//
// -- END OF FILE --

View File

@ -0,0 +1,81 @@
# PCF8574
Arduino library for PCF8574 - I2C IO expander
# Description
This library gives easy control over the 8 pins of a PCF8574 and PCF8574A chip.
These chips are identical in behavior although there are two distinct address ranges.
| TYPE | ADDRESS-RANGE |
|:----|:----:|
|PCF8574 | 0x20 to 0x27 |
|PCF8574A | 0x38 to 0x3F |
THe library allows to read and write both single pins or 8 pins at once.
Furthermore some additional functions are implemented that are a little more
playfull but still are useful.
### Interface
**PCF8574(deviceAddress)** Constructor with device address as parameter.
**begin(val = 0xFF)** set the initial value for the pins and masks.
**begin(sda, scl, val = 0xFF)** 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.
----
**read8()** reads all 8 pins at once. This one does the actual reading.
**read(pin)** reads a single pin; pin = 0..7
**value()** returns the last read inputs again, as this information is buffered
in the class this is faster than reread the pins.
----
**write8(value)** writes all 8 pins at once. This one does the actual reading.
**write(pin, value)** writes a single pin; pin = 0..7; value is HIGH(1) or LOW (0)
**valueOut()** returns the last written data.
----
TODO
**setButtonMask(mask)**
**readButton8()**
**readButton8(mask = 0xFF)**
**readButton(pin)**
----
**toggle(pin)** toggles a single pin
**toggleMask(mask)** toggles a selection of pins, if you want to invert all pins use 0xFF.
**shiftRight(n = 1)** shifts output channels n pins (default 1) pins right (e.g. leds ).
Fills the higher lines with zero's.
**shiftLeft(n = 1)** shifts output channels n pins (default 1) pins left (e.g. leds ).
Fills the lower lines with zero's.
**rotateRight(n = 1)** rotates output channels to right, moving lowest line to highest line.
**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.
# Operation
See examples

View File

@ -14,42 +14,51 @@ PCF8574 PCF_39(0x39); // add leds to lines (used as output)
void setup()
{
Serial.begin(115200);
Serial.print("\npcf8574_test2.ino\nlib version: ");
Serial.println(PCF8574_LIB_VERSION);
PCF_39.begin();
Serial.begin(115200);
Serial.print("\npcf8574_test2.ino\nlib version: ");
Serial.println(PCF8574_LIB_VERSION);
PCF_39.write(0, 1);
for (int i=0; i<7; i++)
{
PCF_39.rotateLeft();
delay(100);
}
PCF_39.begin();
for (int i=0; i<7; i++)
{
PCF_39.rotateRight();
delay(100);
}
PCF_39.write(0, 1);
for (int i = 0; i < 7; i++)
{
PCF_39.rotateLeft();
delay(100);
}
for (int i=0; i<7; i++)
{
PCF_39.rotateLeft(3);
delay(100);
}
for (int i = 0; i < 7; i++)
{
PCF_39.rotateRight();
delay(100);
}
for (int i=0; i<7; i++)
{
PCF_39.rotateRight(2);
delay(100);
}
for (int i = 0; i < 7; i++)
{
PCF_39.rotateLeft(3);
delay(100);
}
for (int i=0; i<255; i++)
{
PCF_39.toggleMask(i);
delay(100);
}
for (int i = 0; i < 7; i++)
{
PCF_39.rotateRight(2);
delay(100);
}
for (int i = 0; i < 255; i++)
{
PCF_39.toggleMask(i);
delay(100);
}
// 0010 0111 -> 0x27
// 1110 0100
PCF_39.write8(0x27);
for (int i = 0; i < 255; i++)
{
PCF_39.reverse();
delay(100);
}
}
void loop()

View File

@ -1,7 +1,7 @@
{
"name": "PCF8574",
"keywords": "I2C,PCF8574,IO,I/O,shift,rotate",
"description": "Library PCF8574 library for Arduino, implements shift rotate.",
"keywords": "I2C, PCF8574, PCF8574A, IO, I/O, shift, rotate",
"description": "Arduino library for PCF8574 - I2C IO expander, implements shift rotate.",
"authors":
[
{
@ -13,12 +13,12 @@
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/Arduino.git"
"url": "https://github.com/RobTillaart/PCF8574.git"
},
"version":"0.1.9",
"version":"0.2.0",
"frameworks": "arduino",
"platforms": "*",
"export": {
"include": "libraries/PCF8574"
"include": "*"
}
}

View File

@ -2,8 +2,10 @@ name=PCF8574
version=0.1.9
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library PCF8574 library for Arduino.
paragraph=Implements shift rotate.
sentence=Arduino library for PCF8574 - I2C IO expander
paragraph=Implements shift rotate and toggle.
category=Signal Input/Output
url=https://github.com/RobTillaart/Arduino/tree/master/libraries/
architectures=*
url=https://github.com/RobTillaart/PCF8574.git
architectures=*
includes=PCF8574.h
depends=