Merge branch 'dal-integration' of https://www.github.com/lancaster-university/microbit-dal into dal-integration
This commit is contained in:
commit
ad764c780b
5 changed files with 112 additions and 72 deletions
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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[] =
|
||||
|
|
|
@ -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++;
|
||||
|
|
Loading…
Reference in a new issue