Skip to content

Commit 7d9b1db

Browse files
committed
0.1.0 PCA9671
1 parent a7a68e7 commit 7d9b1db

File tree

23 files changed

+1479
-0
lines changed

23 files changed

+1479
-0
lines changed

libraries/PCA9671/.arduino-ci.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
platforms:
2+
rpipico:
3+
board: rp2040:rp2040:rpipico
4+
package: rp2040:rp2040
5+
gcc:
6+
features:
7+
defines:
8+
- ARDUINO_ARCH_RP2040
9+
warnings:
10+
flags:
11+
12+
packages:
13+
rp2040:rp2040:
14+
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
15+
16+
compile:
17+
# Choosing to run compilation tests on 2 different Arduino platforms
18+
platforms:
19+
- uno
20+
# - due
21+
# - zero
22+
# - leonardo
23+
- m4
24+
- esp32
25+
- esp8266
26+
# - mega2560
27+
- rpipico
28+
29+
libraries:
30+
- "printHelpers"

libraries/PCA9671/.github/FUNDING.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# These are supported funding model platforms
2+
3+
github: RobTillaart
4+
custom: "https://www.paypal.me/robtillaart"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Arduino-lint
2+
3+
on: [push, pull_request]
4+
jobs:
5+
lint:
6+
runs-on: ubuntu-latest
7+
timeout-minutes: 5
8+
steps:
9+
- uses: actions/checkout@v4
10+
- uses: arduino/arduino-lint-action@v1
11+
with:
12+
library-manager: update
13+
compliance: strict
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Arduino CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
runTest:
7+
runs-on: ubuntu-latest
8+
timeout-minutes: 20
9+
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: ruby/setup-ruby@v1
13+
with:
14+
ruby-version: 2.6
15+
- run: |
16+
gem install arduino_ci
17+
arduino_ci.rb
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: JSON check
2+
3+
on:
4+
push:
5+
paths:
6+
- '**.json'
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 5
13+
steps:
14+
- uses: actions/checkout@v4
15+
- name: json-syntax-check
16+
uses: limitusus/json-syntax-check@v2
17+
with:
18+
pattern: "\\.json$"

