2015-08-12 10:53:41 +00:00
|
|
|
#ifndef MICROBIT_MESSAGE_BUS_H
|
|
|
|
#define MICROBIT_MESSAGE_BUS_H
|
|
|
|
|
|
|
|
#include "mbed.h"
|
2015-08-19 22:35:45 +00:00
|
|
|
#include "MicroBitComponent.h"
|
2015-08-12 10:53:41 +00:00
|
|
|
#include "MicroBitEvent.h"
|
2015-09-11 15:39:38 +00:00
|
|
|
#include "MicroBitListener.h"
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
// Enumeration of core components.
|
|
|
|
#define MICROBIT_CONTROL_BUS_ID 0
|
|
|
|
#define MICROBIT_ID_ANY 0
|
|
|
|
#define MICROBIT_EVT_ANY 0
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Class definition for the MicroBitMessageBus.
|
|
|
|
*
|
|
|
|
* The MicroBitMessageBus is the common mechanism to deliver asynchronous events on the
|
|
|
|
* MicroBit platform. It serves a number of purposes:
|
|
|
|
*
|
|
|
|
* 1) It provides an eventing abstraction that is independent of the underlying substrate.
|
|
|
|
* 2) It provides a mechanism to decouple user code from trusted system code
|
|
|
|
* i.e. the basis of a message passing nano kernel.
|
|
|
|
* 3) It allows a common high level eventing abstraction across a range of hardware types.e.g. buttons, BLE...
|
|
|
|
* 4) It provides a mechanims for extensibility - new devices added via I/O pins can have OO based
|
|
|
|
drivers and communicate via the message bus with minima impact on user level languages.
|
|
|
|
* 5) It allows for the possiblility of event / data aggregation, which in turn can save energy.
|
|
|
|
* It has the following design principles:
|
|
|
|
*
|
|
|
|
* 1) Maintain a low RAM footprint where possible
|
|
|
|
* 2) Make few assumptions about the underlying platform, but allow optimizations where possible.
|
|
|
|
*/
|
2015-08-19 22:35:45 +00:00
|
|
|
class MicroBitMessageBus : public MicroBitComponent
|
2015-08-12 10:53:41 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default constructor.
|
|
|
|
* Anticipating only one MessageBus per device, as filtering is handled within the class.
|
|
|
|
*/
|
|
|
|
MicroBitMessageBus();
|
|
|
|
|
|
|
|
/**
|
2015-08-31 22:25:10 +00:00
|
|
|
* Queues the given event to be sent to all registered recipients.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
2015-08-31 22:25:10 +00:00
|
|
|
* @param The event to send.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
2015-08-31 22:25:10 +00:00
|
|
|
* n.b. THIS IS NOW WRAPPED BY THE MicroBitEvent CLASS FOR CONVENIENCE...
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN,ticks,false);
|
|
|
|
* evt.fire();
|
|
|
|
* //OR YOU CAN DO THIS...
|
|
|
|
* MicroBitEvent evt(id,MICROBIT_BUTTON_EVT_DOWN);
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-08-31 22:25:10 +00:00
|
|
|
void send(MicroBitEvent evt);
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
2015-08-31 22:25:10 +00:00
|
|
|
* Internal function, used to deliver the given event to all relevant recipients.
|
|
|
|
* Normally, this is called once an event has been removed from the event queue.
|
|
|
|
*
|
2015-09-12 10:34:16 +00:00
|
|
|
* IT IS RECOMMENDED THAT ALL EXTERNAL CODE USE THE send() FUNCTIONS INSTEAD OF THIS FUNCTION,
|
|
|
|
* or the constructors provided by MicroBitEvent.
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
2015-08-31 22:25:10 +00:00
|
|
|
* @param evt The event to send.
|
2015-10-31 10:27:38 +00:00
|
|
|
* @param urgent The type of listeners to process (optional). If set to true, only listeners defined as urgent and non-blocking will be processed
|
|
|
|
* otherwise, all other (standard) listeners will be processed.
|
|
|
|
* @return 1 if all matching listeners were processed, 0 if further processing is required.
|
2015-08-12 10:53:41 +00:00
|
|
|
*/
|
2015-10-31 10:27:38 +00:00
|
|
|
int process(MicroBitEvent &evt, bool urgent = false);
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a listener function.
|
|
|
|
*
|
|
|
|
* @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
|
|
|
|
* Use MICROBIT_ID_ANY to receive events from all components.
|
|
|
|
*
|
|
|
|
* @param value The value of messages to listen for. Events with any other values will be filtered.
|
|
|
|
* Use MICROBIT_EVT_ANY to receive events of any value.
|
|
|
|
*
|
2015-10-25 21:51:33 +00:00
|
|
|
* @param handler The function to call when an event is received.
|
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-08-12 10:53:41 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void onButtonBClick()
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); // call function when ever a click event is detected.
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
|
2015-08-12 10:53:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a listener function.
|
|
|
|
*
|
2015-09-10 11:53:39 +00:00
|
|
|
* @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
|
|
|
|
* Use MICROBIT_ID_ANY to receive events from all components.
|
|
|
|
*
|
|
|
|
* @param value The value of messages to listen for. Events with any other values will be filtered.
|
|
|
|
* Use MICROBIT_EVT_ANY to receive events of any value.
|
|
|
|
*
|
|
|
|
* @param hander The function to call when an event is received.
|
2015-10-25 21:51:33 +00:00
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void onButtonBClick(void *arg)
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); // call function when ever a click event is detected.
|
|
|
|
* @endcode
|
2015-08-12 10:53:41 +00:00
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
|
2015-08-12 10:53:41 +00:00
|
|
|
|
2015-09-09 23:04:27 +00:00
|
|
|
/**
|
|
|
|
* Register a listener function.
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
|
|
|
|
* Use MICROBIT_ID_ANY to receive events from all components.
|
|
|
|
*
|
|
|
|
* @param value The value of messages to listen for. Events with any other values will be filtered.
|
|
|
|
* Use MICROBIT_EVT_ANY to receive events of any value.
|
|
|
|
*
|
|
|
|
* @param hander The function to call when an event is received.
|
2015-10-25 21:51:33 +00:00
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void SomeClass::onButtonBClick()
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
2015-09-09 23:04:27 +00:00
|
|
|
*
|
2015-09-10 11:53:39 +00:00
|
|
|
* SomeClass s = new SomeClass();
|
|
|
|
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick);
|
|
|
|
* @endcode
|
2015-09-09 23:04:27 +00:00
|
|
|
*/
|
|
|
|
template <typename T>
|
2015-10-25 21:51:33 +00:00
|
|
|
int listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
|
2015-09-09 23:04:27 +00:00
|
|
|
|
2015-09-10 11:53:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister a listener function.
|
|
|
|
* Listners are identified by the Event ID, Event VALUE and handler registered using listen().
|
|
|
|
*
|
|
|
|
* @param id The Event ID used to register the listener.
|
|
|
|
* @param value The Event VALUE used to register the listener.
|
|
|
|
* @param handler The function used to register the listener.
|
2015-10-25 21:51:33 +00:00
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void onButtonBClick()
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int ignore(int id, int value, void (*handler)(MicroBitEvent));
|
2015-09-10 11:53:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister a listener function.
|
|
|
|
* Listners are identified by the Event ID, Event VALUE and handler registered using listen().
|
|
|
|
*
|
|
|
|
* @param id The Event ID used to register the listener.
|
|
|
|
* @param value The Event VALUE used to register the listener.
|
|
|
|
* @param handler The function used to register the listener.
|
|
|
|
*
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void onButtonBClick(void *arg)
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
|
|
|
|
* @endcode
|
|
|
|
*/
|
2015-10-25 21:51:33 +00:00
|
|
|
int ignore(int id, int value, void (*handler)(MicroBitEvent, void*));
|
2015-09-10 11:53:39 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregister a listener function.
|
|
|
|
* Listners are identified by the Event ID, Event VALUE and handler registered using listen().
|
|
|
|
*
|
|
|
|
* @param id The Event ID used to register the listener.
|
|
|
|
* @param value The Event VALUE used to register the listener.
|
|
|
|
* @param handler The function used to register the listener.
|
|
|
|
*
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
*
|
|
|
|
* void SomeClass::onButtonBClick()
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* SomeClass s = new SomeClass();
|
|
|
|
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick);
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
template <typename T>
|
2015-10-25 21:51:33 +00:00
|
|
|
int ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
|
2015-09-11 15:39:38 +00:00
|
|
|
|
2015-09-28 20:40:44 +00:00
|
|
|
/**
|
|
|
|
* Returns the microBitListener with the given position in our list.
|
|
|
|
* @param n The position in the list to return.
|
|
|
|
* @return the MicroBitListener at postion n in the list, or NULL if the position is invalid.
|
|
|
|
*/
|
|
|
|
MicroBitListener *elementAt(int n);
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
private:
|
2015-09-09 23:04:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add the given MicroBitListener to the list of event handlers, unconditionally.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @param listener The MicroBitListener to add.
|
|
|
|
* @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
|
2015-09-09 23:04:27 +00:00
|
|
|
*/
|
|
|
|
int add(MicroBitListener *newListener);
|
2015-10-25 21:51:33 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove the given MicroBitListener from the list of event handlers.
|
|
|
|
* @param listener The MicroBitListener to remove.
|
|
|
|
* @return MICROBIT_OK if the listener is valid, MICROBIT_INVALID_PARAMETER otherwise.
|
|
|
|
*/
|
2015-09-10 11:53:39 +00:00
|
|
|
int remove(MicroBitListener *newListener);
|
2015-09-09 23:04:27 +00:00
|
|
|
|
2015-10-29 00:08:33 +00:00
|
|
|
/**
|
|
|
|
* Cleanup any MicroBitListeners marked for deletion from the list.
|
|
|
|
* @return The number of listeners removed from the list.
|
|
|
|
*/
|
|
|
|
int deleteMarkedListeners();
|
|
|
|
|
2015-08-19 22:35:45 +00:00
|
|
|
MicroBitListener *listeners; // Chain of active listeners.
|
|
|
|
MicroBitEventQueueItem *evt_queue_head; // Head of queued events to be processed.
|
|
|
|
MicroBitEventQueueItem *evt_queue_tail; // Tail of queued events to be processed.
|
2015-09-11 15:39:38 +00:00
|
|
|
uint16_t nonce_val; // The last nonce issued.
|
2015-10-31 10:27:38 +00:00
|
|
|
uint16_t queueLength; // The number of events currently waiting to be processed.
|
2015-08-19 22:35:45 +00:00
|
|
|
|
|
|
|
void queueEvent(MicroBitEvent &evt);
|
|
|
|
MicroBitEventQueueItem* dequeueEvent();
|
|
|
|
|
|
|
|
virtual void idleTick();
|
|
|
|
virtual int isIdleCallbackNeeded();
|
2015-08-12 10:53:41 +00:00
|
|
|
};
|
|
|
|
|
2015-09-09 23:04:27 +00:00
|
|
|
/**
|
2015-10-26 16:37:12 +00:00
|
|
|
* A registration function to allow C++ member funcitons (methods) to be registered as an event
|
2015-09-09 23:04:27 +00:00
|
|
|
* listener.
|
|
|
|
*
|
|
|
|
* @param id The source of messages to listen for. Events sent from any other IDs will be filtered.
|
|
|
|
* Use MICROBIT_ID_ANY to receive events from all components.
|
|
|
|
*
|
|
|
|
* @param value The value of messages to listen for. Events with any other values will be filtered.
|
|
|
|
* Use MICROBIT_EVT_ANY to receive events of any value.
|
|
|
|
*
|
|
|
|
* @param object The object on which the method should be invoked.
|
2015-10-25 21:51:33 +00:00
|
|
|
* @param handler The method to call when an event is received.
|
|
|
|
*
|
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-09 23:04:27 +00:00
|
|
|
*/
|
|
|
|
template <typename T>
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags)
|
2015-09-09 23:04:27 +00:00
|
|
|
{
|
|
|
|
if (object == NULL || handler == NULL)
|
2015-10-25 21:51:33 +00:00
|
|
|
return MICROBIT_INVALID_PARAMETER;
|
2015-09-09 23:04:27 +00:00
|
|
|
|
2015-09-11 15:39:38 +00:00
|
|
|
MicroBitListener *newListener = new MicroBitListener(id, value, object, handler, flags);
|
2015-09-09 23:04:27 +00:00
|
|
|
|
2015-10-26 16:37:12 +00:00
|
|
|
if(add(newListener) == MICROBIT_OK)
|
|
|
|
return MICROBIT_OK;
|
2015-10-25 21:51:33 +00:00
|
|
|
|
2015-10-26 16:37:12 +00:00
|
|
|
delete newListener;
|
|
|
|
return MICROBIT_NO_RESOURCES;
|
2015-09-09 23:04:27 +00:00
|
|
|
}
|
|
|
|
|
2015-09-10 11:53:39 +00:00
|
|
|
/**
|
|
|
|
* Unregister a listener function.
|
|
|
|
* Listners are identified by the Event ID, Event VALUE and handler registered using listen().
|
|
|
|
*
|
|
|
|
* @param id The Event ID used to register the listener.
|
|
|
|
* @param value The Event VALUE used to register the listener.
|
|
|
|
* @param handler The function used to register the listener.
|
|
|
|
*
|
2015-10-25 21:51:33 +00:00
|
|
|
* @return MICROBIT_OK on success MICROBIT_INVALID_PARAMETER
|
2015-09-10 11:53:39 +00:00
|
|
|
*
|
|
|
|
* Example:
|
|
|
|
* @code
|
|
|
|
* void onButtonBClick(void *arg)
|
|
|
|
* {
|
|
|
|
* //do something
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
|
|
|
|
* @endcode
|
|
|
|
*/
|
|
|
|
template <typename T>
|
2015-10-25 21:51:33 +00:00
|
|
|
int MicroBitMessageBus::ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent))
|
2015-09-10 11:53:39 +00:00
|
|
|
{
|
|
|
|
if (handler == NULL)
|
2015-10-25 21:51:33 +00:00
|
|
|
return MICROBIT_INVALID_PARAMETER;
|
2015-09-10 11:53:39 +00:00
|
|
|
|
|
|
|
MicroBitListener listener(id, value, object, handler);
|
|
|
|
remove(&listener);
|
2015-10-25 21:51:33 +00:00
|
|
|
|
|
|
|
return MICROBIT_OK;
|
2015-09-10 11:53:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-12 10:53:41 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|