First cut at a build without a global MicroBit singleton

master
Joe Finney 7 years ago
parent fdbc41d6b6
commit 5231b5f526
  1. 124
      inc/MicroBit.h
  2. 3
      inc/MicroBitAccelerometer.h
  3. 5
      inc/MicroBitAccelerometerService.h
  4. 5
      inc/MicroBitBLEManager.h
  5. 2
      inc/MicroBitButtonService.h
  6. 15
      inc/MicroBitCompass.h
  7. 2
      inc/MicroBitCompat.h
  8. 4
      inc/MicroBitComponent.h
  9. 1
      inc/MicroBitConfig.h
  10. 24
      inc/MicroBitDisplay.h
  11. 3
      inc/MicroBitEventService.h
  12. 64
      inc/MicroBitFiber.h
  13. 13
      inc/MicroBitFont.h
  14. 5
      inc/MicroBitIO.h
  15. 3
      inc/MicroBitIOPinService.h
  16. 4
      inc/MicroBitLEDService.h
  17. 1
      inc/MicroBitLightSensor.h
  18. 3
      inc/MicroBitMagnetometerService.h
  19. 2
      inc/MicroBitMessageBus.h
  20. 6
      inc/MicroBitMultiButton.h
  21. 10
      inc/MicroBitRadio.h
  22. 7
      inc/MicroBitRadioDatagram.h
  23. 37
      inc/MicroBitRadioEvent.h
  24. 5
      inc/MicroBitTemperatureService.h
  25. 1
      source/CMakeLists.txt
  26. 254
      source/MicroBit.cpp
  27. 12
      source/MicroBitAccelerometer.cpp
  28. 4
      source/MicroBitButton.cpp
  29. 22
      source/MicroBitCompass.cpp
  30. 61
      source/MicroBitDisplay.cpp
  31. 6
      source/MicroBitEvent.cpp
  32. 224
      source/MicroBitFiber.cpp
  33. 19
      source/MicroBitFont.cpp
  34. 2
      source/MicroBitHeapAllocator.cpp
  35. 2
      source/MicroBitImage.cpp
  36. 6
      source/MicroBitLightSensor.cpp
  37. 7
      source/MicroBitMessageBus.cpp
  38. 7
      source/MicroBitMultiButton.cpp
  39. 6
      source/MicroBitSerial.cpp
  40. 76
      source/MicroBitSuperMain.cpp
  41. 10
      source/MicroBitThermometer.cpp
  42. 2
      source/RefCounted.cpp
  43. 22
      source/ble-services/MicroBitAccelerometerService.cpp
  44. 62
      source/ble-services/MicroBitBLEManager.cpp
  45. 6
      source/ble-services/MicroBitButtonService.cpp
  46. 7
      source/ble-services/MicroBitDFUService.cpp
  47. 12
      source/ble-services/MicroBitEventService.cpp
  48. 39
      source/ble-services/MicroBitIOPinService.cpp
  49. 10
      source/ble-services/MicroBitLEDService.cpp
  50. 27
      source/ble-services/MicroBitMagnetometerService.cpp
  51. 18
      source/ble-services/MicroBitRadio.cpp
  52. 10
      source/ble-services/MicroBitRadioDatagram.cpp
  53. 53
      source/ble-services/MicroBitRadioEvent.cpp
  54. 14
      source/ble-services/MicroBitTemperatureService.cpp

