├── .gitignore ├── AUTHORS ├── Src └── MPU6050.cc ├── assets └── icon.jpg ├── ISSUES.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── Inc ├── data_types.h ├── utility_functions.h ├── registers.h ├── bit_definitions.h └── MPU60X0.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.pch -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Basit Ayantunde -------------------------------------------------------------------------------- /Src/MPU6050.cc: -------------------------------------------------------------------------------- 1 | 2 | // TODO(lamarrr): Move header files definitions here 3 | -------------------------------------------------------------------------------- /assets/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lamarrr/MPU60X0/HEAD/assets/icon.jpg -------------------------------------------------------------------------------- /ISSUES.md: -------------------------------------------------------------------------------- 1 | If you open a GitHub Issue, here is our policy: 2 | 1. It must be a bug/performance 3 | issue or a feature request or a build issue or a documentation issue (for small doc fixes please send a PR instead). 4 | 2. Make sure the Issue Template is filled out. 5 | 3. The issue should be related to the repo it is created in. 6 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | If you open a GitHub issue, here is our policy: 2 | 3 | 1. It must be a bug, a feature request, or a significant problem with documentation (for small docs fixes please send a PR instead). 4 | 2. The form below must be filled out. 5 | 6 | ### Describe the problem 7 | Describe the problem clearly here. Be sure to convey here why it's a bug in TensorFlow or a feature request. 8 | 9 | ### Source code / logs 10 | Include any logs or source code that would be helpful to diagnose the problem. If including tracebacks, please include the full traceback. Large logs and files should be attached. Try to provide a reproducible test case that is the bare minimum necessary to generate the problem. 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Basit Ayantunde 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Inc/data_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file data_types.h 3 | * @author Basit Ayantunde (rlamarrr@gmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-08-23 7 | * 8 | * 9 | * @copyright Copyright (c) 2019 Basit Ayantunde 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | 30 | #ifndef DRIVERS_MPU60X0_DATA_TYPES_H_ 31 | #define DRIVERS_MPU60X0_DATA_TYPES_H_ 32 | 33 | #include 34 | 35 | namespace mpu60X0 { 36 | 37 | struct TriAxialData { 38 | int16_t x; 39 | int16_t y; 40 | int16_t z; 41 | }; 42 | 43 | struct BiAxialData { 44 | int16_t a; 45 | int16_t b; 46 | }; 47 | 48 | }; // namespace mpu60X0 49 | // namespace mpu60X0 50 | #endif // DRIVERS_MPU60X0_DATA_TYPES_H_ 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

MPU60X0

