developer.mbed.org branch of Lancaster University's microbit library. The real home for this is https://github.com/lancaster-university/microbit

Dependencies:   microbit-dal

Dependents:   MB02 asteroid_shooting

Files at this revision

API Documentation at this revision

Comitter:
ikkeje
Date:
Mon Dec 23 10:31:28 2019 +0000
Commit message:
1.1

Changed in this revision

LICENSE Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
inc/MicroBit.h Show annotated file Show diff for this revision Revisions of this file
microbit-dal.lib Show annotated file Show diff for this revision Revisions of this file
module.json Show annotated file Show diff for this revision Revisions of this file
source/MicroBit.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 British Broadcasting Corporation.
+This software is provided by Lancaster University by arrangement with the BBC.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,42 @@
+# microbit
+
+A collection of the commonly used components of the micro:bit runtime with a
+standard configuration, to provide an easy to use interface for programming the micro:bit in C/C++.
+
+## Overview
+
+The micro:bit runtime provides an easy to use environment for programming the BBC micro:bit in the C/C++ language, written by Lancaster University. It contains device drivers for all the hardware capabilities of the micro:bit, and also a suite of runtime mechanisms to make programming the micro:bit easier and more flexible. These range from control of the LED matrix display to peer-to-peer radio communication and secure Bluetooth Low Energy services. The micro:bit runtime is proudly built on the ARM mbed and Nordic nrf51 platforms.
+
+In addition to supporting development in C/C++, the runtime is also designed specifically to support higher level languages provided by our partners that target the micro:bit. It is currently used as a support library for all the languages on the BBC www.microbit.co.uk website, including Microsoft Block, Microsoft TouchDevelop, Code Kingdoms JavaScript and Micropython languages.
+
+## Links
+
+[micro:bit runtime docs](http://lancaster-university.github.io/microbit-docs/) | [microbit-dal](https://github.com/lancaster-university/microbit-dal) |  [samples](https://github.com/lancaster-university/microbit-samples)
+
+## Build Environments
+
+| Build Environment | Documentation |
+| ------------- |-------------|
+| ARM mbed online | http://lancaster-university.github.io/microbit-docs/online-toolchains/#mbed |
+| yotta  | http://lancaster-university.github.io/microbit-docs/offline-toolchains/#yotta |
+
+
+
+## Hello World!
+
+```cpp
+#include "MicroBit.h"
+
+MicroBit uBit;
+
+int main()
+{
+    uBit.init();
+
+    uBit.display.scroll("Hello world!");
+}
+```
+
+## BBC Community Guidelines
+
+[BBC Community Guidelines](https://www.microbit.co.uk/help#sect_cg)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/inc/MicroBit.h	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,658 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 British Broadcasting Corporation.
+This software is provided by Lancaster University by arrangement with the BBC.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MICROBIT_H
+#define MICROBIT_H
+
+#include "mbed.h"
+
+#include "MicroBitConfig.h"
+#include "MicroBitHeapAllocator.h"
+#include "MicroBitDevice.h"
+#include "ErrorNo.h"
+#include "MicroBitSystemTimer.h"
+#include "Matrix4.h"
+#include "MicroBitCompat.h"
+#include "MicroBitComponent.h"
+#include "ManagedType.h"
+#include "ManagedString.h"
+#include "MicroBitImage.h"
+#include "MicroBitFont.h"
+#include "MicroBitEvent.h"
+#include "DynamicPwm.h"
+#include "MicroBitI2C.h"
+#include "NotifyEvents.h"
+
+#include "MicroBitButton.h"
+#include "MicroBitPin.h"
+#include "MicroBitCompass.h"
+#include "MicroBitCompassCalibrator.h"
+#include "MicroBitAccelerometer.h"
+#include "MicroBitThermometer.h"
+#include "MicroBitLightSensor.h"
+#include "MicroBitMultiButton.h"
+
+#include "MicroBitSerial.h"
+#include "MicroBitIO.h"
+#include "MicroBitMatrixMaps.h"
+#include "MicroBitDisplay.h"
+
+#include "MicroBitFiber.h"
+#include "MicroBitMessageBus.h"
+
+#include "MicroBitBLEManager.h"
+#include "MicroBitRadio.h"
+#include "MicroBitStorage.h"
+
+// MicroBit::flags values
+#define MICROBIT_INITIALIZED                    0x01
+
+/**
+  * Class definition for a MicroBit device.
+  *
+  * Represents the device as a whole, and includes member variables that represent various device drivers
+  * used to control aspects of the micro:bit.
+  */
+class MicroBit
+{
+    private:
+
+    /**
+      * A listener to perform actions as a result of Message Bus reflection.
+      *
+      * In some cases we want to perform lazy instantiation of components, such as
+      * the compass and the accelerometer, where we only want to add them to the idle
+      * fiber when someone has the intention of using these components.
+      */
+    void                        onListenerRegisteredEvent(MicroBitEvent evt);
+
+    uint8_t                     status;
+
+    public:
+
+    // Serial Interface
+    MicroBitSerial              serial;
+
+	// Reset Button
+	InterruptIn     		    resetButton;
+
+    // Persistent key value store
+    MicroBitStorage             storage;
+
+    // I2C Interface
+    MicroBitI2C                 i2c;
+
+    // Device level Message Bus abstraction
+    MicroBitMessageBus          messageBus;
+
+    // Member variables to represent each of the core components on the device.
+    MicroBitDisplay             display;
+    MicroBitButton              buttonA;
+    MicroBitButton              buttonB;
+    MicroBitMultiButton         buttonAB;
+    MicroBitAccelerometer       accelerometer;
+    MicroBitCompass             compass;
+    MicroBitCompassCalibrator   compassCalibrator;
+    MicroBitThermometer         thermometer;
+
+    //An object of available IO pins on the device
+    MicroBitIO                  io;
+
+    // Bluetooth related member variables.
+	MicroBitBLEManager		    bleManager;
+    MicroBitRadio               radio;
+    BLEDevice                   *ble;
+
+    /**
+      * Constructor.
+      *
+      * Create a representation of a MicroBit device, which includes member variables
+      * that represent various device drivers used to control aspects of the micro:bit.
+      */
+    MicroBit();
+
+    /**
+      * Post constructor initialisation method.
+      *
+      * This call will initialised the scheduler, memory allocator and Bluetooth stack.
+      *
+      * This is required as the Bluetooth stack can't be brought up in a
+      * static context i.e. in a constructor.
+      *
+      * @code
+      * uBit.init();
+      * @endcode
+      *
+      * @note This method must be called before user code utilises any functionality
+      *       contained by uBit.
+      */
+    void init();
+
+    /**
+      * Return the friendly name for this device.
+      *
+      * @return A ManagedString representing the friendly name of this device.
+      *
+      * @code
+      * ManagedString name = uBit.getName();
+      * @endcode
+      */
+    static ManagedString getName();
+
+    /**
+      * Return the serial number of this device.
+      *
+      * @return A ManagedString representing the serial number of this device.
+      *
+      * @code
+      * ManagedString serialNumber = uBit.getSerial();
+      * @endcode
+      */
+    static ManagedString getSerial();
+
+    /**
+      * Will reset the micro:bit when called.
+      *
+      * @code
+      * uBit.reset();
+      * @endcode
+      */
+    void reset();
+
+    /**
+      * Delay execution for the given amount of time.
+      *
+      * If the scheduler is running, this will deschedule the current fiber and perform
+      * a power efficient, concurrent sleep operation.
+      *
+      * If the scheduler is disabled or we're running in an interrupt context, this
+      * will revert to a busy wait.
+      *
+      * Alternatively: wait, wait_ms, wait_us can be used which will perform a blocking sleep
+      * operation.
+      *
+      * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
+      *
+      * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
+      *
+      * @code
+      * uBit.sleep(20); //sleep for 20ms
+      * @endcode
+      *
+      * @note This operation is currently limited by the rate of the system timer, therefore
+      *       the granularity of the sleep operation is limited to 6 ms unless the rate of
+      *       the system timer is modified.
+      */
+    void sleep(uint32_t milliseconds);
+
+    /**
+      * Seed the pseudo random number generator using the hardware random number generator.
+      *
+      * @code
+      * uBit.seedRandom();
+      * @endcode
+      */
+    void seedRandom();
+
+    /**
+      * Seed the pseudo random number generator using the given value.
+      *
+      * @param seed The 32-bit value to seed the generator with.
+      *
+      * @code
+      * uBit.seedRandom(0xBB5EED);
+      * @endcode
+      */
+    void seedRandom(uint32_t seed);
+
+
+    /**
+      * Generate a random number in the given range.
+      * We use a simple Galois LFSR random number generator here,
+      * as a Galois LFSR is sufficient for our applications, and much more lightweight
+      * than the hardware random number generator built int the processor, which takes
+      * a long time and uses a lot of energy.
+      *
+      * KIDS: You shouldn't use this is the real world to generate cryptographic keys though...
+      * have a think why not. :-)
+      *
+      * @param max the upper range to generate a number for. This number cannot be negative.
+      *
+      * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE if max is <= 0.
+      *
+      * @code
+      * uBit.random(200); //a number between 0 and 199
+      * @endcode
+      */
+    int random(int max);
+
+    /**
+      * Determine the time since this MicroBit was last reset.
+      *
+      * @return The time since the last reset, in milliseconds.
+      *
+      * @note This will value overflow after 1.6 months.
+      */
+      //TODO: handle overflow case.
+    unsigned long systemTime();
+
+    /**
+      * Determine the version of the micro:bit runtime currently in use.
+      *
+      * @return A textual description of the version of the micro:bit runtime that
+      *         is currently running on this device.
+      */
+    const char *systemVersion();
+
+    /**
+      * Triggers a microbit panic where an loop will display a panic face
+      * and the status code, if provided.
+      *
+      * This loop will continue for panic_timeout iterations, defaults to 0 (infinite).
+      *
+      * panic_timeout can be configured via a call to microbit_panic_timeout.
+      *
+      * @param statusCode the status code of the associated error.
+      *
+      * @code
+      * microbit_panic_timeout(4);
+      *
+      * // will display loop for 4 iterations.
+      * uBit.panic(10);
+      * @endcode
+      */
+    void panic(int statusCode = 0);
+
+    /**
+      * Add a component to the array of system components. This component will then receive
+      * periodic callbacks, once every tick period in interrupt context.
+      *
+      * @param component The component to add.
+      *
+      * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the component array is full.
+      *
+      * @code
+      * // heap allocated - otherwise it will be paged out!
+      * MicroBitDisplay* display = new MicroBitDisplay();
+      *
+      * uBit.addSystemComponent(display);
+      * @endcode
+      *
+      * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_add_component().
+      */
+	int addSystemComponent(MicroBitComponent *component);
+
+    /**
+      * Remove a component from the array of system components. This component will no longer receive
+      * periodic callbacks.
+      *
+      * @param component The component to remove.
+      *
+      * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
+      *
+      * @code
+      * // heap allocated - otherwise it will be paged out!
+      * MicroBitDisplay* display = new MicroBitDisplay();
+      *
+      * uBit.addSystemComponent(display);
+      *
+      * uBit.removeSystemComponent(display);
+      * @endcode
+      *
+      * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_remove_component().
+      */
+	int removeSystemComponent(MicroBitComponent *component);
+
+    /**
+      * Adds a component to the array of idle thread components, which are processed
+      * when the run queue is empty.
+      *
+      * The system timer will poll isIdleCallbackNeeded on each component to determine
+      * if the scheduler should schedule the idle_task imminently.
+      *
+      * @param component The component to add to the array.
+      *
+      * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the fiber components array is full.
+      *
+      * @code
+      * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
+      *
+      * // heap allocated - otherwise it will be paged out!
+      * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
+      *
+      * fiber_add_idle_component(accelerometer);
+      * @endcode
+      *
+      * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_add_idle_component().
+      */
+	int addIdleComponent(MicroBitComponent *component);
+
+    /**
+      * Remove a component from the array of idle thread components
+      *
+      * @param component The component to remove from the idle component array.
+      *
+      * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
+      *
+      * @code
+      * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
+      *
+      * // heap allocated - otherwise it will be paged out!
+      * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
+      *
+      * uBit.addIdleComponent(accelerometer);
+      *
+      * uBit.removeIdleComponent(accelerometer);
+      * @endcode
+      *
+      * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_remove_idle_component().
+      */
+	int removeIdleComponent(MicroBitComponent *component);
+};
+
+/**
+  * Return the friendly name for this device.
+  *
+  * @return A ManagedString representing the friendly name of this device.
+  *
+  * @code
+  * ManagedString name = uBit.getName();
+  * @endcode
+  */
+inline ManagedString MicroBit::getName()
+{
+    return ManagedString(microbit_friendly_name());
+}
+
+/**
+  * Return the serial number of this device.
+  *
+  * @return A ManagedString representing the serial number of this device.
+  *
+  * @code
+  * ManagedString serialNumber = uBit.getSerial();
+  * @endcode
+  */
+inline ManagedString MicroBit::getSerial()
+{
+    // We take to 16 bit numbers here, as we want the full range of ID bits, but don't want negative numbers...
+    int n1 = microbit_serial_number() & 0xffff;
+    int n2 = (microbit_serial_number() >> 16) & 0xffff;
+
+    // Simply concat the two numbers.
+    ManagedString s1(n1);
+    ManagedString s2(n2);
+
+    return s1 + s2;
+}
+
+/**
+  * Will reset the micro:bit when called.
+  *
+  * @code
+  * uBit.reset();
+  * @endcode
+  */
+inline void MicroBit::reset()
+{
+    if(ble && ble->getGapState().connected) {
+
+        // We have a connected BLE peer. Disconnect the BLE session.
+        ble->gap().disconnect(Gap::REMOTE_USER_TERMINATED_CONNECTION);
+
+        // Wait a little while for the connection to drop.
+        wait_ms(100);
+    }
+
+    microbit_reset();
+}
+
+/**
+  * Delay execution for the given amount of time.
+  *
+  * If the scheduler is running, this will deschedule the current fiber and perform
+  * a power efficient, concurrent sleep operation.
+  *
+  * If the scheduler is disabled or we're running in an interrupt context, this
+  * will revert to a busy wait.
+  *
+  * Alternatively: wait, wait_ms, wait_us can be used which will perform a blocking sleep
+  * operation.
+  *
+  * @param milliseconds the amount of time, in ms, to wait for. This number cannot be negative.
+  *
+  * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER milliseconds is less than zero.
+  *
+  * @code
+  * uBit.sleep(20); //sleep for 20ms
+  * @endcode
+  *
+  * @note This operation is currently limited by the rate of the system timer, therefore
+  *       the granularity of the sleep operation is limited to 6 ms unless the rate of
+  *       the system timer is modified.
+  */
+inline void MicroBit::sleep(uint32_t milliseconds)
+{
+    fiber_sleep(milliseconds);
+}
+
+/**
+  * Generate a random number in the given range.
+  * We use a simple Galois LFSR random number generator here,
+  * as a Galois LFSR is sufficient for our applications, and much more lightweight
+  * than the hardware random number generator built int the processor, which takes
+  * a long time and uses a lot of energy.
+  *
+  * KIDS: You shouldn't use this is the real world to generate cryptographic keys though...
+  * have a think why not. :-)
+  *
+  * @param max the upper range to generate a number for. This number cannot be negative.
+  *
+  * @return A random, natural number between 0 and the max-1. Or MICROBIT_INVALID_VALUE if max is <= 0.
+  *
+  * @code
+  * uBit.random(200); //a number between 0 and 199
+  * @endcode
+  */
+inline int MicroBit::random(int max)
+{
+    return microbit_random(max);
+}
+
+/**
+  * Seed the pseudo random number generator using the hardware random number generator.
+  *
+  * @code
+  * uBit.seedRandom();
+  * @endcode
+  */
+inline void MicroBit::seedRandom()
+{
+    microbit_seed_random();
+}
+
+
+/**
+  * Seed the pseudo random number generator using the given value.
+  *
+  * @param seed The 32-bit value to seed the generator with.
+  *
+  * @code
+  * uBit.seedRandom(0xBB5EED);
+  * @endcode
+  */
+inline void MicroBit::seedRandom(uint32_t seed)
+{
+    microbit_seed_random(seed);
+}
+
+
+/**
+  * Add a component to the array of system components. This component will then receive
+  * periodic callbacks, once every tick period in interrupt context.
+  *
+  * @param component The component to add.
+  *
+  * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the component array is full.
+  *
+  * @code
+  * // heap allocated - otherwise it will be paged out!
+  * MicroBitDisplay* display = new MicroBitDisplay();
+  *
+  * uBit.addSystemComponent(display);
+  * @endcode
+  *
+  * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_add_component().
+  */
+inline int MicroBit::addSystemComponent(MicroBitComponent *component)
+{
+	return system_timer_add_component(component);
+}
+
+/**
+  * Remove a component from the array of system components. This component will no longer receive
+  * periodic callbacks.
+  *
+  * @param component The component to remove.
+  *
+  * @return MICROBIT_OK on success or MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
+  *
+  * @code
+  * // heap allocated - otherwise it will be paged out!
+  * MicroBitDisplay* display = new MicroBitDisplay();
+  *
+  * uBit.addSystemComponent(display);
+  *
+  * uBit.removeSystemComponent(display);
+  * @endcode
+  *
+  * @note This interface is now deprecated, and will be removed in the next major release. Please use system_timer_remove_component().
+  */
+inline int MicroBit::removeSystemComponent(MicroBitComponent *component)
+{
+	return system_timer_remove_component(component);
+}
+
+/**
+  * Adds a component to the array of idle thread components, which are processed
+  * when the run queue is empty.
+  *
+  * The system timer will poll isIdleCallbackNeeded on each component to determine
+  * if the scheduler should schedule the idle_task imminently.
+  *
+  * @param component The component to add to the array.
+  *
+  * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the fiber components array is full.
+  *
+  * @code
+  * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
+  *
+  * // heap allocated - otherwise it will be paged out!
+  * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
+  *
+  * fiber_add_idle_component(accelerometer);
+  * @endcode
+  *
+  * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_add_idle_component().
+  */
+inline int MicroBit::addIdleComponent(MicroBitComponent *component)
+{
+	return fiber_add_idle_component(component);
+}
+
+/**
+  * Remove a component from the array of idle thread components
+  *
+  * @param component The component to remove from the idle component array.
+  *
+  * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added.
+  *
+  * @code
+  * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0);
+  *
+  * // heap allocated - otherwise it will be paged out!
+  * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c);
+  *
+  * uBit.addIdleComponent(accelerometer);
+  *
+  * uBit.removeIdleComponent(accelerometer);
+  * @endcode
+  *
+  * @note This interface is now deprecated, and will be removed in the next major release. Please use fiber_remove_idle_component().
+  */
+inline int MicroBit::removeIdleComponent(MicroBitComponent *component)
+{
+	return fiber_remove_idle_component(component);
+}
+
+
+/**
+  * Determine the time since this MicroBit was last reset.
+  *
+  * @return The time since the last reset, in milliseconds.
+  *
+  * @note This will value overflow after 1.6 months.
+  */
+inline unsigned long MicroBit::systemTime()
+{
+    return system_timer_current_time();
+}
+
+
+/**
+  * Determine the version of the micro:bit runtime currently in use.
+  *
+  * @return A textual description of the version of the micro:bit runtime that
+  *         is currently running on this device.
+  */
+inline const char *MicroBit::systemVersion()
+{
+    return microbit_dal_version();
+}
+
+/**
+  * Triggers a microbit panic where an loop will display a panic face
+  * and the status code, if provided.
+  *
+  * This loop will continue for panic_timeout iterations, defaults to 0 (infinite).
+  *
+  * panic_timeout can be configured via a call to microbit_panic_timeout.
+  *
+  * @param statusCode the status code of the associated error.
+  *
+  * @code
+  * microbit_panic_timeout(4);
+  *
+  * // will display loop for 4 iterations.
+  * uBit.panic(10);
+  * @endcode
+  */
+inline void MicroBit::panic(int statusCode)
+{
+    //show error and enter infinite while
+	microbit_panic(statusCode);
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/microbit-dal.lib	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/Lancaster-University/code/microbit-dal/#eb91bba49623
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/module.json	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,13 @@
+{
+  "name": "microbit",
+  "version": "2.0.0-rc4",
+  "description": "A simple to use collection of the most commonly used components in the micro:bit runtime",
+  "license": "MIT",
+  "dependencies": {
+    "microbit-dal": "lancaster-university/microbit-dal"
+  },
+  "extraIncludes": [
+    "inc"
+  ],
+  "targetDependencies": {}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/MicroBit.cpp	Mon Dec 23 10:31:28 2019 +0000
@@ -0,0 +1,223 @@
+/*
+The MIT License (MIT)
+
+Copyright (c) 2016 British Broadcasting Corporation.
+This software is provided by Lancaster University by arrangement with the BBC.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#include "MicroBitConfig.h"
+/*
+ * The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
+ * If we're compiling under GCC, then we suppress any warnings generated from this code (but not the rest of the DAL)
+ * The ARM cc compiler is more tolerant. We don't test __GNUC__ here to detect GCC as ARMCC also typically sets this
+ * as a compatability option, but does not support the options used...
+ */
+#if !defined(__arm)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+#include "MicroBit.h"
+
+#include "nrf_soc.h"
+
+/*
+ * Return to our predefined compiler settings.
+ */
+#if !defined(__arm)
+#pragma GCC diagnostic pop
+#endif
+
+#if CONFIG_ENABLED(MICROBIT_DBG)
+// We create and initialize to NULL here, but MicroBitSerial will automatically update this as needed in its constructor.
+RawSerial* SERIAL_DEBUG = NULL;
+#endif
+
+/**
+  * Constructor.
+  *
+  * Create a representation of a MicroBit device, which includes member variables
+  * that represent various device drivers used to control aspects of the micro:bit.
+  */
+MicroBit::MicroBit() :
+    serial(USBTX, USBRX),
+	resetButton(MICROBIT_PIN_BUTTON_RESET),
+    storage(),
+    i2c(I2C_SDA0, I2C_SCL0),
+    messageBus(),
+    display(),
+    buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A),
+    buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B),
+    buttonAB(MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B, MICROBIT_ID_BUTTON_AB),
+    accelerometer(i2c),
+    compass(i2c, accelerometer, storage),
+    compassCalibrator(compass, accelerometer, display),
+    thermometer(storage),
+    io(MICROBIT_ID_IO_P0,MICROBIT_ID_IO_P1,MICROBIT_ID_IO_P2,
+       MICROBIT_ID_IO_P3,MICROBIT_ID_IO_P4,MICROBIT_ID_IO_P5,
+       MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,
+       MICROBIT_ID_IO_P9,MICROBIT_ID_IO_P10,MICROBIT_ID_IO_P11,
+       MICROBIT_ID_IO_P12,MICROBIT_ID_IO_P13,MICROBIT_ID_IO_P14,
+       MICROBIT_ID_IO_P15,MICROBIT_ID_IO_P16,MICROBIT_ID_IO_P19,
+       MICROBIT_ID_IO_P20),
+    bleManager(storage),
+    radio(),
+    ble(NULL)
+{
+    // Clear our status
+    status = 0;
+
+    // Bring up soft reset functionality as soon as possible.
+    resetButton.mode(PullUp);
+    resetButton.fall(this, &MicroBit::reset);
+}
+
+/**
+  * Post constructor initialisation method.
+  *
+  * This call will initialised the scheduler, memory allocator and Bluetooth stack.
+  *
+  * This is required as the Bluetooth stack can't be brought up in a
+  * static context i.e. in a constructor.
+  *
+  * @code
+  * uBit.init();
+  * @endcode
+  *
+  * @note This method must be called before user code utilises any functionality
+  *       contained by uBit.
+  */
+void MicroBit::init()
+{
+    if (status & MICROBIT_INITIALIZED)
+        return;
+
+#if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR)
+    // Bring up a nested heap allocator.
+    microbit_create_nested_heap(MICROBIT_NESTED_HEAP_SIZE);
+#endif
+
+    // Bring up fiber scheduler.
+    scheduler_init(messageBus);
+
+    // Seed our random number generator
+    seedRandom();
+
+    // Create an event handler to trap any handlers being created for I2C services.
+    // We do this to enable initialisation of those services only when they're used,
+    // which saves processor time, memeory and battery life.
+    messageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_EVT_ANY, this, &MicroBit::onListenerRegisteredEvent);
+
+    status |= MICROBIT_INITIALIZED;
+
+#if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
+    // Test if we need to enter BLE pairing mode...
+    int i=0;
+    sleep(100);
+    while (buttonA.isPressed() && buttonB.isPressed() && i<10)
+    {
+        sleep(100);
+        i++;
+
+        if (i == 10)
+        {
+#if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
+            microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
+#endif
+            // Start the BLE stack, if it isn't already running.
+            if (!ble)
+            {
+                bleManager.init(getName(), getSerial(), messageBus, true);
+                ble = bleManager.ble;
+            }
+
+            // Enter pairing mode, using the LED matrix for any necessary pairing operations
+            bleManager.pairingMode(display, buttonA);
+        }
+    }
+#endif
+
+    // Attempt to bring up a second heap region, using unused memory normally reserved for Soft Device.
+#if CONFIG_ENABLED(MICROBIT_HEAP_ALLOCATOR) && CONFIG_ENABLED(MICROBIT_HEAP_REUSE_SD)
+#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
+    microbit_create_heap(MICROBIT_SD_GATT_TABLE_START + MICROBIT_SD_GATT_TABLE_SIZE, MICROBIT_SD_LIMIT);
+#else
+    microbit_create_heap(MICROBIT_SRAM_BASE, MICROBIT_SD_LIMIT);
+#endif
+#endif
+
+#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
+    // Start the BLE stack, if it isn't already running.
+    if (!ble)
+    {
+        bleManager.init(getName(), getSerial(), messageBus, false);
+        ble = bleManager.ble;
+    }
+#endif
+}
+
+/**
+  * A listener to perform actions as a result of Message Bus reflection.
+  *
+  * In some cases we want to perform lazy instantiation of components, such as
+  * the compass and the accelerometer, where we only want to add them to the idle
+  * fiber when someone has the intention of using these components.
+  */
+void MicroBit::onListenerRegisteredEvent(MicroBitEvent evt)
+{
+    switch(evt.value)
+    {
+        case MICROBIT_ID_BUTTON_AB:
+            // A user has registered to receive events from the buttonAB multibutton.
+            // Disable click events from being generated by ButtonA and ButtonB, and defer the
+            // control of this to the multibutton handler.
+            //
+            // This way, buttons look independent unless a buttonAB is requested, at which
+            // point button A+B clicks can be correclty handled without breaking
+            // causal ordering.
+            buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
+            buttonB.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
+            buttonAB.setEventConfiguration(MICROBIT_BUTTON_ALL_EVENTS);
+            break;
+
+        case MICROBIT_ID_COMPASS:
+            // A listener has been registered for the compass.
+            // The compass uses lazy instantiation, we just need to read the data once to start it running.
+            // Touch the compass through the heading() function to ensure it is calibrated. if it isn't this will launch any associated calibration algorithms.
+            compass.heading();
+
+            break;
+
+        case MICROBIT_ID_ACCELEROMETER:
+        case MICROBIT_ID_GESTURE:
+            // A listener has been registered for the accelerometer.
+            // The accelerometer uses lazy instantiation, we just need to read the data once to start it running.
+            accelerometer.updateSample();
+            break;
+
+        case MICROBIT_ID_THERMOMETER:
+            // A listener has been registered for the thermometer.
+            // The thermometer uses lazy instantiation, we just need to read the data once to start it running.
+            thermometer.updateSample();
+            break;
+    }
+}
\ No newline at end of file