rusEFI
The most advanced open source ECU
hw_layer
debounce.cpp
Go to the documentation of this file.
1
/**
2
* @file debounce.cpp
3
* @brief Generic button debounce class
4
*
5
* @date Aug 31, 2020
6
* @author David Holdeman, (c) 2020
7
*/
8
#include "
pch.h
"
9
10
#include "
debounce.h
"
11
#include "
hardware.h
"
12
13
ButtonDebounce
*
ButtonDebounce::s_firstDebounce
=
nullptr
;
14
15
ButtonDebounce::ButtonDebounce
(
const
char
*name)
16
: m_name(name)
17
{
18
}
19
20
/**
21
We need to have a separate init function because we do not have the pin or mode in the context in which the class is originally created
22
*/
23
void
ButtonDebounce::init
(
efitimems_t
threshold,
brain_pin_e
&
pin
,
pin_input_mode_e
&mode,
bool
inverted) {
24
// we need to keep track of whether we have already been initialized due to the way unit tests run.
25
if
(!
isInstanceRegisteredInGlobalList
) {
26
// Link us to the list that is used to track ButtonDebounce instances, so that when the configuration changes,
27
// they can be looped through and updated.
28
nextDebounce
=
s_firstDebounce
;
29
s_firstDebounce
=
this
;
30
}
31
m_threshold
= MS2NT(threshold);
32
m_pin
= &
pin
;
33
m_mode
= &mode;
34
m_inverted
= inverted;
35
startConfiguration
();
36
isInstanceRegisteredInGlobalList
=
true
;
37
}
38
39
void
ButtonDebounce::stopConfigurationList
() {
40
ButtonDebounce
*listItem =
s_firstDebounce
;
41
int
loopLimitCounter = 0;
42
while
(listItem !=
nullptr
) {
43
criticalAssertVoid(loopLimitCounter++ < 10000,
"dead stopConfigurationList?"
);
44
listItem->
stopConfiguration
();
45
listItem = listItem->
nextDebounce
;
46
}
47
}
48
49
void
ButtonDebounce::startConfigurationList
() {
50
ButtonDebounce
*listItem =
s_firstDebounce
;
51
int
loopLimitCounter = 0;
52
while
(listItem !=
nullptr
) {
53
criticalAssertVoid(loopLimitCounter++ < 10000,
"dead startConfigurationList?"
);
54
listItem->
startConfiguration
();
55
listItem = listItem->
nextDebounce
;
56
}
57
}
58
59
void
ButtonDebounce::stopConfiguration
() {
60
// If the configuration has changed
61
#if ! EFI_ACTIVE_CONFIGURATION_IN_FLASH
62
if
(*
m_pin
!=
active_pin
|| *
m_mode
!=
active_mode
) {
63
#else
64
if
(*
m_pin
!=
active_pin
|| *
m_mode
!=
active_mode
|| (
isActiveConfigurationVoid
&& ((
int
)(*
m_pin
) != 0 || (
int
)(*
m_mode
) != 0))) {
65
#endif
/* EFI_ACTIVE_CONFIGURATION_IN_FLASH */
66
#if EFI_PROD_CODE
67
efiSetPadUnused
(
active_pin
);
68
#endif
/* EFI_UNIT_TEST */
69
needsPinInitialization
=
true
;
70
}
71
}
72
73
void
ButtonDebounce::startConfiguration
() {
74
#if EFI_PROD_CODE
75
if
(
needsPinInitialization
) {
76
efiSetPadMode
(
m_name
, *
m_pin
,
getInputMode
(*
m_mode
));
77
needsPinInitialization
=
false
;
78
}
79
#endif
80
active_pin
= *
m_pin
;
81
active_mode
= *
m_mode
;
82
}
83
84
/**
85
@returns true if the button is pressed, and will not return true again within the set timeout
86
*/
87
bool
ButtonDebounce::readPinEvent
() {
88
storedValue
=
readPinState2
(
false
);
89
return
storedValue
;
90
}
91
92
bool
ButtonDebounce::getPhysicalState
() {
93
#if EFI_PROD_CODE || EFI_UNIT_TEST
94
return
efiReadPin
(
active_pin
) ^
m_inverted
;
95
#else
96
return
false
;
97
#endif
98
}
99
100
bool
ButtonDebounce::readPinState2
(
bool
valueWithinThreshold) {
101
if
(!
isBrainPinValid
(*
m_pin
)) {
102
return
false
;
103
}
104
efitick_t timeNowNt =
getTimeNowNt
();
105
// If it's been less than the threshold since we were last called
106
if
(
timeLast
.getElapsedNt(timeNowNt) <
m_threshold
) {
107
return
valueWithinThreshold;
108
}
109
bool
value =
getPhysicalState
();
110
// efiPrintf("[debounce] %s value %d", m_name, value);
111
// Invert
112
if
(
active_mode
== PI_PULLUP) {
113
value = !value;
114
// efiPrintf("[debounce] %s inverted %d", m_name, value);
115
}
116
if
(value) {
117
timeLast
.reset();
118
}
119
return
value;
120
}
121
122
bool
ButtonDebounce::readPinState
() {
123
// code comment could be out of date:
124
// storedValue is a class variable, so it needs to be reset.
125
// We don't actually need it to be a class variable in this method,
126
// but when a method is implemented to actually get the pin's state,
127
// for example to implement long button presses, it will be needed.
128
storedValue
=
readPinState2
(
storedValue
);
129
return
storedValue
;
130
}
131
132
void
ButtonDebounce::debug
() {
133
ButtonDebounce
*listItem =
s_firstDebounce
;
134
while
(listItem !=
nullptr
) {
135
#if EFI_PROD_CODE || EFI_UNIT_TEST
136
efiPrintf(
"%s timeLast %f"
, listItem->
m_name
, listItem->
timeLast
.getElapsedSeconds());
137
efiPrintf(
"physical pin state %d"
, listItem->
getPhysicalState
());
138
efiPrintf(
"state %d"
, listItem->
storedValue
);
139
efiPrintf(
"mode %d"
, listItem->
active_mode
);
140
#endif
141
142
listItem = listItem->
nextDebounce
;
143
}
144
}
145
146
void
initButtonDebounce
() {
147
#if !EFI_UNIT_TEST
148
addConsoleAction
(
"debounce"
,
ButtonDebounce::debug
);
149
#endif
/* EFI_UNIT_TEST */
150
}
efiSetPadMode
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
Definition:
bootloader_main.cpp:131
ButtonDebounce
Definition:
debounce.h:15
ButtonDebounce::stopConfiguration
void stopConfiguration()
Definition:
debounce.cpp:59
ButtonDebounce::isInstanceRegisteredInGlobalList
bool isInstanceRegisteredInGlobalList
Definition:
debounce.h:43
ButtonDebounce::active_mode
pin_input_mode_e active_mode
Definition:
debounce.h:40
ButtonDebounce::m_name
const char *const m_name
Definition:
debounce.h:34
ButtonDebounce::storedValue
bool storedValue
Definition:
debounce.h:41
ButtonDebounce::m_mode
pin_input_mode_e * m_mode
Definition:
debounce.h:39
ButtonDebounce::startConfiguration
void startConfiguration()
ButtonDebounce::readPinEvent
bool readPinEvent()
ButtonDebounce::timeLast
Timer timeLast
Definition:
debounce.h:36
ButtonDebounce::init
void init(efitimems_t threshold, brain_pin_e &pin, pin_input_mode_e &mode, bool inverted=false)
Definition:
debounce.cpp:23
ButtonDebounce::getPhysicalState
bool getPhysicalState()
ButtonDebounce::ButtonDebounce
ButtonDebounce(const char *name)
Definition:
debounce.cpp:15
ButtonDebounce::active_pin
brain_pin_e active_pin
Definition:
debounce.h:38
ButtonDebounce::readPinState2
bool readPinState2(bool valueWithinThreshold)
ButtonDebounce::debug
static void debug()
ButtonDebounce::startConfigurationList
static void startConfigurationList()
Definition:
debounce.cpp:49
ButtonDebounce::s_firstDebounce
static ButtonDebounce * s_firstDebounce
Definition:
debounce.h:46
ButtonDebounce::nextDebounce
ButtonDebounce * nextDebounce
Definition:
debounce.h:45
ButtonDebounce::stopConfigurationList
static void stopConfigurationList()
Definition:
debounce.cpp:39
ButtonDebounce::needsPinInitialization
bool needsPinInitialization
Definition:
debounce.h:44
ButtonDebounce::m_threshold
efidur_t m_threshold
Definition:
debounce.h:35
ButtonDebounce::m_pin
brain_pin_e * m_pin
Definition:
debounce.h:37
ButtonDebounce::m_inverted
bool m_inverted
Definition:
debounce.h:42
ButtonDebounce::readPinState
bool readPinState()
addConsoleAction
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
Definition:
cli_registry.cpp:89
Gpio
Gpio
Definition:
rusefi_hw_enums.h:14
debounce.h
Generic button debounce class https://en.wikipedia.org/wiki/Switch#Contact_bounce If we don't 'deboun...
initButtonDebounce
void initButtonDebounce()
getTimeNowNt
efitick_t getTimeNowNt()
Definition:
efitime.cpp:19
isActiveConfigurationVoid
bool isActiveConfigurationVoid
Definition:
engine_configuration.cpp:86
hardware.h
getInputMode
iomode_t getInputMode(pin_input_mode_e mode)
Definition:
io_pins.cpp:103
efiReadPin
bool efiReadPin(brain_pin_e pin)
Definition:
io_pins.cpp:89
efiSetPadUnused
void efiSetPadUnused(brain_pin_e brainPin)
Definition:
io_pins.cpp:20
pch.h
isBrainPinValid
bool isBrainPinValid(brain_pin_e brainPin)
Definition:
pin_repository.cpp:25
pin_input_mode_e
pin_input_mode_e
Definition:
rusefi_enums.h:247
efitimems_t
uint32_t efitimems_t
Definition:
rusefi_types.h:44
pin
brain_pin_e pin
Definition:
stm32_adc.cpp:15
Generated on Wed Oct 9 2024 00:08:03 for rusEFI by
1.9.1