microbit: BLE Profile Beta 1

First functionally complete BLE profile, matching BLE speicfication v1.6.
More specifically, the following services are now functional:

  - AccelerometerService
  - MeganetometerService
  - EventService
  - TemperatureServide
  - IOPinService
  - DFUService
  - ButtonService
  - LEDService

Also, updates to underlying device drivers to enable greater configurability:

  - MicroBitCompass now supports variable sample rates and temperature sensing
  - MicroBitAccelerometer now supports variable sample rates and ranges
  - MicroBitThermometer introduced
  - MicroBitMessageBus adapted to permit enumeration and block removal of listeners

Finally, MicroBit DFU Service has been changed to the new UUIDs specificed in v1.6 of BLE spec.
This commit is contained in:
Joe Finney 2015-09-28 21:40:44 +01:00
parent 4314b68643
commit 18236810a3
24 changed files with 548 additions and 153 deletions

View File

@ -22,6 +22,7 @@
#include "MicroBitPin.h"
#include "MicroBitCompass.h"
#include "MicroBitAccelerometer.h"
#include "MicroBitThermometer.h"
#include "MicroBitMultiButton.h"
#include "MicroBitSerial.h"
@ -105,6 +106,7 @@ class MicroBit
MicroBitMultiButton buttonAB;
MicroBitAccelerometer accelerometer;
MicroBitCompass compass;
MicroBitThermometer thermometer;
//An object of available IO pins on the device
MicroBitIO io;

View File

@ -42,7 +42,7 @@ class MicroBitAccelerometerService
// memory for our 8 bit control characteristics.
uint16_t accelerometerDataCharacteristicBuffer[3];
uint8_t accelerometerPeriodCharacteristicBuffer;
uint16_t accelerometerPeriodCharacteristicBuffer;
// Handles to access each characteristic when they are held by Soft Device.
GattAttribute::Handle_t accelerometerDataCharacteristicHandle;

View File

@ -36,8 +36,6 @@
#define MAG_CTRL_REG1 0x10
#define MAG_CTRL_REG2 0x11
#define MICROBIT_COMPASS_TEMPERATURE_SENSE_PERIOD 1000
/**
* Configuration options
*/
@ -58,7 +56,7 @@ extern const MAG3110SampleRateConfig MAG3110SampleRate[];
#define MICROBIT_COMPASS_EVT_CAL_START 2
#define MICROBIT_COMPASS_EVT_CAL_END 3
#define MICROBIT_COMPASS_EVT_DATA_UPDATE 4
#define MICROBIT_COMPASS_EVT_TEMPERATURE_UPDATE 5
#define MICROBIT_COMPASS_EVT_CONFIG_NEEDED 5
/*
* Status Bits
@ -80,7 +78,6 @@ struct CompassSample
int16_t x;
int16_t y;
int16_t z;
int16_t temperature;
CompassSample()
{
@ -106,16 +103,14 @@ class MicroBitCompass : public MicroBitComponent
uint16_t address; // I2C address of the magnetmometer.
uint16_t samplePeriod; // The time between samples, in millseconds.
unsigned long eventStartTime; // used to store the current system clock when async calibration has started
unsigned long temperatureSampleTime; // used to store the current system clock when async calibration has started
uint8_t temperature; // the current die temperture of the compass chip.
public:
CompassSample minSample; // Calibration sample.
CompassSample maxSample; // Calibration sample.
CompassSample average; // Centre point of sample data.
CompassSample sample; // The latest sample data recorded.
DigitalIn int1; // Data ready interrupt.
public:
/**
* Constructor.
@ -218,7 +213,7 @@ class MicroBitCompass : public MicroBitComponent
* Reads the currently die temperature of the compass.
* @return The temperature, in degrees celsius.
*/
int getTemperature();
int readTemperature();
/**
* Perform the asynchronous calibration of the compass.
@ -305,7 +300,7 @@ class MicroBitCompass : public MicroBitComponent
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 8 bi signed value.
*/
int16_t read8(uint8_t reg);
uint8_t read8(uint8_t reg);
};
#endif

View File

@ -16,6 +16,7 @@
#define MICROBIT_ID_ACCELEROMETER 4
#define MICROBIT_ID_COMPASS 5
#define MICROBIT_ID_DISPLAY 6
#define MICROBIT_ID_THERMOMETER 7
//EDGE connector events
#define MICROBIT_IO_PINS 20

View File

@ -157,40 +157,40 @@
// This enables the control and the LED matrix display via BLE.
// Set '1' to enable.
#ifndef MICROBIT_BLE_LED_SERVICE
#define MICROBIT_BLE_LED_SERVICE 1
#define MICROBIT_BLE_LED_SERVICE 0
#endif
// Enable/Disable BLE Service: MicroBitAccelerometerService
// This enables live access to the on board 3 axis accelerometer.
// Set '1' to enable.
#ifndef MICROBIT_BLE_ACCELEROMETER_SERVICE
#define MICROBIT_BLE_ACCELEROMETER_SERVICE 1
#define MICROBIT_BLE_ACCELEROMETER_SERVICE 0
#endif
// Enable/Disable BLE Service: MicroBitMagnetometerService
// This enables live access to the on board 3 axis magnetometer.
// Set '1' to enable.
#ifndef MICROBIT_BLE_MAGNETOMETER_SERVICE
#define MICROBIT_BLE_MAGNETOMETER_SERVICE 1
#define MICROBIT_BLE_MAGNETOMETER_SERVICE 0
#endif
// Enable/Disable BLE Service: MicroBitButtonService
// This enables live access to the two micro:bit buttons.
// Set '1' to enable.
#ifndef MICROBIT_BLE_BUTTON_SERVICE
#define MICROBIT_BLE_BUTTON_SERVICE 1
#define MICROBIT_BLE_BUTTON_SERVICE 0
#endif
// This enables live access to the two micro:bit buttons.
// Set '1' to enable.
#ifndef MICROBIT_BLE_IO_PIN_SERVICE
#define MICROBIT_BLE_IO_PIN_SERVICE 1
#define MICROBIT_BLE_IO_PIN_SERVICE 0
#endif
// This enables live access to the die temperature sensors on the micro:bit.
// Set '1' to enable.
#ifndef MICROBIT_BLE_TEMPERATURE_SERVICE
#define MICROBIT_BLE_TEMPERATURE_SERVICE 1
#define MICROBIT_BLE_TEMPERATURE_SERVICE 0
#endif
// Defines the maximum length strong that can be written to the

