Repository navigation
Expand file tree
/
Copy pathPCF8574KeyIn.h
More file actions
122 lines (105 loc) · 3.59 KB
/
Copy pathPCF8574KeyIn.h
File metadata and controls
122 lines (105 loc) · 3.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* -*- C++ -*- */
/**************
todo: write description
available keys from 0 to 7 correspond with pcf8574 input pins from p0 to p7
example:
#include <menuIO/PCF8574KeyIn.h>
#define K_UP 0
#define K_RIGHT 1
#define K_LEFT 2
#define K_DOWN 3
#define K_ESC 4
#define K_ENTER 5
keyMap myBtn_map[]={
{K_UP,options->getCmdChar(upCmd)},
{K_RIGHT,options->getCmdChar(rightCmd)},
{K_LEFT,options->getCmdChar(leftCmd)},
{K_DOWN,options->getCmdChar(downCmd)},
{K_ESC,options->getCmdChar(escCmd)},
{K_ENTER,options->getCmdChar(enterCmd)}
};
PCF8574KeyIn<6> myButton(myBtn_map,Wire);
***/
#ifndef __PCF8574KeyIn_h__
#define __PCF8574KeyIn_h__
#include "../menuDefs.h"
#include <Wire.h>
namespace Menu {
#include "keyMapDef.h"
#ifndef BOUNCE_TICK
#define BOUNCE_TICK 30
#endif
//if you hold/repeat a key for this ammount of time we will consider it an escape
#ifndef ESCAPE_TIME
#define ESCAPE_TIME 1500
#endif
//emulate a stream keyboard, this is not using interrupts as a good driver should do
// AND is not using a buffer either!
template <int N,int _dev=0x20> //default pcf8574 address=0x20
class PCF8574KeyIn:public menuIn {
private:
bool modeEdit;
public:
keyMap* keys;
TwoWire& dev;
int lastkey;
unsigned long pressMills=0;
PCF8574KeyIn(keyMap k[],TwoWire& dev=Wire):keys(k),dev(dev),lastkey(-1) {}
void setFieldMode(bool mode) override {
modeEdit = mode;
}
int available(void) {
int ch=peek();
if (lastkey==-1) {
lastkey=ch;
pressMills=millis();
}
else if (ch == -1 && millis()-pressMills < BOUNCE_TICK)
{
lastkey = -1; //released = it's bounce. reset lastkey
return 0;
}
else if (ch != -1 && millis()-pressMills > BOUNCE_TICK) return 1;
else if (ESCAPE_TIME&&millis()-pressMills>ESCAPE_TIME) return 1;
if (ch==lastkey) return 0;
return 1;
}
int peek(void) {
//MENU_DEBUG_OUT<<"peek"<<endl;
dev.requestFrom(_dev, 1);
uint8_t val = dev.read();
for(int n=0;n<N;n++) {
int8_t pin = keys[n].pin;
int8_t code = keys[n].code;
if (((val)&1<<pin)==0) {
//MENU_DEBUG_OUT<<"key "<<pin<<" pressed"<<endl;
if (modeEdit == false && (code == options->getCmdChar(upCmd) || navCmds(code) == options->getCmdChar(downCmd))) {
//if we navigate on menu then return code up/down (left/right) reversed as down/up (right/left)
return (code==options->getCmdChar(upCmd)?options->getCmdChar(downCmd):options->getCmdChar(upCmd));
}
else
{
//else if we inside edit field then return all key codes as is
return code;
}
}
}
return -1;
}
int read() {
//MENU_DEBUG_OUT<<"read"<<endl;
int ch=peek();
if (ch==lastkey) return -1;
int tmp=lastkey;
bool longPress=ESCAPE_TIME&&millis()-pressMills>ESCAPE_TIME;
//MENU_DEBUG_OUT<<"read lastkey="<<lastkey<<" ch="<<ch<<endl;
//MENU_DEBUG_OUT<<"down time:"<<millis()-pressMills<<endl;
pressMills=millis();
lastkey=ch;
return longPress?options->getCmdChar(escCmd):tmp;//long press will result in escape
}
void flush() {}
size_t write(uint8_t v) {return 0;}
};
}//namespace Menu
#endif