First cut at a build without a global MicroBit singleton
This commit is contained in:
parent
fdbc41d6b6
commit
5231b5f526
124
inc/MicroBit.h
124
inc/MicroBit.h
|
@ -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,17 +230,43 @@ 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);
|
||||
|
||||
// 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;
|
||||
/**
|
||||
* 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);
|
||||
};
|
||||
|
||||
// Entry point for application programs. Called after the super-main function
|
||||
// has initialized the device and runtime environment.
|
||||
|
@ -319,3 +274,4 @@ 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,26 +19,40 @@
|
|||
|
||||
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, 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);
|
||||
int listen(uint16_t id, uint16_t value, MicroBitMessageBus &messageBus);
|
||||
|
||||
/**
|
||||
* Disassociates the given MessageBus events with the radio channel.
|
||||
|
@ -46,10 +60,21 @@ class MicroBitRadioEvent
|
|||
* @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;
|
||||
|
||||
// Start refreshing the Matrix Display
|
||||
systemTicker.attach_us(this, &MicroBit::systemTick, tickPeriod * 1000);
|
||||
|
||||
// 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);
|
||||
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 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++;
|
||||
|
||||
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
|
||||
* @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 MicroBit::setTickPeriod(int speedMs)
|
||||
{
|
||||
if(speedMs < 1)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
uBit.systemTicker.detach();
|
||||
|
||||
uBit.systemTicker.attach_us(this, &MicroBit::systemTick, speedMs * 1000);
|
||||
|
||||
tickPeriod = speedMs;
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the currently used tick speed in milliseconds
|
||||
*/
|
||||
int MicroBit::getTickPeriod()
|
||||
{
|
||||
return tickPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the time since this MicroBit was last reset.
|
||||
|
@ -682,12 +605,11 @@ const char *MicroBit::systemVersion()
|
|||
}
|
||||
|
||||
/**
|
||||
* Triggers a microbit panic where an infinite loop will occur swapping between the panicFace and statusCode if provided.
|
||||
*
|
||||
* Triggers a microbit panic. All functionality will cease, and a sad face displayed along with an error code.
|
||||
* @param statusCode the status code of the associated error. Status codes must be in the range 0-255.
|
||||
*/
|
||||
void MicroBit::panic(int statusCode)
|
||||
{
|
||||
//show error and enter infinite while
|
||||
uBit.display.error(statusCode);
|
||||
display.error(statusCode);
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ int MicroBitAccelerometer::writeCommand(uint8_t reg, uint8_t value)
|
|||
command[0] = reg;
|
||||
command[1] = value;
|
||||
|
||||
return uBit.i2c.write(address, (const char *)command, 2);
|
||||
return i2c.write(address, (const char *)command, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,11 +112,11 @@ int MicroBitAccelerometer::readCommand(uint8_t reg, uint8_t* buffer, int length)
|
|||
if (buffer == NULL || length <= 0 )
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
result = uBit.i2c.write(address, (const char *)®, 1, true);
|
||||
result = i2c.write(address, (const char *)®, 1, true);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
result = uBit.i2c.read(address, (char *)buffer, length);
|
||||
result = i2c.read(address, (char *)buffer, length);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
|
@ -134,7 +134,7 @@ int MicroBitAccelerometer::readCommand(uint8_t reg, uint8_t* buffer, int length)
|
|||
* accelerometer(MICROBIT_ID_ACCELEROMETER, MMA8653_DEFAULT_ADDR)
|
||||
* @endcode
|
||||
*/
|
||||
MicroBitAccelerometer::MicroBitAccelerometer(uint16_t id, uint16_t address) : sample(), int1(MICROBIT_PIN_ACCEL_DATA_READY)
|
||||
MicroBitAccelerometer::MicroBitAccelerometer(uint16_t id, uint16_t address, MicroBitI2C& _i2c) : sample(), int1(MICROBIT_PIN_ACCEL_DATA_READY), i2c(_i2c)
|
||||
{
|
||||
// Store our identifiers.
|
||||
this->id = id;
|
||||
|
@ -157,7 +157,7 @@ MicroBitAccelerometer::MicroBitAccelerometer(uint16_t id, uint16_t address) : sa
|
|||
|
||||
// Configure and enable the accelerometer.
|
||||
if (this->configure() == MICROBIT_OK)
|
||||
uBit.flags |= MICROBIT_FLAG_ACCELEROMETER_RUNNING;
|
||||
status |= MICROBIT_COMPONENT_RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -576,7 +576,7 @@ int MicroBitAccelerometer::isIdleCallbackNeeded()
|
|||
*/
|
||||
MicroBitAccelerometer::~MicroBitAccelerometer()
|
||||
{
|
||||
uBit.removeIdleComponent(this);
|
||||
fiber_remove_idle_component(this);
|
||||
}
|
||||
|
||||
const MMA8653SampleRangeConfig MMA8653SampleRange[MMA8653_SAMPLE_RANGES] = {
|
||||
|
|
|
@ -28,7 +28,7 @@ MicroBitButton::MicroBitButton(uint16_t id, PinName name, MicroBitButtonEventCon
|
|||
this->eventConfiguration = eventConfiguration;
|
||||
this->downStartTime = 0;
|
||||
this->sigma = 0;
|
||||
uBit.addSystemComponent(this);
|
||||
fiber_add_system_component(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,5 +128,5 @@ int MicroBitButton::isPressed()
|
|||
*/
|
||||
MicroBitButton::~MicroBitButton()
|
||||
{
|
||||
uBit.removeSystemComponent(this);
|
||||
fiber_remove_system_component(this);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* MICROBIT_COMPASS_EVT_CAL_END // triggered when calibration has finished.
|
||||
* @endcode
|
||||
*/
|
||||
MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sample(), int1(MICROBIT_PIN_COMPASS_DATA_READY)
|
||||
MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address, MicroBitI2C& _i2c, MicroBitAccelerometer& _accelerometer) : average(), sample(), int1(MICROBIT_PIN_COMPASS_DATA_READY), i2c(_i2c), accelerometer(_accelerometer)
|
||||
{
|
||||
this->id = id;
|
||||
this->address = address;
|
||||
|
@ -34,7 +34,7 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
|
|||
status &= ~MICROBIT_COMPASS_STATUS_CALIBRATED;
|
||||
|
||||
// Indicate that we're up and running.
|
||||
uBit.flags |= MICROBIT_FLAG_COMPASS_RUNNING;
|
||||
status |= MICROBIT_COMPONENT_RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,7 @@ int MicroBitCompass::writeCommand(uint8_t reg, uint8_t value)
|
|||
command[0] = reg;
|
||||
command[1] = value;
|
||||
|
||||
return uBit.i2c.write(address, (const char *)command, 2);
|
||||
return i2c.write(address, (const char *)command, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,11 +69,11 @@ int MicroBitCompass::readCommand(uint8_t reg, uint8_t* buffer, int length)
|
|||
if (buffer == NULL || length <= 0)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
result = uBit.i2c.write(address, (const char *)®, 1, true);
|
||||
result = i2c.write(address, (const char *)®, 1, true);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
result = uBit.i2c.read(address, (char *)buffer, length);
|
||||
result = i2c.read(address, (char *)buffer, length);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
|
@ -94,14 +94,14 @@ int MicroBitCompass::read16(uint8_t reg)
|
|||
int result;
|
||||
|
||||
cmd[0] = reg;
|
||||
result = uBit.i2c.write(address, (const char *)cmd, 1);
|
||||
result = i2c.write(address, (const char *)cmd, 1);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x00;
|
||||
|
||||
result = uBit.i2c.read(address, (char *)cmd, 2);
|
||||
result = i2c.read(address, (char *)cmd, 2);
|
||||
if (result !=0)
|
||||
return MICROBIT_I2C_ERROR;
|
||||
|
||||
|
@ -153,8 +153,8 @@ int MicroBitCompass::heading()
|
|||
calibrate();
|
||||
|
||||
// Precompute the tilt compensation parameters to improve readability.
|
||||
float phi = uBit.accelerometer.getRollRadians();
|
||||
float theta = uBit.accelerometer.getPitchRadians();
|
||||
float phi = accelerometer.getRollRadians();
|
||||
float theta = accelerometer.getPitchRadians();
|
||||
float x = (float) getX(NORTH_EAST_DOWN);
|
||||
float y = (float) getY(NORTH_EAST_DOWN);
|
||||
float z = (float) getZ(NORTH_EAST_DOWN);
|
||||
|
@ -314,7 +314,7 @@ int MicroBitCompass::configure()
|
|||
break;
|
||||
|
||||
// Perform a power efficient sleep...
|
||||
uBit.sleep(100);
|
||||
MicroBit::sleep(100);
|
||||
}
|
||||
|
||||
// Find the nearest sample rate to that specified.
|
||||
|
@ -560,7 +560,7 @@ int MicroBitCompass::isIdleCallbackNeeded()
|
|||
*/
|
||||
MicroBitCompass::~MicroBitCompass()
|
||||
{
|
||||
uBit.removeIdleComponent(this);
|
||||
fiber_remove_idle_component(this);
|
||||
}
|
||||
|
||||
const MAG3110SampleRateConfig MAG3110SampleRate[MAG3110_SAMPLE_RATES] = {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "nrf_gpio.h"
|
||||
|
||||
const int timings[MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH] = {1, 23, 70, 163, 351, 726, 1476, 2976};
|
||||
MicroBitDisplay *MicroBitDisplay::defaultDisplay = NULL;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -24,7 +25,6 @@ const int timings[MICROBIT_DISPLAY_GREYSCALE_BIT_DEPTH] = {1, 23, 70, 163, 351,
|
|||
* @endcode
|
||||
*/
|
||||
MicroBitDisplay::MicroBitDisplay(uint16_t id, uint8_t x, uint8_t y) :
|
||||
font(),
|
||||
image(x*2,y)
|
||||
{
|
||||
//set pins as output
|
||||
|
@ -47,7 +47,10 @@ MicroBitDisplay::MicroBitDisplay(uint16_t id, uint8_t x, uint8_t y) :
|
|||
|
||||
this->lightSensor = NULL;
|
||||
|
||||
uBit.flags |= MICROBIT_FLAG_DISPLAY_RUNNING;
|
||||
if (!this->defaultDisplay)
|
||||
this->defaultDisplay = this;
|
||||
|
||||
status |= MICROBIT_COMPONENT_RUNNING;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -58,7 +61,7 @@ MicroBitDisplay::MicroBitDisplay(uint16_t id, uint8_t x, uint8_t y) :
|
|||
*/
|
||||
void MicroBitDisplay::systemTick()
|
||||
{
|
||||
if(!(uBit.flags & MICROBIT_FLAG_DISPLAY_RUNNING))
|
||||
if(!(status & MICROBIT_COMPONENT_RUNNING))
|
||||
return;
|
||||
|
||||
if(mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
|
||||
|
@ -148,7 +151,7 @@ void MicroBitDisplay::render()
|
|||
|
||||
//timer does not have enough resolution for brightness of 1. 23.53 us
|
||||
if(brightness != MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS && brightness > MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS)
|
||||
renderTimer.attach_us(this, &MicroBitDisplay::renderFinish, (((brightness * 950) / (MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS)) * uBit.getTickPeriod()));
|
||||
renderTimer.attach_us(this, &MicroBitDisplay::renderFinish, (((brightness * 950) / (MICROBIT_DISPLAY_MAXIMUM_BRIGHTNESS)) * scheduler_get_tick_period()));
|
||||
|
||||
//this will take around 23us to execute
|
||||
if(brightness <= MICROBIT_DISPLAY_MINIMUM_BRIGHTNESS)
|
||||
|
@ -934,16 +937,16 @@ void MicroBitDisplay::setDisplayMode(DisplayMode mode)
|
|||
if(mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
|
||||
{
|
||||
//to reduce the artifacts on the display - increase the tick
|
||||
if(uBit.getTickPeriod() != MICROBIT_LIGHT_SENSOR_TICK_PERIOD)
|
||||
uBit.setTickPeriod(MICROBIT_LIGHT_SENSOR_TICK_PERIOD);
|
||||
if(scheduler_get_tick_period() != MICROBIT_LIGHT_SENSOR_TICK_PERIOD)
|
||||
scheduler_set_tick_period(MICROBIT_LIGHT_SENSOR_TICK_PERIOD);
|
||||
}
|
||||
|
||||
if(this->mode == DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE && mode != DISPLAY_MODE_BLACK_AND_WHITE_LIGHT_SENSE)
|
||||
{
|
||||
|
||||
//if we previously were in light sense mode - return to our default.
|
||||
if(uBit.getTickPeriod() != MICROBIT_DEFAULT_TICK_PERIOD)
|
||||
uBit.setTickPeriod(MICROBIT_DEFAULT_TICK_PERIOD);
|
||||
if(scheduler_get_tick_period() != FIBER_TICK_PERIOD_MS)
|
||||
scheduler_set_tick_period(FIBER_TICK_PERIOD_MS);
|
||||
|
||||
delete this->lightSensor;
|
||||
|
||||
|
@ -1000,10 +1003,10 @@ void MicroBitDisplay::rotateTo(DisplayRotation rotation)
|
|||
*/
|
||||
void MicroBitDisplay::enable()
|
||||
{
|
||||
if(!(uBit.flags & MICROBIT_FLAG_DISPLAY_RUNNING))
|
||||
if(!(status & MICROBIT_COMPONENT_RUNNING))
|
||||
{
|
||||
setBrightness(brightness);
|
||||
uBit.flags |= MICROBIT_FLAG_DISPLAY_RUNNING; //set the display running flag
|
||||
status |= MICROBIT_COMPONENT_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1018,10 +1021,8 @@ void MicroBitDisplay::enable()
|
|||
*/
|
||||
void MicroBitDisplay::disable()
|
||||
{
|
||||
if(uBit.flags & MICROBIT_FLAG_DISPLAY_RUNNING)
|
||||
{
|
||||
uBit.flags &= ~MICROBIT_FLAG_DISPLAY_RUNNING; //unset the display running flag
|
||||
}
|
||||
if(status & MICROBIT_COMPONENT_RUNNING)
|
||||
status &= ~MICROBIT_COMPONENT_RUNNING; //unset the display running flag
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1053,7 +1054,22 @@ void MicroBitDisplay::setErrorTimeout(int iterations)
|
|||
}
|
||||
|
||||
/**
|
||||
* Displays "=(" and an accompanying status code infinitely.
|
||||
* 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
|
||||
*/
|
||||
void MicroBitDisplay::panic(int statusCode)
|
||||
{
|
||||
if(MicroBitDisplay::defaultDisplay)
|
||||
defaultDisplay->error(statusCode);
|
||||
|
||||
}
|
||||
/**
|
||||
* 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:
|
||||
|
@ -1063,15 +1079,14 @@ void MicroBitDisplay::setErrorTimeout(int iterations)
|
|||
*/
|
||||
void MicroBitDisplay::error(int statusCode)
|
||||
{
|
||||
extern InterruptIn resetButton;
|
||||
DigitalIn resetButton(MICROBIT_PIN_BUTTON_RESET);
|
||||
resetButton.mode(PullUp);
|
||||
|
||||
__disable_irq(); //stop ALL interrupts
|
||||
|
||||
if(statusCode < 0 || statusCode > 255)
|
||||
statusCode = 0;
|
||||
|
||||
disable(); //relinquish PWMOut's control
|
||||
|
||||
uint8_t strobeRow = 0;
|
||||
uint8_t strobeBitMsk = MICROBIT_DISPLAY_ROW_RESET;
|
||||
uint8_t count = errorTimeout ? errorTimeout : 1;
|
||||
|
@ -1122,10 +1137,8 @@ void MicroBitDisplay::error(int statusCode)
|
|||
nrf_gpio_port_write(NRF_GPIO_PORT_SELECT_PORT0, ~coldata<<4 & 0xF0); //set port 0 4-7
|
||||
nrf_gpio_port_write(NRF_GPIO_PORT_SELECT_PORT1, strobeBitMsk | (~coldata>>4 & 0x1F)); //set port 1 8-12
|
||||
|
||||
//set i to an obscene number.
|
||||
i = 1000;
|
||||
|
||||
//burn cycles
|
||||
i = 1000;
|
||||
while(i>0)
|
||||
{
|
||||
// Check if the reset button has been pressed. Interrupts are disabled, so the normal method can't be relied upon...
|
||||
|
@ -1155,7 +1168,7 @@ void MicroBitDisplay::error(int statusCode)
|
|||
*/
|
||||
void MicroBitDisplay::setFont(MicroBitFont font)
|
||||
{
|
||||
this->font = font;
|
||||
MicroBitFont::setSystemFont(font);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1163,7 +1176,7 @@ void MicroBitDisplay::setFont(MicroBitFont font)
|
|||
*/
|
||||
MicroBitFont MicroBitDisplay::getFont()
|
||||
{
|
||||
return this->font;
|
||||
return MicroBitFont::getSystemFont();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1201,5 +1214,5 @@ int MicroBitDisplay::readLightLevel()
|
|||
*/
|
||||
MicroBitDisplay::~MicroBitDisplay()
|
||||
{
|
||||
uBit.removeSystemComponent(this);
|
||||
fiber_remove_system_component(this);
|
||||
}
|
||||
|
|
|
@ -38,15 +38,15 @@ MicroBitEvent::MicroBitEvent()
|
|||
}
|
||||
|
||||
/**
|
||||
* Fires the represented event onto the message bus.
|
||||
* Fires the represented event onto the default message bus.
|
||||
*/
|
||||
void MicroBitEvent::fire(MicroBitEventLaunchMode mode)
|
||||
{
|
||||
if (mode == CREATE_AND_QUEUE)
|
||||
uBit.MessageBus.send(*this);
|
||||
MicroBitMessageBus::defaultMessageBus->send(*this);
|
||||
|
||||
else if (mode == CREATE_AND_FIRE)
|
||||
uBit.MessageBus.process(*this);
|
||||
MicroBitMessageBus::defaultMessageBus->process(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -14,27 +14,43 @@
|
|||
* required to be defined here to allow persistence during context switches.
|
||||
*/
|
||||
Fiber *currentFiber = NULL; // The context in which the current fiber is executing.
|
||||
Fiber *forkedFiber = NULL; // The context in which a newly created child fiber is executing.
|
||||
Fiber *idleFiber = NULL; // IDLE task - performs a power efficient sleep, and system maintenance tasks.
|
||||
static Fiber *forkedFiber = NULL; // The context in which a newly created child fiber is executing.
|
||||
static Fiber *idleFiber = NULL; // IDLE task - performs a power efficient sleep, and system maintenance tasks.
|
||||
|
||||
/*
|
||||
* Scheduler state.
|
||||
*/
|
||||
Fiber *runQueue = NULL; // The list of runnable fibers.
|
||||
Fiber *sleepQueue = NULL; // The list of blocked fibers waiting on a fiber_sleep() operation.
|
||||
Fiber *waitQueue = NULL; // The list of blocked fibers waiting on an event.
|
||||
Fiber *fiberPool = NULL; // Pool of unused fibers, just waiting for a job to do.
|
||||
static Fiber *runQueue = NULL; // The list of runnable fibers.
|
||||
static Fiber *sleepQueue = NULL; // The list of blocked fibers waiting on a fiber_sleep() operation.
|
||||
static Fiber *waitQueue = NULL; // The list of blocked fibers waiting on an event.
|
||||
static Fiber *fiberPool = NULL; // Pool of unused fibers, just waiting for a job to do.
|
||||
|
||||
/*
|
||||
* Time since power on. Measured in milliseconds.
|
||||
* When stored as an unsigned long, this gives us approx 50 days between rollover, which is ample. :-)
|
||||
*/
|
||||
unsigned long ticks = 0;
|
||||
static unsigned int tickPeriod = FIBER_TICK_PERIOD_MS;
|
||||
|
||||
/*
|
||||
* Scheduler wide flags
|
||||
*/
|
||||
uint8_t fiber_flags = 0;
|
||||
static uint8_t fiber_flags = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Fibers may perform wait/notify semantics on events. If set, these operations will be permitted on this MicroBitMessageBus.
|
||||
*/
|
||||
static MicroBitMessageBus *messageBus = NULL;
|
||||
|
||||
// Array of components which are iterated during a system tick
|
||||
static MicroBitComponent* systemTickComponents[MICROBIT_SYSTEM_COMPONENTS];
|
||||
|
||||
// Array of components which are iterated during idle thread execution, isIdleCallbackNeeded is polled during a systemTick.
|
||||
static MicroBitComponent* idleThreadComponents[MICROBIT_IDLE_COMPONENTS];
|
||||
|
||||
// Periodic callback interrupt
|
||||
static Ticker fiberSchedulerTicker;
|
||||
|
||||
/**
|
||||
* Utility function to add the currenty running fiber to the given queue.
|
||||
|
@ -148,8 +164,12 @@ Fiber *getFiberContext()
|
|||
*
|
||||
* 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)
|
||||
{
|
||||
// Store a reference to the messageBus provided.
|
||||
// This parameter will be NULL if we're being run without a message bus.
|
||||
messageBus = _messageBus;
|
||||
|
||||
// Create a new fiber context
|
||||
currentFiber = getFiberContext();
|
||||
|
||||
|
@ -162,16 +182,61 @@ void scheduler_init()
|
|||
idleFiber->tcb.SP = CORTEX_M0_STACK_BASE - 0x04;
|
||||
idleFiber->tcb.LR = (uint32_t) &idle_task;
|
||||
|
||||
// Register to receive events in the NOTIFY channel - this is used to implement wait-notify semantics
|
||||
uBit.MessageBus.listen(MICROBIT_ID_NOTIFY, MICROBIT_EVT_ANY, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_NOTIFY_ONE, MICROBIT_EVT_ANY, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
if (messageBus)
|
||||
{
|
||||
// Register to receive events in the NOTIFY channel - this is used to implement wait-notify semantics
|
||||
messageBus->listen(MICROBIT_ID_NOTIFY, MICROBIT_EVT_ANY, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus->listen(MICROBIT_ID_NOTIFY_ONE, MICROBIT_EVT_ANY, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
// Flag that we now have a scheduler running
|
||||
uBit.flags |= MICROBIT_FLAG_SCHEDULER_RUNNING;
|
||||
// register a period callback to drive the scheduler and any other registered components.
|
||||
fiberSchedulerTicker.attach_us(scheduler_tick, tickPeriod * 1000);
|
||||
|
||||
fiber_flags |= MICROBIT_SCHEDULER_RUNNING;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
if(speedMs < 1)
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
|
||||
tickPeriod = speedMs;
|
||||
fiberSchedulerTicker.detach();
|
||||
fiberSchedulerTicker.attach_us(scheduler_tick, tickPeriod * 1000);
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the currently used tick speed in milliseconds
|
||||
*/
|
||||
int scheduler_get_tick_period()
|
||||
{
|
||||
return tickPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback. Called from interrupt context, once every FIBER_TICK_PERIOD_MS milliseconds.
|
||||
* Determines if the fiber scheduler is operational.
|
||||
* @return 1 if the fber scheduler is running, 0 otherwise.
|
||||
*/
|
||||
int fiber_scheduler_running()
|
||||
{
|
||||
if (fiber_flags & MICROBIT_SCHEDULER_RUNNING)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback. Called from interrupt context, once every FIBER_TICK_PERIOD_MS milliseconds, by default.
|
||||
* Simply checks to determine if any fibers blocked on the sleep queue need to be woken up
|
||||
* and made runnable.
|
||||
*/
|
||||
|
@ -181,7 +246,7 @@ void scheduler_tick()
|
|||
Fiber *t;
|
||||
|
||||
// increment our real-time counter.
|
||||
ticks += uBit.getTickPeriod();
|
||||
ticks += scheduler_get_tick_period();
|
||||
|
||||
// Check the sleep queue, and wake up any fibers as necessary.
|
||||
while (f != NULL)
|
||||
|
@ -197,12 +262,19 @@ void scheduler_tick()
|
|||
|
||||
f = t;
|
||||
}
|
||||
|
||||
// Update any components registered for a callback
|
||||
for(int i = 0; i < MICROBIT_SYSTEM_COMPONENTS; i++)
|
||||
if(systemTickComponents[i] != NULL)
|
||||
systemTickComponents[i]->systemTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Event callback. Called from the message bus whenever an event is raised.
|
||||
* Checks to determine if any fibers blocked on the wait queue need to be woken up
|
||||
* and made runnable due to the event.
|
||||
* @param evt The event to be processed.
|
||||
* @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not associated with a MicroBitMessageBus.
|
||||
*/
|
||||
void scheduler_event(MicroBitEvent evt)
|
||||
{
|
||||
|
@ -210,6 +282,12 @@ void scheduler_event(MicroBitEvent evt)
|
|||
Fiber *t;
|
||||
int notifyOneComplete = 0;
|
||||
|
||||
// This should never happen.
|
||||
// It is however, safe to simply ignore any events provided, ans if no messageBus if recorded,
|
||||
// no fibers are permitted to block on events.
|
||||
if (messageBus == NULL)
|
||||
return;
|
||||
|
||||
// Check the wait queue, and wake up any fibers as necessary.
|
||||
while (f != NULL)
|
||||
{
|
||||
|
@ -244,7 +322,7 @@ void scheduler_event(MicroBitEvent evt)
|
|||
|
||||
// Unregister this event, as we've woken up all the fibers with this match.
|
||||
if (evt.source != MICROBIT_ID_NOTIFY && evt.source != MICROBIT_ID_NOTIFY_ONE)
|
||||
uBit.MessageBus.ignore(evt.source, evt.value, scheduler_event);
|
||||
messageBus->ignore(evt.source, evt.value, scheduler_event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -291,7 +369,7 @@ void fiber_sleep(unsigned long t)
|
|||
|
||||
/**
|
||||
* Blocks the calling thread until the specified event is raised.
|
||||
* The calling thread will be immediatley descheduled, and placed onto a
|
||||
* The calling thread will be immediately descheduled, and placed onto a
|
||||
* wait queue until the requested event is received.
|
||||
*
|
||||
* n.b. the fiber will not be be made runnable until after the event is raised, but there
|
||||
|
@ -299,11 +377,15 @@ void fiber_sleep(unsigned long t)
|
|||
*
|
||||
* @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)
|
||||
{
|
||||
Fiber *f = currentFiber;
|
||||
|
||||
if (messageBus == NULL)
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
// Sleep is a blocking call, so if we'r ein a fork on block context,
|
||||
// it's time to spawn a new fiber...
|
||||
if (currentFiber->flags & MICROBIT_FIBER_FLAG_FOB)
|
||||
|
@ -330,10 +412,12 @@ void fiber_wait_for_event(uint16_t id, uint16_t value)
|
|||
// Register to receive this event, so we can wake up the fiber when it happens.
|
||||
// Special case for teh notify channel, as we always stay registered for that.
|
||||
if (id != MICROBIT_ID_NOTIFY && id != MICROBIT_ID_NOTIFY_ONE)
|
||||
uBit.MessageBus.listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus->listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
|
||||
// Finally, enter the scheduler.
|
||||
schedule();
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -643,7 +727,7 @@ void schedule()
|
|||
|
||||
// We're in a normal scheduling context, so perform a round robin algorithm across runnable fibers.
|
||||
// OK - if we've nothing to do, then run the IDLE task (power saving sleep)
|
||||
if (runQueue == NULL || fiber_flags & MICROBIT_FLAG_DATA_READY)
|
||||
if (runQueue == NULL)
|
||||
currentFiber = idleFiber;
|
||||
|
||||
else if (currentFiber->queue == &runQueue)
|
||||
|
@ -667,7 +751,7 @@ void schedule()
|
|||
{
|
||||
idle();
|
||||
}
|
||||
while (runQueue == NULL || fiber_flags & MICROBIT_FLAG_DATA_READY);
|
||||
while (runQueue == NULL);
|
||||
|
||||
// Switch to a non-idle fiber.
|
||||
// If this fiber is the same as the old one then there'll be no switching at all.
|
||||
|
@ -702,6 +786,91 @@ void schedule()
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a component to to the collection of those invoked when the scheduler's periodic timer is triggered.
|
||||
* The given component is called on each interrupt, within interrupt context.
|
||||
*
|
||||
* @param component The component to add.
|
||||
* @return MICROBIT_OK on success. MICROBIT_NO_RESOURCES is returned if further components cannot be supported.
|
||||
* @note this will be converted into a dynamic list of components
|
||||
*/
|
||||
int fiber_add_system_component(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 will be converted into a dynamic list of components
|
||||
*/
|
||||
int fiber_remove_system_component(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 will be converted into a dynamic list of components
|
||||
*/
|
||||
int fiber_add_idle_component(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 will be converted into a dynamic list of components
|
||||
*/
|
||||
int fiber_remove_idle_component(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of tasks to perform when idle.
|
||||
* Service any background tasks that are required, and attmept power efficient sleep.
|
||||
|
@ -709,16 +878,13 @@ void schedule()
|
|||
void idle()
|
||||
{
|
||||
// Service background tasks
|
||||
uBit.systemTasks();
|
||||
|
||||
for(int i = 0; i < MICROBIT_IDLE_COMPONENTS; i++)
|
||||
if(idleThreadComponents[i] != NULL)
|
||||
idleThreadComponents[i]->idleTick();
|
||||
|
||||
// If the above did create any useful work, enter power efficient sleep.
|
||||
if(scheduler_runqueue_empty())
|
||||
{
|
||||
if (uBit.ble)
|
||||
uBit.ble->waitForEvent();
|
||||
else
|
||||
__WFI();
|
||||
}
|
||||
__WFI();
|
||||
}
|
||||
/**
|
||||
* IDLE task.
|
||||
|
|
|
@ -29,6 +29,7 @@ const unsigned char pendolino3[475] = {
|
|||
|
||||
|
||||
const unsigned char* MicroBitFont::defaultFont = pendolino3;
|
||||
MicroBitFont MicroBitFont::systemFont = MicroBitFont(defaultFont, MICROBIT_FONT_ASCII_END);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -53,3 +54,21 @@ MicroBitFont::MicroBitFont()
|
|||
this->characters = defaultFont;
|
||||
this->asciiEnd = MICROBIT_FONT_ASCII_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current system font to the one specified.
|
||||
* @param font the new font that will be used to render characters..
|
||||
*/
|
||||
void MicroBitFont::setSystemFont(MicroBitFont font)
|
||||
{
|
||||
MicroBitFont::systemFont = font;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retreives the font object used for rendering characters on the display.
|
||||
*/
|
||||
MicroBitFont MicroBitFont::getSystemFont()
|
||||
{
|
||||
return MicroBitFont::systemFont;
|
||||
}
|
||||
|
||||
|
|
|
@ -362,7 +362,7 @@ void *microbit_malloc(size_t size)
|
|||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_PANIC_HEAP_FULL)
|
||||
panic(MICROBIT_OOM);
|
||||
MicroBitDisplay::panic(MICROBIT_OOM);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -519,7 +519,7 @@ int MicroBitImage::print(char c, int16_t x, int16_t y)
|
|||
unsigned char v;
|
||||
int x1, y1;
|
||||
|
||||
MicroBitFont font = uBit.display.getFont();
|
||||
MicroBitFont font = MicroBitFont::getSystemFont();
|
||||
|
||||
// Sanity check. Silently ignore anything out of bounds.
|
||||
if (x >= getWidth() || y >= getHeight() || c < MICROBIT_FONT_ASCII_START || c > font.asciiEnd)
|
||||
|
|
|
@ -82,7 +82,8 @@ MicroBitLightSensor::MicroBitLightSensor() : analogTrigger()
|
|||
{
|
||||
this->chan = 0;
|
||||
|
||||
uBit.MessageBus.listen(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
if (MicroBitMessageBus::defaultMessageBus)
|
||||
MicroBitMessageBus::defaultMessageBus->listen(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
|
||||
this->sensePin = NULL;
|
||||
}
|
||||
|
@ -143,5 +144,6 @@ int MicroBitLightSensor::read()
|
|||
*/
|
||||
MicroBitLightSensor::~MicroBitLightSensor()
|
||||
{
|
||||
uBit.MessageBus.ignore(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing);
|
||||
if (MicroBitMessageBus::defaultMessageBus)
|
||||
MicroBitMessageBus::defaultMessageBus->ignore(MICROBIT_ID_DISPLAY, MICROBIT_DISPLAY_EVT_LIGHT_SENSE, this, &MicroBitLightSensor::startSensing);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include "MicroBit.h"
|
||||
|
||||
MicroBitMessageBus* MicroBitMessageBus::defaultMessageBus = NULL;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Create a new Message Bus.
|
||||
|
@ -16,6 +18,9 @@ MicroBitMessageBus::MicroBitMessageBus()
|
|||
this->evt_queue_head = NULL;
|
||||
this->evt_queue_tail = NULL;
|
||||
this->queueLength = 0;
|
||||
|
||||
if(MicroBitMessageBus::defaultMessageBus == NULL)
|
||||
MicroBitMessageBus::defaultMessageBus = this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -594,5 +599,5 @@ MicroBitListener* MicroBitMessageBus::elementAt(int n)
|
|||
*/
|
||||
MicroBitMessageBus::~MicroBitMessageBus()
|
||||
{
|
||||
uBit.removeIdleComponent(this);
|
||||
fiber_remove_idle_component(this);
|
||||
}
|
||||
|
|
|
@ -23,15 +23,15 @@
|
|||
* MICROBIT_BUTTON_EVT_HOLD
|
||||
* @endcode
|
||||
*/
|
||||
MicroBitMultiButton::MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t button2)
|
||||
MicroBitMultiButton::MicroBitMultiButton(uint16_t id, uint16_t button1, uint16_t button2, MicroBitMessageBus &messageBus)
|
||||
{
|
||||
this->id = id;
|
||||
this->button1 = button1;
|
||||
this->button2 = button2;
|
||||
this->eventConfiguration = MICROBIT_BUTTON_SIMPLE_EVENTS;
|
||||
|
||||
uBit.MessageBus.listen(button1, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
uBit.MessageBus.listen(button2, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(button1, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(button2, MICROBIT_EVT_ANY, this, &MicroBitMultiButton::onButtonEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
uint16_t MicroBitMultiButton::otherSubButton(uint16_t b)
|
||||
|
@ -150,7 +150,6 @@ void MicroBitMultiButton::setEventConfiguration(MicroBitButtonEventConfiguration
|
|||
{
|
||||
this->eventConfiguration = config;
|
||||
}
|
||||
|
||||
void MicroBitMultiButton::onButtonEvent(MicroBitEvent evt)
|
||||
{
|
||||
int button = evt.source;
|
||||
|
|
|
@ -138,9 +138,13 @@ MicroBitImage MicroBitSerial::readImage(int width, int height)
|
|||
*/
|
||||
void MicroBitSerial::sendDisplayState()
|
||||
{
|
||||
return;
|
||||
|
||||
/*
|
||||
for(int i = 0; i < MICROBIT_DISPLAY_HEIGHT; i++)
|
||||
for(int j = 0; j < MICROBIT_DISPLAY_WIDTH; j++)
|
||||
_putc(uBit.display.image.getPixelValue(j,i));
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,12 +157,14 @@ void MicroBitSerial::sendDisplayState()
|
|||
*/
|
||||
void MicroBitSerial::readDisplayState()
|
||||
{
|
||||
/*
|
||||
for(int i = 0; i < MICROBIT_DISPLAY_HEIGHT; i++)
|
||||
for(int j = 0; j < MICROBIT_DISPLAY_WIDTH; j++)
|
||||
{
|
||||
int c = _getc();
|
||||
uBit.display.image.setPixelValue(j,i,c);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
ssize_t MicroBitSerial::readChars(void* buffer, size_t length, char eof) {
|
||||
|
|
|
@ -1,86 +1,18 @@
|
|||
#include "MicroBit.h"
|
||||
|
||||
#ifdef UBIT_SUPERMAIN
|
||||
MicroBit uBit;
|
||||
InterruptIn resetButton(MICROBIT_PIN_BUTTON_RESET);
|
||||
|
||||
extern char* MICROBIT_BLE_DEVICE_NAME;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Bring up soft reset button.
|
||||
resetButton.mode(PullUp);
|
||||
resetButton.fall(microbit_reset);
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_DBG)
|
||||
|
||||
// For diagnostics. Gives time to open the console window. :-)
|
||||
for (int i=3; i>0; i--)
|
||||
{
|
||||
uBit.serial.printf("=== SUPERMAIN: Starting in %d ===\n", i);
|
||||
wait(1.0);
|
||||
}
|
||||
|
||||
uBit.serial.printf("micro:bit runtime DAL version %s\n", MICROBIT_DAL_VERSION);
|
||||
|
||||
uBit.serial.printf("micro:bit runtime version %s\n", MICROBIT_DAL_VERSION);
|
||||
#endif
|
||||
|
||||
// Bring up our nested heap allocator.
|
||||
microbit_heap_init();
|
||||
|
||||
// Bring up fiber scheduler
|
||||
scheduler_init();
|
||||
|
||||
// Bring up random number generator, BLE, display and system timers.
|
||||
uBit.init();
|
||||
|
||||
// Provide time for all threaded initialisers to complete.
|
||||
uBit.sleep(100);
|
||||
|
||||
//check our persistent storage for compassCalibrationData
|
||||
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))
|
||||
uBit.compass.setCalibration(b->compassCalibrationData);
|
||||
}
|
||||
|
||||
delete b;
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_PAIRING_MODE)
|
||||
// Test if we need to enter BLE pairing mode...
|
||||
int i=0;
|
||||
while (uBit.buttonA.isPressed() && uBit.buttonB.isPressed() && i<10)
|
||||
{
|
||||
uBit.sleep(100);
|
||||
i++;
|
||||
|
||||
if (i == 10)
|
||||
{
|
||||
// Start the BLE stack, if it isn't already running.
|
||||
if (!uBit.ble)
|
||||
{
|
||||
uBit.bleManager.init(uBit.getName(), uBit.getSerial(), true);
|
||||
uBit.ble = uBit.bleManager.ble;
|
||||
}
|
||||
|
||||
// Enter pairing mode, using the LED matrix for any necessary pairing operations
|
||||
uBit.bleManager.pairingMode(uBit.display);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_ENABLED)
|
||||
// Start the BLE stack, if it isn't already running.
|
||||
if (!uBit.ble)
|
||||
{
|
||||
uBit.bleManager.init(uBit.getName(), uBit.getSerial(), false);
|
||||
uBit.ble = uBit.bleManager.ble;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start the user application
|
||||
app_main();
|
||||
|
||||
// If app_main exits, there may still be other fibers running, registered event handlers etc.
|
||||
|
@ -91,3 +23,5 @@ int main()
|
|||
// We should never get here, but just in case.
|
||||
while(1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#endif
|
||||
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_sdm.h"
|
||||
|
||||
/*
|
||||
* Return to our predefined compiler settings.
|
||||
|
@ -56,7 +57,9 @@ MicroBitThermometer::MicroBitThermometer(uint16_t id)
|
|||
this->samplePeriod = MICROBIT_THERMOMETER_PERIOD;
|
||||
this->sampleTime = 0;
|
||||
|
||||
uBit.addIdleComponent(this);
|
||||
// If we're running under a fiber scheduer, register ourselves for a periodic callback to keep our data up to date.
|
||||
// Otherwise, we do just do this on demand, when polled through our read() interface.
|
||||
fiber_add_idle_component(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -130,12 +133,15 @@ int MicroBitThermometer::getPeriod()
|
|||
void MicroBitThermometer::updateTemperature()
|
||||
{
|
||||
int32_t processorTemperature;
|
||||
uint8_t sd_enabled;
|
||||
|
||||
// For now, we just rely on the nrf senesor to be the most accurate.
|
||||
// The compass module also has a temperature sensor, and has the lowest power consumption, so will run the cooler...
|
||||
// ...however it isn't trimmed for accuracy during manufacture, so requires calibration.
|
||||
|
||||
if (uBit.ble)
|
||||
sd_softdevice_is_enabled(&sd_enabled);
|
||||
|
||||
if (sd_enabled)
|
||||
{
|
||||
// If Bluetooth is enabled, we need to go through the Nordic software to safely do this
|
||||
sd_temp_get(&processorTemperature);
|
||||
|
|
|
@ -17,7 +17,7 @@ static inline bool isReadOnlyInline(RefCounted *t)
|
|||
// Do some sanity checking while we're here
|
||||
if (refCount == 1 || // object should have been deleted
|
||||
(refCount & 1) == 0) // refCount doesn't look right
|
||||
uBit.panic(MICROBIT_HEAP_ERROR);
|
||||
MicroBitDisplay::panic(MICROBIT_HEAP_ERROR);
|
||||
|
||||
// Not read only
|
||||
return false;
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* Create a representation of the AccelerometerService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble, MicroBitAccelerometer &_accelerometer, MicroBitMessageBus &messageBus) :
|
||||
ble(_ble), accelerometer(_accelerometer)
|
||||
{
|
||||
// Create the data structures that represent each of our characteristics in Soft Device.
|
||||
GattCharacteristic accelerometerDataCharacteristic(MicroBitAccelerometerServiceDataUUID, (uint8_t *)accelerometerDataCharacteristicBuffer, 0,
|
||||
|
@ -28,7 +28,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
|
|||
accelerometerDataCharacteristicBuffer[0] = 0;
|
||||
accelerometerDataCharacteristicBuffer[1] = 0;
|
||||
accelerometerDataCharacteristicBuffer[2] = 0;
|
||||
accelerometerPeriodCharacteristicBuffer = uBit.accelerometer.getPeriod();
|
||||
accelerometerPeriodCharacteristicBuffer = accelerometer.getPeriod();
|
||||
|
||||
// Set default security requirements
|
||||
accelerometerDataCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
|
||||
|
@ -46,7 +46,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
|
|||
ble.gattServer().write(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
|
||||
|
||||
ble.onDataWritten(this, &MicroBitAccelerometerService::onDataWritten);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_ACCELEROMETER, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, this, &MicroBitAccelerometerService::accelerometerUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(MICROBIT_ID_ACCELEROMETER, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE, this, &MicroBitAccelerometerService::accelerometerUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,11 +57,11 @@ void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *
|
|||
if (params->handle == accelerometerPeriodCharacteristicHandle && params->len >= sizeof(accelerometerPeriodCharacteristicBuffer))
|
||||
{
|
||||
accelerometerPeriodCharacteristicBuffer = *((uint16_t *)params->data);
|
||||
uBit.accelerometer.setPeriod(accelerometerPeriodCharacteristicBuffer);
|
||||
accelerometer.setPeriod(accelerometerPeriodCharacteristicBuffer);
|
||||
|
||||
// The accelerometer will choose the nearest period to that requested that it can support
|
||||
// Read back the ACTUAL period it is using, and report this back.
|
||||
accelerometerPeriodCharacteristicBuffer = uBit.accelerometer.getPeriod();
|
||||
accelerometerPeriodCharacteristicBuffer = accelerometer.getPeriod();
|
||||
ble.gattServer().write(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
|
||||
}
|
||||
}
|
||||
|
@ -73,12 +73,12 @@ void MicroBitAccelerometerService::accelerometerUpdate(MicroBitEvent)
|
|||
{
|
||||
if (ble.getGapState().connected)
|
||||
{
|
||||
accelerometerDataCharacteristicBuffer[0] = uBit.accelerometer.getX();
|
||||
accelerometerDataCharacteristicBuffer[1] = uBit.accelerometer.getY();
|
||||
accelerometerDataCharacteristicBuffer[2] = uBit.accelerometer.getZ();
|
||||
accelerometerDataCharacteristicBuffer[0] = accelerometer.getX();
|
||||
accelerometerDataCharacteristicBuffer[1] = accelerometer.getY();
|
||||
accelerometerDataCharacteristicBuffer[2] = accelerometer.getZ();
|
||||
|
||||
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
|
||||
}
|
||||
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t MicroBitAccelerometerServiceUUID[] = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "MicroBit.h"
|
||||
|
||||
|
||||
/* The underlying Nordic libraries that support BLE do not compile cleanly with the stringent GCC settings we employ
|
||||
/* 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...
|
||||
|
@ -180,10 +180,10 @@ void MicroBitBLEManager::advertise()
|
|||
*
|
||||
* Example:
|
||||
* @code
|
||||
* uBit.init();
|
||||
* bleManager.init("zevug");
|
||||
* @endcode
|
||||
*/
|
||||
void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, bool enableBonding)
|
||||
void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumber, MicroBitMessageBus& messageBus, bool enableBonding)
|
||||
{
|
||||
ManagedString BLEName("BBC micro:bit");
|
||||
this->deviceName = deviceName;
|
||||
|
@ -254,42 +254,11 @@ void MicroBitBLEManager::init(ManagedString deviceName, ManagedString serialNumb
|
|||
// Configure the radio at our default power level
|
||||
setTransmitPower(MICROBIT_BLE_DEFAULT_TX_POWER);
|
||||
|
||||
// Bring up any configured auxiliary services.
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_DFU_SERVICE)
|
||||
// Bring up core BLE services.
|
||||
new MicroBitDFUService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_DEVICE_INFORMATION_SERVICE)
|
||||
DeviceInformationService ble_device_information_service (*ble, MICROBIT_BLE_MANUFACTURER, MICROBIT_BLE_MODEL, serialNumber.toCharArray(), MICROBIT_BLE_HARDWARE_VERSION, MICROBIT_BLE_FIRMWARE_VERSION, MICROBIT_BLE_SOFTWARE_VERSION);
|
||||
#endif
|
||||
new MicroBitEventService(*ble, messageBus);
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_EVENT_SERVICE)
|
||||
new MicroBitEventService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_LED_SERVICE)
|
||||
new MicroBitLEDService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
|
||||
new MicroBitAccelerometerService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_MAGNETOMETER_SERVICE)
|
||||
new MicroBitMagnetometerService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_BUTTON_SERVICE)
|
||||
new MicroBitButtonService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_IO_PIN_SERVICE)
|
||||
new MicroBitIOPinService(*ble);
|
||||
#endif
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_BLE_TEMPERATURE_SERVICE)
|
||||
new MicroBitTemperatureService(*ble);
|
||||
#endif
|
||||
|
||||
// Configure for high speed mode where possible.
|
||||
Gap::ConnectionParams_t fast;
|
||||
|
@ -379,7 +348,7 @@ void MicroBitBLEManager::pairingComplete(bool success)
|
|||
if(success)
|
||||
{
|
||||
this->pairingStatus |= MICROBIT_BLE_PAIR_SUCCESSFUL;
|
||||
uBit.addIdleComponent(this);
|
||||
fiber_add_idle_component(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -392,14 +361,17 @@ void MicroBitBLEManager::idleTick()
|
|||
if (ble)
|
||||
ble->disconnect(pairingHandle, Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF);
|
||||
|
||||
uBit.removeIdleComponent(this);
|
||||
fiber_remove_idle_component(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter pairing mode. This is mode is called to initiate pairing, and to enable FOTA programming
|
||||
* of the micro:bit in cases where BLE is disabled during normal operation.
|
||||
*
|
||||
* @param display A reference to the display on which to show usage notes and pass code information.
|
||||
* @prarm authorizationButton The button to use to authorise a pairing request.
|
||||
*/
|
||||
void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
||||
void MicroBitBLEManager::pairingMode(MicroBitDisplay& display, MicroBitButton& authorisationButton)
|
||||
{
|
||||
ManagedString namePrefix("BBC micro:bit [");
|
||||
ManagedString namePostfix("]");
|
||||
|
@ -464,7 +436,7 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
|||
if (brightness >= 255)
|
||||
fadeDirection = 0;
|
||||
|
||||
if (uBit.buttonA.isPressed())
|
||||
if (authorisationButton.isPressed())
|
||||
{
|
||||
pairingStatus &= ~MICROBIT_BLE_PAIR_REQUEST;
|
||||
pairingStatus |= MICROBIT_BLE_PAIR_PASSCODE;
|
||||
|
@ -478,15 +450,15 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
|||
for (int i=0; i<passKey.length(); i++)
|
||||
{
|
||||
display.image.print(passKey.charAt(i),0,0);
|
||||
uBit.sleep(800);
|
||||
fiber_sleep(800);
|
||||
display.clear();
|
||||
uBit.sleep(200);
|
||||
fiber_sleep(200);
|
||||
|
||||
if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
|
||||
break;
|
||||
}
|
||||
|
||||
uBit.sleep(1000);
|
||||
fiber_sleep(1000);
|
||||
}
|
||||
|
||||
if (pairingStatus & MICROBIT_BLE_PAIR_COMPLETE)
|
||||
|
@ -495,7 +467,7 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
|||
{
|
||||
MicroBitImage tick("0,0,0,0,0\n0,0,0,0,255\n0,0,0,255,0\n255,0,255,0,0\n0,255,0,0,0\n");
|
||||
display.print(tick,0,0,0);
|
||||
uBit.sleep(15000);
|
||||
fiber_sleep(15000);
|
||||
timeInPairingMode = MICROBIT_BLE_PAIRING_TIMEOUT * 30;
|
||||
|
||||
/*
|
||||
|
@ -519,7 +491,7 @@ void MicroBitBLEManager::pairingMode(MicroBitDisplay &display)
|
|||
}
|
||||
}
|
||||
|
||||
uBit.sleep(30);
|
||||
MicroBit::sleep(100);
|
||||
timeInPairingMode++;
|
||||
|
||||
if (timeInPairingMode >= MICROBIT_BLE_PAIRING_TIMEOUT * 30)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* Create a representation of the ButtonService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) :
|
||||
MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble, MicroBitMessageBus &messageBus) :
|
||||
ble(_ble)
|
||||
{
|
||||
// Create the data structures that represent each of our characteristics in Soft Device.
|
||||
|
@ -43,8 +43,8 @@ MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) :
|
|||
ble.gattServer().write(buttonADataCharacteristicHandle,(uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
|
||||
ble.gattServer().write(buttonBDataCharacteristicHandle,(uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
|
||||
|
||||
uBit.MessageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonAUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonBUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonAUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonBUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,11 +72,12 @@ void MicroBitDFUService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
{
|
||||
if(params->len > 0 && params->data[0] == MICROBIT_DFU_OPCODE_START_DFU)
|
||||
{
|
||||
uBit.display.stopAnimation();
|
||||
uBit.display.clear();
|
||||
// TODO: Raise a SYSTEM event here.
|
||||
//uBit.display.stopAnimation();
|
||||
//uBit.display.clear();
|
||||
|
||||
#if CONFIG_ENABLED(MICROBIT_DBG)
|
||||
uBit.serial.printf(" ACTIVATING BOOTLOADER.\n");
|
||||
printf(" ACTIVATING BOOTLOADER.\n");
|
||||
#endif
|
||||
|
||||
// Perform an explicit disconnection to assist our peer to reconnect to the DFU service
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
* Create a representation of the EventService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitEventService::MicroBitEventService(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
MicroBitEventService::MicroBitEventService(BLEDevice &_ble, MicroBitMessageBus &_messageBus) :
|
||||
ble(_ble),messageBus(_messageBus)
|
||||
{
|
||||
GattCharacteristic microBitEventCharacteristic(MicroBitEventServiceMicroBitEventCharacteristicUUID, (uint8_t *)µBitEventBuffer, 0, sizeof(EventServiceEvent),
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
|
||||
|
@ -51,7 +51,7 @@ MicroBitEventService::MicroBitEventService(BLEDevice &_ble) :
|
|||
|
||||
ble.onDataWritten(this, &MicroBitEventService::onDataWritten);
|
||||
|
||||
uBit.addIdleComponent(this);
|
||||
fiber_add_idle_component(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,7 +79,7 @@ void MicroBitEventService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
// Read and register for all the events given...
|
||||
while (len >= 4)
|
||||
{
|
||||
uBit.MessageBus.listen(e->type, e->reason, this, &MicroBitEventService::onMicroBitEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(e->type, e->reason, this, &MicroBitEventService::onMicroBitEvent, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
|
||||
len-=4;
|
||||
e++;
|
||||
|
@ -111,7 +111,7 @@ void MicroBitEventService::idleTick()
|
|||
{
|
||||
if (!ble.getGapState().connected && messageBusListenerOffset >0) {
|
||||
messageBusListenerOffset = 0;
|
||||
uBit.MessageBus.ignore(MICROBIT_ID_ANY, MICROBIT_EVT_ANY, this, &MicroBitEventService::onMicroBitEvent);
|
||||
messageBus.ignore(MICROBIT_ID_ANY, MICROBIT_EVT_ANY, this, &MicroBitEventService::onMicroBitEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ void MicroBitEventService::onRequirementsRead(GattReadAuthCallbackParams *params
|
|||
{
|
||||
// Walk through the lsit of message bus listeners.
|
||||
// We send one at a time, and our client can keep reading from this characterisitic until we return an emtpy value.
|
||||
MicroBitListener *l = uBit.MessageBus.elementAt(messageBusListenerOffset++);
|
||||
MicroBitListener *l = messageBus.elementAt(messageBusListenerOffset++);
|
||||
|
||||
if (l != NULL)
|
||||
{
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* Create a representation of the IOPinService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble, MicroBitIO &_io) :
|
||||
ble(_ble), io(_io)
|
||||
{
|
||||
// Create the AD characteristic, that defines whether each pin is treated as analogue or digital
|
||||
GattCharacteristic ioPinServiceADCharacteristic(MicroBitIOPinServiceADConfigurationUUID, (uint8_t *)&ioPinServiceADCharacteristicBuffer, 0, sizeof(ioPinServiceADCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
|
||||
|
@ -48,7 +48,7 @@ MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble) :
|
|||
ble.gattServer().write(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer));
|
||||
|
||||
ble.onDataWritten(this, &MicroBitIOPinService::onDataWritten);
|
||||
uBit.addIdleComponent(this);
|
||||
fiber_add_idle_component(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,10 +113,12 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
for (int i=0; i < MICROBIT_IO_PIN_SERVICE_PINCOUNT; i++)
|
||||
{
|
||||
if(isDigital(i) && isInput(i))
|
||||
MicroBitIOPins[i]->getDigitalValue();
|
||||
io.pin[i].getDigitalValue();
|
||||
//MicroBitIOPins[i]->getDigitalValue();
|
||||
|
||||
if(isAnalog(i) && isInput(i))
|
||||
MicroBitIOPins[i]->getAnalogValue();
|
||||
io.pin[i].getAnalogValue();
|
||||
//MicroBitIOPins[i]->getAnalogValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,10 +135,12 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
for (int i=0; i < MICROBIT_IO_PIN_SERVICE_PINCOUNT; i++)
|
||||
{
|
||||
if(isDigital(i) && isInput(i))
|
||||
MicroBitIOPins[i]->getDigitalValue();
|
||||
io.pin[i].getDigitalValue();
|
||||
//MicroBitIOPins[i]->getDigitalValue();
|
||||
|
||||
if(isAnalog(i) && isInput(i))
|
||||
MicroBitIOPins[i]->getAnalogValue();
|
||||
io.pin[i].getAnalogValue();
|
||||
//MicroBitIOPins[i]->getAnalogValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,9 +156,11 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
if (isOutput(data->pin))
|
||||
{
|
||||
if (isDigital(data->pin))
|
||||
MicroBitIOPins[data->pin]->setDigitalValue(data->value);
|
||||
io.pin[data->pin].setDigitalValue(data->value);
|
||||
//MicroBitIOPins[data->pin]->setDigitalValue(data->value);
|
||||
else
|
||||
MicroBitIOPins[data->pin]->setAnalogValue(data->value*4);
|
||||
io.pin[data->pin].setAnalogValue(data->value*4);
|
||||
//MicroBitIOPins[data->pin]->setAnalogValue(data->value*4);
|
||||
}
|
||||
|
||||
data++;
|
||||
|
@ -182,9 +188,11 @@ void MicroBitIOPinService::onDataRead(GattReadAuthCallbackParams *params)
|
|||
uint8_t value;
|
||||
|
||||
if (isDigital(i))
|
||||
value = MicroBitIOPins[i]->getDigitalValue();
|
||||
value = io.pin[i].getDigitalValue();
|
||||
//value = MicroBitIOPins[i]->getDigitalValue();
|
||||
else
|
||||
value = MicroBitIOPins[i]->getAnalogValue();
|
||||
value = io.pin[i].getAnalogValue();
|
||||
//value = MicroBitIOPins[i]->getAnalogValue();
|
||||
|
||||
ioPinServiceIOData[i] = value;
|
||||
ioPinServiceDataCharacteristicBuffer[pairs].pin = i;
|
||||
|
@ -224,9 +232,11 @@ void MicroBitIOPinService::idleTick()
|
|||
uint8_t value;
|
||||
|
||||
if (isDigital(i))
|
||||
value = MicroBitIOPins[i]->getDigitalValue();
|
||||
value = io.pin[i].getDigitalValue();
|
||||
//value = MicroBitIOPins[i]->getDigitalValue();
|
||||
else
|
||||
value = MicroBitIOPins[i]->getAnalogValue();
|
||||
value = io.pin[i].getAnalogValue();
|
||||
//value = MicroBitIOPins[i]->getAnalogValue();
|
||||
|
||||
// If the data has changed, send an update.
|
||||
if (value != ioPinServiceIOData[i])
|
||||
|
@ -265,6 +275,7 @@ const uint8_t MicroBitIOPinServiceDataUUID[] = {
|
|||
0xe9,0x5d,0x8d,0x00,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
|
||||
};
|
||||
|
||||
/*
|
||||
MicroBitPin * const MicroBitIOPins[] = {
|
||||
&uBit.io.P0,
|
||||
&uBit.io.P1,
|
||||
|
@ -286,5 +297,5 @@ MicroBitPin * const MicroBitIOPins[] = {
|
|||
&uBit.io.P19,
|
||||
&uBit.io.P20
|
||||
};
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* Create a representation of the LEDService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitLEDService::MicroBitLEDService(BLEDevice &_ble) :
|
||||
ble(_ble),
|
||||
MicroBitLEDService::MicroBitLEDService(BLEDevice &_ble, MicroBitDisplay &_display) :
|
||||
ble(_ble), display(_display),
|
||||
matrixCharacteristic(MicroBitLEDServiceMatrixUUID, (uint8_t *)&matrixCharacteristicBuffer, 0, sizeof(matrixCharacteristicBuffer),
|
||||
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ void MicroBitLEDService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
{
|
||||
for (int y=0; y<params->len; y++)
|
||||
for (int x=0; x<5; x++)
|
||||
uBit.display.image.setPixelValue(x, y, (data[y] & (0x01 << (4-x))) ? 255 : 0);
|
||||
display.image.setPixelValue(x, y, (data[y] & (0x01 << (4-x))) ? 255 : 0);
|
||||
}
|
||||
|
||||
else if (params->handle == textCharacteristicHandle)
|
||||
|
@ -74,7 +74,7 @@ void MicroBitLEDService::onDataWritten(const GattWriteCallbackParams *params)
|
|||
ManagedString s((char *)params->data, params->len);
|
||||
|
||||
// Start the string scrolling and we're done.
|
||||
uBit.display.scrollAsync(s, (int) scrollingSpeedCharacteristicBuffer);
|
||||
display.scrollAsync(s, (int) scrollingSpeedCharacteristicBuffer);
|
||||
}
|
||||
|
||||
else if (params->handle == scrollingSpeedCharacteristicHandle && params->len >= sizeof(scrollingSpeedCharacteristicBuffer))
|
||||
|
@ -98,7 +98,7 @@ void MicroBitLEDService::onDataRead(GattReadAuthCallbackParams *params)
|
|||
|
||||
for (int x=0; x<5; x++)
|
||||
{
|
||||
if (uBit.display.image.getPixelValue(x, y))
|
||||
if (display.image.getPixelValue(x, y))
|
||||
matrixCharacteristicBuffer[y] |= 0x01 << (4-x);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* Create a representation of the MagnetometerService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble, MicroBitCompass &_compass, MicroBitMessageBus &messageBus) :
|
||||
ble(_ble), compass(_compass)
|
||||
{
|
||||
// Create the data structures that represent each of our characteristics in Soft Device.
|
||||
GattCharacteristic magnetometerDataCharacteristic(MicroBitMagnetometerServiceDataUUID, (uint8_t *)magnetometerDataCharacteristicBuffer, 0,
|
||||
|
@ -32,7 +32,7 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
|
|||
magnetometerDataCharacteristicBuffer[1] = 0;
|
||||
magnetometerDataCharacteristicBuffer[2] = 0;
|
||||
magnetometerBearingCharacteristicBuffer = 0;
|
||||
magnetometerPeriodCharacteristicBuffer = uBit.compass.getPeriod();
|
||||
magnetometerPeriodCharacteristicBuffer = compass.getPeriod();
|
||||
|
||||
// Set default security requirements
|
||||
magnetometerDataCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
|
||||
|
@ -53,8 +53,8 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
|
|||
ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
|
||||
|
||||
ble.onDataWritten(this, &MicroBitMagnetometerService::onDataWritten);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_DATA_UPDATE, this, &MicroBitMagnetometerService::magnetometerUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CONFIG_NEEDED, this, &MicroBitMagnetometerService::samplePeriodUpdateNeeded);
|
||||
messageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_DATA_UPDATE, this, &MicroBitMagnetometerService::magnetometerUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CONFIG_NEEDED, this, &MicroBitMagnetometerService::samplePeriodUpdateNeeded);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,17 +76,18 @@ void MicroBitMagnetometerService::magnetometerUpdate(MicroBitEvent)
|
|||
{
|
||||
if (ble.getGapState().connected)
|
||||
{
|
||||
magnetometerDataCharacteristicBuffer[0] = uBit.compass.getX();
|
||||
magnetometerDataCharacteristicBuffer[1] = uBit.compass.getY();
|
||||
magnetometerDataCharacteristicBuffer[2] = uBit.compass.getZ();
|
||||
magnetometerPeriodCharacteristicBuffer = uBit.compass.getPeriod();
|
||||
magnetometerDataCharacteristicBuffer[0] = compass.getX();
|
||||
magnetometerDataCharacteristicBuffer[1] = compass.getY();
|
||||
magnetometerDataCharacteristicBuffer[2] = compass.getZ();
|
||||
magnetometerBearingCharacteristicBuffer = (uint16_t) compass.heading();
|
||||
magnetometerPeriodCharacteristicBuffer = compass.getPeriod();
|
||||
|
||||
ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
|
||||
ble.gattServer().notify(magnetometerDataCharacteristicHandle,(uint8_t *)magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
|
||||
|
||||
if (uBit.compass.isCalibrated())
|
||||
if (compass.isCalibrated())
|
||||
{
|
||||
magnetometerBearingCharacteristicBuffer = (uint16_t) uBit.compass.heading();
|
||||
magnetometerBearingCharacteristicBuffer = (uint16_t) compass.heading();
|
||||
ble.gattServer().notify(magnetometerBearingCharacteristicHandle,(uint8_t *)&magnetometerBearingCharacteristicBuffer, sizeof(magnetometerBearingCharacteristicBuffer));
|
||||
}
|
||||
}
|
||||
|
@ -100,11 +101,11 @@ void MicroBitMagnetometerService::magnetometerUpdate(MicroBitEvent)
|
|||
void MicroBitMagnetometerService::samplePeriodUpdateNeeded(MicroBitEvent)
|
||||
{
|
||||
// Reconfigure the compass. This might take a while...
|
||||
uBit.compass.setPeriod(magnetometerPeriodCharacteristicBuffer);
|
||||
compass.setPeriod(magnetometerPeriodCharacteristicBuffer);
|
||||
|
||||
// The compass will choose the nearest sample period to that we've specified.
|
||||
// Read the ACTUAL sample period back.
|
||||
magnetometerPeriodCharacteristicBuffer = uBit.compass.getPeriod();
|
||||
magnetometerPeriodCharacteristicBuffer = compass.getPeriod();
|
||||
|
||||
// Ensure this is reflected in our BLE connection.
|
||||
ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
|
||||
|
|
|
@ -47,7 +47,7 @@ extern "C" void RADIO_IRQHandler(void)
|
|||
{
|
||||
uint8_t sample = NRF_RADIO->RSSISAMPLE;
|
||||
|
||||
uBit.radio.setRSSI(sample);
|
||||
MicroBitRadio::instance->setRSSI(sample);
|
||||
}
|
||||
|
||||
// Start listening and wait for the END event
|
||||
|
@ -61,7 +61,7 @@ extern "C" void RADIO_IRQHandler(void)
|
|||
* Initialise the MicroBitRadio. Note that this class is demand activated, so most resources are only committed
|
||||
* if send/recv or event registrations calls are made.
|
||||
*/
|
||||
MicroBitRadio::MicroBitRadio(uint16_t id) : datagram()
|
||||
MicroBitRadio::MicroBitRadio(uint16_t id) : datagram(*this), event (*this)
|
||||
{
|
||||
this->id = id;
|
||||
this->status = 0;
|
||||
|
@ -101,7 +101,7 @@ int MicroBitRadio::setTransmitPower(int power)
|
|||
*/
|
||||
int MicroBitRadio::setFrequencyBand(int band)
|
||||
{
|
||||
if (uBit.ble)
|
||||
if (ble_running())
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
if (band < 0 || band > 100)
|
||||
|
@ -212,7 +212,7 @@ int MicroBitRadio::enable()
|
|||
return MICROBIT_OK;
|
||||
|
||||
// Only attempt to enable this radio mode if BLE is disabled.
|
||||
if (uBit.ble)
|
||||
if (ble_running())
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
// If this is the first time we've been enable, allocate out receive buffers.
|
||||
|
@ -289,7 +289,7 @@ int MicroBitRadio::enable()
|
|||
NRF_RADIO->TASKS_START = 1;
|
||||
|
||||
// register ourselves for a callback event, in order to empty the receive queue.
|
||||
uBit.addIdleComponent(this);
|
||||
fiber_add_idle_component(this);
|
||||
|
||||
// Done. Record that our RADIO is configured.
|
||||
status |= MICROBIT_RADIO_STATUS_INITIALISED;
|
||||
|
@ -304,7 +304,7 @@ int MicroBitRadio::enable()
|
|||
int MicroBitRadio::disable()
|
||||
{
|
||||
// Only attempt to enable.disable the radio if the protocol is alreayd running.
|
||||
if (uBit.ble)
|
||||
if (ble_running())
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
if (!(status & MICROBIT_RADIO_STATUS_INITIALISED))
|
||||
|
@ -318,7 +318,7 @@ int MicroBitRadio::disable()
|
|||
while(NRF_RADIO->EVENTS_DISABLED == 0);
|
||||
|
||||
// deregister ourselves from the callback event used to empty the receive queue.
|
||||
uBit.removeIdleComponent(this);
|
||||
fiber_remove_idle_component(this);
|
||||
|
||||
return MICROBIT_OK;
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ int MicroBitRadio::disable()
|
|||
*/
|
||||
int MicroBitRadio::setGroup(uint8_t group)
|
||||
{
|
||||
if (uBit.ble)
|
||||
if (ble_running())
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
// Record our group id locally
|
||||
|
@ -422,7 +422,7 @@ FrameBuffer* MicroBitRadio::recv()
|
|||
*/
|
||||
int MicroBitRadio::send(FrameBuffer *buffer)
|
||||
{
|
||||
if (uBit.ble)
|
||||
if (ble_running())
|
||||
return MICROBIT_NOT_SUPPORTED;
|
||||
|
||||
if (buffer == NULL)
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param radio The underlying radio module used to send and receive data.
|
||||
*/
|
||||
MicroBitRadioDatagram::MicroBitRadioDatagram()
|
||||
MicroBitRadioDatagram::MicroBitRadioDatagram(MicroBitRadio &r) : radio(r)
|
||||
{
|
||||
rxQueue = NULL;
|
||||
this->rxQueue = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -90,7 +92,7 @@ int MicroBitRadioDatagram::send(uint8_t *buffer, int len)
|
|||
buf.protocol = MICROBIT_RADIO_PROTOCOL_DATAGRAM;
|
||||
memcpy(buf.payload, buffer, len);
|
||||
|
||||
return uBit.radio.send(&buf);
|
||||
return radio.send(&buf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,7 +113,7 @@ int MicroBitRadioDatagram::send(PacketBuffer data)
|
|||
*/
|
||||
void MicroBitRadioDatagram::packetReceived()
|
||||
{
|
||||
FrameBuffer *packet = uBit.radio.recv();
|
||||
FrameBuffer *packet = radio.recv();
|
||||
int queueDepth = 0;
|
||||
|
||||
// We add to the tail of the queue to preserve causal ordering.
|
||||
|
|
|
@ -15,15 +15,34 @@
|
|||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param radio The underlying radio module that this service will use.
|
||||
*/
|
||||
MicroBitRadioEvent::MicroBitRadioEvent()
|
||||
MicroBitRadioEvent::MicroBitRadioEvent(MicroBitRadio &r) : radio(r)
|
||||
{
|
||||
suppressForwarding = false;
|
||||
this->suppressForwarding = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the given MessageBus events with the radio channel.
|
||||
* Once registered, all events matching the given registration sent to this micro:bit's
|
||||
* 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.
|
||||
*
|
||||
* @return MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if no defult MessageBus is available.
|
||||
*/
|
||||
int MicroBitRadioEvent::listen(uint16_t id, uint16_t value)
|
||||
{
|
||||
if (MicroBitMessageBus::defaultMessageBus)
|
||||
return listen(id, value, *MicroBitMessageBus::defaultMessageBus);
|
||||
|
||||
return MICROBIT_NO_RESOURCES;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -31,9 +50,9 @@ MicroBitRadioEvent::MicroBitRadioEvent()
|
|||
*
|
||||
* @return MICROBIT_OK on success.
|
||||
*/
|
||||
int MicroBitRadioEvent::listen(uint16_t id, uint16_t value)
|
||||
int MicroBitRadioEvent::listen(uint16_t id, uint16_t value, MicroBitMessageBus &messageBus)
|
||||
{
|
||||
return uBit.MessageBus.listen(id, value, this, &MicroBitRadioEvent::eventReceived, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
return messageBus.listen(id, value, this, &MicroBitRadioEvent::eventReceived, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,20 +61,38 @@ int MicroBitRadioEvent::listen(uint16_t id, uint16_t value)
|
|||
* @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 no default MessageBus is available.
|
||||
*/
|
||||
int MicroBitRadioEvent::ignore(uint16_t id, uint16_t value)
|
||||
{
|
||||
return uBit.MessageBus.ignore(id, value, this, &MicroBitRadioEvent::eventReceived);
|
||||
if (MicroBitMessageBus::defaultMessageBus)
|
||||
return ignore(id, value, *MicroBitMessageBus::defaultMessageBus);
|
||||
|
||||
return MICROBIT_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 MicroBitRadioEvent::ignore(uint16_t id, uint16_t value, MicroBitMessageBus &messageBus)
|
||||
{
|
||||
return messageBus.ignore(id, value, this, &MicroBitRadioEvent::eventReceived);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Protocol handler callback. This is called when the radio receives a packet marked as an event
|
||||
* This function process this packet, and fires the event contained inside onto the local MessageBus.
|
||||
*/
|
||||
void MicroBitRadioEvent::packetReceived()
|
||||
{
|
||||
FrameBuffer *p = uBit.radio.recv();
|
||||
FrameBuffer *p = radio.recv();
|
||||
MicroBitEvent *e = (MicroBitEvent *) p->payload;
|
||||
|
||||
suppressForwarding = true;
|
||||
|
@ -83,6 +120,6 @@ void MicroBitRadioEvent::eventReceived(MicroBitEvent e)
|
|||
buf.protocol = MICROBIT_RADIO_PROTOCOL_EVENTBUS;
|
||||
memcpy(buf.payload, (const uint8_t *)&e, sizeof(MicroBitEvent));
|
||||
|
||||
uBit.radio.send(&buf);
|
||||
radio.send(&buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
* Create a representation of the TemperatureService
|
||||
* @param _ble The instance of a BLE device that we're running on.
|
||||
*/
|
||||
MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
|
||||
ble(_ble)
|
||||
MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble, MicroBitThermometer &_thermometer, MicroBitMessageBus &messageBus) :
|
||||
ble(_ble), thermometer(_thermometer)
|
||||
{
|
||||
// Create the data structures that represent each of our characteristics in Soft Device.
|
||||
GattCharacteristic temperatureDataCharacteristic(MicroBitTemperatureServiceDataUUID, (uint8_t *)&temperatureDataCharacteristicBuffer, 0,
|
||||
|
@ -25,7 +25,7 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
|
|||
|
||||
// Initialise our characteristic values.
|
||||
temperatureDataCharacteristicBuffer = 0;
|
||||
temperaturePeriodCharacteristicBuffer = uBit.thermometer.getPeriod();
|
||||
temperaturePeriodCharacteristicBuffer = thermometer.getPeriod();
|
||||
|
||||
// Set default security requirements
|
||||
temperatureDataCharacteristic.requireSecurity(SecurityManager::MICROBIT_BLE_SECURITY_LEVEL);
|
||||
|
@ -43,7 +43,7 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
|
|||
ble.gattServer().write(temperaturePeriodCharacteristicHandle,(uint8_t *)&temperaturePeriodCharacteristicBuffer, sizeof(temperaturePeriodCharacteristicBuffer));
|
||||
|
||||
ble.onDataWritten(this, &MicroBitTemperatureService::onDataWritten);
|
||||
uBit.MessageBus.listen(MICROBIT_ID_THERMOMETER, MICROBIT_THERMOMETER_EVT_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
messageBus.listen(MICROBIT_ID_THERMOMETER, MICROBIT_THERMOMETER_EVT_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_IMMEDIATE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,7 +53,7 @@ void MicroBitTemperatureService::temperatureUpdate(MicroBitEvent)
|
|||
{
|
||||
if (ble.getGapState().connected)
|
||||
{
|
||||
temperatureDataCharacteristicBuffer = uBit.thermometer.getTemperature();
|
||||
temperatureDataCharacteristicBuffer = thermometer.getTemperature();
|
||||
ble.gattServer().notify(temperatureDataCharacteristicHandle,(uint8_t *)&temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer));
|
||||
}
|
||||
}
|
||||
|
@ -66,11 +66,11 @@ void MicroBitTemperatureService::onDataWritten(const GattWriteCallbackParams *pa
|
|||
if (params->handle == temperaturePeriodCharacteristicHandle && params->len >= sizeof(temperaturePeriodCharacteristicBuffer))
|
||||
{
|
||||
temperaturePeriodCharacteristicBuffer = *((uint16_t *)params->data);
|
||||
uBit.thermometer.setPeriod(temperaturePeriodCharacteristicBuffer);
|
||||
thermometer.setPeriod(temperaturePeriodCharacteristicBuffer);
|
||||
|
||||
// The accelerometer will choose the nearest period to that requested that it can support
|
||||
// Read back the ACTUAL period it is using, and report this back.
|
||||
temperaturePeriodCharacteristicBuffer = uBit.accelerometer.getPeriod();
|
||||
temperaturePeriodCharacteristicBuffer = thermometer.getPeriod();
|
||||
ble.gattServer().write(temperaturePeriodCharacteristicHandle, (const uint8_t *)&temperaturePeriodCharacteristicBuffer, sizeof(temperaturePeriodCharacteristicBuffer));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue