microbit: Aligning MicroBitButton and MicroBitMultiButton APIs

Updates to MicroBitButton and MicroBitMultiButton to align the API through
which CLICK events are filtered. Also, updates to the mechanism through which
buttonA and buttonB CLICK/LONG_CLICK events are filtered by
MicroBitMultiButotn to reduce RAM footprint.

No changes to external behaviour of these classes.
This commit is contained in:
Joe Finney 2016-02-26 15:42:57 +00:00
parent 5ec546980b
commit d3922d21e9
6 changed files with 107 additions and 38 deletions

View file

@ -68,6 +68,7 @@ class MicroBit
private:
void compassCalibrator(MicroBitEvent e);
void onABListenerRegisteredEvent(MicroBitEvent evt);
uint32_t randomValue;
//the current tick period in MS

View file

@ -90,6 +90,25 @@ class MicroBitButton : public MicroBitComponent
*/
int isPressed();
/**
* Changes the event configuraiton of this button to the given value.
* All subsequent events generated by this button will then be informed by this configuraiton.
*
* @param config The new configuration for this button. Legal values are MICROBIT_BUTTON_ALL_EVENTS or MICROBIT_BUTTON_SIMPLE_EVENTS.
*
* Example:
* @code
*
* // Configure a button to generate all possible events.
* uBit.buttonA.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
*
* // Configure a button to suppress MICROBIT_BUTTON_EVT_CLICK and MICROBIT_BUTTON_EVT_LONG_CLICK events.
* uBit.buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
*
* @endcode
*/
void setEventConfiguration(MicroBitButtonEventConfiguration config);
/**
* periodic callback from MicroBit clock.
* Check for state change for this button, and fires a hold event if button is pressed.
@ -100,10 +119,6 @@ class MicroBitButton : public MicroBitComponent
* Destructor for MicroBitButton, so that we deregister ourselves as a systemComponent
*/
~MicroBitButton();
private:
void onMultiButtonAttachEvent(MicroBitEvent evt);
};
#endif

View file

@ -21,16 +21,15 @@ class MicroBitMultiButton : public MicroBitComponent
{
uint16_t button1; // ID of the first button we're monitoring
uint16_t button2; // ID of the second button we're monitoring
MicroBitButtonEventConfiguration eventConfiguration; // Do we want to generate high level event (clicks), or defer this to another service.
uint16_t otherSubButton(uint16_t b);
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:
@ -72,9 +71,36 @@ class MicroBitMultiButton : public MicroBitComponent
*/
int isPressed();
/**
* Changes the event configuraiton of this button to the given value.
* All subsequent events generated by this button will then be informed by this configuraiton.
*
* @param config The new configuration for this button. Legal values are MICROBIT_BUTTON_ALL_EVENTS or MICROBIT_BUTTON_SIMPLE_EVENTS.
*
* Example:
* @code
*
* // Configure a button to generate all possible events.
* uBit.buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
*
* // Configure a button to suppress MICROBIT_BUTTON_EVT_CLICK and MICROBIT_BUTTON_EVT_LONG_CLICK events.
* uBit.buttonAB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
*
* @endcode
*
* Possible Events:
* @code
* MICROBIT_BUTTON_EVT_DOWN
* MICROBIT_BUTTON_EVT_UP
* MICROBIT_BUTTON_EVT_CLICK
* MICROBIT_BUTTON_EVT_LONG_CLICK
* MICROBIT_BUTTON_EVT_HOLD
* @endcode
*/
void setEventConfiguration(MicroBitButtonEventConfiguration config);
private:
void onButtonEvent(MicroBitEvent evt);
void onListenerRegisteredEvent(MicroBitEvent evt);
};
#endif

View file

@ -65,6 +65,23 @@ void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
uBit.ble->startAdvertising();
}
void MicroBit::onABListenerRegisteredEvent(MicroBitEvent evt)
{
(void) evt; // Unused parameter
// A user has registered to receive events from the buttonAB multibutton.
// Disable click events from being generated by ButtonA and ButtonB, and defer the
// control of this to the multibutton handler.
//
// This way, buttons look independent unless a buttonAB is requested, at which
// point button A+B clicks can be correclty handled without breaking
// causal ordering.
buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
buttonB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
}
/**
* Constructor.
@ -141,6 +158,7 @@ void MicroBit::init()
// Register our compass calibration algorithm.
MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CALIBRATE, this, &MicroBit::compassCalibrator, MESSAGE_BUS_LISTENER_IMMEDIATE);
MessageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_ID_BUTTON_AB, this, &MicroBit::onABListenerRegisteredEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
}
/**

View file

@ -29,16 +29,28 @@ 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)
/**
* Changes the event configuraiton of this button to the given value.
* all subsequent events generated by this button will then be informed by this configuration.
*
* @param config the new configuration for this button. legal values are MICROBIT_BUTTON_ALL_EVENTS or MICROBIT_BUTTON_SIMPLE_EVENTS.
*
* example:
* @code
*
* // configure a button to generate all possible events.
* uBit.buttonA.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
*
* // configure a button to suppress MICROBIT_BUTTON_EVT_CLICK and MICROBIT_BUTTON_EVT_LONG_CLICK events.
* uBit.buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
*
* @endcode
*/
void MicroBitButton::setEventConfiguration(MicroBitButtonEventConfiguration config)
{
(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;
this->eventConfiguration = config;
}
/**

View file

@ -28,10 +28,10 @@ MicroBitMultiButton::MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t
this->id = id;
this->button1 = button1;
this->button2 = button2;
this->eventConfiguration = MICROBIT_BUTTON_SIMPLE_EVENTS;
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)
@ -72,20 +72,6 @@ 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)
@ -143,15 +129,26 @@ void MicroBitMultiButton::setSupressedState(uint16_t button, int value)
}
}
void MicroBitMultiButton::onListenerRegisteredEvent(MicroBitEvent evt)
/**
* Changes the event configuraiton of this button to the given value.
* All subsequent events generated by this button will then be informed by this configuration.
*
* @param config the new configuration for this button. legal values are MICROBIT_BUTTON_ALL_EVENTS or MICROBIT_BUTTON_SIMPLE_EVENTS.
*
* example:
* @code
*
* // configure a button to generate all possible events from attached buttons.
* uBit.buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
*
* // configure a button to suppress MICROBIT_BUTTON_EVT_CLICK and MICROBIT_BUTTON_EVT_LONG_CLICK events.
* uBit.buttonAB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
*
* @endcode
*/
void MicroBitMultiButton::setEventConfiguration(MicroBitButtonEventConfiguration config)
{
(void) evt; // Unused parameter
// 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);
this->eventConfiguration = config;
}
void MicroBitMultiButton::onButtonEvent(MicroBitEvent evt)
@ -187,7 +184,7 @@ void MicroBitMultiButton::onButtonEvent(MicroBitEvent evt)
setSupressedState(otherButton, 1);
}
else if (!isSubButtonSupressed(button) && isListenerAttached())
else if (!isSubButtonSupressed(button) && eventConfiguration == MICROBIT_BUTTON_ALL_EVENTS)
{
if (isSubButtonHeld(button))
MicroBitEvent e(button, MICROBIT_BUTTON_EVT_LONG_CLICK);