View File

@ -68,9 +68,6 @@ class MicroBitDFUService
private:
// BLE pairing name of this device, encoded as an integer.
uint32_t flashCode;
// State of paiting process.
bool authenticated;
bool flashCodeRequested;
@ -78,9 +75,12 @@ class MicroBitDFUService
// Bluetooth stack we're running on.
BLEDevice &ble;
// memory for our 8 bit control characteristics.
// memory for our 8 bit control characteristic.
uint8_t controlByte;
// BLE pairing name of this device, encoded as an integer.
uint32_t flashCode;
GattAttribute::Handle_t microBitDFUServiceControlCharacteristicHandle;
GattAttribute::Handle_t microBitDFUServiceFlashCodeCharacteristicHandle;

View File

@ -7,6 +7,8 @@
extern const uint8_t MicroBitEventServiceUUID[];
extern const uint8_t MicroBitEventServiceMicroBitEventCharacteristicUUID[];
extern const uint8_t MicroBitEventServiceClientEventCharacteristicUUID[];
extern const uint8_t MicroBitEventServiceMicroBitRequirementsCharacteristicUUID[];
extern const uint8_t MicroBitEventServiceClientRequirementsCharacteristicUUID[];
struct EventServiceEvent
{
@ -19,7 +21,7 @@ struct EventServiceEvent
* Class definition for a MicroBit BLE Event Service.
* Provides a _ble gateway onto the MicroBit Message Bus.
*/
class MicroBitEventService
class MicroBitEventService : public MicroBitComponent
{
public:
@ -29,7 +31,13 @@ class MicroBitEventService
* @param BLE The instance of a BLE device that we're running on.
*/
MicroBitEventService(BLEDevice &_ble);
/**
* Periodic callback from MicroBit scheduler.
* If we're no longer connected, remove any registered Message Bus listeners.
*/
virtual void idleTick();
/**
* Callback. Invoked when any of our attributes are written via BLE.
*/
@ -40,17 +48,32 @@ class MicroBitEventService
*/
void onMicroBitEvent(MicroBitEvent evt);
/**
* read callback on microBitRequirements characteristic.
* Used to iterate through the events that the code on this micro:bit is interested in.
*/
void onRequirementsRead(GattReadAuthCallbackParams *params);
private:
// Bluetooth stack we're running on.
BLEDevice &ble;
// memory for our 8 bit control characteristics.
// memory for our event characteristics.
EventServiceEvent clientEventBuffer;
EventServiceEvent microBitEventBuffer;
EventServiceEvent microBitRequirementsBuffer;
EventServiceEvent clientRequirementsBuffer;
// handles on this service's characterisitics.
GattAttribute::Handle_t microBitEventCharacteristicHandle;
GattAttribute::Handle_t clientRequirementsCharacteristicHandle;
GattAttribute::Handle_t clientEventCharacteristicHandle;
GattCharacteristic *microBitRequirementsCharacteristic;
// Message bus offset last sent to the client...
uint16_t messageBusListenerOffset;
};

View File

@ -38,6 +38,13 @@ class MicroBitMagnetometerService
*/
void magnetometerUpdate(MicroBitEvent e);
/**
* Sample Period Change Needed callback.
* Reconfiguring the magnetometer can to a REALLY long time (sometimes even seconds to complete)
* So we do this in the background when necessary, through this event handler.
*/
void samplePeriodUpdateNeeded(MicroBitEvent e);
// Bluetooth stack we're running on.
BLEDevice &ble;

View File

@ -205,6 +205,13 @@ class MicroBitMessageBus : public MicroBitComponent
template <typename T>
void ignore(uint16_t id, uint16_t value, T* object, void (T::*handler)(MicroBitEvent));
/**
* Returns the microBitListener with the given position in our list.
* @param n The position in the list to return.
* @return the MicroBitListener at postion n in the list, or NULL if the position is invalid.
*/
MicroBitListener *elementAt(int n);
/**
* Returns a 'nonce' for use with the NONCE_ID channel of the message bus.
*/

102
inc/MicroBitThermometer.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef MICROBIT_THERMOMETER_H
#define MICROBIT_THERMOMETER_H
#include "mbed.h"
#include "MicroBitComponent.h"
#define MICROBIT_THERMOMETER_PERIOD 1000
#define MAG3110_SAMPLE_RATES 11
/*
* Temperature events
*/
#define MICROBIT_THERMOMETER_EVT_UPDATE 1
/**
* Class definition for MicroBit Thermometer.
*
* Infers and stores the ambient temoperature based on the surface temperature
* of the various chips on the micro:bit.
*
*/
class MicroBitThermometer : public MicroBitComponent
{
unsigned long sampleTime;
uint32_t samplePeriod;
int16_t temperature;
public:
/**
* Constructor.
* Create new object that can sense temperature.
* @param id the ID of the new MicroBitThermometer object.
*
* Example:
* @code
* thermometer(MICROBIT_ID_THERMOMETER);
* @endcode
*
* Possible Events:
* @code
* MICROBIT_THERMOMETER_EVT_CHANGED
* @endcode
*/
MicroBitThermometer(uint16_t id);
/**
* Set the sample rate at which the temperatureis read (in ms).
* n.b. the temperature is alwasy read in the background, so wis only updated
* when the processor is idle, or when the temperature is explicitly read.
* The default sample period is 1 second.
* @param period the requested time between samples, in milliseconds.
*/
void setPeriod(int period);
/**
* Reads the currently configured sample rate of the thermometer.
* @return The time between samples, in milliseconds.
*/
int getPeriod();
/**
* Gets the current temperature of the microbit.
* @return the current temperature, in degrees celsius.
*
* Example:
* @code
* uBit.thermometer.getTemperature();
* @endcode
*/
int getTemperature();
/**
* Periodic callback from MicroBit idle thread.
* Check if any data is ready for reading by checking the interrupt.
*/
virtual void idleTick();
/**
* Indicates if we'd like some processor time to sense the temperature. 0 means we're not due to read the tmeperature yet.
* @returns 1 if we'd like some processor time, 0 otherwise.
*/
virtual int isIdleCallbackNeeded();
private:
/**
* Determines if we're due to take another temeoratur reading
* @return 1 if we're due to take a temperature reading, 0 otherwise.
*/
int isSampleNeeded();
/**
* Updates our recorded temeprature from the many sensors on the micro:bit!
*/
void updateTemperature();
};
#endif

View File

@ -18,6 +18,7 @@ set(YOTTA_AUTO_MICROBIT-DAL_CPP_FILES
"MicroBitFiber.cpp"
"ManagedString.cpp"
"MicroBitAccelerometer.cpp"
"MicroBitThermometer.cpp"
"MicroBitIO.cpp"
"MicroBitCompat.cpp"
"MicroBitImage.cpp"

View File

@ -59,6 +59,7 @@ MicroBit::MicroBit() :
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),
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,
MICROBIT_ID_IO_P6,MICROBIT_ID_IO_P7,MICROBIT_ID_IO_P8,

View File

@ -144,7 +144,6 @@ int MicroBitAccelerometer::whoAmI()
void MicroBitAccelerometer::update()
{
int8_t data[6];
static int count=0;
readCommand(MMA8653_OUT_X_MSB, (uint8_t *)data, 6);

View File

@ -23,16 +23,11 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
this->id = id;
this->address = address;
//we presume it's calibrated until the average values are read.
//we presume the device calibrated until the average values are read.
this->status = 0x01;
//initialise eventStartTime to 0
this->eventStartTime = 0;
this->temperatureSampleTime = 0;
this->temperature = 0;
// Enable automatic reset after each sample;
writeCommand(MAG_CTRL_REG2, 0xA0);
// Select 10Hz update rate, with oversampling, and enable the device.
this->samplePeriod = 100;
@ -109,9 +104,9 @@ int16_t MicroBitCompass::read16(uint8_t reg)
* @param reg The based address of the 16 bit register to access.
* @return The register value, interpreted as a 8 bi signed value.
*/
int16_t MicroBitCompass::read8(uint8_t reg)
uint8_t MicroBitCompass::read8(uint8_t reg)
{
int8_t data;
uint8_t data;
data = 0;
readCommand(reg, (uint8_t*) &data, 1);
@ -186,19 +181,6 @@ void MicroBitCompass::idleTick()
}
}
// Update the temperature value if needed
if (temperatureSampleTime == 0 || temperatureSampleTime > ticks)
{
uint8_t data;
readCommand(MAG_DIE_TEMP, &data, 1);
temperature = data;
temperatureSampleTime = ticks + MICROBIT_COMPASS_TEMPERATURE_SENSE_PERIOD;
// Indicate that a new sample is available
MicroBitEvent e(id, MICROBIT_COMPASS_EVT_TEMPERATURE_UPDATE);
}
}
/**
@ -253,7 +235,14 @@ void MicroBitCompass::configure()
{
const MAG3110SampleRateConfig *actualSampleRate;
// First find the nearest sample rate to that specified.
// First, take the device offline, so it can be configured.
writeCommand(MAG_CTRL_REG1, 0x00);
// Wait for the part to enter standby mode...
while(this->read8(MAG_SYSMOD) & 0x03)
uBit.sleep(100);
// Find the nearest sample rate to that specified.
actualSampleRate = &MAG3110SampleRate[MAG3110_SAMPLE_RATES-1];
for (int i=MAG3110_SAMPLE_RATES-1; i>=0; i--)
{
@ -266,11 +255,13 @@ void MicroBitCompass::configure()
// OK, we have the correct data. Update our local state.
this->samplePeriod = actualSampleRate->sample_period / 1000;
// Enable automatic reset after each sample;
writeCommand(MAG_CTRL_REG2, 0xA0);
// Bring the device online, with the requested sample frequency.
writeCommand(MAG_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
}
/**
* Attempts to set the sample rate of the compass to the specified value (in ms).
* n.b. the requested rate may not be possible on the hardware. In this case, the
@ -314,8 +305,11 @@ int MicroBitCompass::whoAmI()
* Reads the currently die temperature of the compass.
* @return The temperature, in degrees celsius.
*/
int MicroBitCompass::getTemperature()
int MicroBitCompass::readTemperature()
{
int8_t temperature;
readCommand(MAG_DIE_TEMP, (uint8_t *)&temperature, 1);
return temperature;
}
@ -423,13 +417,13 @@ int MicroBitCompass::isIdleCallbackNeeded()
const MAG3110SampleRateConfig MAG3110SampleRate[MAG3110_SAMPLE_RATES] = {
{12500, 0x00}, // 80 Hz
{25000, 0x20}, // 40 Hz
{50000, 0x40}, // 20 Hz
{50000, 0x40}, // 20 Hz
{100000, 0x60}, // 10 hz
{200000, 0x80}, // 5 hz
{400000, 0x81}, // 2.5 hz
{800000, 0x82}, // 1.25 hz
{400000, 0x88}, // 2.5 hz
{800000, 0x90}, // 1.25 hz
{1600000, 0xb0}, // 0.63 hz
{3200000, 0xd0}, // 0.31 hz
{6400000, 0xf0}, // 0.16 hz
{12800000, 0xf1} // 0.08 hz
{12800000, 0xf8} // 0.08 hz
};

