Skip to content

Commit

Permalink
Merge branch 'dal-integration' of https://www.github.com/lancaster-un…
Browse files Browse the repository at this point in the history
…iversity/microbit-dal into dal-integration
  • Loading branch information
finneyj committed Sep 7, 2018
2 parents 471abe9 + da620c0 commit ad764c7
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 79 deletions.
23 changes: 21 additions & 2 deletions inc/core/EventModel.h
Expand Up @@ -53,10 +53,16 @@ DEALINGS IN THE SOFTWARE.
*/
class EventModel
{
protected:
void (*listener_deletion_callback)(MicroBitListener *); // if not null, this function is invoked when a listener is removed.

public:

static EventModel *defaultEventBus;

// Set listener_deletion_callback to NULL.
EventModel() : listener_deletion_callback(NULL) {}

/**
* Queues the given event to be sent to all registered recipients.
* The method of delivery will vary depending on the underlying implementation.
Expand Down Expand Up @@ -130,6 +136,17 @@ class EventModel
return MICROBIT_OK;
}

/**
* Sets a pointer to handler that's invoked when any listener is deleted.
*
* @returns MICROBIT_OK on success.
**/
int setListenerDeletionCallback(void (*listener_deletion_callback)(MicroBitListener *))
{
this->listener_deletion_callback = listener_deletion_callback;
return MICROBIT_OK;
}

/**
* Register a listener function.
*
Expand Down Expand Up @@ -298,6 +315,8 @@ class EventModel
* @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.
* @param arg the arg that is passed to the handler on an event. Used to differentiate between handlers with the same id and source, but not the same arg.
* Defaults to NULL, which means any handler with the same id, event and callback is removed.
*
* @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER if the handler
* given is NULL.
Expand All @@ -315,12 +334,12 @@ class EventModel
* uBit.messageBus.ignore(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButtonBClick);
* @endcode
*/
int ignore(int id, int value, void (*handler)(MicroBitEvent, void*))
int ignore(int id, int value, void (*handler)(MicroBitEvent, void*), void* arg = NULL)
{
if (handler == NULL)
return MICROBIT_INVALID_PARAMETER;

MicroBitListener listener(id, value, handler, NULL);
MicroBitListener listener(id, value, handler, arg);
remove(&listener);

return MICROBIT_OK;
Expand Down
8 changes: 8 additions & 0 deletions inc/core/MicroBitConfig.h
Expand Up @@ -303,6 +303,14 @@ extern uint32_t __etext;
#define MICROBIT_BLE_DEVICE_INFORMATION_SERVICE 1
#endif

// Enable/Disable BLE Service: MicroBitPartialFlashingService
// This enables the flashing part of the partial flashing service.
// Partial flashing is currently only possible for programs built using MakeCode
// and is disabled by default.
#ifndef MICROBIT_BLE_PARTIAL_FLASHING
#define MICROBIT_BLE_PARTIAL_FLASHING 0
#endif

//
// Accelerometer options
//
Expand Down
4 changes: 4 additions & 0 deletions inc/platform/yotta_cfg_mappings.h
Expand Up @@ -125,6 +125,10 @@
#define MICROBIT_BLE_ADVERTISING_INTERVAL YOTTA_CFG_MICROBIT_DAL_BLUETOOTH_ADVERTISING_INTERVAL
#endif

#ifdef YOTTA_CFG_MICROBIT_DAL_BLUETOOTH_PARTIAL_FLASHING
#define MICROBIT_BLE_PARTIAL_FLASHING YOTTA_CFG_MICROBIT_DAL_BLUETOOTH_PARTIAL_FLASHING
#endif

//we check if the user has requested open mode, otherwise we will double def!
#if (YOTTA_CFG_MICROBIT_DAL_BLUETOOTH_OPEN == 0)

Expand Down
13 changes: 9 additions & 4 deletions source/bluetooth/MicroBitBLEManager.cpp
Expand Up @@ -383,6 +383,9 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
// Bring up core BLE services.
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
new MicroBitDFUService(*ble);
#endif

#if CONFIG_ENABLED(MICROBIT_BLE_PARTIAL_FLASHING)
new MicroBitPartialFlashingService(*ble, messageBus);
#endif

Expand Down Expand Up @@ -638,6 +641,9 @@ int MicroBitBLEManager::advertiseEddystoneUid(const char* uid_namespace, const c
*/
void MicroBitBLEManager::pairingMode(MicroBitDisplay &display, MicroBitButton &authorisationButton)
{
// Do not page this fiber!
currentFiber->flags |= MICROBIT_FIBER_FLAG_DO_NOT_PAGE;

ManagedString namePrefix("BBC micro:bit [");
ManagedString namePostfix("]");
ManagedString BLEName = namePrefix + deviceName + namePostfix;
Expand Down Expand Up @@ -777,18 +783,17 @@ void MicroBitBLEManager::showManagementModeAnimation(MicroBitDisplay &display)
// Animation for display object
// https://makecode.microbit.org/93264-81126-90471-58367

const int mgmt_animation_w = 20;
const int mgmt_animation_h = 5;
const uint8_t mgmt_animation[] =
const uint8_t mgmt_animation[] __attribute__ ((aligned (4))) =
{
0xff, 0xff, 20, 0, 5, 0,
255,255,255,255,255, 255,255,255,255,255, 255,255, 0,255,255, 255, 0, 0, 0,255,
255,255,255,255,255, 255,255, 0,255,255, 255, 0, 0, 0,255, 0, 0, 0, 0, 0,
255,255, 0,255,255, 255, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255,255,255,255,255, 255,255, 0,255,255, 255, 0, 0, 0,255, 0, 0, 0, 0, 0,
255,255,255,255,255, 255,255,255,255,255, 255,255, 0,255,255, 255, 0, 0, 0,255
};

MicroBitImage mgmt(mgmt_animation_w,mgmt_animation_h,mgmt_animation);
MicroBitImage mgmt((ImageData*)mgmt_animation);
display.animate(mgmt,100,5);

const uint8_t bt_icon_raw[] =
Expand Down
150 changes: 77 additions & 73 deletions source/drivers/MicroBitMessageBus.cpp
Expand Up @@ -60,15 +60,15 @@ DEALINGS IN THE SOFTWARE.
*/
MicroBitMessageBus::MicroBitMessageBus()
{
this->listeners = NULL;
this->listeners = NULL;
this->evt_queue_head = NULL;
this->evt_queue_tail = NULL;
this->queueLength = 0;

fiber_add_idle_component(this);
fiber_add_idle_component(this);

if(EventModel::defaultEventBus == NULL)
EventModel::defaultEventBus = this;
if(EventModel::defaultEventBus == NULL)
EventModel::defaultEventBus = this;
}

/**
Expand All @@ -79,7 +79,7 @@ MicroBitMessageBus::MicroBitMessageBus()
*/
void async_callback(void *param)
{
MicroBitListener *listener = (MicroBitListener *)param;
MicroBitListener *listener = (MicroBitListener *)param;

// OK, now we need to decide how to behave depending on our configuration.
// If this a fiber f already active within this listener then check our
Expand Down Expand Up @@ -228,11 +228,11 @@ MicroBitEventQueueItem* MicroBitMessageBus::dequeueEvent()
*/
int MicroBitMessageBus::deleteMarkedListeners()
{
MicroBitListener *l, *p;
MicroBitListener *l, *p;
int removed = 0;

l = listeners;
p = NULL;
l = listeners;
p = NULL;

// Walk this list of event handlers. Delete any that match the given listener.
while (l != NULL)
Expand Down Expand Up @@ -339,14 +339,14 @@ int MicroBitMessageBus::send(MicroBitEvent evt)
*/
int MicroBitMessageBus::process(MicroBitEvent &evt, bool urgent)
{
MicroBitListener *l;
MicroBitListener *l;
int complete = 1;
bool listenerUrgent;

l = listeners;
while (l != NULL)
{
if((l->id == evt.source || l->id == MICROBIT_ID_ANY) && (l->value == evt.value || l->value == MICROBIT_EVT_ANY))
if((l->id == evt.source || l->id == MICROBIT_ID_ANY) && (l->value == evt.value || l->value == MICROBIT_EVT_ANY))
{
// If we're running under the fiber scheduler, then derive the THREADING_MODE for the callback based on the
// metadata in the listener itself.
Expand All @@ -365,19 +365,19 @@ int MicroBitMessageBus::process(MicroBitEvent &evt, bool urgent)
// Otherwise, we invoke it in a 'fork on block' context, that will automatically create a fiber
// should the event handler attempt a blocking operation, but doesn't have the overhead
// of creating a fiber needlessly. (cool huh?)
if (l->flags & MESSAGE_BUS_LISTENER_NONBLOCKING || !fiber_scheduler_running())
async_callback(l);
else
invoke(async_callback, l);
if (l->flags & MESSAGE_BUS_LISTENER_NONBLOCKING || !fiber_scheduler_running())
async_callback(l);
else
invoke(async_callback, l);
}
else
{
complete = 0;
}
}
}

l = l->next;
}
l = l->next;
}

return complete;
}
Expand All @@ -391,25 +391,25 @@ int MicroBitMessageBus::process(MicroBitEvent &evt, bool urgent)
*/
int MicroBitMessageBus::add(MicroBitListener *newListener)
{
MicroBitListener *l, *p;
MicroBitListener *l, *p;
int methodCallback;

//handler can't be NULL!
if (newListener == NULL)
return MICROBIT_INVALID_PARAMETER;
//handler can't be NULL!
if (newListener == NULL)
return MICROBIT_INVALID_PARAMETER;

l = listeners;
l = listeners;

// Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
// registered in a that will already capture these events. If we do, silently ignore.
// Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
// registered in a that will already capture these events. If we do, silently ignore.

// We always check the ID, VALUE and CB_METHOD fields.
// If we have a callback to a method, check the cb_method class. Otherwise, the cb function point is sufficient.
while (l != NULL)
{
methodCallback = (newListener->flags & MESSAGE_BUS_LISTENER_METHOD) && (l->flags & MESSAGE_BUS_LISTENER_METHOD);

if (l->id == newListener->id && l->value == newListener->value && (methodCallback ? *l->cb_method == *newListener->cb_method : l->cb == newListener->cb))
if (l->id == newListener->id && l->value == newListener->value && (methodCallback ? *l->cb_method == *newListener->cb_method : l->cb == newListener->cb) && newListener->cb_arg == l->cb_arg)
{
// We have a perfect match for this event listener already registered.
// If it's marked for deletion, we simply resurrect the listener, and we're done.
Expand All @@ -424,50 +424,50 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
}

// We have a valid, new event handler. Add it to the list.
// if listeners is null - we can automatically add this listener to the list at the beginning...
if (listeners == NULL)
{
listeners = newListener;
// if listeners is null - we can automatically add this listener to the list at the beginning...
if (listeners == NULL)
{
listeners = newListener;
MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);

return MICROBIT_OK;
}

// We maintain an ordered list of listeners.
// The chain is held stictly in increasing order of ID (first level), then value code (second level).
// Find the correct point in the chain for this event.
// Adding a listener is a rare occurance, so we just walk the list...

p = listeners;
l = listeners;

while (l != NULL && l->id < newListener->id)
{
p = l;
l = l->next;
}

while (l != NULL && l->id == newListener->id && l->value < newListener->value)
{
p = l;
l = l->next;
}

//add at front of list
if (p == listeners && (newListener->id < p->id || (p->id == newListener->id && p->value > newListener->value)))
{
newListener->next = p;

//this new listener is now the front!
listeners = newListener;
}

//add after p
else
{
newListener->next = p->next;
p->next = newListener;
}
return MICROBIT_OK;
}

// We maintain an ordered list of listeners.
// The chain is held stictly in increasing order of ID (first level), then value code (second level).
// Find the correct point in the chain for this event.
// Adding a listener is a rare occurance, so we just walk the list...

p = listeners;
l = listeners;

while (l != NULL && l->id < newListener->id)
{
p = l;
l = l->next;
}

while (l != NULL && l->id == newListener->id && l->value <= newListener->value)
{
p = l;
l = l->next;
}

//add at front of list
if (p == listeners && (newListener->id < p->id || (p->id == newListener->id && p->value > newListener->value)))
{
newListener->next = p;

//this new listener is now the front!
listeners = newListener;
}

//add after p
else
{
newListener->next = p->next;
p->next = newListener;
}

MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);
return MICROBIT_OK;
Expand All @@ -482,14 +482,14 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
*/
int MicroBitMessageBus::remove(MicroBitListener *listener)
{
MicroBitListener *l;
MicroBitListener *l;
int removed = 0;

//handler can't be NULL!
if (listener == NULL)
return MICROBIT_INVALID_PARAMETER;
//handler can't be NULL!
if (listener == NULL)
return MICROBIT_INVALID_PARAMETER;

l = listeners;
l = listeners;

// Walk this list of event handlers. Delete any that match the given listener.
while (l != NULL)
Expand All @@ -499,8 +499,12 @@ int MicroBitMessageBus::remove(MicroBitListener *listener)
if(((listener->flags & MESSAGE_BUS_LISTENER_METHOD) && (*l->cb_method == *listener->cb_method)) ||
((!(listener->flags & MESSAGE_BUS_LISTENER_METHOD) && l->cb == listener->cb)))
{
if ((listener->id == MICROBIT_ID_ANY || listener->id == l->id) && (listener->value == MICROBIT_EVT_ANY || listener->value == l->value))
if ((listener->id == MICROBIT_ID_ANY || listener->id == l->id) && (listener->value == MICROBIT_EVT_ANY || listener->value == l->value) && (listener->cb_arg == l->cb_arg || listener->cb_arg == NULL))
{
// if notification of deletion has been requested, invoke the listener deletion callback.
if (listener_deletion_callback)
listener_deletion_callback(l);

// Found a match. mark this to be removed from the list.
l->flags |= MESSAGE_BUS_LISTENER_DELETING;
removed++;
Expand Down

0 comments on commit ad764c7

Please sign in to comment.