Skip to content

Commit

Permalink
Add debounceThreshold
Browse files Browse the repository at this point in the history
  • Loading branch information
RobTillaart committed Jul 14, 2024
1 parent fe196f4 commit 2846116
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 45 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.4.1] - 2024-07-14
- update readme.md
- Fix #21, add section to readme.md
- Fix #22, implement **debounceThreshold**
- add constant **I2C_KEYPAD_THRESHOLD**
- update unit test
- minor edits


## [0.4.0] - 2023-11-09
Expand Down
36 changes: 30 additions & 6 deletions I2CKeyPad .cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ I2CKeyPad::I2CKeyPad(const uint8_t deviceAddress, TwoWire *wire)
_address = deviceAddress;
_wire = wire;
_mode = I2C_KEYPAD_4x4;
_debounceThreshold = 0;
_lastRead = 0;
}


Expand All @@ -28,6 +30,16 @@ bool I2CKeyPad::begin()

uint8_t I2CKeyPad::getKey()
{
if (_debounceThreshold > 0)
{
uint32_t now = micros();
if (now - _debounceThreshold < _lastRead)
{
return I2C_KEYPAD_THRESHOLD;
}
_lastRead = now;
}

if (_mode == I2C_KEYPAD_5x3) return _getKey5x3();
if (_mode == I2C_KEYPAD_6x2) return _getKey6x2();
if (_mode == I2C_KEYPAD_8x1) return _getKey8x1();
Expand All @@ -39,7 +51,7 @@ uint8_t I2CKeyPad::getKey()
uint8_t I2CKeyPad::getLastKey()
{
return _lastKey;
};
}


// to check "press any key"
Expand All @@ -61,13 +73,13 @@ bool I2CKeyPad::isConnected()
uint8_t I2CKeyPad::getChar()
{
return _keyMap[getKey()];
};
}


uint8_t I2CKeyPad::getLastChar()
{
return _keyMap[_lastKey];
};
}


void I2CKeyPad::loadKeyMap(char * keyMap)
Expand Down Expand Up @@ -95,6 +107,18 @@ uint8_t I2CKeyPad::getKeyPadMode()
}


void I2CKeyPad::setDebounceThreshold(uint16_t value)
{
_debounceThreshold = value;
}


uint16_t I2CKeyPad::getDebounceThreshold()
{
return _debounceThreshold;
}


//////////////////////////////////////////////////////
//
// PROTECTED
Expand All @@ -118,7 +142,7 @@ uint8_t I2CKeyPad::_read(uint8_t mask)

