Skip to content

Commit 1788268

Browse files
authored
Fix #10 add read() and write() for free IO pins (#11)
- Fix #10 - add **read1(pin)** - add **write1(pin, value)** experimental see #10 - made **read8()** and **write8()** public for faster multi pin access - update readme.md
1 parent 7782452 commit 1788268

File tree

7 files changed

+120
-41
lines changed

7 files changed

+120
-41
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

88

9+
## [0.3.0] - 2024-02-14
10+
- Fix #10
11+
- add **read1(pin)**
12+
- add **write1(pin, value)** experimental see #10
13+
- made **read8()** and **write8()** public for faster multi pin access
14+
- update readme.md
15+
16+
----
17+
918
## [0.2.1] - 2024-01-06
1019
- Fix URL in examples
1120
- minor edits

README.md

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,36 +51,59 @@ Returns true if the PCF8574 is on the I2C bus.
5151
- **void readInitialState()** read the initial state of the 4 rotary encoders.
5252
Typically called in setup only, or after a sleep e.g. in combination with **setValue()**
5353
- **bool checkChange()** polling to see if one or more RE have changed,
54-
without updating the counters.
54+
without updating the internal counters.
5555
- **void update()** update the internal counters of the RE.
56-
These will add +1 or -1 depending on direction.
56+
The counters will add +1 or -1 depending on rotation direction.
57+
Need to be called before **getValue()** or before **getKeyPressed()**.
58+
Note that **update()** must be called as soon as possible after the interrupt occurs (or as often as possible when polling).
5759
- **void updateSingle()** update the internal counters of the RE.
58-
This will add +1 +2 or +3 as it assumes that the rotary encoder
60+
This will add +1 +2 or +3 as it assumes that the rotary encoder
5961
only goes into a single direction.
6062

6163

6264
#### Counters
6365

6466
- **uint32_t getValue(uint8_r re)** returns the RE counter.
65-
- **void setValue(uint8_r re, uint32_t value = 0)** (re)set the internal counter to value,
66-
default 0
67+
- **void setValue(uint8_r re, uint32_t value = 0)** (re)set the internal counter to value, default 0
68+
69+
70+
#### Read1 - Write1 - experimental
71+
72+
Warning the **write1(pin, value)** might alter the state of the rotary encoder pins.
73+
So this functionality should be tested thoroughly for your application.
74+
Especially the **write()** is **experimental**, see issue #10, feedback welcome.
75+
76+
77+
**Read1()** and **write1()** are functions to access the pins of the PCF8574 that
78+
are not used for rotary encoders.
79+
The user must guard that especially writing the pins do not interfere with the rotary encoder pins.
80+
81+
- **uint8_t read1(uint8_t pin)** reads a single pin (0..7).
82+
Returns HIGH or LOW.
83+
- **bool write1(uint8_t pin, uint8_t value)** writes a single pin (0..7).
84+
Value should be LOW (0) or HIGH (other values).
85+
- **uint8_t read8()** read all pins in one I2C IO action. When one need to access multiple
86+
input pins this is faster but need some bit masking.
87+
- **bool write8(uint8_t value)** writes to multiple pins at once, e.g. to control multiple
88+
LEDs in one IO action. As said before the user must guard not to interfere with the
89+
rotary encoder pins.
6790

6891

6992
#### Debugging
7093

71-
- **int8_t getLastPosition(uint8_r re)** returns last position.
94+
- **int8_t getLastPosition(uint8_r re)** Returns last position.
7295

7396

7497
## Performance
7598

7699
As the decoder is based upon a PCF8574, a I2C device, the performance is affected by the
77-
clock speed of the I2C bus. All four core functions have one call to **\_read8()** which
78-
is the most expensive part.
100+
clock speed of the I2C bus.
101+
All four core functions have one call to **\read8()** which is the most expensive part.
79102

