microbit: Merge branch 'master' into ble-profile

Pulled in changes from MessageBusExtensions to support development of ble profiles.
This commit is contained in:
Joe Finney 2015-09-15 15:17:21 +01:00
commit 037ef999eb
33 changed files with 993 additions and 346 deletions

View file

@ -48,19 +48,6 @@ Then you should **try** to build using the following command:
yt build
```
For GCC, you will have to swap the CortexContextSwitch.s file with the file CortexContextSwitch.s.gcc which will be located in `/yotta_modules/microbit-dal/source`. For an example of how to do this, look below:
```
#first rename the existing one
mv yotta_modules/microbit-dal/source/CortexContextSwitch.s yotta_modules/microbit-dal/source/CortexContextSwitch.s.armcc
#then rename gcc version so that it is included by cmake
mv yotta_modules/microbit-dal/source/CortexContextSwitch.s.gcc yotta_modules/microbit-dal/source/CortexContextSwitch.s
```
This is a temporary measure until Yotta supports assembly preprocessing for armcc.
**NOTE:
To build the final hex files for the micro:bit, you will need to install the srec which can be installed via brew (`brew install srecord`), or you can install it manually from [here](http://srecord.sourceforge.net/).**

View file

@ -0,0 +1,77 @@
#ifndef MEMBER_FUNCTION_CALLBACK_H
#define MEMBER_FUNCTION_CALLBACK_H
#include "mbed.h"
#include "MicroBitEvent.h"
/**
* Class definition for a MemberFunctionCallback.
*
* C++ member functions (also known as methods) have a more complex
* representation than normal C functions. This allows a referene to
* a C++ member function to be stored then called at a later date.
*
* This class is used extensively by the MicroBitMessageBus to deliver
* events to C++ methods.
*/
class MemberFunctionCallback
{
private:
void* object;
uint32_t method[4];
void (*invoke)(void *object, uint32_t *method, MicroBitEvent e);
template <typename T> static void methodCall(void* object, uint32_t*method, MicroBitEvent e);
public:
/**
* Constructor. Creates a MemberFunctionCallback based on a pointer to given method.
* @param object The object the callback method should be invooked on.
* @param method The method to invoke.
*/
template <typename T> MemberFunctionCallback(T* object, void (T::*method)(MicroBitEvent e));
/**
* Comparison of two MemberFunctionCallback objects.
* @return TRUE if the given MemberFunctionCallback is equivalent to this one. FALSE otherwise.
*/
bool operator==(const MemberFunctionCallback &mfc);
/**
* Calls the method reference held by this MemberFunctionCallback.
* @param e The event to deliver to the method
*/
void fire(MicroBitEvent e);
};
/**
* Constructor. Creates a representation of a pointer to a C++ member function (method).
* @param object The object the callback method should be invooked on.
* @param method The method to invoke.
*/
template <typename T>
MemberFunctionCallback::MemberFunctionCallback(T* object, void (T::*method)(MicroBitEvent e))
{
this->object = object;
memclr(this->method, sizeof(this->method));
memcpy(this->method, &method, sizeof(method));
invoke = &MemberFunctionCallback::methodCall<T>;
}
/**
* Template to create static methods capable of invoking a C++ member function (method)
* based on the given paramters.
*/
template <typename T>
void MemberFunctionCallback::methodCall(void *object, uint32_t *method, MicroBitEvent e)
{
T* o = (T*)object;
void (T::*m)(MicroBitEvent);
memcpy(&m, method, sizeof(m));
(o->*m)(e);
}
#endif

View file

@ -2,31 +2,34 @@
#define MICROBIT_H
#include "mbed.h"
#include "MicroBitConfig.h"
#include "MicroBitPanic.h"
#include "ErrorNo.h"
#include "MicroBitConfig.h"
#include "MicroBitHeapAllocator.h"
#include "MicroBitPanic.h"
#include "ErrorNo.h"
#include "MicroBitCompat.h"
#include "MicroBitFiber.h"
#include "MicroBitComponent.h"
#include "ManagedType.h"
#include "ManagedString.h"
#include "MicroBitImage.h"
#include "MicroBitFont.h"
#include "MicroBitImage.h"
#include "MicroBitEvent.h"
#include "MicroBitMessageBus.h"
#include "DynamicPwm.h"
#include "MicroBitComponent.h"
#include "MicroBitI2C.h"
#include "MicroBitSerial.h"
#include "MESEvents.h"
#include "MicroBitButton.h"
#include "MicroBitMultiButton.h"
#include "MicroBitDisplay.h"
#include "MicroBitPin.h"
#include "MicroBitIO.h"
#include "MicroBitCompass.h"
#include "MicroBitAccelerometer.h"
#include "MicroBitMultiButton.h"
#include "MicroBitSerial.h"
#include "MicroBitIO.h"
#include "MicroBitDisplay.h"
#include "MicroBitFiber.h"
#include "MicroBitMessageBus.h"
#include "ble/BLE.h"
#include "ble/services/DeviceInformationService.h"
@ -44,38 +47,6 @@
// Random number generator
#define NRF51822_RNG_ADDRESS 0x4000D000
#define MICROBIT_IO_PINS 20
// Enumeration of core components.
#define MICROBIT_ID_BUTTON_A 1
#define MICROBIT_ID_BUTTON_B 2
#define MICROBIT_ID_BUTTON_RESET 3
#define MICROBIT_ID_ACCELEROMETER 4
#define MICROBIT_ID_COMPASS 5
#define MICROBIT_ID_DISPLAY 6
//EDGE connector events
#define MICROBIT_ID_IO_P0 7 //P0 is the left most pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P1 8 //P1 is the middle pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P2 9 //P2 is the right most pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P3 10 //COL1 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P4 11 //BTN_A
#define MICROBIT_ID_IO_P5 12 //COL2 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P6 13 //ROW2
#define MICROBIT_ID_IO_P7 14 //ROW1
#define MICROBIT_ID_IO_P8 15 //PIN 18
#define MICROBIT_ID_IO_P9 16 //ROW3
#define MICROBIT_ID_IO_P10 17 //COL3 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P11 18 //BTN_B
#define MICROBIT_ID_IO_P12 19 //PIN 20
#define MICROBIT_ID_IO_P13 20 //SCK
#define MICROBIT_ID_IO_P14 21 //MISO
#define MICROBIT_ID_IO_P15 22 //MOSI
#define MICROBIT_ID_IO_P16 23 //PIN 16
#define MICROBIT_ID_IO_P19 24 //SCL
#define MICROBIT_ID_IO_P20 25 //SDA
#define MICROBIT_ID_BUTTON_AB 26 // Button A+B multibutton
// mBed pin assignments of core components.
#define MICROBIT_PIN_SDA P0_30

View file

@ -2,6 +2,7 @@
#define MICROBIT_ACCELEROMETER_H
#include "mbed.h"
#include "MicroBitComponent.h"
/**
* Relevant pin assignments

View file

@ -2,6 +2,8 @@
#define MICROBIT_BUTTON_H
#include "mbed.h"
#include "MicroBitComponent.h"
#include "MicroBitEvent.h"
//TODO: When platform is built for MB2 - pins will be defined by default, these will change...
#define MICROBIT_PIN_BUTTON_A P0_17

View file

@ -2,6 +2,7 @@
#define MICROBIT_COMPASS_H
#include "mbed.h"
#include "MicroBitComponent.h"
/**
* Relevant pin assignments

View file

@ -8,6 +8,41 @@
* If it's in the systemTick queue, you should override systemTick and implement the required functionality.
* Similarly if the component is in the idleTick queue, the idleTick member function should be overridden.
*/
// Enumeration of core components.
#define MICROBIT_ID_BUTTON_A 1
#define MICROBIT_ID_BUTTON_B 2
#define MICROBIT_ID_BUTTON_RESET 3
#define MICROBIT_ID_ACCELEROMETER 4
#define MICROBIT_ID_COMPASS 5
#define MICROBIT_ID_DISPLAY 6
//EDGE connector events
#define MICROBIT_IO_PINS 20
#define MICROBIT_ID_IO_P0 7 //P0 is the left most pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P1 8 //P1 is the middle pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P2 9 //P2 is the right most pad (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P3 10 //COL1 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P4 11 //BTN_A
#define MICROBIT_ID_IO_P5 12 //COL2 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P6 13 //ROW2
#define MICROBIT_ID_IO_P7 14 //ROW1
#define MICROBIT_ID_IO_P8 15 //PIN 18
#define MICROBIT_ID_IO_P9 16 //ROW3
#define MICROBIT_ID_IO_P10 17 //COL3 (ANALOG/DIGITAL)
#define MICROBIT_ID_IO_P11 18 //BTN_B
#define MICROBIT_ID_IO_P12 19 //PIN 20
#define MICROBIT_ID_IO_P13 20 //SCK
#define MICROBIT_ID_IO_P14 21 //MISO
#define MICROBIT_ID_IO_P15 22 //MOSI
#define MICROBIT_ID_IO_P16 23 //PIN 16
#define MICROBIT_ID_IO_P19 24 //SCL
#define MICROBIT_ID_IO_P20 25 //SDA
#define MICROBIT_ID_BUTTON_AB 26 // Button A+B multibutton
#define MICROBIT_ID_ALERT 27 // Alert channel, used for general purpose condition synchronisation and alerting.
class MicroBitComponent
{
protected:

View file

@ -77,6 +77,19 @@
#define FIBER_TICK_PERIOD_MS 6
#endif
//
// Message Bus:
// Default behaviour for event handlers, if not specified in the listen() call
//
// Permissable values are:
// MESSAGE_BUS_LISTENER_REENTRANT
// MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY
// MESSAGE_BUS_LISTENER_DROP_IF_BUSY
// MESSAGE_BUS_LISTENER_NONBLOCKING
#ifndef MESSAGE_BUS_LISTENER_DEFAULT_FLAGS
#define MESSAGE_BUS_LISTENER_DEFAULT_FLAGS MESSAGE_BUS_LISTENER_REENTRANT
#endif
//
// Core micro:bit services

View file

@ -1,8 +1,8 @@
#ifndef MICROBIT_DFU_SERVICE_H
#define MICROBIT_DFU_SERVICE_H
#include "MicroBit.h"
#include "mbed.h"
#include "ble/BLE.h"
// MicroBit ControlPoint OpCodes
// Requests transfer to the Nordic DFU bootloader.

View file

@ -63,7 +63,10 @@
#define MICROBIT_DISPLAY_ANIMATE_DEFAULT_POS -255
#include "mbed.h"
#include "MicroBit.h"
#include "ManagedString.h"
#include "MicroBitComponent.h"
#include "MicroBitImage.h"
#include "MicroBitFont.h"
enum AnimationMode {
ANIMATION_MODE_NONE,
@ -102,6 +105,7 @@ class MicroBitDisplay : public MicroBitComponent
uint8_t mode;
uint8_t greyscaleBitMsk;
uint8_t timingCount;
uint16_t nonce;
Timeout renderTimer;
MicroBitFont font;
@ -217,7 +221,7 @@ class MicroBitDisplay : public MicroBitComponent
* Broadcasts an event onto the shared MessageBus
* @param eventCode The ID of the event that has occurred.
*/
void sendEvent(uint16_t eventcode);
void sendAnimationCompleteEvent();
public:

View file

@ -1,7 +1,16 @@
#ifndef MICROBIT_EVENT_H
#define MICROBIT_EVENT_H
#include "MicroBit.h"
#include "mbed.h"
enum MicroBitEventLaunchMode
{
CREATE_ONLY,
CREATE_AND_QUEUE,
CREATE_AND_FIRE
};
#define MICROBIT_EVENT_DEFAULT_LAUNCH_MODE CREATE_AND_QUEUE
/**
* Class definition for a MicrobitEvent
@ -22,15 +31,24 @@ class MicroBitEvent
* Constructor.
* @param src ID of the MicroBit Component that generated the event e.g. MICROBIT_ID_BUTTON_A.
* @param value Component specific code indicating the cause of the event.
* @param fire whether the event should be fire immediately upon construction
* @param mode optional definition of how the event should be processed after construction (if at all):
*
* CREATE_ONLY: MicroBitEvent is initialised, and no further processing takes place.
* CREATE_AND_QUEUE: MicroBitEvent is initialised, and queued on the MicroBitMessageBus.
* CREATE_AND_FIRE: MicroBitEvent is initialised, and its event handlers are immediately fired (not suitable for use in interrupts!).
*
* Example:
* Example: Create and launch an event using the default configuration
* @code
* MicrobitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK,true); // auto fire
* MicrobitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK);
* @endcode
*
* Example: Create and launch an event and process all registered event handlers immediately.
* @code
* MicrobitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK,CREATE_AND_FIRE);
* @endcode
*/
MicroBitEvent(uint16_t source, uint16_t value, bool fire = true);
MicroBitEvent(uint16_t source, uint16_t value, MicroBitEventLaunchMode mode = MICROBIT_EVENT_DEFAULT_LAUNCH_MODE);
/**
* Default constructor - initialises all values, and sets timestamp to the current time.
@ -38,12 +56,32 @@ class MicroBitEvent
MicroBitEvent();
/**
* Fires the represented event onto the message bus.
* Fires the represented event onto the message bus using the default configuration.
*/
void fire();
/**
* Fires the represented event onto the message bus.
* @param mode Configuration of how the event is processed.
*/
void fire(MicroBitEventLaunchMode mode);
};
/**
* Enclosing class to hold a chain of events.
*/
struct MicroBitEventQueueItem
{
MicroBitEvent evt;
MicroBitEventQueueItem *next;
/**
* Constructor.
* Creates a new MicroBitEventQueueItem.
* @param evt The event that is to be queued.
*/
MicroBitEventQueueItem(MicroBitEvent evt);
};
#endif

View file

@ -1,7 +1,7 @@
#ifndef MICROBIT_EVENT_SERVICE_H
#define MICROBIT_EVENT_SERVICE_H
#include "MicroBit.h"
#include "MicroBitEvent.h"
// UUIDs for our service and characteristics
extern const uint8_t MicroBitEventServiceUUID[];

View file

@ -12,7 +12,7 @@
#include "mbed.h"
#include "MicroBitConfig.h"
#include "MicroBitMessageBus.h"
#include "MicroBitEvent.h"
// TODO: Consider a split mode scheduler, that monitors used stack size, and maintains a dedicated, persistent
// stack for any long lived fibers with large stack

View file

@ -1,8 +1,6 @@
#include "MicroBit.h"
#ifndef MICROBIT_I2C_H
#define MICROBIT_I2C_H
#include "MicroBitComponent.h"
#include "mbed.h"
#define MICROBIT_I2C_MAX_RETRIES 9

View file

@ -2,6 +2,7 @@
#define MICROBIT_IO_H
#include "mbed.h"
#include "MicroBitComponent.h"
#include "MicroBitPin.h"
/**
@ -37,15 +38,13 @@ class MicroBitIO
* Constructor.
* Create a representation of all given I/O pins on the edge connector
*/
MicroBitIO(int MICROBIT_ID_IO_P0, int MICROBIT_ID_IO_P1, int MICROBIT_ID_IO_P2,
int MICROBIT_ID_IO_P3, int MICROBIT_ID_IO_P4, int MICROBIT_ID_IO_P5,
int MICROBIT_ID_IO_P6, int MICROBIT_ID_IO_P7, int MICROBIT_ID_IO_P8,
int MICROBIT_ID_IO_P9, int MICROBIT_ID_IO_P10,int MICROBIT_ID_IO_P11,
int MICROBIT_ID_IO_P12,int MICROBIT_ID_IO_P13,int MICROBIT_ID_IO_P14,
int MICROBIT_ID_IO_P15,int MICROBIT_ID_IO_P16,int MICROBIT_ID_IO_P19,
int MICROBIT_ID_IO_P20);
MicroBitIO(int ID_P0, int ID_P1, int ID_P2,
int ID_P3, int ID_P4, int ID_P5,
int ID_P6, int ID_P7, int ID_P8,
int ID_P9, int ID_P10,int ID_P11,
int ID_P12,int ID_P13,int ID_P14,
int ID_P15,int ID_P16,int ID_P19,
int ID_P20);
};
#endif

97
inc/MicroBitListener.h Normal file
View file

@ -0,0 +1,97 @@
#ifndef MICROBIT_LISTENER_H
#define MICROBIT_LISTENER_H
#include "mbed.h"
#include "MicroBitEvent.h"
#include "MemberFunctionCallback.h"
// MessageBusListener flags...
#define MESSAGE_BUS_LISTENER_PARAMETERISED 0x0001
#define MESSAGE_BUS_LISTENER_METHOD 0x0002
#define MESSAGE_BUS_LISTENER_BUSY 0x0004
#define MESSAGE_BUS_LISTENER_REENTRANT 0x0008
#define MESSAGE_BUS_LISTENER_QUEUE_IF_BUSY 0x0010
#define MESSAGE_BUS_LISTENER_DROP_IF_BUSY 0x0020
#define MESSAGE_BUS_LISTENER_NONBLOCKING 0x0040
struct MicroBitListener
{
uint16_t id; // The ID of the component that this listener is interested in.
uint16_t value; // Value this listener is interested in receiving.
uint16_t flags; // Status and configuration options codes for this listener.
union
{
void (*cb)(MicroBitEvent);
void (*cb_param)(MicroBitEvent, void *);
MemberFunctionCallback *cb_method;
};
void* cb_arg; // Optional argument to be passed to the caller.
MicroBitEvent evt;
MicroBitEventQueueItem *evt_queue;
MicroBitListener *next;
/**
* Constructor.
* Create a new Message Bus Listener.
* @param id The ID of the component you want to listen to.
* @param value The event ID you would like to listen to from that component
* @param handler A function pointer to call when the event is detected.
*/
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Alternative constructor where we register a value to be passed to the
* callback.
*/
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent, void *), void* arg, uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Constructor.
* Create a new Message Bus Listener, with a callback to a c++ member function.
* @param id The ID of the component you want to listen to.
* @param value The event ID you would like to listen to from that component.
* @param object The C++ object on which to call the event handler.
* @param object The method within the C++ object to call.
*/
template <typename T>
MicroBitListener(uint16_t id, uint16_t value, T* object, void (T::*method)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Destructor. Ensures all resources used by this listener are freed.
*/
~MicroBitListener();
/**
* Queues and event up to be processed.
* @param e The event to queue
*/
void queue(MicroBitEvent e);
};
/**
* Constructor.
* Create a new Message Bus Listener, with a callback to a c++ member function.
* @param id The ID of the component you want to listen to.
* @param value The event ID you would like to listen to from that component.
* @param object The C++ object on which to call the event handler.
* @param object The method within the C++ object to call.
*/
template <typename T>
MicroBitListener::MicroBitListener(uint16_t id, uint16_t value, T* object, void (T::*method)(MicroBitEvent), uint16_t flags)
{
this->id = id;
this->value = value;
this->cb_method = new MemberFunctionCallback(object, method);
this->cb_arg = NULL;
this->flags = flags | MESSAGE_BUS_LISTENER_METHOD;
this->next = NULL;
}
#endif

View file

@ -8,6 +8,8 @@
#ifndef MICROBIT_MATRIX_MAPS_H
#define MICROBIT_MATRIX_MAPS_H
#include "mbed.h"
#include "MicroBitDisplay.h"
/**
* Provides the mapping from Matrix ROW/COL to a linear X/Y buffer.
* It's arranged such that matrixMap[col, row] provides the [x,y] screen co-ord.

View file

@ -4,52 +4,13 @@
#include "mbed.h"
#include "MicroBitComponent.h"
#include "MicroBitEvent.h"
#include "MicroBitListener.h"
// Enumeration of core components.
#define MICROBIT_CONTROL_BUS_ID 0
#define MICROBIT_ID_ANY 0
#define MICROBIT_EVT_ANY 0
struct MicroBitListener
{
uint16_t id; // The ID of the component that this listener is interested in.
uint16_t value; // Value this listener is interested in receiving.
void* cb; // Callback function associated with this listener. Either (*cb)(MicroBitEvent) or (*cb)(MicroBitEvent, void*) depending on whether cb_arg is NULL.
void* cb_arg; // Argument to be passed to the caller. This is assumed to be a pointer, so passing in NULL means that the function doesn't take an argument.
MicroBitEvent evt;
MicroBitListener *next;
/**
* Constructor.
* Create a new Message Bus Listener.
* @param id The ID of the component you want to listen to.
* @param value The event ID you would like to listen to from that component
* @param handler A function pointer to call when the event is detected.
*/
MicroBitListener(uint16_t id, uint16_t value, void (*handler)(MicroBitEvent));
/**
* Alternative constructor where we register a value to be passed to the
* callback. If arg == NULL, the function takes no extra arguemnt.
* Otherwise, the function is understood to take an extra argument.
*/
MicroBitListener(uint16_t id, uint16_t value, void *handler, void* arg);
};
struct MicroBitEventQueueItem
{
MicroBitEvent evt;
MicroBitEventQueueItem *next;
/**
* Constructor.
* Creates a new MicroBitEventQueueItem.
* @param evt The event that is to be queued.
*/
MicroBitEventQueueItem(MicroBitEvent evt);
};
/**
* Class definition for the MicroBitMessageBus.
*
@ -99,10 +60,10 @@ class MicroBitMessageBus : public MicroBitComponent
* 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.
*
* IT IS RECOMMENDED THAT ALL EXTERNAL CODE USE THE send() FUNCTIONS INSTEAD OF THIS FUNCTION.
* IT IS RECOMMENDED THAT ALL EXTERNAL CODE USE THE send() FUNCTIONS INSTEAD OF THIS FUNCTION,
* or the constructors provided by MicroBitEvent.
*
* @param evt The event to send.
* @param c The cache entry to reduce lookups for commonly used channels.
*/
void process(MicroBitEvent evt);
@ -126,24 +87,142 @@ class MicroBitMessageBus : public MicroBitComponent
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick); // call function when ever a click event is detected.
* @endcode
*/
void listen(int id, int value, void (*handler)(MicroBitEvent));
void listen(int id, int value, void (*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* Register a listener function.
*
* Same as above, except the listener function is passed an extra argument in addition to the
* MicroBitEvent, when called.
* @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.
*
* 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
*/
void listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg);
void listen(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg, uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* 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.
*
* @param hander The function to call when an event is received.
*
* Example:
* @code
* void SomeClass::onButtonBClick()
* {
* //do something
* }
*
* SomeClass s = new SomeClass();
* uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, s, &SomeClass::onButtonBClick);
* @endcode
*/
template <typename T>
void listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags = MESSAGE_BUS_LISTENER_DEFAULT_FLAGS);
/**
* 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.
*
*
* Example:
* @code
* void onButtonBClick()
* {
* //do something
* }
*
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void ignore(int id, int value, void (*handler)(MicroBitEvent));
/**
* 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.
*
*
* Example:
* @code
* void onButtonBClick(void *arg)
* {
* //do something
* }
*
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
void ignore(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg);
/**
* 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.
*
*
* 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>
void ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
/**
* Returns a 'nonce' for use with the NONCE_ID channel of the message bus.
*/
uint16_t nonce();
private:
/**
* Add the given MicroBitListener to the list of event handlers, unconditionally.
* @param listener The MicroBitListener to validate.
* @return 1 if the listener is valid, 0 otherwise.
*/
int add(MicroBitListener *newListener);
int remove(MicroBitListener *newListener);
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.
int seq; // Sequence number. Used to invalidate cache entries.
uint16_t nonce_val; // The last nonce issued.
void listen(int id, int value, void* handler, void* arg);
void queueEvent(MicroBitEvent &evt);
MicroBitEventQueueItem* dequeueEvent();
@ -151,6 +230,61 @@ class MicroBitMessageBus : public MicroBitComponent
virtual int isIdleCallbackNeeded();
};
/**
* A registrationt function to allow C++ member funcitons (methods) to be registered as an event
* 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.
* @param hander The method to call when an event is received.
*/
template <typename T>
void MicroBitMessageBus::listen(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent), uint16_t flags)
{
if (object == NULL || handler == NULL)
return;
MicroBitListener *newListener = new MicroBitListener(id, value, object, handler, flags);
if(!add(newListener))
delete newListener;
}
/**
* 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.
*
*
* Example:
* @code
* void onButtonBClick(void *arg)
* {
* //do something
* }
*
* uBit.MessageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
template <typename T>
void MicroBitMessageBus::ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent))
{
if (handler == NULL)
return;
MicroBitListener listener(id, value, object, handler);
remove(&listener);
}
#endif

View file

@ -1,8 +1,8 @@
#ifndef MICROBIT_PIN_H
#define MICROBIT_PIN_H
#include "MicroBitComponent.h"
#include "mbed.h"
#include "MicroBitComponent.h"
// Status Field flags...
#define IO_STATUS_DIGITAL_IN 0x01 // Pin is configured as a digital input, with no pull up.
#define IO_STATUS_DIGITAL_OUT 0x02 // Pin is configured as a digital output

View file

@ -1,9 +1,9 @@
#include "MicroBit.h"
#ifndef MICROBIT_SERIAL_H
#define MICROBIT_SERIAL_H
#include "MicroBitComponent.h"
#include "mbed.h"
#include "ManagedString.h"
#include "MicroBitImage.h"
#define MICROBIT_SERIAL_DEFAULT_BAUD_RATE 115200
#define MICROBIT_SERIAL_BUFFER_SIZE 20

View file

@ -1,62 +1,64 @@
# This file is no longer auto-generated to make the repository builds with GCC
# and ARMCC no matter what.
cmake_minimum_required(VERSION 2.8.11)
enable_language(ASM)
set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
"MicroBitSuperMain.cpp"
"MicroBitI2C.cpp"
"MicroBitMultiButton.cpp"
"MicroBitFont.cpp"
"MicroBit.cpp"
"MicroBitButton.cpp"
"MicroBitMessageBus.cpp"
"MicroBitCompass.cpp"
"MicroBitEvent.cpp"
"MicroBitFiber.cpp"
"ManagedString.cpp"
"MicroBitAccelerometer.cpp"
"MicroBitIO.cpp"
"MicroBitCompat.cpp"
"MicroBitImage.cpp"
"MicroBitDisplay.cpp"
"DynamicPwm.cpp"
"MicroBitPin.cpp"
"MicroBitSerial.cpp"
"MicroBitHeapAllocator.cpp"
"ble-services/MicroBitDFUService.cpp"
"ble-services/MicroBitEventService.cpp"
"ble-services/MicroBitLEDService.cpp"
"ble-services/MicroBitAccelerometerService.cpp"
)
if (YOTTA_CFG_MICROBIT_CONFIGFILE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${YOTTA_FORCE_INCLUDE_FLAG} \"${YOTTA_CFG_MICROBIT_CONFIGFILE}\"")
endif ()
if(CMAKE_COMPILER_IS_GNUCC)
file(REMOVE "asm/CortexContextSwitch.s")
configure_file("asm/CortexContextSwitch.s.gcc" "asm/CortexContextSwitch.s" COPYONLY)
else()
file(REMOVE "asm/CortexContextSwitch.s")
configure_file("asm/CortexContextSwitch.s.armcc" "asm/CortexContextSwitch.s" COPYONLY)
endif()
set(YOTTA_AUTO_MICROBIT-DAL_S_FILES
"asm/CortexContextSwitch.s"
)
add_library(microbit-dal
${YOTTA_AUTO_MICROBIT-DAL_CPP_FILES}
${YOTTA_AUTO_MICROBIT-DAL_S_FILES}
)
yotta_postprocess_target(LIBRARY microbit-dal)
target_link_libraries(microbit-dal
mbed-classic
ble
ble-nrf51822
)
# This file is no longer auto-generated to make the repository builds with GCC
# and ARMCC no matter what.
cmake_minimum_required(VERSION 2.8.11)
enable_language(ASM)
set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
"MicroBitSuperMain.cpp"
"MicroBitI2C.cpp"
"MicroBitMultiButton.cpp"
"MicroBitFont.cpp"
"MicroBit.cpp"
"MicroBitButton.cpp"
"MicroBitMessageBus.cpp"
"MicroBitCompass.cpp"
"MicroBitEvent.cpp"
"MicroBitFiber.cpp"
"ManagedString.cpp"
"MicroBitAccelerometer.cpp"
"MicroBitIO.cpp"
"MicroBitCompat.cpp"
"MicroBitImage.cpp"
"MicroBitDisplay.cpp"
"DynamicPwm.cpp"
"MicroBitPin.cpp"
"MicroBitSerial.cpp"
"MicroBitHeapAllocator.cpp"
"MicroBitListener.cpp"
"MemberFunctionCallback.cpp"
"ble-services/MicroBitDFUService.cpp"
"ble-services/MicroBitEventService.cpp"
"ble-services/MicroBitLEDService.cpp"
"ble-services/MicroBitAccelerometerService.cpp"
)
if (YOTTA_CFG_MICROBIT_CONFIGFILE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${YOTTA_FORCE_INCLUDE_FLAG} \"${YOTTA_CFG_MICROBIT_CONFIGFILE}\"")
endif ()
if(CMAKE_COMPILER_IS_GNUCC)
file(REMOVE "asm/CortexContextSwitch.s")
configure_file("asm/CortexContextSwitch.s.gcc" "asm/CortexContextSwitch.s" COPYONLY)
else()
file(REMOVE "asm/CortexContextSwitch.s")
configure_file("asm/CortexContextSwitch.s.armcc" "asm/CortexContextSwitch.s" COPYONLY)
endif()
set(YOTTA_AUTO_MICROBIT-DAL_S_FILES
"asm/CortexContextSwitch.s"
)
add_library(microbit-dal
${YOTTA_AUTO_MICROBIT-DAL_CPP_FILES}
${YOTTA_AUTO_MICROBIT-DAL_S_FILES}
)
yotta_postprocess_target(LIBRARY microbit-dal)
target_link_libraries(microbit-dal
mbed-classic
ble
ble-nrf51822
)

View file

@ -1,6 +1,4 @@
#include "MicroBitHeapAllocator.h"
#include "DynamicPwm.h"
#include "MicroBit.h"
DynamicPwm* DynamicPwm::pwms[NO_PWMS] = { NULL };

View file

@ -1,9 +1,7 @@
#include <string.h>
#include <stdlib.h>
#include "mbed.h"
#include "MicroBitHeapAllocator.h"
#include "MicroBitCompat.h"
#include "ManagedString.h"
#include "MicroBit.h"
/**

View file

@ -0,0 +1,31 @@
/**
* Class definition for a MemberFunctionCallback.
*
* C++ member functions (also known as methods) have a more complex
* representation than normal C functions. This allows a referene to
* a C++ member function to be stored then called at a later date.
*
* This class is used extensively by the MicroBitMessageBus to deliver
* events to C++ methods.
*/
#include "MicroBit.h"
/**
* Calls the method reference held by this MemberFunctionCallback.
* @param e The event to deliver to the method
*/
void MemberFunctionCallback::fire(MicroBitEvent e)
{
invoke(object, method, e);
}
/**
* Comparison of two MemberFunctionCallback objects.
* @return TRUE if the given MemberFunctionCallback is equivalent to this one. FALSE otherwise.
*/
bool MemberFunctionCallback::operator==(const MemberFunctionCallback &mfc)
{
return (object == mfc.object && (memcmp(method,mfc.method,sizeof(method))==0));
}

View file

@ -3,11 +3,10 @@
*
* A MicroBitDisplay represents the LED matrix array on the MicroBit device.
*/
#include "mbed.h"
#include "MicroBit.h"
#include "MicroBitMatrixMaps.h"
#include <new>
#include "nrf_gpio.h"
#include "mbed.h"
const float timings[MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH] = {0.000010, 0.000047, 0.000094, 0.000187, 0.000375, 0.000750, 0.001500, 0.003000};
@ -234,7 +233,7 @@ MicroBitDisplay::animationUpdate()
if(animationMode == ANIMATION_MODE_PRINT_CHARACTER)
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
}
}
}
@ -243,9 +242,13 @@ MicroBitDisplay::animationUpdate()
* Broadcasts an event onto the shared MessageBus
* @param eventCode The ID of the event that has occurred.
*/
void MicroBitDisplay::sendEvent(uint16_t eventCode)
void MicroBitDisplay::sendAnimationCompleteEvent()
{
MicroBitEvent evt(id,eventCode);
// Signal that we've completed an animation.
MicroBitEvent evt1(id,MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
// Wake up any fibers that were blocked on the animation (if any).
MicroBitEvent evt2(MICROBIT_ID_ALERT, nonce);
}
/**
@ -266,7 +269,7 @@ void MicroBitDisplay::updateScrollText()
if (scrollingChar > scrollingText.length())
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
return;
}
scrollingChar++;
@ -284,7 +287,8 @@ void MicroBitDisplay::updatePrintText()
if (printingChar > printingText.length())
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
return;
}
@ -302,7 +306,8 @@ void MicroBitDisplay::updateScrollImage()
if ((image.paste(scrollingImage, scrollingImagePosition, 0, 0) == 0) && scrollingImageRendered)
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
return;
}
@ -321,7 +326,7 @@ void MicroBitDisplay::updateAnimateImage()
if (scrollingImagePosition <= -scrollingImage.getWidth() + (MICROBIT_DISPLAY_WIDTH + scrollingImageStride) && scrollingImageRendered)
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
return;
}
@ -349,7 +354,7 @@ void MicroBitDisplay::resetAnimation(uint16_t delay)
if (animationMode != ANIMATION_MODE_NONE)
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
}
// Clear the display and setup the animation timers.
@ -406,7 +411,8 @@ void MicroBitDisplay::print(char c, int delay)
animationMode = ANIMATION_MODE_PRINT_CHARACTER;
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}
/**
@ -432,7 +438,8 @@ void MicroBitDisplay::print(ManagedString s, int delay)
this->printAsync(s, delay);
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}
/**
@ -459,7 +466,8 @@ void MicroBitDisplay::print(MicroBitImage i, int x, int y, int alpha, int delay)
animationMode = ANIMATION_MODE_PRINT_CHARACTER;
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}
/**
@ -542,7 +550,8 @@ void MicroBitDisplay::scroll(ManagedString s, int delay)
this->scrollAsync(s, delay);
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}
/**
@ -569,7 +578,8 @@ void MicroBitDisplay::scroll(MicroBitImage image, int delay, int stride)
this->scrollAsync(image, delay, stride);
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}
/**
@ -603,7 +613,7 @@ void MicroBitDisplay::animateAsync(MicroBitImage image, int delay, int stride, i
if (animationMode != ANIMATION_MODE_NONE)
{
animationMode = ANIMATION_MODE_NONE;
this->sendEvent(MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
this->sendAnimationCompleteEvent();
}
this->animationDelay = delay;
@ -646,7 +656,8 @@ void MicroBitDisplay::animate(MicroBitImage image, int delay, int stride, int st
this->animateAsync(image, delay, stride, startingPosition);
// Wait for completion.
fiber_wait_for_event(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_ANIMATION_COMPLETE);
nonce = uBit.MessageBus.nonce();
fiber_wait_for_event(MICROBIT_ID_ALERT, nonce);
}

View file

@ -17,14 +17,14 @@
* MicrobitEvent evt(id,MICROBIT_BUTTON_EVT_CLICK,true); // auto fire
* @endcode
*/
MicroBitEvent::MicroBitEvent(uint16_t source, uint16_t value, bool fire)
MicroBitEvent::MicroBitEvent(uint16_t source, uint16_t value, MicroBitEventLaunchMode mode)
{
this->source = source;
this->value = value;
this->timestamp = ticks;
if(fire)
this->fire();
if(mode != CREATE_ONLY)
this->fire(mode);
}
/**
@ -37,10 +37,35 @@ MicroBitEvent::MicroBitEvent()
this->timestamp = ticks;
}
/**
* Fires the represented event onto the message bus.
*/
void MicroBitEvent::fire(MicroBitEventLaunchMode mode)
{
if (mode == CREATE_AND_QUEUE)
uBit.MessageBus.send(*this);
else if (mode == CREATE_AND_FIRE)
uBit.MessageBus.process(*this);
}
/**
* Fires the represented event onto the message bus.
*/
void MicroBitEvent::fire()
{
uBit.MessageBus.send(*this);
fire(MICROBIT_EVENT_DEFAULT_LAUNCH_MODE);
}
/**
* Constructor.
* Create a new MicroBitEventQueueItem.
* @param evt The event to be queued.
*/
MicroBitEventQueueItem::MicroBitEventQueueItem(MicroBitEvent evt)
{
this->evt = evt;
this->next = NULL;
}

View file

@ -212,8 +212,8 @@ void scheduler_event(MicroBitEvent evt)
t = f->next;
// extract the event data this fiber is blocked on.