-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChatterButton.cpp
139 lines (115 loc) · 3.48 KB
/
ChatterButton.cpp
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
/*!
* The MIT License (MIT)
* Copyright (c) 2022 0xdeb <[email protected]>
*/
#include "ChatterButton.h"
#if defined(ARDUINO)
#include <arduino.h>
#else
#include <chrono>
#endif
namespace {
unsigned long milliseconds() {
#if defined(ARDUINO)
return millis();
#else
auto timePoint = std::chrono::steady_clock::now();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(timePoint.time_since_epoch()).count();
return millis;
#endif
}
}
BaseChatterButton::BaseChatterButton(CButtonWire connect) : previousStateDuration{0} {
closeOnGND = (CButtonWire::GND == connect);
set(false);
}
BaseChatterButton::~BaseChatterButton() {}
void BaseChatterButton::set(bool state) {
if (state != this->state) {
previousStateDuration = getStateDuration();
lastChangeTime = milliseconds();
}
this->state = state;
wireChangeTime = 0;
wireAverage = 0;
hasChange = false;
}
bool BaseChatterButton::didChange() {
return hasChange;
}
unsigned long BaseChatterButton::getStateDuration() const {
return milliseconds() - lastChangeTime;
}
unsigned long BaseChatterButton::getPreviousStateDuration() const {
return previousStateDuration;
}
//=====================================================================
ChatterButton::ChatterButton(CButtonWire connect) : BaseChatterButton(connect) {}
ChatterButton::operator bool() {
hasChange = false;
return state;
}
void ChatterButton::update(bool highLevel) {
unsigned long time = milliseconds();
bool lastHighLevel = false;
if ((state && !closeOnGND) || (!state && closeOnGND)) {
lastHighLevel = true;
}
if (wireChangeTime == 0 && highLevel != lastHighLevel) {
wireChangeTime = time;
}
else if (wireChangeTime != 0) {
wireAverage += highLevel ? 1 : -1;
if (time - wireChangeTime > kChatterTimeMs) {
bool newState = (wireAverage > 0 && !closeOnGND) || (wireAverage < 0 && closeOnGND);
if (wireAverage == 0 || newState == state) {
set(state);
} else {
set(newState);
hasChange = true;
if (handlerFn) handlerFn(newState);
}
}
}
}
void ChatterButton::setHandler(ButtonStateHandler handler) {
handlerFn = handler;
}
//=====================================================================
ChatterINTButton::ChatterINTButton(CButtonWire connect) : BaseChatterButton(connect), isReady{true}, currentHighLevel{false}
{}
void ChatterINTButton::updateIfNeeded() {
if (wireChangeTime == 0) return;
unsigned long time = milliseconds();
if (time - wireChangeTime > kChatterTimeMs) {
isReady = true;
bool newState = currentHighLevel == !closeOnGND;
if (newState != state) {
set(newState);
hasChange = true;
} else {
set(state);
}
}
}
ChatterINTButton::operator bool() {
updateIfNeeded();
hasChange = false;
return state;
}
bool ChatterINTButton::didChange() {
updateIfNeeded();
return BaseChatterButton::didChange();
}
void ChatterINTButton::update(bool highLevel) {
unsigned long time = milliseconds();
bool stateHighLevel = false;
if ((state && !closeOnGND) || (!state && closeOnGND)) {
stateHighLevel = true;
}
if (highLevel != stateHighLevel) {
wireChangeTime = time;
isReady = false;
}
currentHighLevel = highLevel;
}