mirror of
https://github.com/OpenSolo/OpenSolo.git
synced 2025-05-29 13:00:12 +02:00
131 lines
2.8 KiB
C++
131 lines
2.8 KiB
C++
#include "button.h"
|
|
#include "buttonmanager.h"
|
|
#include "board.h"
|
|
|
|
Button::Button(GPIOPin p, GPIOPin active, GPIOPin backlight, Io::ButtonID bid, Polarity pol) :
|
|
pin(p),
|
|
activePin(active),
|
|
backlightPin(backlight),
|
|
polarity(pol),
|
|
btnid(bid),
|
|
pressTimestamp(0),
|
|
releaseTimestamp(0),
|
|
reportedEvents(0)
|
|
{
|
|
}
|
|
|
|
void Button::init(bool enableIsr)
|
|
{
|
|
pin.setControl(GPIOPin::IN_PULL);
|
|
if (polarity == ActiveLow) {
|
|
pin.pullup();
|
|
} else {
|
|
pin.pulldown();
|
|
}
|
|
|
|
if (enableIsr) {
|
|
pin.irqInit();
|
|
pin.irqSetRisingEdge();
|
|
pin.irqSetFallingEdge();
|
|
pin.irqEnable();
|
|
}
|
|
|
|
if (activePin != LED_GPIO_NONE) {
|
|
activePin.setControl(GPIOPin::OUT_2MHZ);
|
|
activePin.setHigh();
|
|
}
|
|
|
|
if (backlightPin != LED_GPIO_NONE) {
|
|
backlightPin.setControl(GPIOPin::OUT_2MHZ);
|
|
backlightPin.setLow();
|
|
}
|
|
}
|
|
|
|
bool Button::isr()
|
|
{
|
|
/*
|
|
* An edge has been detected.
|
|
* Not doing any debounce here - TBD if we'll need to.
|
|
*
|
|
* Called in ISR context.
|
|
*/
|
|
|
|
if (!pin.irqPending()) {
|
|
return false;
|
|
}
|
|
|
|
pin.irqAcknowledge();
|
|
|
|
SysTime::Ticks now = SysTime::now();
|
|
|
|
if (isPressed()) {
|
|
|
|
reportedEvents = 0;
|
|
pressTimestamp = now;
|
|
ButtonManager::dispatchEvt(this, Press);
|
|
|
|
if (now - releaseTimestamp < SysTime::msTicks(DoubleClickGapMillis)) {
|
|
// XXX: dispatch dc on press or release?
|
|
ButtonManager::dispatchEvt(this, DoubleClick);
|
|
}
|
|
|
|
} else {
|
|
releaseTimestamp = now;
|
|
|
|
ButtonManager::dispatchEvt(this, Release);
|
|
if ((releaseTimestamp - pressTimestamp) / SysTime::msTicks(1) < ClickMillis) {
|
|
ButtonManager::dispatchEvt(this, ClickRelease);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
SysTime::Ticks Button::pressDuration() const
|
|
{
|
|
/*
|
|
* Return the current press duration.
|
|
*/
|
|
|
|
if (isPressed()) {
|
|
return SysTime::now() - pressTimestamp;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Button::pollForHold()
|
|
{
|
|
/*
|
|
* Called periodically when a button is pressed,
|
|
* in order to generate hold events.
|
|
*/
|
|
|
|
if (holdSuppressed()) {
|
|
return;
|
|
}
|
|
|
|
SysTime::Ticks duration = pressDuration();
|
|
|
|
if (!shortHoldFlagSet()) {
|
|
if (duration > SysTime::msTicks(ShortHoldMillis)) {
|
|
reportedEvents |= ShortHoldReported;
|
|
ButtonManager::dispatchEvt(this, ShortHold);
|
|
}
|
|
}
|
|
|
|
if (!holdFlagSet()) {
|
|
if (duration > SysTime::msTicks(HoldMillis)) {
|
|
reportedEvents |= HoldReported;
|
|
ButtonManager::dispatchEvt(this, Hold);
|
|
}
|
|
}
|
|
|
|
if (!longHoldFlagSet()) {
|
|
if (duration > SysTime::msTicks(LongHoldMillis)) {
|
|
reportedEvents |= LongHoldReported;
|
|
ButtonManager::dispatchEvt(this, LongHold);
|
|
}
|
|
}
|
|
}
|