Skip to main content

stm_32/peripherals/
bmi08x.rs

1// ******************************************************************************
2// * File     : platforms/stm_32/src/peripherals/bmi08x.rs
3// * Date     : June 28, 2026
4// ******************************************************************************
5// *
6// * Copyright (c) 2023, AeroVironment, Inc.
7// * All rights reserved.
8// *
9// * Redistribution and use in source and binary forms, with or without
10// * modification, are permitted provided that the following conditions are met:
11// *
12// * 1.Redistributions of source code must retain the above copyright notice, this
13// * list of conditions and the following disclaimer.
14// *
15// * 2.Redistributions in binary form must reproduce the above copyright notice,
16// * this list of conditions and the following disclaimer in the documentation
17// * and/or other materials provided with the distribution.
18// *
19// * 3.Neither the name of the copyright holder nor the names of its
20// * contributors may be used to endorse or promote products derived from
21// * this software without specific prior written permission.
22// *
23// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24// * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26// * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
27// * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28// * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29// * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30// * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31// * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32// * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33// *
34// ******************************************************************************
35
36use embassy_stm32::exti::ExtiInput;
37use embassy_stm32::gpio::Output;
38use embassy_stm32::mode::Async;
39use embassy_stm32::spi;
40use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
41use embassy_sync::signal::Signal;
42use embassy_time::Instant;
43use embassy_time::Timer;
44
45use veloxity_core::errors;
46use veloxity_core::packets;
47
48use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice;
49use embedded_hal_async::spi::SpiDevice as _;
50
51pub static IMU_SIGNAL: Signal<
52    CriticalSectionRawMutex,
53    Result<packets::ImuPacket<f64>, errors::SensorError>,
54> = Signal::<CriticalSectionRawMutex, Result<packets::ImuPacket<f64>, errors::SensorError>>::new();
55
56// 3 blocks of 2048 bytes
57// 192 blocks of 32 bytes
58static BMI_CONFIG: [u8; 6144] = [
59    0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x48, 0xb4, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x6d, 0xb4,
60    0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xd4, 0xb3, 0x80, 0x2e, 0xb0, 0xb3, 0x80, 0x2e, 0x12, 0xb4,
61    0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfe, 0xb4,
62    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x79, 0x80, 0x2e, 0x18, 0x00,
64    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
65    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
66    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
67    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
68    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
69    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
70    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
71    0x80, 0x2e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
78    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0xfb, 0x7f,
79    0x98, 0x2e, 0x03, 0xb1, 0x12, 0x24, 0x67, 0x00, 0x90, 0x42, 0x81, 0x42, 0xba, 0x82, 0xd1, 0x7f,
80    0xe2, 0x7f, 0x98, 0x2e, 0x3c, 0xb0, 0xd1, 0x6f, 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x4c, 0x2f,
81    0xe1, 0x6f, 0x44, 0x86, 0x03, 0x2e, 0x67, 0x00, 0xc2, 0x40, 0xf7, 0x86, 0x4a, 0x04, 0xc1, 0x42,
82    0x00, 0x2e, 0xc2, 0x40, 0x80, 0xac, 0x01, 0x2f, 0x23, 0x2e, 0x63, 0x00, 0xd1, 0x40, 0xd2, 0x40,
83    0x0a, 0x0f, 0x01, 0x2f, 0x40, 0xac, 0x02, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x63, 0x00, 0xfe, 0x82,
84    0xc2, 0x40, 0x43, 0x40, 0xd3, 0x04, 0x46, 0x84, 0xc3, 0x7f, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80,
85    0x44, 0x40, 0xc1, 0x6f, 0xc3, 0x40, 0xe0, 0x7f, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e,
86    0x00, 0xb0, 0xe1, 0x6f, 0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40,
87    0xc3, 0x40, 0xd1, 0x6f, 0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f,
88    0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, 0xd1, 0x6f,
89    0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x00, 0x2e, 0x40, 0x42,
90    0x98, 0x2e, 0xa5, 0xb0, 0x11, 0x30, 0x23, 0x2e, 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e,
91    0xaa, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xed, 0x8f, 0xd9, 0x31,
92    0x00, 0x00, 0xc6, 0x01, 0x8c, 0x03, 0xc6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00,
93    0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x50,
94    0xf0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x02, 0xbc, 0x0f, 0xb8, 0xe0, 0x7f, 0x00, 0x2e,
95    0x01, 0x2e, 0x01, 0x01, 0x01, 0xbc, 0x0f, 0xb8, 0xd0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01,
96    0x0f, 0xb8, 0xc0, 0x7f, 0x02, 0x30, 0xe6, 0x6f, 0xd4, 0x6f, 0xc3, 0x6f, 0x80, 0x91, 0x04, 0x2f,
97    0x00, 0x91, 0x02, 0x2f, 0xc0, 0xb2, 0x90, 0x2e, 0xf6, 0x01, 0xf0, 0x6f, 0x0b, 0x2e, 0x24, 0x00,
98    0x01, 0x82, 0x40, 0x91, 0x14, 0x2f, 0x41, 0x87, 0x27, 0x2e, 0x24, 0x00, 0x00, 0x40, 0x21, 0x2e,
99    0x1b, 0x00, 0x53, 0x40, 0x10, 0x24, 0x1c, 0x00, 0x13, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x01, 0x42,
100    0x25, 0x2e, 0x18, 0x00, 0x25, 0x2e, 0x19, 0x00, 0x25, 0x2e, 0x1e, 0x00, 0x50, 0x5f, 0xb8, 0x2e,
101    0x0b, 0x2e, 0x00, 0x01, 0xd5, 0xbe, 0xd5, 0xba, 0xb5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x01, 0x01,
102    0xd3, 0xbe, 0xd3, 0xba, 0xa5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x00, 0x01, 0xd4, 0xbe, 0xdf, 0xba,
103    0x95, 0x7f, 0x00, 0x2e, 0x95, 0x6f, 0x0f, 0x2e, 0x1a, 0x00, 0x3d, 0x1a, 0x05, 0x2f, 0x25, 0x2e,
104    0x18, 0x00, 0x25, 0x2e, 0x19, 0x00, 0x2b, 0x2e, 0x1a, 0x00, 0x80, 0x91, 0x01, 0x2f, 0x06, 0x30,
105    0x07, 0x2d, 0x06, 0x40, 0x0f, 0x2e, 0x1b, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xd6, 0x05, 0xb7, 0x23,
106    0x86, 0x7f, 0x00, 0x91, 0x01, 0x2f, 0x04, 0x30, 0x07, 0x2d, 0x44, 0x40, 0x0d, 0x2e, 0x1c, 0x00,
107    0x26, 0x05, 0x00, 0xa9, 0x94, 0x05, 0x26, 0x23, 0x74, 0x7f, 0xc0, 0x90, 0x01, 0x2f, 0x00, 0x2e,
108    0x09, 0x2d, 0x02, 0x86, 0x00, 0x2e, 0xc3, 0x40, 0x09, 0x2e, 0x1d, 0x00, 0xdc, 0x04, 0xc0, 0xa8,
109    0x93, 0x04, 0x9a, 0x22, 0x62, 0x7f, 0x12, 0x30, 0x84, 0x6f, 0xb3, 0x6f, 0x63, 0x0f, 0x14, 0x30,
110    0x08, 0x2f, 0x74, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x04, 0x2f, 0x64, 0x6f, 0x63, 0x0f, 0x14, 0x30,
111    0x00, 0x2f, 0x04, 0x30, 0x54, 0x7f, 0x40, 0x91, 0x0b, 0x2e, 0x18, 0x00, 0x54, 0x6f, 0xa3, 0x6f,
112    0x6a, 0x29, 0x1d, 0x2f, 0x00, 0x91, 0x06, 0x30, 0x14, 0x24, 0x1c, 0x00, 0x0d, 0x2f, 0x2d, 0x2e,
113    0x18, 0x00, 0x05, 0x2e, 0x19, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x19, 0x00, 0x05, 0x2e, 0x19, 0x00,
114    0x53, 0x0e, 0x2b, 0x2f, 0x2d, 0x2e, 0x1e, 0x00, 0x29, 0x2d, 0x2b, 0x2e, 0x18, 0x00, 0x2d, 0x2e,
115    0x19, 0x00, 0x0b, 0x2e, 0x18, 0x00, 0x6b, 0x0e, 0x20, 0x2f, 0x25, 0x2e, 0x1e, 0x00, 0x1e, 0x2d,
116    0x00, 0xb3, 0x05, 0x2f, 0x02, 0x30, 0x25, 0x2e, 0x18, 0x00, 0x25, 0x2e, 0x1e, 0x00, 0x08, 0x2d,
117    0x2b, 0x2e, 0x18, 0x00, 0x09, 0x2e, 0x18, 0x00, 0x63, 0x0e, 0x01, 0x2f, 0x25, 0x2e, 0x1e, 0x00,
118    0x02, 0x40, 0x25, 0x2e, 0x1b, 0x00, 0x31, 0x25, 0x00, 0x2e, 0xd5, 0x40, 0x12, 0x24, 0x1c, 0x00,
119    0x42, 0x25, 0x95, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x83, 0x42, 0x00, 0x2e, 0x05, 0x2e, 0x1e, 0x00,
120    0x80, 0xb2, 0x0d, 0x2f, 0x00, 0x40, 0x21, 0x2e, 0x1b, 0x00, 0x50, 0x40, 0x10, 0x43, 0x00, 0x2e,
121    0x40, 0x40, 0x00, 0x43, 0x20, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x02, 0x2d, 0x25, 0x2e, 0x24, 0x00,
122    0x50, 0x5f, 0xb8, 0x2e, 0x40, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00,
123    0x70, 0x50, 0xf4, 0x7f, 0xe3, 0x7f, 0xd2, 0x7f, 0xc1, 0x7f, 0x12, 0x30, 0x03, 0x2e, 0x66, 0x00,
124    0x91, 0x14, 0x92, 0x7f, 0x00, 0x31, 0xc4, 0x6f, 0x95, 0x6f, 0xe3, 0x6f, 0xa5, 0x0f, 0x70, 0x84,
125    0x01, 0x04, 0x14, 0x2f, 0xd5, 0x6f, 0x00, 0xa9, 0x01, 0x2f, 0xa5, 0x7f, 0x21, 0x2d, 0xdd, 0x04,
126    0xb3, 0x7f, 0x40, 0xb2, 0xb3, 0x6f, 0x1c, 0x18, 0x06, 0x2f, 0x50, 0xa0, 0x01, 0x2f, 0xba, 0x11,
127    0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x6e, 0x00, 0xa1, 0x7f, 0x11, 0x2d, 0xf7, 0x6f,
128    0xfb, 0x05, 0xb7, 0x7f, 0x25, 0x05, 0xb5, 0x6f, 0x2c, 0x18, 0x40, 0xb2, 0x06, 0x2f, 0x50, 0xa0,
129    0x01, 0x2f, 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x5e, 0x00, 0xa1, 0x7f,
130    0x00, 0x2e, 0xa0, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0x02, 0x01, 0x8e, 0xbc, 0x01, 0x2e,
131    0x62, 0x00, 0x9e, 0xb8, 0x01, 0x1a, 0x5f, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8,
132    0x21, 0x2e, 0x62, 0x00, 0x03, 0x2e, 0x62, 0x00, 0x43, 0xb2, 0x10, 0x24, 0x65, 0x00, 0x3c, 0x2f,
133    0x42, 0xb2, 0x22, 0x2f, 0x41, 0xb2, 0x06, 0x2f, 0x01, 0x30, 0x11, 0x42, 0x01, 0x42, 0x3e, 0x80,
134    0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0x90, 0x62, 0x30, 0x11, 0x24,
135    0x81, 0x00, 0x07, 0x2f, 0x30, 0x25, 0x34, 0x37, 0xd4, 0x42, 0xc2, 0x42, 0xfe, 0x86, 0x00, 0x2e,
136    0xc1, 0x42, 0x00, 0x2e, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x35, 0x2f, 0x63, 0x36, 0x13, 0x42,
137    0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0xb2,
138    0x52, 0x30, 0x21, 0x32, 0x0a, 0x2f, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x24, 0x2f, 0x23, 0x31,
139    0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x32, 0x13, 0x42,
140    0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0xb2,
141    0x42, 0x30, 0x11, 0x31, 0x0a, 0x2f, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x0c, 0x2f, 0xa3, 0x30,
142    0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x63, 0x31, 0x13, 0x42,
143    0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x10, 0x24, 0x78, 0x00, 0x11, 0x24,
144    0x52, 0xf0, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x42, 0x42,
145    0x42, 0x82, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x7e, 0x80, 0xa8, 0xb4, 0x01, 0x42,
146    0xb8, 0x2e, 0x12, 0x24, 0x71, 0x00, 0x90, 0x40, 0x84, 0x82, 0x20, 0x50, 0x50, 0x42, 0x77, 0x80,
147    0x82, 0x40, 0x42, 0x42, 0xfb, 0x7f, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82,
148    0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x77, 0x84, 0x00, 0x2e,
149    0x90, 0x40, 0x84, 0x82, 0x82, 0x40, 0x50, 0x42, 0x77, 0x80, 0x42, 0x42, 0x05, 0x82, 0x00, 0x40,
150    0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40,
151    0x40, 0x42, 0x7c, 0x82, 0xe1, 0x7f, 0x98, 0x2e, 0x03, 0xb1, 0xe2, 0x6f, 0x00, 0x2e, 0x90, 0x42,
152    0x81, 0x42, 0xbc, 0x82, 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a,
153    0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80,
154    0x52, 0x42, 0x00, 0x2e, 0x22, 0x40, 0x00, 0x40, 0x28, 0xbd, 0x10, 0x0a, 0x40, 0x42, 0x00, 0x2e,
155    0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x11, 0x24, 0x28, 0xf0, 0x50, 0x50, 0x60, 0x40, 0xf0, 0x7f,
156    0x51, 0x25, 0x60, 0x40, 0xe0, 0x7f, 0x00, 0x2e, 0x41, 0x40, 0xd1, 0x7f, 0x00, 0x2e, 0xe2, 0x6f,
157    0xd0, 0x6f, 0x00, 0xb2, 0xf3, 0x6f, 0xa8, 0xb8, 0x28, 0xbe, 0x59, 0x0a, 0x20, 0x0a, 0x01, 0x2f,
158    0xb0, 0x5f, 0xb8, 0x2e, 0x45, 0x41, 0xc5, 0x7f, 0x00, 0x2e, 0xc5, 0x6f, 0x40, 0x91, 0x09, 0x2f,
159    0x05, 0x2e, 0x28, 0xf0, 0xb2, 0x7f, 0x00, 0x2e, 0xb2, 0x6f, 0x1a, 0x1a, 0x07, 0x2f, 0xf0, 0x3f,
160    0x13, 0x25, 0x05, 0x2d, 0x15, 0x1a, 0x02, 0x2f, 0x10, 0x24, 0xff, 0x00, 0x20, 0x0a, 0xb0, 0x5f,
161    0xb8, 0x2e, 0x01, 0x2e, 0x03, 0x01, 0x8f, 0xbc, 0x01, 0x2e, 0x1f, 0x00, 0x9f, 0xb8, 0x01, 0x1a,
162    0x12, 0x2f, 0x01, 0x2e, 0x03, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x21, 0x2e, 0x1f, 0x00, 0x11, 0x30,
163    0x05, 0x2e, 0x1f, 0x00, 0x51, 0x08, 0xd2, 0x3f, 0x01, 0x2e, 0x07, 0xf0, 0x02, 0x08, 0x91, 0xbc,
164    0x01, 0x0a, 0x21, 0x2e, 0x07, 0xf0, 0xb8, 0x2e, 0xb8, 0x2e, 0x50, 0x50, 0xf2, 0x7f, 0xe1, 0x7f,
165    0x01, 0x30, 0xd1, 0x7f, 0xc1, 0x7f, 0x10, 0x24, 0x91, 0x04, 0xf2, 0x6f, 0xe3, 0x6f, 0x1c, 0x2d,
166    0xc4, 0x6f, 0x9c, 0x01, 0xd5, 0x6f, 0x86, 0x41, 0x6e, 0x0d, 0xd5, 0x7f, 0xb1, 0x7f, 0x0e, 0x2d,
167    0xd6, 0x6f, 0xef, 0xba, 0x61, 0xbf, 0x40, 0x91, 0x01, 0x2f, 0xd6, 0x7f, 0x03, 0x2d, 0x70, 0x0d,
168    0xd5, 0x7f, 0x00, 0x2e, 0xb5, 0x6f, 0x41, 0x8b, 0xb5, 0x7f, 0x00, 0x2e, 0xb5, 0x6f, 0x50, 0xa3,
169    0xee, 0x2f, 0x01, 0x89, 0xc4, 0x7f, 0x00, 0x2e, 0xc4, 0x6f, 0x62, 0x0e, 0xe0, 0x2f, 0xd0, 0x6f,
170    0xb0, 0x5f, 0xb8, 0x2e, 0x90, 0x50, 0xd3, 0x7f, 0xfb, 0x7f, 0xc2, 0x7f, 0xb1, 0x7f, 0x11, 0x30,
171    0xa1, 0x7f, 0x1a, 0x25, 0xc2, 0x6f, 0x72, 0x7f, 0x77, 0x82, 0xb2, 0x6f, 0x82, 0x7f, 0xe2, 0x7f,
172    0x22, 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0x90, 0x7f, 0x00, 0x2e, 0xe1, 0x6f, 0xd0, 0x6f, 0x41, 0x16,
173    0x92, 0x6f, 0x01, 0x08, 0x51, 0x08, 0x48, 0x1a, 0x01, 0x2f, 0x01, 0x30, 0xa1, 0x7f, 0x00, 0x2e,
174    0xfb, 0x6f, 0xa0, 0x6f, 0x70, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xe3, 0x7f, 0xfb, 0x7f, 0xc1, 0x7f,
175    0xd2, 0x7f, 0x1a, 0x25, 0xc0, 0x6f, 0xd2, 0x6f, 0x90, 0x7f, 0xa2, 0x7f, 0x79, 0x82, 0xe2, 0x6f,
176    0xb2, 0x7f, 0x32, 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0xfb, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0xb0, 0x50,
177    0xa4, 0x7f, 0xfb, 0x7f, 0x93, 0x7f, 0x82, 0x7f, 0x71, 0x7f, 0x00, 0x30, 0xa1, 0x6f, 0xe1, 0x7f,
178    0x40, 0x42, 0x00, 0x2e, 0x92, 0x6f, 0x83, 0x6f, 0x71, 0x6f, 0xd3, 0x7f, 0xc2, 0x7f, 0xb1, 0x7f,
179    0x98, 0x2e, 0x7a, 0xb1, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0xb2, 0x1e, 0x2f, 0xb1, 0x6f,
180    0xf2, 0x30, 0x8a, 0x08, 0x13, 0x24, 0xf0, 0x00, 0x4b, 0x08, 0x24, 0xbd, 0x94, 0xb8, 0x51, 0x0a,
181    0x51, 0x7f, 0x00, 0x2e, 0x51, 0x6f, 0x81, 0x16, 0xd3, 0x6f, 0x9a, 0x08, 0xc4, 0x6f, 0xe1, 0x08,
182    0xe1, 0x6f, 0x93, 0x0a, 0x42, 0x42, 0x12, 0x24, 0x00, 0xff, 0x43, 0x40, 0x9a, 0x08, 0x14, 0x24,
183    0xff, 0x00, 0xdc, 0x08, 0xb8, 0xbd, 0x28, 0xb9, 0x9a, 0x0a, 0x42, 0x42, 0x00, 0x2e, 0xfb, 0x6f,
184    0x50, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xd4, 0x7f, 0xfb, 0x7f, 0xc3, 0x7f, 0xa1, 0x7f, 0xb2, 0x7f,
185    0x02, 0x30, 0x92, 0x7f, 0x00, 0x2e, 0x05, 0x2e, 0x20, 0x00, 0xc4, 0x6f, 0x80, 0xb2, 0x0c, 0x2f,
186    0x81, 0x90, 0x1a, 0x2f, 0xd2, 0x6f, 0x07, 0x2e, 0x21, 0x00, 0xa1, 0x32, 0x98, 0x2e, 0xaf, 0xb1,
187    0x02, 0x30, 0x25, 0x2e, 0x20, 0x00, 0x92, 0x7f, 0x10, 0x2d, 0xa1, 0x6f, 0xb2, 0x6f, 0xe4, 0x7f,
188    0xa3, 0x32, 0x98, 0x2e, 0x9c, 0xb1, 0x21, 0x2e, 0x21, 0x00, 0xe2, 0x6f, 0x03, 0x2e, 0x21, 0x00,
189    0x81, 0x42, 0x12, 0x30, 0x25, 0x2e, 0x20, 0x00, 0x92, 0x7f, 0x00, 0x2e, 0xfb, 0x6f, 0x90, 0x6f,
190    0x90, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0x00, 0x30, 0xf0, 0x7f, 0x12, 0x24, 0x86, 0x00, 0x1b, 0x2d,
191    0xf1, 0x6f, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42,
192    0x8c, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42,
193    0x8c, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42,
194    0x41, 0x82, 0xf1, 0x7f, 0xb4, 0x84, 0xf1, 0x6f, 0x43, 0xa2, 0xe1, 0x2f, 0xf0, 0x5f, 0xb8, 0x2e,
195    0xc0, 0x50, 0x92, 0x7f, 0xfb, 0x7f, 0x81, 0x7f, 0x00, 0x30, 0x60, 0x7f, 0x70, 0x7f, 0x50, 0x7f,
196    0x00, 0x2e, 0x03, 0x2e, 0x04, 0x01, 0x9d, 0xbc, 0x9e, 0xb8, 0x41, 0x7f, 0x00, 0x2e, 0x42, 0x6f,
197    0x52, 0x7f, 0xe2, 0x7f, 0x00, 0x2e, 0x83, 0x6f, 0xc4, 0x82, 0xd3, 0x7f, 0x0c, 0x2d, 0x55, 0x6f,
198    0x7f, 0x89, 0xdc, 0x01, 0x9d, 0x01, 0xcb, 0x41, 0x8b, 0x43, 0xcc, 0x01, 0x4d, 0x01, 0xc7, 0x41,
199    0x47, 0x43, 0x54, 0x7f, 0x00, 0x2e, 0x54, 0x6f, 0x00, 0xab, 0xf0, 0x2f, 0x9b, 0x6f, 0x8a, 0x00,
200    0x4b, 0x42, 0xc2, 0x7f, 0xb1, 0x7f, 0x50, 0x7f, 0x7c, 0x80, 0xa0, 0x7f, 0x13, 0x24, 0x09, 0x01,
201    0x3f, 0x2d, 0x50, 0x6f, 0x18, 0x01, 0xc8, 0x84, 0xc8, 0x00, 0x50, 0x00, 0x05, 0x41, 0xc7, 0x40,
202    0x44, 0x40, 0x61, 0x6f, 0x73, 0x6f, 0x2f, 0x18, 0x00, 0xb3, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f,
203    0x30, 0x89, 0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15,
204    0xfc, 0x11, 0xae, 0x0b, 0x4e, 0x00, 0xdf, 0x02, 0x61, 0x7f, 0x73, 0x7f, 0xb4, 0x84, 0x01, 0x82,
205    0xd1, 0x00, 0x88, 0x80, 0xa2, 0x6f, 0x11, 0x01, 0x81, 0x00, 0xc3, 0x40, 0x05, 0x41, 0x84, 0x40,
206    0x1d, 0x18, 0x72, 0x6f, 0x00, 0xb3, 0x63, 0x6f, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89,
207    0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, 0xfc, 0x11,
208    0xae, 0x0b, 0xde, 0x04, 0x97, 0x06, 0x63, 0x7f, 0x72, 0x7f, 0x51, 0x7f, 0x3c, 0x86, 0xb1, 0x6f,
209    0xe2, 0x6f, 0x50, 0x6f, 0x42, 0x0e, 0xbc, 0x2f, 0xe0, 0x6f, 0xc8, 0x82, 0x98, 0x00, 0x48, 0x00,
210    0xc0, 0x6f, 0x83, 0x40, 0x04, 0x40, 0x42, 0x40, 0x61, 0x6f, 0x70, 0x6f, 0x80, 0xb2, 0x1c, 0x18,
211    0x0b, 0x2f, 0x90, 0xa0, 0x03, 0x2f, 0xb0, 0x84, 0xba, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x03, 0x31,
212    0xda, 0x04, 0xfb, 0x14, 0x32, 0x13, 0xfa, 0x11, 0xa3, 0x0b, 0x4e, 0x00, 0x07, 0x02, 0x61, 0x7f,
213    0x70, 0x7f, 0x00, 0x2e, 0x72, 0x6f, 0x80, 0xa8, 0x60, 0x6f, 0xd1, 0x6f, 0x13, 0x2f, 0x80, 0x90,
214    0x03, 0x2f, 0x13, 0x24, 0xff, 0x7f, 0x43, 0x0f, 0x0d, 0x2f, 0xbf, 0xa0, 0x07, 0x2f, 0xbf, 0x90,
215    0x03, 0x2f, 0x12, 0x24, 0x00, 0x80, 0x42, 0x0e, 0x01, 0x2f, 0x40, 0x42, 0x07, 0x2d, 0x10, 0x24,
216    0x00, 0x80, 0x40, 0x42, 0x03, 0x2d, 0x10, 0x24, 0xff, 0x7f, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f,
217    0x40, 0x5f, 0x40, 0x40, 0xb8, 0x2e, 0x11, 0x24, 0x7b, 0x00, 0x30, 0x50, 0x10, 0x30, 0x50, 0x42,
218    0xfb, 0x7f, 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80,
219    0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42,
220    0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x3c, 0x80, 0x42, 0x42, 0x7e, 0x84,
221    0xe0, 0x7f, 0x86, 0x82, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f,
222    0x7d, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x0d, 0x82, 0x02, 0x40, 0xd1, 0x7f, 0x98, 0x2e,
223    0x40, 0xb2, 0xd1, 0x6f, 0x76, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x14, 0x82, 0x02, 0x40,
224    0xd1, 0x7f, 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x6f, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80,
225    0xe1, 0x6f, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42,
226    0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x00, 0x2e,
227    0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0x01, 0x2e, 0x55, 0xf0, 0xf0, 0x7f, 0x00, 0x2e,
228    0xf0, 0x6f, 0x21, 0x2e, 0x55, 0xf0, 0xf0, 0x5f, 0xb8, 0x2e, 0x20, 0x50, 0x00, 0x30, 0xe0, 0x7f,
229    0xfb, 0x7f, 0x11, 0x24, 0xb1, 0xf0, 0x42, 0x40, 0x43, 0x30, 0x93, 0x0a, 0x42, 0x42, 0x58, 0x82,
230    0x12, 0x24, 0xaf, 0x00, 0x62, 0x42, 0x12, 0x24, 0xff, 0x00, 0x42, 0x42, 0x69, 0x82, 0x72, 0x3c,
231    0x43, 0x40, 0x9a, 0x08, 0x83, 0x32, 0x93, 0x0a, 0x42, 0x42, 0x42, 0x82, 0x02, 0x3f, 0x43, 0x40,
232    0x9a, 0x08, 0x52, 0x42, 0x0b, 0x31, 0x4b, 0x42, 0x7e, 0x82, 0x72, 0x31, 0x42, 0x42, 0x00, 0x2e,
233    0x03, 0x2e, 0x40, 0xf0, 0x5f, 0xb2, 0x03, 0x2f, 0x03, 0x2e, 0x40, 0xf0, 0x5e, 0x90, 0x27, 0x2f,
234    0x11, 0x24, 0x00, 0x02, 0x12, 0x24, 0x05, 0x80, 0x13, 0x24, 0xff, 0xb7, 0x1b, 0x24, 0x00, 0xb0,
235    0x04, 0x30, 0x05, 0x30, 0x56, 0x32, 0x6e, 0x1a, 0x00, 0x2f, 0x25, 0x36, 0x69, 0x1a, 0x01, 0x2f,
236    0x5b, 0x25, 0x00, 0x2e, 0x56, 0x41, 0x26, 0x0d, 0x06, 0x30, 0xcf, 0xbb, 0x41, 0xbe, 0xc0, 0x91,
237    0x01, 0x2f, 0x00, 0x2e, 0x01, 0x2d, 0x22, 0x0d, 0x81, 0x8d, 0x90, 0xa1, 0xf5, 0x2f, 0xeb, 0x0e,
238    0xe8, 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x20, 0x1a, 0x05, 0x2f, 0x20, 0x30, 0xe0, 0x7f, 0x03, 0x2d,
239    0x30, 0x30, 0xe0, 0x7f, 0x00, 0x2e, 0xe0, 0x6f, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0,
240    0x98, 0x2e, 0x43, 0xb3, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e,
241    0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f,
242    0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x43, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, 0x7f,
243    0x00, 0x2e, 0x60, 0x6f, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0xb9, 0xb0, 0x40, 0x30, 0x21, 0x2e,
244    0xb8, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f,
245    0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f,
246    0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e,
247    0x29, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0x90, 0x1b, 0x2f,
248    0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x2e, 0x04, 0x01,
249    0x0f, 0xbc, 0x0f, 0xb8, 0x01, 0xb2, 0x0d, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x01, 0x90, 0x04, 0x2f,
250    0x98, 0x2e, 0x1a, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, 0x01, 0x2e, 0x37, 0xf0, 0x21, 0x2e,
251    0x37, 0xf0, 0x02, 0x2d, 0x98, 0x2e, 0xf3, 0xb2, 0x80, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f,
252    0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f,
253    0x60, 0x5f, 0xc8, 0x2e, 0x60, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0f, 0x2e, 0x01, 0xf0,
254    0xfe, 0xbf, 0xfe, 0xbb, 0xb7, 0x05, 0xa6, 0x7f, 0xd3, 0x7f, 0xc4, 0x7f, 0xb5, 0x7f, 0x14, 0x24,
255    0x89, 0xf0, 0x3f, 0x8b, 0x03, 0x41, 0x44, 0x41, 0xb8, 0xbd, 0x9c, 0x0b, 0xa3, 0x6f, 0x14, 0x24,
256    0x9a, 0x00, 0xb3, 0x11, 0x43, 0x8b, 0x16, 0x43, 0x00, 0x2e, 0x67, 0x41, 0x46, 0x41, 0xf8, 0xbf,
257    0xbe, 0x0b, 0xb3, 0x11, 0x16, 0x43, 0x43, 0x8d, 0x00, 0x2e, 0xa5, 0x41, 0x86, 0x41, 0xd8, 0xbe,
258    0x6e, 0x0b, 0xeb, 0x10, 0x03, 0x43, 0x13, 0x30, 0x27, 0x2e, 0x22, 0x00, 0x03, 0x31, 0x27, 0x2e,
259    0xb8, 0xf0, 0xf6, 0x6f, 0xe7, 0x6f, 0xc4, 0x6f, 0xb5, 0x6f, 0xd3, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e,
260    0xa0, 0x50, 0x80, 0x7f, 0x91, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f,
261    0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0xb9, 0xf0, 0x60, 0x7f, 0x10, 0x30, 0x61, 0x6f,
262    0x08, 0x08, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0x9e, 0x00, 0x10, 0x30, 0x21, 0x2e, 0xb9, 0xf0,
263    0x21, 0x2e, 0x5f, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f,
264    0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0x20, 0x50, 0xe7, 0x7f, 0xf6, 0x7f,
265    0x56, 0x32, 0x0f, 0x2e, 0x58, 0xf0, 0x7e, 0x1a, 0x02, 0x2f, 0x16, 0x30, 0x2d, 0x2e, 0x23, 0x00,
266    0x16, 0x24, 0x80, 0x00, 0x2d, 0x2e, 0xb9, 0xf0, 0xe7, 0x6f, 0xf6, 0x6f, 0xe0, 0x5f, 0xc8, 0x2e,
267    0x30, 0x50, 0x04, 0x30, 0xd4, 0x7f, 0xe4, 0x7f, 0xfb, 0x7f, 0x13, 0x24, 0x26, 0xf0, 0xc2, 0x40,
268    0xc1, 0x86, 0xe4, 0x7f, 0xd2, 0x7f, 0x00, 0x2e, 0xd1, 0x40, 0x18, 0xbc, 0x18, 0xba, 0xd2, 0x6f,
269    0xe1, 0x6f, 0x90, 0x0a, 0x0c, 0x0b, 0xd2, 0x7f, 0xe4, 0x7f, 0x00, 0x2e, 0xe4, 0x6f, 0xc3, 0x40,
270    0xe3, 0x0a, 0xdb, 0x6f, 0xdb, 0x7f, 0xe3, 0x7f, 0x13, 0x24, 0x15, 0x01, 0xe2, 0x6f, 0x09, 0x2e,
271    0x16, 0x01, 0xd1, 0x6f, 0x98, 0x2e, 0xea, 0xb1, 0x21, 0x2e, 0x58, 0xf0, 0x98, 0x2e, 0x43, 0xb3,
272    0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x98, 0x2e, 0x4d, 0xb3, 0x20, 0x26, 0x98, 0x2e, 0xfa, 0x01,
273    0x98, 0x2e, 0xf5, 0xb4, 0x98, 0x2e, 0xf1, 0xb4, 0x98, 0x2e, 0xde, 0xb4, 0x98, 0x2e, 0xf9, 0xb4,
274    0x01, 0x2e, 0x40, 0xf0, 0x21, 0x2e, 0x9d, 0x00, 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e,
275    0x43, 0xb3, 0x21, 0x30, 0x10, 0x24, 0x9a, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x05, 0x2e,
276    0x22, 0x00, 0x80, 0xb2, 0x02, 0x30, 0x05, 0x2f, 0x23, 0x2e, 0x5f, 0xf0, 0x25, 0x2e, 0x22, 0x00,
277    0x98, 0x2e, 0x17, 0x01, 0x98, 0x2e, 0x31, 0xb1, 0x01, 0x2e, 0x23, 0x00, 0x01, 0x90, 0x00, 0x30,
278    0xe7, 0x2f, 0x21, 0x2e, 0x23, 0x00, 0x98, 0x2e, 0x80, 0xb4, 0xe3, 0x2d, 0x80, 0x30, 0x21, 0x2e,
279    0xba, 0xf0, 0x10, 0x24, 0x80, 0x00, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x0a, 0x21, 0x2e, 0x06, 0xf0,
280    0x00, 0x3e, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x08, 0x51, 0x30, 0x01, 0x0a, 0x21, 0x2e, 0x06, 0xf0,
281    0xb8, 0x2e, 0x00, 0x31, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x10, 0x30, 0x21, 0x2e, 0xbb, 0xf0,
282    0xb8, 0x2e, 0x10, 0x24, 0x80, 0x00, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, 0x1a, 0x24, 0x26, 0x00,
283    0x80, 0x2e, 0xab, 0xb4, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
284    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
285    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
286    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
287    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
288    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
289    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
290    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
291    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
292    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
293    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
294    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
295    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
296    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
297    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
298    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
299    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
300    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
301    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
302    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
303    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
304    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
305    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
306    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
307    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
308    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
309    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
310    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
311    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
312    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
313    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
314    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
315    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
316    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
317    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
318    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
319    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
320    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
321    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
322    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
323    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
324    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
325    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
326    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
327    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
328    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
329    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
330    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
331    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
332    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
333    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
334    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
335    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
336    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
337    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
338    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
339    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
340    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
341    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
342    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
343    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
344    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
345    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
346    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
347    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
348    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
349    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
350    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
351    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
352    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
353    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
354    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
355    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
356    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
357    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
358    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
359    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
360    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
361    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
362    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
363    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
364    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
365    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
366    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
367    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
368    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
369    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
370    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
371    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
372    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
373    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
374    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
375    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
376    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
377    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
378    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
379    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
380    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
381    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
382    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
383    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
384    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
385    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
386    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
387    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
388    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
389    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
390    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
391    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
392    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
393    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
394    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
395    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
396    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
397    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
398    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
399    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
400    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
401    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
402    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
403    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
404    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
405    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
406    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
407    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
408    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
409    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
410    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
411    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
412    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
413    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
414    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
415    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
416    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
417    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
418    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
419    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
420    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
421    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
422    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
423    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
424    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
425    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
426    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
427    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
428    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
429    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
430    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
431    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
432    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
433    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
434    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
435    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
436    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
437    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
438    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
439    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
440    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
441    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
442    0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
443];
444
445// 0,1,2,3 --> 3,6,12,24g for BMI088;
446#[repr(u32)]
447#[derive(Clone, Copy)]
448pub enum AccelRange088 {
449    Max3G = 0,
450    Max6G = 1,
451    Max12G = 2,
452    Max24G = 3,
453}
454// 0,1,2,3 --> 3,6,12,24g for BMI088;
455#[repr(u32)]
456#[derive(Clone, Copy)]
457pub enum AccelRange085 {
458    Max2g = 0,
459    Max4g = 1,
460    Max8g = 2,
461    Max16g = 3,
462}
463
464pub enum AccelRange {
465    Bmi088(AccelRange088),
466    Bmi085(AccelRange085),
467}
468
469// 0,1,2,3,4 --> 2000,1000,500,250,125 deg/s
470#[repr(u8)]
471#[derive(Clone, Copy)]
472pub enum GyroRange {
473    Max125dps = 0x04,
474    Max250dps = 0x03,
475    Max500dps = 0x02,
476    Max1000dps = 0x01,
477    Max2000dps = 0x00,
478}
479
480#[repr(u8)]
481#[derive(Clone, Copy)]
482pub enum GyroBandwidth {
483    Odr2000Hz = 0x01, // BMI08_GYRO_BW_230_ODR_2000_HZ
484    Odr1000Hz = 0x02, // BMI08_GYRO_BW_116_ODR_1000_HZ
485    Odr400Hz = 0x03,  // BMI08_GYRO_BW_47_ODR_400_HZ
486}
487
488#[repr(u8)]
489#[derive(Clone, Copy)]
490pub enum SampleRate {
491    Odr2000Hz = 0x03, // BMI08_ACCEL_DATA_SYNC_MODE_2000HZ
492    Odr1000Hz = 0x02, // BMI08_ACCEL_DATA_SYNC_MODE_1000HZ
493    Odr400Hz = 0x01,  // BMI08_ACCEL_DATA_SYNC_MODE_400HZ
494}
495
496const SPI_READ: u8 = 0x80;
497const SPI_WRITE: u8 = 0x00;
498
499pub struct Bmi08xSensor {
500    pub dev_a: SpiDevice<
501        'static,
502        CriticalSectionRawMutex,
503        spi::Spi<'static, Async, spi::mode::Master>,
504        Output<'static>,
505    >,
506    pub dev_g: SpiDevice<
507        'static,
508        CriticalSectionRawMutex,
509        spi::Spi<'static, Async, spi::mode::Master>,
510        Output<'static>,
511    >,
512
513    pub sample_rate: SampleRate,
514
515    pub drdy_a: ExtiInput<'static, Async>,
516    pub drdy_g: ExtiInput<'static, Async>,
517    pub jumper: Output<'static>,
518
519    pub range_a: AccelRange,
520    pub range_g: GyroRange,
521}
522
523impl Bmi08xSensor {
524    async fn read_register_a(&mut self, reg_addr: u8) -> u8 {
525        let tx = [reg_addr | SPI_READ, 0x00, 0x00];
526        let mut rx = [0u8; 3];
527        let _ = self.dev_a.transfer(&mut rx, &tx).await;
528        rx[2]
529    }
530    async fn read_register_g(&mut self, reg_addr: u8) -> u8 {
531        let tx = [reg_addr | SPI_READ, 0x00];
532        let mut rx = [0u8; 2];
533        let _ = self.dev_g.transfer(&mut rx, &tx).await;
534        rx[1]
535    }
536
537    async fn write_register_a(&mut self, reg_addr: u8, value: u8) {
538        let tx = [reg_addr | SPI_WRITE, value];
539        let _ = self.dev_a.write(&tx).await; // Soft Reset
540    }
541
542    async fn write_register_g(&mut self, reg_addr: u8, value: u8) {
543        let tx = [reg_addr | SPI_WRITE, value];
544        let _ = self.dev_g.write(&tx).await; // Soft Reset
545    }
546
547    pub async fn run(&mut self) {
548        // time for power-on
549        Timer::after_millis(50).await;
550
551        const ACCEL_PROD_ID_REG: u8 = 0x00; //BMI08_REG_ACCEL_CHIP_ID
552        const ACCEL_PROD_ID_088: u8 = 0x1E;
553        const ACCEL_PROD_ID_085: u8 = 0x1F;
554
555        // Check Accel ID  (0x80)
556        let _ = self.read_register_a(ACCEL_PROD_ID_REG).await; // Lock to SPI mode
557
558        // Second Read is to get the ID
559        let accel_id = self.read_register_a(ACCEL_PROD_ID_REG).await;
560        let mut accel_range: f64 = 0f64;
561
562        if accel_id == ACCEL_PROD_ID_088 {
563            accel_range = match &self.range_a {
564                AccelRange::Bmi088(range) => {
565                    3.0 * ((0x0001 << (*range as u32)) as f64) * 9.80665f64
566                }
567                AccelRange::Bmi085(range) => {
568                    2.0 * ((0x0001 << (*range as u32)) as f64) * 9.80665f64
569                }
570            };
571        } else if accel_id == ACCEL_PROD_ID_085 {
572            accel_range = match &self.range_a {
573                AccelRange::Bmi088(range) => {
574                    3.0 * ((0x0001 << (*range as u32)) as f64) * 9.80665f64
575                }
576                AccelRange::Bmi085(range) => {
577                    2.0 * ((0x0001 << (*range as u32)) as f64) * 9.80665f64
578                }
579            };
580        }
581
582        const GYRO_PROD_ID_REG: u8 = 0x00; // BMI08_REG_GYRO_CHIP_ID
583        const GYRO_PROD_ID: u8 = 0x0F;
584
585        // Second Read is to get the ID
586        let gyro_id = self.read_register_g(GYRO_PROD_ID_REG).await;
587        let mut gyro_range: f64 = 0f64;
588
589        if gyro_id == GYRO_PROD_ID {
590            gyro_range = match &self.range_g {
591                GyroRange::Max125dps => 125.0f64,
592                GyroRange::Max250dps => 250.0f64,
593                GyroRange::Max500dps => 500.0f64,
594                GyroRange::Max1000dps => 1000.0f64,
595                GyroRange::Max2000dps => 2000.0f64,
596            } * 0.017453292519943295f64;
597        }
598
599        // Accel Soft Reset (0x7E, 0xB6) //BMI08_REG_ACCEL_SOFTRESET
600        self.write_register_a(0x7E, 0xB6).await;
601        Timer::after_micros(1000).await; // required
602
603        // Lock to SPI mode again (after soft reset)
604        self.read_register_a(ACCEL_PROD_ID_REG).await;
605        Timer::after_micros(4900).await; // not needed? It's in the Bosh code
606
607        // Activate Accel (0x7C,0x00) //BMI08_REG_ACCEL_PWR_CONF
608        self.write_register_a(0x7C, 0x00).await;
609        Timer::after_micros(450).await; // required
610
611        // Disable "Config Loading" (0x59, 0x00) // BMI08_REG_ACCEL_INIT_CTRL
612        self.write_register_a(0x59, 0x00).await;
613
614        // Write Sensor Program
615        const BLOCK_SIZE: usize = 32;
616        for (index, block) in BMI_CONFIG.chunks(BLOCK_SIZE).enumerate() {
617            self.write_register_a(0x5B, 0x00).await; //BMI08_REG_ACCEL_RESERVED_5B
618            self.write_register_a(0x5C, index as u8).await; //BMI08_REG_ACCEL_RESERVED_5C
619            let mut tx = [0u8; BLOCK_SIZE + 1];
620            tx[0] = 0x5E | SPI_WRITE; // BMI08_REG_ACCEL_FEATURE_CFG
621            for (i, &item) in block.iter().enumerate() {
622                tx[i + 1] = item;
623            }
624            let _ = self.dev_a.write(&tx).await;
625        }
626
627        // Re-enable "Config Loading"
628        self.write_register_a(0x59, 0x01).await;
629        Timer::after_micros(150000).await; // required?
630
631        // Unknown status register read (0x2A|SPI_READ)
632        // BMI08_REG_ACCEL_INIT_CTRL = 0x2A   (0xAA)
633        let _ = self.read_register_a(0x2A).await;
634
635        // Activate Accel, again (0x7C,0x00)
636        // BMI08_REG_ACCEL_PWR_CONF = 0x7C
637        self.write_register_a(0x7C, 0x00).await;
638        Timer::after_micros(450).await; // required, was 5000us, using 450us like above
639
640        // Accelerometer ON (0x7D,0x04)
641        // BMI08_REG_ACCEL_PWR_CTRL = 0x7D
642        self.write_register_a(0x7D, 0x04).await; //
643        Timer::after_micros(100).await;
644
645        // Read/Write Low Power Mode
646        // BMI08_REG_GYRO_LPM1 = 0x11 (0x91)
647        let _ = self.read_register_g(0x11).await;
648        self.write_register_g(0x11, 0x00).await;
649        Timer::after_millis(30).await;
650
651        // Read/Write Gyro Bandwidth
652        // BMI08_REG_GYRO_BANDWIDTH = 0x10 (0x90)
653        let gyro_bw = match self.sample_rate {
654            SampleRate::Odr2000Hz => GyroBandwidth::Odr2000Hz as u8,
655            SampleRate::Odr1000Hz => GyroBandwidth::Odr1000Hz as u8,
656            SampleRate::Odr400Hz => GyroBandwidth::Odr400Hz as u8,
657        };
658        let _ = self.read_register_g(0x10).await;
659        self.write_register_g(0x10, gyro_bw).await;
660
661        // Read/Write Gyro Range
662        // BMI08_REG_GYRO_RANGE = 0x0F (0x8F)
663        let _ = self.read_register_g(0x0F).await;
664        self.write_register_g(0x0F, self.range_g as u8).await;
665        Timer::after_micros(10000).await; // do we need this delay??
666
667        // Read/Write BMI08_REG_ACCEL_FEATURE_CFG 7+1 bytes
668        // This is undocumented, from Bosh drivers
669        const BMI08_REG_ACCEL_FEATURE_CFG: u8 = 0x5E; //(0xDE)
670        const BMI08_ACCEL_DATA_SYNC_MODE_MASK: u8 = 0x03;
671        let mut tx = [0u8; 8];
672        let mut sync_cfg = [0u8; 8];
673        tx[0] = BMI08_REG_ACCEL_FEATURE_CFG | SPI_READ;
674        let _ = self.dev_a.transfer(&mut sync_cfg, &tx).await;
675
676        // Unclear why this is 16-bit data, just following what Bosh does
677        sync_cfg[1] = BMI08_REG_ACCEL_FEATURE_CFG | SPI_WRITE; // 0x5E
678        let sync_cfg_mode = self.sample_rate as u8;
679        let reg_data = sync_cfg_mode & BMI08_ACCEL_DATA_SYNC_MODE_MASK;
680        sync_cfg[6] = reg_data; // low byte
681        sync_cfg[7] = 0; // high byte
682        let _ = self.dev_a.write(&sync_cfg[1..]).await;
683
684        Timer::after_micros(100000).await; // delay of 100ms for data sync to take effect.
685
686        // BMI08_REG_ACCEL_INT2_IO_CONF = 0x54 (0xD4)
687        let _ = self.read_register_a(0x54).await;
688        self.write_register_a(0x54, 0x13).await; //Int2 as input, active high, reserved[0] = 1
689        // BMI08_REG_ACCEL_INT1_MAP = 0x56
690        self.write_register_a(0x56, 0x01).await; // undocumented
691        // BMI08_INT1_INT2_MAP_DATA = 0x58
692        self.write_register_a(0x58, 0x04).await; // !! change, map data ready interrupt to Int1
693
694        // BMI08_REG_ACCEL_INT1_IO_CONF = 0x53 (0xD3)
695        let _ = self.read_register_a(0x53).await;
696        self.write_register_a(0x53, 0x0A).await; //Int1 as output, active high
697
698        // BMI08_REG_ACCEL_CONF = 0x40
699        //	readRegisterA(BMI08_REG_ACCEL_CONF); 		// (0x40)
700        //	writeRegisterA(BMI08_REG_ACCEL_CONF, rangeA_);// (0x40,0x0A) Int1 as output, active high
701
702        // BMI08_REG_GYRO_INT3_INT4_IO_MAP = 0x18 (0x98)
703        let _ = self.read_register_g(0x18).await;
704        self.write_register_g(0x18, 0x81).await; //(0x18,0x80) 0x81 to map drdy to both int3 and int4
705
706        // BMI08_REG_GYRO_INT3_INT4_IO_CONF = 0x16 (0x96)
707        let _ = self.read_register_g(0x16).await; // (0x96)
708        self.write_register_g(0x16, 0x05).await; // (0x16,0x05)
709        //BMI08_REG_GYRO_INT_CTRL = 0x15
710        self.write_register_g(0x15, 0x80).await; //(0x15,0x80) Enable drdy interrupt on new data
711
712        // yes this is a repeat sequence
713        // BMI08_REG_GYRO_INT3_INT4_IO_MAP = 0x18 (0x98)
714        let _ = self.read_register_g(0x18).await;
715        self.write_register_g(0x18, 0x81).await; //(0x18,0x80) 0x81 to map drdy to both int3 and int4
716
717        // BMI08_REG_GYRO_INT3_INT4_IO_CONF = 0x16 (0x96)
718        let _ = self.read_register_g(0x16).await; // (0x16)
719        self.write_register_g(0x16, 0x05).await; // (0x16,0x05)
720        //BMI08_REG_GYRO_INT_CTRL = 0x15
721        self.write_register_g(0x15, 0x80).await; //(0x15,0x80) Enable drdy interrupt on new data
722
723        // Done Initializations
724
725        let scale_factor_a = accel_range / 32767f64 / 4.0f64; // m/s^2
726        let scale_factor_g = gyro_range / 32767f64; // to rad/s
727
728        loop {
729            self.drdy_g.wait_for_rising_edge().await;
730
731            self.jumper.set_high();
732            Timer::after_micros(60).await;
733            self.jumper.set_low();
734
735            let timestamp = Instant::now();
736
737            // read temperature, ax, and ay
738            const BMI_ACCEL_CMD: u8 = 0x12;
739            const BMI_ACCEL_BYTES: usize = 20;
740            let mut rx = [0u8; BMI_ACCEL_BYTES];
741            let mut tx = [0u8; BMI_ACCEL_BYTES];
742            tx[0] = BMI_ACCEL_CMD | SPI_READ;
743            let _ = self.dev_a.transfer(&mut rx, &tx).await;
744
745            let seq = ((rx[8] as u64 | (rx[9] as u64) << 8 | (rx[10] as u64) << 16) * 625u64
746                / 16u64) as u32; // 625/64 = 39.0625us/count
747            let mut temperature = ((rx[18] as u32) << 3 | (((rx[19] as u32) >> 6) & 0x0003)) as f32;
748
749            if temperature > 1023.0 {
750                temperature -= 2048.0;
751            }
752
753            temperature *= 0.125;
754            temperature += 23.0; // + 273.15; // K
755
756            let mut accel = [0f64; 3];
757            accel[0] = scale_factor_a * (((rx[15] as i16) << 8 | (rx[14] as i16)) as f64);
758            accel[1] = scale_factor_a * (((rx[17] as i16) << 8 | (rx[16] as i16)) as f64);
759
760            // Read az
761            const BMI_ACCEL_SYNC_CMD: u8 = 0x27;
762            const BMI_ACCEL_SYNC_BYTES: usize = 4;
763            let mut rx = [0u8; BMI_ACCEL_SYNC_BYTES];
764            let mut tx = [0u8; BMI_ACCEL_SYNC_BYTES];
765            tx[0] = BMI_ACCEL_SYNC_CMD | SPI_READ;
766            let _ = self.dev_a.transfer(&mut rx, &tx).await;
767
768            accel[2] = scale_factor_a * (((rx[3] as i16) << 8 | (rx[2] as i16)) as f64);
769
770            // Read gyro
771            const BMI_GYRO_CMD: u8 = 0x02;
772            const BMI_GYRO_BYTES: usize = 7;
773            let mut rx = [0u8; BMI_GYRO_BYTES];
774            let mut tx = [0u8; BMI_GYRO_BYTES];
775            tx[0] = BMI_GYRO_CMD | SPI_READ;
776            let _ = self.dev_g.transfer(&mut rx, &tx).await;
777
778            let mut gyro = [0f64; 3];
779            gyro[0] = scale_factor_g * (((rx[2] as i16) << 8 | (rx[1] as i16)) as f64);
780            gyro[1] = scale_factor_g * (((rx[4] as i16) << 8 | (rx[3] as i16)) as f64);
781            gyro[2] = scale_factor_g * (((rx[6] as i16) << 8 | (rx[5] as i16)) as f64);
782
783            let status = 0u16; // dummy value
784            let header = packets::RosflightPacketHeader {
785                timestamp: timestamp.as_micros(),
786                status,
787            };
788            let imu_packet = packets::ImuPacket {
789                header,
790                accel,
791                gyro,
792                temperature,
793                seq,
794            };
795            IMU_SIGNAL.signal(Ok(imu_packet));
796        }
797    }
798}
799
800#[embassy_executor::task]
801pub async fn task(mut bmi: Bmi08xSensor) {
802    bmi.run().await;
803}