@ -56,8 +56,6 @@
#define MICROBIT_PIN_SDA P0_30
#define MICROBIT_PIN_SCL P0_0
#define MICROBIT_DEFAULT_TICK_PERIOD FIBER_TICK_PERIOD_MS
/**
* Class definition for a MicroBit device.
*
@ -71,16 +69,10 @@ class MicroBit
void onABListenerRegisteredEvent(MicroBitEvent evt);
uint32_t randomValue;
//the current tick period in MS
int tickPeriod;
public:
// Map of device state.
uint32_t flags;
// Periodic callback
Ticker systemTicker;
// Reset Button
InterruptIn resetButton;
// I2C Interface
MicroBitI2C i2c;
@ -88,14 +80,8 @@ class MicroBit
// Serial Interface
MicroBitSerial serial;
// Array of components which are iterated during a system tick
MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS];
// Array of components which are iterated during idle thread execution, isIdleCallbackNeeded is polled during a systemTick.
MicroBitComponent* idleThreadComponents[MICROBIT_IDLE_COMPONENTS];
// Device level Message Bus abstraction
MicroBitMessageBus MessageBus;
MicroBitMessageBus messageBus;
// Member variables to represent each of the core components on the device.
MicroBitDisplay display;
@ -121,7 +107,6 @@ class MicroBit
*
* Exposed objects:
* @code
* uBit.systemTicker; //the Ticker callback that performs routines like updating the display.
* uBit.MessageBus; //The message bus where events are fired.
* uBit.display; //The display object for the LED matrix.
* uBit.buttonA; //The buttonA object for button a.
@ -152,14 +137,14 @@ class MicroBit
*
* @return A string representing the friendly name of this device.
*/
ManagedString getName();
static ManagedString getName();
/**
* Return the serial number of this device.
*
* @return A string representing the serial number of this device.
*/
ManagedString getSerial();
static ManagedString getSerial();
/**
* Will reset the micro:bit when called.
@ -185,10 +170,10 @@ class MicroBit
*
* Example:
* @code
* uBit.sleep(20); //sleep for 20ms
* MicroBit::sleep(20); //sleep for 20ms
* @endcode
*/
int sleep(int milliseconds);
static int sleep(int milliseconds);
/**
* Seed the pseudo random number generator using the hardware generator.
@ -227,62 +212,6 @@ class MicroBit
*/
int random(int max);
/**
* Period callback. Used by MicroBitDisplay, FiberScheduler and I2C sensors to
* provide a power efficient sense of time.
*/
void systemTick();
/**
* System tasks to be executed by the idle thread when the Micro:Bit isn't busy or when data needs to be read.
*/
void systemTasks();
/**
* add a component to the array of system components which invocate the systemTick member function during a systemTick
*
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
int addSystemComponent(MicroBitComponent *component);
/**
* remove a component from the array of system components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
int removeSystemComponent(MicroBitComponent *component);
/**
* add a component to the array of of idle thread components.
* isIdleCallbackNeeded is polled during a systemTick to determine if the idle thread should jump to the front of the queue
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
int addIdleComponent(MicroBitComponent *component);
/**
* remove a component from the array of idle thread components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
int removeIdleComponent(MicroBitComponent *component);
/*
* Reconfigures the ticker to the given speed in milliseconds.
* @param speedMs the speed in milliseconds
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if speedUs < 1
*
* @note this will also modify the value that is added to ticks in MiroBitFiber:scheduler_tick()
*/
int setTickPeriod(int speedMs);
/*
* Returns the currently used tick speed in milliseconds
*/
int getTickPeriod();
/**
* Determine the time since this MicroBit was last reset.
*
@ -301,21 +230,48 @@ class MicroBit
/**
* Triggers a microbit panic where an infinite loop will occur swapping between the panicFace and statusCode if provided.
*
*
* @param statusCode the status code of the associated error. Status codes must be in the range 0-255.
*/
void panic(int statusCode = 0);
/**
* add a component to the array of components which invocate the systemTick member function during a systemTick
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
* @note This interface is now deprecated. See fiber_add_system_component().
*/
int addSystemComponent(MicroBitComponent *component);
/**
* remove a component from the array of components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMTER is returned if the given component has not been previous added.
* @note This interface is now deprecated. See fiber_remove_system_component().
*/
int removeSystemComponent(MicroBitComponent *component);
/**
* add a component to the array of components which invocate the systemTick member function during a systemTick
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
* @note This interface is now deprecated. See fiber_add_idle_component().
*/
int addIdleComponent(MicroBitComponent *component);
/**
* remove a component from the array of components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMTER is returned if the given component has not been previous added.
* @note This interface is now deprecated. See fiber_remove_idle_component().
*/
int removeIdleComponent(MicroBitComponent *component);
};
// Definition of the global instance of the MicroBit class.
// Using this as a variation on the singleton pattern, just to make
// code integration a little bit easier for third parties.
extern MicroBit uBit;
// Entry point for application programs. Called after the super-main function
// has initialized the device and runtime environment.
extern "C" void app_main();
#endif

@ -150,6 +150,7 @@ class MicroBitAccelerometer : public MicroBitComponent
MMA8653Sample sample; // The last sample read.
DigitalIn int1; // Data ready interrupt.
float pitch; // Pitch of the device, in radians.
MicroBitI2C& i2c; // The I2C interface to use.
float roll; // Roll of the device, in radians.
uint8_t sigma; // the number of ticks that the instantaneous gesture has been stable.
BasicGesture lastGesture; // the last, stable gesture recorded.
@ -169,7 +170,7 @@ class MicroBitAccelerometer : public MicroBitComponent
* accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR)
* @endcode
*/
MicroBitAccelerometer(uint16_t id, uint16_t address);
MicroBitAccelerometer(uint16_t id, uint16_t address, MicroBitI2C &_i2c);
/**
* Configures the accelerometer for G range and sample rate defined

@ -22,7 +22,7 @@ class MicroBitAccelerometerService
* Create a representation of the AccelerometerService
* @param _ble The instance of a BLE device that we're running on.
*/
MicroBitAccelerometerService(BLEDevice &_ble);
MicroBitAccelerometerService(BLEDevice &_ble, MicroBitAccelerometer &_acclerometer, MicroBitMessageBus &messageBus);
private:
@ -38,7 +38,8 @@ class MicroBitAccelerometerService
void accelerometerUpdate(MicroBitEvent e);
// Bluetooth stack we're running on.
BLEDevice &ble;
BLEDevice &ble;
MicroBitAccelerometer &accelerometer;
// memory for our 8 bit control characteristics.
uint16_t accelerometerDataCharacteristicBuffer[3];