View File

@ -226,7 +226,6 @@ void scheduler_event(MicroBitEvent evt)
}
// Unregister this event, as we've woken up all the fibers with this match.
pc.printf("Scheduler: Deregistering for Event: %d:%d\n", evt.source, evt.value);
uBit.MessageBus.ignore(evt.source, evt.value, scheduler_event);
}
@ -311,7 +310,6 @@ void fiber_wait_for_event(uint16_t id, uint16_t value)
queue_fiber(f, &waitQueue);
// Register to receive this event, so we can wake up the fiber when it happens.
pc.printf("Scheduler: Registering for Event: %d:%d\n", id, value);
uBit.MessageBus.listen(id, value, scheduler_event, MESSAGE_BUS_LISTENER_NONBLOCKING);
// Finally, enter the scheduler.

View File

@ -374,7 +374,6 @@ int MicroBitMessageBus::add(MicroBitListener *newListener)
if (newListener == NULL)
return 0;
l = listeners;
// Firstly, we treat a listener as an idempotent operation. Ensure we don't already have this handler
@ -459,25 +458,28 @@ int MicroBitMessageBus::remove(MicroBitListener *listener)
// Walk this list of event handlers. Delete any that match the given listener.
while (l != NULL)
{
if (l->id == listener->id && l->value == listener->value && ((listener->flags & MESSAGE_BUS_LISTENER_METHOD) == (l->flags & MESSAGE_BUS_LISTENER_METHOD)))
if ((listener->flags & MESSAGE_BUS_LISTENER_METHOD) == (l->flags & MESSAGE_BUS_LISTENER_METHOD))
{
if(((listener->flags & MESSAGE_BUS_LISTENER_METHOD) && (*l->cb_method == *listener->cb_method)) ||
((!(listener->flags & MESSAGE_BUS_LISTENER_METHOD) && l->cb == listener->cb)))
((!(listener->flags & MESSAGE_BUS_LISTENER_METHOD) && l->cb == listener->cb)))
{
// Found a match. Remove from the list.
if (p == NULL)
listeners = l->next;
else
p->next = l->next;
if ((listener->id == MICROBIT_ID_ANY || listener->id == l->id) && (listener->value == MICROBIT_EVT_ANY || listener->value == l->value))
{
// Found a match. Remove from the list.
if (p == NULL)
listeners = l->next;
else
p->next = l->next;
// delete the listener.
MicroBitListener *t = l;
l = l->next;
// delete the listener.
MicroBitListener *t = l;
l = l->next;
delete t;
removed++;
delete t;
removed++;
continue;
continue;
}
}
}
@ -488,3 +490,24 @@ int MicroBitMessageBus::remove(MicroBitListener *listener)
return removed;
}
/**
* Returns the microBitListener with the given position in our list.
* @param n The position in the list to return.
* @return the MicroBitListener at postion n in the list, or NULL if the position is invalid.
*/
MicroBitListener* MicroBitMessageBus::elementAt(int n)
{
MicroBitListener *l = listeners;
while (n > 0)
{
if (l == NULL)
return NULL;
n--;
l = l->next;
}
return l;
}

