From e79284d797abcc22342f43991fe362241f5b8a6f Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 15 Jun 2018 18:39:56 +0100 Subject: [PATCH] Introduce accelerometer/magnetometer autodetection - Autodetection logic added to MicroBitAccelerometer/MicroBitCompass - Added single byte I2C read utility function into MicroBitI2C - Added isDetected() method into sensor drivers --- inc/core/ErrorNo.h | 3 ++ inc/drivers/FXOS8700.h | 15 ++---- inc/drivers/LSM303Accelerometer.h | 10 +++- inc/drivers/LSM303Magnetometer.h | 10 +++- inc/drivers/MAG3110.h | 10 +++- inc/drivers/MMA8653.h | 11 ++++- inc/drivers/MicroBitAccelerometer.h | 12 +++++ inc/drivers/MicroBitCompass.h | 14 +++++- inc/drivers/MicroBitI2C.h | 12 +++++ source/drivers/FXOS8700.cpp | 48 ++++++++------------ source/drivers/LSM303Accelerometer.cpp | 11 ++++- source/drivers/LSM303Magnetometer.cpp | 12 ++++- source/drivers/MAG3110.cpp | 12 ++++- source/drivers/MMA8653.cpp | 11 ++++- source/drivers/MicroBitAccelerometer.cpp | 58 ++++++++++++++++++++++++ source/drivers/MicroBitCompass.cpp | 57 ++++++++++++++++++++++- source/drivers/MicroBitI2C.cpp | 23 +++++++++- 17 files changed, 273 insertions(+), 56 deletions(-) diff --git a/inc/core/ErrorNo.h b/inc/core/ErrorNo.h index b8a1190..dadec32 100644 --- a/inc/core/ErrorNo.h +++ b/inc/core/ErrorNo.h @@ -82,5 +82,8 @@ enum PanicCode{ // Dereference of a NULL pointer through the ManagedType class, MICROBIT_NULL_DEREFERENCE = 40, + + // A requested hardware peripheral could not be found, + MICROBIT_HARDWARE_UNAVAILABLE = 50, }; #endif diff --git a/inc/drivers/FXOS8700.h b/inc/drivers/FXOS8700.h index 17977f7..f558197 100644 --- a/inc/drivers/FXOS8700.h +++ b/inc/drivers/FXOS8700.h @@ -176,7 +176,7 @@ DEALINGS IN THE SOFTWARE. class FXOS8700 : public MicroBitAccelerometer, public MicroBitCompass { MicroBitI2C& i2c; // The I2C interface to use. - MicroBitPin &int1; // Data ready interrupt. + MicroBitPin int1; // Data ready interrupt. uint16_t address; // I2C address of this accelerometer. public: @@ -190,7 +190,7 @@ class FXOS8700 : public MicroBitAccelerometer, public MicroBitCompass * @param address the default I2C address of the accelerometer. Defaults to: FXOS8700_DEFAULT_ADDR. * */ - FXOS8700(MicroBitI2C &_i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address = FXOS8700_DEFAULT_ADDR, uint16_t aid = MICROBIT_ID_ACCELEROMETER, uint16_t cid = MICROBIT_ID_COMPASS); + FXOS8700(MicroBitI2C &_i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address = FXOS8700_DEFAULT_ADDR, uint16_t aid = MICROBIT_ID_ACCELEROMETER, uint16_t cid = MICROBIT_ID_COMPASS); /** * Configures the accelerometer for G range and sample rate defined @@ -218,16 +218,11 @@ class FXOS8700 : public MicroBitAccelerometer, public MicroBitCompass virtual int requestUpdate(); /** - * Attempts to read the 8 bit ID from the accelerometer, this can be used for - * validation purposes. + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer * - * @return the 8 bit ID returned by the accelerometer, or DEVICE_I2C_ERROR if the request fails. - * - * @code - * accelerometer.whoAmI(); - * @endcode + * @return true if the WHO_AM_I value is succesfully read. false otherwise. */ - int whoAmI(); + static int isDetected(MicroBitI2C &i2c, uint16_t address = FXOS8700_DEFAULT_ADDR); /** * A periodic callback invoked by the fiber scheduler idle thread. diff --git a/inc/drivers/LSM303Accelerometer.h b/inc/drivers/LSM303Accelerometer.h index 11c3761..0ca8048 100644 --- a/inc/drivers/LSM303Accelerometer.h +++ b/inc/drivers/LSM303Accelerometer.h @@ -92,7 +92,7 @@ DEALINGS IN THE SOFTWARE. class LSM303Accelerometer : public MicroBitAccelerometer { MicroBitI2C& i2c; // The I2C interface to use. - MicroBitPin& int1; // Data ready interrupt. + MicroBitPin int1; // Data ready interrupt. uint16_t address; // I2C address of this accelerometer. public: @@ -105,7 +105,7 @@ class LSM303Accelerometer : public MicroBitAccelerometer * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ - LSM303Accelerometer(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address = LSM303_A_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER); + LSM303Accelerometer(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address = LSM303_A_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER); /** * Configures the accelerometer for G range and sample rate defined @@ -140,6 +140,12 @@ class LSM303Accelerometer : public MicroBitAccelerometer */ virtual void idleTick(); + /** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ + static int isDetected(MicroBitI2C &i2c, uint16_t address = LSM303_A_DEFAULT_ADDR); /** * Destructor. diff --git a/inc/drivers/LSM303Magnetometer.h b/inc/drivers/LSM303Magnetometer.h index 89ea508..ad624ec 100644 --- a/inc/drivers/LSM303Magnetometer.h +++ b/inc/drivers/LSM303Magnetometer.h @@ -84,7 +84,7 @@ DEALINGS IN THE SOFTWARE. class LSM303Magnetometer : public MicroBitCompass { MicroBitI2C& i2c; // The I2C interface to use. - MicroBitPin& int1; // Data ready interrupt. + MicroBitPin int1; // Data ready interrupt. uint16_t address; // I2C address of this compass. public: @@ -97,7 +97,7 @@ class LSM303Magnetometer : public MicroBitCompass * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ - LSM303Magnetometer(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address = LSM303_M_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS); + LSM303Magnetometer(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address = LSM303_M_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS); /** * Configures the compass for the sample rate defined in this object. @@ -126,6 +126,12 @@ class LSM303Magnetometer : public MicroBitCompass */ virtual void idleTick(); + /** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ + static int isDetected(MicroBitI2C &i2c, uint16_t address = LSM303_M_DEFAULT_ADDR); /** * Destructor. diff --git a/inc/drivers/MAG3110.h b/inc/drivers/MAG3110.h index 898d548..7749893 100644 --- a/inc/drivers/MAG3110.h +++ b/inc/drivers/MAG3110.h @@ -80,7 +80,7 @@ DEALINGS IN THE SOFTWARE. class MAG3110 : public MicroBitCompass { MicroBitI2C& i2c; // The I2C interface to use. - MicroBitPin& int1; // Data ready interrupt. + MicroBitPin int1; // Data ready interrupt. uint16_t address; // I2C address of this compass. public: @@ -93,7 +93,7 @@ class MAG3110 : public MicroBitCompass * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ - MAG3110(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS); + MAG3110(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address = MAG3110_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_COMPASS); /** * Configures the compass for the sample rate defined in this object. @@ -122,6 +122,12 @@ class MAG3110 : public MicroBitCompass */ virtual void idleTick(); + /** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ + static int isDetected(MicroBitI2C &i2c, uint16_t address = MAG3110_DEFAULT_ADDR); /** * Destructor. diff --git a/inc/drivers/MMA8653.h b/inc/drivers/MMA8653.h index 62fe477..bfe5530 100644 --- a/inc/drivers/MMA8653.h +++ b/inc/drivers/MMA8653.h @@ -68,7 +68,7 @@ DEALINGS IN THE SOFTWARE. class MMA8653 : public MicroBitAccelerometer { MicroBitI2C& i2c; // The I2C interface to use. - MicroBitPin& int1; // Data ready interrupt. + MicroBitPin int1; // Data ready interrupt. uint16_t address; // I2C address of this accelerometer. public: @@ -81,7 +81,7 @@ class MMA8653 : public MicroBitAccelerometer * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ - MMA8653(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address = MMA8653_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER); + MMA8653(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address = MMA8653_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER); /** * Configures the accelerometer for G range and sample rate defined @@ -116,6 +116,13 @@ class MMA8653 : public MicroBitAccelerometer */ virtual void idleTick(); + /** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ + static int isDetected(MicroBitI2C &i2c, uint16_t address = MMA8653_DEFAULT_ADDR); + /** * Destructor. diff --git a/inc/drivers/MicroBitAccelerometer.h b/inc/drivers/MicroBitAccelerometer.h index 9e1598a..c6c73eb 100644 --- a/inc/drivers/MicroBitAccelerometer.h +++ b/inc/drivers/MicroBitAccelerometer.h @@ -29,6 +29,7 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitComponent.h" #include "MicroBitPin.h" #include "CoordinateSystem.h" +#include "MicroBitI2C.h" /** * Status flags @@ -117,6 +118,8 @@ class MicroBitAccelerometer : public MicroBitComponent public: + static MicroBitAccelerometer *detectedAccelerometer; // The autodetected instance of a MicroBitAcelerometer driver. + /** * Constructor. * Create a software abstraction of an accelerometer. @@ -127,6 +130,15 @@ class MicroBitAccelerometer : public MicroBitComponent */ MicroBitAccelerometer(CoordinateSpace &coordinateSpace, uint16_t id = MICROBIT_ID_ACCELEROMETER); + /** + * Device autodetection. Scans the given I2C bus for supported accelerometer devices. + * if found, constructs an appropriate driver and returns it. + * + * @param i2c the bus to scan. + * + */ + static MicroBitAccelerometer& autoDetect(MicroBitI2C &i2c); + /** * Attempts to set the sample rate of the accelerometer to the specified value (in ms). * diff --git a/inc/drivers/MicroBitCompass.h b/inc/drivers/MicroBitCompass.h index 62e1cdc..2047218 100644 --- a/inc/drivers/MicroBitCompass.h +++ b/inc/drivers/MicroBitCompass.h @@ -59,10 +59,12 @@ class MicroBitCompass : public MicroBitComponent Sample3D sample; // The last sample read, in the coordinate system specified by the coordinateSpace variable. Sample3D sampleENU; // The last sample read, in raw ENU format (stored in case requests are made for data in other coordinate spaces) CoordinateSpace &coordinateSpace; // The coordinate space transform (if any) to apply to the raw data from the hardware. - MicroBitAccelerometer* accelerometer; // The accelerometer to use for tilt compensation. + MicroBitAccelerometer* accelerometer; // The accelerometer to use for tilt compensation. public: + static MicroBitCompass *detectedCompass; // The autodetected instance of a MicroBitAcelerometer driver. + /** * Constructor. * Create a software abstraction of an e-compass. @@ -84,6 +86,16 @@ class MicroBitCompass : public MicroBitComponent */ MicroBitCompass(MicroBitAccelerometer &accel, CoordinateSpace &coordinateSpace, uint16_t id = MICROBIT_ID_COMPASS); + /** + * Device autodetection. Scans the given I2C bus for supported compass devices. + * if found, constructs an appropriate driver and returns it. + * + * @param i2c the bus to scan. + * + */ + static MicroBitCompass& autoDetect(MicroBitI2C &i2c); + + /** * Gets the current heading of the device, relative to magnetic north. * diff --git a/inc/drivers/MicroBitI2C.h b/inc/drivers/MicroBitI2C.h index 563c09b..e626aeb 100644 --- a/inc/drivers/MicroBitI2C.h +++ b/inc/drivers/MicroBitI2C.h @@ -131,6 +131,18 @@ class MicroBitI2C : public I2C */ int readRegister(uint8_t address, uint8_t reg, uint8_t* buffer, int length); + /** + * Issues a single byte read command, and returns the value read, or an error. + * + * Blocks the calling thread until complete. + * + * @param address The address of the I2C device to write to. + * @param reg The address of the register to access. + * + * @return the byte read on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed. + */ + int readRegister(uint8_t address, uint8_t reg); + }; #endif diff --git a/source/drivers/FXOS8700.cpp b/source/drivers/FXOS8700.cpp index da32638..095d028 100644 --- a/source/drivers/FXOS8700.cpp +++ b/source/drivers/FXOS8700.cpp @@ -149,7 +149,7 @@ int FXOS8700::configure() * @param address the default I2C address of the accelerometer. Defaults to: FXS8700_DEFAULT_ADDR. * */ -FXOS8700::FXOS8700(MicroBitI2C &_i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t aid, uint16_t cid) : +FXOS8700::FXOS8700(MicroBitI2C &_i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t aid, uint16_t cid) : MicroBitAccelerometer(coordinateSpace, aid), MicroBitCompass(coordinateSpace, cid), i2c(_i2c), int1(_int1) @@ -165,38 +165,26 @@ FXOS8700::FXOS8700(MicroBitI2C &_i2c, MicroBitPin &_int1, CoordinateSpace &coord } /** - * Attempts to read the 8 bit ID from the accelerometer, this can be used for - * validation purposes. - * - * @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails. - * - * @code - * accelerometer.whoAmI(); - * @endcode - */ -int FXOS8700::whoAmI() + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ +int FXOS8700::isDetected(MicroBitI2C &i2c, uint16_t address) { - uint8_t data; - int result; - - result = i2c.readRegister(address, FXOS8700_WHO_AM_I, &data, 1); - if (result !=0) - return MICROBIT_I2C_ERROR; - - return (int)data; + return i2c.readRegister(address, FXOS8700_WHO_AM_I) == FXOS8700_WHOAMI_VAL; } - /** - * Poll to see if new data is available from the hardware. If so, update it. - * n.b. it is not necessary to explicitly call this funciton to update data - * (it normally happens in the background when the scheduler is idle), but a check is performed - * if the user explicitly requests up to date data. - * - * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the update fails. - * - * @note This method should be overidden by the hardware driver to implement the requested - * changes in hardware. - */ +/** + * Poll to see if new data is available from the hardware. If so, update it. + * n.b. it is not necessary to explicitly call this funciton to update data + * (it normally happens in the background when the scheduler is idle), but a check is performed + * if the user explicitly requests up to date data. + * + * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the update fails. + * + * @note This method should be overidden by the hardware driver to implement the requested + * changes in hardware. + */ int FXOS8700::requestUpdate() { // Ensure we're scheduled to update the data periodically diff --git a/source/drivers/LSM303Accelerometer.cpp b/source/drivers/LSM303Accelerometer.cpp index e79d0c1..2f81f12 100644 --- a/source/drivers/LSM303Accelerometer.cpp +++ b/source/drivers/LSM303Accelerometer.cpp @@ -73,7 +73,7 @@ CREATE_KEY_VALUE_TABLE(accelerometerPeriod, accelerometerPeriodData); * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ -LSM303Accelerometer::LSM303Accelerometer(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitAccelerometer(coordinateSpace, id), i2c(_i2c), int1(_int1) +LSM303Accelerometer::LSM303Accelerometer(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitAccelerometer(coordinateSpace, id), i2c(_i2c), int1(_int1) { // Store our identifiers. this->status = 0; @@ -190,6 +190,15 @@ void LSM303Accelerometer::idleTick() requestUpdate(); } +/** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ +int LSM303Accelerometer::isDetected(MicroBitI2C &i2c, uint16_t address) +{ + return i2c.readRegister(address, LSM303_WHO_AM_I_A) == LSM303_A_WHOAMI_VAL; +} /** * Destructor. diff --git a/source/drivers/LSM303Magnetometer.cpp b/source/drivers/LSM303Magnetometer.cpp index 8044857..abd0c83 100644 --- a/source/drivers/LSM303Magnetometer.cpp +++ b/source/drivers/LSM303Magnetometer.cpp @@ -84,7 +84,7 @@ int LSM303Magnetometer::configure() * @param address the default I2C address of the magnetometer. Defaults to: FXS8700_DEFAULT_ADDR. * */ -LSM303Magnetometer::LSM303Magnetometer(MicroBitI2C &_i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitCompass(coordinateSpace, id), i2c(_i2c), int1(_int1) +LSM303Magnetometer::LSM303Magnetometer(MicroBitI2C &_i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitCompass(coordinateSpace, id), i2c(_i2c), int1(_int1) { // Store our identifiers. this->address = address; @@ -160,6 +160,16 @@ void LSM303Magnetometer::idleTick() requestUpdate(); } +/** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ +int LSM303Magnetometer::isDetected(MicroBitI2C &i2c, uint16_t address) +{ + return i2c.readRegister(address, LSM303_WHO_AM_I_M) == LSM303_M_WHOAMI_VAL; +} + /** * Destructor for FXS8700, where we deregister from the array of fiber components. */ diff --git a/source/drivers/MAG3110.cpp b/source/drivers/MAG3110.cpp index 45f365b..8bc18fd 100644 --- a/source/drivers/MAG3110.cpp +++ b/source/drivers/MAG3110.cpp @@ -115,7 +115,7 @@ int MAG3110::configure() * @param address the default I2C address of the magnetometer. Defaults to: FXS8700_DEFAULT_ADDR. * */ -MAG3110::MAG3110(MicroBitI2C &_i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitCompass(coordinateSpace, id), i2c(_i2c), int1(_int1) +MAG3110::MAG3110(MicroBitI2C &_i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitCompass(coordinateSpace, id), i2c(_i2c), int1(_int1) { // Store our identifiers. this->address = address; @@ -190,6 +190,16 @@ void MAG3110::idleTick() requestUpdate(); } +/** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ +int MAG3110::isDetected(MicroBitI2C &i2c, uint16_t address) +{ + return i2c.readRegister(address, MAG_WHOAMI) == MAG3110_WHOAMI_VAL; +} + /** * Destructor for FXS8700, where we deregister from the array of fiber components. */ diff --git a/source/drivers/MMA8653.cpp b/source/drivers/MMA8653.cpp index 0c0e270..8195fc4 100644 --- a/source/drivers/MMA8653.cpp +++ b/source/drivers/MMA8653.cpp @@ -71,7 +71,7 @@ CREATE_KEY_VALUE_TABLE(accelerometerPeriod, accelerometerPeriodData); * @param id The unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER * */ -MMA8653::MMA8653(MicroBitI2C& _i2c, MicroBitPin &_int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitAccelerometer(coordinateSpace, id), i2c(_i2c), int1(_int1) +MMA8653::MMA8653(MicroBitI2C& _i2c, MicroBitPin _int1, CoordinateSpace &coordinateSpace, uint16_t address, uint16_t id) : MicroBitAccelerometer(coordinateSpace, id), i2c(_i2c), int1(_int1) { // Store our identifiers. this->status = 0; @@ -205,6 +205,15 @@ void MMA8653::idleTick() requestUpdate(); } +/** + * Attempts to read the 8 bit WHO_AM_I value from the accelerometer + * + * @return true if the WHO_AM_I value is succesfully read. false otherwise. + */ +int MMA8653::isDetected(MicroBitI2C &i2c, uint16_t address) +{ + return i2c.readRegister(address, MMA8653_WHOAMI) == MMA8653_WHOAMI_VAL; +} /** * Destructor. diff --git a/source/drivers/MicroBitAccelerometer.cpp b/source/drivers/MicroBitAccelerometer.cpp index 1406da2..c2f0c01 100644 --- a/source/drivers/MicroBitAccelerometer.cpp +++ b/source/drivers/MicroBitAccelerometer.cpp @@ -27,7 +27,12 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitEvent.h" #include "MicroBitCompat.h" #include "MicroBitFiber.h" +#include "MicroBitDevice.h" +#include "MicroBitI2C.h" +#include "MMA8653.h" +#include "FXOS8700.h" +#include "LSM303Accelerometer.h" /** * Constructor. @@ -63,6 +68,58 @@ MicroBitAccelerometer::MicroBitAccelerometer(CoordinateSpace &cspace, uint16_t i this->shake.impulse_8 = 1; } +/** + * Device autodetection. Scans the given I2C bus for supported accelerometer devices. + * if found, constructs an appropriate driver and returns it. + * + * @param i2c the bus to scan. + * @param id the unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER + * + */ +MicroBitAccelerometer& MicroBitAccelerometer::autoDetect(MicroBitI2C &i2c) +{ + if (MicroBitAccelerometer::detectedAccelerometer == NULL) + { + // Configuration of IRQ lines + MicroBitPin int1(MICROBIT_ID_IO_INT1, P0_28, PIN_CAPABILITY_STANDARD); + MicroBitPin int2(MICROBIT_ID_IO_INT2, P0_29, PIN_CAPABILITY_STANDARD); + MicroBitPin int3(MICROBIT_ID_IO_INT3, P0_27, PIN_CAPABILITY_STANDARD); + + // All known accelerometer/magnetometer peripherals have the same alignment + CoordinateSpace &coordinateSpace = *(new CoordinateSpace(SIMPLE_CARTESIAN, true, COORDINATE_SPACE_ROTATED_0)); + + // Now, probe for connected peripherals, if none have already been found. + if (MMA8653::isDetected(i2c)) + MicroBitAccelerometer::detectedAccelerometer = new MMA8653(i2c, int1, coordinateSpace); + + else if (LSM303Accelerometer::isDetected(i2c)) + MicroBitAccelerometer::detectedAccelerometer = new LSM303Accelerometer(i2c, int1, coordinateSpace); + + else if (FXOS8700::isDetected(i2c)) + { + FXOS8700 *fxos = new FXOS8700(i2c, int3, coordinateSpace); + MicroBitAccelerometer::detectedAccelerometer = fxos; + MicroBitCompass::detectedCompass = fxos; + } + + // Insert this case to support FXOS on the microbit1.5-SN + //else if (FXOS8700::isDetected(i2c, 0x3A)) + //{ + // FXOS8700 *fxos = new FXOS8700(i2c, int3, coordinateSpace, 0x3A); + // MicroBitAccelerometer::detectedAccelerometer = fxos; + // MicroBitCompass::detectedCompass = fxos; + //} + + else + { + microbit_panic(MICROBIT_HARDWARE_UNAVAILABLE); + } + } + + return *MicroBitAccelerometer::detectedAccelerometer; +} + + /** * Stores data from the accelerometer sensor in our buffer, and perform gesture tracking. * @@ -546,3 +603,4 @@ MicroBitAccelerometer::~MicroBitAccelerometer() { } +MicroBitAccelerometer* MicroBitAccelerometer::detectedAccelerometer = NULL; diff --git a/source/drivers/MicroBitCompass.cpp b/source/drivers/MicroBitCompass.cpp index 72d7b69..627791e 100644 --- a/source/drivers/MicroBitCompass.cpp +++ b/source/drivers/MicroBitCompass.cpp @@ -27,6 +27,11 @@ DEALINGS IN THE SOFTWARE. #include "MicroBitEvent.h" #include "MicroBitCompat.h" #include "MicroBitFiber.h" +#include "MicroBitDevice.h" + +#include "MAG3110.h" +#include "LSM303Magnetometer.h" +#include "FXOS8700.h" /** @@ -81,6 +86,56 @@ void MicroBitCompass::init(uint16_t id) status |= MICROBIT_COMPONENT_RUNNING; } +/** + * Device autodetection. Scans the given I2C bus for supported accelerometer devices. + * if found, constructs an appropriate driver and returns it. + * + * @param i2c the bus to scan. + * @param id the unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER + * + */ +MicroBitCompass& MicroBitCompass::autoDetect(MicroBitI2C &i2c) +{ + if (MicroBitCompass::detectedCompass == NULL) + { + // Configuration of IRQ lines + MicroBitPin int1(MICROBIT_ID_IO_INT1, P0_28, PIN_CAPABILITY_STANDARD); + MicroBitPin int2(MICROBIT_ID_IO_INT2, P0_29, PIN_CAPABILITY_STANDARD); + MicroBitPin int3(MICROBIT_ID_IO_INT3, P0_27, PIN_CAPABILITY_STANDARD); + + // All known accelerometer/magnetometer peripherals have the same alignment + CoordinateSpace &coordinateSpace = *(new CoordinateSpace(SIMPLE_CARTESIAN, true, COORDINATE_SPACE_ROTATED_0)); + + // Now, probe for connected peripherals, if none have already been found. + if (MAG3110::isDetected(i2c)) + MicroBitCompass::detectedCompass = new MAG3110(i2c, int2, coordinateSpace); + + else if (LSM303Magnetometer::isDetected(i2c)) + MicroBitCompass::detectedCompass = new LSM303Magnetometer(i2c, int2, coordinateSpace); + + else if (FXOS8700::isDetected(i2c)) + { + FXOS8700 *fxos = new FXOS8700(i2c, int3, coordinateSpace); + MicroBitAccelerometer::detectedAccelerometer = fxos; + MicroBitCompass::detectedCompass = fxos; + } + + // Insert this case to support FXOS on the microbit1.5-SN + //else if (FXOS8700::isDetected(i2c, 0x3A)) + //{ + // FXOS8700 *fxos = new FXOS8700(i2c, int3, coordinateSpace, 0x3A); + // MicroBitAccelerometer::detectedAccelerometer = fxos; + // MicroBitCompass::detectedCompass = fxos; + //} + + else + { + microbit_panic(MICROBIT_HARDWARE_UNAVAILABLE); + } + } + + return *MicroBitCompass::detectedCompass; +} /** * Gets the current heading of the device, relative to magnetic north. @@ -416,4 +471,4 @@ MicroBitCompass::~MicroBitCompass() { } - +MicroBitCompass* MicroBitCompass::detectedCompass= NULL; diff --git a/source/drivers/MicroBitI2C.cpp b/source/drivers/MicroBitI2C.cpp index 46a5c89..c8edfd7 100644 --- a/source/drivers/MicroBitI2C.cpp +++ b/source/drivers/MicroBitI2C.cpp @@ -162,10 +162,9 @@ int MicroBitI2C::writeRegister(uint8_t address, uint8_t reg, uint8_t value) * * Blocks the calling thread until complete. * + * @param address The address of the I2C device to write to. * @param reg The address of the register to access. - * * @param buffer Memory area to read the data into. - * * @param length The number of bytes to read. * * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed. @@ -187,3 +186,23 @@ int MicroBitI2C::readRegister(uint8_t address, uint8_t reg, uint8_t* buffer, int return MICROBIT_OK; } + +/** + * Issues a single byte read command, and returns the value read, or an error. + * + * Blocks the calling thread until complete. + * + * @param address The address of the I2C device to write to. + * @param reg The address of the register to access. + * + * @return the byte read on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed. + */ +int MicroBitI2C::readRegister(uint8_t address, uint8_t reg) +{ + int result; + uint8_t data; + + result = readRegister(address, reg, &data, 1); + + return (result == MICROBIT_OK) ? (int)data : result; +}