@ -76,7 +76,7 @@ class MicroBitBLEManager : MicroBitComponent
* uBit.init();
* @endcode
*/
void init(ManagedString deviceName, ManagedString serialNumber, bool enableBonding);
void init(ManagedString deviceName, ManagedString serialNumber, MicroBitMessageBus& messageBus, bool enableBonding);
/**
* Change the output power level of the transmitter to the given value.
@ -92,8 +92,9 @@ class MicroBitBLEManager : MicroBitComponent
* of the micro:bit in cases where BLE is disabled during normal operation.
*
* @param display a MicroBitDisplay to use when displaying pairing information.
* @prarm authorizationButton The button to use to authorise a pairing request.
*/
void pairingMode(MicroBitDisplay &display);
void pairingMode(MicroBitDisplay &display, MicroBitButton &authorisationButton);
/**
* Makes the micro:bit discoverable via BLE, such that bonded devices can connect

@ -22,7 +22,7 @@ class MicroBitButtonService
* Create a representation of the ButtonService
* @param _ble The instance of a BLE device that we're running on.
*/
MicroBitButtonService(BLEDevice &_ble);
MicroBitButtonService(BLEDevice &_ble, MicroBitMessageBus &messageBus);
private:

@ -4,6 +4,7 @@
#include "mbed.h"
#include "MicroBitComponent.h"
#include "MicroBitCoordinateSystem.h"
#include "MicroBitAccelerometer.h"
/**
* Relevant pin assignments
@ -122,12 +123,14 @@ class MicroBitCompass : public MicroBitComponent
* Used to track asynchronous events in the event bus.
*/
uint16_t address; // I2C address of the magnetmometer.
uint16_t samplePeriod; // The time between samples, in millseconds.
uint16_t address; // I2C address of the magnetmometer.
uint16_t samplePeriod; // The time between samples, in millseconds.
CompassSample average; // Centre point of sample data.
CompassSample sample; // The latest sample data recorded.
DigitalIn int1; // Data ready interrupt.
CompassSample average; // Centre point of sample data.
CompassSample sample; // The latest sample data recorded.
DigitalIn int1; // Data ready interrupt.
MicroBitI2C& i2c; // The I2C interface the sensor is connected to.
MicroBitAccelerometer& accelerometer; // The accelerometer to use for tilt compensation.
public:
@ -149,7 +152,7 @@ class MicroBitCompass : public MicroBitComponent
* MICROBIT_COMPASS_EVT_CAL_END // triggered when calibration has finished.
* @endcode
*/
MicroBitCompass(uint16_t id, uint16_t address);
MicroBitCompass(uint16_t id, uint16_t address, MicroBitI2C& _i2c, MicroBitAccelerometer &_accelerometer);
/**
* Configures the compass for the sample rate defined

@ -6,6 +6,7 @@
#define MICROBIT_COMPAT_H
#include "ErrorNo.h"
#include "MicroBitDevice.h"
#define PI 3.14159265359
@ -67,5 +68,4 @@ int string_reverse(char *s);
*/
void itoa(int n, char *s);
#endif

