-
Notifications
You must be signed in to change notification settings - Fork 250
/
Copy pathky040.h
153 lines (125 loc) · 3.86 KB
/
ky040.h
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//
// ky040.h
//
// Circle - A C++ bare metal environment for Raspberry Pi
// Copyright (C) 2022 R. Stange <[email protected]>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#ifndef _sensor_ky040_h
#define _sensor_ky040_h
#include <circle/gpiomanager.h>
#include <circle/gpiopin.h>
#include <circle/timer.h>
#include <circle/types.h>
/// \note This driver supports an interrupt mode and a polling mode.
class CKY040 /// Driver for KY-040 rotary encoder module
{
public:
enum TEvent
{
EventClockwise,
EventCounterclockwise,
EventSwitchDown,
EventSwitchUp,
EventSwitchClick,
EventSwitchDoubleClick,
EventSwitchTripleClick,
EventSwitchHold, ///< generated each second
EventUnknown
};
typedef void TEventHandler (TEvent Event, void *pParam);
public:
/// \param nCLKPin GPIO pin number of clock pin (encoder pin A)
/// \param nDTPin GPIO pin number of data pin (encoder pin B)
/// \param nSWPin GPIO pin number of switch pin
/// \param pGPIOManager Pointer to GPIO manager object (0 enables polling mode)
CKY040 (unsigned nCLKPin, unsigned nDTPin, unsigned nSWPin, CGPIOManager *pGPIOManager = 0);
~CKY040 (void);
/// \brief Operation successful?
boolean Initialize (void);
/// \brief Register a handler, to be called on an event from the encoder
/// \param pHandler Pointer to the handler
/// \param pParam Optional user parameter, handed over to the handler
void RegisterEventHandler (TEventHandler *pHandler, void *pParam = 0);
/// \return Number of seconds, the switch is hold down
/// \note Only valid, when EventSwitchHold has been received.
unsigned GetHoldSeconds (void) const;
/// \brief Has to be called very frequently in polling mode
void Update (void);
private:
enum TState
{
StateStart,
StateCWStart,
StateCWBothLow,
StateCWFirstHigh,
StateCCWStart,
StateCCWBothLow,
StateCCWFirstHigh,
StateInvalid,
StateUnknown
};
enum TSwitchState
{
SwitchStateStart,
SwitchStateDown,
SwitchStateClick,
SwitchStateDown2,
SwitchStateClick2,
SwitchStateDown3,
SwitchStateClick3,
SwitchStateHold,
SwitchStateInvalid,
SwitchStateUnknown
};
enum TSwitchEvent
{
SwitchEventDown,
SwitchEventUp,
SwitchEventTick,
SwitchEventUnknown
};
private:
void HandleSwitchEvent (TSwitchEvent SwitchEvent);
static void EncoderInterruptHandler (void *pParam);
static void SwitchInterruptHandler (void *pParam);
static void SwitchDebounceHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext);
static void SwitchTickHandler (TKernelTimerHandle hTimer, void *pParam, void *pContext);
private:
CGPIOPin m_CLKPin;
CGPIOPin m_DTPin;
CGPIOPin m_SWPin;
boolean m_bPollingMode;
boolean m_bInterruptConnected;
TEventHandler *m_pEventHandler;
void *m_pEventParam;
// encoder
TState m_State;
static TState s_NextState[StateUnknown][2][2];
static TEvent s_Output[StateUnknown][2][2];
// switch low level
TKernelTimerHandle m_hDebounceTimer;
TKernelTimerHandle m_hTickTimer;
unsigned m_nLastSWLevel;
boolean m_bDebounceActive;
unsigned m_nDebounceLastTicks;
// switch higher level
TSwitchState m_SwitchState;
unsigned m_nSwitchLastTicks;
unsigned m_nHoldCounter;
static TSwitchState s_NextSwitchState[SwitchStateUnknown][SwitchEventUnknown];
static TEvent s_SwitchOutput[SwitchStateUnknown][SwitchEventUnknown];
};
#endif