Merge branch 'dal-integration' of https://www.github.com/lancaster-university/microbit-dal into dal-integration

This commit is contained in:
Joe Finney 2018-09-07 18:48:20 +01:00
commit ad764c780b
5 changed files with 112 additions and 72 deletions

View file

@ -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.
@ -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.
*
@ -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.
@ -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;

View file

@ -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
//

View file

@ -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)

View file

@ -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
@ -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;
@ -777,10 +783,9 @@ 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,
@ -788,7 +793,7 @@ void MicroBitBLEManager::showManagementModeAnimation(MicroBitDisplay &display)
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[] =

View file

@ -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;
}
/**
@ -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
@ -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)
@ -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.
@ -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;
}
@ -391,17 +391,17 @@ 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.
@ -409,7 +409,7 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
{
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.
@ -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;
}
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...
// 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;
p = listeners;
l = listeners;
while (l != NULL && l->id < newListener->id)
{
p = l;
l = l->next;
}
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;
}
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;
//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;
}
//this new listener is now the front!
listeners = newListener;
}
//add after p
else
{
newListener->next = p->next;
p->next = newListener;
}
//add after p
else
{
newListener->next = p->next;
p->next = newListener;
}
MicroBitEvent(MICROBIT_ID_MESSAGE_BUS_LISTENER, newListener->id);
return MICROBIT_OK;
@ -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)
@ -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++;