@ -52,6 +52,10 @@
#define MICROBIT_ID_NOTIFY_ONE 1022 // Notfication channel, for general purpose synchronisation
#define MICROBIT_ID_NOTIFY 1023 // Notfication channel, for general purpose synchronisation
// Universal flags used as part of the status field
#define MICROBIT_COMPONENT_RUNNING 0x01
class MicroBitComponent
{
protected:

@ -274,6 +274,7 @@
#ifndef MICROBIT_BLE_MAXIMUM_SCROLLTEXT
#define MICROBIT_BLE_MAXIMUM_SCROLLTEXT 20
#endif
//
// Accelerometer options
//

@ -106,7 +106,9 @@ class MicroBitDisplay : public MicroBitComponent
uint8_t errorTimeout;
Timeout renderTimer;
MicroBitFont font;
//
// Reference to the first display created. Used as a defaut output channel, such as panic().
static MicroBitDisplay *defaultDisplay;
//
// State used by all animation routines.
@ -551,6 +553,17 @@ public:
*/
void clear();
/**
* Displays "=(" and an accompanying status code on the default display.
* @param statusCode the appropriate status code - 0 means no code will be displayed. Status codes must be in the range 0-255.
*
* Example:
* @code
* uBit.display.error(20);
* @endcode
*/
static void panic(int statusCode);
/**
* Displays "=(" and an accompanying status code infinitely.
* @param statusCode the appropriate status code - 0 means no code will be displayed. Status codes must be in the range 0-255.
@ -562,7 +575,7 @@ public:
*/
void error(int statusCode);
/**
/**
* Defines the length of time that the device will remain in a error state before resetting.
* @param iteration The number of times the error code will be displayed before resetting. Set to zero to remain in error state forever.
*
@ -574,13 +587,16 @@ public:
void setErrorTimeout(int iterations);
/**
* Updates the font property of this object with the new font.
* @param font the new font that will be used to render characters..
* Updates the font that will be used for display operations.
* DEPRECATED: Please use MicroBitFont::setSystemFont() instead.
*
* @param font the new font that will be used to render characters.
*/
void setFont(MicroBitFont font);
/**
* Retreives the font object used for rendering characters on the display.
* DEPRECATED: Please use MicroBitFont::getSystemFont() instead.
*/
MicroBitFont getFont();

@ -30,7 +30,7 @@ class MicroBitEventService : public MicroBitComponent
* Create a representation of the EventService
* @param BLE The instance of a BLE device that we're running on.
*/
MicroBitEventService(BLEDevice &_ble);
MicroBitEventService(BLEDevice &_ble, MicroBitMessageBus &_messageBus);
/**
* Periodic callback from MicroBit scheduler.
@ -58,6 +58,7 @@ class MicroBitEventService : public MicroBitComponent
// Bluetooth stack we're running on.
BLEDevice &ble;
MicroBitMessageBus &messageBus;
// memory for our event characteristics.
EventServiceEvent clientEventBuffer;

@ -18,7 +18,7 @@
// stack for any long lived fibers with large stack
// Fiber Scheduler Flags
#define MICROBIT_FLAG_DATA_READY 0x01
#define MICROBIT_SCHEDULER_RUNNING 0x01
// Fiber Flags
#define MICROBIT_FIBER_FLAG_FOB 0x01
@ -70,13 +70,35 @@ struct Fiber
extern Fiber *currentFiber;
/**
* Initialises the Fiber scheduler.
* Creates a Fiber context around the calling thread, and adds it to the run queue as the current thread.
*
* This function must be called once only from the main thread, and before any other Fiber operation.
*/
void scheduler_init();
void scheduler_init(MicroBitMessageBus *_messageBus);
/*
* Reconfigures the system wide timer to the given period in milliseconds.
*
* @param speedMs the new period of the timer in milliseconds
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if speedMs < 1
*
* @note this will also modify the value that is added to ticks in MiroBitFiber:scheduler_tick()
*/
int scheduler_set_tick_period(int speedMs);
/*
* Returns the currently used tick speed in milliseconds
*/
int scheduler_get_tick_period();
/**
* Determines if the fiber scheduler is operational.
* @return 1 if the fber scheduler is running, 0 otherwise.
*/
int fiber_scheduler_running();
/**
* Exit point for all fibers.
@ -157,8 +179,9 @@ void scheduler_tick();
*
* @param id The ID field of the event to listen for (e.g. MICROBIT_ID_BUTTON_A)
* @param value The VALUE of the event to listen for (e.g. MICROBIT_BUTTON_EVT_CLICK)
* @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not associated with a MicroBitMessageBus.
*/
void fiber_wait_for_event(uint16_t id, uint16_t value);
int fiber_wait_for_event(uint16_t id, uint16_t value);
/**
* Executes the given function asynchronously if necessary.
@ -242,6 +265,36 @@ void idle();
*/
void idle_task();
/**
* add a component to the array of system components which invocate the systemTick member function during a systemTick
*
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
int fiber_add_system_component(MicroBitComponent *component);
/**
* remove a component from the array of system components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
int fiber_remove_system_component(MicroBitComponent *component);
/**
* add a component to the array of of idle thread components.
* isIdleCallbackNeeded is polled during a systemTick to determine if the idle thread should jump to the front of the queue
* @param component The component to add.
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
*/
int fiber_add_idle_component(MicroBitComponent *component);
/**
* remove a component from the array of idle thread components
* @param component The component to remove.
* @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previous added.
*/
int fiber_remove_idle_component(MicroBitComponent *component);
/**
* Determines if the processor is executing in interrupt context.
* @return true if any the processor is currently executing any interrupt service routine. False otherwise.
@ -266,9 +319,4 @@ extern "C" void restore_register_context(Cortex_M0_TCB *tcb);
*/
extern unsigned long ticks;
/**
* This variable is used to prioritise the systems' idle fibre to execute essential tasks.
*/
extern uint8_t fiber_flags;
#endif

@ -17,6 +17,7 @@ class MicroBitFont
public:
static const unsigned char* defaultFont;
static MicroBitFont systemFont;
const unsigned char* characters;
@ -37,6 +38,18 @@ class MicroBitFont
* Sets the characters to defaultFont characters and asciiEnd to MICROBIT_FONT_ASCII_END.
*/
MicroBitFont();
/**
* Changes the current system font to the one specified.
* @param font the new font that will be used to render characters..
*/
static void setSystemFont(MicroBitFont font);
/**
* Retreives the font object used for rendering characters on the display.
*/
static MicroBitFont getSystemFont();
};
#endif

