fsdfds
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal by
source/drivers/MicroBitAccelerometer.cpp@37:b624ae5e94a5, 2016-07-13 (annotated)
- Committer:
- LancasterUniversity
- Date:
- Wed Jul 13 12:18:16 2016 +0100
- Revision:
- 37:b624ae5e94a5
- Parent:
- 6:2e1c2e0d8c7a
- Child:
- 38:1a9e8e5e23f2
Synchronized with git rev 7443b783
Author: Joe Finney
Fix typos
Who changed what in which revision?
User | Revision | Line number | New 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 *)®, 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; |
Jonathan Austin |
1:8aa5cdb4ab67 | 192 | this->lastGesture = GESTURE_NONE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 193 | this->currentGesture = GESTURE_NONE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 194 | this->shake.x = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 195 | this->shake.y = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 196 | this->shake.z = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 197 | this->shake.count = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 198 | this->shake.timer = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 199 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 200 | // Configure and enable the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 201 | if (this->configure() == MICROBIT_OK) |
Jonathan Austin |
1:8aa5cdb4ab67 | 202 | status |= MICROBIT_COMPONENT_RUNNING; |
Jonathan Austin |
1:8aa5cdb4ab67 | 203 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 204 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 205 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 206 | * Attempts to read the 8 bit ID from the accelerometer, this can be used for |
Jonathan Austin |
1:8aa5cdb4ab67 | 207 | * validation purposes. |
Jonathan Austin |
1:8aa5cdb4ab67 | 208 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 209 | * @return the 8 bit ID returned by the accelerometer, or MICROBIT_I2C_ERROR if the request fails. |
Jonathan Austin |
1:8aa5cdb4ab67 | 210 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 211 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 212 | * accelerometer.whoAmI(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 213 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 214 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 215 | int MicroBitAccelerometer::whoAmI() |
Jonathan Austin |
1:8aa5cdb4ab67 | 216 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 217 | uint8_t data; |
Jonathan Austin |
1:8aa5cdb4ab67 | 218 | int result; |
Jonathan Austin |
1:8aa5cdb4ab67 | 219 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 220 | result = readCommand(MMA8653_WHOAMI, &data, 1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 221 | if (result !=0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 222 | return MICROBIT_I2C_ERROR; |
Jonathan Austin |
1:8aa5cdb4ab67 | 223 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 224 | return (int)data; |
Jonathan Austin |
1:8aa5cdb4ab67 | 225 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 226 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 227 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 228 | * Reads the acceleration data from the accelerometer, and stores it in our buffer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 229 | * This only happens if the accelerometer indicates that it has new data via int1. |
Jonathan Austin |
1:8aa5cdb4ab67 | 230 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 231 | * On first use, this member function will attempt to add this component to the |
Jonathan Austin |
1:8aa5cdb4ab67 | 232 | * list of fiber components in order to constantly update the values stored |
Jonathan Austin |
1:8aa5cdb4ab67 | 233 | * by this object. |
Jonathan Austin |
1:8aa5cdb4ab67 | 234 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 235 | * This technique is called lazy instantiation, and it means that we do not |
Jonathan Austin |
1:8aa5cdb4ab67 | 236 | * obtain the overhead from non-chalantly adding this component to fiber components. |
Jonathan Austin |
1:8aa5cdb4ab67 | 237 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 238 | * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR if the read request fails. |
Jonathan Austin |
1:8aa5cdb4ab67 | 239 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 240 | int MicroBitAccelerometer::updateSample() |
Jonathan Austin |
1:8aa5cdb4ab67 | 241 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 242 | if(!(status & MICROBIT_ACCEL_ADDED_TO_IDLE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 243 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 244 | fiber_add_idle_component(this); |
Jonathan Austin |
1:8aa5cdb4ab67 | 245 | status |= MICROBIT_ACCEL_ADDED_TO_IDLE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 246 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 247 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 248 | // Poll interrupt line from accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 249 | // n.b. Default is Active LO. Interrupt is cleared in data read. |
Jonathan Austin |
1:8aa5cdb4ab67 | 250 | if(!int1) |
Jonathan Austin |
1:8aa5cdb4ab67 | 251 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 252 | int8_t data[6]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 253 | int result; |
Jonathan Austin |
1:8aa5cdb4ab67 | 254 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 255 | result = readCommand(MMA8653_OUT_X_MSB, (uint8_t *)data, 6); |
Jonathan Austin |
1:8aa5cdb4ab67 | 256 | if (result !=0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 257 | return MICROBIT_I2C_ERROR; |
Jonathan Austin |
1:8aa5cdb4ab67 | 258 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 259 | // read MSB values... |
Jonathan Austin |
1:8aa5cdb4ab67 | 260 | sample.x = data[0]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 261 | sample.y = data[2]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 262 | sample.z = data[4]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 263 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 264 | // Normalize the data in the 0..1024 range. |
Jonathan Austin |
1:8aa5cdb4ab67 | 265 | sample.x *= 8; |
Jonathan Austin |
1:8aa5cdb4ab67 | 266 | sample.y *= 8; |
Jonathan Austin |
1:8aa5cdb4ab67 | 267 | sample.z *= 8; |
Jonathan Austin |
1:8aa5cdb4ab67 | 268 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 269 | #if CONFIG_ENABLED(USE_ACCEL_LSB) |
Jonathan Austin |
1:8aa5cdb4ab67 | 270 | // Add in LSB values. |
Jonathan Austin |
1:8aa5cdb4ab67 | 271 | sample.x += (data[1] / 64); |
Jonathan Austin |
1:8aa5cdb4ab67 | 272 | sample.y += (data[3] / 64); |
Jonathan Austin |
1:8aa5cdb4ab67 | 273 | sample.z += (data[5] / 64); |
Jonathan Austin |
1:8aa5cdb4ab67 | 274 | #endif |
Jonathan Austin |
1:8aa5cdb4ab67 | 275 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 276 | // Scale into millig (approx!) |
Jonathan Austin |
1:8aa5cdb4ab67 | 277 | sample.x *= this->sampleRange; |
Jonathan Austin |
1:8aa5cdb4ab67 | 278 | sample.y *= this->sampleRange; |
Jonathan Austin |
1:8aa5cdb4ab67 | 279 | sample.z *= this->sampleRange; |
Jonathan Austin |
1:8aa5cdb4ab67 | 280 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 281 | // Indicate that pitch and roll data is now stale, and needs to be recalculated if needed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 282 | status &= ~MICROBIT_ACCEL_PITCH_ROLL_VALID; |
Jonathan Austin |
1:8aa5cdb4ab67 | 283 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 284 | // Update gesture tracking |
Jonathan Austin |
1:8aa5cdb4ab67 | 285 | updateGesture(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 286 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 287 | // Indicate that a new sample is available |
Jonathan Austin |
1:8aa5cdb4ab67 | 288 | MicroBitEvent e(id, MICROBIT_ACCELEROMETER_EVT_DATA_UPDATE); |
Jonathan Austin |
1:8aa5cdb4ab67 | 289 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 290 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 291 | return MICROBIT_OK; |
Jonathan Austin |
1:8aa5cdb4ab67 | 292 | }; |
Jonathan Austin |
1:8aa5cdb4ab67 | 293 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 294 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 295 | * A service function. |
Jonathan Austin |
1:8aa5cdb4ab67 | 296 | * It calculates the current scalar acceleration of the device (x^2 + y^2 + z^2). |
Jonathan Austin |
1:8aa5cdb4ab67 | 297 | * It does not, however, square root the result, as this is a relatively high cost operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 298 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 299 | * This is left to application code should it be needed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 300 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 301 | * @return the sum of the square of the acceleration of the device across all axes. |
Jonathan Austin |
1:8aa5cdb4ab67 | 302 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 303 | int MicroBitAccelerometer::instantaneousAccelerationSquared() |
Jonathan Austin |
1:8aa5cdb4ab67 | 304 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 305 | updateSample(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 306 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 307 | // Use pythagoras theorem to determine the combined force acting on the device. |
Jonathan Austin |
1:8aa5cdb4ab67 | 308 | return (int)sample.x*(int)sample.x + (int)sample.y*(int)sample.y + (int)sample.z*(int)sample.z; |
Jonathan Austin |
1:8aa5cdb4ab67 | 309 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 310 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 311 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 312 | * Service function. |
Jonathan Austin |
1:8aa5cdb4ab67 | 313 | * Determines a 'best guess' posture of the device based on instantaneous data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 314 | * |
LancasterUniversity | 37:b624ae5e94a5 | 315 | * This makes no use of historic data, and forms the input to the filter implemented in updateGesture(). |
Jonathan Austin |
1:8aa5cdb4ab67 | 316 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 317 | * @return A 'best guess' of the current posture of the device, based on instanataneous data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 318 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 319 | BasicGesture MicroBitAccelerometer::instantaneousPosture() |
Jonathan Austin |
1:8aa5cdb4ab67 | 320 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 321 | int force = instantaneousAccelerationSquared(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 322 | bool shakeDetected = false; |
Jonathan Austin |
1:8aa5cdb4ab67 | 323 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 324 | // Test for shake events. |
Jonathan Austin |
1:8aa5cdb4ab67 | 325 | // 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 | 326 | // 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 | 327 | // |
Jonathan Austin |
1:8aa5cdb4ab67 | 328 | // If we see enough zero crossings in succession (MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD), then we decide that the device |
Jonathan Austin |
1:8aa5cdb4ab67 | 329 | // has been shaken. |
Jonathan Austin |
1:8aa5cdb4ab67 | 330 | if ((getX() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.x) || (getX() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.x)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 331 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 332 | shakeDetected = true; |
Jonathan Austin |
1:8aa5cdb4ab67 | 333 | shake.x = !shake.x; |
Jonathan Austin |
1:8aa5cdb4ab67 | 334 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 335 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 336 | if ((getY() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.y) || (getY() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.y)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 337 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 338 | shakeDetected = true; |
Jonathan Austin |
1:8aa5cdb4ab67 | 339 | shake.y = !shake.y; |
Jonathan Austin |
1:8aa5cdb4ab67 | 340 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 341 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 342 | if ((getZ() < -MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && shake.z) || (getZ() > MICROBIT_ACCELEROMETER_SHAKE_TOLERANCE && !shake.z)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 343 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 344 | shakeDetected = true; |
Jonathan Austin |
1:8aa5cdb4ab67 | 345 | shake.z = !shake.z; |
Jonathan Austin |
1:8aa5cdb4ab67 | 346 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 347 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 348 | if (shakeDetected && shake.count < MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD && ++shake.count == MICROBIT_ACCELEROMETER_SHAKE_COUNT_THRESHOLD) |
Jonathan Austin |
1:8aa5cdb4ab67 | 349 | shake.shaken = 1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 350 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 351 | if (++shake.timer >= MICROBIT_ACCELEROMETER_SHAKE_DAMPING) |
Jonathan Austin |
1:8aa5cdb4ab67 | 352 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 353 | shake.timer = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 354 | if (shake.count > 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 355 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 356 | if(--shake.count == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 357 | shake.shaken = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 358 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 359 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 360 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 361 | if (shake.shaken) |
Jonathan Austin |
1:8aa5cdb4ab67 | 362 | return GESTURE_SHAKE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 363 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 364 | if (force < MICROBIT_ACCELEROMETER_FREEFALL_THRESHOLD) |
Jonathan Austin |
1:8aa5cdb4ab67 | 365 | return GESTURE_FREEFALL; |
Jonathan Austin |
1:8aa5cdb4ab67 | 366 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 367 | if (force > MICROBIT_ACCELEROMETER_3G_THRESHOLD) |
Jonathan Austin |
1:8aa5cdb4ab67 | 368 | return GESTURE_3G; |
Jonathan Austin |
1:8aa5cdb4ab67 | 369 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 370 | if (force > MICROBIT_ACCELEROMETER_6G_THRESHOLD) |
Jonathan Austin |
1:8aa5cdb4ab67 | 371 | return GESTURE_6G; |
Jonathan Austin |
1:8aa5cdb4ab67 | 372 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 373 | if (force > MICROBIT_ACCELEROMETER_8G_THRESHOLD) |
Jonathan Austin |
1:8aa5cdb4ab67 | 374 | return GESTURE_8G; |
Jonathan Austin |
1:8aa5cdb4ab67 | 375 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 376 | // Determine our posture. |
Jonathan Austin |
1:8aa5cdb4ab67 | 377 | if (getX() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 378 | return GESTURE_LEFT; |
Jonathan Austin |
1:8aa5cdb4ab67 | 379 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 380 | if (getX() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 381 | return GESTURE_RIGHT; |
Jonathan Austin |
1:8aa5cdb4ab67 | 382 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 383 | if (getY() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 384 | return GESTURE_DOWN; |
Jonathan Austin |
1:8aa5cdb4ab67 | 385 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 386 | if (getY() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 387 | return GESTURE_UP; |
Jonathan Austin |
1:8aa5cdb4ab67 | 388 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 389 | if (getZ() < (-1000 + MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 390 | return GESTURE_FACE_UP; |
Jonathan Austin |
1:8aa5cdb4ab67 | 391 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 392 | if (getZ() > (1000 - MICROBIT_ACCELEROMETER_TILT_TOLERANCE)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 393 | return GESTURE_FACE_DOWN; |
Jonathan Austin |
1:8aa5cdb4ab67 | 394 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 395 | return GESTURE_NONE; |
Jonathan Austin |
1:8aa5cdb4ab67 | 396 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 397 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 398 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 399 | * Updates the basic gesture recognizer. This performs instantaneous pose recognition, and also some low pass filtering to promote |
Jonathan Austin |
1:8aa5cdb4ab67 | 400 | * stability. |
Jonathan Austin |
1:8aa5cdb4ab67 | 401 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 402 | void MicroBitAccelerometer::updateGesture() |
Jonathan Austin |
1:8aa5cdb4ab67 | 403 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 404 | // Determine what it looks like we're doing based on the latest sample... |
Jonathan Austin |
1:8aa5cdb4ab67 | 405 | BasicGesture g = instantaneousPosture(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 406 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 407 | // Perform some low pass filtering to reduce jitter from any detected effects |
Jonathan Austin |
1:8aa5cdb4ab67 | 408 | if (g == currentGesture) |
Jonathan Austin |
1:8aa5cdb4ab67 | 409 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 410 | if (sigma < MICROBIT_ACCELEROMETER_GESTURE_DAMPING) |
Jonathan Austin |
1:8aa5cdb4ab67 | 411 | sigma++; |
Jonathan Austin |
1:8aa5cdb4ab67 | 412 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 413 | else |
Jonathan Austin |
1:8aa5cdb4ab67 | 414 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 415 | currentGesture = g; |
Jonathan Austin |
1:8aa5cdb4ab67 | 416 | sigma = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 417 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 418 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 419 | // If we've reached threshold, update our record and raise the relevant event... |
Jonathan Austin |
1:8aa5cdb4ab67 | 420 | if (currentGesture != lastGesture && sigma >= MICROBIT_ACCELEROMETER_GESTURE_DAMPING) |
Jonathan Austin |
1:8aa5cdb4ab67 | 421 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 422 | lastGesture = currentGesture; |
Jonathan Austin |
1:8aa5cdb4ab67 | 423 | MicroBitEvent e(MICROBIT_ID_GESTURE, lastGesture); |
Jonathan Austin |
1:8aa5cdb4ab67 | 424 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 425 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 426 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 427 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 428 | * Attempts to set the sample rate of the accelerometer to the specified value (in ms). |
Jonathan Austin |
1:8aa5cdb4ab67 | 429 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 430 | * @param period the requested time between samples, in milliseconds. |
Jonathan Austin |
1:8aa5cdb4ab67 | 431 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 432 | * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails. |
Jonathan Austin |
1:8aa5cdb4ab67 | 433 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 434 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 435 | * // sample rate is now 20 ms. |
Jonathan Austin |
1:8aa5cdb4ab67 | 436 | * accelerometer.setPeriod(20); |
Jonathan Austin |
1:8aa5cdb4ab67 | 437 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 438 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 439 | * @note The requested rate may not be possible on the hardware. In this case, the |
Jonathan Austin |
1:8aa5cdb4ab67 | 440 | * nearest lower rate is chosen. |
Jonathan Austin |
1:8aa5cdb4ab67 | 441 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 442 | int MicroBitAccelerometer::setPeriod(int period) |
Jonathan Austin |
1:8aa5cdb4ab67 | 443 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 444 | this->samplePeriod = period; |
Jonathan Austin |
1:8aa5cdb4ab67 | 445 | return this->configure(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 446 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 447 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 448 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 449 | * Reads the currently configured sample rate of the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 450 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 451 | * @return The time between samples, in milliseconds. |
Jonathan Austin |
1:8aa5cdb4ab67 | 452 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 453 | int MicroBitAccelerometer::getPeriod() |
Jonathan Austin |
1:8aa5cdb4ab67 | 454 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 455 | return (int)samplePeriod; |
Jonathan Austin |
1:8aa5cdb4ab67 | 456 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 457 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 458 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 459 | * Attempts to set the sample range of the accelerometer to the specified value (in g). |
Jonathan Austin |
1:8aa5cdb4ab67 | 460 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 461 | * @param range The requested sample range of samples, in g. |
Jonathan Austin |
1:8aa5cdb4ab67 | 462 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 463 | * @return MICROBIT_OK on success, MICROBIT_I2C_ERROR is the request fails. |
Jonathan Austin |
1:8aa5cdb4ab67 | 464 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 465 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 466 | * // the sample range of the accelerometer is now 8G. |
Jonathan Austin |
1:8aa5cdb4ab67 | 467 | * accelerometer.setRange(8); |
Jonathan Austin |
1:8aa5cdb4ab67 | 468 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 469 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 470 | * @note The requested range may not be possible on the hardware. In this case, the |
Jonathan Austin |
1:8aa5cdb4ab67 | 471 | * nearest lower range is chosen. |
Jonathan Austin |
1:8aa5cdb4ab67 | 472 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 473 | int MicroBitAccelerometer::setRange(int range) |
Jonathan Austin |
1:8aa5cdb4ab67 | 474 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 475 | this->sampleRange = range; |
Jonathan Austin |
1:8aa5cdb4ab67 | 476 | return this->configure(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 477 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 478 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 479 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 480 | * Reads the currently configured sample range of the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 481 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 482 | * @return The sample range, in g. |
Jonathan Austin |
1:8aa5cdb4ab67 | 483 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 484 | int MicroBitAccelerometer::getRange() |
Jonathan Austin |
1:8aa5cdb4ab67 | 485 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 486 | return (int)sampleRange; |
Jonathan Austin |
1:8aa5cdb4ab67 | 487 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 488 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 489 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 490 | * Reads the value of the X axis from the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 491 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 492 | * @param system The coordinate system to use. By default, a simple cartesian system is provided. |
Jonathan Austin |
1:8aa5cdb4ab67 | 493 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 494 | * @return The force measured in the X axis, in milli-g. |
Jonathan Austin |
1:8aa5cdb4ab67 | 495 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 496 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 497 | * accelerometer.getX(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 498 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 499 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 500 | int MicroBitAccelerometer::getX(MicroBitCoordinateSystem system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 501 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 502 | updateSample(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 503 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 504 | switch (system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 505 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 506 | case SIMPLE_CARTESIAN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 507 | return -sample.x; |
Jonathan Austin |
1:8aa5cdb4ab67 | 508 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 509 | case NORTH_EAST_DOWN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 510 | return sample.y; |
Jonathan Austin |
1:8aa5cdb4ab67 | 511 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 512 | case RAW: |
Jonathan Austin |
1:8aa5cdb4ab67 | 513 | default: |
Jonathan Austin |
1:8aa5cdb4ab67 | 514 | return sample.x; |
Jonathan Austin |
1:8aa5cdb4ab67 | 515 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 516 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 517 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 518 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 519 | * Reads the value of the Y axis from the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 520 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 521 | * @return The force measured in the Y axis, in milli-g. |
Jonathan Austin |
1:8aa5cdb4ab67 | 522 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 523 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 524 | * accelerometer.getY(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 525 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 526 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 527 | int MicroBitAccelerometer::getY(MicroBitCoordinateSystem system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 528 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 529 | updateSample(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 530 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 531 | switch (system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 532 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 533 | case SIMPLE_CARTESIAN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 534 | return -sample.y; |
Jonathan Austin |
1:8aa5cdb4ab67 | 535 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 536 | case NORTH_EAST_DOWN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 537 | return -sample.x; |
Jonathan Austin |
1:8aa5cdb4ab67 | 538 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 539 | case RAW: |
Jonathan Austin |
1:8aa5cdb4ab67 | 540 | default: |
Jonathan Austin |
1:8aa5cdb4ab67 | 541 | return sample.y; |
Jonathan Austin |
1:8aa5cdb4ab67 | 542 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 543 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 544 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 545 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 546 | * Reads the value of the Z axis from the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 547 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 548 | * @return The force measured in the Z axis, in milli-g. |
Jonathan Austin |
1:8aa5cdb4ab67 | 549 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 550 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 551 | * accelerometer.getZ(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 552 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 553 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 554 | int MicroBitAccelerometer::getZ(MicroBitCoordinateSystem system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 555 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 556 | updateSample(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 557 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 558 | switch (system) |
Jonathan Austin |
1:8aa5cdb4ab67 | 559 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 560 | case NORTH_EAST_DOWN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 561 | return -sample.z; |
Jonathan Austin |
1:8aa5cdb4ab67 | 562 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 563 | case SIMPLE_CARTESIAN: |
Jonathan Austin |
1:8aa5cdb4ab67 | 564 | case RAW: |
Jonathan Austin |
1:8aa5cdb4ab67 | 565 | default: |
Jonathan Austin |
1:8aa5cdb4ab67 | 566 | return sample.z; |
Jonathan Austin |
1:8aa5cdb4ab67 | 567 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 568 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 569 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 570 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 571 | * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 572 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 573 | * @return The pitch of the device, in degrees. |
Jonathan Austin |
1:8aa5cdb4ab67 | 574 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 575 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 576 | * accelerometer.getPitch(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 577 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 578 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 579 | int MicroBitAccelerometer::getPitch() |
Jonathan Austin |
1:8aa5cdb4ab67 | 580 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 581 | return (int) ((360*getPitchRadians()) / (2*PI)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 582 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 583 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 584 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 585 | * Provides a rotation compensated pitch of the device, based on the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 586 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 587 | * @return The pitch of the device, in radians. |
Jonathan Austin |
1:8aa5cdb4ab67 | 588 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 589 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 590 | * accelerometer.getPitchRadians(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 591 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 592 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 593 | float MicroBitAccelerometer::getPitchRadians() |
Jonathan Austin |
1:8aa5cdb4ab67 | 594 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 595 | if (!(status & MICROBIT_ACCEL_PITCH_ROLL_VALID)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 596 | recalculatePitchRoll(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 597 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 598 | return pitch; |
Jonathan Austin |
1:8aa5cdb4ab67 | 599 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 600 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 601 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 602 | * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 603 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 604 | * @return The roll of the device, in degrees. |
Jonathan Austin |
1:8aa5cdb4ab67 | 605 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 606 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 607 | * accelerometer.getRoll(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 608 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 609 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 610 | int MicroBitAccelerometer::getRoll() |
Jonathan Austin |
1:8aa5cdb4ab67 | 611 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 612 | return (int) ((360*getRollRadians()) / (2*PI)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 613 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 614 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 615 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 616 | * Provides a rotation compensated roll of the device, based on the latest update retrieved from the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 617 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 618 | * @return The roll of the device, in radians. |
Jonathan Austin |
1:8aa5cdb4ab67 | 619 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 620 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 621 | * accelerometer.getRollRadians(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 622 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 623 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 624 | float MicroBitAccelerometer::getRollRadians() |
Jonathan Austin |
1:8aa5cdb4ab67 | 625 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 626 | if (!(status & MICROBIT_ACCEL_PITCH_ROLL_VALID)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 627 | recalculatePitchRoll(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 628 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 629 | return roll; |
Jonathan Austin |
1:8aa5cdb4ab67 | 630 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 631 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 632 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 633 | * Recalculate roll and pitch values for the current sample. |
Jonathan Austin |
1:8aa5cdb4ab67 | 634 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 635 | * @note We only do this at most once per sample, as the necessary trigonemteric functions are rather |
Jonathan Austin |
1:8aa5cdb4ab67 | 636 | * heavyweight for a CPU without a floating point unit. |
Jonathan Austin |
1:8aa5cdb4ab67 | 637 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 638 | void MicroBitAccelerometer::recalculatePitchRoll() |
Jonathan Austin |
1:8aa5cdb4ab67 | 639 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 640 | float x = (float) getX(NORTH_EAST_DOWN); |
Jonathan Austin |
1:8aa5cdb4ab67 | 641 | float y = (float) getY(NORTH_EAST_DOWN); |
Jonathan Austin |
1:8aa5cdb4ab67 | 642 | float z = (float) getZ(NORTH_EAST_DOWN); |
Jonathan Austin |
1:8aa5cdb4ab67 | 643 | |
LancasterUniversity | 6:2e1c2e0d8c7a | 644 | roll = atan2((double)getY(NORTH_EAST_DOWN), (double)getZ(NORTH_EAST_DOWN)); |
LancasterUniversity | 6:2e1c2e0d8c7a | 645 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 646 | pitch = atan(-x / (y*sin(roll) + z*cos(roll))); |
Jonathan Austin |
1:8aa5cdb4ab67 | 647 | status |= MICROBIT_ACCEL_PITCH_ROLL_VALID; |
Jonathan Austin |
1:8aa5cdb4ab67 | 648 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 649 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 650 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 651 | * Retrieves the last recorded gesture. |
Jonathan Austin |
1:8aa5cdb4ab67 | 652 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 653 | * @return The last gesture that was detected. |
Jonathan Austin |
1:8aa5cdb4ab67 | 654 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 655 | * Example: |
Jonathan Austin |
1:8aa5cdb4ab67 | 656 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 657 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 658 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 659 | * if (accelerometer.getGesture() == SHAKE) |
Jonathan Austin |
1:8aa5cdb4ab67 | 660 | * display.scroll("SHAKE!"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 661 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 662 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 663 | BasicGesture MicroBitAccelerometer::getGesture() |
Jonathan Austin |
1:8aa5cdb4ab67 | 664 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 665 | return lastGesture; |
Jonathan Austin |
1:8aa5cdb4ab67 | 666 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 667 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 668 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 669 | * A periodic callback invoked by the fiber scheduler idle thread. |
Jonathan Austin |
1:8aa5cdb4ab67 | 670 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 671 | * Internally calls updateSample(). |
Jonathan Austin |
1:8aa5cdb4ab67 | 672 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 673 | void MicroBitAccelerometer::idleTick() |
Jonathan Austin |
1:8aa5cdb4ab67 | 674 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 675 | updateSample(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 676 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 677 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 678 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 679 | * Returns 0 or 1. 1 indicates data is waiting to be read, zero means data is not ready to be read. |
Jonathan Austin |
1:8aa5cdb4ab67 | 680 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 681 | * We check if any data is ready for reading by checking the interrupt flag on the accelerometer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 682 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 683 | int MicroBitAccelerometer::isIdleCallbackNeeded() |
Jonathan Austin |
1:8aa5cdb4ab67 | 684 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 685 | return !int1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 686 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 687 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 688 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 689 | * Destructor for MicroBitAccelerometer, where we deregister from the array of fiber components. |
Jonathan Austin |
1:8aa5cdb4ab67 | 690 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 691 | MicroBitAccelerometer::~MicroBitAccelerometer() |
Jonathan Austin |
1:8aa5cdb4ab67 | 692 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 693 | fiber_remove_idle_component(this); |
Jonathan Austin |
1:8aa5cdb4ab67 | 694 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 695 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 696 | const MMA8653SampleRangeConfig MMA8653SampleRange[MMA8653_SAMPLE_RANGES] = { |
Jonathan Austin |
1:8aa5cdb4ab67 | 697 | {2, 0}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 698 | {4, 1}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 699 | {8, 2} |
Jonathan Austin |
1:8aa5cdb4ab67 | 700 | }; |
Jonathan Austin |
1:8aa5cdb4ab67 | 701 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 702 | const MMA8653SampleRateConfig MMA8653SampleRate[MMA8653_SAMPLE_RATES] = { |
Jonathan Austin |
1:8aa5cdb4ab67 | 703 | {1250, 0x00}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 704 | {2500, 0x08}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 705 | {5000, 0x10}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 706 | {10000, 0x18}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 707 | {20000, 0x20}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 708 | {80000, 0x28}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 709 | {160000, 0x30}, |
Jonathan Austin |
1:8aa5cdb4ab67 | 710 | {640000, 0x38} |
LancasterUniversity | 6:2e1c2e0d8c7a | 711 | }; |