Eddystone test using modified DAL

Dependencies:   BLE_API mbed-dev-bin nRF51822

Dependents:   microbit-eddystone

Fork of microbit-dal by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MicroBitAccelerometer.h Source File

MicroBitAccelerometer.h

00001 /*
00002 The MIT License (MIT)
00003 
00004 Copyright (c) 2016 British Broadcasting Corporation.
00005 This software is provided by Lancaster University by arrangement with the BBC.
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a
00008 copy of this software and associated documentation files (the "Software"),
00009 to deal in the Software without restriction, including without limitation
00010 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011 and/or sell copies of the Software, and to permit persons to whom the
00012 Software is furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00020 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00022 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00023 DEALINGS IN THE SOFTWARE.
00024 */
00025 
00026 #ifndef MICROBIT_ACCELEROMETER_H
00027 #define MICROBIT_ACCELEROMETER_H
00028 
00029 #include "mbed.h"
00030 #include "MicroBitConfig.h"
00031 #include "MicroBitComponent.h"
00032 #include "MicroBitCoordinateSystem.h"
00033 #include "MicroBitI2C.h"
00034 
00035 /**
00036   * Relevant pin assignments
00037   */
00038 #define MICROBIT_PIN_ACCEL_DATA_READY          P0_28
00039 
00040 /**
00041   * Status flags
00042   */
00043 #define MICROBIT_ACCEL_PITCH_ROLL_VALID           0x02
00044 #define MICROBIT_ACCEL_ADDED_TO_IDLE              0x04
00045 
00046 /**
00047   * I2C constants
00048   */
00049 #define MMA8653_DEFAULT_ADDR    0x3A
00050 
00051 /**
00052   * MMA8653 Register map (partial)
00053   */
00054 #define MMA8653_STATUS          0x00
00055 #define MMA8653_OUT_X_MSB       0x01
00056 #define MMA8653_WHOAMI          0x0D
00057 #define MMA8653_XYZ_DATA_CFG    0x0E
00058 #define MMA8653_CTRL_REG1       0x2A
00059 #define MMA8653_CTRL_REG2       0x2B
00060 #define MMA8653_CTRL_REG3       0x2C
00061 #define MMA8653_CTRL_REG4       0x2D
00062 #define MMA8653_CTRL_REG5       0x2E
00063 
00064 
00065 /**
00066   * MMA8653 constants
00067   */
00068 #define MMA8653_WHOAMI_VAL      0x5A
00069 
00070 #define MMA8653_SAMPLE_RANGES   3
00071 #define MMA8653_SAMPLE_RATES    8
00072 
00073 /**
00074   * Accelerometer events
00075   */
00076 #define MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE              1
00077 
00078 /**
00079   * Gesture events
00080   */
00081 #define MICROBIT_ACCELEROMETER_EVT_NONE                     0
00082 #define MICROBIT_ACCELEROMETER_EVT_TILT_UP                  1
00083 #define MICROBIT_ACCELEROMETER_EVT_TILT_DOWN                2
00084 #define MICROBIT_ACCELEROMETER_EVT_TILT_LEFT                3
00085 #define MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT               4
00086 #define MICROBIT_ACCELEROMETER_EVT_FACE_UP                  5
00087 #define MICROBIT_ACCELEROMETER_EVT_FACE_DOWN                6
00088 #define MICROBIT_ACCELEROMETER_EVT_FREEFALL                 7
00089 #define MICROBIT_ACCELEROMETER_EVT_3G                       8
00090 #define MICROBIT_ACCELEROMETER_EVT_6G                       9
00091 #define MICROBIT_ACCELEROMETER_EVT_8G                       10
00092 #define MICROBIT_ACCELEROMETER_EVT_SHAKE                    11
00093 
00094 /**
00095   * Gesture recogniser constants
00096   */
00097 #define MICROBIT_ACCELEROMETER_REST_TOLERANCE               200
00098 #define MICROBIT_ACCELEROMETER_TILT_TOLERANCE               200
00099 #define MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE           400
00100 #define MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE              400
00101 #define MICROBIT_ACCELEROMETER_3G_TOLERANCE                 3072
00102 #define MICROBIT_ACCELEROMETER_6G_TOLERANCE                 6144
00103 #define MICROBIT_ACCELEROMETER_8G_TOLERANCE                 8192
00104 #define MICROBIT_ACCELEROMETER_GESTURE_DAMPING              5
00105 #define MICROBIT_ACCELEROMETER_SHAKE_DAMPING                10 
00106 #define MICROBIT_ACCELEROMETER_SHAKE_RTX                    30
00107 
00108 #define MICROBIT_ACCELEROMETER_REST_THRESHOLD               (MICROBIT_ACCELEROMETER_REST_TOLERANCE * MICROBIT_ACCELEROMETER_REST_TOLERANCE)
00109 #define MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD           (MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE * MICROBIT_ACCELEROMETER_FREEFALL_TOLERANCE)
00110 #define MICROBIT_ACCELEROMETER_3G_THRESHOLD                 (MICROBIT_ACCELEROMETER_3G_TOLERANCE * MICROBIT_ACCELEROMETER_3G_TOLERANCE)
00111 #define MICROBIT_ACCELEROMETER_6G_THRESHOLD                 (MICROBIT_ACCELEROMETER_6G_TOLERANCE * MICROBIT_ACCELEROMETER_6G_TOLERANCE)
00112 #define MICROBIT_ACCELEROMETER_8G_THRESHOLD                 (MICROBIT_ACCELEROMETER_8G_TOLERANCE * MICROBIT_ACCELEROMETER_8G_TOLERANCE)
00113 #define MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD        4
00114 
00115 struct MMA8653Sample
00116 {
00117     int16_t         x;
00118     int16_t         y;
00119     int16_t         z;
00120 };
00121 
00122 struct MMA8653SampleRateConfig
00123 {
00124     uint32_t        sample_period;
00125     uint8_t         ctrl_reg1;
00126 };
00127 
00128 struct MMA8653SampleRangeConfig
00129 {
00130     uint8_t         sample_range;
00131     uint8_t         xyz_data_cfg;
00132 };
00133 
00134 
00135 extern const MMA8653SampleRangeConfig MMA8653SampleRange[];
00136 extern const MMA8653SampleRateConfig MMA8653SampleRate[];
00137 
00138 struct ShakeHistory
00139 {
00140     uint16_t    shaken:1,
00141                 x:1,
00142                 y:1,
00143                 z:1,
00144                 unused,
00145                 impulse_3,
00146                 impulse_6,
00147                 impulse_8,
00148                 count:8;
00149 
00150     uint16_t    timer;
00151 };
00152 
00153 /**
00154  * Class definition for MicroBit Accelerometer.
00155  *
00156  * Represents an implementation of the Freescale MMA8653 3 axis accelerometer
00157  * Also includes basic data caching and on demand activation.
00158  */
00159 class MicroBitAccelerometer : public MicroBitComponent
00160 {
00161     uint16_t        address;            // I2C address of this accelerometer.
00162     uint16_t        samplePeriod;       // The time between samples, in milliseconds.
00163     uint8_t         sampleRange;        // The sample range of the accelerometer in g.
00164     MMA8653Sample   sample;             // The last sample read.
00165     DigitalIn       int1;               // Data ready interrupt.
00166     float           pitch;              // Pitch of the device, in radians.
00167     MicroBitI2C&    i2c;                // The I2C interface to use.
00168     float           roll;               // Roll of the device, in radians.
00169     uint8_t         sigma;              // the number of ticks that the instantaneous gesture has been stable.
00170     uint8_t         impulseSigma;       // the number of ticks since an impulse event has been generated.
00171     uint16_t        lastGesture;        // the last, stable gesture recorded.
00172     uint16_t        currentGesture;     // the instantaneous, unfiltered gesture detected.
00173     ShakeHistory    shake;              // State information needed to detect shake events.
00174 
00175     public:
00176 
00177     /**
00178       * Constructor.
00179       * Create a software abstraction of an accelerometer.
00180       *
00181       * @param _i2c an instance of MicroBitI2C used to communicate with the onboard accelerometer.
00182       *
00183       * @param address the default I2C address of the accelerometer. Defaults to: MMA8653_DEFAULT_ADDR.
00184       *
00185       * @param id the unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER
00186       *
00187       * @code
00188       * MicroBitI2C i2c = MicroBitI2C(I2C_SDA0, I2C_SCL0);
00189       *
00190       * MicroBitAccelerometer accelerometer = MicroBitAccelerometer(i2c);
00191       * @endcode
00192      */
00193     MicroBitAccelerometer(MicroBitI2C &_i2c, uint16_t address = MMA8653_DEFAULT_ADDR, uint16_t id = MICROBIT_ID_ACCELEROMETER);
00194 
00195     /**
00196       * Configures the accelerometer for G range and sample rate defined
00197       * in this object. The nearest values are chosen to those defined
00198       * that are supported by the hardware. The instance variables are then
00199       * updated to reflect reality.
00200       *
00201       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
00202       */
00203     int configure();
00204 
00205     /**
00206       * Reads the acceleration data from the accelerometer, and stores it in our buffer.
00207       * This only happens if the accelerometer indicates that it has new data via int1.
00208       *
00209       * On first use, this member function will attempt to add this component to the
00210       * list of fiber components in order to constantly update the values stored
00211       * by this object.
00212       *
00213       * This technique is called lazy instantiation, and it means that we do not
00214       * obtain the overhead from non-chalantly adding this component to fiber components.
00215       *
00216       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the read request fails.
00217       */
00218     int updateSample();
00219 
00220     /**
00221       * Attempts to set the sample rate of the accelerometer to the specified value (in ms).
00222       *
00223       * @param period the requested time between samples, in milliseconds.
00224       *
00225       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
00226       *
00227       * @code
00228       * // sample rate is now 20 ms.
00229       * accelerometer.setPeriod(20);
00230       * @endcode
00231       *
00232       * @note The requested rate may not be possible on the hardware. In this case, the
00233       * nearest lower rate is chosen.
00234       */
00235     int setPeriod(int period);
00236 
00237     /**
00238       * Reads the currently configured sample rate of the accelerometer.
00239       *
00240       * @return The time between samples, in milliseconds.
00241       */
00242     int getPeriod();
00243 
00244     /**
00245       * Attempts to set the sample range of the accelerometer to the specified value (in g).
00246       *
00247       * @param range The requested sample range of samples, in g.
00248       *
00249       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
00250       *
00251       * @code
00252       * // the sample range of the accelerometer is now 8G.
00253       * accelerometer.setRange(8);
00254       * @endcode
00255       *
00256       * @note The requested range may not be possible on the hardware. In this case, the
00257       * nearest lower range is chosen.
00258       */
00259     int setRange(int range);
00260 
00261     /**
00262       * Reads the currently configured sample range of the accelerometer.
00263       *
00264       * @return The sample range, in g.
00265       */
00266     int getRange();
00267 
00268     /**
00269       * Attempts to read the 8 bit ID from the accelerometer, this can be used for
00270       * validation purposes.
00271       *
00272       * @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
00273       *
00274       * @code
00275       * accelerometer.whoAmI();
00276       * @endcode
00277       */
00278     int whoAmI();
00279 
00280     /**
00281       * Reads the value of the X axis from the latest update retrieved from the accelerometer.
00282       *
00283       * @param system The coordinate system to use. By default, a simple cartesian system is provided.
00284       *
00285       * @return The force measured in the X axis, in milli-g.
00286       *
00287       * @code
00288       * accelerometer.getX();
00289       * @endcode
00290       */
00291     int getX(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00292 
00293     /**
00294       * Reads the value of the Y axis from the latest update retrieved from the accelerometer.
00295       *
00296       * @return The force measured in the Y axis, in milli-g.
00297       *
00298       * @code
00299       * accelerometer.getY();
00300       * @endcode
00301       */
00302     int getY(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00303 
00304     /**
00305       * Reads the value of the Z axis from the latest update retrieved from the accelerometer.
00306       *
00307       * @return The force measured in the Z axis, in milli-g.
00308       *
00309       * @code
00310       * accelerometer.getZ();
00311       * @endcode
00312       */
00313     int getZ(MicroBitCoordinateSystem system = SIMPLE_CARTESIAN);
00314 
00315     /**
00316       * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
00317       *
00318       * @return The pitch of the device, in degrees.
00319       *
00320       * @code
00321       * accelerometer.getPitch();
00322       * @endcode
00323       */
00324     int getPitch();
00325 
00326     /**
00327       * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
00328       *
00329       * @return The pitch of the device, in radians.
00330       *
00331       * @code
00332       * accelerometer.getPitchRadians();
00333       * @endcode
00334       */
00335     float getPitchRadians();
00336 
00337     /**
00338       * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
00339       *
00340       * @return The roll of the device, in degrees.
00341       *
00342       * @code
00343       * accelerometer.getRoll();
00344       * @endcode
00345       */
00346     int getRoll();
00347 
00348     /**
00349       * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
00350       *
00351       * @return The roll of the device, in radians.
00352       *
00353       * @code
00354       * accelerometer.getRollRadians();
00355       * @endcode
00356       */
00357     float getRollRadians();
00358 
00359     /**
00360       * Retrieves the last recorded gesture.
00361       *
00362       * @return The last gesture that was detected.
00363       *
00364       * Example:
00365       * @code
00366       * MicroBitDisplay display;
00367       *
00368       * if (accelerometer.getGesture() == SHAKE)
00369       *     display.scroll("SHAKE!");
00370       * @endcode
00371       */
00372     uint16_t getGesture();
00373 
00374     /**
00375       * A periodic callback invoked by the fiber scheduler idle thread.
00376       *
00377       * Internally calls updateSample().
00378       */
00379     virtual void idleTick();
00380 
00381     /**
00382       * Destructor for MicroBitButton, where we deregister this instance from the array of fiber components.
00383       */
00384     ~MicroBitAccelerometer();
00385 
00386     private:
00387 
00388     /**
00389       * Issues a standard, 2 byte I2C command write to the accelerometer.
00390       *
00391       * Blocks the calling thread until complete.
00392       *
00393       * @param reg The address of the register to write to.
00394       *
00395       * @param value The value to write.
00396       *
00397       * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
00398       */
00399     int writeCommand(uint8_t reg, uint8_t value);
00400 
00401     /**
00402       * Issues a read command, copying data into the specified buffer.
00403       *
00404       * Blocks the calling thread until complete.
00405       *
00406       * @param reg The address of the register to access.
00407       *
00408       * @param buffer Memory area to read the data into.
00409       *
00410       * @param length The number of bytes to read.
00411       *
00412       * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
00413       */
00414     int readCommand(uint8_t reg, uint8_t* buffer, int length);
00415 
00416     /**
00417       * Recalculate roll and pitch values for the current sample.
00418       *
00419       * @note We only do this at most once per sample, as the necessary trigonemteric functions are rather
00420       *       heavyweight for a CPU without a floating point unit.
00421       */
00422     void recalculatePitchRoll();
00423 
00424     /**
00425       * Updates the basic gesture recognizer. This performs instantaneous pose recognition, and also some low pass filtering to promote
00426       * stability.
00427       */
00428     void updateGesture();
00429 
00430     /**
00431       * A service function.
00432       * It calculates the current scalar acceleration of the device (x^2 + y^2 + z^2).
00433       * It does not, however, square root the result, as this is a relatively high cost operation.
00434       *
00435       * This is left to application code should it be needed.
00436       *
00437       * @return the sum of the square of the acceleration of the device across all axes.
00438       */
00439     int instantaneousAccelerationSquared();
00440 
00441     /**
00442      * Service function.
00443      * Determines a 'best guess' posture of the device based on instantaneous data.
00444      *
00445      * This makes no use of historic data, and forms this input to the filter implemented in updateGesture().
00446      *
00447      * @return A 'best guess' of the current posture of the device, based on instanataneous data.
00448      */
00449     uint16_t instantaneousPosture();
00450 };
00451 
00452 #endif