-
Notifications
You must be signed in to change notification settings - Fork 0
/
debouncer.h
128 lines (105 loc) · 3.56 KB
/
debouncer.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
/* Kabuki Tek Toolkit @version 0.x
@link https://github.com/kabuki-starship/kabuki.toolkit.tek.git
@file /debouncer.h
@author Cale McCollough <https://cookingwithcale.org>
@license Copyright 2014-20 (C) Kabuki Starship (TM) <kabukistarship.com>.
This Source Code Form is subject to the terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not distributed with this file, You can obtain one
at <https://mozilla.org/MPL/2.0/>. */
#pragma once
#include <_config.h>
#ifndef KABUKI_TEK_SENSORS_DEBOUNCER
#define KABUKI_TEK_SENSORS_DEBOUNCER
namespace _ {
/* Dr Marty's switch debounce algorithm for shift registers and GPIO pins.
In order to use this class, simply feed the constructor the address of the
memory you want to store the debounced data too. This allows the debounced
General Purpose Inputs (GPI) and shift register inputs to to be packed into
a single array of bytes so they can be quickly polled.
Be sure to memory align your variables! In the example below, 5 bytes
requires an array of size 8 on a 32-bit MCU, an array of size 6 on an 8-bit
MCU with 16-bit memory addresses.
@code
// 100Hz polling example with one 74HC165 shift register and GPI Port.
#include <mbed.h"
SPI Spi1 (D11, D12, D13);
DigitalOut Spi1CS (D10);
Ticker pollInputsTicker;
PortIn GPIPort (PortA);
CHA InputStates[5];
Debouncer<ISC> GPIPortDebouncer ((ISC*)&InputStates[0]);
Debouncer<CHA> ShiftRegisterDebouncer (&InputStates[4]);
void PollInputsHandler () {
Spi1CS = 1;
CHA shift = ShiftRegisterDebouncer.Debounce (Spi1.write (0));
ISC portA = GPIPortDebouncer.Debounce (GPIPort);
Spi1CS = 0;
}
ISC main () {
pollInputsTicker.attach (&pollInputsHandler, 1.0f / 100.0f);
Spi1.format (8,3);
Spi1.frequency (115200);
while (true) ;
}
@endcode
*/
template <typename T>
class Debouncer {
public:
/* Constructor. */
Debouncer(T* stateAddress)
: one_(0), two_(0), three_(0), state_(stateAddress) {}
/* Debounces the input and returns an XOR of changes.
Using an XOR of the previous state shows you which button states
have changed. */
inline T Debounce(T sample) {
T one = one_, two = two_, three = three_;
T* state = state_;
T previous_state = *state,
current_state =
previous_state & (one | two | three) | (one & two & three);
*state = current_state;
three_ = two;
two_ = one;
one_ = sample;
return previous_state ^ current_state;
}
private:
T one_, //< Sample t - 1.
two_, //< Sample t - 2.
three_; //< Sample t - 3.
T* state_; //< Pointer to the state.
};
} // namespace _
#if 0
#include "Debouncer.h"
#define _BaudRate 115200
//Serial pc (USBTX, USBRX);
SPI Spi1 (D11, D12, D13);
DigitalOut Spi1CS (D10),
RedLED (LED_RED),
GreenLED (LED_GREEN),
BlueLED (LED_BLUE);
PortIn GPIPort (PortA);
void PollInputsHandler () {
Spi1CS = 1;
CHA dataIn = ShiftRegisterDebouncer.debounce (Spi1.write (0));
ISC portA = GPIPortDebouncer.debounce (GPIPort);
if (dataIn & 0b001) RedLED = RedLED == 0?1:0;
if (dataIn & 0b010) GreenLED = GreenLED == 0?1:0;
if (dataIn & 0b100) BlueLED = BlueLED == 0?1:0;
Spi1CS = 0;
printf ("%x%x", dataIn, portA);
}
ISC main () {
static const FPC updateInterval = 0.010f;
PrintLine (" ", '=');
pollInputsTicker.attach (&pollInputsHandler, updateInterval);
RedLED = GreenLED = BlueLED = 1;
Spi1CS = 0;
Spi1.format (8, 3);
Spi1.frequency (_BaudRate);
while (true);
}
#endif
#endif