0.3.1 I2CKeyPad8x8

This commit is contained in:
Rob Tillaart 2024-09-29 09:49:52 +02:00
parent 27e7621c92
commit f3b7324bd4
6 changed files with 95 additions and 35 deletions

View File

@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.3.1] - 2024-09-26
- update documentation, errors and more
- fix **isPressed()** to handle I2C communication error as no key pressed.
- update comments.
## [0.3.0] - 2024-07-15 ## [0.3.0] - 2024-07-15
- sync with I2CKeyPad 0.5.0 - sync with I2CKeyPad 0.5.0
- implement **debounceThreshold** - implement **debounceThreshold**

View File

@ -1,7 +1,7 @@
// //
// FILE: I2CKeyPad8x8.cpp // FILE: I2CKeyPad8x8.cpp
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.3.0 // VERSION: 0.3.1
// PURPOSE: Arduino library for 8x8 or smaller KeyPad connected to an I2C PCF8575. // PURPOSE: Arduino library for 8x8 or smaller KeyPad connected to an I2C PCF8575.
// URL: https://github.com/RobTillaart/I2CKeyPad8x8 // URL: https://github.com/RobTillaart/I2CKeyPad8x8
@ -64,8 +64,9 @@ uint8_t I2CKeyPad8x8::getLastKey()
bool I2CKeyPad8x8::isPressed() bool I2CKeyPad8x8::isPressed()
{ {
uint16_t a = _read(0xFF00); uint16_t a = _read(0xFF00);
if (a == 0xFF00) return false; if (a == 0xFF00) return false; // NO KEY
return (a != 0xFF00); if (a == 0xFFFF) return false; // I2C ERROR
return true; // 1 or more keys pressed.
} }
@ -124,7 +125,7 @@ uint16_t I2CKeyPad8x8::_read(uint16_t mask)
_wire->write(mask & 0xFF); _wire->write(mask & 0xFF);
if (_wire->endTransmission() != 0) if (_wire->endTransmission() != 0)
{ {
// set communication error // set I2C communication error
return 0xFFFF; return 0xFFFF;
} }
_wire->requestFrom(_address, (uint8_t)2); _wire->requestFrom(_address, (uint8_t)2);
@ -141,7 +142,6 @@ uint8_t I2CKeyPad8x8::_getKey8x8()
// mask = 8 rows as input pull up, 8 columns as output // mask = 8 rows as input pull up, 8 columns as output
uint16_t rows = _read(0xFF00); uint16_t rows = _read(0xFF00);
// check if single line has gone low. // check if single line has gone low.
if (rows == 0xFF00) return I2C_KEYPAD8x8_NOKEY; if (rows == 0xFF00) return I2C_KEYPAD8x8_NOKEY;
else if (rows == 0xFE00) key = 0; else if (rows == 0xFE00) key = 0;
@ -168,7 +168,8 @@ uint8_t I2CKeyPad8x8::_getKey8x8()
else if (cols == 0x007F) key += 56; else if (cols == 0x007F) key += 56;
else return I2C_KEYPAD8x8_FAIL; else return I2C_KEYPAD8x8_FAIL;
return key; // 0..65 // return single key pressed 0..63
return key;
} }

View File