3 | 4 | MPU60X0 is an STM32 I2C Blocking, Master mode driver for invensense' MPU6050 and MPU6000 IMUs. 5 | 6 | Features: 7 | - Blocking mode API 8 | - Takes advantage of burst read and write cycles where possible 9 | - Utilizes bit field packing instead of conventional byte operations to ensure readability 10 | - Ultra lightweight and compact abstractions 11 | - Based on the STM32 HAL firmware. 12 | The API is designed to be conistent and easy to read by utilising struct packing instead of the conventional byte operations. 13 | 14 | 15 | ## Examples 16 | TBD 17 | 18 | 19 | ## Dependencies 20 | 21 | - STM32Fx HAL I2C driver 22 | - STM32Fx HAL UART Driver (Debugging) 23 | 24 | 25 | ## Installation 26 | 27 | Copy the header files to your Inc directory 28 | 29 | 30 | 31 | 32 | 33 | ## Known Issues 34 | 35 | We utilize bit fields, Clang doesn't raise warnings about the bit field sizes being unable to fit with the byte data struct representations, gcc however raises the warning, This is not a problem at the compilation phase unless you use a flag such as -Werror that points it out as an error. 36 | 37 | 38 | ## Contributing 39 | We employ the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and [Nest's embedded c++ styles](https://github.com/openthread/openthread/blob/master/STYLE_GUIDE.md) 40 | However in contrast to [Nest's embedded c++ styles](https://github.com/openthread/openthread/blob/master/STYLE_GUIDE.md), We: 41 | 42 | - utilize modern C++ STL abstractions such as [std::pair](https://en.cppreference.com/w/cpp/utility/pair) 43 | - utilize [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration) to represent discretized time intervals for timeouts 44 | 45 | ## License 46 | [MIT License](assets/LICENSE) 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Inc/utility_functions.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file utility_functions.h 3 | * @author Basit Ayantunde (rlamarrr@gmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-08-23 7 | * 8 | * 9 | * @copyright Copyright (c) 2019 Basit Ayantunde 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | 30 | #ifndef DRIVERS_MPU60X0_UTILITY_FUNCTIONS_H_ 31 | #define DRIVERS_MPU60X0_UTILITY_FUNCTIONS_H_ 32 | 33 | #include 34 | #include 35 | #include 36 | #include "bit_definitions.h" // NOLINT 37 | #include "data_types.h" // NOLINT 38 | 39 | namespace mpu60X0 { 40 | 41 | // Utility Functions 42 | constexpr float kBasisI16 = 43 | static_cast(std::numeric_limits::max()); 44 | // smallest and closest to int16 in precision is float32, using higher is 45 | // redundant 46 | float TemperatureToDegreesCelsius(int16_t temp) { 47 | return (temp / 340.0F) + 36.53F; 48 | } 49 | float OrientationToMS1(int16_t value, GyroscopeFullScale scale) { 50 | switch (scale) { 51 | case GyroscopeFullScale::DegPs1000: 52 | return (value / kBasisI16) * 1000.0F; 53 | 54 | case GyroscopeFullScale::DegPs2000: 55 | return (value / kBasisI16) * 2000.0F; 56 | 57 | case GyroscopeFullScale::DegPs250: 58 | return (value / kBasisI16) * 250.0F; 59 | 60 | case GyroscopeFullScale::DegPs500: 61 | return (value / kBasisI16) * 500.0F; 62 | 63 | default: 64 | return std::numeric_limits::signaling_NaN(); 65 | } 66 | } 67 | 68 | float AccelerationToMs2(int16_t value, AccelerometerFullScale scale) { 69 | switch (scale) { 70 | case AccelerometerFullScale::k16G: 71 | return (value / kBasisI16) * 16.0F; 72 | 73 | case AccelerometerFullScale::k2G: 74 | return (value / kBasisI16) * 2.0F; 75 | 76 | case AccelerometerFullScale::k4G: 77 | return (value / kBasisI16) * 4.0F; 78 | 79 | case AccelerometerFullScale::k8G: 80 | return (value / kBasisI16) * 8.0F; 81 | 82 | default: 83 | return std::numeric_limits::signaling_NaN(); 84 | } 85 | } 86 | float GyroscopeX_FactoryTrimValue(uint8_t){}; 87 | float GyroscopeY_FactoryTrimValue(uint8_t){}; 88 | float GyroscopeZ_FactoryTrimValue(uint8_t){}; 89 | 90 | float AccelerometerX_FactoryTrimValue(uint8_t){}; 91 | float AccelerometerY_FactoryTrimValue(uint8_t){}; 92 | float AccelerometerZ_FactoryTrimValue(uint8_t){}; 93 | 94 | int16_t SelfTestResponse(int16_t, int16_t){}; 95 | float FactoryTrimChange(float, int16_t){}; 96 | 97 | }; // namespace mpu60X0 98 | // namespace mpu60X0 99 | 100 | #endif // DRIVERS_MPU60X0_UTILITY_FUNCTIONS_H_ 101 | -------------------------------------------------------------------------------- /Inc/registers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file registers.h 3 | * @author Basit Ayantunde (rlamarrr@gmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-08-23 7 | * 8 | * 9 | * @copyright Copyright (c) 2019 Basit Ayantunde 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | 30 | #ifndef DRIVERS_MPU60X0_REGISTERS_H_ 31 | #define DRIVERS_MPU60X0_REGISTERS_H_ 32 | 33 | #include 34 | 35 | namespace mpu60X0 { 36 | 37 | using register_type = uint8_t; 38 | 39 | namespace register_map { 40 | constexpr register_type SelfTestX = 13U; 41 | constexpr register_type SelfTestY = 14U; 42 | constexpr register_type SelfTestZ = 15U; 43 | constexpr register_type SelfTestA = 16U; 44 | constexpr register_type SampleRateDivider = 25U; 45 | constexpr register_type Config = 26U; 46 | constexpr register_type GyroscopeConfig = 27U; 47 | constexpr register_type AccelerometerConfig = 28U; 48 | constexpr register_type FreeFallAccelerationThreshold = 29U; 49 | constexpr register_type FreeFallDuration = 30U; 50 | constexpr register_type MotionDetectionThreshold = 31U; 51 | constexpr register_type MotionDetectionDuration = 32U; 52 | constexpr register_type ZeroMotionDetectionThreshold = 33U; 53 | constexpr register_type ZeroMotionDetectionDuration = 34U; 54 | constexpr register_type FifoEnable = 35U; 55 | constexpr register_type I2cMasterCtrl = 36U; 56 | constexpr register_type I2cSlave0_RW_Address = 37U; 57 | constexpr register_type I2cSlave0_Register = 38U; 58 | constexpr register_type I2cSlave0_Control = 39U; 59 | constexpr register_type I2cSlave1_RW_Address = 40U; 60 | constexpr register_type I2cSlave1_Register = 41U; 61 | constexpr register_type I2cSlave1_Control = 42U; 62 | constexpr register_type I2cSlave2_RW_Address = 43U; 63 | constexpr register_type I2cSlave2_Register = 44U; 64 | constexpr register_type I2cSlave2_Control = 45U; 65 | constexpr register_type I2cSlave3_RW_Address = 46U; 66 | constexpr register_type I2cSlave3_Register = 47U; 67 | constexpr register_type I2cSlave3_Control = 48U; 68 | constexpr register_type I2cSlave4_RW_Address = 49U; 69 | constexpr register_type I2cSlave4_Register = 50U; 70 | constexpr register_type I2cSlave4_D0 = 51U; 71 | constexpr register_type I2cSlave4_Control = 52U; 72 | constexpr register_type I2cSlave4_D1 = 53U; 73 | constexpr register_type I2cMasterStatus = 54U; 74 | constexpr register_type InterruptPinConfig = 55U; 75 | constexpr register_type InterruptEnable = 56U; 76 | constexpr register_type InterruptStatus = 58U; 77 | constexpr register_type AccelerometerX_OutH = 59U; 78 | constexpr register_type AccelerometerX_OutL = 60U; 79 | constexpr register_type AccelerometerY_OutH = 61U; 80 | constexpr register_type AccelerometerY_OutL = 62U; 81 | constexpr register_type AccelerometerZ_OutH = 63U; 82 | constexpr register_type AccelerometerZ_OutL = 64U; 83 | constexpr register_type TemperatureOutH = 65U; 84 | constexpr register_type TemperatureOutL = 66U; 85 | constexpr register_type GyroscopeX_OutH = 67U; 86 | constexpr register_type GyroscopeX_OutL = 68U; 87 | constexpr register_type GyroscopeY_OutH = 69U; 88 | constexpr register_type GyroscopeY_OutL = 70U; 89 | constexpr register_type GyroscopeZ_OutH = 71U; 90 | constexpr register_type GyroscopeZ_OutL = 72U; 91 | constexpr register_type ExternalSensorData0 = 73U; 92 | constexpr register_type ExternalSensorData1 = 74U; 93 | constexpr register_type ExternalSensorData2 = 75U; 94 | constexpr register_type ExternalSensorData3 = 76U; 95 | constexpr register_type ExternalSensorData4 = 77U; 96 | constexpr register_type ExternalSensorData5 = 78U; 97 | constexpr register_type ExternalSensorData6 = 79U; 98 | constexpr register_type ExternalSensorData7 = 80U; 99 | constexpr register_type ExternalSensorData8 = 81U; 100 | constexpr register_type ExternalSensorData9 = 82U; 101 | constexpr register_type ExternalSensorData10 = 83U; 102 | constexpr register_type ExternalSensorData11 = 84U; 103 | constexpr register_type ExternalSensorData12 = 85U; 104 | constexpr register_type ExternalSensorData13 = 86U; 105 | constexpr register_type ExternalSensorData14 = 87U; 106 | constexpr register_type ExternalSensorData15 = 88U; 107 | constexpr register_type ExternalSensorData16 = 89U; 108 | constexpr register_type ExternalSensorData17 = 90U; 109 | constexpr register_type ExternalSensorData18 = 91U; 110 | constexpr register_type ExternalSensorData19 = 92U; 111 | constexpr register_type ExternalSensorData20 = 93U; 112 | constexpr register_type ExternalSensorData21 = 94U; 113 | constexpr register_type ExternalSensorData22 = 95U; 114 | constexpr register_type ExternalSensorData23 = 96U; 115 | constexpr register_type MotionDetectionStatus = 97U; 116 | constexpr register_type I2cSlave0_DataOut = 99U; 117 | constexpr register_type I2cSlave1_DataOut = 100U; 118 | constexpr register_type I2cSlave2_DataOut = 101U; 119 | constexpr register_type I2cSlave3_DataOut = 102U; 120 | constexpr register_type I2cMasterDelayControl = 103U; 121 | constexpr register_type SignalPathReset = 104U; 122 | constexpr register_type MotionDetectionControl = 105U; 123 | constexpr register_type UserControl = 106U; 124 | constexpr register_type PowerManagement1 = 107U; 125 | constexpr register_type PowerManagement2 = 108U; 126 | constexpr register_type FifoCountH = 114U; 127 | constexpr register_type FifoCountL = 115U; 128 | constexpr register_type FifoReadWrite = 116U; 129 | constexpr register_type WhoAmI = 117U; 130 | }; // namespace register_map 131 | 132 | }; // namespace mpu60X0 133 | #endif // DRIVERS_MPU60X0_REGISTERS_H_ 134 | -------------------------------------------------------------------------------- /Inc/bit_definitions.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file bit_definitions.h 3 | * @author Basit Ayantunde (rlamarrr@gmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-08-23 7 | * 8 | * 9 | * @copyright Copyright (c) 2019 Basit Ayantunde 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | 30 | #ifndef DRIVERS_MPU60X0_BIT_DEFINITIONS_H_ 31 | #define DRIVERS_MPU60X0_BIT_DEFINITIONS_H_ 32 | 33 | #include 34 | 35 | #define MPU_CDEBUG 36 | 37 | #ifdef MPU_CDEBUG 38 | #define MPU_SIZE_CASSERT(x) \ 39 | static_assert(sizeof(x) == 1U, "sizeof " #x " is larger than a byte"); 40 | #else 41 | #define MPU_SIZE_CASSERT(x) 42 | #endif 43 | 44 | namespace mpu60X0 { 45 | // Good 'Ol bit packing 46 | enum struct FrameSync : uint8_t { 47 | InputDisabled = 0U, 48 | TemperatureOutL = 1U, 49 | GyroscopeX_OutL = 2U, 50 | GyroscopeY_OutL = 3U, 51 | GyroscopeZ_OutL = 4U, 52 | AccelerometerX_OutL = 5U, 53 | AccelerometerY_OutL = 6U, 54 | AccelerometerZ_OutL = 7U 55 | }; 56 | 57 | enum struct DlpfConfig : uint8_t { 58 | A_260Hz_G_256Hz = 0U, 59 | A_184Hz_G_188Hz = 1U, 60 | A_94Hz_G_98Hz = 2U, 61 | A_44Hz_G_42Hz = 3U, 62 | A_21Hz_G_20Hz = 4U, 63 | A_10Hz_G_10Hz = 5U, 64 | A_5Hz_G_5Hz = 6U, 65 | ___reserved__ = 7U 66 | }; 67 | 68 | struct Config { 69 | DlpfConfig dlpf_config : 3U; 70 | FrameSync ext_frame_sync : 3U; 71 | uint8_t __reserved__ : 2U; 72 | Config() { *reinterpret_cast(this) = 0U; } 73 | }; 74 | 75 | MPU_SIZE_CASSERT(Config); 76 | 77 | enum struct GyroscopeFullScale : uint8_t { 78 | DegPs250 = 0U, 79 | DegPs500 = 1U, 80 | DegPs1000 = 2U, 81 | DegPs2000 = 3U, 82 | }; 83 | 84 | struct GyroscopeConfig { 85 | uint8_t __reserved__ : 3U; 86 | GyroscopeFullScale full_scale : 2U; 87 | bool z_self_test : 1U; 88 | bool y_self_test : 1U; 89 | bool x_self_test : 1U; 90 | 91 | GyroscopeConfig() { *reinterpret_cast(this) = 0U; } 92 | }; 93 | 94 | MPU_SIZE_CASSERT(GyroscopeConfig); 95 | 96 | enum struct AccelerometerFullScale : uint8_t { 97 | k2G = 0U, 98 | k4G = 1U, 99 | k8G = 2U, 100 | k16G = 3U 101 | }; 102 | 103 | struct AccelerometerConfig { 104 | uint8_t __reserved__ : 3U; 105 | AccelerometerFullScale full_scale : 2U; 106 | bool z_self_test : 1U; 107 | bool y_self_test : 1U; 108 | bool x_self_test : 1U; 109 | 110 | AccelerometerConfig() { *reinterpret_cast(this) = 0U; } 111 | }; 112 | 113 | MPU_SIZE_CASSERT(AccelerometerConfig); 114 | 115 | struct FifoEnableConfig { 116 | bool enable_slave0_fifo : 1U; 117 | bool enable_slave1_fifo : 1U; 118 | bool enable_slave2_fifo : 1U; 119 | bool enable_acceleration_fifo : 1U; 120 | bool enable_gyroscope_z_fifo : 1U; 121 | bool enable_gyroscope_y_fifo : 1U; 122 | bool enable_gyroscope_x_fifo : 1U; 123 | bool enable_temperature_fifo : 1U; 124 | 125 | FifoEnableConfig() { *reinterpret_cast(this) = 0U; } 126 | }; 127 | 128 | MPU_SIZE_CASSERT(FifoEnableConfig); 129 | 130 | enum struct I2cMasterClockSpeed : uint8_t { 131 | F348kHz = 0U, 132 | F333kHz = 1U, 133 | F320kHz = 2U, 134 | F308kHz = 3U, 135 | F296kHz = 4U, 136 | F286kHz = 5U, 137 | F276kHz = 6U, 138 | F267kHz = 7U, 139 | F258kHz = 8U, 140 | F500kHz = 9U, 141 | F471kHz = 10U, 142 | F444kHz = 11U, 143 | F421kHz = 12U, 144 | F400kHz = 13U, 145 | F381kHz = 14U, 146 | F364kHz = 15U, 147 | }; 148 | 149 | enum struct I2cMasterReadWriteTransition : uint8_t { 150 | Restart = 0U, 151 | StartStop = 1U, 152 | }; 153 | 154 | struct I2cMasterCtrlConfig { 155 | I2cMasterClockSpeed clock_speed : 4U; 156 | I2cMasterReadWriteTransition rw_transition : 1U; 157 | bool enable_slave3_fifo : 1U; 158 | bool dri_await_ext_sensor_data : 1U; 159 | bool enable_multi_master : 1U; 160 | 161 | I2cMasterCtrlConfig() { *reinterpret_cast(this) = 0U; } 162 | }; 163 | 164 | MPU_SIZE_CASSERT(I2cMasterCtrlConfig); 165 | 166 | struct InterruptPinConfig { 167 | uint8_t ___reserved___ : 1U; 168 | bool bypass_i2c_enable : 1U; 169 | bool frame_sync_enable : 1U; 170 | uint8_t frame_sync_logic_level : 1U; 171 | bool clear_on_read : 1U; 172 | bool latch_enable_until_interrupt_clear : 1U; 173 | bool open_drain : 1U; 174 | uint8_t logic_level : 1U; 175 | 176 | InterruptPinConfig() { *reinterpret_cast(this) = 0U; } 177 | }; 178 | 179 | MPU_SIZE_CASSERT(InterruptPinConfig); 180 | 181 | struct InterruptEnableConfig { 182 | bool data_ready_interrupt_enable : 1U; 183 | uint8_t __reserved__ : 2U; 184 | bool i2c_master_interrupt_enable : 1U; 185 | bool fifo_overflow_interrupt_enable : 1U; 186 | bool enable_zero_motion_detection_interrupt : 1U; 187 | bool enable_motion_detection_interrupt : 1U; 188 | bool enable_freefall_detection_interrupt : 1U; 189 | 190 | InterruptEnableConfig() { *reinterpret_cast(this) = 0U; } 191 | }; 192 | 193 | MPU_SIZE_CASSERT(InterruptEnableConfig); 194 | 195 | struct InterruptStatus { 196 | bool data_ready : 1U; 197 | uint8_t __reserved__ : 2U; 198 | bool i2c_master_interrupt : 1U; 199 | bool fifo_overflow : 1U; 200 | bool zero_motion_detected : 1U; 201 | bool motion_detected : 1U; 202 | bool free_fall_detected : 1U; 203 | 204 | InterruptStatus() { *reinterpret_cast(this) = 0U; } 205 | }; 206 | 207 | MPU_SIZE_CASSERT(InterruptStatus); 208 | 209 | enum struct ClockSource : uint8_t { 210 | Internal_8MHz = 0U, 211 | PllGyro_X = 1U, 212 | PllGyro_Y = 2U, 213 | PllGyro_Z = 3U, 214 | External_32_768kHz = 4U, 215 | External_19_2MHz = 5U, 216 | ClockSourceNone = 7U 217 | }; 218 | 219 | struct I2cMasterDelayCtrlConfig { 220 | bool slave0_delayed_access : 1U; 221 | bool slave1_delayed_access : 1U; 222 | bool slave2_delayed_access : 1U; 223 | bool slave3_delayed_access : 1U; 224 | bool slave4_delayed_access : 1U; 225 | uint8_t __reserved__ : 2U; 226 | bool delayed_shadow : 1U; 227 | 228 | I2cMasterDelayCtrlConfig() { *reinterpret_cast(this) = 0U; } 229 | }; 230 | 231 | MPU_SIZE_CASSERT(I2cMasterDelayCtrlConfig); 232 | 233 | struct SignalPathResetConfig { 234 | bool temperature_reset : 1U; 235 | bool accelerometer_reset : 1U; 236 | bool gyroscope_reset : 1U; 237 | uint8_t __reserved__ : 5U; 238 | 239 | SignalPathResetConfig() { *reinterpret_cast(this) = 0U; } 240 | }; 241 | 242 | MPU_SIZE_CASSERT(SignalPathResetConfig); 243 | 244 | struct MotionDetectionCtrlConfig { 245 | uint8_t motion_counter_decrement_rate : 2U; 246 | uint8_t freefall_counter_decrement_rate : 2U; 247 | uint8_t accelerometer_poweron_delay : 2U; 248 | uint8_t __reserved__ : 2U; 249 | 250 | MotionDetectionCtrlConfig() { *reinterpret_cast(this) = 0U; } 251 | }; 252 | 253 | MPU_SIZE_CASSERT(MotionDetectionCtrlConfig); 254 | 255 | struct UserCtrlConfig { 256 | bool clear_sensor_register_and_path : 1U; 257 | bool reset_i2c_master : 1U; 258 | bool reset_fifo_buffer : 1U; 259 | uint8_t __reserved1__ : 1U; 260 | bool enable_spi_interface : 1U; 261 | bool i2c_master_mode_enable : 1U; 262 | bool fifo_enable : 1U; 263 | uint8_t __reserved2__ : 1U; 264 | 265 | UserCtrlConfig() { *reinterpret_cast(this) = 0U; } 266 | }; 267 | 268 | MPU_SIZE_CASSERT(UserCtrlConfig); 269 | 270 | struct PowerManagement1_Config { 271 | ClockSource clock_source : 3U; 272 | bool disable_temperature : 1U; 273 | uint8_t __reserved__ : 1U; 274 | bool cycle_sleep : 1U; 275 | bool sleep_mode : 1U; 276 | bool reset_registers : 1U; 277 | 278 | PowerManagement1_Config() { *reinterpret_cast(this) = 0U; } 279 | }; 280 | 281 | MPU_SIZE_CASSERT(PowerManagement1_Config); 282 | 283 | enum struct WakeupFrequency : uint8_t { 284 | F1_25Hz = 0U, 285 | F5Hz = 1U, 286 | F25Hz = 2U, 287 | F40Hz = 3U 288 | }; 289 | 290 | struct PowerManagement2_Config { 291 | bool gyroscope_z_standby : 1U; 292 | bool gyroscope_y_standby : 1U; 293 | bool gyroscope_x_standby : 1U; 294 | bool accelerometer_z_standby : 1U; 295 | bool accelerometer_y_standby : 1U; 296 | bool accelerometer_x_standby : 1U; 297 | WakeupFrequency wakeup_frequency : 2U; 298 | 299 | PowerManagement2_Config() { *reinterpret_cast(this) = 0U; } 300 | }; 301 | 302 | MPU_SIZE_CASSERT(PowerManagement1_Config); 303 | 304 | struct MotionDetectionStatus { 305 | bool zero_motion : 1; 306 | uint8_t __reserved__ : 1; 307 | bool z_positive : 1; 308 | bool z_negative : 1; 309 | bool y_positive : 1; 310 | bool y_negative : 1; 311 | bool x_positive : 1; 312 | bool x_negative : 1; 313 | 314 | MotionDetectionStatus() { *reinterpret_cast(this) = 0U; } 315 | }; 316 | 317 | MPU_SIZE_CASSERT(MotionDetectionStatus); 318 | 319 | }; // namespace mpu60X0 320 | #endif // DRIVERS_MPU60X0_BIT_DEFINITIONS_H_ 321 | -------------------------------------------------------------------------------- /Inc/MPU60X0.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MPU60X0.h 3 | * @author Basit Ayantunde (rlamarrr@gmail.com) 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-08-23 7 | * 8 | * 9 | * @copyright Copyright (c) 2019 Basit Ayantunde 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | * 28 | */ 29 | #ifndef DRIVERS_MPU60X0_MPU60X0_H_ 30 | #define DRIVERS_MPU60X0_MPU60X0_H_ 31 | 32 | #include // NOLINT 33 | #include 34 | #include 35 | 36 | #include 37 | #include 38 | 39 | extern "C" { 40 | // loads dependencies and device definitions for the peripherals 41 | #include "main.h" // NOLINT 42 | 43 | #ifdef STM32F7 44 | #include "stm32f7xx_hal.h" // NOLINT 45 | #include "stm32f7xx_hal_i2c.h" // NOLINT 46 | #include "stm32f7xx_hal_uart.h" // NOLINT 47 | #else 48 | #ifdef STM32F4 49 | #include "stm32f4xx_hal.h" // NOLINT 50 | #include "stm32f4xx_hal_i2c.h" // NOLINT 51 | #include "stm32f4xx_hal_uart.h" // NOLINT 52 | #else 53 | #ifdef STM32F3 54 | #include "stm32f3xx_hal.h" // NOLINT 55 | #include "stm32f3xx_hal_i2c.h" // NOLINT 56 | #include "stm32f3xx_hal_uart.h" // NOLINT 57 | #endif 58 | #endif 59 | #endif 60 | } 61 | 62 | #include "bit_definitions.h" // NOLINT 63 | #include "data_types.h" // NOLINT 64 | #include "registers.h" // NOLINT 65 | 66 | namespace mpu60X0 { 67 | 68 | // TODO(lamarrr): encapsulate this to a source file to prevent user access 69 | #define RETURN_F_IF_ERROR(v) \ 70 | if (v.first != Status::OK) return v.first 71 | #define RETURN_IF_ERROR(v) \ 72 | if (v.first != Status::OK) return v 73 | 74 | enum struct Status : uint8_t { 75 | OK = HAL_StatusTypeDef::HAL_OK, 76 | Error = HAL_StatusTypeDef::HAL_ERROR, 77 | Busy = HAL_StatusTypeDef::HAL_BUSY, 78 | Timeout = HAL_StatusTypeDef::HAL_TIMEOUT, 79 | }; 80 | 81 | template 82 | using Result = std::pair; 83 | 84 | // Blocking master mode API that maximizes utilization of Burst byte Reads 85 | struct MPU60X0 { 86 | using duration_type = std::chrono::duration; 87 | 88 | private: 89 | uint8_t device_address_; 90 | I2C_HandleTypeDef* handle_; 91 | 92 | public: 93 | MPU60X0(uint8_t address, I2C_HandleTypeDef* handle) : handle_{handle} { 94 | device_address_ = address << 1U; 95 | } 96 | 97 | MPU60X0(const MPU60X0&) noexcept {} 98 | MPU60X0(MPU60X0&&) noexcept {} 99 | MPU60X0& operator=(const MPU60X0&) noexcept = default; 100 | MPU60X0& operator=(MPU60X0&&) noexcept = default; 101 | ~MPU60X0() noexcept { 102 | device_address_ = 0U; 103 | handle_ = nullptr; 104 | } 105 | 106 | Status WriteByte_(register_type reg, uint8_t data, 107 | duration_type timeout) noexcept { 108 | uint8_t buffer[2] = {reg, data}; 109 | return static_cast(HAL_I2C_Master_Transmit( 110 | handle_, device_address_, buffer, sizeof(buffer), timeout.count())); 111 | } 112 | 113 | /** 114 | * @brief 115 | * 116 | * @template-parameter ByteRep: 117 | * @parameter reg: 118 | * @parameter b_rep: 119 | * @parameter timeout: 120 | * @returns Status: 121 | */ 122 | template 123 | Status WriteByteAs_(register_type reg, ByteRep b_rep, 124 | duration_type timeout) noexcept { 125 | static_assert(sizeof(ByteRep) == 1U, "Type must be byte sized"); 126 | uint8_t value = reinterpret_cast(b_rep); 127 | printf("[WriteByteAs_] Sending value: %u\n", value); 128 | return WriteByte_(reg, value, timeout); 129 | } 130 | 131 | /** 132 | * @brief 133 | * 134 | * @parameter reg: 135 | * @parameter data: 136 | * @parameter size: 137 | * @parameter timeout: 138 | * @returns Status: 139 | */ 140 | Status BurstWrite_(register_type reg, const uint8_t* data, uint16_t size, 141 | duration_type timeout) noexcept { 142 | return static_cast(HAL_I2C_Master_Transmit( 143 | handle_, device_address_, const_cast(data), size, 144 | timeout.count())); 145 | } 146 | 147 | Result ReadByte_(register_type reg, duration_type timeout) noexcept { 148 | uint8_t data{}; 149 | Status status = static_cast(HAL_I2C_Master_Transmit( 150 | handle_, device_address_, ®, 1, timeout.count())); 151 | 152 | if (status != Status::OK) return std::make_pair(status, data); 153 | 154 | status = static_cast(HAL_I2C_Master_Receive( 155 | handle_, device_address_, &data, 1, timeout.count())); 156 | return std::make_pair(status, data); 157 | } 158 | 159 | template 160 | Result ReadByteAs_(register_type reg, 161 | duration_type timeout) noexcept { 162 | static_assert(sizeof(ByteRep) == 1U, "Type must be byte sized"); 163 | Result data = ReadByte_(reg, timeout); 164 | ByteRep res{}; 165 | *(reinterpret_cast(&res)) = data.second; 166 | 167 | return std::make_pair(data.first, res); 168 | } 169 | 170 | Status BurstRead_(register_type reg, uint8_t* data, uint16_t size, 171 | duration_type timeout) noexcept { 172 | Status status = static_cast(HAL_I2C_Master_Transmit( 173 | handle_, device_address_, ®, 1, timeout.count())); 174 | if (status != Status::OK) return status; 175 | status = static_cast(HAL_I2C_Master_Receive( 176 | handle_, device_address_, data, size, timeout.count())); 177 | return status; 178 | } 179 | 180 | bool Ready(uint32_t trials, duration_type timeout) noexcept { 181 | return HAL_I2C_IsDeviceReady(handle_, device_address_, trials, 182 | timeout.count()) == HAL_OK; 183 | } 184 | 185 | // that the device be configured to use one of the gyroscopes (or an external 186 | // clock source) as the clock reference for improved stability 187 | Status Initialize() { 188 | PowerManagement1_Config cfg{}; 189 | cfg.clock_source = ClockSource::PllGyro_X; 190 | cfg.reset_registers = true; 191 | duration_type timeout = duration_type{250}; 192 | return WritePowerManagement1_Config(cfg, timeout); 193 | } 194 | 195 | /** 196 | * 197 | * 198 | **/ 199 | 200 | Status WriteSelfTestX(uint8_t data, duration_type timeout) noexcept { 201 | return WriteByte_(register_map::SelfTestX, data, timeout); 202 | } 203 | 204 | Result ReadSelfTestX(duration_type timeout) noexcept { 205 | return ReadByte_(register_map::SelfTestX, timeout); 206 | } 207 | 208 | Status WriteSelfTestY(uint8_t data, duration_type timeout) noexcept { 209 | return WriteByte_(register_map::SelfTestY, data, timeout); 210 | } 211 | 212 | Result ReadSelfTestY(duration_type timeout) noexcept { 213 | return ReadByte_(register_map::SelfTestY, timeout); 214 | } 215 | 216 | Status WriteSelfTestZ(uint8_t data, duration_type timeout) noexcept { 217 | return WriteByte_(register_map::SelfTestZ, data, timeout); 218 | } 219 | 220 | Result ReadSelfTestZ(duration_type timeout) noexcept { 221 | return ReadByte_(register_map::SelfTestZ, timeout); 222 | } 223 | 224 | Status WriteSelfTestA(uint8_t data, duration_type timeout) noexcept { 225 | return WriteByte_(register_map::SelfTestA, data, timeout); 226 | } 227 | 228 | Result ReadSelfTestA(duration_type timeout) noexcept { 229 | return ReadByte_(register_map::SelfTestA, timeout); 230 | } 231 | 232 | Result GetGyroscopeX_SelfTestValue(duration_type timeout) noexcept { 233 | Result res = ReadSelfTestX(timeout); 234 | res.second &= 00011111U; 235 | return res; 236 | } 237 | 238 | Result GetGyroscopeY_SelfTestValue(duration_type timeout) noexcept { 239 | Result res = ReadSelfTestY(timeout); 240 | res.second &= 00011111U; 241 | return res; 242 | } 243 | 244 | Result GetGyroscopeZ_SelfTestValue(duration_type timeout) noexcept { 245 | Result res = ReadSelfTestZ(timeout); 246 | res.second &= 00011111U; 247 | return res; 248 | } 249 | 250 | // 5 bit precision 251 | Result GetAccelerometerX_SelfTestValue( 252 | duration_type timeout) noexcept { 253 | Result res_head = ReadSelfTestX(timeout); 254 | 255 | RETURN_IF_ERROR(res_head); 256 | 257 | Result res_tail = ReadSelfTestA(timeout); 258 | res_tail.second = ((res_head.second & 0b11100000U) >> 3U) | 259 | ((res_tail.second & 0b00110000U) >> 4U); 260 | return res_tail; 261 | } 262 | 263 | Result GetAccelerometerY_SelfTestValue( 264 | duration_type timeout) noexcept { 265 | Result res_head = ReadSelfTestY(timeout); 266 | 267 | RETURN_IF_ERROR(res_head); 268 | 269 | Result res_tail = ReadSelfTestA(timeout); 270 | res_tail.second = ((res_head.second & 0b11100000U) >> 3U) | 271 | ((res_tail.second & 0b00001100U) >> 2U); 272 | return res_tail; 273 | } 274 | 275 | Result GetAccelerometerZ_SelfTestValue( 276 | duration_type timeout) noexcept { 277 | Result res_head = ReadSelfTestZ(timeout); 278 | 279 | RETURN_IF_ERROR(res_head); 280 | 281 | Result res_tail = ReadSelfTestA(timeout); 282 | res_tail.second = ((res_head.second & 0b11100000U) >> 3U) | 283 | (res_tail.second & 0b00000011U); 284 | return res_tail; 285 | } 286 | 287 | Status SetGyroscopeX_SelfTestValue(uint8_t data, 288 | duration_type timeout) noexcept { 289 | Result res = ReadSelfTestX(timeout); 290 | 291 | RETURN_F_IF_ERROR(res); 292 | 293 | res.second = (res.second & 0b11100000U) | (0b00011111U & data); 294 | 295 | return WriteSelfTestX(res.second, timeout); 296 | } 297 | 298 | Status SetGyroscopeY_SelfTestValue(uint8_t data, 299 | duration_type timeout) noexcept { 300 | Result res = ReadSelfTestY(timeout); 301 | 302 | RETURN_F_IF_ERROR(res); 303 | 304 | res.second = (res.second & 0b11100000U) | (0b00011111U & data); 305 | 306 | return WriteSelfTestY(res.second, timeout); 307 | } 308 | 309 | Status SetGyroscopeZ_SelfTestValue(uint8_t data, 310 | duration_type timeout) noexcept { 311 | Result res = ReadSelfTestZ(timeout); 312 | 313 | RETURN_F_IF_ERROR(res); 314 | 315 | res.second = (res.second & 0b11100000U) | (0b00011111U & data); 316 | 317 | return WriteSelfTestZ(res.second, timeout); 318 | } 319 | 320 | /** 321 | * @brief 322 | * 323 | * @parameter data: 5 bit value 324 | * @parameter timeout: 325 | * @returns Status: 326 | */ 327 | Status SetAccelerometerX_SelfTestValue(uint8_t data, 328 | duration_type timeout) noexcept { 329 | Result res_head = ReadSelfTestX(timeout); 330 | 331 | RETURN_F_IF_ERROR(res_head); 332 | 333 | res_head.second = 334 | ((data << 3U) & 0b11100000U) | (res_head.second & 0b00011111U); 335 | res_head.first = WriteSelfTestX(res_head.second, timeout); 336 | 337 | RETURN_F_IF_ERROR(res_head); 338 | 339 | res_head = ReadSelfTestA(timeout); 340 | 341 | RETURN_F_IF_ERROR(res_head); 342 | 343 | res_head.second = 344 | ((data << 4) & 0b00110000U) | (res_head.second & 0b11001111U); 345 | 346 | return WriteSelfTestA(res_head.second, timeout); 347 | } 348 | 349 | Status SetAccelerometerY_SelfTestValue(uint8_t data, 350 | duration_type timeout) noexcept { 351 | Result res_head = ReadSelfTestY(timeout); 352 | 353 | RETURN_F_IF_ERROR(res_head); 354 | 355 | res_head.second = 356 | ((data << 3) & 0b11100000U) | (res_head.second & 0b00011111U); 357 | res_head.first = WriteSelfTestY(res_head.second, timeout); 358 | 359 | RETURN_F_IF_ERROR(res_head); 360 | 361 | res_head = ReadSelfTestA(timeout); 362 | 363 | RETURN_F_IF_ERROR(res_head); 364 | 365 | res_head.second = 366 | ((data << 2) & 0b00001100U) | (res_head.second & 0b11110011U); 367 | 368 | return WriteSelfTestA(res_head.second, timeout); 369 | } 370 | 371 | Status SetAccelerometerZ_SelfTestValue(uint8_t data, 372 | duration_type timeout) noexcept { 373 | Result res_head = ReadSelfTestZ(timeout); 374 | 375 | RETURN_F_IF_ERROR(res_head); 376 | 377 | res_head.second = 378 | ((data << 3) & 0b11100000U) | (res_head.second & 0b00011111U); 379 | res_head.first = WriteSelfTestZ(res_head.second, timeout); 380 | 381 | RETURN_F_IF_ERROR(res_head); 382 | 383 | res_head = ReadSelfTestA(timeout); 384 | 385 | RETURN_F_IF_ERROR(res_head); 386 | 387 | res_head.second = (data & 0b00000011U) | (res_head.second & 0b11111100U); 388 | 389 | return WriteSelfTestA(res_head.second, timeout); 390 | } 391 | 392 | /** 393 | * 394 | * 395 | **/ 396 | 397 | Status WriteSampleRateDivider(uint8_t data, duration_type timeout) noexcept { 398 | return WriteByte_(register_map::SampleRateDivider, data, timeout); 399 | } 400 | 401 | Result ReadSampleRateDivider(duration_type timeout) noexcept { 402 | return ReadByte_(register_map::SampleRateDivider, timeout); 403 | } 404 | /** 405 | * 406 | * 407 | **/ 408 | 409 | Status WriteConfig(Config config, duration_type timeout) noexcept { 410 | return WriteByteAs_(register_map::Config, config, timeout); 411 | } 412 | 413 | Result ReadConfig(duration_type timeout) noexcept { 414 | return ReadByteAs_(register_map::Config, timeout); 415 | } 416 | 417 | Status SetExternalFrameSync(FrameSync fsync, duration_type timeout) noexcept { 418 | // 419 | Result conf = ReadConfig(timeout); 420 | 421 | RETURN_F_IF_ERROR(conf); 422 | 423 | conf.second.ext_frame_sync = 424 | static_cast(static_cast(fsync) & 0b111U); 425 | 426 | return WriteConfig(conf.second, timeout); 427 | } 428 | 429 | Status SetDlpfConfig(DlpfConfig dlpf_cfg, duration_type timeout) noexcept { 430 | Result conf = ReadConfig(timeout); 431 | 432 | RETURN_F_IF_ERROR(conf); 433 | 434 | conf.second.dlpf_config = 435 | static_cast(static_cast(dlpf_cfg) & 0b111U); 436 | 437 | return WriteConfig(conf.second, timeout); 438 | } 439 | 440 | Result GetExternalFrameSync(duration_type timeout) noexcept { 441 | Result conf = ReadConfig(timeout); 442 | 443 | return std::make_pair(conf.first, FrameSync{conf.second.ext_frame_sync}); 444 | } 445 | 446 | Result GetDlpfConfig(duration_type timeout) noexcept { 447 | Result conf = ReadConfig(timeout); 448 | 449 | return std::make_pair(conf.first, DlpfConfig{conf.second.dlpf_config}); 450 | } 451 | 452 | /** 453 | * 454 | * 455 | **/ 456 | 457 | Status WriteGyroscopeConfig(GyroscopeConfig gyro_cfg, 458 | duration_type timeout) noexcept { 459 | return WriteByteAs_(register_map::GyroscopeConfig, gyro_cfg, timeout); 460 | } 461 | 462 | Result ReadGyroscopeConfig(duration_type timeout) noexcept { 463 | return ReadByteAs_(register_map::GyroscopeConfig, timeout); 464 | } 465 | 466 | Status SetGyroscopeX_SelfTestState(bool activate, 467 | duration_type timeout) noexcept { 468 | Result res = 469 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 470 | 471 | RETURN_F_IF_ERROR(res); 472 | 473 | res.second.x_self_test = activate; 474 | 475 | return WriteByteAs_(register_map::GyroscopeConfig, 476 | res.second, timeout); 477 | } 478 | 479 | Status SetGyroscopeY_SelfTestState(bool activate, 480 | duration_type timeout) noexcept { 481 | Result res = 482 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 483 | 484 | RETURN_F_IF_ERROR(res); 485 | 486 | res.second.y_self_test = activate; 487 | 488 | return WriteByteAs_(register_map::GyroscopeConfig, 489 | res.second, timeout); 490 | } 491 | 492 | Status SetGyroscopeZ_SelfTestState(bool activate, 493 | duration_type timeout) noexcept { 494 | Result res = 495 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 496 | 497 | RETURN_F_IF_ERROR(res); 498 | 499 | res.second.z_self_test = activate; 500 | 501 | return WriteByteAs_(register_map::GyroscopeConfig, 502 | res.second, timeout); 503 | } 504 | 505 | // 3 bit, x, y, z 506 | Status SetGyroscopeSelfTestStates(uint8_t tri_state, 507 | duration_type timeout) noexcept { 508 | Result res = 509 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 510 | 511 | RETURN_F_IF_ERROR(res); 512 | 513 | res.second.x_self_test = static_cast(0b0000100 & tri_state); 514 | res.second.y_self_test = static_cast(0b0000010 & tri_state); 515 | res.second.z_self_test = static_cast(0b0000001 & tri_state); 516 | 517 | return WriteByteAs_(register_map::GyroscopeConfig, 518 | res.second, timeout); 519 | } 520 | 521 | Status SetGyroscopeFullScaleRange(GyroscopeFullScale full_scale, 522 | duration_type timeout) noexcept { 523 | Result res = 524 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 525 | 526 | RETURN_F_IF_ERROR(res); 527 | 528 | res.second.full_scale = full_scale; 529 | 530 | return WriteByteAs_(register_map::GyroscopeConfig, 531 | res.second, timeout); 532 | } 533 | 534 | Result GetGyroscopeX_SelfTestState(duration_type timeout) noexcept { 535 | Result res = 536 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 537 | 538 | return std::make_pair(res.first, bool{res.second.x_self_test}); 539 | } 540 | 541 | Result GetGyroscopeY_SelfTestState(duration_type timeout) noexcept { 542 | Result res = 543 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 544 | 545 | return std::make_pair(res.first, bool{res.second.y_self_test}); 546 | } 547 | 548 | Result GetGyroscopeZ_SelfTestState(duration_type timeout) noexcept { 549 | Result res = 550 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 551 | 552 | return std::make_pair(res.first, bool{res.second.z_self_test}); 553 | } 554 | 555 | // first bit, second bit, third bit 556 | Result GetGyroscopeSelfTestStates(duration_type timeout) noexcept { 557 | uint8_t data{}; 558 | 559 | Result res = ReadGyroscopeConfig(timeout); 560 | 561 | if (res.first != Status::OK) return std::make_pair(res.first, data); 562 | 563 | data = (static_cast(res.second.x_self_test) << 2U) | 564 | (static_cast(res.second.y_self_test) << 1U) | 565 | static_cast(res.second.z_self_test); 566 | 567 | return std::make_pair(res.first, data); 568 | } 569 | 570 | Result GetGyroscopeFullScaleRange( 571 | duration_type timeout) noexcept { 572 | Result res = 573 | ReadByteAs_(register_map::GyroscopeConfig, timeout); 574 | 575 | return std::make_pair(res.first, GyroscopeFullScale{res.second.full_scale}); 576 | } 577 | 578 | /** 579 | * 580 | * 581 | **/ 582 | 583 | Status WriteAccelerometerConfig(AccelerometerConfig acc_cfg, 584 | duration_type timeout) noexcept { 585 | return WriteByteAs_(register_map::AccelerometerConfig, 586 | acc_cfg, timeout); 587 | } 588 | 589 | Result ReadAccelerometerConfig( 590 | duration_type timeout) noexcept { 591 | return ReadByteAs_(register_map::AccelerometerConfig, 592 | timeout); 593 | } 594 | 595 | Status SetAccelerometerX_SelfTestState(bool activate, 596 | duration_type timeout) noexcept { 597 | Result acc_cfg = ReadAccelerometerConfig(timeout); 598 | 599 | RETURN_F_IF_ERROR(acc_cfg); 600 | 601 | acc_cfg.second.x_self_test = activate; 602 | 603 | return WriteByteAs_(register_map::AccelerometerConfig, 604 | acc_cfg.second, timeout); 605 | } 606 | 607 | Status SetAccelerometerY_SelfTestState(bool activate, 608 | duration_type timeout) noexcept { 609 | Result acc_cfg = ReadAccelerometerConfig(timeout); 610 | 611 | RETURN_F_IF_ERROR(acc_cfg); 612 | 613 | acc_cfg.second.y_self_test = activate; 614 | 615 | return WriteByteAs_(register_map::AccelerometerConfig, 616 | acc_cfg.second, timeout); 617 | } 618 | 619 | Status SetAccelerometerZ_SelfTestState(bool activate, 620 | duration_type timeout) noexcept { 621 | Result acc_cfg = ReadAccelerometerConfig(timeout); 622 | 623 | RETURN_F_IF_ERROR(acc_cfg); 624 | 625 | acc_cfg.second.z_self_test = activate; 626 | 627 | return WriteByteAs_(register_map::AccelerometerConfig, 628 | acc_cfg.second, timeout); 629 | } 630 | 631 | Status SetAccelerometerSelfTestStates(uint8_t tri_state, 632 | duration_type timeout) noexcept { 633 | Result res = ReadByteAs_( 634 | register_map::AccelerometerConfig, timeout); 635 | 636 | RETURN_F_IF_ERROR(res); 637 | 638 | res.second.x_self_test = static_cast(0b0000100 & tri_state); 639 | res.second.y_self_test = static_cast(0b0000010 & tri_state); 640 | res.second.z_self_test = static_cast(0b0000001 & tri_state); 641 | 642 | return WriteByteAs_(register_map::AccelerometerConfig, 643 | res.second, timeout); 644 | } 645 | 646 | Status SetAccelerometerFullScaleRange(AccelerometerFullScale full_scale, 647 | duration_type timeout) noexcept { 648 | Result res = ReadByteAs_( 649 | register_map::AccelerometerConfig, timeout); 650 | 651 | RETURN_F_IF_ERROR(res); 652 | 653 | res.second.full_scale = full_scale; 654 | 655 | return WriteByteAs_(register_map::AccelerometerConfig, 656 | res.second, timeout); 657 | } 658 | 659 | Result GetAccelerometerX_SelfTestState(duration_type timeout) noexcept { 660 | Result res = ReadByteAs_( 661 | register_map::GyroscopeConfig, timeout); 662 | 663 | return std::make_pair(res.first, bool{res.second.x_self_test}); 664 | } 665 | 666 | Result GetAccelerometerY_SelfTestState(duration_type timeout) noexcept { 667 | Result res = ReadByteAs_( 668 | register_map::GyroscopeConfig, timeout); 669 | 670 | return std::make_pair(res.first, bool{res.second.y_self_test}); 671 | } 672 | 673 | Result GetAccelerometerZ_SelfTestState(duration_type timeout) noexcept { 674 | Result res = ReadByteAs_( 675 | register_map::GyroscopeConfig, timeout); 676 | 677 | return std::make_pair(res.first, bool{res.second.z_self_test}); 678 | } 679 | 680 | Result GetAccelerometerSelfTestStates( 681 | duration_type timeout) noexcept { 682 | uint8_t data{}; 683 | 684 | Result res = ReadAccelerometerConfig(timeout); 685 | 686 | if (res.first != Status::OK) return std::make_pair(res.first, data); 687 | 688 | data = (static_cast(res.second.x_self_test) << 2U) | 689 | (static_cast(res.second.y_self_test) << 1U) | 690 | static_cast(res.second.z_self_test); 691 | 692 | return std::make_pair(res.first, data); 693 | } 694 | 695 | Result GetAccelerometerFullScaleRange( 696 | duration_type timeout) noexcept { 697 | Result res = ReadAccelerometerConfig(timeout); 698 | return std::make_pair(res.first, 699 | AccelerometerFullScale{res.second.full_scale}); 700 | } 701 | 702 | /** 703 | * 704 | * 705 | **/ 706 | 707 | Status WriteFreeFallAccelerationThreshold(uint8_t acc_thresh, 708 | duration_type timeout) noexcept { 709 | return WriteByte_(register_map::FreeFallAccelerationThreshold, acc_thresh, 710 | timeout); 711 | } 712 | 713 | Result ReadFreeFallAccelerationThreshold( 714 | duration_type timeout) noexcept { 715 | return ReadByte_(register_map::FreeFallAccelerationThreshold, timeout); 716 | } 717 | 718 | /** 719 | * 720 | * 721 | **/ 722 | 723 | Status WriteFreeFallDuration(uint8_t ff_dur, duration_type timeout) noexcept { 724 | return WriteByte_(register_map::FreeFallDuration, ff_dur, timeout); 725 | } 726 | 727 | Result ReadFreeFallDuration(duration_type timeout) noexcept { 728 | return ReadByte_(register_map::FreeFallDuration, timeout); 729 | } 730 | 731 | /** 732 | * 733 | * 734 | **/ 735 | 736 | Status WriteMotionDetectionThreshold(uint8_t mot_det_thresh, 737 | duration_type timeout) noexcept { 738 | return WriteByte_(register_map::MotionDetectionThreshold, mot_det_thresh, 739 | timeout); 740 | } 741 | 742 | Result ReadMotionDetectionThreshold(duration_type timeout) noexcept { 743 | return ReadByte_(register_map::MotionDetectionThreshold, timeout); 744 | } 745 | 746 | /** 747 | * 748 | * 749 | **/ 750 | 751 | Status WriteMotionDetectionDuration(uint8_t mot_det_dur, 752 | duration_type timeout) noexcept { 753 | return WriteByte_(register_map::MotionDetectionDuration, mot_det_dur, 754 | timeout); 755 | } 756 | 757 | Result ReadMotionDetectionDuration(duration_type timeout) noexcept { 758 | return ReadByte_(register_map::MotionDetectionDuration, timeout); 759 | } 760 | 761 | /** 762 | * 763 | * 764 | **/ 765 | 766 | Status WriteZeroMotionDetectionThreshold(uint8_t mot_det_thresh, 767 | duration_type timeout) noexcept { 768 | return WriteByte_(register_map::MotionDetectionThreshold, mot_det_thresh, 769 | timeout); 770 | } 771 | 772 | Result ReadZeroMotionDetectionThreshold( 773 | duration_type timeout) noexcept { 774 | return ReadByte_(register_map::MotionDetectionThreshold, timeout); 775 | } 776 | 777 | /** 778 | * 779 | * 780 | **/ 781 | 782 | Status WriteZeroMotionDetectionDuration(uint8_t mot_det_dur, 783 | duration_type timeout) noexcept { 784 | return WriteByte_(register_map::MotionDetectionDuration, mot_det_dur, 785 | timeout); 786 | } 787 | 788 | Result ReadZeroMotionDetectionDuration( 789 | duration_type timeout) noexcept { 790 | return ReadByte_(register_map::MotionDetectionDuration, timeout); 791 | } 792 | 793 | /** 794 | * 795 | * 796 | **/ 797 | 798 | Status WriteFifoEnableConfig(FifoEnableConfig fifo_en_cfg, 799 | duration_type timeout) noexcept { 800 | return WriteByteAs_(register_map::FifoEnable, fifo_en_cfg, 801 | timeout); 802 | } 803 | 804 | Result ReadFifoEnableConfig( 805 | duration_type timeout) noexcept { 806 | return ReadByteAs_(register_map::FifoEnable, timeout); 807 | } 808 | 809 | Status SetTemperatureFifoEnable(bool enable, duration_type timeout) noexcept { 810 | Result res = ReadFifoEnableConfig(timeout); 811 | 812 | RETURN_F_IF_ERROR(res); 813 | 814 | res.second.enable_temperature_fifo = enable; 815 | 816 | return WriteFifoEnableConfig(res.second, timeout); 817 | } 818 | 819 | Status SetGyroscopeX_FifoEnable(bool enable, duration_type timeout) noexcept { 820 | Result res = ReadFifoEnableConfig(timeout); 821 | 822 | RETURN_F_IF_ERROR(res); 823 | 824 | res.second.enable_gyroscope_x_fifo = enable; 825 | 826 | return WriteFifoEnableConfig(res.second, timeout); 827 | } 828 | 829 | Status SetGyroscopeY_FifoEnable(bool enable, duration_type timeout) noexcept { 830 | Result res = ReadFifoEnableConfig(timeout); 831 | 832 | RETURN_F_IF_ERROR(res); 833 | 834 | res.second.enable_gyroscope_y_fifo = enable; 835 | 836 | return WriteFifoEnableConfig(res.second, timeout); 837 | } 838 | 839 | Status SetGyroscopeZ_FifoEnable(bool enable, duration_type timeout) noexcept { 840 | Result res = ReadFifoEnableConfig(timeout); 841 | 842 | RETURN_F_IF_ERROR(res); 843 | 844 | res.second.enable_gyroscope_z_fifo = enable; 845 | 846 | return WriteFifoEnableConfig(res.second, timeout); 847 | } 848 | 849 | Status SetAccelerometerFifoEnable(bool enable, 850 | duration_type timeout) noexcept { 851 | Result res = ReadFifoEnableConfig(timeout); 852 | 853 | RETURN_F_IF_ERROR(res); 854 | 855 | res.second.enable_acceleration_fifo = enable; 856 | 857 | return WriteFifoEnableConfig(res.second, timeout); 858 | } 859 | 860 | Status SetSlave2_FifoEnable(bool enable, duration_type timeout) noexcept { 861 | Result res = ReadFifoEnableConfig(timeout); 862 | 863 | RETURN_F_IF_ERROR(res); 864 | 865 | res.second.enable_slave2_fifo = enable; 866 | 867 | return WriteFifoEnableConfig(res.second, timeout); 868 | } 869 | 870 | Status SetSlave1_FifoEnable(bool enable, duration_type timeout) noexcept { 871 | Result res = ReadFifoEnableConfig(timeout); 872 | 873 | RETURN_F_IF_ERROR(res); 874 | 875 | res.second.enable_slave1_fifo = enable; 876 | 877 | return WriteFifoEnableConfig(res.second, timeout); 878 | } 879 | 880 | Status SetSlave0_FifoEnable(bool enable, duration_type timeout) noexcept { 881 | Result res = ReadFifoEnableConfig(timeout); 882 | 883 | RETURN_F_IF_ERROR(res); 884 | 885 | res.second.enable_slave0_fifo = enable; 886 | 887 | return WriteFifoEnableConfig(res.second, timeout); 888 | } 889 | 890 | Result GetTemperatureFifoEnable(duration_type timeout) noexcept { 891 | Result res = ReadFifoEnableConfig(timeout); 892 | return std::make_pair(res.first, bool{res.second.enable_temperature_fifo}); 893 | } 894 | 895 | Result GetGyroscopeX_FifoEnable(duration_type timeout) noexcept { 896 | Result res = ReadFifoEnableConfig(timeout); 897 | return std::make_pair(res.first, bool{res.second.enable_gyroscope_x_fifo}); 898 | } 899 | 900 | Result GetGyroscopeY_FifoEnable(duration_type timeout) noexcept { 901 | Result res = ReadFifoEnableConfig(timeout); 902 | return std::make_pair(res.first, bool{res.second.enable_gyroscope_y_fifo}); 903 | } 904 | 905 | Result GetGyroscopeZ_FifoEnable(duration_type timeout) noexcept { 906 | Result res = ReadFifoEnableConfig(timeout); 907 | return std::make_pair(res.first, bool{res.second.enable_gyroscope_z_fifo}); 908 | } 909 | 910 | Result GetAccelerometerFifoEnable(duration_type timeout) noexcept { 911 | Result res = ReadFifoEnableConfig(timeout); 912 | return std::make_pair(res.first, bool{res.second.enable_acceleration_fifo}); 913 | } 914 | 915 | Result GetSlave2_FifoEnable(duration_type timeout) noexcept { 916 | Result res = ReadFifoEnableConfig(timeout); 917 | return std::make_pair(res.first, bool{res.second.enable_slave2_fifo}); 918 | } 919 | 920 | Result GetSlave1_FifoEnable(duration_type timeout) noexcept { 921 | Result res = ReadFifoEnableConfig(timeout); 922 | return std::make_pair(res.first, bool{res.second.enable_slave1_fifo}); 923 | } 924 | 925 | Result GetSlave0_FifoEnable(duration_type timeout) noexcept { 926 | Result res = ReadFifoEnableConfig(timeout); 927 | return std::make_pair(res.first, bool{res.second.enable_slave0_fifo}); 928 | } 929 | 930 | /** 931 | * 932 | * 933 | **/ 934 | 935 | Status WriteI2cMasterCtrlConfig(I2cMasterCtrlConfig mast_cfg, 936 | duration_type timeout) noexcept { 937 | return WriteByteAs_(register_map::I2cMasterCtrl, 938 | mast_cfg, timeout); 939 | } 940 | 941 | Result ReadI2cMasterCtrlConfig( 942 | duration_type timeout) noexcept { 943 | return ReadByteAs_(register_map::I2cMasterCtrl, 944 | timeout); 945 | } 946 | 947 | Status SetMultiMasterEnable(bool enable, duration_type timeout) noexcept { 948 | Result res = ReadI2cMasterCtrlConfig(timeout); 949 | 950 | res.second.enable_multi_master = enable; 951 | 952 | return WriteByteAs_(register_map::I2cMasterCtrl, 953 | res.second, timeout); 954 | } 955 | 956 | // DRI - Data ready Interrupt 957 | Status SetDRI_AwaitExtSensorData(bool enable, 958 | duration_type timeout) noexcept { 959 | Result res = ReadI2cMasterCtrlConfig(timeout); 960 | 961 | res.second.dri_await_ext_sensor_data = enable; 962 | 963 | return WriteByteAs_(register_map::I2cMasterCtrl, 964 | res.second, timeout); 965 | } 966 | 967 | Status SetSlave3_FifoEnable(bool enable, duration_type timeout) noexcept { 968 | Result res = ReadI2cMasterCtrlConfig(timeout); 969 | 970 | res.second.enable_slave3_fifo = enable; 971 | 972 | return WriteByteAs_(register_map::I2cMasterCtrl, 973 | res.second, timeout); 974 | } 975 | 976 | Status SetI2cMasterReadWriteTransition(I2cMasterReadWriteTransition rw_trans, 977 | duration_type timeout) noexcept { 978 | Result res = ReadI2cMasterCtrlConfig(timeout); 979 | 980 | res.second.rw_transition = static_cast( 981 | static_cast(rw_trans) & 0b1U); 982 | 983 | return WriteByteAs_(register_map::I2cMasterCtrl, 984 | res.second, timeout); 985 | } 986 | 987 | Status SetI2cMasterClockSpeed(I2cMasterClockSpeed clock_speed, 988 | duration_type timeout) noexcept { 989 | Result res = ReadI2cMasterCtrlConfig(timeout); 990 | 991 | res.second.clock_speed = static_cast( 992 | static_cast(clock_speed) & 0b1111U); 993 | 994 | return WriteByteAs_(register_map::I2cMasterCtrl, 995 | res.second, timeout); 996 | } 997 | 998 | Result GetMultiMasterEnable(duration_type timeout) noexcept { 999 | Result res = ReadI2cMasterCtrlConfig(timeout); 1000 | 1001 | return std::make_pair(res.first, bool{res.second.enable_multi_master}); 1002 | } 1003 | 1004 | Result GetDRI_AwaitExtSensorData(duration_type timeout) noexcept { 1005 | Result res = ReadI2cMasterCtrlConfig(timeout); 1006 | 1007 | return std::make_pair(res.first, 1008 | bool{res.second.dri_await_ext_sensor_data}); 1009 | } 1010 | 1011 | Result GetSlave3_FifoEnable(duration_type timeout) noexcept { 1012 | Result res = ReadI2cMasterCtrlConfig(timeout); 1013 | 1014 | return std::make_pair(res.first, bool{res.second.enable_slave3_fifo}); 1015 | } 1016 | 1017 | Result GetI2cMasterReadWriteTransition( 1018 | duration_type timeout) noexcept { 1019 | Result res = ReadI2cMasterCtrlConfig(timeout); 1020 | 1021 | return std::make_pair( 1022 | res.first, I2cMasterReadWriteTransition{res.second.rw_transition}); 1023 | } 1024 | 1025 | Result GetI2cMasterClockSpeed( 1026 | duration_type timeout) noexcept { 1027 | Result res = ReadI2cMasterCtrlConfig(timeout); 1028 | 1029 | return std::make_pair(res.first, 1030 | I2cMasterClockSpeed{res.second.clock_speed}); 1031 | } 1032 | 1033 | /** 1034 | * 1035 | * 1036 | **/ 1037 | 1038 | /** 1039 | * 1040 | * 1041 | **/ 1042 | 1043 | /** 1044 | * 1045 | * 1046 | **/ 1047 | 1048 | /** 1049 | * 1050 | * 1051 | **/ 1052 | 1053 | /** 1054 | * 1055 | * 1056 | **/ 1057 | 1058 | Status WriteInterruptPinConfig(InterruptPinConfig config, 1059 | duration_type timeout) noexcept { 1060 | return WriteByteAs_(register_map::InterruptPinConfig, 1061 | config, timeout); 1062 | } 1063 | 1064 | Result ReadInterruptPinConfig( 1065 | duration_type timeout) noexcept { 1066 | return ReadByteAs_(register_map::InterruptPinConfig, 1067 | timeout); 1068 | } 1069 | 1070 | /** 1071 | * 1072 | * 1073 | **/ 1074 | 1075 | Status WriteInterruptEnableConfig(InterruptEnableConfig int_en_cfg, 1076 | duration_type timeout) noexcept { 1077 | return WriteByteAs_(register_map::InterruptEnable, 1078 | int_en_cfg, timeout); 1079 | } 1080 | 1081 | Result ReadInterruptEnableConfig( 1082 | duration_type timeout) noexcept { 1083 | return ReadByteAs_(register_map::InterruptEnable, 1084 | timeout); 1085 | } 1086 | 1087 | Status SetFreeFallDetectionInterruptEnable(bool enable, 1088 | duration_type timeout) noexcept { 1089 | Result res = ReadInterruptEnableConfig(timeout); 1090 | 1091 | RETURN_F_IF_ERROR(res); 1092 | 1093 | res.second.enable_freefall_detection_interrupt = enable; 1094 | return WriteInterruptEnableConfig(res.second, timeout); 1095 | } 1096 | 1097 | Status SetMotionDetectionInterruptEnable(bool enable, 1098 | duration_type timeout) noexcept { 1099 | Result res = ReadInterruptEnableConfig(timeout); 1100 | 1101 | RETURN_F_IF_ERROR(res); 1102 | 1103 | res.second.enable_motion_detection_interrupt = enable; 1104 | 1105 | return WriteInterruptEnableConfig(res.second, timeout); 1106 | } 1107 | 1108 | Status SetZeroMotionDetectionInterruptEnable(bool enable, 1109 | duration_type timeout) noexcept { 1110 | Result res = ReadInterruptEnableConfig(timeout); 1111 | 1112 | RETURN_F_IF_ERROR(res); 1113 | 1114 | res.second.enable_zero_motion_detection_interrupt = enable; 1115 | return WriteInterruptEnableConfig(res.second, timeout); 1116 | } 1117 | 1118 | Status SetFifoOverflowInterruptEnable(bool enable, 1119 | duration_type timeout) noexcept { 1120 | Result res = ReadInterruptEnableConfig(timeout); 1121 | 1122 | RETURN_F_IF_ERROR(res); 1123 | 1124 | res.second.fifo_overflow_interrupt_enable = enable; 1125 | return WriteInterruptEnableConfig(res.second, timeout); 1126 | } 1127 | 1128 | Status SetI2cMasterInterruptEnable(bool enable, 1129 | duration_type timeout) noexcept { 1130 | Result res = ReadInterruptEnableConfig(timeout); 1131 | 1132 | RETURN_F_IF_ERROR(res); 1133 | 1134 | res.second.i2c_master_interrupt_enable = enable; 1135 | 1136 | return WriteInterruptEnableConfig(res.second, timeout); 1137 | } 1138 | 1139 | Status SetDataReadyInterruptEnable(bool enable, 1140 | duration_type timeout) noexcept { 1141 | Result res = ReadInterruptEnableConfig(timeout); 1142 | 1143 | RETURN_F_IF_ERROR(res); 1144 | 1145 | res.second.data_ready_interrupt_enable = enable; 1146 | 1147 | return WriteInterruptEnableConfig(res.second, timeout); 1148 | } 1149 | 1150 | Result GetFreeFallDetectionInterruptEnable( 1151 | duration_type timeout) noexcept { 1152 | Result res = ReadInterruptEnableConfig(timeout); 1153 | return std::make_pair(res.first, 1154 | bool{res.second.enable_freefall_detection_interrupt}); 1155 | } 1156 | 1157 | Result GetMotionDetectionInterruptEnable( 1158 | duration_type timeout) noexcept { 1159 | Result res = ReadInterruptEnableConfig(timeout); 1160 | return std::make_pair(res.first, 1161 | bool{res.second.enable_motion_detection_interrupt}); 1162 | } 1163 | 1164 | Result GetZeroMotionDetectionInterruptEnable( 1165 | duration_type timeout) noexcept { 1166 | Result res = ReadInterruptEnableConfig(timeout); 1167 | return std::make_pair( 1168 | res.first, bool{res.second.enable_zero_motion_detection_interrupt}); 1169 | } 1170 | 1171 | Result GetFifoOverflowInterruptEnable(duration_type timeout) noexcept { 1172 | Result res = ReadInterruptEnableConfig(timeout); 1173 | return std::make_pair(res.first, 1174 | bool{res.second.fifo_overflow_interrupt_enable}); 1175 | } 1176 | 1177 | Result GetI2cMasterInterruptEnable(duration_type timeout) noexcept { 1178 | Result res = ReadInterruptEnableConfig(timeout); 1179 | return std::make_pair(res.first, 1180 | bool{res.second.i2c_master_interrupt_enable}); 1181 | } 1182 | 1183 | Result GetDataReadyInterruptEnable(duration_type timeout) noexcept { 1184 | Result res = ReadInterruptEnableConfig(timeout); 1185 | return std::make_pair(res.first, 1186 | bool{res.second.data_ready_interrupt_enable}); 1187 | } 1188 | 1189 | /** 1190 | * 1191 | * 1192 | **/ 1193 | 1194 | Result ReadInterruptStatus(duration_type timeout) noexcept { 1195 | return ReadByteAs_(register_map::InterruptStatus, timeout); 1196 | } 1197 | 1198 | Result GetFreeFallDetectionInterruptState( 1199 | duration_type timeout) noexcept { 1200 | Result res = ReadInterruptStatus(timeout); 1201 | return std::make_pair(res.first, bool{res.second.free_fall_detected}); 1202 | } 1203 | 1204 | Result GetMotionInterruptState(duration_type timeout) noexcept { 1205 | Result res = ReadInterruptStatus(timeout); 1206 | return std::make_pair(res.first, bool{res.second.motion_detected}); 1207 | } 1208 | 1209 | Result GetZeroMotionInterruptState(duration_type timeout) noexcept { 1210 | Result res = ReadInterruptStatus(timeout); 1211 | return std::make_pair(res.first, bool{res.second.zero_motion_detected}); 1212 | } 1213 | 1214 | Result GetFifoOverflowInterruptState(duration_type timeout) noexcept { 1215 | Result res = ReadInterruptStatus(timeout); 1216 | return std::make_pair(res.first, bool{res.second.fifo_overflow}); 1217 | } 1218 | 1219 | Result GetI2cMasterInterruptState(duration_type timeout) noexcept { 1220 | Result res = ReadInterruptStatus(timeout); 1221 | return std::make_pair(res.first, bool{res.second.i2c_master_interrupt}); 1222 | } 1223 | 1224 | Result GetDataReadyInterruptState(duration_type timeout) noexcept { 1225 | Result res = ReadInterruptStatus(timeout); 1226 | return std::make_pair(res.first, bool{res.second.data_ready}); 1227 | } 1228 | 1229 | /** 1230 | * 1231 | * 1232 | **/ 1233 | 1234 | Result ReadAccelerometerX(duration_type timeout) noexcept { 1235 | uint8_t data[2]{}; 1236 | Status status = BurstRead_(register_map::AccelerometerX_OutH, data, 1237 | sizeof(data), timeout); 1238 | int16_t a_x = 1239 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1240 | return std::make_pair(status, a_x); 1241 | } 1242 | 1243 | Result ReadAccelerometerY(duration_type timeout) noexcept { 1244 | uint8_t data[2]{}; 1245 | 1246 | Status status = BurstRead_(register_map::AccelerometerY_OutH, data, 1247 | sizeof(data), timeout); 1248 | int16_t a_y = 1249 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1250 | return std::make_pair(status, a_y); 1251 | } 1252 | 1253 | Result ReadAccelerometerZ(duration_type timeout) noexcept { 1254 | uint8_t data[2]{}; 1255 | Status status = BurstRead_(register_map::AccelerometerZ_OutH, data, 1256 | sizeof(data), timeout); 1257 | int16_t a_z = 1258 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1259 | 1260 | return std::make_pair(status, a_z); 1261 | } 1262 | 1263 | Result ReadAccelerometer(duration_type timeout) noexcept { 1264 | uint8_t data[2 * 3]; 1265 | Status status = BurstRead_(register_map::AccelerometerX_OutH, data, 1266 | sizeof(data), timeout); 1267 | TriAxialData a; 1268 | a.x = (static_cast(data[0]) << 8) | 1269 | (static_cast(data[1])); 1270 | a .y = (static_cast(data[2]) << 8) | 1271 | (static_cast(data[3])); 1272 | a.z = (static_cast(data[4]) << 8) | 1273 | (static_cast(data[5])); 1274 | return std::make_pair(status, a); 1275 | } 1276 | 1277 | Result ReadAccelerometerXY(duration_type timeout) noexcept { 1278 | uint8_t data[2 * 2]{}; 1279 | 1280 | Status status = BurstRead_(register_map::AccelerometerX_OutH, data, 1281 | sizeof(data), timeout); 1282 | BiAxialData a_xy; 1283 | a_xy.a = (static_cast(data[0]) << 8) | 1284 | (static_cast(data[1])), 1285 | a_xy.b = (static_cast(data[1]) << 8) | 1286 | (static_cast(data[2])); 1287 | return std::make_pair(status, a_xy); 1288 | } 1289 | 1290 | Result ReadAccelerometerYZ(duration_type timeout) noexcept { 1291 | uint8_t data[2 * 2]{}; 1292 | 1293 | Status status = BurstRead_(register_map::AccelerometerY_OutH, data, 1294 | sizeof(data), timeout); 1295 | BiAxialData a_yz; 1296 | a_yz.a = (static_cast(data[0]) << 8) | 1297 | (static_cast(data[1])); 1298 | a_yz.b = (static_cast(data[1]) << 8) | 1299 | (static_cast(data[2])); 1300 | 1301 | return std::make_pair(status, a_yz); 1302 | } 1303 | 1304 | /** 1305 | * 1306 | * 1307 | **/ 1308 | 1309 | Result ReadTemperature(duration_type timeout) noexcept { 1310 | uint8_t data[2]{}; 1311 | 1312 | Status status = 1313 | BurstRead_(register_map::TemperatureOutH, data, sizeof(data), timeout); 1314 | 1315 | int16_t temp = 1316 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1317 | 1318 | return std::make_pair(status, temp); 1319 | } 1320 | 1321 | /** 1322 | * 1323 | * 1324 | **/ 1325 | 1326 | Result ReadGyroscopeX(duration_type timeout) noexcept { 1327 | uint8_t data[2]{}; 1328 | Status status = 1329 | BurstRead_(register_map::GyroscopeX_OutH, data, sizeof(data), timeout); 1330 | int16_t gx = 1331 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1332 | return std::make_pair(status, gx); 1333 | } 1334 | 1335 | Result ReadGyroscopeY(duration_type timeout) noexcept { 1336 | uint8_t data[2]{}; 1337 | Status status = 1338 | BurstRead_(register_map::GyroscopeY_OutH, data, sizeof(data), timeout); 1339 | int16_t gy = 1340 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1341 | 1342 | return std::make_pair(status, gy); 1343 | } 1344 | 1345 | Result ReadGyroscopeZ(duration_type timeout) noexcept { 1346 | uint8_t data[2]{}; 1347 | Status status = 1348 | BurstRead_(register_map::GyroscopeZ_OutH, data, sizeof(data), timeout); 1349 | int16_t gz = 1350 | (static_cast(data[0]) << 8) | (static_cast(data[1])); 1351 | 1352 | return std::make_pair(status, gz); 1353 | } 1354 | 1355 | Result ReadGyroscope(duration_type timeout) noexcept { 1356 | uint8_t data[2 * 3]{}; 1357 | Status status = 1358 | BurstRead_(register_map::GyroscopeX_OutH, data, sizeof(data), timeout); 1359 | TriAxialData g; 1360 | g.x = (static_cast(data[0]) << 8) | 1361 | (static_cast(data[1])); 1362 | g.y = (static_cast(data[2]) << 8) | 1363 | (static_cast(data[3])); 1364 | g.z = (static_cast(data[4]) << 8) | 1365 | (static_cast(data[5])); 1366 | return std::make_pair(status, g); 1367 | } 1368 | 1369 | Result ReadGyroscopeXY(duration_type timeout) noexcept { 1370 | uint8_t data[2 * 2]{}; 1371 | Status status = 1372 | BurstRead_(register_map::GyroscopeX_OutH, data, sizeof(data), timeout); 1373 | BiAxialData xy; 1374 | xy.a = (static_cast(data[0]) << 8) | 1375 | (static_cast(data[1])); 1376 | xy.b = (static_cast(data[1]) << 8) | 1377 | (static_cast(data[2])); 1378 | 1379 | return std::make_pair(status, xy); 1380 | } 1381 | 1382 | Result ReadGyroscopeYZ(duration_type timeout) noexcept { 1383 | uint8_t data[2 * 2]{}; 1384 | Status status = 1385 | BurstRead_(register_map::GyroscopeY_OutH, data, sizeof(data), timeout); 1386 | BiAxialData yz; 1387 | yz.a = (static_cast(data[0]) << 8) | 1388 | (static_cast(data[1])); 1389 | yz.b = (static_cast(data[1]) << 8) | 1390 | (static_cast(data[2])); 1391 | 1392 | return std::make_pair(status, yz); 1393 | } 1394 | 1395 | /** 1396 | * 1397 | * 1398 | **/ 1399 | 1400 | Result ReadExternalSensorData(uint8_t sensor_data_index, 1401 | duration_type timeout) noexcept { 1402 | // TODO(lamarrr): find a better implementation with bound checking 1403 | return ReadByte_(register_map::ExternalSensorData0 + sensor_data_index, 1404 | timeout); 1405 | } 1406 | 1407 | /** 1408 | * 1409 | * 1410 | **/ 1411 | 1412 | Result ReadMotionDetectionStatus( 1413 | duration_type timeout) noexcept { 1414 | return ReadByteAs_( 1415 | register_map::MotionDetectionStatus, timeout); 1416 | } 1417 | 1418 | Result GetNegativeX_MotionDetected(duration_type timeout) noexcept { 1419 | Result res = ReadByteAs_( 1420 | register_map::MotionDetectionStatus, timeout); 1421 | 1422 | return std::make_pair(res.first, bool{res.second.x_negative}); 1423 | } 1424 | Result GetPositiveX_MotionDetected(duration_type timeout) noexcept { 1425 | Result res = ReadByteAs_( 1426 | register_map::MotionDetectionStatus, timeout); 1427 | 1428 | return std::make_pair(res.first, bool{res.second.x_positive}); 1429 | } 1430 | 1431 | Result GetNegativeY_MotionDetected(duration_type timeout) noexcept { 1432 | Result res = ReadByteAs_( 1433 | register_map::MotionDetectionStatus, timeout); 1434 | 1435 | return std::make_pair(res.first, bool{res.second.y_negative}); 1436 | } 1437 | 1438 | Result GetPositiveY_MotionDetected(duration_type timeout) noexcept { 1439 | Result res = ReadByteAs_( 1440 | register_map::MotionDetectionStatus, timeout); 1441 | 1442 | return std::make_pair(res.first, bool{res.second.y_positive}); 1443 | } 1444 | 1445 | Result GetNegativeZ_MotionDetected(duration_type timeout) noexcept { 1446 | Result res = ReadByteAs_( 1447 | register_map::MotionDetectionStatus, timeout); 1448 | 1449 | return std::make_pair(res.first, bool{res.second.z_negative}); 1450 | } 1451 | 1452 | Result GetPositiveZ_MotionDetected(duration_type timeout) noexcept { 1453 | Result res = ReadByteAs_( 1454 | register_map::MotionDetectionStatus, timeout); 1455 | 1456 | return std::make_pair(res.first, bool{res.second.z_positive}); 1457 | } 1458 | 1459 | Result GetZeroMotionDetected(duration_type timeout) noexcept { 1460 | Result res = ReadByteAs_( 1461 | register_map::MotionDetectionStatus, timeout); 1462 | return std::make_pair(res.first, bool{res.second.zero_motion}); 1463 | } 1464 | 1465 | /** 1466 | * 1467 | * 1468 | **/ 1469 | 1470 | Status WriteI2cSlave0_DataOut(uint8_t data, duration_type timeout) noexcept { 1471 | return WriteByte_(register_map::I2cSlave0_DataOut, data, timeout); 1472 | } 1473 | 1474 | Result ReadI2cSlave0_DataOut(duration_type timeout) noexcept { 1475 | return ReadByte_(register_map::I2cSlave0_DataOut, timeout); 1476 | } 1477 | 1478 | Status WriteI2cSlave1_DataOut(uint8_t data, duration_type timeout) noexcept { 1479 | return WriteByte_(register_map::I2cSlave1_DataOut, data, timeout); 1480 | } 1481 | 1482 | Result ReadI2cSlave1_DataOut(duration_type timeout) noexcept { 1483 | return ReadByte_(register_map::I2cSlave1_DataOut, timeout); 1484 | } 1485 | 1486 | Status WriteI2cSlave2_DataOut(uint8_t data, duration_type timeout) noexcept { 1487 | return WriteByte_(register_map::I2cSlave2_DataOut, data, timeout); 1488 | } 1489 | 1490 | Result ReadI2cSlave2_DataOut(duration_type timeout) noexcept { 1491 | return ReadByte_(register_map::I2cSlave2_DataOut, timeout); 1492 | } 1493 | 1494 | Status WriteI2cSlave3_DataOut(uint8_t data, duration_type timeout) noexcept { 1495 | return WriteByte_(register_map::I2cSlave3_DataOut, data, timeout); 1496 | } 1497 | 1498 | Result ReadI2cSlave3_DataOut(duration_type timeout) noexcept { 1499 | return ReadByte_(register_map::I2cSlave3_DataOut, timeout); 1500 | } 1501 | 1502 | /** 1503 | * 1504 | * 1505 | **/ 1506 | 1507 | Status WriteI2cMasterDelayCtrlConfig(I2cMasterDelayCtrlConfig ctrl_cfg, 1508 | duration_type timeout) noexcept { 1509 | return WriteByteAs_( 1510 | register_map::I2cMasterDelayControl, ctrl_cfg, timeout); 1511 | } 1512 | 1513 | Result ReadI2cMasterDelayCtrlConfig( 1514 | duration_type timeout) noexcept { 1515 | return ReadByteAs_( 1516 | register_map::I2cMasterDelayControl, timeout); 1517 | } 1518 | 1519 | /** 1520 | * 1521 | * 1522 | **/ 1523 | 1524 | Status WriteSignalPathResetConfig(SignalPathResetConfig spr_cfg, 1525 | duration_type timeout) noexcept { 1526 | return WriteByteAs_(register_map::SignalPathReset, 1527 | spr_cfg, timeout); 1528 | } 1529 | 1530 | Result ReadSignalPathResetConfig( 1531 | duration_type timeout) noexcept { 1532 | return ReadByteAs_(register_map::SignalPathReset, 1533 | timeout); 1534 | } 1535 | 1536 | Status SetGyroscopeSignalPathReset(bool reset, 1537 | duration_type timeout) noexcept { 1538 | Result cfg = ReadSignalPathResetConfig(timeout); 1539 | 1540 | RETURN_F_IF_ERROR(cfg); 1541 | 1542 | cfg.second.gyroscope_reset = reset; 1543 | return WriteSignalPathResetConfig(cfg.second, timeout); 1544 | } 1545 | 1546 | Status SetAccelerometerSignalPathReset(bool reset, 1547 | duration_type timeout) noexcept { 1548 | Result cfg = ReadSignalPathResetConfig(timeout); 1549 | 1550 | RETURN_F_IF_ERROR(cfg); 1551 | 1552 | cfg.second.accelerometer_reset = reset; 1553 | return WriteSignalPathResetConfig(cfg.second, timeout); 1554 | } 1555 | 1556 | Status SetTemperatureSignalPathReset(bool reset, 1557 | duration_type timeout) noexcept { 1558 | Result cfg = ReadSignalPathResetConfig(timeout); 1559 | 1560 | RETURN_F_IF_ERROR(cfg); 1561 | 1562 | cfg.second.temperature_reset = reset; 1563 | return WriteSignalPathResetConfig(cfg.second, timeout); 1564 | } 1565 | 1566 | Result GetGyroscopeSignalPathReset(duration_type timeout) noexcept { 1567 | Result cfg = ReadSignalPathResetConfig(timeout); 1568 | 1569 | return std::make_pair(cfg.first, bool{cfg.second.gyroscope_reset}); 1570 | } 1571 | 1572 | Result GetAccelerometerSignalPathReset(duration_type timeout) noexcept { 1573 | Result cfg = ReadSignalPathResetConfig(timeout); 1574 | 1575 | return std::make_pair(cfg.first, bool{cfg.second.accelerometer_reset}); 1576 | } 1577 | 1578 | Result GetTemperatureSignalPathReset(duration_type timeout) noexcept { 1579 | Result cfg = ReadSignalPathResetConfig(timeout); 1580 | 1581 | return std::make_pair(cfg.first, bool{cfg.second.temperature_reset}); 1582 | } 1583 | 1584 | /** 1585 | * 1586 | * 1587 | **/ 1588 | 1589 | Status WriteMotionDetectionCtrlConfig(MotionDetectionCtrlConfig cfg, 1590 | duration_type timeout) noexcept { 1591 | return WriteByteAs_( 1592 | register_map::MotionDetectionControl, cfg, timeout); 1593 | } 1594 | 1595 | Result GetMotionDetectionCtrlConfig( 1596 | MotionDetectionCtrlConfig, duration_type timeout) noexcept { 1597 | return ReadByteAs_( 1598 | register_map::MotionDetectionControl, timeout); 1599 | } 1600 | 1601 | /** 1602 | * 1603 | * 1604 | **/ 1605 | 1606 | Status WriteUserCtrlConfig(UserCtrlConfig cfg, 1607 | duration_type timeout) noexcept { 1608 | return WriteByteAs_(register_map::UserControl, cfg, 1609 | timeout); 1610 | } 1611 | 1612 | Result ReadUserCtrlConfig(duration_type timeout) noexcept { 1613 | return ReadByteAs_(register_map::UserControl, timeout); 1614 | } 1615 | 1616 | Status SetFifoEnable(bool enable, duration_type timeout) noexcept { 1617 | Result cfg = ReadUserCtrlConfig(timeout); 1618 | 1619 | RETURN_F_IF_ERROR(cfg); 1620 | 1621 | cfg.second.fifo_enable = enable; 1622 | 1623 | return WriteUserCtrlConfig(cfg.second, timeout); 1624 | } 1625 | 1626 | Status SetI2cMasterEnable(bool enable, duration_type timeout) noexcept { 1627 | Result cfg = ReadUserCtrlConfig(timeout); 1628 | 1629 | RETURN_F_IF_ERROR(cfg); 1630 | 1631 | cfg.second.i2c_master_mode_enable = enable; 1632 | 1633 | return WriteUserCtrlConfig(cfg.second, timeout); 1634 | } 1635 | 1636 | Status SetUseSpiInterface(bool enable, duration_type timeout) noexcept { 1637 | Result cfg = ReadUserCtrlConfig(timeout); 1638 | 1639 | RETURN_F_IF_ERROR(cfg); 1640 | 1641 | cfg.second.enable_spi_interface = enable; 1642 | 1643 | return WriteUserCtrlConfig(cfg.second, timeout); 1644 | } 1645 | 1646 | Status SetFifoReset(bool enable, duration_type timeout) noexcept { 1647 | Result cfg = ReadUserCtrlConfig(timeout); 1648 | 1649 | RETURN_F_IF_ERROR(cfg); 1650 | 1651 | cfg.second.reset_fifo_buffer = enable; 1652 | 1653 | return WriteUserCtrlConfig(cfg.second, timeout); 1654 | } 1655 | 1656 | Status SetI2cMasterReset(bool enable, duration_type timeout) noexcept { 1657 | Result cfg = ReadUserCtrlConfig(timeout); 1658 | 1659 | RETURN_F_IF_ERROR(cfg); 1660 | 1661 | cfg.second.reset_i2c_master = enable; 1662 | 1663 | return WriteUserCtrlConfig(cfg.second, timeout); 1664 | } 1665 | 1666 | Status SetSignalPathReset(bool enable, duration_type timeout) noexcept { 1667 | Result cfg = ReadUserCtrlConfig(timeout); 1668 | 1669 | RETURN_F_IF_ERROR(cfg); 1670 | 1671 | cfg.second.clear_sensor_register_and_path = enable; 1672 | 1673 | return WriteUserCtrlConfig(cfg.second, timeout); 1674 | } 1675 | 1676 | Result GetFifoEnable(duration_type timeout) noexcept { 1677 | Result cfg = ReadUserCtrlConfig(timeout); 1678 | return std::make_pair(cfg.first, bool{cfg.second.fifo_enable}); 1679 | } 1680 | 1681 | Result GetI2cMasterEnable(duration_type timeout) noexcept { 1682 | Result cfg = ReadUserCtrlConfig(timeout); 1683 | return std::make_pair(cfg.first, bool{cfg.second.i2c_master_mode_enable}); 1684 | } 1685 | 1686 | Result GetUseSpiInterface(duration_type timeout) noexcept { 1687 | Result cfg = ReadUserCtrlConfig(timeout); 1688 | return std::make_pair(cfg.first, bool{cfg.second.enable_spi_interface}); 1689 | } 1690 | 1691 | Result GetFifoReset(duration_type timeout) noexcept { 1692 | Result cfg = ReadUserCtrlConfig(timeout); 1693 | return std::make_pair(cfg.first, bool{cfg.second.reset_fifo_buffer}); 1694 | } 1695 | 1696 | Result GetI2cMasterReset(duration_type timeout) noexcept { 1697 | Result cfg = ReadUserCtrlConfig(timeout); 1698 | return std::make_pair(cfg.first, bool{cfg.second.reset_i2c_master}); 1699 | } 1700 | 1701 | Result GetSignalPathReset(duration_type timeout) noexcept { 1702 | Result cfg = ReadUserCtrlConfig(timeout); 1703 | return std::make_pair(cfg.first, 1704 | bool{cfg.second.clear_sensor_register_and_path}); 1705 | } 1706 | 1707 | /** 1708 | * 1709 | * 1710 | **/ 1711 | 1712 | Status WritePowerManagement1_Config(PowerManagement1_Config cfg, 1713 | duration_type timeout) noexcept { 1714 | return WriteByteAs_(register_map::PowerManagement1, 1715 | cfg, timeout); 1716 | } 1717 | 1718 | Result ReadPowerManagement1_Config( 1719 | duration_type timeout) noexcept { 1720 | return ReadByteAs_(register_map::PowerManagement1, 1721 | timeout); 1722 | } 1723 | 1724 | Status SetDeviceRegisterReset(bool reset, duration_type timeout) noexcept { 1725 | Result cfg = ReadPowerManagement1_Config(timeout); 1726 | 1727 | RETURN_F_IF_ERROR(cfg); 1728 | 1729 | cfg.second.reset_registers = reset; 1730 | 1731 | return WritePowerManagement1_Config(cfg.second, timeout); 1732 | } 1733 | 1734 | Status SetSleep(bool sleep, duration_type timeout) noexcept { 1735 | Result cfg = ReadPowerManagement1_Config(timeout); 1736 | 1737 | RETURN_F_IF_ERROR(cfg); 1738 | 1739 | cfg.second.sleep_mode = sleep; 1740 | 1741 | return WritePowerManagement1_Config(cfg.second, timeout); 1742 | } 1743 | 1744 | Status SetSleepCycle(bool cycle, duration_type timeout) noexcept { 1745 | Result cfg = ReadPowerManagement1_Config(timeout); 1746 | 1747 | RETURN_F_IF_ERROR(cfg); 1748 | 1749 | cfg.second.cycle_sleep = cycle; 1750 | 1751 | return WritePowerManagement1_Config(cfg.second, timeout); 1752 | } 1753 | 1754 | Status SetTemperatureDisable(bool disable, duration_type timeout) noexcept { 1755 | Result cfg = ReadPowerManagement1_Config(timeout); 1756 | 1757 | RETURN_F_IF_ERROR(cfg); 1758 | 1759 | cfg.second.disable_temperature = disable; 1760 | 1761 | return WritePowerManagement1_Config(cfg.second, timeout); 1762 | } 1763 | 1764 | Status SetClockSource(ClockSource clk, duration_type timeout) noexcept { 1765 | Result cfg = ReadPowerManagement1_Config(timeout); 1766 | 1767 | RETURN_F_IF_ERROR(cfg); 1768 | 1769 | cfg.second.clock_source = 1770 | static_cast(static_cast(clk) & 0b111U); 1771 | 1772 | return WritePowerManagement1_Config(cfg.second, timeout); 1773 | } 1774 | 1775 | Result GetDeviceRegisterReset(duration_type timeout) noexcept { 1776 | Result cfg = ReadPowerManagement1_Config(timeout); 1777 | return std::make_pair(cfg.first, bool{cfg.second.reset_registers}); 1778 | } 1779 | 1780 | Result GetSleep(duration_type timeout) noexcept { 1781 | Result cfg = ReadPowerManagement1_Config(timeout); 1782 | return std::make_pair(cfg.first, bool{cfg.second.sleep_mode}); 1783 | } 1784 | 1785 | Result GetSleepCycle(duration_type timeout) noexcept { 1786 | Result cfg = ReadPowerManagement1_Config(timeout); 1787 | return std::make_pair(cfg.first, bool{cfg.second.cycle_sleep}); 1788 | } 1789 | 1790 | Result GetTemperatureDisable(duration_type timeout) noexcept { 1791 | Result cfg = ReadPowerManagement1_Config(timeout); 1792 | return std::make_pair(cfg.first, bool{cfg.second.disable_temperature}); 1793 | } 1794 | 1795 | Result GetClockSource(duration_type timeout) noexcept { 1796 | Result cfg = ReadPowerManagement1_Config(timeout); 1797 | return std::make_pair(cfg.first, ClockSource{cfg.second.clock_source}); 1798 | } 1799 | 1800 | /** 1801 | * 1802 | * 1803 | **/ 1804 | 1805 | Status WritePowerManagement2_Config(PowerManagement2_Config cfg, 1806 | duration_type timeout) noexcept { 1807 | return WriteByteAs_(register_map::PowerManagement2, 1808 | cfg, timeout); 1809 | } 1810 | 1811 | Result ReadPowerManagement2_Config( 1812 | duration_type timeout) noexcept { 1813 | return ReadByteAs_(register_map::PowerManagement2, 1814 | timeout); 1815 | } 1816 | 1817 | Status SetWakeupFrequency(WakeupFrequency wfreq, 1818 | duration_type timeout) noexcept { 1819 | Result cfg = ReadPowerManagement2_Config(timeout); 1820 | 1821 | RETURN_F_IF_ERROR(cfg); 1822 | 1823 | cfg.second.wakeup_frequency = 1824 | static_cast(static_cast(wfreq) & 0b11U); 1825 | return WriteByteAs_(register_map::PowerManagement2, 1826 | cfg.second, timeout); 1827 | } 1828 | 1829 | Status SetAccelerometerX_Standby(bool standby, 1830 | duration_type timeout) noexcept { 1831 | Result cfg = ReadPowerManagement2_Config(timeout); 1832 | 1833 | RETURN_F_IF_ERROR(cfg); 1834 | 1835 | cfg.second.accelerometer_x_standby = standby; 1836 | return WriteByteAs_(register_map::PowerManagement2, 1837 | cfg.second, timeout); 1838 | } 1839 | 1840 | Status SetAccelerometerY_Standby(bool standby, 1841 | duration_type timeout) noexcept { 1842 | Result cfg = ReadPowerManagement2_Config(timeout); 1843 | 1844 | RETURN_F_IF_ERROR(cfg); 1845 | 1846 | cfg.second.accelerometer_y_standby = standby; 1847 | return WriteByteAs_(register_map::PowerManagement2, 1848 | cfg.second, timeout); 1849 | } 1850 | 1851 | Status SetAccelerometerZ_Standby(bool standby, 1852 | duration_type timeout) noexcept { 1853 | Result cfg = ReadPowerManagement2_Config(timeout); 1854 | 1855 | RETURN_F_IF_ERROR(cfg); 1856 | 1857 | cfg.second.accelerometer_z_standby = standby; 1858 | return WriteByteAs_(register_map::PowerManagement2, 1859 | cfg.second, timeout); 1860 | } 1861 | 1862 | Status SetGyroscopeX_Standby(bool standby, duration_type timeout) noexcept { 1863 | Result cfg = ReadPowerManagement2_Config(timeout); 1864 | 1865 | RETURN_F_IF_ERROR(cfg); 1866 | 1867 | cfg.second.gyroscope_x_standby = standby; 1868 | return WriteByteAs_(register_map::PowerManagement2, 1869 | cfg.second, timeout); 1870 | } 1871 | 1872 | Status SetGyroscopeY_Standby(bool standby, duration_type timeout) noexcept { 1873 | Result cfg = ReadPowerManagement2_Config(timeout); 1874 | 1875 | RETURN_F_IF_ERROR(cfg); 1876 | 1877 | cfg.second.gyroscope_y_standby = standby; 1878 | return WriteByteAs_(register_map::PowerManagement2, 1879 | cfg.second, timeout); 1880 | } 1881 | 1882 | Status SetGyroscopeZ_Standby(bool standby, duration_type timeout) noexcept { 1883 | Result cfg = ReadPowerManagement2_Config(timeout); 1884 | 1885 | RETURN_F_IF_ERROR(cfg); 1886 | 1887 | cfg.second.gyroscope_z_standby = standby; 1888 | return WriteByteAs_(register_map::PowerManagement2, 1889 | cfg.second, timeout); 1890 | } 1891 | 1892 | Result GetWakeupFrequency(duration_type timeout) noexcept { 1893 | Result cfg = ReadPowerManagement2_Config(timeout); 1894 | 1895 | return std::make_pair(cfg.first, 1896 | WakeupFrequency{cfg.second.wakeup_frequency}); 1897 | } 1898 | 1899 | Result GetAccelerometerX_Standby(duration_type timeout) noexcept { 1900 | Result cfg = ReadPowerManagement2_Config(timeout); 1901 | 1902 | return std::make_pair(cfg.first, bool{cfg.second.accelerometer_x_standby}); 1903 | } 1904 | 1905 | Result GetAccelerometerY_Standby(duration_type timeout) noexcept { 1906 | Result cfg = ReadPowerManagement2_Config(timeout); 1907 | 1908 | return std::make_pair(cfg.first, bool{cfg.second.accelerometer_y_standby}); 1909 | } 1910 | 1911 | Result GetAccelerometerZ_Standby(duration_type timeout) noexcept { 1912 | Result cfg = ReadPowerManagement2_Config(timeout); 1913 | 1914 | return std::make_pair(cfg.first, bool{cfg.second.accelerometer_z_standby}); 1915 | } 1916 | 1917 | Result GetGyroscopeX_Standby(duration_type timeout) noexcept { 1918 | Result cfg = ReadPowerManagement2_Config(timeout); 1919 | 1920 | return std::make_pair(cfg.first, bool{cfg.second.gyroscope_x_standby}); 1921 | } 1922 | 1923 | Result GetGyroscopeY_Standby(duration_type timeout) noexcept { 1924 | Result cfg = ReadPowerManagement2_Config(timeout); 1925 | 1926 | return std::make_pair(cfg.first, bool{cfg.second.gyroscope_y_standby}); 1927 | } 1928 | 1929 | Result GetGyroscopeZ_Standby(duration_type timeout) noexcept { 1930 | Result cfg = ReadPowerManagement2_Config(timeout); 1931 | 1932 | return std::make_pair(cfg.first, bool{cfg.second.gyroscope_z_standby}); 1933 | } 1934 | 1935 | /** 1936 | * 1937 | * 1938 | **/ 1939 | 1940 | Result ReadFifoCount(duration_type timeout) noexcept { 1941 | uint8_t data[2]{}; 1942 | 1943 | Status status = 1944 | BurstRead_(register_map::FifoCountH, data, sizeof(data), timeout); 1945 | 1946 | uint16_t fifo_cnt = (static_cast(data[0]) << 8) | 1947 | (static_cast(data[1])); 1948 | return std::make_pair(status, fifo_cnt); 1949 | } 1950 | 1951 | /** 1952 | * 1953 | * 1954 | **/ 1955 | 1956 | Status WriteFifoData(uint8_t data, duration_type timeout) noexcept { 1957 | return WriteByte_(register_map::FifoReadWrite, data, timeout); 1958 | } 1959 | 1960 | Result ReadFifoData(duration_type timeout) noexcept { 1961 | return ReadByte_(register_map::FifoReadWrite, timeout); 1962 | } 1963 | 1964 | /** 1965 | * 1966 | * 1967 | **/ 1968 | 1969 | Result ReadWhoAmI(duration_type timeout) noexcept { 1970 | return ReadByte_(register_map::FifoReadWrite, timeout); 1971 | } 1972 | 1973 | /** 1974 | * 1975 | * 1976 | **/ 1977 | }; 1978 | } // namespace mpu60X0 1979 | #endif // DRIVERS_MPU60X0_MPU60X0_H_ 1980 | --------------------------------------------------------------------------------