microbit: On demand suppression on button click events.

MicroBitMultiButton now provides an indication to MicroBitButton instances when an application is actively utilising that button as part of a button group. This
permits that MicroBitButton to more accurately filter events, and provide a
consistent abstraction.

More specifically, this patch:

 - Extends the MessageBus functionality to indicate when listeners are
   attached to events. This allows components to perform on demand tailoring
   of their behaviour.

 - Extends MicroBitMultiButton to indicate to relevant MicroBitButton
   instances when they are part of a button group.

 - Extends MicroBitButton to perform filtering of button events dynamically
   (rather than statically) when part of a MultiButton group.

 - Code cleanup of static functions that are more cleanly implemented as
   methods.
This commit is contained in:
Joe Finney 2016-02-08 13:31:48 +00:00
parent dda8598513
commit c1ae235ebd
7 changed files with 59 additions and 16 deletions

View file

@ -100,6 +100,10 @@ class MicroBitButton : public MicroBitComponent
* Destructor for MicroBitButton, so that we deregister ourselves as a systemComponent
*/
~MicroBitButton();
private:
void onMultiButtonAttachEvent(MicroBitEvent evt);
};
#endif

View file

@ -46,9 +46,11 @@
#define MICROBIT_ID_THERMOMETER 28
#define MICROBIT_ID_RADIO 29
#define MICROBIT_ID_RADIO_DATA_READY 30
#define MICROBIT_ID_MULTIBUTTON_ATTACH 31
#define MICROBIT_ID_NOTIFY 1023 // Notfication channel, for general purpose synchronisation
#define MICROBIT_ID_NOTIFY_ONE 1022 // Notfication channel, for general purpose synchronisation
#define MICROBIT_ID_MESSAGE_BUS_LISTENER 1021 // Message bus indication that a handler for a given ID has been registered.
#define MICROBIT_ID_NOTIFY_ONE 1022 // Notfication channel, for general purpose synchronisation
#define MICROBIT_ID_NOTIFY 1023 // Notfication channel, for general purpose synchronisation
class MicroBitComponent
{

View file

@ -9,6 +9,7 @@
#define MICROBIT_MULTI_BUTTON_HOLD_TRIGGERED_2 0x08
#define MICROBIT_MULTI_BUTTON_SUPRESSED_1 0X10
#define MICROBIT_MULTI_BUTTON_SUPRESSED_2 0x20
#define MICROBIT_MULTI_BUTTON_ATTACHED 0x40
/**
* Class definition for MicroBitMultiButton.
@ -25,9 +26,11 @@ class MicroBitMultiButton : public MicroBitComponent
int isSubButtonPressed(uint16_t button);
int isSubButtonHeld(uint16_t button);
int isSubButtonSupressed(uint16_t button);
int isListenerAttached();
void setButtonState(uint16_t button, int value);
void setHoldState(uint16_t button, int value);
void setSupressedState(uint16_t button, int value);
void setListenerAttached(int value);
public:
@ -68,8 +71,10 @@ class MicroBitMultiButton : public MicroBitComponent
* @endcode
*/
int isPressed();
void onEvent(MicroBitEvent evt);
private:
void onButtonEvent(MicroBitEvent evt);
void onListenerRegisteredEvent(MicroBitEvent evt);
};
#endif

View file

@ -91,8 +91,8 @@ MicroBit::MicroBit() :
serial(USBTX, USBRX),
MessageBus(),
display(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_WIDTH, MICROBIT_DISPLAY_HEIGHT),
buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A, MICROBIT_BUTTON_SIMPLE_EVENTS),
buttonB(MICROBIT_ID_BUTTON_B,MICROBIT_PIN_BUTTON_B, MICROBIT_BUTTON_SIMPLE_EVENTS),
buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A, MICROBIT_BUTTON_ALL_EVENTS),
buttonB(MICROBIT_ID_BUTTON_B,MICROBIT_PIN_BUTTON_B, MICROBIT_BUTTON_ALL_EVENTS),
buttonAB(MICROBIT_ID_BUTTON_AB,MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B),
accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR),
compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR),

