31#include "../functors.h"
32#include "../i2c_device.h"
33#include "../i2c_device_utilities.h"
34#include "../utilities.h"
58 if (range == GyroRange::RANGE_2000)
return 2000;
59 if (range == GyroRange::RANGE_1000)
return 1000;
60 if (range == GyroRange::RANGE_500)
return 500;
83 if (range == AccelRange::RANGE_16G)
return 16;
84 if (range == AccelRange::RANGE_8G)
return 8;
85 if (range == AccelRange::RANGE_4G)
return 4;
101 PLL_EXTERNAL_32KHZ = 4,
102 PLL_EXTERNAL_19MHZ = 5,
162 return data_ & ACCEL_FIFO_EN;
168 return data_ & XG_FIFO_EN;
174 return data_ & YG_FIFO_EN;
180 return data_ & ZG_FIFO_EN;
186 return data_ & TEMP_FIFO_EN;
190 static constexpr uint8_t TEMP_FIFO_EN =
bits::BV8(7);
191 static constexpr uint8_t XG_FIFO_EN =
bits::BV8(6);
192 static constexpr uint8_t YG_FIFO_EN =
bits::BV8(5);
193 static constexpr uint8_t ZG_FIFO_EN =
bits::BV8(4);
194 static constexpr uint8_t ACCEL_FIFO_EN =
bits::BV8(3);
221 return data_ & DATA_RDY_INT;
227 return data_ & FIFO_OFLOW_INT;
231 static constexpr uint8_t FIFO_OFLOW_INT =
bits::BV8(4);
232 static constexpr uint8_t DATA_RDY_INT =
bits::BV8(0);
281 template<
typename MANAGER>
286 template<
typename OUT,
typename IN>
using FUTURE =
typename PARENT::template FUTURE<OUT, IN>;
289 template<u
int8_t REGISTER,
typename T = u
int8_t,
typename FUNCTOR = functor::ChangeEndianness<T>>
291 template<u
int8_t REGISTER,
typename T = u
int8_t,
typename FUNCTOR = functor::ChangeEndianness<T>>
294 template<u
int8_t REGISTER>
297 static constexpr const uint8_t SMPRT_DIV = 0x19;
298 static constexpr const uint8_t CONFIG = 0x1A;
299 static constexpr const uint8_t GYRO_CONFIG = 0x1B;
300 static constexpr const uint8_t ACCEL_CONFIG = 0x1C;
302 static constexpr const uint8_t FIFO_EN = 0x23;
303 static constexpr const uint8_t INT_PIN_CFG = 0x37;
304 static constexpr const uint8_t INT_ENABLE = 0x38;
305 static constexpr const uint8_t INT_STATUS = 0x3A;
307 static constexpr const uint8_t ACCEL_XOUT = 0x3B;
308 static constexpr const uint8_t TEMP_OUT = 0x41;
309 static constexpr const uint8_t GYRO_XOUT = 0x43;
311 static constexpr const uint8_t USER_CTRL = 0x6A;
312 static constexpr const uint8_t FIFO_RESET = 0x04;
313 static constexpr const uint8_t FIFO_ENABLE = 0x40;
315 static constexpr const uint8_t PWR_MGMT_1 = 0x6B;
316 static constexpr const uint8_t PWR_MGMT_2 = 0x6C;
318 static constexpr const uint8_t FIFO_COUNT = 0x72;
319 static constexpr const uint8_t FIFO_R_W = 0x74;
321 static constexpr const uint8_t WHO_AM_I = 0x75;
323 class PowerManagement;
337 :
PARENT{manager, DEVICE_ADDRESS(ad0),
i2c::I2C_FAST, true} {}
355 class BeginFuture :
public FUTURE<void, containers::array<uint8_t, 6>>
357 using PARENT = FUTURE<void, containers::array<uint8_t, 6>>;
361 AccelRange accel_range = AccelRange::RANGE_2G,
362 DLPF low_pass_filter = DLPF::ACCEL_BW_260HZ,
363 ClockSelect clock_select = ClockSelect::INTERNAL_8MHZ)
364 : PARENT{{ CONFIG, uint8_t(low_pass_filter), uint8_t(gyro_range), uint8_t(accel_range),
418 using PARENT = FUTURE<void, containers::array<uint8_t, 15>>;
423 uint8_t sample_rate_divider,
424 GyroRange gyro_range = GyroRange::RANGE_250,
425 AccelRange accel_range = AccelRange::RANGE_2G,
426 DLPF low_pass_filter = DLPF::ACCEL_BW_260HZ,
427 ClockSelect clock_select = ClockSelect::INTERNAL_8MHZ)
428 : PARENT{{ CONFIG, uint8_t(low_pass_filter), uint8_t(gyro_range), uint8_t(accel_range),
430 SMPRT_DIV, sample_rate_divider,
433 USER_CTRL, FIFO_ENABLE | FIFO_RESET}} {}
630 return int16_t(temp * 10L / 34L + 3653);
900 AccelRange accel_range = AccelRange::RANGE_2G,
901 DLPF low_pass_filter = DLPF::ACCEL_BW_260HZ,
902 ClockSelect clock_select = ClockSelect::INTERNAL_8MHZ)
938 uint8_t sample_rate_divider,
939 GyroRange gyro_range = GyroRange::RANGE_250,
940 AccelRange accel_range = AccelRange::RANGE_2G,
941 DLPF low_pass_filter = DLPF::ACCEL_BW_260HZ,
942 ClockSelect clock_select = ClockSelect::INTERNAL_8MHZ)
945 fifo_enable, int_enable, sample_rate_divider, gyro_range, accel_range, low_pass_filter, clock_select};
963 return this->
template sync_write<EndFuture>();
977 return this->
template sync_write<ResetFuture>();
993 return this->
template sync_read<GyroFuture>(gyro);
1010 int16_t temp = INT16_MIN;
1011 this->
template sync_read<TemperatureFuture>(temp);
1028 return this->
template sync_read<AccelFuture>(accel);
1045 return this->
template sync_read<AllMeasuresFuture>(sensors);
1063 this->
template sync_read<InterruptStatusFuture>(status);
1078 return this->
template sync_write<ResetFifoFuture>();
1098 this->
template sync_read<FifoCountFuture>(count);
1123 return this->
template sync_read<FifoPopFuture<T>>(output);
1138 return this->
template sync_write<FifoPushFuture>(data);
1142 class PowerManagement
1145 constexpr PowerManagement() : value_{} {}
1146 explicit constexpr PowerManagement(
ClockSelect clock_select,
bool temp_disable =
false,
1147 bool cycle =
false,
bool sleep =
false,
bool device_reset =
false)
1148 : value_{
bits::OR8(uint8_t(clock_select),
bits::IF8(temp_disable, TEMP_DIS_MASK),
1149 bits::IF8(cycle, CYCLE_MASK),
bits::IF8(sleep, SLEEP_MASK),
1150 bits::IF8(device_reset, RESET_MASK))} {}
1151 constexpr PowerManagement(
bool temp_disable,
bool cycle,
bool sleep,
bool device_reset)
1152 : value_{
bits::ORIF8(temp_disable, TEMP_DIS_MASK, cycle, CYCLE_MASK,
1153 sleep, SLEEP_MASK, device_reset, RESET_MASK)} {}
1157 return static_cast<ClockSelect>(value_ & CLOCK_SEL_MASK);
1160 bool temp_disable()
const
1162 return value_ & TEMP_DIS_MASK;
1167 return value_ & CYCLE_MASK;
1172 return value_ & SLEEP_MASK;
1175 bool device_reset()
const
1177 return value_ & RESET_MASK;
1181 static constexpr uint8_t CLOCK_SEL_MASK =
bits::BV8(0, 1, 2);
1182 static constexpr uint8_t TEMP_DIS_MASK =
bits::BV8(3);
1183 static constexpr uint8_t CYCLE_MASK =
bits::BV8(5);
1184 static constexpr uint8_t SLEEP_MASK =
bits::BV8(6);
1185 static constexpr uint8_t RESET_MASK =
bits::BV8(7);
1189 static constexpr uint8_t DEVICE_ADDRESS(
AD0 ad0)
1191 return uint8_t(uint8_t(0x68 | uint8_t(ad0)) << 1);
Configuration for MPU6050 FIFO Enable register (register map §4.6).
bool temperature() const
If true, chip temperature will be loaded to FIFO buffer.
bool accel() const
If true, accelerometer measures on 3 axes will be loaded to FIFO buffer.
bool gyro_x() const
If true, gyroscope measures on X axis will be loaded to FIFO buffer.
constexpr FIFOEnable(bool accel=false, bool gyro_x=false, bool gyro_y=false, bool gyro_z=false, bool temperature=false)
Create a new FIFOEnable configuration value.
bool gyro_z() const
If true, gyroscope measures on Z axis will be loaded to FIFO buffer.
bool gyro_y() const
If true, gyroscope measures on Y axis will be loaded to FIFO buffer.
The structure of the Interrupt Status register (register map §4.16).
bool overflow() const
If true, a FIFO buffer overflow will generate an interrupt.
bool data_ready() const
If true, the Data Ready interrupt is enabled.
constexpr INTStatus(bool data_ready=false, bool overflow=false)
Create a new INTStatus configuration value.
Create a future to be used by asynchronous method begin(BeginFuture&).
Create a future to be used by asynchronous method end(EndFuture&).
Create a future to be used by asynchronous method begin(FifoBeginFuture&).
Create a future to be used by asynchronous method reset(ResetFuture&).
I2C device driver for the MPU6050 gyroscope/accelerometer chip.
MPU6050(MANAGER &manager, AD0 ad0=AD0::LOW)
Create a new device driver for a MPU6050 chip.
int fifo_count(FifoCountFuture &future)
Get the number of bytes currently stored in the FIFO buffer (register map §4.30).
bool begin(FIFOEnable fifo_enable, INTEnable int_enable, uint8_t sample_rate_divider, GyroRange gyro_range=GyroRange::RANGE_250, AccelRange accel_range=AccelRange::RANGE_2G, DLPF low_pass_filter=DLPF::ACCEL_BW_260HZ, ClockSelect clock_select=ClockSelect::INTERNAL_8MHZ)
Start operation of this gyroscope/accelerometer chip.
bool accel_measures(Sensor3D &accel)
Get latest accelerometer measurements from the device (register map §4.17).
int gyro_measures(GyroFuture &future)
Get latest gyroscope measurements from the device (register map §4.19).
bool reset_fifo()
Reset the FIFO buffer (parameter map §4.27).
int end(EndFuture &future) INLINE
Put the chip to sleep mode (low-power mode); stops sampling operations if any.
int all_measures(AllMeasuresFuture &future)
Get latest measurements of all device sensors (gyroscope, accelerometer, temperature).
bool fifo_push(uint8_t data)
Push one byte to the FIFO buffer (register map §4.31).
uint16_t fifo_count()
Get the number of bytes currently stored in the FIFO buffer (register map §4.30).
bool gyro_measures(Sensor3D &gyro)
Get latest gyroscope measurements from the device (register map §4.19).
bool all_measures(AllSensors &sensors)
Get latest measurements of all device sensors (gyroscope, accelerometer, temperature).
int begin(FifoBeginFuture &future)
Start operation of this gyroscope/accelerometer chip.
static constexpr int16_t convert_temp_to_centi_degrees(int16_t temp)
Convert the raw temperature obtained from temperature() to centi-degrees Celsius.
bool reset() INLINE
Reset the chip (register map §4.28).
bool begin(GyroRange gyro_range=GyroRange::RANGE_250, AccelRange accel_range=AccelRange::RANGE_2G, DLPF low_pass_filter=DLPF::ACCEL_BW_260HZ, ClockSelect clock_select=ClockSelect::INTERNAL_8MHZ)
Start operation of this gyroscope/accelerometer chip.
int accel_measures(AccelFuture &future)
Get latest accelerometer measurements from the device (register map §4.17).
int reset_fifo(ResetFifoFuture &future)
Reset the FIFO buffer (parameter map §4.27).
int fifo_push(FifoPushFuture &future)
Push one byte to the FIFO buffer (register map §4.31).
int reset(ResetFuture &future) INLINE
Reset the chip (register map §4.28).
int temperature(TemperatureFuture &future)
Get latest chip temperature measurement (register map §4.18).
int begin(BeginFuture &future)
Start operation of this gyroscope/accelerometer chip.
int fifo_pop(FifoPopFuture< T > &future)
Get one sample out of the FIFO buffer (register map §4.31).
INTStatus interrupt_status()
Get the interrupt status (register map §4.16) after an interrupt has occurred.
bool end() INLINE
Put the chip to sleep mode (low-power mode); stops sampling operations if any.
bool fifo_pop(T &output)
Get one sample out of the FIFO buffer (register map §4.31).
int interrupt_status(InterruptStatusFuture &future)
Get the interrupt status (register map §4.16) after an interrupt has occurred.
int16_t temperature()
Get latest chip temperature measurement (register map §4.18).
Base class for all I2C devices.
static constexpr I2CLightCommand write(uint8_t write_count=0, bool finish_future=false, bool stop=false)
Build a write I2CLightCommand that can be later pushed to the I2C Manager for proper handling.
int async_write(F &future, bool stop=true)
Helper method that asynchronously launches I2C commands for a simple Future performing only one write...
MANAGER MANAGER
the type of I2C Manager that can handle this device.
int async_read(F &future, bool stop=true)
Helper method that asynchronously launches I2C commands for a simple Future performing one write foll...
int launch_commands(ABSTRACT_FUTURE &future, utils::range< I2CLightCommand > commands)
Launch execution (asynchronously or synchronously, depending on MANAGER) of a chain of I2CLightComman...
Generic Future that can be used to read an I2C device register.
Generic Future that can be used to write to an I2C device register.
Common types used by 3D sensors (e.g.
#define INLINE
Specific GCC attribute to force the compiler to always inline code of a given function.
Defines utility methods for bits manipulation.
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Defines API for magnetic sensors for direction, speed and acceleration properties.
DLPF
The Digital Low Pass Filter bandwidth to select for the chip (register map §4.3).
AccelRange
The full-scale range of the accelerometer in g (datasheet §6.2).
ClockSelect
The clock to select for the chip (datasheet §6.6).
static constexpr uint16_t GYRO_RANGE_DPS(GyroRange range)
Convert a GyroRange constant to the real gyroscope range in dps.
AD0
Possible values of I2C address lower bit for the chip (the chip may have one of two possible addresse...
@ LOW
When AD0 pin is low, I2C address is 0x68.
@ HIGH
When AD0 pin is high, I2C address is 0x69.
static constexpr uint16_t ACCEL_RANGE_G(AccelRange range)
Convert an AccelRange constant to the real accelerometer range in g.
GyroRange
The full-scale range of the gyroscope in dps (datasheet §6.1).
Contains the API around Future implementation.
@ READY
The status of a Future once its output value has been fully set by a provider.
Define API to define and manage I2C devices.
constexpr uint8_t as_uint8_t(T input)
Cast a one byte long bit-fields struct into a byte.
Structure to store all MPU6050 sensors data (3 axis gyroscope and accelerometer, chip temperature).
Sensor3D accel
3 axis accelerometer measurements
Sensor3D gyro
3 axis gyroscope measurements
int16_t temperature
Temperature measurement.
Structure to store 3 axis data for one sensor (gyroscope or accelerometer).