@ -13,8 +13,9 @@
class MicroBitIO
{
public:
MicroBitPin P0;
MicroBitPin pin[0];
MicroBitPin P0;
MicroBitPin P1;
MicroBitPin P2;
MicroBitPin P3;

@ -35,7 +35,7 @@ class MicroBitIOPinService : public MicroBitComponent
* Create a representation of the IOPinService
* @param _ble The instance of a BLE device that we're running on.
*/
MicroBitIOPinService(BLEDevice &_ble);
MicroBitIOPinService(BLEDevice &_ble, MicroBitIO &_io);
/**
* periodic callback from MicroBit scheduler.
@ -91,6 +91,7 @@ class MicroBitIOPinService : public MicroBitComponent
// Bluetooth stack we're running on.
BLEDevice &ble;
MicroBitIO &io;
// memory for our 8 bit control characteristics.
uint32_t ioPinServiceADCharacteristicBuffer;

@ -22,8 +22,9 @@ class MicroBitLEDService
* Constructor.
* Create a representation of the LEDService
* @param BLE The instance of a BLE device that we're running on.
* @param display The instance of a MicroBitDisplay to interface with.
*/
MicroBitLEDService(BLEDevice &_ble);
MicroBitLEDService(BLEDevice &_ble, MicroBitDisplay &_display);
/**
* Callback. Invoked when any of our attributes are written via BLE.
@ -39,6 +40,7 @@ class MicroBitLEDService
// Bluetooth stack we're running on.
BLEDevice &ble;
MicroBitDisplay &display;
// memory for our 8 bit control characteristics.
uint8_t matrixCharacteristicBuffer[5];

@ -3,6 +3,7 @@
#include "mbed.h"
#include "MicroBitComponent.h"
#include "MicroBitMessageBus.h"
#define MICROBIT_LIGHT_SENSOR_CHAN_NUM 3
#define MICROBIT_LIGHT_SENSOR_AN_SET_TIME 4000

@ -23,7 +23,7 @@ class MicroBitMagnetometerService
* Create a representation of the MagnetometerService
* @param _ble The instance of a BLE device that we're running on.
*/
MicroBitMagnetometerService(BLEDevice &_ble);
MicroBitMagnetometerService(BLEDevice &_ble, MicroBitCompass &_compass, MicroBitMessageBus &messageBus);
private:
@ -47,6 +47,7 @@ class MicroBitMagnetometerService
// Bluetooth stack we're running on.
BLEDevice &ble;
MicroBitCompass &compass;
// memory for our 8 bit control characteristics.
int16_t magnetometerDataCharacteristicBuffer[3];

@ -33,6 +33,8 @@ class MicroBitMessageBus : public MicroBitComponent
{
public:
static MicroBitMessageBus *defaultMessageBus;
/**
* Default constructor.
* Anticipating only one MessageBus per device, as filtering is handled within the class.

@ -1,7 +1,9 @@
#ifndef MICROBIT_MULTI_BUTTON_H
#define MICROBIT_MULTI_BUTTON_H
#include "MicroBit.h"
#include "mbed.h"
#include "MicroBitButton.h"
#include "MicroBitMessageBus.h"
#define MICROBIT_MULTI_BUTTON_STATE_1 0x01
#define MICROBIT_MULTI_BUTTON_STATE_2 0x02
@ -57,7 +59,7 @@ class MicroBitMultiButton : public MicroBitComponent
* MICROBIT_BUTTON_EVT_HOLD
* @endcode
*/
MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t button2);
MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t button2, MicroBitMessageBus &messageBus);
/**
* Tests if this MultiButton is currently pressed.

@ -1,8 +1,13 @@
#ifndef MICROBIT_RADIO_H
#define MICROBIT_RADIO_H
class MicroBitRadio;
struct FrameBuffer;
#include "mbed.h"
#include "PacketBuffer.h"
#include "MicroBitRadioDatagram.h"
#include "MicroBitRadioEvent.h"
/**
* Provides a simple broadcast radio abstraction, built upon the raw nrf51822 RADIO module.
@ -46,6 +51,7 @@
// Events
#define MICROBIT_RADIO_EVT_DATAGRAM 1 // Event to signal that a new datagram has been received.
struct FrameBuffer
{
uint8_t length; // The length of the remaining bytes in the packet. includes protocol/version/group fields, excluding the length field itself.
@ -58,8 +64,6 @@ struct FrameBuffer
uint8_t rssi; // Received signal strength of this frame.
};
#include "MicroBitRadioDatagram.h"
#include "MicroBitRadioEvent.h"
class MicroBitRadio : MicroBitComponent
{
@ -72,7 +76,7 @@ class MicroBitRadio : MicroBitComponent
public:
MicroBitRadioDatagram datagram; // A simple datagram service.
MicroBitRadioEvent event; // A simple event handling service.
static MicroBitRadio *instance; // A singleton reference, used purely by the interrupt service routine.
static MicroBitRadio *instance; // A singleton reference, used purely by the interrupt service routine.
/**
* Constructor.

@ -18,14 +18,17 @@
class MicroBitRadioDatagram
{
FrameBuffer *rxQueue; // A linear list of incoming packets, queued awaiting processing.
MicroBitRadio &radio; // The underlying radio module used to send and receive data.
FrameBuffer *rxQueue; // A linear list of incoming packets, queued awaiting processing.
public:
/**
* Constructor.
*
* @param radio The underlying radio module used to send and receive data.
*/
MicroBitRadioDatagram();
MicroBitRadioDatagram(MicroBitRadio &r);
/**
* Retreives packet payload data into the given buffer.

@ -19,37 +19,62 @@
class MicroBitRadioEvent
{
bool suppressForwarding; // A private flag used to prevent event forwarding loops.
bool suppressForwarding; // A private flag used to prevent event forwarding loops.
MicroBitRadio &radio; // A reference to the underlying radio module to use.
public:
/**
* Constructor.
*/
MicroBitRadioEvent();
MicroBitRadioEvent(MicroBitRadio &r);
/**
* Associates the given MessageBus events with the radio channel.
* Once registered, all events matching the given registration sent to this micro:bit's
* MessageBus will be automatically retrasmitted on the radio.
* default MessageBus will be automaticlaly retrasmitted on the radio.
*
* @param id The ID of the events to register.
* @param value the VALUE of the event to register. use MICROBIT_EVT_ANY for all event values matching the given ID.
* @param value the VALUE of the event to register. use MICROBIT_EVT_ANY for all event values matching the given id.
*
* @return MICROBIT_OK on success.
* @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if no defult MessageBus is available.
*/
int listen(uint16_t id, uint16_t value);
/**
* Associates the given MessageBus events with the radio channel.
* Once registered, all events matching the given registration sent to the given
* MessageBus will be automaticlaly retrasmitted on the radio.
*
* @param id The ID of the events to register.
* @param value the VALUE of the event to register. use MICROBIT_EVT_ANY for all event values matching the given id.
* @param The message bus to listen for events on.
*
* @return MICROBIT_OK on success.
*/
int listen(uint16_t id, uint16_t value, MicroBitMessageBus &messageBus);
/**
* Disassociates the given MessageBus events with the radio channel.
*
* @param id The ID of the events to deregister.
* @param value the VALUE of the event to deregister. use MICROBIT_EVT_ANY for all event values matching the given ID.
*
* @return MICROBIT_OK on success.
* @return MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the default message bus does not exist.
*/
int ignore(uint16_t id, uint16_t value);
/**
* Disassociates the given MessageBus events with the radio channel.
*
* @param id The ID of the events to deregister.
* @param value the VALUE of the event to deregister. use MICROBIT_EVT_ANY for all event values matching the given ID.
* @param The message bus to deregister on.
*
* @return MICROBIT_OK on success.
*/
int ignore(uint16_t id, uint16_t value, MicroBitMessageBus &messageBus);
/**
* Protocol handler callback. This is called when the radio receives a packet marked as using the event protocol.
* This function process this packet, and fires the event contained inside onto the local MessageBus.

@ -22,7 +22,7 @@ class MicroBitTemperatureService
* Create a representation of the TempertureService
* @param _ble The instance of a BLE device that we're running on.
*/
MicroBitTemperatureService(BLEDevice &_ble);
MicroBitTemperatureService(BLEDevice &_ble, MicroBitThermometer &_thermometer, MicroBitMessageBus &messageBus);
/**
* Callback. Invoked when any of our attributes are written via BLE.
@ -37,7 +37,8 @@ class MicroBitTemperatureService
private:
// Bluetooth stack we're running on.
BLEDevice &ble;
BLEDevice &ble;
MicroBitThermometer &thermometer;
// memory for our 8 bit temperature characteristic.
int8_t temperatureDataCharacteristicBuffer;

@ -22,6 +22,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
"MicroBitThermometer.cpp"
"MicroBitIO.cpp"
"MicroBitCompat.cpp"
"MicroBitDevice.cpp"
"MicroBitImage.cpp"
"MicroBitDisplay.cpp"
"DynamicPwm.cpp"

@ -21,24 +21,6 @@
#pragma GCC diagnostic pop
#endif
/**
* custom function for panic for malloc & new due to scoping issue.
*/
void panic(int statusCode)
{
uBit.panic(statusCode);
}
/**
* Callback that performs a hard reset when a BLE GAP disconnect occurs.
* Only used when an explicit reset is invoked locally whilst a BLE connection is in progress.
* This allows for a clean diconnect of the BLE connection before resetting.
*/
void bleDisconnectionResetCallback(const Gap::DisconnectionCallbackParams_t *)
{
NVIC_SystemReset();
}
/**
* Perform a hard reset of the micro:bit.
* If BLE connected, then try to signal a disconnect first
@ -46,25 +28,9 @@ void bleDisconnectionResetCallback(const Gap::DisconnectionCallbackParams_t *)
void
microbit_reset()
{
if(uBit.ble && uBit.ble->getGapState().connected) {
uBit.ble->onDisconnection(bleDisconnectionResetCallback);
uBit.ble->gap().disconnect(Gap::REMOTE_USER_TERMINATED_CONNECTION);
// We should be reset by the disconnection callback, so we wait to
// allow that to happen. If it doesn't happen, then we fall through to the
// hard rest here. (For example there is a race condition where
// the remote device disconnects between us testing the connection
// state and re-setting the disconnection callback).
uBit.sleep(1000);
}
NVIC_SystemReset();
}
void bleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
{
uBit.ble->startAdvertising();
}
void MicroBit::onABListenerRegisteredEvent(MicroBitEvent evt)
{
(void) evt; // Unused parameter
@ -103,16 +69,16 @@ void MicroBit::onABListenerRegisteredEvent(MicroBitEvent evt)
* @endcode
*/
MicroBit::MicroBit() :
flags(0x00),
resetButton(MICROBIT_PIN_BUTTON_RESET),
i2c(MICROBIT_PIN_SDA, MICROBIT_PIN_SCL),
serial(USBTX, USBRX),
MessageBus(),
messageBus(),
display(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_WIDTH, MICROBIT_DISPLAY_HEIGHT),
buttonA(MICROBIT_ID_BUTTON_A,MICROBIT_PIN_BUTTON_A, MICROBIT_BUTTON_ALL_EVENTS),
buttonB(MICROBIT_ID_BUTTON_B,MICROBIT_PIN_BUTTON_B, MICROBIT_BUTTON_ALL_EVENTS),
buttonAB(MICROBIT_ID_BUTTON_AB,MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B),
accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR),
compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR),
buttonAB(MICROBIT_ID_BUTTON_AB,MICROBIT_ID_BUTTON_A,MICROBIT_ID_BUTTON_B, messageBus),
accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR, i2c),
compass(MICROBIT_ID_COMPASS, MAG3110_DEFAULT_ADDR,i2c,accelerometer),
thermometer(MICROBIT_ID_THERMOMETER),
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,
@ -125,6 +91,9 @@ MicroBit::MicroBit() :
radio(MICROBIT_ID_RADIO),
ble(NULL)
{
// Bring up soft reset functionality as soon as possible.
resetButton.mode(PullUp);
resetButton.fall(this, &MicroBit::reset);
}
/**
@ -140,25 +109,74 @@ MicroBit::MicroBit() :
*/
void MicroBit::init()
{
// Bring up our nested heap allocator.
microbit_heap_init();
// Bring up fiber scheduler
scheduler_init(&messageBus);
sleep(10);
// Load any stored calibration data from persistent storage.
MicroBitStorage s = MicroBitStorage();
MicroBitConfigurationBlock *b = s.getConfigurationBlock();
//if we have some calibrated data, calibrate the compass!
if(b->magic == MICROBIT_STORAGE_CONFIG_MAGIC)
{
if(b->compassCalibrationData != CompassSample(0,0,0))
compass.setCalibration(b->compassCalibrationData);
}
delete b;
// TODO: YUCK!!! MOVE THESE INTO THE RELEVANT COMPONENTS!!
//add the display to the systemComponent array
addSystemComponent(&uBit.display);
addSystemComponent(&display);
//add the compass and accelerometer to the idle array
addIdleComponent(&uBit.accelerometer);
addIdleComponent(&uBit.compass);
addIdleComponent(&uBit.MessageBus);
addIdleComponent(&accelerometer);
addIdleComponent(&compass);
addIdleComponent(&messageBus);
// Seed our random number generator
seedRandom();
tickPeriod = MICROBIT_DEFAULT_TICK_PERIOD;
// Register our compass calibration algorithm.
messageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CALIBRATE, this, &MicroBit::compassCalibrator, MESSAGE_BUS_LISTENER_IMMEDIATE);
messageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_ID_BUTTON_AB, this, &MicroBit::onABListenerRegisteredEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
// Start refreshing the Matrix Display
systemTicker.attach_us(this, &MicroBit::systemTick, tickPeriod * 1000);
#if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
// Test if we need to enter BLE pairing mode...
int i=0;
while (buttonA.isPressed() && buttonB.isPressed() && i<10)
{
sleep(100);
i++;
// Register our compass calibration algorithm.
MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CALIBRATE, this, &MicroBit::compassCalibrator, MESSAGE_BUS_LISTENER_IMMEDIATE);
MessageBus.listen(MICROBIT_ID_MESSAGE_BUS_LISTENER, MICROBIT_ID_BUTTON_AB, this, &MicroBit::onABListenerRegisteredEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
if (i == 10)
{
// 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
#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
}
/**
@ -208,8 +226,8 @@ void MicroBit::compassCalibrator(MicroBitEvent)
cursor.on = (cursor.on + 1) % 4;
// take a snapshot of the current accelerometer data.
int x = uBit.accelerometer.getX();
int y = uBit.accelerometer.getY();
int x = accelerometer.getX();
int y = accelerometer.getY();
// Deterine the position of the user controlled pixel on the screen.
if (x < -PIXEL2_THRESHOLD)
@ -245,7 +263,7 @@ void MicroBit::compassCalibrator(MicroBitEvent)
img.setPixelValue(cursor.x, cursor.y, 255);
// Update the buffer to the screen.
uBit.display.image.paste(img,0,0,0);
display.image.paste(img,0,0,0);
// test if we need to update the state at the users position.
for (int i=0; i<PERIMETER_POINTS; i++)
@ -264,7 +282,7 @@ void MicroBit::compassCalibrator(MicroBitEvent)
}
}
uBit.sleep(100);
sleep(100);
}
// We have enough sample data to make a fairly accurate calibration.
@ -361,6 +379,15 @@ ManagedString MicroBit::getSerial()
*/
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.
sleep(100);
}
microbit_reset();
}
@ -387,7 +414,7 @@ int MicroBit::sleep(int milliseconds)
if(milliseconds < 0)
return MICROBIT_INVALID_PARAMETER;
if (flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
if (fiber_scheduler_running())
fiber_sleep(milliseconds);
else
wait_ms(milliseconds);
@ -418,7 +445,6 @@ int MicroBit::random(int max)
{
uint32_t m, result;
//return MICROBIT_INVALID_VALUE if max is <= 0...
if(max <= 0)
return MICROBIT_INVALID_PARAMETER;
@ -468,7 +494,7 @@ void MicroBit::seedRandom()
{
randomValue = 0;
if(uBit.ble)
if(ble)
{
// If Bluetooth is enabled, we need to go through the Nordic software to safely do this.
uint32_t result = sd_rand_application_vector_get((uint8_t*)&randomValue, sizeof(randomValue));
@ -510,42 +536,6 @@ void MicroBit::seedRandom(uint32_t seed)
}
/**
* Periodic callback. Used by MicroBitDisplay, FiberScheduler and buttons.
*/
void MicroBit::systemTick()
{
// Scheduler callback. We do this here just as a single timer is more efficient. :-)
if (uBit.flags & MICROBIT_FLAG_SCHEDULER_RUNNING)
scheduler_tick();
//work out if any idle components need processing, if so prioritise the idle thread
for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
if(idleThreadComponents[i] != NULL && idleThreadComponents[i]->isIdleCallbackNeeded())
{
fiber_flags |= MICROBIT_FLAG_DATA_READY;
break;
}
//update any components in the systemComponents array
for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++)
if(systemTickComponents[i] != NULL)
systemTickComponents[i]->systemTick();
}
/**
* System tasks to be executed by the idle thread when the Micro:Bit isn't busy or when data needs to be read.
*/
void MicroBit::systemTasks()
{
//call the idleTick member function indiscriminately
for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
if(idleThreadComponents[i] != NULL)
idleThreadComponents[i]->idleTick();
fiber_flags &= ~MICROBIT_FLAG_DATA_READY;
}
/**
* add a component to the array of components which invocate the systemTick member function during a systemTick
* @param component The component to add.
@ -554,16 +544,7 @@ void MicroBit::systemTasks()
*/
int MicroBit::addSystemComponent(MicroBitComponent *component)
{
int i = 0;
while(systemTickComponents[i] != NULL && i < MICROBIT_SYSTEM_COMPONENTS)
i++;
if(i == MICROBIT_SYSTEM_COMPONENTS)
return MICROBIT_NO_RESOURCES;
systemTickComponents[i] = component;
return MICROBIT_OK;
return fiber_add_system_component(component);
}
/**
@ -574,17 +555,7 @@ int MicroBit::addSystemComponent(MicroBitComponent *component)
*/
int MicroBit::removeSystemComponent(MicroBitComponent *component)
{
int i = 0;
while(systemTickComponents[i] != component && i < MICROBIT_SYSTEM_COMPONENTS)
i++;
if(i == MICROBIT_SYSTEM_COMPONENTS)
return MICROBIT_INVALID_PARAMETER;
systemTickComponents[i] = NULL;
return MICROBIT_OK;
return fiber_remove_system_component(component);
}
/**
@ -595,17 +566,7 @@ int MicroBit::removeSystemComponent(MicroBitComponent *component)
*/
int MicroBit::addIdleComponent(MicroBitComponent *component)
{
int i = 0;
while(idleThreadComponents[i] != NULL && i < MICROBIT_IDLE_COMPONENTS)
i++;
if(i == MICROBIT_IDLE_COMPONENTS)
return MICROBIT_NO_RESOURCES;
idleThreadComponents[i] = component;
return MICROBIT_OK;
return fiber_add_idle_component(component);
}
/**
@ -616,47 +577,9 @@ int MicroBit::addIdleComponent(MicroBitComponent *component)
*/
int MicroBit::removeIdleComponent(MicroBitComponent *component)
{
int i = 0;
while(idleThreadComponents[i] != component && i < MICROBIT_IDLE_COMPONENTS)
i++;
if(i == MICROBIT_IDLE_COMPONENTS)
return MICROBIT_INVALID_PARAMETER;
idleThreadComponents[i] = NULL;
return MICROBIT_OK;
return fiber_remove_idle_component(component);
}
/*
* Reconfigures the ticker to the given speed in milliseconds.
* @param speedMs the speed in milliseconds