Revised to disable BLE for radio communication as needed.

Dependencies:   BLE_API nRF51822 mbed-dev-bin

Dependents:   microbit

Committer:
tsfarber
Date:
Tue Nov 26 04:12:46 2019 +0000
Revision:
74:26717338739d
Parent:
65:f7ebabf23e15
This program combines samples programs radio TX and radio RX so that both units can send or receive depending on which unit's buttons are pressed. Tested successfully. MicroBitConfig.h has been edited to disable BLE.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 1:8aa5cdb4ab67 1 /*
Jonathan Austin 1:8aa5cdb4ab67 2 The MIT License (MIT)
Jonathan Austin 1:8aa5cdb4ab67 3
Jonathan Austin 1:8aa5cdb4ab67 4 Copyright (c) 2016 British Broadcasting Corporation.
Jonathan Austin 1:8aa5cdb4ab67 5 This software is provided by Lancaster University by arrangement with the BBC.
Jonathan Austin 1:8aa5cdb4ab67 6
Jonathan Austin 1:8aa5cdb4ab67 7 Permission is hereby granted, free of charge, to any person obtaining a
Jonathan Austin 1:8aa5cdb4ab67 8 copy of this software and associated documentation files (the "Software"),
Jonathan Austin 1:8aa5cdb4ab67 9 to deal in the Software without restriction, including without limitation
Jonathan Austin 1:8aa5cdb4ab67 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
Jonathan Austin 1:8aa5cdb4ab67 11 and/or sell copies of the Software, and to permit persons to whom the
Jonathan Austin 1:8aa5cdb4ab67 12 Software is furnished to do so, subject to the following conditions:
Jonathan Austin 1:8aa5cdb4ab67 13
Jonathan Austin 1:8aa5cdb4ab67 14 The above copyright notice and this permission notice shall be included in
Jonathan Austin 1:8aa5cdb4ab67 15 all copies or substantial portions of the Software.
Jonathan Austin 1:8aa5cdb4ab67 16
Jonathan Austin 1:8aa5cdb4ab67 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jonathan Austin 1:8aa5cdb4ab67 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jonathan Austin 1:8aa5cdb4ab67 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Jonathan Austin 1:8aa5cdb4ab67 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jonathan Austin 1:8aa5cdb4ab67 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 23 DEALINGS IN THE SOFTWARE.
Jonathan Austin 1:8aa5cdb4ab67 24 */
Jonathan Austin 1:8aa5cdb4ab67 25
Jonathan Austin 1:8aa5cdb4ab67 26 /**
Jonathan Austin 1:8aa5cdb4ab67 27 * Class definition for MicroBit Accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 28 *
Jonathan Austin 1:8aa5cdb4ab67 29 * Represents an implementation of the Freescale MMA8653 3 axis accelerometer
Jonathan Austin 1:8aa5cdb4ab67 30 * Also includes basic data caching and on demand activation.
Jonathan Austin 1:8aa5cdb4ab67 31 */
Jonathan Austin 1:8aa5cdb4ab67 32 #include "MicroBitConfig.h"
Jonathan Austin 1:8aa5cdb4ab67 33 #include "MicroBitAccelerometer.h"
Jonathan Austin 1:8aa5cdb4ab67 34 #include "ErrorNo.h"
Jonathan Austin 1:8aa5cdb4ab67 35 #include "MicroBitConfig.h"
Jonathan Austin 1:8aa5cdb4ab67 36 #include "MicroBitEvent.h"
Jonathan Austin 1:8aa5cdb4ab67 37 #include "MicroBitCompat.h"
Jonathan Austin 1:8aa5cdb4ab67 38 #include "MicroBitFiber.h"
Jonathan Austin 1:8aa5cdb4ab67 39
Jonathan Austin 1:8aa5cdb4ab67 40 /**
Jonathan Austin 1:8aa5cdb4ab67 41 * Configures the accelerometer for G range and sample rate defined
Jonathan Austin 1:8aa5cdb4ab67 42 * in this object. The nearest values are chosen to those defined
Jonathan Austin 1:8aa5cdb4ab67 43 * that are supported by the hardware. The instance variables are then
Jonathan Austin 1:8aa5cdb4ab67 44 * updated to reflect reality.
Jonathan Austin 1:8aa5cdb4ab67 45 *
Jonathan Austin 1:8aa5cdb4ab67 46 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the accelerometer could not be configured.
Jonathan Austin 1:8aa5cdb4ab67 47 */
Jonathan Austin 1:8aa5cdb4ab67 48 int MicroBitAccelerometer::configure()
Jonathan Austin 1:8aa5cdb4ab67 49 {
Jonathan Austin 1:8aa5cdb4ab67 50 const MMA8653SampleRangeConfig *actualSampleRange;
Jonathan Austin 1:8aa5cdb4ab67 51 const MMA8653SampleRateConfig *actualSampleRate;
Jonathan Austin 1:8aa5cdb4ab67 52 int result;
Jonathan Austin 1:8aa5cdb4ab67 53
Jonathan Austin 1:8aa5cdb4ab67 54 // First find the nearest sample rate to that specified.
Jonathan Austin 1:8aa5cdb4ab67 55 actualSampleRate = &MMA8653SampleRate[MMA8653_SAMPLE_RATES-1];
Jonathan Austin 1:8aa5cdb4ab67 56 for (int i=MMA8653_SAMPLE_RATES-1; i>=0; i--)
Jonathan Austin 1:8aa5cdb4ab67 57 {
Jonathan Austin 1:8aa5cdb4ab67 58 if(MMA8653SampleRate[i].sample_period < this->samplePeriod * 1000)
Jonathan Austin 1:8aa5cdb4ab67 59 break;
Jonathan Austin 1:8aa5cdb4ab67 60
Jonathan Austin 1:8aa5cdb4ab67 61 actualSampleRate = &MMA8653SampleRate[i];
Jonathan Austin 1:8aa5cdb4ab67 62 }
Jonathan Austin 1:8aa5cdb4ab67 63
Jonathan Austin 1:8aa5cdb4ab67 64 // Now find the nearest sample range to that specified.
Jonathan Austin 1:8aa5cdb4ab67 65 actualSampleRange = &MMA8653SampleRange[MMA8653_SAMPLE_RANGES-1];
Jonathan Austin 1:8aa5cdb4ab67 66 for (int i=MMA8653_SAMPLE_RANGES-1; i>=0; i--)
Jonathan Austin 1:8aa5cdb4ab67 67 {
Jonathan Austin 1:8aa5cdb4ab67 68 if(MMA8653SampleRange[i].sample_range < this->sampleRange)
Jonathan Austin 1:8aa5cdb4ab67 69 break;
Jonathan Austin 1:8aa5cdb4ab67 70
Jonathan Austin 1:8aa5cdb4ab67 71 actualSampleRange = &MMA8653SampleRange[i];
Jonathan Austin 1:8aa5cdb4ab67 72 }
Jonathan Austin 1:8aa5cdb4ab67 73
Jonathan Austin 1:8aa5cdb4ab67 74 // OK, we have the correct data. Update our local state.
Jonathan Austin 1:8aa5cdb4ab67 75 this->samplePeriod = actualSampleRate->sample_period / 1000;
Jonathan Austin 1:8aa5cdb4ab67 76 this->sampleRange = actualSampleRange->sample_range;
Jonathan Austin 1:8aa5cdb4ab67 77
Jonathan Austin 1:8aa5cdb4ab67 78 // Now configure the accelerometer accordingly.
Jonathan Austin 1:8aa5cdb4ab67 79 // First place the device into standby mode, so it can be configured.
Jonathan Austin 1:8aa5cdb4ab67 80 result = writeCommand(MMA8653_CTRL_REG1, 0x00);
Jonathan Austin 1:8aa5cdb4ab67 81 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 82 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 83
Jonathan Austin 1:8aa5cdb4ab67 84 // Enable high precisiosn mode. This consumes a bit more power, but still only 184 uA!
Jonathan Austin 1:8aa5cdb4ab67 85 result = writeCommand(MMA8653_CTRL_REG2, 0x10);
Jonathan Austin 1:8aa5cdb4ab67 86 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 87 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 88
Jonathan Austin 1:8aa5cdb4ab67 89 // Enable the INT1 interrupt pin.
Jonathan Austin 1:8aa5cdb4ab67 90 result = writeCommand(MMA8653_CTRL_REG4, 0x01);
Jonathan Austin 1:8aa5cdb4ab67 91 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 92 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 93
Jonathan Austin 1:8aa5cdb4ab67 94 // Select the DATA_READY event source to be routed to INT1
Jonathan Austin 1:8aa5cdb4ab67 95 result = writeCommand(MMA8653_CTRL_REG5, 0x01);
Jonathan Austin 1:8aa5cdb4ab67 96 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 97 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 98
Jonathan Austin 1:8aa5cdb4ab67 99 // Configure for the selected g range.
Jonathan Austin 1:8aa5cdb4ab67 100 result = writeCommand(MMA8653_XYZ_DATA_CFG, actualSampleRange->xyz_data_cfg);
Jonathan Austin 1:8aa5cdb4ab67 101 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 102 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 103
Jonathan Austin 1:8aa5cdb4ab67 104 // Bring the device back online, with 10bit wide samples at the requested frequency.
Jonathan Austin 1:8aa5cdb4ab67 105 result = writeCommand(MMA8653_CTRL_REG1, actualSampleRate->ctrl_reg1 | 0x01);
Jonathan Austin 1:8aa5cdb4ab67 106 if (result != 0)
Jonathan Austin 1:8aa5cdb4ab67 107 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 108
Jonathan Austin 1:8aa5cdb4ab67 109 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 110 }
Jonathan Austin 1:8aa5cdb4ab67 111
Jonathan Austin 1:8aa5cdb4ab67 112 /**
Jonathan Austin 1:8aa5cdb4ab67 113 * Issues a standard, 2 byte I2C command write to the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 114 *
Jonathan Austin 1:8aa5cdb4ab67 115 * Blocks the calling thread until complete.
Jonathan Austin 1:8aa5cdb4ab67 116 *
Jonathan Austin 1:8aa5cdb4ab67 117 * @param reg The address of the register to write to.
Jonathan Austin 1:8aa5cdb4ab67 118 *
Jonathan Austin 1:8aa5cdb4ab67 119 * @param value The value to write.
Jonathan Austin 1:8aa5cdb4ab67 120 *
Jonathan Austin 1:8aa5cdb4ab67 121 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the the write request failed.
Jonathan Austin 1:8aa5cdb4ab67 122 */
Jonathan Austin 1:8aa5cdb4ab67 123 int MicroBitAccelerometer::writeCommand(uint8_t reg, uint8_t value)
Jonathan Austin 1:8aa5cdb4ab67 124 {
Jonathan Austin 1:8aa5cdb4ab67 125 uint8_t command[2];
Jonathan Austin 1:8aa5cdb4ab67 126 command[0] = reg;
Jonathan Austin 1:8aa5cdb4ab67 127 command[1] = value;
Jonathan Austin 1:8aa5cdb4ab67 128
Jonathan Austin 1:8aa5cdb4ab67 129 return i2c.write(address, (const char *)command, 2);
Jonathan Austin 1:8aa5cdb4ab67 130 }
Jonathan Austin 1:8aa5cdb4ab67 131
Jonathan Austin 1:8aa5cdb4ab67 132 /**
Jonathan Austin 1:8aa5cdb4ab67 133 * Issues a read command, copying data into the specified buffer.
Jonathan Austin 1:8aa5cdb4ab67 134 *
Jonathan Austin 1:8aa5cdb4ab67 135 * Blocks the calling thread until complete.
Jonathan Austin 1:8aa5cdb4ab67 136 *
Jonathan Austin 1:8aa5cdb4ab67 137 * @param reg The address of the register to access.
Jonathan Austin 1:8aa5cdb4ab67 138 *
Jonathan Austin 1:8aa5cdb4ab67 139 * @param buffer Memory area to read the data into.
Jonathan Austin 1:8aa5cdb4ab67 140 *
Jonathan Austin 1:8aa5cdb4ab67 141 * @param length The number of bytes to read.
Jonathan Austin 1:8aa5cdb4ab67 142 *
Jonathan Austin 1:8aa5cdb4ab67 143 * @return MICROBIT_OK on success, MICROBIT_INVALID_PARAMETER or MICROBIT_I2C_ERROR if the the read request failed.
Jonathan Austin 1:8aa5cdb4ab67 144 */
Jonathan Austin 1:8aa5cdb4ab67 145 int MicroBitAccelerometer::readCommand(uint8_t reg, uint8_t* buffer, int length)
Jonathan Austin 1:8aa5cdb4ab67 146 {
Jonathan Austin 1:8aa5cdb4ab67 147 int result;
Jonathan Austin 1:8aa5cdb4ab67 148
Jonathan Austin 1:8aa5cdb4ab67 149 if (buffer == NULL || length <= 0 )
Jonathan Austin 1:8aa5cdb4ab67 150 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 151
Jonathan Austin 1:8aa5cdb4ab67 152 result = i2c.write(address, (const char *)&reg, 1, true);
Jonathan Austin 1:8aa5cdb4ab67 153 if (result !=0)
Jonathan Austin 1:8aa5cdb4ab67 154 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 155
Jonathan Austin 1:8aa5cdb4ab67 156 result = i2c.read(address, (char *)buffer, length);
Jonathan Austin 1:8aa5cdb4ab67 157 if (result !=0)
Jonathan Austin 1:8aa5cdb4ab67 158 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 159
Jonathan Austin 1:8aa5cdb4ab67 160 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 161 }
Jonathan Austin 1:8aa5cdb4ab67 162
Jonathan Austin 1:8aa5cdb4ab67 163 /**
Jonathan Austin 1:8aa5cdb4ab67 164 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 165 * Create a software abstraction of an accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 166 *
Jonathan Austin 1:8aa5cdb4ab67 167 * @param _i2c an instance of MicroBitI2C used to communicate with the onboard accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 168 *
Jonathan Austin 1:8aa5cdb4ab67 169 * @param address the default I2C address of the accelerometer. Defaults to: MMA8653_DEFAULT_ADDR.
Jonathan Austin 1:8aa5cdb4ab67 170 *
Jonathan Austin 1:8aa5cdb4ab67 171 * @param id the unique EventModel id of this component. Defaults to: MICROBIT_ID_ACCELEROMETER
Jonathan Austin 1:8aa5cdb4ab67 172 *
Jonathan Austin 1:8aa5cdb4ab67 173 * @code
Jonathan Austin 1:8aa5cdb4ab67 174 * MicroBitI2C i2c = MicroBitI2C(I2C_SDA0, I2C_SCL0);
Jonathan Austin 1:8aa5cdb4ab67 175 *
Jonathan Austin 1:8aa5cdb4ab67 176 * MicroBitAccelerometer accelerometer = MicroBitAccelerometer(i2c);
Jonathan Austin 1:8aa5cdb4ab67 177 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 178 */
Jonathan Austin 1:8aa5cdb4ab67 179 MicroBitAccelerometer::MicroBitAccelerometer(MicroBitI2C& _i2c, uint16_t address, uint16_t id) : sample(), int1(MICROBIT_PIN_ACCEL_DATA_READY), i2c(_i2c)
Jonathan Austin 1:8aa5cdb4ab67 180 {
Jonathan Austin 1:8aa5cdb4ab67 181 // Store our identifiers.
Jonathan Austin 1:8aa5cdb4ab67 182 this->id = id;
Jonathan Austin 1:8aa5cdb4ab67 183 this->status = 0;
Jonathan Austin 1:8aa5cdb4ab67 184 this->address = address;
Jonathan Austin 1:8aa5cdb4ab67 185
Jonathan Austin 1:8aa5cdb4ab67 186 // Update our internal state for 50Hz at +/- 2g (50Hz has a period af 20ms).
Jonathan Austin 1:8aa5cdb4ab67 187 this->samplePeriod = 20;
Jonathan Austin 1:8aa5cdb4ab67 188 this->sampleRange = 2;
Jonathan Austin 1:8aa5cdb4ab67 189
Jonathan Austin 1:8aa5cdb4ab67 190 // Initialise gesture history
Jonathan Austin 1:8aa5cdb4ab67 191 this->sigma = 0;
LancasterUniversity 38:1a9e8e5e23f2 192 this->impulseSigma = 0;
LancasterUniversity 39:112df23f039f 193 this->lastGesture = MICROBIT_ACCELEROMETER_EVT_NONE;
LancasterUniversity 39:112df23f039f 194 this->currentGesture = MICROBIT_ACCELEROMETER_EVT_NONE;
Jonathan Austin 1:8aa5cdb4ab67 195 this->shake.x = 0;
Jonathan Austin 1:8aa5cdb4ab67 196 this->shake.y = 0;
Jonathan Austin 1:8aa5cdb4ab67 197 this->shake.z = 0;
Jonathan Austin 1:8aa5cdb4ab67 198 this->shake.count = 0;
Jonathan Austin 1:8aa5cdb4ab67 199 this->shake.timer = 0;
LancasterUniversity 38:1a9e8e5e23f2 200 this->shake.impulse_3 = 1;
LancasterUniversity 38:1a9e8e5e23f2 201 this->shake.impulse_6 = 1;
LancasterUniversity 38:1a9e8e5e23f2 202 this->shake.impulse_8 = 1;
Jonathan Austin 1:8aa5cdb4ab67 203
Jonathan Austin 1:8aa5cdb4ab67 204 // Configure and enable the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 205 if (this->configure() == MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 206 status |= MICROBIT_COMPONENT_RUNNING;
Jonathan Austin 1:8aa5cdb4ab67 207 }
Jonathan Austin 1:8aa5cdb4ab67 208
Jonathan Austin 1:8aa5cdb4ab67 209 /**
Jonathan Austin 1:8aa5cdb4ab67 210 * Attempts to read the 8 bit ID from the accelerometer, this can be used for
Jonathan Austin 1:8aa5cdb4ab67 211 * validation purposes.
Jonathan Austin 1:8aa5cdb4ab67 212 *
Jonathan Austin 1:8aa5cdb4ab67 213 * @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails.
Jonathan Austin 1:8aa5cdb4ab67 214 *
Jonathan Austin 1:8aa5cdb4ab67 215 * @code
Jonathan Austin 1:8aa5cdb4ab67 216 * accelerometer.whoAmI();
Jonathan Austin 1:8aa5cdb4ab67 217 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 218 */
Jonathan Austin 1:8aa5cdb4ab67 219 int MicroBitAccelerometer::whoAmI()
Jonathan Austin 1:8aa5cdb4ab67 220 {
Jonathan Austin 1:8aa5cdb4ab67 221 uint8_t data;
Jonathan Austin 1:8aa5cdb4ab67 222 int result;
Jonathan Austin 1:8aa5cdb4ab67 223
Jonathan Austin 1:8aa5cdb4ab67 224 result = readCommand(MMA8653_WHOAMI, &data, 1);
Jonathan Austin 1:8aa5cdb4ab67 225 if (result !=0)
Jonathan Austin 1:8aa5cdb4ab67 226 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 227
Jonathan Austin 1:8aa5cdb4ab67 228 return (int)data;
Jonathan Austin 1:8aa5cdb4ab67 229 }
Jonathan Austin 1:8aa5cdb4ab67 230
Jonathan Austin 1:8aa5cdb4ab67 231 /**
Jonathan Austin 1:8aa5cdb4ab67 232 * Reads the acceleration data from the accelerometer, and stores it in our buffer.
Jonathan Austin 1:8aa5cdb4ab67 233 * This only happens if the accelerometer indicates that it has new data via int1.
Jonathan Austin 1:8aa5cdb4ab67 234 *
Jonathan Austin 1:8aa5cdb4ab67 235 * On first use, this member function will attempt to add this component to the
Jonathan Austin 1:8aa5cdb4ab67 236 * list of fiber components in order to constantly update the values stored
Jonathan Austin 1:8aa5cdb4ab67 237 * by this object.
Jonathan Austin 1:8aa5cdb4ab67 238 *
Jonathan Austin 1:8aa5cdb4ab67 239 * This technique is called lazy instantiation, and it means that we do not
Jonathan Austin 1:8aa5cdb4ab67 240 * obtain the overhead from non-chalantly adding this component to fiber components.
Jonathan Austin 1:8aa5cdb4ab67 241 *
Jonathan Austin 1:8aa5cdb4ab67 242 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the read request fails.
Jonathan Austin 1:8aa5cdb4ab67 243 */
Jonathan Austin 1:8aa5cdb4ab67 244 int MicroBitAccelerometer::updateSample()
Jonathan Austin 1:8aa5cdb4ab67 245 {
Jonathan Austin 1:8aa5cdb4ab67 246 if(!(status & MICROBIT_ACCEL_ADDED_TO_IDLE))
Jonathan Austin 1:8aa5cdb4ab67 247 {
Jonathan Austin 1:8aa5cdb4ab67 248 fiber_add_idle_component(this);
Jonathan Austin 1:8aa5cdb4ab67 249 status |= MICROBIT_ACCEL_ADDED_TO_IDLE;
Jonathan Austin 1:8aa5cdb4ab67 250 }
Jonathan Austin 1:8aa5cdb4ab67 251
Jonathan Austin 1:8aa5cdb4ab67 252 // Poll interrupt line from accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 253 // n.b. Default is Active LO. Interrupt is cleared in data read.
Jonathan Austin 1:8aa5cdb4ab67 254 if(!int1)
Jonathan Austin 1:8aa5cdb4ab67 255 {
Jonathan Austin 1:8aa5cdb4ab67 256 int8_t data[6];
Jonathan Austin 1:8aa5cdb4ab67 257 int result;
Jonathan Austin 1:8aa5cdb4ab67 258
Jonathan Austin 1:8aa5cdb4ab67 259 result = readCommand(MMA8653_OUT_X_MSB, (uint8_t *)data, 6);
Jonathan Austin 1:8aa5cdb4ab67 260 if (result !=0)
Jonathan Austin 1:8aa5cdb4ab67 261 return MICROBIT_I2C_ERROR;
Jonathan Austin 1:8aa5cdb4ab67 262
Jonathan Austin 1:8aa5cdb4ab67 263 // read MSB values...
Jonathan Austin 1:8aa5cdb4ab67 264 sample.x = data[0];
Jonathan Austin 1:8aa5cdb4ab67 265 sample.y = data[2];
Jonathan Austin 1:8aa5cdb4ab67 266 sample.z = data[4];
Jonathan Austin 1:8aa5cdb4ab67 267
Jonathan Austin 1:8aa5cdb4ab67 268 // Normalize the data in the 0..1024 range.
Jonathan Austin 1:8aa5cdb4ab67 269 sample.x *= 8;
Jonathan Austin 1:8aa5cdb4ab67 270 sample.y *= 8;
Jonathan Austin 1:8aa5cdb4ab67 271 sample.z *= 8;
Jonathan Austin 1:8aa5cdb4ab67 272
Jonathan Austin 1:8aa5cdb4ab67 273 #if CONFIG_ENABLED(USE_ACCEL_LSB)
Jonathan Austin 1:8aa5cdb4ab67 274 // Add in LSB values.
Jonathan Austin 1:8aa5cdb4ab67 275 sample.x += (data[1] / 64);
Jonathan Austin 1:8aa5cdb4ab67 276 sample.y += (data[3] / 64);
Jonathan Austin 1:8aa5cdb4ab67 277 sample.z += (data[5] / 64);
Jonathan Austin 1:8aa5cdb4ab67 278 #endif
Jonathan Austin 1:8aa5cdb4ab67 279
Jonathan Austin 1:8aa5cdb4ab67 280 // Scale into millig (approx!)
Jonathan Austin 1:8aa5cdb4ab67 281 sample.x *= this->sampleRange;
Jonathan Austin 1:8aa5cdb4ab67 282 sample.y *= this->sampleRange;
Jonathan Austin 1:8aa5cdb4ab67 283 sample.z *= this->sampleRange;
Jonathan Austin 1:8aa5cdb4ab67 284
Jonathan Austin 1:8aa5cdb4ab67 285 // Indicate that pitch and roll data is now stale, and needs to be recalculated if needed.
Jonathan Austin 1:8aa5cdb4ab67 286 status &= ~MICROBIT_ACCEL_PITCH_ROLL_VALID;
Jonathan Austin 1:8aa5cdb4ab67 287
Jonathan Austin 1:8aa5cdb4ab67 288 // Update gesture tracking
Jonathan Austin 1:8aa5cdb4ab67 289 updateGesture();
Jonathan Austin 1:8aa5cdb4ab67 290
Jonathan Austin 1:8aa5cdb4ab67 291 // Indicate that a new sample is available
Jonathan Austin 1:8aa5cdb4ab67 292 MicroBitEvent e(id, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE);
Jonathan Austin 1:8aa5cdb4ab67 293 }
Jonathan Austin 1:8aa5cdb4ab67 294
Jonathan Austin 1:8aa5cdb4ab67 295 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 296 };
Jonathan Austin 1:8aa5cdb4ab67 297
Jonathan Austin 1:8aa5cdb4ab67 298 /**
Jonathan Austin 1:8aa5cdb4ab67 299 * A service function.
Jonathan Austin 1:8aa5cdb4ab67 300 * It calculates the current scalar acceleration of the device (x^2 + y^2 + z^2).
Jonathan Austin 1:8aa5cdb4ab67 301 * It does not, however, square root the result, as this is a relatively high cost operation.
Jonathan Austin 1:8aa5cdb4ab67 302 *
Jonathan Austin 1:8aa5cdb4ab67 303 * This is left to application code should it be needed.
Jonathan Austin 1:8aa5cdb4ab67 304 *
Jonathan Austin 1:8aa5cdb4ab67 305 * @return the sum of the square of the acceleration of the device across all axes.
Jonathan Austin 1:8aa5cdb4ab67 306 */
Jonathan Austin 1:8aa5cdb4ab67 307 int MicroBitAccelerometer::instantaneousAccelerationSquared()
Jonathan Austin 1:8aa5cdb4ab67 308 {
Jonathan Austin 1:8aa5cdb4ab67 309 updateSample();
Jonathan Austin 1:8aa5cdb4ab67 310
Jonathan Austin 1:8aa5cdb4ab67 311 // Use pythagoras theorem to determine the combined force acting on the device.
Jonathan Austin 1:8aa5cdb4ab67 312 return (int)sample.x*(int)sample.x + (int)sample.y*(int)sample.y + (int)sample.z*(int)sample.z;
Jonathan Austin 1:8aa5cdb4ab67 313 }
Jonathan Austin 1:8aa5cdb4ab67 314
Jonathan Austin 1:8aa5cdb4ab67 315 /**
Jonathan Austin 1:8aa5cdb4ab67 316 * Service function.
Jonathan Austin 1:8aa5cdb4ab67 317 * Determines a 'best guess' posture of the device based on instantaneous data.
Jonathan Austin 1:8aa5cdb4ab67 318 *
LancasterUniversity 37:b624ae5e94a5 319 * This makes no use of historic data, and forms the input to the filter implemented in updateGesture().
Jonathan Austin 1:8aa5cdb4ab67 320 *
Jonathan Austin 1:8aa5cdb4ab67 321 * @return A 'best guess' of the current posture of the device, based on instanataneous data.
Jonathan Austin 1:8aa5cdb4ab67 322 */
LancasterUniversity 39:112df23f039f 323 uint16_t MicroBitAccelerometer::instantaneousPosture()
Jonathan Austin 1:8aa5cdb4ab67 324 {
Jonathan Austin 1:8aa5cdb4ab67 325 bool shakeDetected = false;
Jonathan Austin 1:8aa5cdb4ab67 326
Jonathan Austin 1:8aa5cdb4ab67 327 // Test for shake events.
Jonathan Austin 1:8aa5cdb4ab67 328 // We detect a shake by measuring zero crossings in each axis. In other words, if we see a strong acceleration to the left followed by
LancasterUniversity 37:b624ae5e94a5 329 // a strong acceleration to the right, then we can infer a shake. Similarly, we can do this for each axis (left/right, up/down, in/out).
Jonathan Austin 1:8aa5cdb4ab67 330 //
Jonathan Austin 1:8aa5cdb4ab67 331 // If we see enough zero crossings in succession (MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD), then we decide that the device
Jonathan Austin 1:8aa5cdb4ab67 332 // has been shaken.
Jonathan Austin 1:8aa5cdb4ab67 333 if ((getX() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.x) || (getX() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.x))
Jonathan Austin 1:8aa5cdb4ab67 334 {
Jonathan Austin 1:8aa5cdb4ab67 335 shakeDetected = true;
Jonathan Austin 1:8aa5cdb4ab67 336 shake.x = !shake.x;
Jonathan Austin 1:8aa5cdb4ab67 337 }
Jonathan Austin 1:8aa5cdb4ab67 338
Jonathan Austin 1:8aa5cdb4ab67 339 if ((getY() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.y) || (getY() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.y))
Jonathan Austin 1:8aa5cdb4ab67 340 {
Jonathan Austin 1:8aa5cdb4ab67 341 shakeDetected = true;
Jonathan Austin 1:8aa5cdb4ab67 342 shake.y = !shake.y;
Jonathan Austin 1:8aa5cdb4ab67 343 }
Jonathan Austin 1:8aa5cdb4ab67 344
Jonathan Austin 1:8aa5cdb4ab67 345 if ((getZ() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.z) || (getZ() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.z))
Jonathan Austin 1:8aa5cdb4ab67 346 {
Jonathan Austin 1:8aa5cdb4ab67 347 shakeDetected = true;
Jonathan Austin 1:8aa5cdb4ab67 348 shake.z = !shake.z;
Jonathan Austin 1:8aa5cdb4ab67 349 }
Jonathan Austin 1:8aa5cdb4ab67 350
LancasterUniversity 65:f7ebabf23e15 351 // If we detected a zero crossing in this sample period, count this.
LancasterUniversity 65:f7ebabf23e15 352 if (shakeDetected && shake.count < MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD)
LancasterUniversity 55:6920de8ba10a 353 {
LancasterUniversity 65:f7ebabf23e15 354 shake.count++;
LancasterUniversity 65:f7ebabf23e15 355
LancasterUniversity 65:f7ebabf23e15 356 if (shake.count == 1)
LancasterUniversity 65:f7ebabf23e15 357 shake.timer = 0;
LancasterUniversity 65:f7ebabf23e15 358
LancasterUniversity 65:f7ebabf23e15 359 if (shake.count == MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD)
Jonathan Austin 1:8aa5cdb4ab67 360 {
LancasterUniversity 65:f7ebabf23e15 361 shake.shaken = 1;
LancasterUniversity 65:f7ebabf23e15 362 shake.timer = 0;
LancasterUniversity 65:f7ebabf23e15 363 return MICROBIT_ACCELEROMETER_EVT_SHAKE;
Jonathan Austin 1:8aa5cdb4ab67 364 }
Jonathan Austin 1:8aa5cdb4ab67 365 }
Jonathan Austin 1:8aa5cdb4ab67 366
LancasterUniversity 65:f7ebabf23e15 367 // measure how long we have been detecting a SHAKE event.
LancasterUniversity 65:f7ebabf23e15 368 if (shake.count > 0)
LancasterUniversity 65:f7ebabf23e15 369 {
LancasterUniversity 65:f7ebabf23e15 370 shake.timer++;
LancasterUniversity 65:f7ebabf23e15 371
LancasterUniversity 65:f7ebabf23e15 372 // If we've issued a SHAKE event already, and sufficient time has assed, allow another SHAKE event to be issued.
LancasterUniversity 65:f7ebabf23e15 373 if (shake.shaken && shake.timer >= MICROBIT_ACCELEROMETER_SHAKE_RTX)
LancasterUniversity 65:f7ebabf23e15 374 {
LancasterUniversity 65:f7ebabf23e15 375 shake.shaken = 0;
LancasterUniversity 65:f7ebabf23e15 376 shake.timer = 0;
LancasterUniversity 65:f7ebabf23e15 377 shake.count = 0;
LancasterUniversity 65:f7ebabf23e15 378 }
LancasterUniversity 65:f7ebabf23e15 379
LancasterUniversity 65:f7ebabf23e15 380 // Decay our count of zero crossings over time. We don't want them to accumulate if the user performs slow moving motions.
LancasterUniversity 65:f7ebabf23e15 381 else if (!shake.shaken && shake.timer >= MICROBIT_ACCELEROMETER_SHAKE_DAMPING)
LancasterUniversity 65:f7ebabf23e15 382 {
LancasterUniversity 65:f7ebabf23e15 383 shake.timer = 0;
LancasterUniversity 65:f7ebabf23e15 384 if (shake.count > 0)
LancasterUniversity 65:f7ebabf23e15 385 shake.count--;
LancasterUniversity 65:f7ebabf23e15 386 }
LancasterUniversity 65:f7ebabf23e15 387 }
Jonathan Austin 1:8aa5cdb4ab67 388
LancasterUniversity 42:e2869e0fa366 389 if (instantaneousAccelerationSquared() < MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD)
LancasterUniversity 42:e2869e0fa366 390 return MICROBIT_ACCELEROMETER_EVT_FREEFALL;
LancasterUniversity 42:e2869e0fa366 391
Jonathan Austin 1:8aa5cdb4ab67 392 // Determine our posture.
Jonathan Austin 1:8aa5cdb4ab67 393 if (getX() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 394 return MICROBIT_ACCELEROMETER_EVT_TILT_LEFT;
Jonathan Austin 1:8aa5cdb4ab67 395
Jonathan Austin 1:8aa5cdb4ab67 396 if (getX() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 397 return MICROBIT_ACCELEROMETER_EVT_TILT_RIGHT;
Jonathan Austin 1:8aa5cdb4ab67 398
Jonathan Austin 1:8aa5cdb4ab67 399 if (getY() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 400 return MICROBIT_ACCELEROMETER_EVT_TILT_DOWN;
Jonathan Austin 1:8aa5cdb4ab67 401
Jonathan Austin 1:8aa5cdb4ab67 402 if (getY() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 403 return MICROBIT_ACCELEROMETER_EVT_TILT_UP;
Jonathan Austin 1:8aa5cdb4ab67 404
Jonathan Austin 1:8aa5cdb4ab67 405 if (getZ() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 406 return MICROBIT_ACCELEROMETER_EVT_FACE_UP;
Jonathan Austin 1:8aa5cdb4ab67 407
Jonathan Austin 1:8aa5cdb4ab67 408 if (getZ() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE))
LancasterUniversity 39:112df23f039f 409 return MICROBIT_ACCELEROMETER_EVT_FACE_DOWN;
Jonathan Austin 1:8aa5cdb4ab67 410
LancasterUniversity 39:112df23f039f 411 return MICROBIT_ACCELEROMETER_EVT_NONE;
Jonathan Austin 1:8aa5cdb4ab67 412 }
Jonathan Austin 1:8aa5cdb4ab67 413
Jonathan Austin 1:8aa5cdb4ab67 414 /**
Jonathan Austin 1:8aa5cdb4ab67 415 * Updates the basic gesture recognizer. This performs instantaneous pose recognition, and also some low pass filtering to promote
Jonathan Austin 1:8aa5cdb4ab67 416 * stability.
Jonathan Austin 1:8aa5cdb4ab67 417 */
Jonathan Austin 1:8aa5cdb4ab67 418 void MicroBitAccelerometer::updateGesture()
Jonathan Austin 1:8aa5cdb4ab67 419 {
LancasterUniversity 38:1a9e8e5e23f2 420 // Check for High/Low G force events - typically impulses, impacts etc.
LancasterUniversity 38:1a9e8e5e23f2 421 // Again, during such spikes, these event take priority of the posture of the device.
LancasterUniversity 38:1a9e8e5e23f2 422 // For these events, we don't perform any low pass filtering.
LancasterUniversity 38:1a9e8e5e23f2 423 int force = instantaneousAccelerationSquared();
LancasterUniversity 38:1a9e8e5e23f2 424
LancasterUniversity 38:1a9e8e5e23f2 425 if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD)
LancasterUniversity 38:1a9e8e5e23f2 426 {
LancasterUniversity 38:1a9e8e5e23f2 427 if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD && !shake.impulse_3)
LancasterUniversity 38:1a9e8e5e23f2 428 {
LancasterUniversity 39:112df23f039f 429 MicroBitEvent e(MICROBIT_ID_GESTURE, MICROBIT_ACCELEROMETER_EVT_3G);
LancasterUniversity 38:1a9e8e5e23f2 430 shake.impulse_3 = 1;
LancasterUniversity 38:1a9e8e5e23f2 431 }
LancasterUniversity 38:1a9e8e5e23f2 432 if (force > MICROBIT_ACCELEROMETER_6G_THRESHOLD && !shake.impulse_6)
LancasterUniversity 38:1a9e8e5e23f2 433 {
LancasterUniversity 39:112df23f039f 434 MicroBitEvent e(MICROBIT_ID_GESTURE, MICROBIT_ACCELEROMETER_EVT_6G);
LancasterUniversity 38:1a9e8e5e23f2 435 shake.impulse_6 = 1;
LancasterUniversity 38:1a9e8e5e23f2 436 }
LancasterUniversity 38:1a9e8e5e23f2 437 if (force > MICROBIT_ACCELEROMETER_8G_THRESHOLD && !shake.impulse_8)
LancasterUniversity 38:1a9e8e5e23f2 438 {
LancasterUniversity 39:112df23f039f 439 MicroBitEvent e(MICROBIT_ID_GESTURE, MICROBIT_ACCELEROMETER_EVT_8G);
LancasterUniversity 38:1a9e8e5e23f2 440 shake.impulse_8 = 1;
LancasterUniversity 38:1a9e8e5e23f2 441 }
LancasterUniversity 38:1a9e8e5e23f2 442
LancasterUniversity 38:1a9e8e5e23f2 443 impulseSigma = 0;
LancasterUniversity 38:1a9e8e5e23f2 444 }
LancasterUniversity 38:1a9e8e5e23f2 445
LancasterUniversity 38:1a9e8e5e23f2 446 // Reset the impulse event onve the acceleration has subsided.
LancasterUniversity 38:1a9e8e5e23f2 447 if (impulseSigma < MICROBIT_ACCELEROMETER_GESTURE_DAMPING)
LancasterUniversity 38:1a9e8e5e23f2 448 impulseSigma++;
LancasterUniversity 38:1a9e8e5e23f2 449 else
LancasterUniversity 42:e2869e0fa366 450 shake.impulse_3 = shake.impulse_6 = shake.impulse_8 = 0;
LancasterUniversity 38:1a9e8e5e23f2 451
LancasterUniversity 38:1a9e8e5e23f2 452
Jonathan Austin 1:8aa5cdb4ab67 453 // Determine what it looks like we're doing based on the latest sample...
LancasterUniversity 39:112df23f039f 454 uint16_t g = instantaneousPosture();
Jonathan Austin 1:8aa5cdb4ab67 455
LancasterUniversity 65:f7ebabf23e15 456 if (g == MICROBIT_ACCELEROMETER_EVT_SHAKE)
LancasterUniversity 65:f7ebabf23e15 457 {
LancasterUniversity 65:f7ebabf23e15 458 MicroBitEvent e(MICROBIT_ID_GESTURE, MICROBIT_ACCELEROMETER_EVT_SHAKE);
LancasterUniversity 65:f7ebabf23e15 459 return;
LancasterUniversity 65:f7ebabf23e15 460 }
LancasterUniversity 65:f7ebabf23e15 461
Jonathan Austin 1:8aa5cdb4ab67 462 // Perform some low pass filtering to reduce jitter from any detected effects
Jonathan Austin 1:8aa5cdb4ab67 463 if (g == currentGesture)
Jonathan Austin 1:8aa5cdb4ab67 464 {
Jonathan Austin 1:8aa5cdb4ab67 465 if (sigma < MICROBIT_ACCELEROMETER_GESTURE_DAMPING)
Jonathan Austin 1:8aa5cdb4ab67 466 sigma++;
Jonathan Austin 1:8aa5cdb4ab67 467 }
Jonathan Austin 1:8aa5cdb4ab67 468 else
Jonathan Austin 1:8aa5cdb4ab67 469 {
Jonathan Austin 1:8aa5cdb4ab67 470 currentGesture = g;
Jonathan Austin 1:8aa5cdb4ab67 471 sigma = 0;
Jonathan Austin 1:8aa5cdb4ab67 472 }
Jonathan Austin 1:8aa5cdb4ab67 473
Jonathan Austin 1:8aa5cdb4ab67 474 // If we've reached threshold, update our record and raise the relevant event...
Jonathan Austin 1:8aa5cdb4ab67 475 if (currentGesture != lastGesture && sigma >= MICROBIT_ACCELEROMETER_GESTURE_DAMPING)
Jonathan Austin 1:8aa5cdb4ab67 476 {
Jonathan Austin 1:8aa5cdb4ab67 477 lastGesture = currentGesture;
Jonathan Austin 1:8aa5cdb4ab67 478 MicroBitEvent e(MICROBIT_ID_GESTURE, lastGesture);
Jonathan Austin 1:8aa5cdb4ab67 479 }
Jonathan Austin 1:8aa5cdb4ab67 480 }
Jonathan Austin 1:8aa5cdb4ab67 481
Jonathan Austin 1:8aa5cdb4ab67 482 /**
Jonathan Austin 1:8aa5cdb4ab67 483 * Attempts to set the sample rate of the accelerometer to the specified value (in ms).
Jonathan Austin 1:8aa5cdb4ab67 484 *
Jonathan Austin 1:8aa5cdb4ab67 485 * @param period the requested time between samples, in milliseconds.
Jonathan Austin 1:8aa5cdb4ab67 486 *
Jonathan Austin 1:8aa5cdb4ab67 487 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
Jonathan Austin 1:8aa5cdb4ab67 488 *
Jonathan Austin 1:8aa5cdb4ab67 489 * @code
Jonathan Austin 1:8aa5cdb4ab67 490 * // sample rate is now 20 ms.
Jonathan Austin 1:8aa5cdb4ab67 491 * accelerometer.setPeriod(20);
Jonathan Austin 1:8aa5cdb4ab67 492 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 493 *
Jonathan Austin 1:8aa5cdb4ab67 494 * @note The requested rate may not be possible on the hardware. In this case, the
Jonathan Austin 1:8aa5cdb4ab67 495 * nearest lower rate is chosen.
Jonathan Austin 1:8aa5cdb4ab67 496 */
Jonathan Austin 1:8aa5cdb4ab67 497 int MicroBitAccelerometer::setPeriod(int period)
Jonathan Austin 1:8aa5cdb4ab67 498 {
Jonathan Austin 1:8aa5cdb4ab67 499 this->samplePeriod = period;
Jonathan Austin 1:8aa5cdb4ab67 500 return this->configure();
Jonathan Austin 1:8aa5cdb4ab67 501 }
Jonathan Austin 1:8aa5cdb4ab67 502
Jonathan Austin 1:8aa5cdb4ab67 503 /**
Jonathan Austin 1:8aa5cdb4ab67 504 * Reads the currently configured sample rate of the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 505 *
Jonathan Austin 1:8aa5cdb4ab67 506 * @return The time between samples, in milliseconds.
Jonathan Austin 1:8aa5cdb4ab67 507 */
Jonathan Austin 1:8aa5cdb4ab67 508 int MicroBitAccelerometer::getPeriod()
Jonathan Austin 1:8aa5cdb4ab67 509 {
Jonathan Austin 1:8aa5cdb4ab67 510 return (int)samplePeriod;
Jonathan Austin 1:8aa5cdb4ab67 511 }
Jonathan Austin 1:8aa5cdb4ab67 512
Jonathan Austin 1:8aa5cdb4ab67 513 /**
Jonathan Austin 1:8aa5cdb4ab67 514 * Attempts to set the sample range of the accelerometer to the specified value (in g).
Jonathan Austin 1:8aa5cdb4ab67 515 *
Jonathan Austin 1:8aa5cdb4ab67 516 * @param range The requested sample range of samples, in g.
Jonathan Austin 1:8aa5cdb4ab67 517 *
Jonathan Austin 1:8aa5cdb4ab67 518 * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails.
Jonathan Austin 1:8aa5cdb4ab67 519 *
Jonathan Austin 1:8aa5cdb4ab67 520 * @code
Jonathan Austin 1:8aa5cdb4ab67 521 * // the sample range of the accelerometer is now 8G.
Jonathan Austin 1:8aa5cdb4ab67 522 * accelerometer.setRange(8);
Jonathan Austin 1:8aa5cdb4ab67 523 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 524 *
Jonathan Austin 1:8aa5cdb4ab67 525 * @note The requested range may not be possible on the hardware. In this case, the
Jonathan Austin 1:8aa5cdb4ab67 526 * nearest lower range is chosen.
Jonathan Austin 1:8aa5cdb4ab67 527 */
Jonathan Austin 1:8aa5cdb4ab67 528 int MicroBitAccelerometer::setRange(int range)
Jonathan Austin 1:8aa5cdb4ab67 529 {
Jonathan Austin 1:8aa5cdb4ab67 530 this->sampleRange = range;
Jonathan Austin 1:8aa5cdb4ab67 531 return this->configure();
Jonathan Austin 1:8aa5cdb4ab67 532 }
Jonathan Austin 1:8aa5cdb4ab67 533
Jonathan Austin 1:8aa5cdb4ab67 534 /**
Jonathan Austin 1:8aa5cdb4ab67 535 * Reads the currently configured sample range of the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 536 *
Jonathan Austin 1:8aa5cdb4ab67 537 * @return The sample range, in g.
Jonathan Austin 1:8aa5cdb4ab67 538 */
Jonathan Austin 1:8aa5cdb4ab67 539 int MicroBitAccelerometer::getRange()
Jonathan Austin 1:8aa5cdb4ab67 540 {
Jonathan Austin 1:8aa5cdb4ab67 541 return (int)sampleRange;
Jonathan Austin 1:8aa5cdb4ab67 542 }
Jonathan Austin 1:8aa5cdb4ab67 543
Jonathan Austin 1:8aa5cdb4ab67 544 /**
Jonathan Austin 1:8aa5cdb4ab67 545 * Reads the value of the X axis from the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 546 *
Jonathan Austin 1:8aa5cdb4ab67 547 * @param system The coordinate system to use. By default, a simple cartesian system is provided.
Jonathan Austin 1:8aa5cdb4ab67 548 *
Jonathan Austin 1:8aa5cdb4ab67 549 * @return The force measured in the X axis, in milli-g.
Jonathan Austin 1:8aa5cdb4ab67 550 *
Jonathan Austin 1:8aa5cdb4ab67 551 * @code
Jonathan Austin 1:8aa5cdb4ab67 552 * accelerometer.getX();
Jonathan Austin 1:8aa5cdb4ab67 553 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 554 */
Jonathan Austin 1:8aa5cdb4ab67 555 int MicroBitAccelerometer::getX(MicroBitCoordinateSystem system)
Jonathan Austin 1:8aa5cdb4ab67 556 {
Jonathan Austin 1:8aa5cdb4ab67 557 updateSample();
Jonathan Austin 1:8aa5cdb4ab67 558
Jonathan Austin 1:8aa5cdb4ab67 559 switch (system)
Jonathan Austin 1:8aa5cdb4ab67 560 {
Jonathan Austin 1:8aa5cdb4ab67 561 case SIMPLE_CARTESIAN:
Jonathan Austin 1:8aa5cdb4ab67 562 return -sample.x;
Jonathan Austin 1:8aa5cdb4ab67 563
Jonathan Austin 1:8aa5cdb4ab67 564 case NORTH_EAST_DOWN:
Jonathan Austin 1:8aa5cdb4ab67 565 return sample.y;
Jonathan Austin 1:8aa5cdb4ab67 566
Jonathan Austin 1:8aa5cdb4ab67 567 case RAW:
Jonathan Austin 1:8aa5cdb4ab67 568 default:
Jonathan Austin 1:8aa5cdb4ab67 569 return sample.x;
Jonathan Austin 1:8aa5cdb4ab67 570 }
Jonathan Austin 1:8aa5cdb4ab67 571 }
Jonathan Austin 1:8aa5cdb4ab67 572
Jonathan Austin 1:8aa5cdb4ab67 573 /**
Jonathan Austin 1:8aa5cdb4ab67 574 * Reads the value of the Y axis from the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 575 *
Jonathan Austin 1:8aa5cdb4ab67 576 * @return The force measured in the Y axis, in milli-g.
Jonathan Austin 1:8aa5cdb4ab67 577 *
Jonathan Austin 1:8aa5cdb4ab67 578 * @code
Jonathan Austin 1:8aa5cdb4ab67 579 * accelerometer.getY();
Jonathan Austin 1:8aa5cdb4ab67 580 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 581 */
Jonathan Austin 1:8aa5cdb4ab67 582 int MicroBitAccelerometer::getY(MicroBitCoordinateSystem system)
Jonathan Austin 1:8aa5cdb4ab67 583 {
Jonathan Austin 1:8aa5cdb4ab67 584 updateSample();
Jonathan Austin 1:8aa5cdb4ab67 585
Jonathan Austin 1:8aa5cdb4ab67 586 switch (system)
Jonathan Austin 1:8aa5cdb4ab67 587 {
Jonathan Austin 1:8aa5cdb4ab67 588 case SIMPLE_CARTESIAN:
Jonathan Austin 1:8aa5cdb4ab67 589 return -sample.y;
Jonathan Austin 1:8aa5cdb4ab67 590
Jonathan Austin 1:8aa5cdb4ab67 591 case NORTH_EAST_DOWN:
Jonathan Austin 1:8aa5cdb4ab67 592 return -sample.x;
Jonathan Austin 1:8aa5cdb4ab67 593
Jonathan Austin 1:8aa5cdb4ab67 594 case RAW:
Jonathan Austin 1:8aa5cdb4ab67 595 default:
Jonathan Austin 1:8aa5cdb4ab67 596 return sample.y;
Jonathan Austin 1:8aa5cdb4ab67 597 }
Jonathan Austin 1:8aa5cdb4ab67 598 }
Jonathan Austin 1:8aa5cdb4ab67 599
Jonathan Austin 1:8aa5cdb4ab67 600 /**
Jonathan Austin 1:8aa5cdb4ab67 601 * Reads the value of the Z axis from the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 602 *
Jonathan Austin 1:8aa5cdb4ab67 603 * @return The force measured in the Z axis, in milli-g.
Jonathan Austin 1:8aa5cdb4ab67 604 *
Jonathan Austin 1:8aa5cdb4ab67 605 * @code
Jonathan Austin 1:8aa5cdb4ab67 606 * accelerometer.getZ();
Jonathan Austin 1:8aa5cdb4ab67 607 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 608 */
Jonathan Austin 1:8aa5cdb4ab67 609 int MicroBitAccelerometer::getZ(MicroBitCoordinateSystem system)
Jonathan Austin 1:8aa5cdb4ab67 610 {
Jonathan Austin 1:8aa5cdb4ab67 611 updateSample();
Jonathan Austin 1:8aa5cdb4ab67 612
Jonathan Austin 1:8aa5cdb4ab67 613 switch (system)
Jonathan Austin 1:8aa5cdb4ab67 614 {
Jonathan Austin 1:8aa5cdb4ab67 615 case NORTH_EAST_DOWN:
Jonathan Austin 1:8aa5cdb4ab67 616 return -sample.z;
Jonathan Austin 1:8aa5cdb4ab67 617
Jonathan Austin 1:8aa5cdb4ab67 618 case SIMPLE_CARTESIAN:
Jonathan Austin 1:8aa5cdb4ab67 619 case RAW:
Jonathan Austin 1:8aa5cdb4ab67 620 default:
Jonathan Austin 1:8aa5cdb4ab67 621 return sample.z;
Jonathan Austin 1:8aa5cdb4ab67 622 }
Jonathan Austin 1:8aa5cdb4ab67 623 }
Jonathan Austin 1:8aa5cdb4ab67 624
Jonathan Austin 1:8aa5cdb4ab67 625 /**
Jonathan Austin 1:8aa5cdb4ab67 626 * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 627 *
Jonathan Austin 1:8aa5cdb4ab67 628 * @return The pitch of the device, in degrees.
Jonathan Austin 1:8aa5cdb4ab67 629 *
Jonathan Austin 1:8aa5cdb4ab67 630 * @code
Jonathan Austin 1:8aa5cdb4ab67 631 * accelerometer.getPitch();
Jonathan Austin 1:8aa5cdb4ab67 632 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 633 */
Jonathan Austin 1:8aa5cdb4ab67 634 int MicroBitAccelerometer::getPitch()
Jonathan Austin 1:8aa5cdb4ab67 635 {
Jonathan Austin 1:8aa5cdb4ab67 636 return (int) ((360*getPitchRadians()) / (2*PI));
Jonathan Austin 1:8aa5cdb4ab67 637 }
Jonathan Austin 1:8aa5cdb4ab67 638
Jonathan Austin 1:8aa5cdb4ab67 639 /**
Jonathan Austin 1:8aa5cdb4ab67 640 * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 641 *
Jonathan Austin 1:8aa5cdb4ab67 642 * @return The pitch of the device, in radians.
Jonathan Austin 1:8aa5cdb4ab67 643 *
Jonathan Austin 1:8aa5cdb4ab67 644 * @code
Jonathan Austin 1:8aa5cdb4ab67 645 * accelerometer.getPitchRadians();
Jonathan Austin 1:8aa5cdb4ab67 646 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 647 */
Jonathan Austin 1:8aa5cdb4ab67 648 float MicroBitAccelerometer::getPitchRadians()
Jonathan Austin 1:8aa5cdb4ab67 649 {
Jonathan Austin 1:8aa5cdb4ab67 650 if (!(status & MICROBIT_ACCEL_PITCH_ROLL_VALID))
Jonathan Austin 1:8aa5cdb4ab67 651 recalculatePitchRoll();
Jonathan Austin 1:8aa5cdb4ab67 652
Jonathan Austin 1:8aa5cdb4ab67 653 return pitch;
Jonathan Austin 1:8aa5cdb4ab67 654 }
Jonathan Austin 1:8aa5cdb4ab67 655
Jonathan Austin 1:8aa5cdb4ab67 656 /**
Jonathan Austin 1:8aa5cdb4ab67 657 * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 658 *
Jonathan Austin 1:8aa5cdb4ab67 659 * @return The roll of the device, in degrees.
Jonathan Austin 1:8aa5cdb4ab67 660 *
Jonathan Austin 1:8aa5cdb4ab67 661 * @code
Jonathan Austin 1:8aa5cdb4ab67 662 * accelerometer.getRoll();
Jonathan Austin 1:8aa5cdb4ab67 663 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 664 */
Jonathan Austin 1:8aa5cdb4ab67 665 int MicroBitAccelerometer::getRoll()
Jonathan Austin 1:8aa5cdb4ab67 666 {
Jonathan Austin 1:8aa5cdb4ab67 667 return (int) ((360*getRollRadians()) / (2*PI));
Jonathan Austin 1:8aa5cdb4ab67 668 }
Jonathan Austin 1:8aa5cdb4ab67 669
Jonathan Austin 1:8aa5cdb4ab67 670 /**
Jonathan Austin 1:8aa5cdb4ab67 671 * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer.
Jonathan Austin 1:8aa5cdb4ab67 672 *
Jonathan Austin 1:8aa5cdb4ab67 673 * @return The roll of the device, in radians.
Jonathan Austin 1:8aa5cdb4ab67 674 *
Jonathan Austin 1:8aa5cdb4ab67 675 * @code
Jonathan Austin 1:8aa5cdb4ab67 676 * accelerometer.getRollRadians();
Jonathan Austin 1:8aa5cdb4ab67 677 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 678 */
Jonathan Austin 1:8aa5cdb4ab67 679 float MicroBitAccelerometer::getRollRadians()
Jonathan Austin 1:8aa5cdb4ab67 680 {
Jonathan Austin 1:8aa5cdb4ab67 681 if (!(status & MICROBIT_ACCEL_PITCH_ROLL_VALID))
Jonathan Austin 1:8aa5cdb4ab67 682 recalculatePitchRoll();
Jonathan Austin 1:8aa5cdb4ab67 683
Jonathan Austin 1:8aa5cdb4ab67 684 return roll;
Jonathan Austin 1:8aa5cdb4ab67 685 }
Jonathan Austin 1:8aa5cdb4ab67 686
Jonathan Austin 1:8aa5cdb4ab67 687 /**
Jonathan Austin 1:8aa5cdb4ab67 688 * Recalculate roll and pitch values for the current sample.
Jonathan Austin 1:8aa5cdb4ab67 689 *
Jonathan Austin 1:8aa5cdb4ab67 690 * @note We only do this at most once per sample, as the necessary trigonemteric functions are rather
Jonathan Austin 1:8aa5cdb4ab67 691 * heavyweight for a CPU without a floating point unit.
Jonathan Austin 1:8aa5cdb4ab67 692 */
Jonathan Austin 1:8aa5cdb4ab67 693 void MicroBitAccelerometer::recalculatePitchRoll()
Jonathan Austin 1:8aa5cdb4ab67 694 {
LancasterUniversity 43:0374ea4d2167 695 double x = (double) getX(NORTH_EAST_DOWN);
LancasterUniversity 43:0374ea4d2167 696 double y = (double) getY(NORTH_EAST_DOWN);
LancasterUniversity 43:0374ea4d2167 697 double z = (double) getZ(NORTH_EAST_DOWN);
Jonathan Austin 1:8aa5cdb4ab67 698
LancasterUniversity 43:0374ea4d2167 699 roll = atan2(y, z);
LancasterUniversity 43:0374ea4d2167 700 pitch = atan(-x / (y*sin(roll) + z*cos(roll)));
LancasterUniversity 6:2e1c2e0d8c7a 701
Jonathan Austin 1:8aa5cdb4ab67 702 status |= MICROBIT_ACCEL_PITCH_ROLL_VALID;
Jonathan Austin 1:8aa5cdb4ab67 703 }
Jonathan Austin 1:8aa5cdb4ab67 704
Jonathan Austin 1:8aa5cdb4ab67 705 /**
Jonathan Austin 1:8aa5cdb4ab67 706 * Retrieves the last recorded gesture.
Jonathan Austin 1:8aa5cdb4ab67 707 *
Jonathan Austin 1:8aa5cdb4ab67 708 * @return The last gesture that was detected.
Jonathan Austin 1:8aa5cdb4ab67 709 *
Jonathan Austin 1:8aa5cdb4ab67 710 * Example:
Jonathan Austin 1:8aa5cdb4ab67 711 * @code
Jonathan Austin 1:8aa5cdb4ab67 712 * MicroBitDisplay display;
Jonathan Austin 1:8aa5cdb4ab67 713 *
Jonathan Austin 1:8aa5cdb4ab67 714 * if (accelerometer.getGesture() == SHAKE)
Jonathan Austin 1:8aa5cdb4ab67 715 * display.scroll("SHAKE!");
Jonathan Austin 1:8aa5cdb4ab67 716 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 717 */
LancasterUniversity 39:112df23f039f 718 uint16_t MicroBitAccelerometer::getGesture()
Jonathan Austin 1:8aa5cdb4ab67 719 {
Jonathan Austin 1:8aa5cdb4ab67 720 return lastGesture;
Jonathan Austin 1:8aa5cdb4ab67 721 }
Jonathan Austin 1:8aa5cdb4ab67 722
Jonathan Austin 1:8aa5cdb4ab67 723 /**
Jonathan Austin 1:8aa5cdb4ab67 724 * A periodic callback invoked by the fiber scheduler idle thread.
Jonathan Austin 1:8aa5cdb4ab67 725 *
Jonathan Austin 1:8aa5cdb4ab67 726 * Internally calls updateSample().
Jonathan Austin 1:8aa5cdb4ab67 727 */
Jonathan Austin 1:8aa5cdb4ab67 728 void MicroBitAccelerometer::idleTick()
Jonathan Austin 1:8aa5cdb4ab67 729 {
Jonathan Austin 1:8aa5cdb4ab67 730 updateSample();
Jonathan Austin 1:8aa5cdb4ab67 731 }
Jonathan Austin 1:8aa5cdb4ab67 732
Jonathan Austin 1:8aa5cdb4ab67 733 /**
Jonathan Austin 1:8aa5cdb4ab67 734 * Destructor for MicroBitAccelerometer, where we deregister from the array of fiber components.
Jonathan Austin 1:8aa5cdb4ab67 735 */
Jonathan Austin 1:8aa5cdb4ab67 736 MicroBitAccelerometer::~MicroBitAccelerometer()
Jonathan Austin 1:8aa5cdb4ab67 737 {
Jonathan Austin 1:8aa5cdb4ab67 738 fiber_remove_idle_component(this);
Jonathan Austin 1:8aa5cdb4ab67 739 }
Jonathan Austin 1:8aa5cdb4ab67 740
Jonathan Austin 1:8aa5cdb4ab67 741 const MMA8653SampleRangeConfig MMA8653SampleRange[MMA8653_SAMPLE_RANGES] = {
Jonathan Austin 1:8aa5cdb4ab67 742 {2, 0},
Jonathan Austin 1:8aa5cdb4ab67 743 {4, 1},
Jonathan Austin 1:8aa5cdb4ab67 744 {8, 2}
Jonathan Austin 1:8aa5cdb4ab67 745 };
Jonathan Austin 1:8aa5cdb4ab67 746
Jonathan Austin 1:8aa5cdb4ab67 747 const MMA8653SampleRateConfig MMA8653SampleRate[MMA8653_SAMPLE_RATES] = {
Jonathan Austin 1:8aa5cdb4ab67 748 {1250, 0x00},
Jonathan Austin 1:8aa5cdb4ab67 749 {2500, 0x08},
Jonathan Austin 1:8aa5cdb4ab67 750 {5000, 0x10},
Jonathan Austin 1:8aa5cdb4ab67 751 {10000, 0x18},
Jonathan Austin 1:8aa5cdb4ab67 752 {20000, 0x20},
Jonathan Austin 1:8aa5cdb4ab67 753 {80000, 0x28},
Jonathan Austin 1:8aa5cdb4ab67 754 {160000, 0x30},
Jonathan Austin 1:8aa5cdb4ab67 755 {640000, 0x38}
LancasterUniversity 6:2e1c2e0d8c7a 756 };