View File

@ -0,0 +1,136 @@
#include "MicroBit.h"
#include "nrf_soc.h"
/**
* Constructor.
* Create new object that can sense temperature.
* @param id the ID of the new MicroBitThermometer object.
*
* Example:
* @code
* thermometer(MICROBIT_ID_THERMOMETER);
* @endcode
*
* Possible Events:
* @code
* MICROBIT_THERMOMETER_EVT_CHANGED
* @endcode
*/
MicroBitThermometer::MicroBitThermometer(uint16_t id)
{
this->id = id;
this->samplePeriod = MICROBIT_THERMOMETER_PERIOD;
this->sampleTime = 0;
uBit.addIdleComponent(this);
}
/**
* Gets the current temperature of the microbit.
* @return the current temperature, in degrees celsius.
*
* Example:
* @code
* uBit.thermometer.getTemperature();
* @endcode
*/
int MicroBitThermometer::getTemperature()
{
if (isSampleNeeded())
updateTemperature();
return temperature;
}
/**
* Indicates if we'd like some processor time to sense the temperature. 0 means we're not due to read the tmeperature yet.
* @returns 1 if we'd like some processor time, 0 otherwise.
*/
int MicroBitThermometer::isIdleCallbackNeeded()
{
return isSampleNeeded();
}
/**
* periodic callback.
* Check once every second or so for a new temperature reading.
*/
void MicroBitThermometer::idleTick()
{
if (isSampleNeeded())
updateTemperature();
}
/**
* Determines if we're due to take another temeoratur reading
* @return 1 if we're due to take a temperature reading, 0 otherwise.
*/
int MicroBitThermometer::isSampleNeeded()
{
return ticks >= sampleTime;
}
/**
* Set the sample rate at which the temperatureis read (in ms).
* n.b. the temperature is alwasy read in the background, so wis only updated
* when the processor is idle, or when the temperature is explicitly read.
* The default sample period is 1 second.
* @param period the requested time between samples, in milliseconds.
*/
void MicroBitThermometer::setPeriod(int period)
{
samplePeriod = period;
}
/**
* Reads the currently configured sample rate of the thermometer.
* @return The time between samples, in milliseconds.
*/
int MicroBitThermometer::getPeriod()
{
return samplePeriod;
}
/**
* Updates our recorded temperature from the many sensors on the micro:bit!
*/
void MicroBitThermometer::updateTemperature()
{
int32_t processorTemperature;
// 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)
{
// If Bluetooth is enabled, we need to go through the Nordic software to safely do this
sd_temp_get(&processorTemperature);
}
else
{
// Othwerwise, we access the information directly...
uint32_t *TEMP = (uint32_t *)0x4000C508;
NRF_TEMP->TASKS_START = 1;
while (NRF_TEMP->EVENTS_DATARDY == 0);
NRF_TEMP->EVENTS_DATARDY = 0;
processorTemperature = *TEMP;
NRF_TEMP->TASKS_STOP = 1;
}
// Record our reading...
temperature = processorTemperature / 4;
// Schedule our next sample.
sampleTime = ticks + samplePeriod;
// Send an event to indicate that we'e updated our temperature.
MicroBitEvent e(id, MICROBIT_THERMOMETER_EVT_UPDATE);
}

View File

