microbit-dal/source/MicroBitButton.cpp

103 lines
3.3 KiB
C++
Raw Normal View History

#include "inc/MicroBit.h"
#include "inc/MicroBitButton.h"
#include "inc/MicroBitMessageBus.h"
/**
* Constructor.
* Create a pin representation with the given ID.
* @param id the ID of the new MicroBitButton object.
* @param name the physical pin on the processor that this butotn is connected to.
* @param mode the configuration of internal pullups/pulldowns, as define in the mbed PinMode class. PullNone by default.
*
* Example:
* @code
* buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A); //a number between 0 and 200 inclusive
* @endcode
*
* Possible Events:
* @code
* MICROBIT_BUTTON_EVT_DOWN
* MICROBIT_BUTTON_EVT_UP
* MICROBIT_BUTTON_EVT_CLICK
* MICROBIT_BUTTON_EVT_LONG_CLICK
* MICROBIT_BUTTON_EVT_DOUBLE_CLICK
* MICROBIT_BUTTON_EVT_HOLD
* @endcode
*/
MicroBitButton::MicroBitButton(uint16_t id, PinName name, PinMode mode) : pin(name, mode)
{
this->id = id;
this->name = name;
this->downStartTime = 0;
this->sigma = 0;
this->doubleClickTimer = 0;
uBit.addSystemComponent(this);
}
/**
* periodic callback from MicroBit clock.
* Check for state change for this button, and fires a hold event if button is pressed.
*/
void MicroBitButton::systemTick()
{
//
// If the pin is pulled low (touched), increment our culumative counter.
// otherwise, decrement it. We're essentially building a lazy follower here.
// This makes the output debounced for buttons, and desensitizes touch sensors
// (particularly in environments where there is mains noise!)
//
if(!pin)
{
if (sigma < MICROBIT_BUTTON_SIGMA_MAX)
sigma++;
}
else
{
if (sigma > MICROBIT_BUTTON_SIGMA_MIN)
sigma--;
}
// Check to see if we have off->on state change.
if(sigma > MICROBIT_BUTTON_SIGMA_THRESH_HI && !(status & MICROBIT_BUTTON_STATE))
{
// Record we have a state change, and raise an event.
status |= MICROBIT_BUTTON_STATE;
MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN);
//Record the time the button was pressed.
downStartTime=ticks;
}
// Check to see if we have on->off state change.
if(sigma < MICROBIT_BUTTON_SIGMA_THRESH_LO && (status & MICROBIT_BUTTON_STATE))
{
status = 0;
MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_UP);
//determine if this is a long click or a normal click and send event
if((ticks - downStartTime) >= MICROBIT_BUTTON_LONG_CLICK_TIME)
MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_LONG_CLICK);
else
MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK);
}
//if button is pressed and the hold triggered event state is not triggered AND we are greater than the button debounce value
if((status & MICROBIT_BUTTON_STATE) && !(status & MICROBIT_BUTTON_STATE_HOLD_TRIGGERED) && (ticks - downStartTime) >= MICROBIT_BUTTON_HOLD_TIME)
{
//set the hold triggered event flag
status |= MICROBIT_BUTTON_STATE_HOLD_TRIGGERED;
//fire hold event
MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_HOLD);
}
}
/**
* Tests if this Button is currently pressed.
* @return 1 if this button is pressed, 0 otherwise.
*/
int MicroBitButton::isPressed()
{
return status & MICROBIT_BUTTON_STATE ? 1 : 0;
}