1use super::{AccelRaw, GyroRaw, MagRaw, Timestamp};
4use crate::register::{fifo_ctrl, fifo_status};
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub enum FifoMode {
10 Bypass,
12 Fifo,
14 Stream,
16 StreamToFifo,
18}
19
20impl FifoMode {
21 pub(crate) const fn bits(self) -> u8 {
22 match self {
23 Self::Bypass => 0b00,
24 Self::Fifo => 0b01,
25 Self::Stream => 0b10,
26 Self::StreamToFifo => 0b11,
27 }
28 }
29}
30
31#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub enum FifoSize {
35 Samples16,
37 Samples32,
39 Samples64,
41 Samples128,
43}
44
45impl FifoSize {
46 pub(crate) const fn bits(self) -> u8 {
47 match self {
48 Self::Samples16 => 0b00,
49 Self::Samples32 => 0b01,
50 Self::Samples64 => 0b10,
51 Self::Samples128 => 0b11,
52 }
53 }
54
55 pub const fn samples(self) -> u16 {
57 match self {
58 Self::Samples16 => 16,
59 Self::Samples32 => 32,
60 Self::Samples64 => 64,
61 Self::Samples128 => 128,
62 }
63 }
64}
65
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
68#[cfg_attr(feature = "defmt", derive(defmt::Format))]
69pub struct FifoConfig {
70 pub watermark: u8,
72 pub mode: FifoMode,
74 pub size: FifoSize,
76}
77
78impl FifoConfig {
79 pub const DEFAULT: Self = Self {
81 watermark: 0,
82 mode: FifoMode::Bypass,
83 size: FifoSize::Samples16,
84 };
85
86 pub const fn new(mode: FifoMode, size: FifoSize, watermark: u8) -> Self {
88 Self {
89 watermark,
90 mode,
91 size,
92 }
93 }
94
95 #[must_use]
97 pub const fn with_mode(self, mode: FifoMode) -> Self {
98 Self { mode, ..self }
99 }
100
101 #[must_use]
103 pub const fn with_size(self, size: FifoSize) -> Self {
104 Self { size, ..self }
105 }
106
107 #[must_use]
109 pub const fn with_watermark(self, watermark: u8) -> Self {
110 Self { watermark, ..self }
111 }
112
113 pub(crate) const fn ctrl_value(self) -> u8 {
114 ((self.size.bits() << fifo_ctrl::FIFO_SIZE_SHIFT) & fifo_ctrl::FIFO_SIZE_MASK)
115 | ((self.mode.bits() << fifo_ctrl::FIFO_MODE_SHIFT) & fifo_ctrl::FIFO_MODE_MASK)
116 }
117}
118
119impl Default for FifoConfig {
120 fn default() -> Self {
121 Self::DEFAULT
122 }
123}
124
125#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
127#[cfg_attr(feature = "defmt", derive(defmt::Format))]
128pub struct FifoStatus {
129 pub full: bool,
131 pub watermark: bool,
133 pub overflow: bool,
135 pub not_empty: bool,
137 pub sample_count_bytes: u16,
139}
140
141#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
143#[cfg_attr(feature = "defmt", derive(defmt::Format))]
144pub struct FifoReadout {
145 pub status: FifoStatus,
147 pub bytes_read: usize,
149 pub timestamp: Timestamp,
151}
152
153#[derive(Clone, Copy, Debug, PartialEq, Eq)]
160#[cfg_attr(feature = "defmt", derive(defmt::Format))]
161pub struct FifoFrameFormat {
162 pub accel: bool,
164 pub gyro: bool,
166 pub mag: bool,
168 pub big_endian: bool,
170}
171
172impl FifoFrameFormat {
173 pub const fn new(accel: bool, gyro: bool, mag: bool) -> Self {
175 Self {
176 accel,
177 gyro,
178 mag,
179 big_endian: false,
180 }
181 }
182
183 #[must_use]
185 pub const fn with_big_endian(mut self, big_endian: bool) -> Self {
186 self.big_endian = big_endian;
187 self
188 }
189
190 pub const fn bytes_per_frame(self) -> usize {
192 super::fifo_frame_bytes(self.accel, self.gyro, self.mag)
193 }
194
195 pub const fn frame_count(self, bytes: usize) -> usize {
197 let frame = self.bytes_per_frame();
198 if frame == 0 { 0 } else { bytes / frame }
199 }
200}
201
202pub(crate) fn fifo_read_len(
203 status: FifoStatus,
204 format: FifoFrameFormat,
205 buffer_len: usize,
206) -> usize {
207 if buffer_len == 0 {
208 return 0;
209 }
210 let mut available = status.sample_count_bytes as usize;
211 if available == 0 {
212 return 0;
213 }
214 let frame = format.bytes_per_frame();
215 if frame == 0 {
216 return 0;
217 }
218 if available > buffer_len {
219 available = buffer_len;
220 }
221 available - (available % frame)
222}
223
224#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
226#[cfg_attr(feature = "defmt", derive(defmt::Format))]
227#[allow(dead_code)]
228pub struct FifoFrame {
229 pub accel: Option<AccelRaw>,
231 pub gyro: Option<GyroRaw>,
233 pub mag: Option<MagRaw>,
235}
236
237#[allow(dead_code)]
239pub struct FifoFrameIterator<'a> {
240 data: &'a [u8],
241 format: FifoFrameFormat,
242 offset: usize,
243}
244
245#[allow(dead_code)]
246impl<'a> FifoFrameIterator<'a> {
247 pub const fn new(data: &'a [u8], format: FifoFrameFormat) -> Self {
249 Self {
250 data,
251 format,
252 offset: 0,
253 }
254 }
255
256 fn take6(&self, offset: usize) -> [u8; 6] {
257 [
258 self.data[offset],
259 self.data[offset + 1],
260 self.data[offset + 2],
261 self.data[offset + 3],
262 self.data[offset + 4],
263 self.data[offset + 5],
264 ]
265 }
266
267 pub const fn remaining(&self) -> usize {
269 if self.offset >= self.data.len() {
270 0
271 } else {
272 self.data.len() - self.offset
273 }
274 }
275}
276
277impl<'a> Iterator for FifoFrameIterator<'a> {
278 type Item = FifoFrame;
279
280 fn next(&mut self) -> Option<Self::Item> {
281 let frame_len = self.format.bytes_per_frame();
282 if frame_len == 0 || self.offset + frame_len > self.data.len() {
283 return None;
284 }
285
286 let mut offset = self.offset;
287 let accel = if self.format.accel {
288 let bytes = self.take6(offset);
289 offset += 6;
290 Some(AccelRaw::from_bytes(bytes, self.format.big_endian))
291 } else {
292 None
293 };
294
295 let gyro = if self.format.gyro {
296 let bytes = self.take6(offset);
297 offset += 6;
298 Some(GyroRaw::from_bytes(bytes, self.format.big_endian))
299 } else {
300 None
301 };
302
303 let mag = if self.format.mag {
304 let bytes = self.take6(offset);
305 offset += 6;
306 Some(MagRaw::from_bytes(bytes, self.format.big_endian))
307 } else {
308 None
309 };
310
311 self.offset = offset;
312 Some(FifoFrame { accel, gyro, mag })
313 }
314}
315
316#[allow(dead_code)]
317impl FifoFrame {
318 pub const fn accel_only() -> FifoFrameFormat {
320 FifoFrameFormat::new(true, false, false)
321 }
322
323 pub const fn gyro_only() -> FifoFrameFormat {
325 FifoFrameFormat::new(false, true, false)
326 }
327
328 pub const fn accel_gyro() -> FifoFrameFormat {
330 FifoFrameFormat::new(true, true, false)
331 }
332}
333
334impl FifoStatus {
335 pub(crate) const fn from_regs(status: u8, smpl_cnt_lsb: u8) -> Self {
336 let msb = (status & fifo_status::SMPL_CNT_MSB_MASK) as u16;
337 let lsb = smpl_cnt_lsb as u16;
338 Self {
339 full: (status & fifo_status::FIFO_FULL) != 0,
340 watermark: (status & fifo_status::FIFO_WTM) != 0,
341 overflow: (status & fifo_status::FIFO_OVFLOW) != 0,
342 not_empty: (status & fifo_status::FIFO_NOT_EMPTY) != 0,
343 sample_count_bytes: (msb << 8) | lsb,
344 }
345 }
346
347 pub const fn any(self) -> bool {
349 self.full || self.watermark || self.overflow || self.not_empty
350 }
351
352 pub const fn samples(self, bytes_per_sample: u16) -> u16 {
354 if bytes_per_sample == 0 {
355 0
356 } else {
357 self.sample_count_bytes / bytes_per_sample
358 }
359 }
360}
361
362#[cfg(test)]
363mod tests {
364 use super::*;
365
366 #[test]
367 fn frame_format_sizes() {
368 let none = FifoFrameFormat::new(false, false, false);
369 assert_eq!(none.bytes_per_frame(), 0);
370
371 let accel = FifoFrameFormat::new(true, false, false);
372 assert_eq!(accel.bytes_per_frame(), 6);
373 assert_eq!(accel.frame_count(12), 2);
374 assert_eq!(accel.frame_count(11), 1);
375
376 let accel_gyro = FifoFrameFormat::new(true, true, false);
377 assert_eq!(accel_gyro.bytes_per_frame(), 12);
378
379 let all = FifoFrameFormat::new(true, true, true);
380 assert_eq!(all.bytes_per_frame(), 18);
381 }
382
383 #[test]
384 fn parse_accel_gyro_little_endian() {
385 let format = FifoFrameFormat::new(true, true, false).with_big_endian(false);
386 let buffer = [
387 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, ];
390
391 let mut iter = FifoFrameIterator::new(&buffer, format);
392 let frame = iter.next().expect("frame");
393 let accel = frame.accel.expect("accel");
394 let gyro = frame.gyro.expect("gyro");
395
396 assert_eq!(accel.x, 1);
397 assert_eq!(accel.y, 2);
398 assert_eq!(accel.z, 3);
399 assert_eq!(gyro.x, 4);
400 assert_eq!(gyro.y, 5);
401 assert_eq!(gyro.z, 6);
402 assert!(iter.next().is_none());
403 }
404
405 #[test]
406 fn parse_accel_big_endian() {
407 let format = FifoFrameFormat::new(true, false, false).with_big_endian(true);
408 let buffer = [0x00, 0x01, 0x00, 0x02, 0x00, 0x03];
409
410 let mut iter = FifoFrameIterator::new(&buffer, format);
411 let frame = iter.next().expect("frame");
412 let accel = frame.accel.expect("accel");
413
414 assert_eq!(accel.x, 1);
415 assert_eq!(accel.y, 2);
416 assert_eq!(accel.z, 3);
417 }
418
419 #[test]
420 fn fifo_read_len_aligns_to_frames() {
421 let status = FifoStatus {
422 sample_count_bytes: 25,
423 ..FifoStatus::default()
424 };
425 let format = FifoFrameFormat::new(true, true, false); assert_eq!(fifo_read_len(status, format, 64), 24);
427 assert_eq!(fifo_read_len(status, format, 12), 12);
428 assert_eq!(fifo_read_len(status, format, 8), 0);
429 }
430}