99 */
1010// ----------------------------------------------------------------------------
1111
12+ #include < atomic>
1213#include < cstdint>
1314#include < modm/board.hpp>
1415#include < modm/driver/inertial/bmi270.hpp>
15- #include < modm/processing/timer .hpp>
16+ #include < modm/processing/fiber/mutex .hpp>
1617
1718using namespace Board ;
1819
@@ -28,6 +29,58 @@ using Imu = modm::Bmi270<Transport>;
2829
2930Imu imu{Transport::I2cAddress::SdoLow};
3031
32+ std::atomic<uint32_t > accInterruptCount{0 };
33+ std::atomic<uint32_t > gyroInterruptCount{0 };
34+
35+ std::atomic<int32_t > accX{0 };
36+ std::atomic<int32_t > accY{0 };
37+ std::atomic<int32_t > accZ{0 };
38+
39+ std::atomic<int32_t > gyroX{0 };
40+ std::atomic<int32_t > gyroY{0 };
41+ std::atomic<int32_t > gyroZ{0 };
42+
43+ modm::fiber::mutex imuBusLock;
44+
45+ void
46+ onDataReadyInterrupt ()
47+ {
48+ if (!imuBusLock.try_lock ()) { return ; }
49+
50+ const auto status = imu.getStatus ();
51+ if (!status)
52+ {
53+ imuBusLock.unlock ();
54+ return ;
55+ }
56+
57+ if (status->accDataReady )
58+ {
59+ const auto data = imu.readAccData ();
60+ if (data)
61+ {
62+ accInterruptCount.fetch_add (1 , std::memory_order_relaxed);
63+ accX.store (data->raw [0 ], std::memory_order_relaxed);
64+ accY.store (data->raw [1 ], std::memory_order_relaxed);
65+ accZ.store (data->raw [2 ], std::memory_order_relaxed);
66+ }
67+ }
68+
69+ if (status->gyroDataReady )
70+ {
71+ const auto data = imu.readGyroData ();
72+ if (data)
73+ {
74+ gyroInterruptCount.fetch_add (1 , std::memory_order_relaxed);
75+ gyroX.store (data->raw [0 ], std::memory_order_relaxed);
76+ gyroY.store (data->raw [1 ], std::memory_order_relaxed);
77+ gyroZ.store (data->raw [2 ], std::memory_order_relaxed);
78+ }
79+ }
80+
81+ imuBusLock.unlock ();
82+ }
83+
3184bool
3285configureDriver ()
3386{
@@ -74,99 +127,75 @@ main()
74127{
75128 Board::initialize ();
76129 Leds::setOutput ();
77- I2c::connect<Scl::Scl, Sda::Sda>(I2c::PullUps::External );
130+ I2c::connect<Scl::Scl, Sda::Sda>(I2c::PullUps::Internal );
78131 I2c::initialize<Board::SystemClock, 1_MHz, 10_pct>();
79132 Int1::setInput (Int1::InputType::PullDown);
80133 Int2::setInput (Int2::InputType::PullDown);
81134
82- MODM_LOG_INFO << " BMI270 I2C polling example" << modm::endl;
135+ MODM_LOG_INFO << " BMI270 I2C interrupt example" << modm::endl;
83136
84137 if (!configureDriver ()) { MODM_LOG_ERROR << " Configuration failed!" << modm::endl; }
85138
86- uint32_t accSampleCount{0 };
87- uint32_t gyroSampleCount{0 };
88- modm::PeriodicTimer printTimer{1s};
89-
90- Imu::AccData latestAccData{};
91- latestAccData.raw = modm::Vector3i (0 , 0 , 0 );
92- latestAccData.range = Imu::AccRange::Range2g;
93-
94- Imu::GyroData latestGyroData{};
95- latestGyroData.raw = modm::Vector3i (0 , 0 , 0 );
96- latestGyroData.range = Imu::GyroRange::Range2000dps;
97-
98- std::optional<Imu::SensorStatus> latestStatus;
139+ Exti::connect<Int1>(Exti::Trigger::RisingEdge, [](auto ) { onDataReadyInterrupt (); });
99140
100141 while (true )
101142 {
102- if (Int1::read ())
143+ modm::this_fiber::sleep_for (1s);
144+
145+ const uint32_t accCount = accInterruptCount.exchange (0 , std::memory_order_relaxed);
146+ const uint32_t gyroCount = gyroInterruptCount.exchange (0 , std::memory_order_relaxed);
147+
148+ Imu::AccData accData{};
149+ accData.raw = modm::Vector3i (accX.load (std::memory_order_relaxed),
150+ accY.load (std::memory_order_relaxed),
151+ accZ.load (std::memory_order_relaxed));
152+ accData.range = Imu::AccRange::Range2g;
153+
154+ Imu::GyroData gyroData{};
155+ gyroData.raw = modm::Vector3i (gyroX.load (std::memory_order_relaxed),
156+ gyroY.load (std::memory_order_relaxed),
157+ gyroZ.load (std::memory_order_relaxed));
158+ gyroData.range = Imu::GyroRange::Range2000dps;
159+
160+ const modm::Vector3f acc = accData.getFloat ();
161+ const modm::Vector3f gyro = gyroData.getFloat ();
162+
163+ std::optional<Imu::Temperature> temperature;
164+ std::optional<Imu::SensorStatus> status;
165+ imuBusLock.lock ();
166+ temperature = imu.getTemperature ();
167+ status = imu.getStatus ();
168+ imuBusLock.unlock ();
169+
170+ MODM_LOG_INFO << " Interrupts in last 1s: acc=" << accCount << " gyro=" << gyroCount
171+ << modm::endl;
172+
173+ MODM_LOG_INFO << " Latest Values Acc [mg] x: " << acc[0 ] << " y: " << acc[1 ]
174+ << " z: " << acc[2 ] << modm::endl;
175+ MODM_LOG_INFO << " Latest Values Gyro [deg/s] x: " << gyro[0 ] << " y: " << gyro[1 ]
176+ << " z: " << gyro[2 ] << modm::endl;
177+
178+ if (temperature and temperature->valid )
179+ {
180+ MODM_LOG_INFO << " Current Temperature [C]: " << temperature->celsius << modm::endl;
181+ } else
103182 {
104- if (const auto status = imu.getStatus ())
105- {
106- latestStatus = status;
107-
108- if (status->accDataReady )
109- {
110- if (const auto accData = imu.readAccData ())
111- {
112- latestAccData = *accData;
113- ++accSampleCount;
114- }
115- }
116-
117- if (status->gyroDataReady )
118- {
119- if (const auto gyroData = imu.readGyroData ())
120- {
121- latestGyroData = *gyroData;
122- ++gyroSampleCount;
123- }
124- }
125- }
183+ MODM_LOG_INFO << " Temperature: invalid" << modm::endl;
126184 }
127185
128- if (printTimer.execute ())
186+ if (status)
187+ {
188+ MODM_LOG_INFO << " Current Status: acc=" << status->accDataReady
189+ << " gyro=" << status->gyroDataReady << " aux=" << status->auxDataReady
190+ << " cmd=" << status->commandReady << " auxBusy=" << status->auxBusy
191+ << modm::endl;
192+ } else
129193 {
130- const modm::Vector3f acc = latestAccData.getFloat ();
131- const modm::Vector3f gyro = latestGyroData.getFloat ();
132- const std::optional<Imu::Temperature> temperature = imu.getTemperature ();
133-
134- MODM_LOG_INFO << " Data-ready events in last 1s: acc=" << accSampleCount
135- << " gyro=" << gyroSampleCount << modm::endl;
136-
137- accSampleCount = 0 ;
138- gyroSampleCount = 0 ;
139-
140- MODM_LOG_INFO << " Latest Values Acc [mg] x: " << acc[0 ] << " y: " << acc[1 ]
141- << " z: " << acc[2 ] << modm::endl;
142- MODM_LOG_INFO << " Latest Values Gyro [deg/s] x: " << gyro[0 ] << " y: " << gyro[1 ]
143- << " z: " << gyro[2 ] << modm::endl;
144-
145- if (temperature and temperature->valid )
146- {
147- MODM_LOG_INFO << " Current Temperature [C]: " << temperature->celsius << modm::endl;
148- } else
149- {
150- MODM_LOG_INFO << " Temperature: invalid" << modm::endl;
151- }
152-
153- if (latestStatus)
154- {
155- MODM_LOG_INFO << " Current Status: acc=" << latestStatus->accDataReady
156- << " gyro=" << latestStatus->gyroDataReady
157- << " aux=" << latestStatus->auxDataReady
158- << " cmd=" << latestStatus->commandReady
159- << " auxBusy=" << latestStatus->auxBusy << modm::endl;
160- } else
161- {
162- MODM_LOG_INFO << " Status: unavailable" << modm::endl;
163- }
164- MODM_LOG_INFO << modm::endl;
165-
166- Board::LedGreen::toggle ();
194+ MODM_LOG_INFO << " Status: unavailable" << modm::endl;
167195 }
196+ MODM_LOG_INFO << modm::endl;
168197
169- modm::this_fiber::yield ();
198+ Board::LedGreen::toggle ();
170199 }
171200
172201 return 0 ;
0 commit comments