uint8_t I2CKeyPad::_getKey4x4()
{
// key = row + 4 x col
// key = row + 4 x column
uint8_t key = 0;

// mask = 4 rows as input pull up, 4 columns as output
Expand Down Expand Up @@ -150,7 +174,7 @@ uint8_t I2CKeyPad::_getKey4x4()
// not tested
uint8_t I2CKeyPad::_getKey5x3()
{
// key = row + 5 x col
// key = row + 5 x column
uint8_t key = 0;

// mask = 5 rows as input pull up, 3 columns as output
Expand Down Expand Up @@ -182,7 +206,7 @@ uint8_t I2CKeyPad::_getKey5x3()
// not tested
uint8_t I2CKeyPad::_getKey6x2()
{
// key = row + 6 x col
// key = row + 6 x column
uint8_t key = 0;

// mask = 6 rows as input pull up, 2 columns as output
Expand Down
48 changes: 28 additions & 20 deletions I2CKeyPad.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

#define I2C_KEYPAD_NOKEY 16
#define I2C_KEYPAD_FAIL 17
//
#define I2C_KEYPAD_THRESHOLD 255


// experimental
#define I2C_KEYPAD_4x4 44
Expand All @@ -29,37 +32,42 @@ class I2CKeyPad
I2CKeyPad(const uint8_t deviceAddress, TwoWire *wire = &Wire);

// call Wire.begin() first!
bool begin();
bool begin();

// get raw key's 0..15
uint8_t getKey();
uint8_t getLastKey();
uint8_t getKey();
uint8_t getLastKey();

bool isPressed();
bool isConnected();
bool isPressed();
bool isConnected();

// get 'translated' keys
// user must load KeyMap, there is no check.
uint8_t getChar();
uint8_t getLastChar();
void loadKeyMap(char * keyMap); // char[19]
uint8_t getChar();
uint8_t getLastChar();
void loadKeyMap(char * keyMap); // char[19]

// mode functions - experimental
void setKeyPadMode(uint8_t mode = I2C_KEYPAD_4x4);
uint8_t getKeyPadMode();
void setKeyPadMode(uint8_t mode = I2C_KEYPAD_4x4);
uint8_t getKeyPadMode();

// value in microseconds, max 65535 us
void setDebounceThreshold(uint16_t value = 0);
uint16_t getDebounceThreshold();


protected:
uint8_t _address;
uint8_t _lastKey;
uint8_t _mode;
uint8_t _read(uint8_t mask);
uint8_t _getKey4x4();

// experimental - could be public ?!
uint8_t _getKey5x3();
uint8_t _getKey6x2();
uint8_t _getKey8x1();
uint8_t _address;
uint8_t _lastKey;
uint8_t _mode;
uint8_t _read(uint8_t mask);
uint16_t _debounceThreshold;
uint32_t _lastRead;

uint8_t _getKey4x4();
uint8_t _getKey5x3();
uint8_t _getKey6x2();
uint8_t _getKey8x1();

TwoWire* _wire;

Expand Down
52 changes: 34 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,18 @@ See the conceptual schema below.
It might take some trying to get the correct pins connected.

```
PROC PCF8574 KEYPAD
+--------+ +--------+ +--------+
| | | 0|----------|R |
| SDA |--------| 1|----------|O |
| SCL |--------| 2|----------|W |
| | | 3|----------|S |
| | | | | |
| | | 4|----------|C |
| | | 5|----------|O |
| | | 6|----------|L |
| | | 7|----------|S |
+--------+ +--------+ +--------+
PROC PCF8574 KEYPAD
+--------+ +---------+ +---------+
| | | 0 |<-------->| R |
| SDA |<------>| 1 |<-------->| O |
| SCL |------->| 2 |<-------->| W |
| | | 3 |<-------->| S |
| | | | | |
| | | 4 |<-------->| C |
| | | 5 |<-------->| O |
| | | 6 |<-------->| L |
| | | 7 |<-------->| S |
+--------+ +---------+ +---------+
```


Expand All @@ -65,6 +65,8 @@ These devices are identical in behaviour although there are two distinct address
| PCF8574 | 0x20 to 0x27 | same range as PCF8575 ! |
| PCF8574A | 0x38 to 0x3F |

Be careful to select an unique I2C address for every device on the bus.


### I2C multiplexing

Expand Down Expand Up @@ -156,14 +158,33 @@ It is even possible to change the mapping runtime after each key.
Note: a keyMap char array may be longer than 18 characters, but only the first 18 are used.
The length is **NOT** checked upon loading.

Note: The 5x3, 6x2 and the 8x1 modi also uses a keymap of length 18.
Note: The 5x3, 6x2 and the 8x1 modi also uses a key map of length 18.


### Debouncing threshold

**Experimental** since version 0.4.1, the library implements a debounce threshold.
If a key bounces, it can trigger multiple interrupts, while the purpose is to
act like only one keypress. The debounce threshold prevents reading a key too fast. The default value of the threshold is zero to be backwards compatible.
The value is set in microseconds, with a maximum of 65535 ~65 milliseconds,
which is about 16 keys per second.

// value in microseconds, max 65535 us
- **void setDebounceThreshold(uint16_t value = 0)** set the threshold,
default to zero to reset its value.
- **uint16_t getDebounceThreshold()** return the set threshold.

If a debounce threshold is set, and **getKey()** is called too fast,
it will return **I2C_KEYPAD_THRESHOLD**.


### Basic working

After the **keypad.begin()** the sketch calls the **keyPad.getKey()** to read values from the keypad.
- If no key is pressed **I2CKEYPAD_NOKEY** code (16) is returned.
- If the read value is not valid, e.g. two keys pressed, **I2CKEYPAD_FAIL** code (17) is returned.
- If a debounce threshold is set, **I2C_KEYPAD_THRESHOLD** might be returned.
See section above.
- Otherwise a number 0..15 is returned.

Note NOKEY and FAIL bot have bit 4 set, all valid keys don't.
Expand All @@ -180,11 +201,6 @@ This makes checking the keypad far more efficient as one does not need to poll o
See examples.


## Operation

See examples


## Future

#### Must
Expand Down
17 changes: 17 additions & 0 deletions test/unit_test_001.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ unittest(test_constants)
{
assertEqual(16, I2C_KEYPAD_NOKEY);
assertEqual(17, I2C_KEYPAD_FAIL);
assertEqual(255, I2C_KEYPAD_THRESHOLD);

assertEqual(44, I2C_KEYPAD_4x4);
assertEqual(53, I2C_KEYPAD_5x3);
Expand Down Expand Up @@ -100,6 +101,22 @@ unittest(test_KeyMap)
}


unittest(test_debounce_threshold)
{
const uint8_t KEYPAD_ADDRESS = 0x38;
I2CKeyPad keyPad(KEYPAD_ADDRESS);

// default 0
assertEqual(0, keyPad.getDebounceThreshold());

for (uint16_t th = 5000; th < 60000; th += 5000)
{
keyPad.setDebounceThreshold(th);
assertEqual(th, keyPad.getDebounceThreshold());
}
}


// Issues with Wire - to be investigated...
//
// unittest(test_read)
Expand Down

0 comments on commit 2846116

Please sign in to comment.