@ -2,7 +2,7 @@
// //
// FILE: I2CKeyPad8x8.h // FILE: I2CKeyPad8x8.h
// AUTHOR: Rob Tillaart // AUTHOR: Rob Tillaart
// VERSION: 0.3.0 // VERSION: 0.3.1
// PURPOSE: Arduino library for 8x8 or smaller KeyPad connected to an I2C PCF8575. // PURPOSE: Arduino library for 8x8 or smaller KeyPad connected to an I2C PCF8575.
// URL: https://github.com/RobTillaart/I2CKeyPad // URL: https://github.com/RobTillaart/I2CKeyPad
@ -11,12 +11,13 @@
#include "Wire.h" #include "Wire.h"
#define I2C_KEYPAD8x8_LIB_VERSION (F("0.3.0")) #define I2C_KEYPAD8x8_LIB_VERSION (F("0.3.1"))
#define I2C_KEYPAD8x8_NOKEY 64 #define I2C_KEYPAD8x8_NOKEY 64
#define I2C_KEYPAD8x8_FAIL 65 #define I2C_KEYPAD8x8_FAIL 65
#define I2C_KEYPAD8x8_THRESHOLD 255 #define I2C_KEYPAD8x8_THRESHOLD 255
class I2CKeyPad8x8 class I2CKeyPad8x8
{ {
public: public:
@ -26,7 +27,7 @@ public:
bool begin(); bool begin();
bool isConnected(); bool isConnected();
// get raw key's 0..65 // get raw key's 0..63, 64, 65
uint8_t getKey(); uint8_t getKey();
uint8_t getLastKey(); uint8_t getLastKey();
bool isPressed(); bool isPressed();

View File

@ -16,10 +16,11 @@ Arduino library for 8x8 or smaller KeyPad connected to an I2C PCF8575.
## Description ## Description
EXPERIMENTAL (first tests ==> OK) **Experimental** (first tests ==> OK)
The I2CKeyPad8x8 library implements the reading of a 8x8 keypad by means of a PCF8575. The I2CKeyPad8x8 library implements the reading of a 8x8 keypad by means
Smaller keypads, meaning less columns or rows (e.g. 5x4) can be read with it too. of a PCF8575. Smaller keypads, meaning less columns or rows (e.g. 5x4)
can be read with it too.
### Breaking change ### Breaking change
@ -30,11 +31,12 @@ can return **I2C_KEYPAD_THRESHOLD** (255).
### Related ### Related
Relates strongly to https://github.com/RobTillaart/I2CKeyPad. which is an 4x4 version using **PCF8574**. Relates strongly to https://github.com/RobTillaart/I2CKeyPad. which is
an 4x4 version using **PCF8574**.
- https://github.com/RobTillaart/PCF8575 - https://github.com/RobTillaart/PCF8575
- https://github.com/RobTillaart/AnalogKeypad - https://github.com/RobTillaart/AnalogKeypad
- https://github.com/RobTillaart/I2CKeyPad4x4 - https://github.com/RobTillaart/I2CKeyPad
- https://github.com/RobTillaart/I2CKeyPad8x8 - https://github.com/RobTillaart/I2CKeyPad8x8
@ -102,29 +104,55 @@ too if they are behind the multiplexer.
- **I2CKeyPad8x8(const uint8_t deviceAddress, TwoWire \*wire = &Wire)** - **I2CKeyPad8x8(const uint8_t deviceAddress, TwoWire \*wire = &Wire)**
The constructor sets the device address and optionally The constructor sets the device address and optionally
allows to selects the I2C bus to use. allows to selects the I2C bus to use.
- **bool begin()** The return value shows if the PCF8575 with the given address is connected properly. - **bool begin()** The return value shows if the PCF8575 with the given
address is connected properly.
Call wire.begin() first! Call wire.begin() first!
- **bool isConnected()** returns false if the PCF8575 cannot be connected to. - **bool isConnected()** returns false if the PCF8575 cannot be connected to.
### getKey
- **uint8_t getKey()** Returns default 0..63 for regular keys, - **uint8_t getKey()** Returns default 0..63 for regular keys,
Returns **I2C_KEYPAD8X8_NOKEY** (64) if no key is pressed and and **I2C_KEYPAD8X8_FAIL** Returns **I2C_KEYPAD8X8_NOKEY** (64) if no key is pressed and and **I2C_KEYPAD8X8_FAIL**
(17) in case of an error, e.g. multiple keys pressed. (65) in case of an error, e.g. multiple keys pressed.
If a debounce delay is set, it might return **I2C_KEYPAD8X8_THRESHOLD** if called too fast. If a debounce delay is set (see below), it will return **I2C_KEYPAD8X8_THRESHOLD** (255)
- **uint8_t getLastKey()** Returns the last **valid** key pressed 0..63, or **I2C_KEYPAD8X8_NOKEY** (64) which is also the initial value. if the function is called too fast.
- **bool isPressed()** Returns true if one or more keys of the keyPad are pressed, - **uint8_t getLastKey()** Returns the last **valid** key pressed 0..63, or **I2C_KEYPAD8X8_NOKEY**
however there is no check if multiple keys are pressed. (64) which is also the initial value.
This function does not "cache" failed keys.
- **bool isPressed()** Returns true if one or more keys of the keyPad are pressed.
Note there is no check if multiple keys are pressed or just one.
Returns false if no key is pressed or when there is a communication error.
So checking **getKey()** yourself will give more information, but is slightly slower.
| getKey() | HEX code | Meaning | Notes |
|:----------:|:------------:|:--------------------------|:--------|
| 0..63 | 0x00..0x3F | valid key pressed |
| 64 | 0x40 | I2C_KEYPAD8X8_NOKEY |
| 65 | 0x41 | I2C_KEYPAD8X8_FAIL | multi key or I2C communication error.
| 255 | 0xFF | I2C_KEYPAD8X8_THRESHOLD |
### KeyMap functions ### KeyMap functions
Note: **loadKeyMap()** must be called before **getChar()** and **getLastChar()**! Note: **loadKeyMap()** must be called before **getChar()** and **getLastChar()**
can be used!
- **char getChar()** returns the char corresponding to mapped key pressed. - **char getChar()** returns the char corresponding to mapped key pressed.
It returns **I2C_KEYPAD_THRESHOLD** if called too fast. The function returns **I2C_KEYPAD_THRESHOLD** (255) if called too fast and a debounce threshold is set.
- **char getLastChar()** returns the last char pressed. - **char getLastChar()** returns the last char pressed.
This function is not affected by the debounce threshold. This function is not affected by the debounce threshold.
- **bool loadKeyMap(char \* keyMap)** keyMap should point to a (global) char array of length 66. - **bool loadKeyMap(char \* keyMap)** keyMap should point to a (global) char array of length 67.
This array maps index 0..63 on a char and index \[64\] maps to **I2CKeyPad8x8_NOKEY** (typical 'N') This array maps index 0..63 on a character and index \[64\] maps to **I2CKeyPad8x8_NOKEY** (typical 'N')
and index \[65\] maps **I2CKeyPad8x8_FAIL** (typical 'F'). index 66 is the null char. and index \[65\] maps **I2CKeyPad8x8_FAIL** (typical 'F'). Index 66 is the null char.
This allows to define a keymap as a null terminated char array, e.g.
```cpp
char keymap = "1234567890...NF"; // ... stands for 50+ more chars.
kp8.loadKeyMap(keymap);
```
**WARNING** **WARNING**
@ -135,6 +163,8 @@ If there is no key map loaded the user should **NOT** call **getChar()** or
Note: a keyMap char array may be longer than 66 characters, but only the first 66 are used. Note: a keyMap char array may be longer than 66 characters, but only the first 66 are used.
The length is **NOT** checked upon loading (as it may contain a NULL char). The length is **NOT** checked upon loading (as it may contain a NULL char).
See also future section below.
### Debouncing threshold ### Debouncing threshold
@ -172,14 +202,15 @@ Feedback welcome!
### Basic working ### Basic working
After the **keypad.begin()** the sketch calls the **keyPad.getKey()** to read values from the keypad. After the **keypad.begin()** the sketch calls the **keyPad.getKey()** to read values from the keypad.
- If no key is pressed **I2C_KEYPAD8x8_NOKEY** code (16) is returned. - If no key is pressed **I2C_KEYPAD8x8_NOKEY** code (64) is returned.
- If the read value is not valid, e.g. two keys pressed, **I2C_KEYPAD8x8_FAIL** code (17) is returned. - If the read value is not valid, e.g. two keys pressed, **I2C_KEYPAD8x8_FAIL** code (65) is returned.
- If a debounce threshold is set, **I2C_KEYPAD8x8_THRESHOLD** might be returned. - If a debounce threshold is set, **I2C_KEYPAD8x8_THRESHOLD** (255) might be returned.
See section above. See section above.
- Otherwise a number 0..63 is returned. - Otherwise a number 0..63 is returned.
Note NOKEY and FAIL both have bit 8 set, all valid keys don't. Note **I2C_KEYPAD8x8_NOKEY**, **I2C_KEYPAD8x8_FAIL** and **I2C_KEYPAD8x8_THRESHOLD**, all are 64 or
This allows fast checking for valid keys. beyond, all valid keys are below 64.
This allows easy and fast checking for validity of keys.
Only if a key map is loaded, the user can call **getChar()** and **getLastChar()** to get mapped keys. Only if a key map is loaded, the user can call **getChar()** and **getLastChar()** to get mapped keys.
@ -188,7 +219,20 @@ Only if a key map is loaded, the user can call **getChar()** and **getLastChar()
The library enables the PCF8575 to generate interrupts on the PCF8575 when a key is pressed. The library enables the PCF8575 to generate interrupts on the PCF8575 when a key is pressed.
This makes checking the keypad far more efficient as one does not need to poll the device over I2C. This makes checking the keypad far more efficient as one does not need to poll the device over I2C.
See examples. See examples (TODO).
## Smaller keypads
If one wants to connect a smaller keyPad e.g. a 4x4 to the PCF8575, one need to be
sure to have the rows on P00..P07 and the columns on P10..P17 (or P08..P15).
This library does not support the usage of the "not used" pins, when connecting a
smaller keypad than 8x8.
In issue #7 an idea is proposed to use the https://github.com/RobTillaart/I2CKeyPad
with a PCF8575. It proposes to connect a 4x4 keypad to the P00..P07 pins.
Warning: this idea is not confirmed to work yet, feedback is welcome.
## Future ## Future
@ -201,15 +245,24 @@ See examples.
#### Should #### Should
- test extensively - test extensively
- basic working (OK)
- interrupts - interrupts
- keymapping - keymapping
- performance - performance
- improve error handling? - improve error handling
- **I2C_KEYPAD_ERR_MODE** - **I2C_KEYPAD_ERR_MODE**
- **I2C_KEYPAD_ERR_COMM** (66?) or map to **I2C_KEYPAD_FAIL**?
#### Could #### Could
- add examples
- from https://github.com/RobTillaart/I2CKeyPad?
- KeyMap
- checking if NULL? ==> FAIL, how?
- checking length of keymap during load.
- default ASCII map (32..96?)
- in PROGMEM?
- add **uint8_t getAddress()**
#### Wont #### Wont

View File

@ -15,7 +15,7 @@
"type": "git", "type": "git",
"url": "https://github.com/RobTillaart/I2CKeyPad8x8.git" "url": "https://github.com/RobTillaart/I2CKeyPad8x8.git"
}, },
"version": "0.3.0", "version": "0.3.1",
"license": "MIT", "license": "MIT",
"frameworks": "*", "frameworks": "*",
"platforms": "*", "platforms": "*",

View File

@ -1,5 +1,5 @@
name=I2CKeyPad8x8 name=I2CKeyPad8x8
version=0.3.0 version=0.3.1
author=Rob Tillaart <rob.tillaart@gmail.com> author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com> maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for a 8x8 (or smaller) keypad connected to an I2C PCF8575. sentence=Arduino library for a 8x8 (or smaller) keypad connected to an I2C PCF8575.