microbit: First draft of reconfigurable frequencies of MicroBitCompass

This commit is contained in:
Joe Finney 2015-09-19 21:00:38 +01:00
parent 2c9f63902c
commit ae0e5611c3
9 changed files with 156 additions and 15 deletions

View File

@ -36,6 +36,7 @@
#include "MicroBitDFUService.h"
#include "MicroBitEventService.h"
#include "MicroBitLEDService.h"
#include "MicroBitAccelerometerService.h"
#include "ExternalEvents.h"
// MicroBit::flags values
@ -109,6 +110,7 @@ class MicroBit
MicroBitDFUService *ble_firmware_update_service;
MicroBitEventService *ble_event_service;
MicroBitLEDService *ble_led_service;
MicroBitAccelerometerService *ble_accelerometer_service;
/**
* Constructor.

View File

@ -36,6 +36,10 @@
#define MMA8653_SAMPLE_RANGES 3
#define MMA8653_SAMPLE_RATES 8
/*
* Accelerometer events
*/
#define MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE 1
struct MMA8653Sample
{

View File

@ -24,12 +24,18 @@ class MicroBitAccelerometerService
*/
MicroBitAccelerometerService(BLEDevice &_ble);
private:
/**
* Callback. Invoked when any of our attributes are written via BLE.
*/
void onDataWritten(const GattWriteCallbackParams *params);
private:
/**
* Accelerometer update callback
*/
void accelerometerUpdate(MicroBitEvent e);
// Bluetooth stack we're running on.
BLEDevice &ble;

View File

@ -36,12 +36,26 @@
#define MAG_CTRL_REG1 0x10
#define MAG_CTRL_REG2 0x11
/**
* Configuration options
*/
struct MAG3110SampleRateConfig
{
uint32_t sample_period;
uint8_t ctrl_reg1;
};
extern const MAG3110SampleRateConfig MAG3110SampleRate[];
#define MAG3110_SAMPLE_RATES 11
/*
* Compass events
*/
#define MICROBIT_COMPASS_EVT_CAL_REQUIRED 1
#define MICROBIT_COMPASS_EVT_CAL_START 2
#define MICROBIT_COMPASS_EVT_CAL_END 3
#define MICROBIT_COMPASS_EVT_DATA_UPDATE 4
/*
* Status Bits
@ -86,7 +100,7 @@ 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
public:
@ -117,6 +131,28 @@ class MicroBitCompass : public MicroBitComponent
*/
MicroBitCompass(uint16_t id, uint16_t address);
/**
* Configures the compass for the sample rate defined
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
*/
void configure();
/**
* 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
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
*/
void setPeriod(int period);
/**
* Reads the currently configured sample rate of the compass.
* @return The time between samples, in milliseconds.
*/
int getPeriod();
/**
* Gets the current heading of the device, relative to magnetic north.
* @return the current heading, in degrees.

View File

@ -160,6 +160,12 @@
#define MICROBIT_BLE_LED_SERVICE 1
#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
#endif
// Defines the maximum length strong that can be written to the
// display over BLE.

View File

@ -121,6 +121,10 @@ void MicroBit::init()
ble_led_service = new MicroBitLEDService(*ble);
#endif
#if CONFIG_ENABLED(MICROBIT_BLE_ACCELEROMETER_SERVICE)
ble_accelerometer_service = new MicroBitAccelerometerService(*ble);
#endif
// Setup advertising.
ble->accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble->accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)MICROBIT_BLE_DEVICE_NAME, sizeof(MICROBIT_BLE_DEVICE_NAME));

View File

@ -174,7 +174,8 @@ void MicroBitAccelerometer::update()
sample.y *= this->sampleRange;
sample.z *= this->sampleRange;
//TODO: Issue an event.
// Indicate that a new sample is available
MicroBitEvent e(id, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE);
};
/**

View File

@ -32,8 +32,9 @@ MicroBitCompass::MicroBitCompass(uint16_t id, uint16_t address) : average(), sam
// Enable automatic reset after each sample;
writeCommand(MAG_CTRL_REG2, 0xA0);
// Select 10Hz update rate, with oversampling. Also enables the device.
writeCommand(MAG_CTRL_REG1, 0x61);
// Select 10Hz update rate, with oversampling, and enable the device.
this->samplePeriod = 100;
this->configure();
//fetch our previous average values
average.x = read16(MAG_OFF_X_MSB);
@ -175,6 +176,11 @@ void MicroBitCompass::idleTick()
calibrateEnd();
}
}
else
{
// Indicate that a new sample is available
MicroBitEvent e(id, MICROBIT_COMPASS_EVT_DATA_UPDATE);
}
}
}
@ -220,6 +226,56 @@ int MicroBitCompass::getZ()
return sample.z;
}
/**
* Configures the compass for the sample rate defined
* in this object. The nearest values are chosen to those defined
* that are supported by the hardware. The instance variables are then
* updated to reflect reality.
*/
void MicroBitCompass::configure()
{
const MAG3110SampleRateConfig *actualSampleRate;
// First find the nearest sample rate to that specified.
actualSampleRate = &MAG3110SampleRate[MAG3110_SAMPLE_RATES-1];
for (int i=MAG3110_SAMPLE_RATES-1; i>=0; i--)
{
if(MAG3110SampleRate[i].sample_period < this->samplePeriod * 1000)
break;
actualSampleRate = &MAG3110SampleRate[i];
}
// OK, we have the correct data. Update our local state.
this->samplePeriod = actualSampleRate->sample_period / 1000;
// 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
* nearest lower rate is chosen.
* @param period the requested time between samples, in milliseconds.
*/
void MicroBitCompass::setPeriod(int period)
{
this->samplePeriod = period;
this->configure();
}
/**
* Reads the currently configured sample rate of the compass.
* @return The time between samples, in milliseconds.
*/
int MicroBitCompass::getPeriod()
{
return (int)samplePeriod;
}
/**
* Attempts to determine the 8 bit ID from the magnetometer.
* @return the id of the compass (magnetometer)
@ -333,6 +389,21 @@ void MicroBitCompass::clearCalibration()
*/
int MicroBitCompass::isIdleCallbackNeeded()
{
//Active HI
// The MAG3110 raises an interrupt line when data is ready, which we sample here.
// The interrupt line is active HI, so simply return the state of the pin.
return int1;
}
const MAG3110SampleRateConfig MAG3110SampleRate[MAG3110_SAMPLE_RATES] = {
{12500, 0x00}, // 80 Hz
{25000, 0x20}, // 40 Hz
{50000, 0x40}, // 20 Hz
{100000, 0x60}, // 10 hz
{200000, 0x80}, // 5 hz
{400000, 0x81}, // 2.5 hz
{800000, 0x82}, // 1.25 hz
{1600000, 0xb0}, // 0.63 hz
{3200000, 0xd0}, // 0.31 hz
{6400000, 0xf0}, // 0.16 hz
{12800000, 0xf1} // 0.08 hz
};

View File

@ -42,9 +42,9 @@ MicroBitAccelerometerService::MicroBitAccelerometerService(BLEDevice &_ble) :
ble.updateCharacteristicValue(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);
}
/**
* Callback. Invoked when any of our attributes are written via BLE.
*/
@ -57,6 +57,17 @@ void MicroBitAccelerometerService::onDataWritten(const GattWriteCallbackParams *
}
}
/**
* Accelerometer update callback
*/
void MicroBitAccelerometerService::accelerometerUpdate(MicroBitEvent e)
{
accelerometerDataCharacteristicBuffer[0] = uBit.accelerometer.getX();
accelerometerDataCharacteristicBuffer[1] = uBit.accelerometer.getY();
accelerometerDataCharacteristicBuffer[2] = uBit.accelerometer.getZ();
ble.gattServer().notify(accelerometerDataCharacteristicHandle,(uint8_t *)accelerometerDataCharacteristicBuffer, sizeof(accelerometerDataCharacteristicBuffer));
}
const uint8_t MicroBitAccelerometerServiceUUID[] = {
0xe9,0x5d,0x07,0x53,0x25,0x1d,0x47,0x0a,0xa0,0x62,0xfa,0x19,0x22,0xdf,0xa9,0xa8