Sygaldry
Loading...
Searching...
No Matches
sygsp-icm20948.hpp
1/*
2Copyright 2023 Travis J. West, https://traviswest.ca, Input Devices and Music
3Interaction Laboratory (IDMIL), Centre for Interdisciplinary Research in Music
4Media and Technology (CIRMMT), McGill University, Montréal, Canada, and Univ.
5Lille, Inria, CNRS, Centrale Lille, UMR 9189 CRIStAL, F-59000 Lille, France
6
7SPDX-License-Identifier: MIT
8*/
9#pragma once
10#include "sygah-mimu.hpp"
11#include "sygah-metadata.hpp"
12#include "sygsp-icm20948_registers.hpp"
13#include "sygsp-icm20948_tests.hpp"
14#include "sygsp-delay.hpp"
15#include "sygsp-micros.hpp"
16#include "sygsp-mimu_units.hpp"
17
18namespace sygaldry { namespace sygsp {
23
24template<typename Serif, typename AK09916Serif>
26: name_<"ICM20948 MIMU">
27{
28 struct inputs_t {
29 // TODO: sensitivity, digital low pass filter controls, measurement rate, etc.
30 } inputs;
31
32 struct outputs_t {
33 vec3_message<"accelerometer raw", int, -32768, 32767, "LSB"> accl_raw;
34 slider<"accelerometer sensitivity", "g/LSB", float, 1/16384.0f, 1/2048.0f, 1/4096.0f> accl_sensitivity;
35 vec3_message<"accelerometer", float, -16, 16, "g"> accl;
36
37 vec3_message<"gyroscope raw", int, -32768, 32767, "LSB"> gyro_raw;
38 slider<"gyroscope sensitivity", "(rad/s)/LSB", float, 1/131.0f * rad_per_deg, 1/16.4f * rad_per_deg, 1/16.4f * rad_per_deg> gyro_sensitivity;
39 vec3_message<"gyroscope", float, -2000.0f * rad_per_deg, 2000.0f * rad_per_deg, "rad/s"> gyro;
40
41 vec3_message<"magnetometer raw", int, -32768, 32767, "LSB"> magn_raw;
42 slider<"magnetometer sensitivity", "uT/LSB", float, 0.15f, 0.15f> magn_sensitivity;
43 vec3_message<"magnetometer", float, -4900, 4900, "uT"> magn;
44
45 slider_message<"elapsed", "time in microseconds elapsed since last measurement", unsigned long, 0, 1000000, 0> elapsed;
46
47 text_message<"error message"> error_message;
48
49 toggle<"running"> running;
50 } outputs;
51
52 using Registers = ICM20948Registers<Serif>;
53 using AK09916Registers = ICM20948Registers<AK09916Serif>;
54
56 void init()
57 {
58 outputs.running = true;
59 if (!ICM20948Tests<Serif, AK09916Serif>::test()) outputs.running = false;
60 if (!outputs.running) return;
61 Registers::PWR_MGMT_1::DEVICE_RESET::trigger(); delay(10); // reset (establish known preconditions)
62 Registers::PWR_MGMT_1::SLEEP::disable(); delay(10); // disable sleep
63 Registers::INT_PIN_CFG::BYPASS_EN::enable(); delay(1); // bypass the I2C controller, connecting the aux bus to the main bus
64 Registers::GYRO_CONFIG_1::GYRO_FS_SEL::DPS_2000::set();
65 Registers::ACCEL_CONFIG::ACCEL_FS_SEL::G_8::set();
66 AK09916Registers::CNTL3::SRST::trigger(); delay(1); // soft-reset the magnetometer (establish known preconditions)
67 AK09916Registers::CNTL2::MODE::ContinuousMode100Hz::set(); delay(1); // enable continuous reads
68 outputs.accl_sensitivity = outputs.accl_sensitivity.init();
69 outputs.gyro_sensitivity = outputs.gyro_sensitivity.init();
70 outputs.magn_sensitivity = outputs.magn_sensitivity.init();
71 }
72
73 // poll the ICM20948 for new data and update endpoints
74 void main()
75 {
76 if (!outputs.running) return; // TODO: retry connecting every so often
77
78 static constexpr uint8_t IMU_N_OUT = 1 + Registers::GYRO_ZOUT_L::address
79 - Registers::ACCEL_XOUT_H::address;
80 static constexpr uint8_t MAG_N_OUT = 1 + AK09916Registers::ST2::address
81 - AK09916Registers::HXL::address;
82 static_assert(IMU_N_OUT == 12);
83 static_assert(MAG_N_OUT == 8);
84
85 static uint8_t raw[IMU_N_OUT];
86 static auto prev = micros();
87 auto now = micros();
88 bool read = false;
89 if (Registers::INT_STATUS_1::read())
90 {
91 read = true;
92 Serif::read(Registers::ACCEL_XOUT_H::address, raw, IMU_N_OUT);
93 outputs.accl_raw = { (int)(int16_t)( raw[0] << 8 | ( raw[1] & 0xFF))
94 , (int)(int16_t)( raw[2] << 8 | ( raw[3] & 0xFF))
95 , (int)(int16_t)( raw[4] << 8 | ( raw[5] & 0xFF))
96 };
97 outputs.gyro_raw = { (int)(int16_t)( raw[6] << 8 | ( raw[7] & 0xFF))
98 , (int)(int16_t)( raw[8] << 8 | ( raw[9] & 0xFF))
99 , (int)(int16_t)(raw[10] << 8 | (raw[11] & 0xFF))
100 };
101 outputs.accl = { outputs.accl_raw.x() * outputs.accl_sensitivity
102 , outputs.accl_raw.y() * outputs.accl_sensitivity
103 , outputs.accl_raw.z() * outputs.accl_sensitivity
104 };
105 outputs.gyro = { outputs.gyro_raw.x() * outputs.gyro_sensitivity
106 , outputs.gyro_raw.y() * outputs.gyro_sensitivity
107 , outputs.gyro_raw.z() * outputs.gyro_sensitivity
108 };
109 }
110 if (AK09916Registers::ST1::DRDY::read_field())
111 {
112 read = true;
113 AK09916Serif::read(AK09916Registers::HXL::address, raw, MAG_N_OUT);
114 outputs.magn_raw = { (int)(int16_t)( raw[1] << 8 | ( raw[0] & 0xFF))
115 , (int)(int16_t)( raw[3] << 8 | ( raw[2] & 0xFF))
116 , (int)(int16_t)( raw[5] << 8 | ( raw[4] & 0xFF))
117 };
118 outputs.magn = { outputs.magn_raw.x() * outputs.magn_sensitivity
119 , -outputs.magn_raw.y() * outputs.magn_sensitivity
120 , -outputs.magn_raw.z() * outputs.magn_sensitivity
121 };
122 }
123 if (read)
124 {
125 outputs.elapsed = now - prev;
126 prev = now;
127 }
128 }
129};
130
133} }
static _consteval auto init()
Returns the initial value of the range.
Definition sygah-endpoints.hpp:73
unsigned long micros()
Get the number of microseconds elapsed since boot.
Definition sygsa-micros.cpp:19
void delay(unsigned long ms)
Definition sygsa-delay.cpp:14
static constexpr float rad_per_deg
Definition sygsp-mimu_units.hpp:40
Document the name of an entity, e.g. an endpoint, component, or binding.
Definition sygah-metadata.hpp:33
A numeric endpoint with user customizeable range and occasional value semantics.
Definition sygah-endpoints.hpp:376
A numeric endpoint with user customizeable range and persistent value semantics.
Definition sygah-endpoints.hpp:348
Definition sygsp-icm20948_registers.hpp:27
Definition sygsp-icm20948_tests.hpp:22
Definition sygsp-icm20948.hpp:28
Definition sygsp-icm20948.hpp:32
Definition sygsp-icm20948.hpp:27
void init()
initialize the ICM20948 for continuous reading
Definition sygsp-icm20948.hpp:56
A text string endpoint with occasional message semantics.
Definition sygah-endpoints.hpp:320
A two-state integer endpoint with persistent value semantics.
Definition sygah-endpoints.hpp:289
A MIMU data vector.
Definition sygah-mimu.hpp:40
constexpr auto & x() noexcept
Mutable vector component access; remember to call set_updated() if you change the value of the vector...
Definition sygah-mimu.hpp:45
constexpr auto & z() noexcept
Mutable vector component access; remember to call set_updated() if you change the value of the vector...
Definition sygah-mimu.hpp:49
constexpr auto & y() noexcept
Mutable vector component access; remember to call set_updated() if you change the value of the vector...
Definition sygah-mimu.hpp:47