80103
Early tests gave the following indicative times (Arduino UNO) for the **update()**
81104
function (with no updates it is ~8 us faster).
82-
Note that above 500 KHz the gain becomes less while reliability of signal decreases.
83-
(500 KHz is about ~3x faster than 100 KHz in practice.)
105+
Note that above 500 KHz the gain becomes less while reliability of signal decreases.
106+
(500 KHz is about 3x faster than 100 KHz in practice.)
84107
As 400 KHz is a standard I2C clock speed it is the preferred one.
85108

86109

@@ -95,20 +118,15 @@ As 400 KHz is a standard I2C clock speed it is the preferred one.
95118
| 700 KHz | 73 | 6 | 8% |
96119

97120

98-
At @400KHz it can update 4 rotary encoders in ~100us.
121+
At 400 KHz it can update 4 rotary encoders in ~100us.
99122
At a 50% update percentage this implies a max of about
100-
5000 **update()** calls per second in theory
123+
5000 **update()** calls per second in theory.
101124
**to be tested in practice**
102125

103126
Note that a high speed drill goes up to 30000 RPM = 500 RPS = 2000 interrupts per second,
104127
assuming 4 pulses == 360°. (not tested)
105128

106129

107-
## Operational
108-
109-
See examples..
110-
111-
112130
## Future
113131

114132
#### Must

keywords.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ updateSingle KEYWORD2
1515
getValue KEYWORD2
1616
setValue KEYWORD2
1717

18+
read1 KEYWORD2
19+
write1 KEYWORD2
20+
read8 KEYWORD2
21+
write8 KEYWORD2
22+
1823
getLastPosition KEYWORD2
1924

2025