@ -20,7 +20,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
GattCharacteristic accelerometerDataCharacteristic(MicroBitAccelerometerServiceDataUUID, (uint8_t *)accelerometerDataCharacteristicBuffer, 0,
sizeof(accelerometerDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic accelerometerPeriodCharacteristic(MicroBitAccelerometerServicePeriodUUID, (uint8_t *)accelerometerPeriodCharacteristicBuffer, 0,
GattCharacteristic accelerometerPeriodCharacteristic(MicroBitAccelerometerServicePeriodUUID, (uint8_t *)&accelerometerPeriodCharacteristicBuffer, 0,
sizeof(accelerometerPeriodCharacteristicBuffer),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
@ -28,7 +28,7 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
accelerometerDataCharacteristicBuffer[0] = 0;
accelerometerDataCharacteristicBuffer[1] = 0;
accelerometerDataCharacteristicBuffer[2] = 0;
accelerometerPeriodCharacteristicBuffer = 0;
accelerometerPeriodCharacteristicBuffer = uBit.accelerometer.getPeriod();
GattCharacteristic *characteristics[] = {&accelerometerDataCharacteristic, &accelerometerPeriodCharacteristic};
GattService service(MicroBitAccelerometerServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
@ -38,8 +38,8 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
accelerometerDataCharacteristicHandle = accelerometerDataCharacteristic.getValueHandle();
accelerometerPeriodCharacteristicHandle = accelerometerPeriodCharacteristic.getValueHandle();
ble.updateCharacteristicValue(accelerometerDataCharacteristicHandle, (const uint8_t *)&accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
ble.updateCharacteristicValue(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
ble.gattServer().write(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
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_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
@ -52,8 +52,13 @@ void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *
{
if (params->handle == accelerometerPeriodCharacteristicHandle && params->len >= sizeof(accelerometerPeriodCharacteristicBuffer))
{
accelerometerPeriodCharacteristicBuffer = *((uint8_t *)params->data);
accelerometerPeriodCharacteristicBuffer = *((uint16_t *)params->data);
uBit.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();
ble.gattServer().write(accelerometerPeriodCharacteristicHandle, (const uint8_t *)&accelerometerPeriodCharacteristicBuffer, sizeof(accelerometerPeriodCharacteristicBuffer));
}
}
@ -62,11 +67,14 @@ void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *
*/
void MicroBitAccelerometerService::accelerometerUpdate(MicroBitEvent e)
{
accelerometerDataCharacteristicBuffer[0] = uBit.accelerometer.getX();
accelerometerDataCharacteristicBuffer[1] = uBit.accelerometer.getY();
accelerometerDataCharacteristicBuffer[2] = uBit.accelerometer.getZ();
if (ble.getGapState().connected)
{
accelerometerDataCharacteristicBuffer[0] = uBit.accelerometer.getX();
accelerometerDataCharacteristicBuffer[1] = uBit.accelerometer.getY();
accelerometerDataCharacteristicBuffer[2] = uBit.accelerometer.getZ();
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
}
}
const uint8_t MicroBitAccelerometerServiceUUID[] = {

View File

@ -17,10 +17,10 @@ MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) :
ble(_ble)
{
// Create the data structures that represent each of our characteristics in Soft Device.
GattCharacteristic buttonADataCharacteristic(MicroBitButtonAServiceDataUUID, (uint8_t *)buttonADataCharacteristicBuffer, 0,
GattCharacteristic buttonADataCharacteristic(MicroBitButtonAServiceDataUUID, (uint8_t *)&buttonADataCharacteristicBuffer, 0,
sizeof(buttonADataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic buttonBDataCharacteristic(MicroBitButtonBServiceDataUUID, (uint8_t *)buttonADataCharacteristicBuffer, 0,
GattCharacteristic buttonBDataCharacteristic(MicroBitButtonBServiceDataUUID, (uint8_t *)&buttonADataCharacteristicBuffer, 0,
sizeof(buttonADataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
@ -36,8 +36,8 @@ MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) :
buttonADataCharacteristicHandle = buttonADataCharacteristic.getValueHandle();
buttonBDataCharacteristicHandle = buttonBDataCharacteristic.getValueHandle();
ble.updateCharacteristicValue(buttonADataCharacteristicHandle, (const uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
ble.updateCharacteristicValue(buttonBDataCharacteristicHandle, (const uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
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_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
uBit.MessageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, this, &MicroBitButtonService::buttonBUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
@ -49,22 +49,25 @@ MicroBitButtonService::MicroBitButtonService(BLEDevice &_ble) :
*/
void MicroBitButtonService::buttonAUpdate(MicroBitEvent e)
{
if (e.value == MICROBIT_BUTTON_EVT_UP)
if (ble.getGapState().connected)
{
buttonADataCharacteristicBuffer = 0;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_UP)
{
buttonADataCharacteristicBuffer = 0;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_DOWN)
{
buttonADataCharacteristicBuffer = 1;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_DOWN)
{
buttonADataCharacteristicBuffer = 1;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_HOLD)
{
buttonADataCharacteristicBuffer = 2;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
if (e.value == MICROBIT_BUTTON_EVT_HOLD)
{
buttonADataCharacteristicBuffer = 2;
ble.gattServer().notify(buttonADataCharacteristicHandle,(uint8_t *)&buttonADataCharacteristicBuffer, sizeof(buttonADataCharacteristicBuffer));
}
}
}
@ -73,22 +76,25 @@ void MicroBitButtonService::buttonAUpdate(MicroBitEvent e)
*/
void MicroBitButtonService::buttonBUpdate(MicroBitEvent e)
{
if (e.value == MICROBIT_BUTTON_EVT_UP)
if (ble.getGapState().connected)
{
buttonBDataCharacteristicBuffer = 0;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_UP)
{
buttonBDataCharacteristicBuffer = 0;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_DOWN)
{
buttonBDataCharacteristicBuffer = 1;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_DOWN)
{
buttonBDataCharacteristicBuffer = 1;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
}
if (e.value == MICROBIT_BUTTON_EVT_HOLD)
{
buttonBDataCharacteristicBuffer = 2;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
if (e.value == MICROBIT_BUTTON_EVT_HOLD)
{
buttonBDataCharacteristicBuffer = 2;
ble.gattServer().notify(buttonBDataCharacteristicHandle,(uint8_t *)&buttonBDataCharacteristicBuffer, sizeof(buttonBDataCharacteristicBuffer));
}
}
}

View File

@ -21,21 +21,31 @@ MicroBitEventService::MicroBitEventService(BLEDevice &_ble) :
GattCharacteristic clientEventCharacteristic(MicroBitEventServiceClientEventCharacteristicUUID, (uint8_t *)&clientEventBuffer, 0, sizeof(EventServiceEvent),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
GattCharacteristic clientRequirementsCharacteristic(MicroBitEventServiceClientRequirementsCharacteristicUUID, (uint8_t *)&clientRequirementsBuffer, 0, sizeof(EventServiceEvent), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
microBitRequirementsCharacteristic = new GattCharacteristic(MicroBitEventServiceMicroBitRequirementsCharacteristicUUID, (uint8_t *)&microBitRequirementsBuffer, 0, sizeof(EventServiceEvent), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
microBitRequirementsCharacteristic->setReadAuthorizationCallback(this, &MicroBitEventService::onRequirementsRead);
clientEventBuffer.type = 0x00;
clientEventBuffer.reason = 0x00;
microBitEventBuffer.type = 0x00;
microBitEventBuffer.reason = 0x00;
microBitEventBuffer = microBitRequirementsBuffer = clientRequirementsBuffer = clientEventBuffer;
messageBusListenerOffset = 0;
GattCharacteristic *characteristics[] = {&microBitEventCharacteristic, &clientEventCharacteristic};
GattCharacteristic *characteristics[] = {&microBitEventCharacteristic, &clientEventCharacteristic, &clientRequirementsCharacteristic, microBitRequirementsCharacteristic};
GattService service(MicroBitEventServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
ble.addService(service);
microBitEventCharacteristicHandle = microBitEventCharacteristic.getValueHandle();
clientEventCharacteristicHandle = clientEventCharacteristic.getValueHandle();
clientRequirementsCharacteristicHandle = clientRequirementsCharacteristic.getValueHandle();
ble.onDataWritten(this, &MicroBitEventService::onDataWritten);
uBit.addIdleComponent(this);
}
@ -56,6 +66,19 @@ void MicroBitEventService::onDataWritten(const GattWriteCallbackParams *params)
len-=4;
e++;
}
return;
}
if (params->handle == clientRequirementsCharacteristicHandle) {
// Read and register for all the events given...
while (len >= 4)
{
uBit.MessageBus.listen(e->type, e->reason, this, &MicroBitEventService::onMicroBitEvent, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
len-=4;
e++;
}
return;
}
}
@ -70,19 +93,62 @@ void MicroBitEventService::onMicroBitEvent(MicroBitEvent evt)
e->type = evt.source;
e->reason = evt.value;
ble.updateCharacteristicValue(microBitEventCharacteristicHandle, (const uint8_t *)e, sizeof(EventServiceEvent));
ble.gattServer().notify(microBitEventCharacteristicHandle, (const uint8_t *)e, sizeof(EventServiceEvent));
}
}
/**
* Periodic callback from MicroBit scheduler.
* If we're no longer connected, remove any registered Message Bus listeners.
*/
void MicroBitEventService::idleTick()
{
if (!ble.getGapState().connected && messageBusListenerOffset >0) {
messageBusListenerOffset = 0;
uBit.MessageBus.ignore(MICROBIT_ID_ANY, MICROBIT_EVT_ANY, this, &MicroBitEventService::onMicroBitEvent);
}
}
const uint8_t MicroBitEventServiceUUID[] = {
/**
* read callback on data characteristic.
* reads all the pins marked as inputs, and updates the data stored in the BLE stack.
*/
void MicroBitEventService::onRequirementsRead(GattReadAuthCallbackParams *params)
{
if (params->handle == microBitRequirementsCharacteristic->getValueHandle())
{
// 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++);
if (l != NULL)
{
microBitRequirementsBuffer.type = l->id;
microBitRequirementsBuffer.reason = l->value;
ble.gattServer().write(microBitRequirementsCharacteristic->getValueHandle(), (uint8_t *)&microBitRequirementsBuffer, sizeof(EventServiceEvent));
} else {
ble.gattServer().write(microBitRequirementsCharacteristic->getValueHandle(), (uint8_t *)&microBitRequirementsBuffer, 0);
}
}
}
const uint8_t MicroBitEventServiceUUID[] = {
0xe9,0x5d,0x93,0xaf,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};
const uint8_t MicroBitEventServiceMicroBitEventCharacteristicUUID[] = {
const uint8_t MicroBitEventServiceMicroBitEventCharacteristicUUID[] = {
0xe9,0x5d,0x97,0x75,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};
const uint8_t MicroBitEventServiceClientEventCharacteristicUUID[] = {
const uint8_t MicroBitEventServiceClientEventCharacteristicUUID[] = {
0xe9,0x5d,0x54,0x04,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};
const uint8_t MicroBitEventServiceMicroBitRequirementsCharacteristicUUID[] = {
0xe9,0x5d,0xb8,0x4c,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};
const uint8_t MicroBitEventServiceClientRequirementsCharacteristicUUID[] = {
0xe9,0x5d,0x23,0xc4,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};

View File

@ -23,7 +23,7 @@ MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble) :
GattCharacteristic ioPinServiceIOCharacteristic(MicroBitIOPinServiceIOConfigurationUUID, (uint8_t *)&ioPinServiceIOCharacteristicBuffer, 0, sizeof(ioPinServiceIOCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
// Create the Data characteristic, that allows the actual read and write operations.
ioPinServiceDataCharacteristic = new GattCharacteristic(MicroBitIOPinServiceDataUUID, (uint8_t *)&ioPinServiceDataCharacteristicBuffer, 0, sizeof(ioPinServiceDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
ioPinServiceDataCharacteristic = new GattCharacteristic(MicroBitIOPinServiceDataUUID, (uint8_t *)ioPinServiceDataCharacteristicBuffer, 0, sizeof(ioPinServiceDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
ioPinServiceDataCharacteristic->setReadAuthorizationCallback(this, &MicroBitIOPinService::onDataRead);
@ -39,10 +39,11 @@ MicroBitIOPinService::MicroBitIOPinService(BLEDevice &_ble) :
ioPinServiceADCharacteristicHandle = ioPinServiceADCharacteristic.getValueHandle();
ioPinServiceIOCharacteristicHandle = ioPinServiceIOCharacteristic.getValueHandle();
ble.updateCharacteristicValue(ioPinServiceADCharacteristicHandle, (const uint8_t *)&ioPinServiceADCharacteristicBuffer, sizeof(ioPinServiceADCharacteristicBuffer));
ble.updateCharacteristicValue(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer));
ble.gattServer().write(ioPinServiceADCharacteristicHandle, (const uint8_t *)&ioPinServiceADCharacteristicBuffer, sizeof(ioPinServiceADCharacteristicBuffer));
ble.gattServer().write(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer));
ble.onDataWritten(this, &MicroBitIOPinService::onDataWritten);
uBit.addIdleComponent(this);
}
/**
@ -75,7 +76,7 @@ int MicroBitIOPinService::isAnalog(int i)
*/
int MicroBitIOPinService::isInput(int i)
{
return ((ioPinServiceIOCharacteristicBuffer & (1 << i)) == 0);
return ((ioPinServiceIOCharacteristicBuffer & (1 << i)) != 0);
}
/**
@ -86,7 +87,7 @@ int MicroBitIOPinService::isInput(int i)
*/
int MicroBitIOPinService::isOutput(int i)
{
return ((ioPinServiceIOCharacteristicBuffer & (1 << i)) != 0);
return ((ioPinServiceIOCharacteristicBuffer & (1 << i)) == 0);
}
/**
@ -101,7 +102,7 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params)
// Our IO configuration may be changing... read the new value, and push it back into the BLE stack.
ioPinServiceIOCharacteristicBuffer = *value;
ble.updateCharacteristicValue(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer));
ble.gattServer().write(ioPinServiceIOCharacteristicHandle, (const uint8_t *)&ioPinServiceIOCharacteristicBuffer, sizeof(ioPinServiceIOCharacteristicBuffer));
// Also, drop any selected pins into input mode, so we can pick up changes later
for (int i=0; i < MICROBIT_IO_PIN_SERVICE_PINCOUNT; i++)
@ -121,7 +122,7 @@ void MicroBitIOPinService::onDataWritten(const GattWriteCallbackParams *params)
// Our IO configuration may be changing... read the new value, and push it back into the BLE stack.
ioPinServiceADCharacteristicBuffer = *value;
ble.updateCharacteristicValue(ioPinServiceADCharacteristicHandle, (const uint8_t *)&ioPinServiceADCharacteristicBuffer, sizeof(ioPinServiceADCharacteristicBuffer));
ble.gattServer().write(ioPinServiceADCharacteristicHandle, (const uint8_t *)&ioPinServiceADCharacteristicBuffer, sizeof(ioPinServiceADCharacteristicBuffer));
// Also, drop any selected pins into input mode, so we can pick up changes later
for (int i=0; i < MICROBIT_IO_PIN_SERVICE_PINCOUNT; i++)
@ -173,7 +174,7 @@ void MicroBitIOPinService::onDataRead(GattReadAuthCallbackParams *params)
{
if (isInput(i))
{
uint8_t value;
uint8_t value;
if (isDigital(i))
value = MicroBitIOPins[i]->getDigitalValue();
@ -193,7 +194,7 @@ void MicroBitIOPinService::onDataRead(GattReadAuthCallbackParams *params)
// If there's any data, issue a BLE notification.
if (pairs > 0)
ble.updateCharacteristicValue(ioPinServiceDataCharacteristic->getValueHandle(), (uint8_t *)&ioPinServiceDataCharacteristic, pairs * sizeof(IOData));
ble.gattServer().notify(ioPinServiceDataCharacteristic->getValueHandle(), (uint8_t *)ioPinServiceDataCharacteristicBuffer, pairs * sizeof(IOData));
}
}
@ -215,7 +216,7 @@ void MicroBitIOPinService::idleTick()
{
if (isInput(i))
{
uint8_t value;
uint8_t value;
if (isDigital(i))
value = MicroBitIOPins[i]->getDigitalValue();
@ -240,7 +241,7 @@ void MicroBitIOPinService::idleTick()
// If there were any changes, issue a BLE notification.
if (pairs > 0)
ble.gattServer().notify(ioPinServiceDataCharacteristic->getValueHandle(), (uint8_t *)&ioPinServiceDataCharacteristic, pairs * sizeof(IOData));
ble.gattServer().notify(ioPinServiceDataCharacteristic->getValueHandle(), (uint8_t *)ioPinServiceDataCharacteristicBuffer, pairs * sizeof(IOData));
}
const uint8_t MicroBitIOPinServiceUUID[] = {

View File

@ -32,7 +32,6 @@ MicroBitLEDService::MicroBitLEDService(BLEDevice &_ble) :
matrixCharacteristic.setReadAuthorizationCallback(this, &MicroBitLEDService::onDataRead);
GattCharacteristic *characteristics[] = {&matrixCharacteristic, &textCharacteristic, &scrollingSpeedCharacteristic};
GattService service(MicroBitLEDServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
@ -42,12 +41,10 @@ MicroBitLEDService::MicroBitLEDService(BLEDevice &_ble) :
textCharacteristicHandle = textCharacteristic.getValueHandle();
scrollingSpeedCharacteristicHandle = scrollingSpeedCharacteristic.getValueHandle();
ble.updateCharacteristicValue(scrollingSpeedCharacteristicHandle, (const uint8_t *)&scrollingSpeedCharacteristicBuffer, sizeof(scrollingSpeedCharacteristicBuffer));
ble.updateCharacteristicValue(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer));
ble.gattServer().write(scrollingSpeedCharacteristicHandle, (const uint8_t *)&scrollingSpeedCharacteristicBuffer, sizeof(scrollingSpeedCharacteristicBuffer));
ble.gattServer().write(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer));
ble.onDataWritten(this, &MicroBitLEDService::onDataWritten);
}
@ -111,7 +108,7 @@ void MicroBitLEDService::onDataRead(GattReadAuthCallbackParams *params)
}
}
ble.updateCharacteristicValue(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer));
ble.gattServer().write(matrixCharacteristicHandle, (const uint8_t *)&matrixCharacteristicBuffer, sizeof(matrixCharacteristicBuffer));
}
}

View File

@ -20,10 +20,10 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
GattCharacteristic magnetometerDataCharacteristic(MicroBitMagnetometerServiceDataUUID, (uint8_t *)magnetometerDataCharacteristicBuffer, 0,
sizeof(magnetometerDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic magnetometerBearingCharacteristic(MicroBitMagnetometerServiceBearingUUID, (uint8_t *)magnetometerBearingCharacteristicBuffer, 0,
GattCharacteristic magnetometerBearingCharacteristic(MicroBitMagnetometerServiceBearingUUID, (uint8_t *)&magnetometerBearingCharacteristicBuffer, 0,
sizeof(magnetometerBearingCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
GattCharacteristic magnetometerPeriodCharacteristic(MicroBitMagnetometerServicePeriodUUID, (uint8_t *)magnetometerPeriodCharacteristicBuffer, 0,
GattCharacteristic magnetometerPeriodCharacteristic(MicroBitMagnetometerServicePeriodUUID, (uint8_t *)&magnetometerPeriodCharacteristicBuffer, 0,
sizeof(magnetometerPeriodCharacteristicBuffer),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
@ -32,7 +32,7 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
magnetometerDataCharacteristicBuffer[1] = 0;
magnetometerDataCharacteristicBuffer[2] = 0;
magnetometerBearingCharacteristicBuffer = 0;
magnetometerPeriodCharacteristicBuffer = 0;
magnetometerPeriodCharacteristicBuffer = uBit.compass.getPeriod();
GattCharacteristic *characteristics[] = {&magnetometerDataCharacteristic, &magnetometerBearingCharacteristic, &magnetometerPeriodCharacteristic};
GattService service(MicroBitMagnetometerServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));
@ -43,12 +43,14 @@ MicroBitMagnetometerService::MicroBitMagnetometerService(BLEDevice &_ble) :
magnetometerBearingCharacteristicHandle = magnetometerBearingCharacteristic.getValueHandle();
magnetometerPeriodCharacteristicHandle = magnetometerPeriodCharacteristic.getValueHandle();
ble.updateCharacteristicValue(magnetometerDataCharacteristicHandle, (const uint8_t *)&magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
ble.updateCharacteristicValue(magnetometerBearingCharacteristicHandle, (const uint8_t *)&magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
ble.updateCharacteristicValue(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
ble.gattServer().notify(magnetometerDataCharacteristicHandle,(uint8_t *)magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
ble.gattServer().notify(magnetometerBearingCharacteristicHandle,(uint8_t *)&magnetometerBearingCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
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_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CONFIG_NEEDED, this, &MicroBitMagnetometerService::samplePeriodUpdateNeeded);
}
/**
@ -58,8 +60,8 @@ void MicroBitMagnetometerService::onDataWritten(const GattWriteCallbackParams *p
{
if (params->handle == magnetometerPeriodCharacteristicHandle && params->len >= sizeof(magnetometerPeriodCharacteristicBuffer))
{
magnetometerPeriodCharacteristicBuffer = *((uint8_t *)params->data);
uBit.compass.setPeriod(magnetometerPeriodCharacteristicBuffer);
magnetometerPeriodCharacteristicBuffer = *((uint16_t *)params->data);
MicroBitEvent evt(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_CONFIG_NEEDED);
}
}
@ -68,13 +70,37 @@ void MicroBitMagnetometerService::onDataWritten(const GattWriteCallbackParams *p
*/
void MicroBitMagnetometerService::magnetometerUpdate(MicroBitEvent e)
{
magnetometerDataCharacteristicBuffer[0] = uBit.compass.getX();
magnetometerDataCharacteristicBuffer[1] = uBit.compass.getY();
magnetometerDataCharacteristicBuffer[2] = uBit.compass.getZ();
magnetometerBearingCharacteristicBuffer = (uint16_t) uBit.compass.heading();
if (ble.getGapState().connected)
{
magnetometerDataCharacteristicBuffer[0] = uBit.compass.getX();
magnetometerDataCharacteristicBuffer[1] = uBit.compass.getY();
magnetometerDataCharacteristicBuffer[2] = uBit.compass.getZ();
magnetometerBearingCharacteristicBuffer = (uint16_t) uBit.compass.heading();
magnetometerPeriodCharacteristicBuffer = uBit.compass.getPeriod();
ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
ble.gattServer().notify(magnetometerDataCharacteristicHandle,(uint8_t *)magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
ble.gattServer().notify(magnetometerBearingCharacteristicHandle,(uint8_t *)&magnetometerBearingCharacteristicBuffer, sizeof(magnetometerBearingCharacteristicBuffer));
}
}
/**
* Sample Period Change Needed callback.
* Reconfiguring the magnetometer can to a REALLY long time (sometimes even seconds to complete)
* So we do this in the background when necessary, through this event handler.
*/
void MicroBitMagnetometerService::samplePeriodUpdateNeeded(MicroBitEvent e)
{
// Reconfigure the compass. This might take a while...
uBit.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();
// Ensure this is reflected in our BLE connection.
ble.gattServer().write(magnetometerPeriodCharacteristicHandle, (const uint8_t *)&magnetometerPeriodCharacteristicBuffer, sizeof(magnetometerPeriodCharacteristicBuffer));
ble.gattServer().notify(magnetometerDataCharacteristicHandle,(uint8_t *)magnetometerDataCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
ble.gattServer().notify(magnetometerDataCharacteristicHandle,(uint8_t *)magnetometerBearingCharacteristicBuffer, sizeof(magnetometerDataCharacteristicBuffer));
}
const uint8_t MicroBitMagnetometerServiceUUID[] = {
@ -89,9 +115,8 @@ const uint8_t MicroBitMagnetometerServicePeriodUUID[] = {
0xe9,0x5d,0x38,0x6c,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};
// TODO: Need an assigned UUID from martin here..
const uint8_t MicroBitMagnetometerServiceBearingUUID[] = {
0xe9,0x5d,0xde,0xad,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
0xe9,0x5d,0x97,0x15,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8
};

View File

@ -17,7 +17,7 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
ble(_ble)
{
// Create the data structures that represent each of our characteristics in Soft Device.
GattCharacteristic temperatureDataCharacteristic(MicroBitTemperatureServiceDataUUID, (uint8_t *)temperatureDataCharacteristicBuffer, 0,
GattCharacteristic temperatureDataCharacteristic(MicroBitTemperatureServiceDataUUID, (uint8_t *)&temperatureDataCharacteristicBuffer, 0,
sizeof(temperatureDataCharacteristicBuffer), GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
// Initialise our characteristic values.
@ -29,9 +29,9 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
ble.addService(service);
temperatureDataCharacteristicHandle = temperatureDataCharacteristic.getValueHandle();
ble.updateCharacteristicValue(temperatureDataCharacteristicHandle, (const uint8_t *)&temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer));
ble.gattServer().write(temperatureDataCharacteristicHandle,(uint8_t *)&temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer));
uBit.MessageBus.listen(MICROBIT_ID_COMPASS, MICROBIT_COMPASS_EVT_TEMPERATURE_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
uBit.MessageBus.listen(MICROBIT_ID_THERMOMETER, MICROBIT_THERMOMETER_EVT_UPDATE, this, &MicroBitTemperatureService::temperatureUpdate, MESSAGE_BUS_LISTENER_NONBLOCKING | MESSAGE_BUS_LISTENER_URGENT);
}
/**
@ -39,8 +39,11 @@ MicroBitTemperatureService::MicroBitTemperatureService(BLEDevice &_ble) :
*/
void MicroBitTemperatureService::temperatureUpdate(MicroBitEvent e)
{
temperatureDataCharacteristicBuffer = uBit.compass.getTemperature();
ble.gattServer().notify(temperatureDataCharacteristicHandle,(uint8_t *)temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer));
if (ble.getGapState().connected)
{
temperatureDataCharacteristicBuffer = uBit.thermometer.getTemperature();
ble.gattServer().notify(temperatureDataCharacteristicHandle,(uint8_t *)&temperatureDataCharacteristicBuffer, sizeof(temperatureDataCharacteristicBuffer));
}
}
const uint8_t MicroBitTemperatureServiceUUID[] = {