View file

@ -29,6 +29,16 @@ MicroBitButton::MicroBitButton(uint16_t id, PinName name, MicroBitButtonEventCon
this->downStartTime = 0;
this->sigma = 0;
uBit.addSystemComponent(this);
uBit.MessageBus.listen(MICROBIT_ID_MULTIBUTTON_ATTACH, id, this, &MicroBitButton::onMultiButtonAttachEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
}
void MicroBitButton::onMultiButtonAttachEvent(MicroBitEvent evt)
{
(void) evt; // Unused parameter
// This button is now part of a button group. Suppress individual events (such as click) from being generated.
this->eventConfiguration = MICROBIT_BUTTON_SIMPLE_EVENTS;
}
/**

View file

@ -481,6 +481,8 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
if (listeners == NULL)
{
listeners = newListener;
MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);
return MICROBIT_OK;
}
@ -520,6 +522,7 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
p->next = newListener;
}
MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);
return MICROBIT_OK;
}

View file

@ -1,11 +1,5 @@
#include "MicroBit.h"
void
onMultiButtonEvent(MicroBitEvent evt)
{
uBit.buttonAB.onEvent(evt);
}
/**
* Constructor.
* Create a representation of a virtual button, that generates events based upon the combination
@ -35,8 +29,9 @@ MicroBitMultiButton::MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t
this->button1 = button1;
this->button2 = button2;
uBit.MessageBus.listen(button1, MICROBIT_EVT_ANY, onMultiButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
uBit.MessageBus.listen(button2, MICROBIT_EVT_ANY, onMultiButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
uBit.MessageBus.listen(button1, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
uBit.MessageBus.listen(button2, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
uBit.MessageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, id, this, &MicroBitMultiButton::onListenerRegisteredEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
}
uint16_t MicroBitMultiButton::otherSubButton(uint16_t b)
@ -77,6 +72,20 @@ int MicroBitMultiButton::isSubButtonSupressed(uint16_t button)
return 0;
}
int MicroBitMultiButton::isListenerAttached()
{
return status & MICROBIT_MULTI_BUTTON_ATTACHED;
}
void MicroBitMultiButton::setListenerAttached(int value)
{
if (value)
status |= MICROBIT_MULTI_BUTTON_ATTACHED;
else
status &= ~MICROBIT_MULTI_BUTTON_ATTACHED;
}
void MicroBitMultiButton::setButtonState(uint16_t button, int value)
{
if (button == button1)
@ -134,8 +143,18 @@ void MicroBitMultiButton::setSupressedState(uint16_t button, int value)
}
}
void MicroBitMultiButton::onListenerRegisteredEvent(MicroBitEvent evt)
{
(void) evt; // Unused parameter
void MicroBitMultiButton::onEvent(MicroBitEvent evt)
// Simply indicate to the buttons we are tracking that they are now part of a button group.
// As a result, they will suppress some individual events from being generated.
MicroBitEvent(MICROBIT_ID_MULTIBUTTON_ATTACH, button1);
MicroBitEvent(MICROBIT_ID_MULTIBUTTON_ATTACH, button2);
setListenerAttached(1);
}
void MicroBitMultiButton::onButtonEvent(MicroBitEvent evt)
{
int button = evt.source;
int otherButton = otherSubButton(button);
@ -168,7 +187,7 @@ void MicroBitMultiButton::onEvent(MicroBitEvent evt)
setSupressedState(otherButton, 1);
}
else if (!isSubButtonSupressed(button))
else if (!isSubButtonSupressed(button) && isListenerAttached())
{
if (isSubButtonHeld(button))
MicroBitEvent e(button, MICROBIT_BUTTON_EVT_LONG_CLICK);