library.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rotaryDecoder",
3-
"keywords": "rotary,encoder,PCF8574",
4-
"description": "Arduino library to rotary decoder with a PCF8574\nSupports up to 4 RE's",
3+
"keywords": "rotary,encoder,decoder,PCF8574",
4+
"description": "Arduino library for rotary decoder with a PCF8574\nSupports up to 4 rotary encoders.",
55
"authors":
66
[
77
{
@@ -15,7 +15,7 @@
1515
"type": "git",
1616
"url": "https://github.com/RobTillaart/rotaryDecoder.git"
1717
},
18-
"version": "0.2.1",
18+
"version": "0.3.0",
1919
"license": "MIT",
2020
"frameworks": "*",
2121
"platforms": "*",

library.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=rotaryDecoder
2-
version=0.2.1
2+
version=0.3.0
33
author=Rob Tillaart <[email protected]>
44
maintainer=Rob Tillaart <[email protected]>
5-
sentence=Arduino library to rotary decoder with a PCF8574
6-
paragraph=Supports up to 4 RE's
5+
sentence=Arduino library for rotary decoder with a PCF8574.
6+
paragraph=Supports up to 4 rotary encoders.
77
category=Data Processing
88
url=https://github.com/RobTillaart/rotaryDecoder
99
architectures=*

rotaryDecoder.cpp

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//
22
// FILE: rotaryDecoder.cpp
33
// AUTHOR: Rob Tillaart
4-
// VERSION: 0.2.1
4+
// VERSION: 0.3.0
55
// DATE: 2021-05-08
6-
// PURPOSE: rotary decoder library for Arduino
6+
// PURPOSE: Arduino library for rotary decoder
77
// URL: https://github.com/RobTillaart/rotaryDecoder
88

99

@@ -40,7 +40,7 @@ bool rotaryDecoder::isConnected()
4040

4141
void rotaryDecoder::readInitialState()
4242
{
43-
uint8_t value = _read8();
43+
uint8_t value = read8();
4444
_lastValue = value;
4545
for (uint8_t i = 0; i < _count; i++)
4646
{
@@ -52,14 +52,14 @@ void rotaryDecoder::readInitialState()
5252

5353
bool rotaryDecoder::checkChange()
5454
{
55-
uint8_t value = _read8();
55+
uint8_t value = read8();
5656
return (_lastValue != value);
5757
}
5858

5959

6060
bool rotaryDecoder::update()
6161
{
62-
uint8_t value = _read8();
62+
uint8_t value = read8();
6363
if (_lastValue == value)
6464
{
6565
return false;
@@ -93,7 +93,7 @@ bool rotaryDecoder::update()
9393

9494
bool rotaryDecoder::updateSingle()
9595
{
96-
uint8_t value = _read8();
96+
uint8_t value = read8();
9797
if (_lastValue == value)
9898
{
9999
return false;
@@ -143,21 +143,61 @@ void rotaryDecoder::setValue(uint8_t re, int32_t value)
143143
}
144144

145145

146-
uint8_t rotaryDecoder::getLastPosition(uint8_t re)
146+
/////////////////////////////////////////////////////
147+
//
148+
// READ - WRITE interface
149+
//
150+
uint8_t rotaryDecoder::read1(uint8_t pin)
147151
{
148-
return _lastPos[re];
149-
};
152+
uint8_t mask = 1 << pin;
153+
uint8_t tmp = read8();
154+
return (tmp & mask) > 0 ? HIGH : LOW;
155+
}
156+
157+
158+
bool rotaryDecoder::write1(uint8_t pin, uint8_t value)
159+
{
160+
uint8_t mask = 1 << pin;
161+
uint8_t tmp = read8();
162+
if (value == LOW) tmp &= ~mask;
163+
else tmp |= mask;
164+
return write8(tmp);
165+
}
166+
167+
168+
uint8_t rotaryDecoder::read8()
169+
{
170+
_wire->requestFrom(_address, (uint8_t)1);
171+
uint8_t x = _wire->read();
172+
// Serial.println(x, HEX);
173+
return x;
174+
}
175+
176+
177+
bool rotaryDecoder::write8(uint8_t value)
178+
{
179+
_wire->beginTransmission(_address);
180+
_wire->write(value);
181+
return (_wire->endTransmission() == 0);
182+
}
183+
150184

151185
/////////////////////////////////////////////////////
152186
//
153-
// PRIVATE
187+
// DEBUG
154188
//
155-
uint8_t rotaryDecoder::_read8()
189+
uint8_t rotaryDecoder::getLastPosition(uint8_t re)
156190
{
157-
_wire->requestFrom(_address, (uint8_t)1);
158-
return _wire->read();
191+
return _lastPos[re];
159192
}
160193

161194

195+
/////////////////////////////////////////////////////
196+
//
197+
// PROTECTED
198+
//
199+
200+
201+
162202
// -- END OF FILE --
163203

rotaryDecoder.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22
//
33
// FILE: rotaryDecoder.h
44
// AUTHOR: Rob Tillaart
5-
// VERSION: 0.2.1
5+
// VERSION: 0.3.0
66
// DATE: 2021-05-08
7-
// PURPOSE: rotary decoder library for Arduino
7+
// PURPOSE: Arduino library for rotary decoder
88
// URL: https://github.com/RobTillaart/rotaryDecoder
99

1010

1111
#include "Arduino.h"
1212
#include "Wire.h"
1313

14-
#define ROTARY_DECODER_LIB_VERSION (F("0.2.1"))
14+
#define ROTARY_DECODER_LIB_VERSION (F("0.3.0"))
1515

1616

1717
class rotaryDecoder
@@ -37,17 +37,24 @@ class rotaryDecoder
3737
int32_t getValue(uint8_t re);
3838
void setValue(uint8_t re, int32_t value = 0);
3939

40+
41+
// READ - WRITE interface
42+
uint8_t read1(uint8_t pin);
43+
bool write1(uint8_t pin, uint8_t value);
44+
uint8_t read8();
45+
bool write8(uint8_t value);
46+
47+
4048
// DEBUG
4149
uint8_t getLastPosition(uint8_t re);
4250

4351

44-
private:
52+
protected:
4553
uint8_t _count = 0;
4654
uint8_t _lastValue = 0;
4755
uint8_t _lastPos[4] = { 0, 0, 0, 0 };
4856
int32_t _encoder[4] = { 0, 0, 0, 0 };
4957

50-
uint8_t _read8();
5158
uint8_t _address;
5259
TwoWire * _wire;
5360
};

0 commit comments

Comments
 (0)