Merge branch 'ram-efficient-multibutton'

master
Joe Finney 2016-02-26 16:33:55 +00:00
commit 27ffb0b91c
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);