libraries/PCA9671/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Change Log PCA9671
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
6+
and this project adheres to [Semantic Versioning](http://semver.org/).
7+
8+
9+
## [0.1.0] - 2025-03-16
10+
11+
- initial version based upon PCF8575 library.
12+
13+
14+

libraries/PCA9671/LICENSE

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

libraries/PCA9671/PCA9671.cpp

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
//
2+
// FILE: PCA9671.cpp
3+
// AUTHOR: Rob Tillaart
4+
// DATE: 2025-03-16
5+
// VERSION: 0.1.0
6+
// PURPOSE: Arduino library for the PCA9671, I2C 16-bit I/O expander
7+
// URL: https://github.com/RobTillaart/PCA9671
8+
9+
10+
11+
#include "PCA9671.h"
12+
13+
14+
15+
PCA9671::PCA9671(const uint8_t deviceAddress, TwoWire *wire)
16+
{
17+
_address = deviceAddress;
18+
_wire = wire;
19+
_dataIn = 0;
20+
_dataOut = 0xFFFF;
21+
_buttonMask = 0xFFFF;
22+
_error = PCA9671_OK;
23+
}
24+
25+
26+
bool PCA9671::begin(uint16_t value)
27+
{
28+
if (! isConnected()) return false;
29+
PCA9671::write16(value);
30+
return true;
31+
}
32+
33+
34+
bool PCA9671::isConnected()
35+
{
36+
_wire->beginTransmission(_address);
37+
return ( _wire->endTransmission() == 0);
38+
}
39+
40+
41+
bool PCA9671::setAddress(const uint8_t deviceAddress)
42+
{
43+
if ((deviceAddress < 0x20) || (deviceAddress > 0x27)) return false;
44+
_address = deviceAddress;
45+
return isConnected();
46+
}
47+
48+
49+
uint8_t PCA9671::getAddress()
50+
{
51+
return _address;
52+
}
53+
54+
55+
uint16_t PCA9671::read16()
56+
{
57+
if (_wire->requestFrom(_address, (uint8_t)2) != 2)
58+
{
59+
_error = PCA9671_I2C_ERROR;
60+
return _dataIn; // last value
61+
}
62+
_dataIn = _wire->read(); // low 8 bits
63+
_dataIn |= (_wire->read() << 8); // high 8 bits
64+
return _dataIn;
65+
}
66+
67+
68+
uint8_t PCA9671::read(const uint8_t pin)
69+
{
70+
if (pin > 15)
71+
{
72+
_error = PCA9671_PIN_ERROR;
73+
return 0;
74+
}
75+
PCA9671::read16();
76+
return (_dataIn & (1 << pin)) > 0;
77+
}
78+
79+
80+
uint16_t PCA9671::value()
81+
{
82+
return _dataIn;
83+
};
84+
85+
86+
void PCA9671::write16(const uint16_t value)
87+
{
88+
_dataOut = value;
89+
_wire->beginTransmission(_address);
90+
_wire->write(_dataOut & 0xFF); // low 8 bits
91+
_wire->write(_dataOut >> 8); // high 8 bits
92+
_error = _wire->endTransmission();
93+
}
94+
95+
96+
void PCA9671::write(const uint8_t pin, const uint8_t value)
97+
{
98+
if (pin > 15)
99+
{
100+
_error = PCA9671_PIN_ERROR;
101+
return;
102+
}
103+
if (value == LOW)
104+
{
105+
_dataOut &= ~(1 << pin);
106+
}
107+
else
108+
{
109+
_dataOut |= (1 << pin);
110+
}
111+
PCA9671::write16(_dataOut);
112+
}
113+
114+
115+
uint16_t PCA9671::valueOut()
116+
{
117+
return _dataOut;
118+
}
119+
120+
121+
void PCA9671::toggle(const uint8_t pin)
122+
{
123+
if (pin > 15)
124+
{
125+
_error = PCA9671_PIN_ERROR;
126+
return;
127+
}
128+
toggleMask(1 << pin);
129+
}
130+
131+
132+
void PCA9671::toggleMask(const uint16_t mask)
133+
{
134+
_dataOut ^= mask;
135+
PCA9671::write16(_dataOut);
136+
}
137+
138+
139+
void PCA9671::shiftRight(const uint8_t n)
140+
{
141+
if ((n == 0) || (_dataOut == 0)) return;
142+
if (n > 15) _dataOut = 0; // shift 15++ clears all, valid...
143+
if (_dataOut != 0) _dataOut >>= n; // only shift if there are bits set
144+
PCA9671::write16(_dataOut);
145+
}
146+
147+
148+
void PCA9671::shiftLeft(const uint8_t n)
149+
{
150+
if ((n == 0) || (_dataOut == 0)) return;
151+
if (n > 15) _dataOut = 0; // shift 15++ clears all, valid...
152+
if (_dataOut != 0) _dataOut <<= n; // only shift if there are bits set
153+
PCA9671::write16(_dataOut);
154+
}
155+
156+
157+
void PCA9671::rotateRight(const uint8_t n)
158+
{
159+
uint8_t r = n & 15;
160+
if (r == 0) return;
161+
_dataOut = (_dataOut >> r) | (_dataOut << (15 - r));
162+
PCA9671::write16(_dataOut);
163+
}
164+
165+
166+
void PCA9671::rotateLeft(const uint8_t n)
167+
{
168+
rotateRight(16 - (n & 15));
169+
}
170+
171+
172+
void PCA9671::reverse() // quite fast
173+
{ // 1 char === 1 bit
174+
uint16_t x = _dataOut; // x = 0123456789ABCDEF
175+
x = (((x & 0xAAAA) >> 1) | ((x & 0x5555) << 1)); // x = 1032547698BADCFE
176+
x = (((x & 0xCCCC) >> 2) | ((x & 0x3333) << 2)); // x = 32107654BA98FEDC
177+
x = (((x & 0xF0F0) >> 4) | ((x & 0x0F0F) << 4)); // x = 76543210FEDCBA98
178+
x = (x >> 8) | ( x << 8); // x = FEDCBA9876543210
179+
PCA9671::write16(x);
180+
}
181+
182+
183+
//////////////////////////////////////////////////
184+
//
185+
// READBUTTON
186+
//
187+
uint16_t PCA9671::readButton16(const uint16_t mask)
188+
{
189+
uint16_t temp = _dataOut;
190+
PCA9671::write16(mask | _dataOut); // read only selected lines
191+
PCA9671::read16();
192+
PCA9671::write16(temp); // restore
193+
return _dataIn;
194+
}
195+
196+
197+
uint16_t PCA9671::readButton16()
198+
{
199+
return readButton16(_buttonMask);
200+
}
201+
202+
203+
uint8_t PCA9671::readButton(const uint8_t pin)
204+
{
205+
if (pin > 15)
206+
{
207+
_error = PCA9671_PIN_ERROR;
208+
return 0;
209+
}
210+
uint16_t temp = _dataOut;
211+
PCA9671::write(pin, HIGH);
212+
uint8_t rtn = PCA9671::read(pin);
213+
PCA9671::write16(temp);
214+
return rtn;
215+
}
216+
217+
218+
void PCA9671::setButtonMask(uint16_t mask)
219+
{
220+
_buttonMask = mask;
221+
};
222+
223+
224+
uint16_t PCA9671::getButtonMask()
225+
{
226+
return _buttonMask;
227+
};
228+
229+
230+
//////////////////////////////////////////////////
231+
//
232+
// SELECT
233+
//
234+
void PCA9671::select(const uint8_t pin)
235+
{
236+
uint16_t n = 0x0000;
237+
if (pin < 16) n = 1L << pin;
238+
PCA9671::write16(n);
239+
};
240+
241+
242+
void PCA9671::selectN(const uint8_t pin)
243+
{
244+
uint16_t n = 0xFFFF;
245+
if (pin < 16) n = (2L << pin) - 1;
246+
PCA9671::write16(n);
247+
};
248+
249+
250+
void PCA9671::selectNone()
251+
{
252+
PCA9671::write16(0x0000);
253+
};
254+
255+
256+
void PCA9671::selectAll()
257+
{
258+
PCA9671::write16(0xFFFF);
259+
};
260+
261+
262+
int PCA9671::lastError()
263+
{
264+
int e = _error;
265+
_error = PCA9671_OK; // reset error after read, is this wise?
266+
return e;
267+
}
268+
269+
270+
// -- END OF FILE --
271+

0 commit comments

Comments
 (0)