Add support for Bosch BMI270 gyro/accelerometer sensor

This commit is contained in:
Bruce Luckcuck 2020-01-17 18:08:43 -05:00
parent c29b125a59
commit 447cbac988
27 changed files with 26435 additions and 11 deletions

View File

@ -0,0 +1,30 @@
Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
BSD-3-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,19 @@
BMI2xy Sensor API
> This package contains BMI2xy sensor API
**Note : When updating from 2.19.0 to 2.34.0, the gyroscope offset calibration data cannot be reused. In case of a permanently stored gyroscope offset (inside the sensor NVM or on the host), please perform calibration again with API version 2.34.0.
## Sensor Overview
The BMI2xy is a small, low power, low noise inertial measurement unit designed for use in mobile applications like augmented reality or indoor navigation which require highly accurate, real-time sensor data.
### Features
- Indoor navigation, pedestrian dead-reckoning, step-counting
For more information refer [product page](https://www.bosch-sensortec.com/bst/products/all_products/bmi270)
---
#### Copyright (C) 2019 Bosch Sensortec GmbH

After

Width:  |  Height:  |  Size: 777 B

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,640 @@
/**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi270.c
* @date 2020-01-10
* @version v2.46.1
*
*//***************************************************************************/
/*! Header files
****************************************************************************/
#include "bmi270.h"
/***************************************************************************/
/*! Global Variable
****************************************************************************/
/*! @name Global array that stores the configuration file of BMI270 */
const uint8_t bmi270_config_file[] = {
0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x3d, 0xb1, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x91, 0x03, 0x80, 0x2e, 0xbc,
0xb0, 0x80, 0x2e, 0xa3, 0x03, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x00, 0xb0, 0x50, 0x30, 0x21, 0x2e, 0x59, 0xf5,
0x10, 0x30, 0x21, 0x2e, 0x6a, 0xf5, 0x80, 0x2e, 0x3b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x01, 0x00, 0x22,
0x00, 0x75, 0x00, 0x00, 0x10, 0x00, 0x10, 0xd1, 0x00, 0xb3, 0x43, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x19, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
0xe0, 0xaa, 0x38, 0x05, 0xe0, 0x90, 0x30, 0xfa, 0x00, 0x96, 0x00, 0x4b, 0x09, 0x11, 0x00, 0x11, 0x00, 0x02, 0x00,
0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a, 0x04, 0x00, 0x3f, 0x7b, 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3,
0x04, 0xec, 0xe6, 0x0c, 0x46, 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00, 0xa0, 0x00, 0x01, 0x00, 0x0c, 0x00,
0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x32, 0x00, 0x05, 0x00, 0xee,
0x06, 0x04, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x04, 0x00, 0xa8, 0x05, 0xee, 0x06, 0x00, 0x04, 0xbc, 0x02, 0xb3, 0x00,
0x85, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xb4, 0x00, 0x01, 0x00, 0xb9, 0x00, 0x01, 0x00, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2e, 0x00, 0xc1, 0xfd, 0x2d, 0xde,
0x00, 0xeb, 0x00, 0xda, 0x00, 0x00, 0x0c, 0xff, 0x0f, 0x00, 0x04, 0xc0, 0x00, 0x5b, 0xf5, 0xc9, 0x01, 0x1e, 0xf2,
0x80, 0x00, 0x3f, 0xff, 0x19, 0xf4, 0x58, 0xf5, 0x66, 0xf5, 0x64, 0xf5, 0xc0, 0xf1, 0xf0, 0x00, 0xe0, 0x00, 0xcd,
0x01, 0xd3, 0x01, 0xdb, 0x01, 0xff, 0x7f, 0xff, 0x01, 0xe4, 0x00, 0x74, 0xf7, 0xf3, 0x00, 0xfa, 0x00, 0xff, 0x3f,
0xca, 0x03, 0x6c, 0x38, 0x56, 0xfe, 0x44, 0xfd, 0xbc, 0x02, 0xf9, 0x06, 0x00, 0xfc, 0x12, 0x02, 0xae, 0x01, 0x58,
0xfa, 0x9a, 0xfd, 0x77, 0x05, 0xbb, 0x02, 0x96, 0x01, 0x95, 0x01, 0x7f, 0x01, 0x82, 0x01, 0x89, 0x01, 0x87, 0x01,
0x88, 0x01, 0x8a, 0x01, 0x8c, 0x01, 0x8f, 0x01, 0x8d, 0x01, 0x92, 0x01, 0x91, 0x01, 0xdd, 0x00, 0x9f, 0x01, 0x7e,
0x01, 0xdb, 0x00, 0xb6, 0x01, 0x70, 0x69, 0x26, 0xd3, 0x9c, 0x07, 0x1f, 0x05, 0x9d, 0x00, 0x00, 0x08, 0xbc, 0x05,
0x37, 0xfa, 0xa2, 0x01, 0xaa, 0x01, 0xa1, 0x01, 0xa8, 0x01, 0xa0, 0x01, 0xa8, 0x05, 0xb4, 0x01, 0xb4, 0x01, 0xce,
0x00, 0xd0, 0x00, 0xfc, 0x00, 0xc5, 0x01, 0xff, 0xfb, 0xb1, 0x00, 0x00, 0x38, 0x00, 0x30, 0xfd, 0xf5, 0xfc, 0xf5,
0xcd, 0x01, 0xa0, 0x00, 0x5f, 0xff, 0x00, 0x40, 0xff, 0x00, 0x00, 0x80, 0x6d, 0x0f, 0xeb, 0x00, 0x7f, 0xff, 0xc2,
0xf5, 0x68, 0xf7, 0xb3, 0xf1, 0x67, 0x0f, 0x5b, 0x0f, 0x61, 0x0f, 0x80, 0x0f, 0x58, 0xf7, 0x5b, 0xf7, 0x83, 0x0f,
0x86, 0x00, 0x72, 0x0f, 0x85, 0x0f, 0xc6, 0xf1, 0x7f, 0x0f, 0x6c, 0xf7, 0x00, 0xe0, 0x00, 0xff, 0xd1, 0xf5, 0x87,
0x0f, 0x8a, 0x0f, 0xff, 0x03, 0xf0, 0x3f, 0x8b, 0x00, 0x8e, 0x00, 0x90, 0x00, 0xb9, 0x00, 0x2d, 0xf5, 0xca, 0xf5,
0xcb, 0x01, 0x20, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x50, 0x98, 0x2e,
0xd7, 0x0e, 0x50, 0x32, 0x98, 0x2e, 0xfa, 0x03, 0x00, 0x30, 0xf0, 0x7f, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x00,
0x2e, 0x01, 0x80, 0x08, 0xa2, 0xfb, 0x2f, 0x98, 0x2e, 0xba, 0x03, 0x21, 0x2e, 0x19, 0x00, 0x01, 0x2e, 0xee, 0x00,
0x00, 0xb2, 0x07, 0x2f, 0x01, 0x2e, 0x19, 0x00, 0x00, 0xb2, 0x03, 0x2f, 0x01, 0x50, 0x03, 0x52, 0x98, 0x2e, 0x07,
0xcc, 0x01, 0x2e, 0xdd, 0x00, 0x00, 0xb2, 0x27, 0x2f, 0x05, 0x2e, 0x8a, 0x00, 0x05, 0x52, 0x98, 0x2e, 0xc7, 0xc1,
0x03, 0x2e, 0xe9, 0x00, 0x40, 0xb2, 0xf0, 0x7f, 0x08, 0x2f, 0x01, 0x2e, 0x19, 0x00, 0x00, 0xb2, 0x04, 0x2f, 0x00,
0x30, 0x21, 0x2e, 0xe9, 0x00, 0x98, 0x2e, 0xb4, 0xb1, 0x01, 0x2e, 0x18, 0x00, 0x00, 0xb2, 0x10, 0x2f, 0x05, 0x50,
0x98, 0x2e, 0x4d, 0xc3, 0x05, 0x50, 0x98, 0x2e, 0x5a, 0xc7, 0x98, 0x2e, 0xf9, 0xb4, 0x98, 0x2e, 0x54, 0xb2, 0x98,
0x2e, 0x67, 0xb6, 0x98, 0x2e, 0x17, 0xb2, 0x10, 0x30, 0x21, 0x2e, 0x77, 0x00, 0x01, 0x2e, 0xef, 0x00, 0x00, 0xb2,
0x04, 0x2f, 0x98, 0x2e, 0x7a, 0xb7, 0x00, 0x30, 0x21, 0x2e, 0xef, 0x00, 0x01, 0x2e, 0xd4, 0x00, 0x04, 0xae, 0x0b,
0x2f, 0x01, 0x2e, 0xdd, 0x00, 0x00, 0xb2, 0x07, 0x2f, 0x05, 0x52, 0x98, 0x2e, 0x8e, 0x0e, 0x00, 0xb2, 0x02, 0x2f,
0x10, 0x30, 0x21, 0x2e, 0x7d, 0x00, 0x01, 0x2e, 0x7d, 0x00, 0x00, 0x90, 0x90, 0x2e, 0xf1, 0x02, 0x01, 0x2e, 0xd7,
0x00, 0x00, 0xb2, 0x04, 0x2f, 0x98, 0x2e, 0x2f, 0x0e, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, 0x01, 0x2e, 0x7b, 0x00,
0x00, 0xb2, 0x12, 0x2f, 0x01, 0x2e, 0xd4, 0x00, 0x00, 0x90, 0x02, 0x2f, 0x98, 0x2e, 0x1f, 0x0e, 0x09, 0x2d, 0x98,
0x2e, 0x81, 0x0d, 0x01, 0x2e, 0xd4, 0x00, 0x04, 0x90, 0x02, 0x2f, 0x50, 0x32, 0x98, 0x2e, 0xfa, 0x03, 0x00, 0x30,
0x21, 0x2e, 0x7b, 0x00, 0x01, 0x2e, 0x7c, 0x00, 0x00, 0xb2, 0x90, 0x2e, 0x09, 0x03, 0x01, 0x2e, 0x7c, 0x00, 0x01,
0x31, 0x01, 0x08, 0x00, 0xb2, 0x04, 0x2f, 0x98, 0x2e, 0x47, 0xcb, 0x10, 0x30, 0x21, 0x2e, 0x77, 0x00, 0x81, 0x30,
0x01, 0x2e, 0x7c, 0x00, 0x01, 0x08, 0x00, 0xb2, 0x61, 0x2f, 0x03, 0x2e, 0x89, 0x00, 0x01, 0x2e, 0xd4, 0x00, 0x98,
0xbc, 0x98, 0xb8, 0x05, 0xb2, 0x0f, 0x58, 0x23, 0x2f, 0x07, 0x90, 0x09, 0x54, 0x00, 0x30, 0x37, 0x2f, 0x15, 0x41,
0x04, 0x41, 0xdc, 0xbe, 0x44, 0xbe, 0xdc, 0xba, 0x2c, 0x01, 0x61, 0x00, 0x0f, 0x56, 0x4a, 0x0f, 0x0c, 0x2f, 0xd1,
0x42, 0x94, 0xb8, 0xc1, 0x42, 0x11, 0x30, 0x05, 0x2e, 0x6a, 0xf7, 0x2c, 0xbd, 0x2f, 0xb9, 0x80, 0xb2, 0x08, 0x22,
0x98, 0x2e, 0xc3, 0xb7, 0x21, 0x2d, 0x61, 0x30, 0x23, 0x2e, 0xd4, 0x00, 0x98, 0x2e, 0xc3, 0xb7, 0x00, 0x30, 0x21,
0x2e, 0x5a, 0xf5, 0x18, 0x2d, 0xe1, 0x7f, 0x50, 0x30, 0x98, 0x2e, 0xfa, 0x03, 0x0f, 0x52, 0x07, 0x50, 0x50, 0x42,
0x70, 0x30, 0x0d, 0x54, 0x42, 0x42, 0x7e, 0x82, 0xe2, 0x6f, 0x80, 0xb2, 0x42, 0x42, 0x05, 0x2f, 0x21, 0x2e, 0xd4,
0x00, 0x10, 0x30, 0x98, 0x2e, 0xc3, 0xb7, 0x03, 0x2d, 0x60, 0x30, 0x21, 0x2e, 0xd4, 0x00, 0x01, 0x2e, 0xd4, 0x00,
0x06, 0x90, 0x18, 0x2f, 0x01, 0x2e, 0x76, 0x00, 0x0b, 0x54, 0x07, 0x52, 0xe0, 0x7f, 0x98, 0x2e, 0x7a, 0xc1, 0xe1,
0x6f, 0x08, 0x1a, 0x40, 0x30, 0x08, 0x2f, 0x21, 0x2e, 0xd4, 0x00, 0x20, 0x30, 0x98, 0x2e, 0xaf, 0xb7, 0x50, 0x32,
0x98, 0x2e, 0xfa, 0x03, 0x05, 0x2d, 0x98, 0x2e, 0x38, 0x0e, 0x00, 0x30, 0x21, 0x2e, 0xd4, 0x00, 0x00, 0x30, 0x21,
0x2e, 0x7c, 0x00, 0x18, 0x2d, 0x01, 0x2e, 0xd4, 0x00, 0x03, 0xaa, 0x01, 0x2f, 0x98, 0x2e, 0x45, 0x0e, 0x01, 0x2e,
0xd4, 0x00, 0x3f, 0x80, 0x03, 0xa2, 0x01, 0x2f, 0x00, 0x2e, 0x02, 0x2d, 0x98, 0x2e, 0x5b, 0x0e, 0x30, 0x30, 0x98,
0x2e, 0xce, 0xb7, 0x00, 0x30, 0x21, 0x2e, 0x7d, 0x00, 0x50, 0x32, 0x98, 0x2e, 0xfa, 0x03, 0x01, 0x2e, 0x77, 0x00,
0x00, 0xb2, 0x24, 0x2f, 0x98, 0x2e, 0xf5, 0xcb, 0x03, 0x2e, 0xd5, 0x00, 0x11, 0x54, 0x01, 0x0a, 0xbc, 0x84, 0x83,
0x86, 0x21, 0x2e, 0xc9, 0x01, 0xe0, 0x40, 0x13, 0x52, 0xc4, 0x40, 0x82, 0x40, 0xa8, 0xb9, 0x52, 0x42, 0x43, 0xbe,
0x53, 0x42, 0x04, 0x0a, 0x50, 0x42, 0xe1, 0x7f, 0xf0, 0x31, 0x41, 0x40, 0xf2, 0x6f, 0x25, 0xbd, 0x08, 0x08, 0x02,
0x0a, 0xd0, 0x7f, 0x98, 0x2e, 0xa8, 0xcf, 0x06, 0xbc, 0xd1, 0x6f, 0xe2, 0x6f, 0x08, 0x0a, 0x80, 0x42, 0x98, 0x2e,
0x58, 0xb7, 0x00, 0x30, 0x21, 0x2e, 0xee, 0x00, 0x21, 0x2e, 0x77, 0x00, 0x21, 0x2e, 0xdd, 0x00, 0x80, 0x2e, 0xf4,
0x01, 0x1a, 0x24, 0x22, 0x00, 0x80, 0x2e, 0xec, 0x01, 0x10, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0xf3, 0x03, 0x57, 0x50,
0xfb, 0x6f, 0x01, 0x30, 0x71, 0x54, 0x11, 0x42, 0x42, 0x0e, 0xfc, 0x2f, 0xc0, 0x2e, 0x01, 0x42, 0xf0, 0x5f, 0x80,
0x2e, 0x00, 0xc1, 0xfd, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x01,
0x34, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x06, 0x32, 0x0f, 0x2e, 0x61, 0xf5, 0xfe, 0x09, 0xc0, 0xb3, 0x04,
0x2f, 0x17, 0x30, 0x2f, 0x2e, 0xef, 0x00, 0x2d, 0x2e, 0x61, 0xf5, 0xf6, 0x6f, 0xe7, 0x6f, 0xe0, 0x5f, 0xc8, 0x2e,
0x20, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x46, 0x30, 0x0f, 0x2e, 0xa4, 0xf1, 0xbe, 0x09, 0x80, 0xb3, 0x06, 0x2f, 0x0d,
0x2e, 0xd4, 0x00, 0x84, 0xaf, 0x02, 0x2f, 0x16, 0x30, 0x2d, 0x2e, 0x7b, 0x00, 0x86, 0x30, 0x2d, 0x2e, 0x60, 0xf5,
0xf6, 0x6f, 0xe7, 0x6f, 0xe0, 0x5f, 0xc8, 0x2e, 0x01, 0x2e, 0x77, 0xf7, 0x09, 0xbc, 0x0f, 0xb8, 0x00, 0xb2, 0x10,
0x50, 0xfb, 0x7f, 0x10, 0x30, 0x0b, 0x2f, 0x03, 0x2e, 0x8a, 0x00, 0x96, 0xbc, 0x9f, 0xb8, 0x40, 0xb2, 0x05, 0x2f,
0x03, 0x2e, 0x68, 0xf7, 0x9e, 0xbc, 0x9f, 0xb8, 0x40, 0xb2, 0x07, 0x2f, 0x03, 0x2e, 0x7e, 0x00, 0x41, 0x90, 0x01,
0x2f, 0x98, 0x2e, 0xdc, 0x03, 0x03, 0x2c, 0x00, 0x30, 0x21, 0x2e, 0x7e, 0x00, 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e,
0x20, 0x50, 0xe0, 0x7f, 0xfb, 0x7f, 0x00, 0x2e, 0x27, 0x50, 0x98, 0x2e, 0x3b, 0xc8, 0x29, 0x50, 0x98, 0x2e, 0xa7,
0xc8, 0x01, 0x50, 0x98, 0x2e, 0x55, 0xcc, 0xe1, 0x6f, 0x2b, 0x50, 0x98, 0x2e, 0xe0, 0xc9, 0xfb, 0x6f, 0x00, 0x30,
0xe0, 0x5f, 0x21, 0x2e, 0x7e, 0x00, 0xb8, 0x2e, 0x73, 0x50, 0x01, 0x30, 0x57, 0x54, 0x11, 0x42, 0x42, 0x0e, 0xfc,
0x2f, 0xb8, 0x2e, 0x21, 0x2e, 0x59, 0xf5, 0x10, 0x30, 0xc0, 0x2e, 0x21, 0x2e, 0x4a, 0xf1, 0x90, 0x50, 0xf7, 0x7f,
0xe6, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa1, 0x7f, 0x90, 0x7f, 0x82, 0x7f, 0x7b, 0x7f, 0x98, 0x2e, 0x35,
0xb7, 0x00, 0xb2, 0x90, 0x2e, 0x97, 0xb0, 0x03, 0x2e, 0x8f, 0x00, 0x07, 0x2e, 0x91, 0x00, 0x05, 0x2e, 0xb1, 0x00,
0x3f, 0xba, 0x9f, 0xb8, 0x01, 0x2e, 0xb1, 0x00, 0xa3, 0xbd, 0x4c, 0x0a, 0x05, 0x2e, 0xb1, 0x00, 0x04, 0xbe, 0xbf,
0xb9, 0xcb, 0x0a, 0x4f, 0xba, 0x22, 0xbd, 0x01, 0x2e, 0xb3, 0x00, 0xdc, 0x0a, 0x2f, 0xb9, 0x03, 0x2e, 0xb8, 0x00,
0x0a, 0xbe, 0x9a, 0x0a, 0xcf, 0xb9, 0x9b, 0xbc, 0x01, 0x2e, 0x97, 0x00, 0x9f, 0xb8, 0x93, 0x0a, 0x0f, 0xbc, 0x91,
0x0a, 0x0f, 0xb8, 0x90, 0x0a, 0x25, 0x2e, 0x18, 0x00, 0x05, 0x2e, 0xc1, 0xf5, 0x2e, 0xbd, 0x2e, 0xb9, 0x01, 0x2e,
0x19, 0x00, 0x31, 0x30, 0x8a, 0x04, 0x00, 0x90, 0x07, 0x2f, 0x01, 0x2e, 0xd4, 0x00, 0x04, 0xa2, 0x03, 0x2f, 0x01,
0x2e, 0x18, 0x00, 0x00, 0xb2, 0x0c, 0x2f, 0x19, 0x50, 0x05, 0x52, 0x98, 0x2e, 0x4d, 0xb7, 0x05, 0x2e, 0x78, 0x00,
0x80, 0x90, 0x10, 0x30, 0x01, 0x2f, 0x21, 0x2e, 0x78, 0x00, 0x25, 0x2e, 0xdd, 0x00, 0x98, 0x2e, 0x3e, 0xb7, 0x00,
0xb2, 0x02, 0x30, 0x01, 0x30, 0x04, 0x2f, 0x01, 0x2e, 0x19, 0x00, 0x00, 0xb2, 0x00, 0x2f, 0x21, 0x30, 0x01, 0x2e,
0xea, 0x00, 0x08, 0x1a, 0x0e, 0x2f, 0x23, 0x2e, 0xea, 0x00, 0x33, 0x30, 0x1b, 0x50, 0x0b, 0x09, 0x01, 0x40, 0x17,
0x56, 0x46, 0xbe, 0x4b, 0x08, 0x4c, 0x0a, 0x01, 0x42, 0x0a, 0x80, 0x15, 0x52, 0x01, 0x42, 0x00, 0x2e, 0x01, 0x2e,
0x18, 0x00, 0x00, 0xb2, 0x1f, 0x2f, 0x03, 0x2e, 0xc0, 0xf5, 0xf0, 0x30, 0x48, 0x08, 0x47, 0xaa, 0x74, 0x30, 0x07,
0x2e, 0x7a, 0x00, 0x61, 0x22, 0x4b, 0x1a, 0x05, 0x2f, 0x07, 0x2e, 0x66, 0xf5, 0xbf, 0xbd, 0xbf, 0xb9, 0xc0, 0x90,
0x0b, 0x2f, 0x1d, 0x56, 0x2b, 0x30, 0xd2, 0x42, 0xdb, 0x42, 0x01, 0x04, 0xc2, 0x42, 0x04, 0xbd, 0xfe, 0x80, 0x81,
0x84, 0x23, 0x2e, 0x7a, 0x00, 0x02, 0x42, 0x02, 0x32, 0x25, 0x2e, 0x62, 0xf5, 0x05, 0x2e, 0xd6, 0x00, 0x81, 0x84,
0x25, 0x2e, 0xd6, 0x00, 0x02, 0x31, 0x25, 0x2e, 0x60, 0xf5, 0x05, 0x2e, 0x8a, 0x00, 0x0b, 0x50, 0x90, 0x08, 0x80,
0xb2, 0x0b, 0x2f, 0x05, 0x2e, 0xca, 0xf5, 0xf0, 0x3e, 0x90, 0x08, 0x25, 0x2e, 0xca, 0xf5, 0x05, 0x2e, 0x59, 0xf5,
0xe0, 0x3f, 0x90, 0x08, 0x25, 0x2e, 0x59, 0xf5, 0x90, 0x6f, 0xa1, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe6,
0x6f, 0xf7, 0x6f, 0x7b, 0x6f, 0x82, 0x6f, 0x70, 0x5f, 0xc8, 0x2e, 0xc0, 0x50, 0x90, 0x7f, 0xe5, 0x7f, 0xd4, 0x7f,
0xc3, 0x7f, 0xb1, 0x7f, 0xa2, 0x7f, 0x87, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x60, 0xf5, 0x60,
0x7f, 0x98, 0x2e, 0x35, 0xb7, 0x02, 0x30, 0x63, 0x6f, 0x15, 0x52, 0x50, 0x7f, 0x62, 0x7f, 0x5a, 0x2c, 0x02, 0x32,
0x1a, 0x09, 0x00, 0xb3, 0x14, 0x2f, 0x00, 0xb2, 0x03, 0x2f, 0x09, 0x2e, 0x18, 0x00, 0x00, 0x91, 0x0c, 0x2f, 0x43,
0x7f, 0x98, 0x2e, 0x97, 0xb7, 0x1f, 0x50, 0x02, 0x8a, 0x02, 0x32, 0x04, 0x30, 0x25, 0x2e, 0x64, 0xf5, 0x15, 0x52,
0x50, 0x6f, 0x43, 0x6f, 0x44, 0x43, 0x25, 0x2e, 0x60, 0xf5, 0xd9, 0x08, 0xc0, 0xb2, 0x36, 0x2f, 0x98, 0x2e, 0x3e,
0xb7, 0x00, 0xb2, 0x06, 0x2f, 0x01, 0x2e, 0x19, 0x00, 0x00, 0xb2, 0x02, 0x2f, 0x50, 0x6f, 0x00, 0x90, 0x0a, 0x2f,
0x01, 0x2e, 0x79, 0x00, 0x00, 0x90, 0x19, 0x2f, 0x10, 0x30, 0x21, 0x2e, 0x79, 0x00, 0x00, 0x30, 0x98, 0x2e, 0xdc,
0x03, 0x13, 0x2d, 0x01, 0x2e, 0xc3, 0xf5, 0x0c, 0xbc, 0x0f, 0xb8, 0x12, 0x30, 0x10, 0x04, 0x03, 0xb0, 0x26, 0x25,
0x21, 0x50, 0x03, 0x52, 0x98, 0x2e, 0x4d, 0xb7, 0x10, 0x30, 0x21, 0x2e, 0xee, 0x00, 0x02, 0x30, 0x60, 0x7f, 0x25,
0x2e, 0x79, 0x00, 0x60, 0x6f, 0x00, 0x90, 0x05, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0xea, 0x00, 0x15, 0x50, 0x21, 0x2e,
0x64, 0xf5, 0x15, 0x52, 0x23, 0x2e, 0x60, 0xf5, 0x02, 0x32, 0x50, 0x6f, 0x00, 0x90, 0x02, 0x2f, 0x03, 0x30, 0x27,
0x2e, 0x78, 0x00, 0x07, 0x2e, 0x60, 0xf5, 0x1a, 0x09, 0x00, 0x91, 0xa3, 0x2f, 0x19, 0x09, 0x00, 0x91, 0xa0, 0x2f,
0x90, 0x6f, 0xa2, 0x6f, 0xb1, 0x6f, 0xc3, 0x6f, 0xd4, 0x6f, 0xe5, 0x6f, 0x7b, 0x6f, 0xf6, 0x6f, 0x87, 0x6f, 0x40,
0x5f, 0xc8, 0x2e, 0xc0, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x26, 0x30, 0x0f, 0x2e, 0x61, 0xf5, 0x2f, 0x2e, 0x7c, 0x00,
0x0f, 0x2e, 0x7c, 0x00, 0xbe, 0x09, 0xa2, 0x7f, 0x80, 0x7f, 0x80, 0xb3, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0x91,
0x7f, 0x7b, 0x7f, 0x0b, 0x2f, 0x23, 0x50, 0x1a, 0x25, 0x12, 0x40, 0x42, 0x7f, 0x74, 0x82, 0x12, 0x40, 0x52, 0x7f,
0x00, 0x2e, 0x00, 0x40, 0x60, 0x7f, 0x98, 0x2e, 0x6a, 0xd6, 0x81, 0x30, 0x01, 0x2e, 0x7c, 0x00, 0x01, 0x08, 0x00,
0xb2, 0x42, 0x2f, 0x03, 0x2e, 0x89, 0x00, 0x01, 0x2e, 0x89, 0x00, 0x97, 0xbc, 0x06, 0xbc, 0x9f, 0xb8, 0x0f, 0xb8,
0x00, 0x90, 0x23, 0x2e, 0xd8, 0x00, 0x10, 0x30, 0x01, 0x30, 0x2a, 0x2f, 0x03, 0x2e, 0xd4, 0x00, 0x44, 0xb2, 0x05,
0x2f, 0x47, 0xb2, 0x00, 0x30, 0x2d, 0x2f, 0x21, 0x2e, 0x7c, 0x00, 0x2b, 0x2d, 0x03, 0x2e, 0xfd, 0xf5, 0x9e, 0xbc,
0x9f, 0xb8, 0x40, 0x90, 0x14, 0x2f, 0x03, 0x2e, 0xfc, 0xf5, 0x99, 0xbc, 0x9f, 0xb8, 0x40, 0x90, 0x0e, 0x2f, 0x03,
0x2e, 0x49, 0xf1, 0x25, 0x54, 0x4a, 0x08, 0x40, 0x90, 0x08, 0x2f, 0x98, 0x2e, 0x35, 0xb7, 0x00, 0xb2, 0x10, 0x30,
0x03, 0x2f, 0x50, 0x30, 0x21, 0x2e, 0xd4, 0x00, 0x10, 0x2d, 0x98, 0x2e, 0xaf, 0xb7, 0x00, 0x30, 0x21, 0x2e, 0x7c,
0x00, 0x0a, 0x2d, 0x05, 0x2e, 0x69, 0xf7, 0x2d, 0xbd, 0x2f, 0xb9, 0x80, 0xb2, 0x01, 0x2f, 0x21, 0x2e, 0x7d, 0x00,
0x23, 0x2e, 0x7c, 0x00, 0xe0, 0x31, 0x21, 0x2e, 0x61, 0xf5, 0xf6, 0x6f, 0xe7, 0x6f, 0x80, 0x6f, 0xa2, 0x6f, 0xb3,
0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0x7b, 0x6f, 0x91, 0x6f, 0x40, 0x5f, 0xc8, 0x2e, 0x60, 0x51, 0x0a, 0x25, 0x36, 0x88,
0xf4, 0x7f, 0xeb, 0x7f, 0x00, 0x32, 0x31, 0x52, 0x32, 0x30, 0x13, 0x30, 0x98, 0x2e, 0x15, 0xcb, 0x0a, 0x25, 0x33,
0x84, 0xd2, 0x7f, 0x43, 0x30, 0x05, 0x50, 0x2d, 0x52, 0x98, 0x2e, 0x95, 0xc1, 0xd2, 0x6f, 0x27, 0x52, 0x98, 0x2e,
0xd7, 0xc7, 0x2a, 0x25, 0xb0, 0x86, 0xc0, 0x7f, 0xd3, 0x7f, 0xaf, 0x84, 0x29, 0x50, 0xf1, 0x6f, 0x98, 0x2e, 0x4d,
0xc8, 0x2a, 0x25, 0xae, 0x8a, 0xaa, 0x88, 0xf2, 0x6e, 0x2b, 0x50, 0xc1, 0x6f, 0xd3, 0x6f, 0xf4, 0x7f, 0x98, 0x2e,
0xb6, 0xc8, 0xe0, 0x6e, 0x00, 0xb2, 0x32, 0x2f, 0x33, 0x54, 0x83, 0x86, 0xf1, 0x6f, 0xc3, 0x7f, 0x04, 0x30, 0x30,
0x30, 0xf4, 0x7f, 0xd0, 0x7f, 0xb2, 0x7f, 0xe3, 0x30, 0xc5, 0x6f, 0x56, 0x40, 0x45, 0x41, 0x28, 0x08, 0x03, 0x14,
0x0e, 0xb4, 0x08, 0xbc, 0x82, 0x40, 0x10, 0x0a, 0x2f, 0x54, 0x26, 0x05, 0x91, 0x7f, 0x44, 0x28, 0xa3, 0x7f, 0x98,
0x2e, 0xd9, 0xc0, 0x08, 0xb9, 0x33, 0x30, 0x53, 0x09, 0xc1, 0x6f, 0xd3, 0x6f, 0xf4, 0x6f, 0x83, 0x17, 0x47, 0x40,
0x6c, 0x15, 0xb2, 0x6f, 0xbe, 0x09, 0x75, 0x0b, 0x90, 0x42, 0x45, 0x42, 0x51, 0x0e, 0x32, 0xbc, 0x02, 0x89, 0xa1,
0x6f, 0x7e, 0x86, 0xf4, 0x7f, 0xd0, 0x7f, 0xb2, 0x7f, 0x04, 0x30, 0x91, 0x6f, 0xd6, 0x2f, 0xeb, 0x6f, 0xa0, 0x5e,
0xb8, 0x2e, 0x03, 0x2e, 0x97, 0x00, 0x1b, 0xbc, 0x60, 0x50, 0x9f, 0xbc, 0x0c, 0xb8, 0xf0, 0x7f, 0x40, 0xb2, 0xeb,
0x7f, 0x2b, 0x2f, 0x03, 0x2e, 0x7f, 0x00, 0x41, 0x40, 0x01, 0x2e, 0xc8, 0x00, 0x01, 0x1a, 0x11, 0x2f, 0x37, 0x58,
0x23, 0x2e, 0xc8, 0x00, 0x10, 0x41, 0xa0, 0x7f, 0x38, 0x81, 0x01, 0x41, 0xd0, 0x7f, 0xb1, 0x7f, 0x98, 0x2e, 0x64,
0xcf, 0xd0, 0x6f, 0x07, 0x80, 0xa1, 0x6f, 0x11, 0x42, 0x00, 0x2e, 0xb1, 0x6f, 0x01, 0x42, 0x11, 0x30, 0x01, 0x2e,
0xfc, 0x00, 0x00, 0xa8, 0x03, 0x30, 0xcb, 0x22, 0x4a, 0x25, 0x01, 0x2e, 0x7f, 0x00, 0x3c, 0x89, 0x35, 0x52, 0x05,
0x54, 0x98, 0x2e, 0xc4, 0xce, 0xc1, 0x6f, 0xf0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0x04, 0x2d, 0x01, 0x30, 0xf0, 0x6f,
0x98, 0x2e, 0x95, 0xcf, 0xeb, 0x6f, 0xa0, 0x5f, 0xb8, 0x2e, 0x03, 0x2e, 0xb3, 0x00, 0x02, 0x32, 0xf0, 0x30, 0x03,
0x31, 0x30, 0x50, 0x8a, 0x08, 0x08, 0x08, 0xcb, 0x08, 0xe0, 0x7f, 0x80, 0xb2, 0xf3, 0x7f, 0xdb, 0x7f, 0x25, 0x2f,
0x03, 0x2e, 0xca, 0x00, 0x41, 0x90, 0x04, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0xca, 0x00, 0x98, 0x2e, 0x3f, 0x03, 0xc0,
0xb2, 0x05, 0x2f, 0x03, 0x2e, 0xda, 0x00, 0x00, 0x30, 0x41, 0x04, 0x23, 0x2e, 0xda, 0x00, 0x98, 0x2e, 0x92, 0xb2,
0x10, 0x25, 0xf0, 0x6f, 0x00, 0xb2, 0x05, 0x2f, 0x01, 0x2e, 0xda, 0x00, 0x02, 0x30, 0x10, 0x04, 0x21, 0x2e, 0xda,
0x00, 0x40, 0xb2, 0x01, 0x2f, 0x23, 0x2e, 0xc8, 0x01, 0xdb, 0x6f, 0xe0, 0x6f, 0xd0, 0x5f, 0x80, 0x2e, 0x95, 0xcf,
0x01, 0x30, 0xe0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0x11, 0x30, 0x23, 0x2e, 0xca, 0x00, 0xdb, 0x6f, 0xd0, 0x5f, 0xb8,
0x2e, 0xd0, 0x50, 0x0a, 0x25, 0x33, 0x84, 0x55, 0x50, 0xd2, 0x7f, 0xe2, 0x7f, 0x03, 0x8c, 0xc0, 0x7f, 0xbb, 0x7f,
0x00, 0x30, 0x05, 0x5a, 0x39, 0x54, 0x51, 0x41, 0xa5, 0x7f, 0x96, 0x7f, 0x80, 0x7f, 0x98, 0x2e, 0xd9, 0xc0, 0x05,
0x30, 0xf5, 0x7f, 0x20, 0x25, 0x91, 0x6f, 0x3b, 0x58, 0x3d, 0x5c, 0x3b, 0x56, 0x98, 0x2e, 0x67, 0xcc, 0xc1, 0x6f,
0xd5, 0x6f, 0x52, 0x40, 0x50, 0x43, 0xc1, 0x7f, 0xd5, 0x7f, 0x10, 0x25, 0x98, 0x2e, 0xfe, 0xc9, 0x10, 0x25, 0x98,
0x2e, 0x74, 0xc0, 0x86, 0x6f, 0x30, 0x28, 0x92, 0x6f, 0x82, 0x8c, 0xa5, 0x6f, 0x6f, 0x52, 0x69, 0x0e, 0x39, 0x54,
0xdb, 0x2f, 0x19, 0xa0, 0x15, 0x30, 0x03, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x81, 0x01, 0x0a, 0x2d, 0x01, 0x2e, 0x81,
0x01, 0x05, 0x28, 0x42, 0x36, 0x21, 0x2e, 0x81, 0x01, 0x02, 0x0e, 0x01, 0x2f, 0x98, 0x2e, 0xf3, 0x03, 0x57, 0x50,
0x12, 0x30, 0x01, 0x40, 0x98, 0x2e, 0xfe, 0xc9, 0x51, 0x6f, 0x0b, 0x5c, 0x8e, 0x0e, 0x3b, 0x6f, 0x57, 0x58, 0x02,
0x30, 0x21, 0x2e, 0x95, 0x01, 0x45, 0x6f, 0x2a, 0x8d, 0xd2, 0x7f, 0xcb, 0x7f, 0x13, 0x2f, 0x02, 0x30, 0x3f, 0x50,
0xd2, 0x7f, 0xa8, 0x0e, 0x0e, 0x2f, 0xc0, 0x6f, 0x53, 0x54, 0x02, 0x00, 0x51, 0x54, 0x42, 0x0e, 0x10, 0x30, 0x59,
0x52, 0x02, 0x30, 0x01, 0x2f, 0x00, 0x2e, 0x03, 0x2d, 0x50, 0x42, 0x42, 0x42, 0x12, 0x30, 0xd2, 0x7f, 0x80, 0xb2,
0x03, 0x2f, 0x00, 0x30, 0x21, 0x2e, 0x80, 0x01, 0x12, 0x2d, 0x01, 0x2e, 0xc9, 0x00, 0x02, 0x80, 0x05, 0x2e, 0x80,
0x01, 0x11, 0x30, 0x91, 0x28, 0x00, 0x40, 0x25, 0x2e, 0x80, 0x01, 0x10, 0x0e, 0x05, 0x2f, 0x01, 0x2e, 0x7f, 0x01,
0x01, 0x90, 0x01, 0x2f, 0x98, 0x2e, 0xf3, 0x03, 0x00, 0x2e, 0xa0, 0x41, 0x01, 0x90, 0xa6, 0x7f, 0x90, 0x2e, 0xe3,
0xb4, 0x01, 0x2e, 0x95, 0x01, 0x00, 0xa8, 0x90, 0x2e, 0xe3, 0xb4, 0x5b, 0x54, 0x95, 0x80, 0x82, 0x40, 0x80, 0xb2,
0x02, 0x40, 0x2d, 0x8c, 0x3f, 0x52, 0x96, 0x7f, 0x90, 0x2e, 0xc2, 0xb3, 0x29, 0x0e, 0x76, 0x2f, 0x01, 0x2e, 0xc9,
0x00, 0x00, 0x40, 0x81, 0x28, 0x45, 0x52, 0xb3, 0x30, 0x98, 0x2e, 0x0f, 0xca, 0x5d, 0x54, 0x80, 0x7f, 0x00, 0x2e,
0xa1, 0x40, 0x72, 0x7f, 0x82, 0x80, 0x82, 0x40, 0x60, 0x7f, 0x98, 0x2e, 0xfe, 0xc9, 0x10, 0x25, 0x98, 0x2e, 0x74,
0xc0, 0x62, 0x6f, 0x05, 0x30, 0x87, 0x40, 0xc0, 0x91, 0x04, 0x30, 0x05, 0x2f, 0x05, 0x2e, 0x83, 0x01, 0x80, 0xb2,
0x14, 0x30, 0x00, 0x2f, 0x04, 0x30, 0x05, 0x2e, 0xc9, 0x00, 0x73, 0x6f, 0x81, 0x40, 0xe2, 0x40, 0x69, 0x04, 0x11,
0x0f, 0xe1, 0x40, 0x16, 0x30, 0xfe, 0x29, 0xcb, 0x40, 0x02, 0x2f, 0x83, 0x6f, 0x83, 0x0f, 0x22, 0x2f, 0x47, 0x56,
0x13, 0x0f, 0x12, 0x30, 0x77, 0x2f, 0x49, 0x54, 0x42, 0x0e, 0x12, 0x30, 0x73, 0x2f, 0x00, 0x91, 0x0a, 0x2f, 0x01,
0x2e, 0x8b, 0x01, 0x19, 0xa8, 0x02, 0x30, 0x6c, 0x2f, 0x63, 0x50, 0x00, 0x2e, 0x17, 0x42, 0x05, 0x42, 0x68, 0x2c,
0x12, 0x30, 0x0b, 0x25, 0x08, 0x0f, 0x50, 0x30, 0x02, 0x2f, 0x21, 0x2e, 0x83, 0x01, 0x03, 0x2d, 0x40, 0x30, 0x21,
0x2e, 0x83, 0x01, 0x2b, 0x2e, 0x85, 0x01, 0x5a, 0x2c, 0x12, 0x30, 0x00, 0x91, 0x2b, 0x25, 0x04, 0x2f, 0x63, 0x50,
0x02, 0x30, 0x17, 0x42, 0x17, 0x2c, 0x02, 0x42, 0x98, 0x2e, 0xfe, 0xc9, 0x10, 0x25, 0x98, 0x2e, 0x74, 0xc0, 0x05,
0x2e, 0xc9, 0x00, 0x81, 0x84, 0x5b, 0x30, 0x82, 0x40, 0x37, 0x2e, 0x83, 0x01, 0x02, 0x0e, 0x07, 0x2f, 0x5f, 0x52,
0x40, 0x30, 0x62, 0x40, 0x41, 0x40, 0x91, 0x0e, 0x01, 0x2f, 0x21, 0x2e, 0x83, 0x01, 0x05, 0x30, 0x2b, 0x2e, 0x85,
0x01, 0x12, 0x30, 0x36, 0x2c, 0x16, 0x30, 0x15, 0x25, 0x81, 0x7f, 0x98, 0x2e, 0xfe, 0xc9, 0x10, 0x25, 0x98, 0x2e,
0x74, 0xc0, 0x19, 0xa2, 0x16, 0x30, 0x15, 0x2f, 0x05, 0x2e, 0x97, 0x01, 0x80, 0x6f, 0x82, 0x0e, 0x05, 0x2f, 0x01,
0x2e, 0x86, 0x01, 0x06, 0x28, 0x21, 0x2e, 0x86, 0x01, 0x0b, 0x2d, 0x03, 0x2e, 0x87, 0x01, 0x5f, 0x54, 0x4e, 0x28,
0x91, 0x42, 0x00, 0x2e, 0x82, 0x40, 0x90, 0x0e, 0x01, 0x2f, 0x21, 0x2e, 0x88, 0x01, 0x02, 0x30, 0x13, 0x2c, 0x05,
0x30, 0xc0, 0x6f, 0x08, 0x1c, 0xa8, 0x0f, 0x16, 0x30, 0x05, 0x30, 0x5b, 0x50, 0x09, 0x2f, 0x02, 0x80, 0x2d, 0x2e,
0x82, 0x01, 0x05, 0x42, 0x05, 0x80, 0x00, 0x2e, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x06, 0x42, 0x02, 0x30, 0x90,
0x6f, 0x3e, 0x88, 0x01, 0x40, 0x04, 0x41, 0x4c, 0x28, 0x01, 0x42, 0x07, 0x80, 0x10, 0x25, 0x24, 0x40, 0x00, 0x40,
0x00, 0xa8, 0xf5, 0x22, 0x23, 0x29, 0x44, 0x42, 0x7a, 0x82, 0x7e, 0x88, 0x43, 0x40, 0x04, 0x41, 0x00, 0xab, 0xf5,
0x23, 0xdf, 0x28, 0x43, 0x42, 0xd9, 0xa0, 0x14, 0x2f, 0x00, 0x90, 0x02, 0x2f, 0xd2, 0x6f, 0x81, 0xb2, 0x05, 0x2f,
0x63, 0x54, 0x06, 0x28, 0x90, 0x42, 0x85, 0x42, 0x09, 0x2c, 0x02, 0x30, 0x5b, 0x50, 0x03, 0x80, 0x29, 0x2e, 0x7e,
0x01, 0x2b, 0x2e, 0x82, 0x01, 0x05, 0x42, 0x12, 0x30, 0x2b, 0x2e, 0x83, 0x01, 0x45, 0x82, 0x00, 0x2e, 0x40, 0x40,
0x7a, 0x82, 0x02, 0xa0, 0x08, 0x2f, 0x63, 0x50, 0x3b, 0x30, 0x15, 0x42, 0x05, 0x42, 0x37, 0x80, 0x37, 0x2e, 0x7e,
0x01, 0x05, 0x42, 0x12, 0x30, 0x01, 0x2e, 0xc9, 0x00, 0x02, 0x8c, 0x40, 0x40, 0x84, 0x41, 0x7a, 0x8c, 0x04, 0x0f,
0x03, 0x2f, 0x01, 0x2e, 0x8b, 0x01, 0x19, 0xa4, 0x04, 0x2f, 0x2b, 0x2e, 0x82, 0x01, 0x98, 0x2e, 0xf3, 0x03, 0x12,
0x30, 0x81, 0x90, 0x61, 0x52, 0x08, 0x2f, 0x65, 0x42, 0x65, 0x42, 0x43, 0x80, 0x39, 0x84, 0x82, 0x88, 0x05, 0x42,
0x45, 0x42, 0x85, 0x42, 0x05, 0x43, 0x00, 0x2e, 0x80, 0x41, 0x00, 0x90, 0x90, 0x2e, 0xe1, 0xb4, 0x65, 0x54, 0xc1,
0x6f, 0x80, 0x40, 0x00, 0xb2, 0x43, 0x58, 0x69, 0x50, 0x44, 0x2f, 0x55, 0x5c, 0xb7, 0x87, 0x8c, 0x0f, 0x0d, 0x2e,
0x96, 0x01, 0xc4, 0x40, 0x36, 0x2f, 0x41, 0x56, 0x8b, 0x0e, 0x2a, 0x2f, 0x0b, 0x52, 0xa1, 0x0e, 0x0a, 0x2f, 0x05,
0x2e, 0x8f, 0x01, 0x14, 0x25, 0x98, 0x2e, 0xfe, 0xc9, 0x4b, 0x54, 0x02, 0x0f, 0x69, 0x50, 0x05, 0x30, 0x65, 0x54,
0x15, 0x2f, 0x03, 0x2e, 0x8e, 0x01, 0x4d, 0x5c, 0x8e, 0x0f, 0x3a, 0x2f, 0x05, 0x2e, 0x8f, 0x01, 0x98, 0x2e, 0xfe,
0xc9, 0x4f, 0x54, 0x82, 0x0f, 0x05, 0x30, 0x69, 0x50, 0x65, 0x54, 0x30, 0x2f, 0x6d, 0x52, 0x15, 0x30, 0x42, 0x8c,
0x45, 0x42, 0x04, 0x30, 0x2b, 0x2c, 0x84, 0x43, 0x6b, 0x52, 0x42, 0x8c, 0x00, 0x2e, 0x85, 0x43, 0x15, 0x30, 0x24,
0x2c, 0x45, 0x42, 0x8e, 0x0f, 0x20, 0x2f, 0x0d, 0x2e, 0x8e, 0x01, 0xb1, 0x0e, 0x1c, 0x2f, 0x23, 0x2e, 0x8e, 0x01,
0x1a, 0x2d, 0x0e, 0x0e, 0x17, 0x2f, 0xa1, 0x0f, 0x15, 0x2f, 0x23, 0x2e, 0x8d, 0x01, 0x13, 0x2d, 0x98, 0x2e, 0x74,
0xc0, 0x43, 0x54, 0xc2, 0x0e, 0x0a, 0x2f, 0x65, 0x50, 0x04, 0x80, 0x0b, 0x30, 0x06, 0x82, 0x0b, 0x42, 0x79, 0x80,
0x41, 0x40, 0x12, 0x30, 0x25, 0x2e, 0x8c, 0x01, 0x01, 0x42, 0x05, 0x30, 0x69, 0x50, 0x65, 0x54, 0x84, 0x82, 0x43,
0x84, 0xbe, 0x8c, 0x84, 0x40, 0x86, 0x41, 0x26, 0x29, 0x94, 0x42, 0xbe, 0x8e, 0xd5, 0x7f, 0x19, 0xa1, 0x43, 0x40,
0x0b, 0x2e, 0x8c, 0x01, 0x84, 0x40, 0xc7, 0x41, 0x5d, 0x29, 0x27, 0x29, 0x45, 0x42, 0x84, 0x42, 0xc2, 0x7f, 0x01,
0x2f, 0xc0, 0xb3, 0x1d, 0x2f, 0x05, 0x2e, 0x94, 0x01, 0x99, 0xa0, 0x01, 0x2f, 0x80, 0xb3, 0x13, 0x2f, 0x80, 0xb3,
0x18, 0x2f, 0xc0, 0xb3, 0x16, 0x2f, 0x12, 0x40, 0x01, 0x40, 0x92, 0x7f, 0x98, 0x2e, 0x74, 0xc0, 0x92, 0x6f, 0x10,
0x0f, 0x20, 0x30, 0x03, 0x2f, 0x10, 0x30, 0x21, 0x2e, 0x7e, 0x01, 0x0a, 0x2d, 0x21, 0x2e, 0x7e, 0x01, 0x07, 0x2d,
0x20, 0x30, 0x21, 0x2e, 0x7e, 0x01, 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e, 0x7e, 0x01, 0xc2, 0x6f, 0x01, 0x2e, 0xc9,
0x00, 0xbc, 0x84, 0x02, 0x80, 0x82, 0x40, 0x00, 0x40, 0x90, 0x0e, 0xd5, 0x6f, 0x02, 0x2f, 0x15, 0x30, 0x98, 0x2e,
0xf3, 0x03, 0x41, 0x91, 0x05, 0x30, 0x07, 0x2f, 0x67, 0x50, 0x3d, 0x80, 0x2b, 0x2e, 0x8f, 0x01, 0x05, 0x42, 0x04,
0x80, 0x00, 0x2e, 0x05, 0x42, 0x02, 0x2c, 0x00, 0x30, 0x00, 0x30, 0xa2, 0x6f, 0x98, 0x8a, 0x86, 0x40, 0x80, 0xa7,
0x05, 0x2f, 0x98, 0x2e, 0xf3, 0x03, 0xc0, 0x30, 0x21, 0x2e, 0x95, 0x01, 0x06, 0x25, 0x1a, 0x25, 0xe2, 0x6f, 0x76,
0x82, 0x96, 0x40, 0x56, 0x43, 0x51, 0x0e, 0xfb, 0x2f, 0xbb, 0x6f, 0x30, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xb8, 0x00,
0x01, 0x31, 0x41, 0x08, 0x40, 0xb2, 0x20, 0x50, 0xf2, 0x30, 0x02, 0x08, 0xfb, 0x7f, 0x01, 0x30, 0x10, 0x2f, 0x05,
0x2e, 0xcc, 0x00, 0x81, 0x90, 0xe0, 0x7f, 0x03, 0x2f, 0x23, 0x2e, 0xcc, 0x00, 0x98, 0x2e, 0x55, 0xb6, 0x98, 0x2e,
0x1d, 0xb5, 0x10, 0x25, 0xfb, 0x6f, 0xe0, 0x6f, 0xe0, 0x5f, 0x80, 0x2e, 0x95, 0xcf, 0x98, 0x2e, 0x95, 0xcf, 0x10,
0x30, 0x21, 0x2e, 0xcc, 0x00, 0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x00, 0x51, 0x05, 0x58, 0xeb, 0x7f, 0x2a, 0x25,
0x89, 0x52, 0x6f, 0x5a, 0x89, 0x50, 0x13, 0x41, 0x06, 0x40, 0xb3, 0x01, 0x16, 0x42, 0xcb, 0x16, 0x06, 0x40, 0xf3,
0x02, 0x13, 0x42, 0x65, 0x0e, 0xf5, 0x2f, 0x05, 0x40, 0x14, 0x30, 0x2c, 0x29, 0x04, 0x42, 0x08, 0xa1, 0x00, 0x30,
0x90, 0x2e, 0x52, 0xb6, 0xb3, 0x88, 0xb0, 0x8a, 0xb6, 0x84, 0xa4, 0x7f, 0xc4, 0x7f, 0xb5, 0x7f, 0xd5, 0x7f, 0x92,
0x7f, 0x73, 0x30, 0x04, 0x30, 0x55, 0x40, 0x42, 0x40, 0x8a, 0x17, 0xf3, 0x08, 0x6b, 0x01, 0x90, 0x02, 0x53, 0xb8,
0x4b, 0x82, 0xad, 0xbe, 0x71, 0x7f, 0x45, 0x0a, 0x09, 0x54, 0x84, 0x7f, 0x98, 0x2e, 0xd9, 0xc0, 0xa3, 0x6f, 0x7b,
0x54, 0xd0, 0x42, 0xa3, 0x7f, 0xf2, 0x7f, 0x60, 0x7f, 0x20, 0x25, 0x71, 0x6f, 0x75, 0x5a, 0x77, 0x58, 0x79, 0x5c,
0x75, 0x56, 0x98, 0x2e, 0x67, 0xcc, 0xb1, 0x6f, 0x62, 0x6f, 0x50, 0x42, 0xb1, 0x7f, 0xb3, 0x30, 0x10, 0x25, 0x98,
0x2e, 0x0f, 0xca, 0x84, 0x6f, 0x20, 0x29, 0x71, 0x6f, 0x92, 0x6f, 0xa5, 0x6f, 0x76, 0x82, 0x6a, 0x0e, 0x73, 0x30,
0x00, 0x30, 0xd0, 0x2f, 0xd2, 0x6f, 0xd1, 0x7f, 0xb4, 0x7f, 0x98, 0x2e, 0x2b, 0xb7, 0x15, 0xbd, 0x0b, 0xb8, 0x02,
0x0a, 0xc2, 0x6f, 0xc0, 0x7f, 0x98, 0x2e, 0x2b, 0xb7, 0x15, 0xbd, 0x0b, 0xb8, 0x42, 0x0a, 0xc0, 0x6f, 0x08, 0x17,
0x41, 0x18, 0x89, 0x16, 0xe1, 0x18, 0xd0, 0x18, 0xa1, 0x7f, 0x27, 0x25, 0x16, 0x25, 0x98, 0x2e, 0x79, 0xc0, 0x8b,
0x54, 0x90, 0x7f, 0xb3, 0x30, 0x82, 0x40, 0x80, 0x90, 0x0d, 0x2f, 0x7d, 0x52, 0x92, 0x6f, 0x98, 0x2e, 0x0f, 0xca,
0xb2, 0x6f, 0x90, 0x0e, 0x06, 0x2f, 0x8b, 0x50, 0x14, 0x30, 0x42, 0x6f, 0x51, 0x6f, 0x14, 0x42, 0x12, 0x42, 0x01,
0x42, 0x00, 0x2e, 0x31, 0x6f, 0x98, 0x2e, 0x74, 0xc0, 0x41, 0x6f, 0x80, 0x7f, 0x98, 0x2e, 0x74, 0xc0, 0x82, 0x6f,
0x10, 0x04, 0x43, 0x52, 0x01, 0x0f, 0x05, 0x2e, 0xcb, 0x00, 0x00, 0x30, 0x04, 0x30, 0x21, 0x2f, 0x51, 0x6f, 0x43,
0x58, 0x8c, 0x0e, 0x04, 0x30, 0x1c, 0x2f, 0x85, 0x88, 0x41, 0x6f, 0x04, 0x41, 0x8c, 0x0f, 0x04, 0x30, 0x16, 0x2f,
0x84, 0x88, 0x00, 0x2e, 0x04, 0x41, 0x04, 0x05, 0x8c, 0x0e, 0x04, 0x30, 0x0f, 0x2f, 0x82, 0x88, 0x31, 0x6f, 0x04,
0x41, 0x04, 0x05, 0x8c, 0x0e, 0x04, 0x30, 0x08, 0x2f, 0x83, 0x88, 0x00, 0x2e, 0x04, 0x41, 0x8c, 0x0f, 0x04, 0x30,
0x02, 0x2f, 0x21, 0x2e, 0xad, 0x01, 0x14, 0x30, 0x00, 0x91, 0x14, 0x2f, 0x03, 0x2e, 0xa1, 0x01, 0x41, 0x90, 0x0e,
0x2f, 0x03, 0x2e, 0xad, 0x01, 0x14, 0x30, 0x4c, 0x28, 0x23, 0x2e, 0xad, 0x01, 0x46, 0xa0, 0x06, 0x2f, 0x81, 0x84,
0x8d, 0x52, 0x48, 0x82, 0x82, 0x40, 0x21, 0x2e, 0xa1, 0x01, 0x42, 0x42, 0x5c, 0x2c, 0x02, 0x30, 0x05, 0x2e, 0xaa,
0x01, 0x80, 0xb2, 0x02, 0x30, 0x55, 0x2f, 0x03, 0x2e, 0xa9, 0x01, 0x92, 0x6f, 0xb3, 0x30, 0x98, 0x2e, 0x0f, 0xca,
0xb2, 0x6f, 0x90, 0x0f, 0x00, 0x30, 0x02, 0x30, 0x4a, 0x2f, 0xa2, 0x6f, 0x87, 0x52, 0x91, 0x00, 0x85, 0x52, 0x51,
0x0e, 0x02, 0x2f, 0x00, 0x2e, 0x43, 0x2c, 0x02, 0x30, 0xc2, 0x6f, 0x7f, 0x52, 0x91, 0x0e, 0x02, 0x30, 0x3c, 0x2f,
0x51, 0x6f, 0x81, 0x54, 0x98, 0x2e, 0xfe, 0xc9, 0x10, 0x25, 0xb3, 0x30, 0x21, 0x25, 0x98, 0x2e, 0x0f, 0xca, 0x32,
0x6f, 0xc0, 0x7f, 0xb3, 0x30, 0x12, 0x25, 0x98, 0x2e, 0x0f, 0xca, 0x42, 0x6f, 0xb0, 0x7f, 0xb3, 0x30, 0x12, 0x25,
0x98, 0x2e, 0x0f, 0xca, 0xb2, 0x6f, 0x90, 0x28, 0x83, 0x52, 0x98, 0x2e, 0xfe, 0xc9, 0xc2, 0x6f, 0x90, 0x0f, 0x00,
0x30, 0x02, 0x30, 0x1d, 0x2f, 0x05, 0x2e, 0xa1, 0x01, 0x80, 0xb2, 0x12, 0x30, 0x0f, 0x2f, 0x42, 0x6f, 0x03, 0x2e,
0xab, 0x01, 0x91, 0x0e, 0x02, 0x30, 0x12, 0x2f, 0x52, 0x6f, 0x03, 0x2e, 0xac, 0x01, 0x91, 0x0f, 0x02, 0x30, 0x0c,
0x2f, 0x21, 0x2e, 0xaa, 0x01, 0x0a, 0x2c, 0x12, 0x30, 0x03, 0x2e, 0xcb, 0x00, 0x8d, 0x58, 0x08, 0x89, 0x41, 0x40,
0x11, 0x43, 0x00, 0x43, 0x25, 0x2e, 0xa1, 0x01, 0xd4, 0x6f, 0x8f, 0x52, 0x00, 0x43, 0x3a, 0x89, 0x00, 0x2e, 0x10,
0x43, 0x10, 0x43, 0x61, 0x0e, 0xfb, 0x2f, 0x03, 0x2e, 0xa0, 0x01, 0x11, 0x1a, 0x02, 0x2f, 0x02, 0x25, 0x21, 0x2e,
0xa0, 0x01, 0xeb, 0x6f, 0x00, 0x5f, 0xb8, 0x2e, 0x91, 0x52, 0x10, 0x30, 0x02, 0x30, 0x95, 0x56, 0x52, 0x42, 0x4b,
0x0e, 0xfc, 0x2f, 0x8d, 0x54, 0x88, 0x82, 0x93, 0x56, 0x80, 0x42, 0x53, 0x42, 0x40, 0x42, 0x42, 0x86, 0x83, 0x54,
0xc0, 0x2e, 0xc2, 0x42, 0x00, 0x2e, 0xa3, 0x52, 0x00, 0x51, 0x52, 0x40, 0x47, 0x40, 0x1a, 0x25, 0x01, 0x2e, 0x97,
0x00, 0x8f, 0xbe, 0x72, 0x86, 0xfb, 0x7f, 0x0b, 0x30, 0x7c, 0xbf, 0xa5, 0x50, 0x10, 0x08, 0xdf, 0xba, 0x70, 0x88,
0xf8, 0xbf, 0xcb, 0x42, 0xd3, 0x7f, 0x6c, 0xbb, 0xfc, 0xbb, 0xc5, 0x0a, 0x90, 0x7f, 0x1b, 0x7f, 0x0b, 0x43, 0xc0,
0xb2, 0xe5, 0x7f, 0xb7, 0x7f, 0xa6, 0x7f, 0xc4, 0x7f, 0x90, 0x2e, 0x1c, 0xb7, 0x07, 0x2e, 0xd2, 0x00, 0xc0, 0xb2,
0x0b, 0x2f, 0x97, 0x52, 0x01, 0x2e, 0xcd, 0x00, 0x82, 0x7f, 0x98, 0x2e, 0xbb, 0xcc, 0x0b, 0x30, 0x37, 0x2e, 0xd2,
0x00, 0x82, 0x6f, 0x90, 0x6f, 0x1a, 0x25, 0x00, 0xb2, 0x8b, 0x7f, 0x14, 0x2f, 0xa6, 0xbd, 0x25, 0xbd, 0xb6, 0xb9,
0x2f, 0xb9, 0x80, 0xb2, 0xd4, 0xb0, 0x0c, 0x2f, 0x99, 0x54, 0x9b, 0x56, 0x0b, 0x30, 0x0b, 0x2e, 0xb1, 0x00, 0xa1,
0x58, 0x9b, 0x42, 0xdb, 0x42, 0x6c, 0x09, 0x2b, 0x2e, 0xb1, 0x00, 0x8b, 0x42, 0xcb, 0x42, 0x86, 0x7f, 0x73, 0x84,
0xa7, 0x56, 0xc3, 0x08, 0x39, 0x52, 0x05, 0x50, 0x72, 0x7f, 0x63, 0x7f, 0x98, 0x2e, 0xc2, 0xc0, 0xe1, 0x6f, 0x62,
0x6f, 0xd1, 0x0a, 0x01, 0x2e, 0xcd, 0x00, 0xd5, 0x6f, 0xc4, 0x6f, 0x72, 0x6f, 0x97, 0x52, 0x9d, 0x5c, 0x98, 0x2e,
0x06, 0xcd, 0x23, 0x6f, 0x90, 0x6f, 0x99, 0x52, 0xc0, 0xb2, 0x04, 0xbd, 0x54, 0x40, 0xaf, 0xb9, 0x45, 0x40, 0xe1,
0x7f, 0x02, 0x30, 0x06, 0x2f, 0xc0, 0xb2, 0x02, 0x30, 0x03, 0x2f, 0x9b, 0x5c, 0x12, 0x30, 0x94, 0x43, 0x85, 0x43,
0x03, 0xbf, 0x6f, 0xbb, 0x80, 0xb3, 0x20, 0x2f, 0x06, 0x6f, 0x26, 0x01, 0x16, 0x6f, 0x6e, 0x03, 0x45, 0x42, 0xc0,
0x90, 0x29, 0x2e, 0xce, 0x00, 0x9b, 0x52, 0x14, 0x2f, 0x9b, 0x5c, 0x00, 0x2e, 0x93, 0x41, 0x86, 0x41, 0xe3, 0x04,
0xae, 0x07, 0x80, 0xab, 0x04, 0x2f, 0x80, 0x91, 0x0a, 0x2f, 0x86, 0x6f, 0x73, 0x0f, 0x07, 0x2f, 0x83, 0x6f, 0xc0,
0xb2, 0x04, 0x2f, 0x54, 0x42, 0x45, 0x42, 0x12, 0x30, 0x04, 0x2c, 0x11, 0x30, 0x02, 0x2c, 0x11, 0x30, 0x11, 0x30,
0x02, 0xbc, 0x0f, 0xb8, 0xd2, 0x7f, 0x00, 0xb2, 0x0a, 0x2f, 0x01, 0x2e, 0xfc, 0x00, 0x05, 0x2e, 0xc7, 0x01, 0x10,
0x1a, 0x02, 0x2f, 0x21, 0x2e, 0xc7, 0x01, 0x03, 0x2d, 0x02, 0x2c, 0x01, 0x30, 0x01, 0x30, 0xb0, 0x6f, 0x98, 0x2e,
0x95, 0xcf, 0xd1, 0x6f, 0xa0, 0x6f, 0x98, 0x2e, 0x95, 0xcf, 0xe2, 0x6f, 0x9f, 0x52, 0x01, 0x2e, 0xce, 0x00, 0x82,
0x40, 0x50, 0x42, 0x0c, 0x2c, 0x42, 0x42, 0x11, 0x30, 0x23, 0x2e, 0xd2, 0x00, 0x01, 0x30, 0xb0, 0x6f, 0x98, 0x2e,
0x95, 0xcf, 0xa0, 0x6f, 0x01, 0x30, 0x98, 0x2e, 0x95, 0xcf, 0x00, 0x2e, 0xfb, 0x6f, 0x00, 0x5f, 0xb8, 0x2e, 0x83,
0x86, 0x01, 0x30, 0x00, 0x30, 0x94, 0x40, 0x24, 0x18, 0x06, 0x00, 0x53, 0x0e, 0x4f, 0x02, 0xf9, 0x2f, 0xb8, 0x2e,
0xa9, 0x52, 0x00, 0x2e, 0x60, 0x40, 0x41, 0x40, 0x0d, 0xbc, 0x98, 0xbc, 0xc0, 0x2e, 0x01, 0x0a, 0x0f, 0xb8, 0xab,
0x52, 0x53, 0x3c, 0x52, 0x40, 0x40, 0x40, 0x4b, 0x00, 0x82, 0x16, 0x26, 0xb9, 0x01, 0xb8, 0x41, 0x40, 0x10, 0x08,
0x97, 0xb8, 0x01, 0x08, 0xc0, 0x2e, 0x11, 0x30, 0x01, 0x08, 0x43, 0x86, 0x25, 0x40, 0x04, 0x40, 0xd8, 0xbe, 0x2c,
0x0b, 0x22, 0x11, 0x54, 0x42, 0x03, 0x80, 0x4b, 0x0e, 0xf6, 0x2f, 0xb8, 0x2e, 0x9f, 0x50, 0x10, 0x50, 0xad, 0x52,
0x05, 0x2e, 0xd3, 0x00, 0xfb, 0x7f, 0x00, 0x2e, 0x13, 0x40, 0x93, 0x42, 0x41, 0x0e, 0xfb, 0x2f, 0x98, 0x2e, 0xa5,
0xb7, 0x98, 0x2e, 0x87, 0xcf, 0x01, 0x2e, 0xd9, 0x00, 0x00, 0xb2, 0xfb, 0x6f, 0x0b, 0x2f, 0x01, 0x2e, 0x69, 0xf7,
0xb1, 0x3f, 0x01, 0x08, 0x01, 0x30, 0xf0, 0x5f, 0x23, 0x2e, 0xd9, 0x00, 0x21, 0x2e, 0x69, 0xf7, 0x80, 0x2e, 0x7a,
0xb7, 0xf0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0xc0, 0xf8, 0x03, 0x2e, 0xfc, 0xf5, 0x15, 0x54, 0xaf, 0x56, 0x82, 0x08,
0x0b, 0x2e, 0x69, 0xf7, 0xcb, 0x0a, 0xb1, 0x58, 0x80, 0x90, 0xdd, 0xbe, 0x4c, 0x08, 0x5f, 0xb9, 0x59, 0x22, 0x80,
0x90, 0x07, 0x2f, 0x03, 0x34, 0xc3, 0x08, 0xf2, 0x3a, 0x0a, 0x08, 0x02, 0x35, 0xc0, 0x90, 0x4a, 0x0a, 0x48, 0x22,
0xc0, 0x2e, 0x23, 0x2e, 0xfc, 0xf5, 0x10, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x56, 0xc7, 0x98, 0x2e, 0x49, 0xc3, 0x10,
0x30, 0xfb, 0x6f, 0xf0, 0x5f, 0x21, 0x2e, 0xcc, 0x00, 0x21, 0x2e, 0xca, 0x00, 0xb8, 0x2e, 0x03, 0x2e, 0xd3, 0x00,
0x16, 0xb8, 0x02, 0x34, 0x4a, 0x0c, 0x21, 0x2e, 0x2d, 0xf5, 0xc0, 0x2e, 0x23, 0x2e, 0xd3, 0x00, 0x03, 0xbc, 0x21,
0x2e, 0xd5, 0x00, 0x03, 0x2e, 0xd5, 0x00, 0x40, 0xb2, 0x10, 0x30, 0x21, 0x2e, 0x77, 0x00, 0x01, 0x30, 0x05, 0x2f,
0x05, 0x2e, 0xd8, 0x00, 0x80, 0x90, 0x01, 0x2f, 0x23, 0x2e, 0x6f, 0xf5, 0xc0, 0x2e, 0x21, 0x2e, 0xd9, 0x00, 0x11,
0x30, 0x81, 0x08, 0x01, 0x2e, 0x6a, 0xf7, 0x71, 0x3f, 0x23, 0xbd, 0x01, 0x08, 0x02, 0x0a, 0xc0, 0x2e, 0x21, 0x2e,
0x6a, 0xf7, 0x30, 0x25, 0x00, 0x30, 0x21, 0x2e, 0x5a, 0xf5, 0x10, 0x50, 0x21, 0x2e, 0x7b, 0x00, 0x21, 0x2e, 0x7c,
0x00, 0xfb, 0x7f, 0x98, 0x2e, 0xc3, 0xb7, 0x40, 0x30, 0x21, 0x2e, 0xd4, 0x00, 0xfb, 0x6f, 0xf0, 0x5f, 0x03, 0x25,
0x80, 0x2e, 0xaf, 0xb7, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x01, 0x2e, 0x5d, 0xf7, 0x08, 0xbc, 0x80, 0xac, 0x0e, 0xbb, 0x02, 0x2f,
0x00, 0x30, 0x41, 0x04, 0x82, 0x06, 0xc0, 0xa4, 0x00, 0x30, 0x11, 0x2f, 0x40, 0xa9, 0x03, 0x2f, 0x40, 0x91, 0x0d,
0x2f, 0x00, 0xa7, 0x0b, 0x2f, 0x80, 0xb3, 0xb3, 0x58, 0x02, 0x2f, 0x90, 0xa1, 0x26, 0x13, 0x20, 0x23, 0x80, 0x90,
0x10, 0x30, 0x01, 0x2f, 0xcc, 0x0e, 0x00, 0x2f, 0x00, 0x30, 0xb8, 0x2e, 0xb5, 0x50, 0x18, 0x08, 0x08, 0xbc, 0x88,
0xb6, 0x0d, 0x17, 0xc6, 0xbd, 0x56, 0xbc, 0xb7, 0x58, 0xda, 0xba, 0x04, 0x01, 0x1d, 0x0a, 0x10, 0x50, 0x05, 0x30,
0x32, 0x25, 0x45, 0x03, 0xfb, 0x7f, 0xf6, 0x30, 0x21, 0x25, 0x98, 0x2e, 0x37, 0xca, 0x16, 0xb5, 0x9a, 0xbc, 0x06,
0xb8, 0x80, 0xa8, 0x41, 0x0a, 0x0e, 0x2f, 0x80, 0x90, 0x02, 0x2f, 0x2d, 0x50, 0x48, 0x0f, 0x09, 0x2f, 0xbf, 0xa0,
0x04, 0x2f, 0xbf, 0x90, 0x06, 0x2f, 0xb7, 0x54, 0xca, 0x0f, 0x03, 0x2f, 0x00, 0x2e, 0x02, 0x2c, 0xb7, 0x52, 0x2d,
0x52, 0xf2, 0x33, 0x98, 0x2e, 0xd9, 0xc0, 0xfb, 0x6f, 0xf1, 0x37, 0xc0, 0x2e, 0x01, 0x08, 0xf0, 0x5f, 0xbf, 0x56,
0xb9, 0x54, 0xd0, 0x40, 0xc4, 0x40, 0x0b, 0x2e, 0xfd, 0xf3, 0xbf, 0x52, 0x90, 0x42, 0x94, 0x42, 0x95, 0x42, 0x05,
0x30, 0xc1, 0x50, 0x0f, 0x88, 0x06, 0x40, 0x04, 0x41, 0x96, 0x42, 0xc5, 0x42, 0x48, 0xbe, 0x73, 0x30, 0x0d, 0x2e,
0xd8, 0x00, 0x4f, 0xba, 0x84, 0x42, 0x03, 0x42, 0x81, 0xb3, 0x02, 0x2f, 0x2b, 0x2e, 0x6f, 0xf5, 0x06, 0x2d, 0x05,
0x2e, 0x77, 0xf7, 0xbd, 0x56, 0x93, 0x08, 0x25, 0x2e, 0x77, 0xf7, 0xbb, 0x54, 0x25, 0x2e, 0xc2, 0xf5, 0x07, 0x2e,
0xfd, 0xf3, 0x42, 0x30, 0xb4, 0x33, 0xda, 0x0a, 0x4c, 0x00, 0x27, 0x2e, 0xfd, 0xf3, 0x43, 0x40, 0xd4, 0x3f, 0xdc,
0x08, 0x43, 0x42, 0x00, 0x2e, 0x00, 0x2e, 0x43, 0x40, 0x24, 0x30, 0xdc, 0x0a, 0x43, 0x42, 0x04, 0x80, 0x03, 0x2e,
0xfd, 0xf3, 0x4a, 0x0a, 0x23, 0x2e, 0xfd, 0xf3, 0x61, 0x34, 0xc0, 0x2e, 0x01, 0x42, 0x00, 0x2e, 0x60, 0x50, 0x1a,
0x25, 0x7a, 0x86, 0xe0, 0x7f, 0xf3, 0x7f, 0x03, 0x25, 0xc3, 0x52, 0x41, 0x84, 0xdb, 0x7f, 0x33, 0x30, 0x98, 0x2e,
0x16, 0xc2, 0x1a, 0x25, 0x7d, 0x82, 0xf0, 0x6f, 0xe2, 0x6f, 0x32, 0x25, 0x16, 0x40, 0x94, 0x40, 0x26, 0x01, 0x85,
0x40, 0x8e, 0x17, 0xc4, 0x42, 0x6e, 0x03, 0x95, 0x42, 0x41, 0x0e, 0xf4, 0x2f, 0xdb, 0x6f, 0xa0, 0x5f, 0xb8, 0x2e,
0xb0, 0x51, 0xfb, 0x7f, 0x98, 0x2e, 0xe8, 0x0d, 0x5a, 0x25, 0x98, 0x2e, 0x0f, 0x0e, 0xcb, 0x58, 0x32, 0x87, 0xc4,
0x7f, 0x65, 0x89, 0x6b, 0x8d, 0xc5, 0x5a, 0x65, 0x7f, 0xe1, 0x7f, 0x83, 0x7f, 0xa6, 0x7f, 0x74, 0x7f, 0xd0, 0x7f,
0xb6, 0x7f, 0x94, 0x7f, 0x17, 0x30, 0xc7, 0x52, 0xc9, 0x54, 0x51, 0x7f, 0x00, 0x2e, 0x85, 0x6f, 0x42, 0x7f, 0x00,
0x2e, 0x51, 0x41, 0x45, 0x81, 0x42, 0x41, 0x13, 0x40, 0x3b, 0x8a, 0x00, 0x40, 0x4b, 0x04, 0xd0, 0x06, 0xc0, 0xac,
0x85, 0x7f, 0x02, 0x2f, 0x02, 0x30, 0x51, 0x04, 0xd3, 0x06, 0x41, 0x84, 0x05, 0x30, 0x5d, 0x02, 0xc9, 0x16, 0xdf,
0x08, 0xd3, 0x00, 0x8d, 0x02, 0xaf, 0xbc, 0xb1, 0xb9, 0x59, 0x0a, 0x65, 0x6f, 0x11, 0x43, 0xa1, 0xb4, 0x52, 0x41,
0x53, 0x41, 0x01, 0x43, 0x34, 0x7f, 0x65, 0x7f, 0x26, 0x31, 0xe5, 0x6f, 0xd4, 0x6f, 0x98, 0x2e, 0x37, 0xca, 0x32,
0x6f, 0x75, 0x6f, 0x83, 0x40, 0x42, 0x41, 0x23, 0x7f, 0x12, 0x7f, 0xf6, 0x30, 0x40, 0x25, 0x51, 0x25, 0x98, 0x2e,
0x37, 0xca, 0x14, 0x6f, 0x20, 0x05, 0x70, 0x6f, 0x25, 0x6f, 0x69, 0x07, 0xa2, 0x6f, 0x31, 0x6f, 0x0b, 0x30, 0x04,
0x42, 0x9b, 0x42, 0x8b, 0x42, 0x55, 0x42, 0x32, 0x7f, 0x40, 0xa9, 0xc3, 0x6f, 0x71, 0x7f, 0x02, 0x30, 0xd0, 0x40,
0xc3, 0x7f, 0x03, 0x2f, 0x40, 0x91, 0x15, 0x2f, 0x00, 0xa7, 0x13, 0x2f, 0x00, 0xa4, 0x11, 0x2f, 0x84, 0xbd, 0x98,
0x2e, 0x79, 0xca, 0x55, 0x6f, 0xb7, 0x54, 0x54, 0x41, 0x82, 0x00, 0xf3, 0x3f, 0x45, 0x41, 0xcb, 0x02, 0xf6, 0x30,
0x98, 0x2e, 0x37, 0xca, 0x35, 0x6f, 0xa4, 0x6f, 0x41, 0x43, 0x03, 0x2c, 0x00, 0x43, 0xa4, 0x6f, 0x35, 0x6f, 0x17,
0x30, 0x42, 0x6f, 0x51, 0x6f, 0x93, 0x40, 0x42, 0x82, 0x00, 0x41, 0xc3, 0x00, 0x03, 0x43, 0x51, 0x7f, 0x00, 0x2e,
0x94, 0x40, 0x41, 0x41, 0x4c, 0x02, 0xc4, 0x6f, 0xd1, 0x56, 0x63, 0x0e, 0x74, 0x6f, 0x51, 0x43, 0xa5, 0x7f, 0x8a,
0x2f, 0x09, 0x2e, 0xd8, 0x00, 0x01, 0xb3, 0x21, 0x2f, 0xcb, 0x58, 0x90, 0x6f, 0x13, 0x41, 0xb6, 0x6f, 0xe4, 0x7f,
0x00, 0x2e, 0x91, 0x41, 0x14, 0x40, 0x92, 0x41, 0x15, 0x40, 0x17, 0x2e, 0x6f, 0xf5, 0xb6, 0x7f, 0xd0, 0x7f, 0xcb,
0x7f, 0x98, 0x2e, 0x00, 0x0c, 0x07, 0x15, 0xc2, 0x6f, 0x14, 0x0b, 0x29, 0x2e, 0x6f, 0xf5, 0xc3, 0xa3, 0xc1, 0x8f,
0xe4, 0x6f, 0xd0, 0x6f, 0xe6, 0x2f, 0x14, 0x30, 0x05, 0x2e, 0x6f, 0xf5, 0x14, 0x0b, 0x29, 0x2e, 0x6f, 0xf5, 0x18,
0x2d, 0xcd, 0x56, 0x04, 0x32, 0xb5, 0x6f, 0x1c, 0x01, 0x51, 0x41, 0x52, 0x41, 0xc3, 0x40, 0xb5, 0x7f, 0xe4, 0x7f,
0x98, 0x2e, 0x1f, 0x0c, 0xe4, 0x6f, 0x21, 0x87, 0x00, 0x43, 0x04, 0x32, 0xcf, 0x54, 0x5a, 0x0e, 0xef, 0x2f, 0x15,
0x54, 0x09, 0x2e, 0x77, 0xf7, 0x22, 0x0b, 0x29, 0x2e, 0x77, 0xf7, 0xfb, 0x6f, 0x50, 0x5e, 0xb8, 0x2e, 0x10, 0x50,
0x01, 0x2e, 0xd4, 0x00, 0x00, 0xb2, 0xfb, 0x7f, 0x51, 0x2f, 0x01, 0xb2, 0x48, 0x2f, 0x02, 0xb2, 0x42, 0x2f, 0x03,
0x90, 0x56, 0x2f, 0xd7, 0x52, 0x79, 0x80, 0x42, 0x40, 0x81, 0x84, 0x00, 0x40, 0x42, 0x42, 0x98, 0x2e, 0x93, 0x0c,
0xd9, 0x54, 0xd7, 0x50, 0xa1, 0x40, 0x98, 0xbd, 0x82, 0x40, 0x3e, 0x82, 0xda, 0x0a, 0x44, 0x40, 0x8b, 0x16, 0xe3,
0x00, 0x53, 0x42, 0x00, 0x2e, 0x43, 0x40, 0x9a, 0x02, 0x52, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x15, 0x54, 0x4a, 0x0e,
0x3a, 0x2f, 0x3a, 0x82, 0x00, 0x30, 0x41, 0x40, 0x21, 0x2e, 0x85, 0x0f, 0x40, 0xb2, 0x0a, 0x2f, 0x98, 0x2e, 0xb1,
0x0c, 0x98, 0x2e, 0x45, 0x0e, 0x98, 0x2e, 0x5b, 0x0e, 0xfb, 0x6f, 0xf0, 0x5f, 0x00, 0x30, 0x80, 0x2e, 0xce, 0xb7,
0xdd, 0x52, 0xd3, 0x54, 0x42, 0x42, 0x4f, 0x84, 0x73, 0x30, 0xdb, 0x52, 0x83, 0x42, 0x1b, 0x30, 0x6b, 0x42, 0x23,
0x30, 0x27, 0x2e, 0xd7, 0x00, 0x37, 0x2e, 0xd4, 0x00, 0x21, 0x2e, 0xd6, 0x00, 0x7a, 0x84, 0x17, 0x2c, 0x42, 0x42,
0x30, 0x30, 0x21, 0x2e, 0xd4, 0x00, 0x12, 0x2d, 0x21, 0x30, 0x00, 0x30, 0x23, 0x2e, 0xd4, 0x00, 0x21, 0x2e, 0x7b,
0xf7, 0x0b, 0x2d, 0x17, 0x30, 0x98, 0x2e, 0x51, 0x0c, 0xd5, 0x50, 0x0c, 0x82, 0x72, 0x30, 0x2f, 0x2e, 0xd4, 0x00,
0x25, 0x2e, 0x7b, 0xf7, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xf0, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0x0a, 0x25, 0x39,
0x86, 0xfb, 0x7f, 0xe1, 0x32, 0x62, 0x30, 0x98, 0x2e, 0xc2, 0xc4, 0xb5, 0x56, 0xa5, 0x6f, 0xab, 0x08, 0x91, 0x6f,
0x4b, 0x08, 0xdf, 0x56, 0xc4, 0x6f, 0x23, 0x09, 0x4d, 0xba, 0x93, 0xbc, 0x8c, 0x0b, 0xd1, 0x6f, 0x0b, 0x09, 0xcb,
0x52, 0xe1, 0x5e, 0x56, 0x42, 0xaf, 0x09, 0x4d, 0xba, 0x23, 0xbd, 0x94, 0x0a, 0xe5, 0x6f, 0x68, 0xbb, 0xeb, 0x08,
0xbd, 0xb9, 0x63, 0xbe, 0xfb, 0x6f, 0x52, 0x42, 0xe3, 0x0a, 0xc0, 0x2e, 0x43, 0x42, 0x90, 0x5f, 0xd1, 0x50, 0x03,
0x2e, 0x25, 0xf3, 0x13, 0x40, 0x00, 0x40, 0x9b, 0xbc, 0x9b, 0xb4, 0x08, 0xbd, 0xb8, 0xb9, 0x98, 0xbc, 0xda, 0x0a,
0x08, 0xb6, 0x89, 0x16, 0xc0, 0x2e, 0x19, 0x00, 0x62, 0x02, 0x10, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x81, 0x0d, 0x01,
0x2e, 0xd4, 0x00, 0x31, 0x30, 0x08, 0x04, 0xfb, 0x6f, 0x01, 0x30, 0xf0, 0x5f, 0x23, 0x2e, 0xd6, 0x00, 0x21, 0x2e,
0xd7, 0x00, 0xb8, 0x2e, 0x01, 0x2e, 0xd7, 0x00, 0x03, 0x2e, 0xd6, 0x00, 0x48, 0x0e, 0x01, 0x2f, 0x80, 0x2e, 0x1f,
0x0e, 0xb8, 0x2e, 0xe3, 0x50, 0x21, 0x34, 0x01, 0x42, 0x82, 0x30, 0xc1, 0x32, 0x25, 0x2e, 0x62, 0xf5, 0x01, 0x00,
0x22, 0x30, 0x01, 0x40, 0x4a, 0x0a, 0x01, 0x42, 0xb8, 0x2e, 0xe3, 0x54, 0xf0, 0x3b, 0x83, 0x40, 0xd8, 0x08, 0xe5,
0x52, 0x83, 0x42, 0x00, 0x30, 0x83, 0x30, 0x50, 0x42, 0xc4, 0x32, 0x27, 0x2e, 0x64, 0xf5, 0x94, 0x00, 0x50, 0x42,
0x40, 0x42, 0xd3, 0x3f, 0x84, 0x40, 0x7d, 0x82, 0xe3, 0x08, 0x40, 0x42, 0x83, 0x42, 0xb8, 0x2e, 0xdd, 0x52, 0x00,
0x30, 0x40, 0x42, 0x7c, 0x86, 0xb9, 0x52, 0x09, 0x2e, 0x70, 0x0f, 0xbf, 0x54, 0xc4, 0x42, 0xd3, 0x86, 0x54, 0x40,
0x55, 0x40, 0x94, 0x42, 0x85, 0x42, 0x21, 0x2e, 0xd7, 0x00, 0x42, 0x40, 0x25, 0x2e, 0xfd, 0xf3, 0xc0, 0x42, 0x7e,
0x82, 0x05, 0x2e, 0x7d, 0x00, 0x80, 0xb2, 0x14, 0x2f, 0x05, 0x2e, 0x89, 0x00, 0x27, 0xbd, 0x2f, 0xb9, 0x80, 0x90,
0x02, 0x2f, 0x21, 0x2e, 0x6f, 0xf5, 0x0c, 0x2d, 0x07, 0x2e, 0x71, 0x0f, 0x14, 0x30, 0x1c, 0x09, 0x05, 0x2e, 0x77,
0xf7, 0xbd, 0x56, 0x47, 0xbe, 0x93, 0x08, 0x94, 0x0a, 0x25, 0x2e, 0x77, 0xf7, 0xe7, 0x54, 0x50, 0x42, 0x4a, 0x0e,
0xfc, 0x2f, 0xb8, 0x2e, 0x50, 0x50, 0x02, 0x30, 0x43, 0x86, 0xe5, 0x50, 0xfb, 0x7f, 0xe3, 0x7f, 0xd2, 0x7f, 0xc0,
0x7f, 0xb1, 0x7f, 0x00, 0x2e, 0x41, 0x40, 0x00, 0x40, 0x48, 0x04, 0x98, 0x2e, 0x74, 0xc0, 0x1e, 0xaa, 0xd3, 0x6f,
0x14, 0x30, 0xb1, 0x6f, 0xe3, 0x22, 0xc0, 0x6f, 0x52, 0x40, 0xe4, 0x6f, 0x4c, 0x0e, 0x12, 0x42, 0xd3, 0x7f, 0xeb,
0x2f, 0x03, 0x2e, 0x86, 0x0f, 0x40, 0x90, 0x11, 0x30, 0x03, 0x2f, 0x23, 0x2e, 0x86, 0x0f, 0x02, 0x2c, 0x00, 0x30,
0xd0, 0x6f, 0xfb, 0x6f, 0xb0, 0x5f, 0xb8, 0x2e, 0x40, 0x50, 0xf1, 0x7f, 0x0a, 0x25, 0x3c, 0x86, 0xeb, 0x7f, 0x41,
0x33, 0x22, 0x30, 0x98, 0x2e, 0xc2, 0xc4, 0xd3, 0x6f, 0xf4, 0x30, 0xdc, 0x09, 0x47, 0x58, 0xc2, 0x6f, 0x94, 0x09,
0xeb, 0x58, 0x6a, 0xbb, 0xdc, 0x08, 0xb4, 0xb9, 0xb1, 0xbd, 0xe9, 0x5a, 0x95, 0x08, 0x21, 0xbd, 0xf6, 0xbf, 0x77,
0x0b, 0x51, 0xbe, 0xf1, 0x6f, 0xeb, 0x6f, 0x52, 0x42, 0x54, 0x42, 0xc0, 0x2e, 0x43, 0x42, 0xc0, 0x5f, 0x50, 0x50,
0xf5, 0x50, 0x31, 0x30, 0x11, 0x42, 0xfb, 0x7f, 0x7b, 0x30, 0x0b, 0x42, 0x11, 0x30, 0x02, 0x80, 0x23, 0x33, 0x01,
0x42, 0x03, 0x00, 0x07, 0x2e, 0x80, 0x03, 0x05, 0x2e, 0xd3, 0x00, 0x23, 0x52, 0xe2, 0x7f, 0xd3, 0x7f, 0xc0, 0x7f,
0x98, 0x2e, 0xb6, 0x0e, 0xd1, 0x6f, 0x08, 0x0a, 0x1a, 0x25, 0x7b, 0x86, 0xd0, 0x7f, 0x01, 0x33, 0x12, 0x30, 0x98,
0x2e, 0xc2, 0xc4, 0xd1, 0x6f, 0x08, 0x0a, 0x00, 0xb2, 0x0d, 0x2f, 0xe3, 0x6f, 0x01, 0x2e, 0x80, 0x03, 0x51, 0x30,
0xc7, 0x86, 0x23, 0x2e, 0x21, 0xf2, 0x08, 0xbc, 0xc0, 0x42, 0x98, 0x2e, 0xa5, 0xb7, 0x00, 0x2e, 0x00, 0x2e, 0xd0,
0x2e, 0xb0, 0x6f, 0x0b, 0xb8, 0x03, 0x2e, 0x1b, 0x00, 0x08, 0x1a, 0xb0, 0x7f, 0x70, 0x30, 0x04, 0x2f, 0x21, 0x2e,
0x21, 0xf2, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0x6d, 0xc0, 0x98, 0x2e, 0x5d, 0xc0, 0xed, 0x50, 0x98,
0x2e, 0x44, 0xcb, 0xef, 0x50, 0x98, 0x2e, 0x46, 0xc3, 0xf1, 0x50, 0x98, 0x2e, 0x53, 0xc7, 0x35, 0x50, 0x98, 0x2e,
0x64, 0xcf, 0x10, 0x30, 0x98, 0x2e, 0xdc, 0x03, 0x20, 0x26, 0xc0, 0x6f, 0x02, 0x31, 0x12, 0x42, 0xab, 0x33, 0x0b,
0x42, 0x37, 0x80, 0x01, 0x30, 0x01, 0x42, 0xf3, 0x37, 0xf7, 0x52, 0xfb, 0x50, 0x44, 0x40, 0xa2, 0x0a, 0x42, 0x42,
0x8b, 0x31, 0x09, 0x2e, 0x5e, 0xf7, 0xf9, 0x54, 0xe3, 0x08, 0x83, 0x42, 0x1b, 0x42, 0x23, 0x33, 0x4b, 0x00, 0xbc,
0x84, 0x0b, 0x40, 0x33, 0x30, 0x83, 0x42, 0x0b, 0x42, 0xe0, 0x7f, 0xd1, 0x7f, 0x98, 0x2e, 0x58, 0xb7, 0xd1, 0x6f,
0x80, 0x30, 0x40, 0x42, 0x03, 0x30, 0xe0, 0x6f, 0xf3, 0x54, 0x04, 0x30, 0x00, 0x2e, 0x00, 0x2e, 0x01, 0x89, 0x62,
0x0e, 0xfa, 0x2f, 0x43, 0x42, 0x11, 0x30, 0xfb, 0x6f, 0xc0, 0x2e, 0x01, 0x42, 0xb0, 0x5f, 0xc1, 0x4a, 0x00, 0x00,
0x6d, 0x57, 0x00, 0x00, 0x77, 0x8e, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xd3, 0xff, 0xff, 0xff, 0xe5, 0xff, 0xff,
0xff, 0xee, 0xe1, 0xff, 0xff, 0x7c, 0x13, 0x00, 0x00, 0x46, 0xe6, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1,
0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00,
0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e,
0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80, 0x2e, 0x00, 0xc1, 0x80,
0x2e, 0x00, 0xc1
};
/*! @name Global array that stores the feature input configuration of BMI270 */
const struct bmi2_feature_config bmi270_feat_in[BMI270_MAX_FEAT_IN] = {
{ .type = BMI2_MAX_BURST_LEN, .page = BMI2_PAGE_1, .start_addr = BMI270_MAX_BURST_LEN_STRT_ADDR },
{ .type = BMI2_CRT_GYRO_SELF_TEST, .page = BMI2_PAGE_1, .start_addr = BMI270_CRT_GYRO_SELF_TEST_STRT_ADDR },
{ .type = BMI2_ABORT_CRT_GYRO_SELF_TEST, .page = BMI2_PAGE_1, .start_addr = BMI270_ABORT_STRT_ADDR },
{ .type = BMI2_AXIS_MAP, .page = BMI2_PAGE_1, .start_addr = BMI270_AXIS_MAP_STRT_ADDR },
{ .type = BMI2_GYRO_SELF_OFF, .page = BMI2_PAGE_1, .start_addr = BMI270_GYRO_SELF_OFF_STRT_ADDR },
{ .type = BMI2_NVM_PROG_PREP, .page = BMI2_PAGE_1, .start_addr = BMI270_NVM_PROG_PREP_STRT_ADDR },
{ .type = BMI2_GYRO_GAIN_UPDATE, .page = BMI2_PAGE_1, .start_addr = BMI270_GYRO_GAIN_UPDATE_STRT_ADDR },
{ .type = BMI2_ANY_MOTION, .page = BMI2_PAGE_1, .start_addr = BMI270_ANY_MOT_STRT_ADDR },
{ .type = BMI2_NO_MOTION, .page = BMI2_PAGE_2, .start_addr = BMI270_NO_MOT_STRT_ADDR },
{ .type = BMI2_SIG_MOTION, .page = BMI2_PAGE_2, .start_addr = BMI270_SIG_MOT_STRT_ADDR },
{ .type = BMI2_STEP_COUNTER_PARAMS, .page = BMI2_PAGE_3, .start_addr = BMI270_STEP_CNT_1_STRT_ADDR },
{ .type = BMI2_STEP_DETECTOR, .page = BMI2_PAGE_6, .start_addr = BMI270_STEP_CNT_4_STRT_ADDR },
{ .type = BMI2_STEP_COUNTER, .page = BMI2_PAGE_6, .start_addr = BMI270_STEP_CNT_4_STRT_ADDR },
{ .type = BMI2_STEP_ACTIVITY, .page = BMI2_PAGE_6, .start_addr = BMI270_STEP_CNT_4_STRT_ADDR },
{ .type = BMI2_WRIST_GESTURE, .page = BMI2_PAGE_6, .start_addr = BMI270_WRIST_GEST_STRT_ADDR },
{ .type = BMI2_WRIST_WEAR_WAKE_UP, .page = BMI2_PAGE_7, .start_addr = BMI270_WRIST_WEAR_WAKE_UP_STRT_ADDR },
};
/*! @name Global array that stores the feature output configuration */
const struct bmi2_feature_config bmi270_feat_out[BMI270_MAX_FEAT_OUT] = {
{ .type = BMI2_STEP_COUNTER, .page = BMI2_PAGE_0, .start_addr = BMI270_STEP_CNT_OUT_STRT_ADDR },
{ .type = BMI2_STEP_ACTIVITY, .page = BMI2_PAGE_0, .start_addr = BMI270_STEP_ACT_OUT_STRT_ADDR },
{ .type = BMI2_WRIST_GESTURE, .page = BMI2_PAGE_0, .start_addr = BMI270_WRIST_GEST_OUT_STRT_ADDR },
{ .type = BMI2_GYRO_GAIN_UPDATE, .page = BMI2_PAGE_0, .start_addr = BMI270_GYR_USER_GAIN_OUT_STRT_ADDR },
{ .type = BMI2_GYRO_CROSS_SENSE, .page = BMI2_PAGE_0, .start_addr = BMI270_GYRO_CROSS_SENSE_STRT_ADDR },
{ .type = BMI2_NVM_STATUS, .page = BMI2_PAGE_0, .start_addr = BMI270_NVM_VFRM_OUT_STRT_ADDR },
{ .type = BMI2_VFRM_STATUS, .page = BMI2_PAGE_0, .start_addr = BMI270_NVM_VFRM_OUT_STRT_ADDR }
};
/******************************************************************************/
/*! Local Function Prototypes
******************************************************************************/
/*!
* @brief This internal API is used to validate the device pointer for
* null conditions.
*
* @param[in] dev : Structure instance of bmi2_dev.
*
* @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/
static int8_t null_ptr_check(const struct bmi2_dev *dev);
/***************************************************************************/
/*! User Interface Definitions
****************************************************************************/
/*!
* @brief This API:
* 1) updates the device structure with address of the configuration file.
* 2) Initializes BMI270 sensor.
* 3) Writes the configuration file.
* 4) Updates the feature offset parameters in the device structure.
* 5) Updates the maximum number of pages, in the device structure.
*/
int8_t bmi270_init(struct bmi2_dev *dev)
{
/* Variable to define error */
int8_t rslt;
/* Null-pointer check */
rslt = null_ptr_check(dev);
if (rslt == BMI2_OK)
{
/* Assign chip id of BMI270 */
dev->chip_id = BMI270_CHIP_ID;
/* get the size of config array */
dev->config_size = sizeof(bmi270_config_file);
/* Enable the variant specific features if any */
dev->variant_feature = BMI2_GYRO_CROSS_SENS_ENABLE | BMI2_CRT_RTOSK_ENABLE;
/* An extra dummy byte is read during SPI read */
if (dev->intf == BMI2_SPI_INTERFACE)
{
dev->dummy_byte = 1;
}
else
{
dev->dummy_byte = 0;
}
/* If configuration file pointer is not assigned any address */
if (!dev->config_file_ptr)
{
/* Give the address of the configuration file array to
* the device pointer
*/
dev->config_file_ptr = bmi270_config_file;
}
/* Initialize BMI2 sensor */
rslt = bmi2_sec_init(dev);
if (rslt == BMI2_OK)
{
/* Assign the offsets of the feature input
* configuration to the device structure
*/
dev->feat_config = bmi270_feat_in;
/* Assign the offsets of the feature output to
* the device structure
*/
dev->feat_output = bmi270_feat_out;
/* Assign the maximum number of pages to the
* device structure
*/
dev->page_max = BMI270_MAX_PAGE_NUM;
/* Assign maximum number of input sensors/
* features to device structure
*/
dev->input_sens = BMI270_MAX_FEAT_IN;
/* Assign maximum number of output sensors/
* features to device structure
*/
dev->out_sens = BMI270_MAX_FEAT_OUT;
/* Get the gyroscope cross axis sensitivity */
rslt = bmi2_get_gyro_cross_sense(dev);
}
}
return rslt;
}
/***************************************************************************/
/*! Local Function Definitions
****************************************************************************/
/*!
* @brief This internal API is used to validate the device structure pointer for
* null conditions.
*/
static int8_t null_ptr_check(const struct bmi2_dev *dev)
{
/* Variable to define error */
int8_t rslt = BMI2_OK;
if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_us == NULL))
{
/* Device structure pointer is not valid */
rslt = BMI2_E_NULL_PTR;
}
return rslt;
}

View File

@ -0,0 +1,132 @@
/**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi270.h
* @date 2020-01-10
* @version v2.46.1
*
*/#ifndef BMI270_H_
#define BMI270_H_
/*! CPP guard */
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
/*! Header files
****************************************************************************/
#include "bmi2.h"
/***************************************************************************/
/*! Macro definitions
****************************************************************************/
/*! @name BMI270 Chip identifier */
#define BMI270_CHIP_ID UINT8_C(0x24)
/*! @name BMI270 feature input start addresses */
#define BMI270_MAX_BURST_LEN_STRT_ADDR UINT8_C(0x02)
#define BMI270_CRT_GYRO_SELF_TEST_STRT_ADDR UINT8_C(0x03)
#define BMI270_ABORT_STRT_ADDR UINT8_C(0x03)
#define BMI270_AXIS_MAP_STRT_ADDR UINT8_C(0x04)
#define BMI270_GYRO_SELF_OFF_STRT_ADDR UINT8_C(0x05)
#define BMI270_NVM_PROG_PREP_STRT_ADDR UINT8_C(0x05)
#define BMI270_GYRO_GAIN_UPDATE_STRT_ADDR UINT8_C(0x06)
#define BMI270_ANY_MOT_STRT_ADDR UINT8_C(0x0C)
#define BMI270_NO_MOT_STRT_ADDR UINT8_C(0x00)
#define BMI270_SIG_MOT_STRT_ADDR UINT8_C(0x04)
#define BMI270_STEP_CNT_1_STRT_ADDR UINT8_C(0x00)
#define BMI270_STEP_CNT_4_STRT_ADDR UINT8_C(0x02)
#define BMI270_WRIST_GEST_STRT_ADDR UINT8_C(0x06)
#define BMI270_WRIST_WEAR_WAKE_UP_STRT_ADDR UINT8_C(0x00)
/*! @name BMI270 feature output start addresses */
#define BMI270_STEP_CNT_OUT_STRT_ADDR UINT8_C(0x00)
#define BMI270_STEP_ACT_OUT_STRT_ADDR UINT8_C(0x04)
#define BMI270_WRIST_GEST_OUT_STRT_ADDR UINT8_C(0x06)
#define BMI270_GYR_USER_GAIN_OUT_STRT_ADDR UINT8_C(0x08)
#define BMI270_GYRO_CROSS_SENSE_STRT_ADDR UINT8_C(0x0C)
#define BMI270_NVM_VFRM_OUT_STRT_ADDR UINT8_C(0x0E)
/*! @name Defines maximum number of pages */
#define BMI270_MAX_PAGE_NUM UINT8_C(8)
/*! @name Defines maximum number of feature input configurations */
#define BMI270_MAX_FEAT_IN UINT8_C(16)
/*! @name Defines maximum number of feature outputs */
#define BMI270_MAX_FEAT_OUT UINT8_C(7)
/*! @name Mask definitions for feature interrupt status bits */
#define BMI270_SIG_MOT_STATUS_MASK UINT8_C(0x01)
#define BMI270_STEP_CNT_STATUS_MASK UINT8_C(0x02)
#define BMI270_STEP_ACT_STATUS_MASK UINT8_C(0x04)
#define BMI270_WRIST_WAKE_UP_STATUS_MASK UINT8_C(0x08)
#define BMI270_WRIST_GEST_STATUS_MASK UINT8_C(0x10)
#define BMI270_NO_MOT_STATUS_MASK UINT8_C(0x20)
#define BMI270_ANY_MOT_STATUS_MASK UINT8_C(0x40)
/***************************************************************************/
/*! BMI270 User Interface function prototypes
****************************************************************************/
/*!
* @brief This API:
* 1) updates the device structure with address of the configuration file.
* 2) Initializes BMI270 sensor.
* 3) Writes the configuration file.
* 4) Updates the feature offset parameters in the device structure.
* 5) Updates the maximum number of pages, in the device structure.
*
* @param[in, out] dev : Structure instance of bmi2_dev.
*
* @return Result of API execution status
*
* @retval BMI2_OK - Success
* @retval BMI2_E_NULL_PTR - Error: Null pointer error
* @retval BMI2_E_COM_FAIL - Error: Communication fail
* @retval BMI2_E_DEV_NOT_FOUND - Invalid device
*/
int8_t bmi270_init(struct bmi2_dev *dev);
/******************************************************************************/
/*! @name C++ Guard Macros */
/******************************************************************************/
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* BMI270_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,409 @@
/**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi2_ois.c
* @date 2020-01-10
* @version v2.46.1
*
*//******************************************************************************/
/*! @name Header Files */
/******************************************************************************/
#include "bmi2_ois.h"
/******************************************************************************/
/*! Local Function Prototypes
******************************************************************************/
/*!
* @brief This internal API gets the OIS accelerometer and the gyroscope data.
*
* @param[out] ois_data : Structure instance of bmi2_sens_axes_data.
* @param[in] reg_addr : Register address where data is stored.
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
* @param[in] ois_gyr_cross_sens_zx :"gyroscope cross sensitivity value which was calculated during
* bmi2xy_init(), refer the example ois_accel_gyro.c for more info"
*
* @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/
static int8_t get_ois_acc_gyr_data(struct bmi2_ois_sens_axes_data *ois_data,
uint8_t reg_addr,
const struct bmi2_ois_dev *ois_dev,
int16_t ois_gyr_cross_sens_zx);
/*!
* @brief This internal API is used to validate the OIS device pointer for null
* conditions.
*
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
*
* @return Result of API execution status
* @retval zero -> Success / +ve value -> Warning / -ve value -> Error
*/
static int8_t null_ptr_check(const struct bmi2_ois_dev *ois_dev);
/*!
* @brief This internal API corrects the gyroscope cross-axis sensitivity
* between the z and the x axis.
*
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
* @param[in] ois_gyr_cross_sens_zx : "gyroscope cross sensitivity value which was calculated during bmi2xy_init(),
* refer the example ois_accel_gyro.c for more info"
*
*/
static void comp_gyro_cross_axis_sensitivity(struct bmi2_ois_sens_axes_data *ois_data, int16_t ois_gyr_cross_sens_zx);
/******************************************************************************/
/*! @name User Interface Definitions */
/******************************************************************************/
/*!
* @brief This API reads the data from the given OIS register address of bmi2
* sensor.
*/
int8_t bmi2_ois_get_regs(uint8_t ois_reg_addr,
uint8_t *ois_reg_data,
uint16_t data_len,
const struct bmi2_ois_dev *ois_dev)
{
/* Variable to define error */
int8_t rslt;
/* Variable to define dummy byte for SPI read */
uint8_t dummy_byte = 1;
/* Variable to define temporary length */
uint16_t temp_len = data_len + dummy_byte;
/* Variable to define temporary buffer */
uint8_t temp_buf[temp_len];
/* Variable to index bytes read */
uint16_t index = 0;
/* Null-pointer check */
rslt = null_ptr_check(ois_dev);
if ((rslt == BMI2_OIS_OK) && (ois_reg_data != NULL))
{
/* Configuring reg_addr for SPI Interface */
ois_reg_addr = (ois_reg_addr | BMI2_OIS_SPI_RD_MASK);
/* Read from OIS register through OIS interface */
rslt = ois_dev->ois_read(ois_dev->dev_id, ois_reg_addr, temp_buf, temp_len);
if (rslt == BMI2_OIS_OK)
{
/* Read the data from the position next to dummy byte */
while (index < data_len)
{
ois_reg_data[index] = temp_buf[index + dummy_byte];
index++;
}
}
else
{
rslt = BMI2_OIS_E_COM_FAIL;
}
}
else
{
rslt = BMI2_OIS_E_NULL_PTR;
}
return rslt;
}
/*!
* @brief This API writes data to the given OIS register address of bmi2 sensor.
*/
int8_t bmi2_ois_set_regs(uint8_t ois_reg_addr,
uint8_t *ois_reg_data,
uint16_t data_len,
const struct bmi2_ois_dev *ois_dev)
{
/* Variable to define error */
int8_t rslt;
/* Null-pointer check */
rslt = null_ptr_check(ois_dev);
if ((rslt == BMI2_OIS_OK) && (ois_reg_data != NULL))
{
/* Configuring reg_addr for SPI Interface */
ois_reg_addr = (ois_reg_addr & BMI2_OIS_SPI_WR_MASK);
/* Burst write to OIS register through OIS interface */
rslt = ois_dev->ois_write(ois_dev->dev_id, ois_reg_addr, ois_reg_data, data_len);
if (rslt != BMI2_OIS_OK)
{
rslt = BMI2_OIS_E_COM_FAIL;
}
}
else
{
rslt = BMI2_OIS_E_NULL_PTR;
}
return rslt;
}
/*!
* @brief This API enables/disables accelerometer/gyroscope data read through
* OIS interface.
*/
int8_t bmi2_ois_set_config(const struct bmi2_ois_dev *ois_dev)
{
/* Variable to define error */
int8_t rslt;
/* Variable to store data */
uint8_t reg_data = 0;
/* Null-pointer check */
rslt = null_ptr_check(ois_dev);
if (rslt == BMI2_OIS_OK)
{
rslt = bmi2_ois_get_regs(BMI2_OIS_CONFIG_ADDR, &reg_data, 1, ois_dev);
if (rslt == BMI2_OIS_OK)
{
/* Enable/Disable Low pass filter */
reg_data = BMI2_SET_BIT_POS0(reg_data, BMI2_OIS_LP_FILTER_EN, ois_dev->lp_filter_en);
/* Configures Low pass filter cut-off frequency */
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_LP_FILTER_CONFIG, ois_dev->lp_filter_config);
/* Low pass filter - mute on secondary interface */
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_LP_FILTER_MUTE, ois_dev->lp_filter_mute);
/* Enable/Disable ois on accelerometer */
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_ACC_EN, ois_dev->acc_en);
/* Enable/Disable ois on gyroscope */
reg_data = BMI2_OIS_SET_BITS(reg_data, BMI2_OIS_GYR_EN, ois_dev->gyr_en);
/* Set the OIS configurations */
rslt = bmi2_ois_set_regs(BMI2_OIS_CONFIG_ADDR, &reg_data, 1, ois_dev);
}
}
return rslt;
}
/*!
* @brief This API gets the status of accelerometer/gyroscope enable for data
* read through OIS interface.
*/
int8_t bmi2_ois_get_config(struct bmi2_ois_dev *ois_dev)
{
/* Variable to define error */
int8_t rslt;
/* Variable to store data */
uint8_t reg_data = 0;
/* Null-pointer check */
rslt = null_ptr_check(ois_dev);
if (rslt == BMI2_OIS_OK)
{
rslt = bmi2_ois_get_regs(BMI2_OIS_CONFIG_ADDR, &reg_data, 1, ois_dev);
if (rslt == BMI2_OIS_OK)
{
/* Get the status of Low pass filter enable */
ois_dev->lp_filter_en = BMI2_GET_BIT_POS0(reg_data, BMI2_OIS_LP_FILTER_EN);
/* Get the status of Low pass filter cut-off frequency */
ois_dev->lp_filter_config = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_LP_FILTER_CONFIG);
/* Get the status of Low pass filter mute */
ois_dev->lp_filter_mute = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_LP_FILTER_MUTE);
/* Get the status of accelerometer enable */
ois_dev->acc_en = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_ACC_EN);
/* Get the status of gyroscope enable */
ois_dev->gyr_en = BMI2_OIS_GET_BITS(reg_data, BMI2_OIS_GYR_EN);
}
}
return rslt;
}
/*!
* @brief This API reads accelerometer/gyroscope data through OIS interface.
*/
int8_t bmi2_ois_read_data(const uint8_t *sens_sel,
uint8_t n_sens,
struct bmi2_ois_dev *ois_dev,
int16_t gyr_cross_sens_zx)
{
/* Variable to define error */
int8_t rslt;
/* Variable to define loop */
uint8_t loop = 0;
/* Variable to update register address */
uint8_t reg_addr = 0;
/* Null-pointer check */
rslt = null_ptr_check(ois_dev);
if ((rslt == BMI2_OIS_OK) && (sens_sel != NULL))
{
for (loop = 0; loop < n_sens; loop++)
{
switch (sens_sel[loop])
{
case BMI2_OIS_ACCEL:
/* Update OIS accelerometer address */
reg_addr = BMI2_OIS_ACC_X_LSB_ADDR;
/* Get OIS accelerometer data */
rslt = get_ois_acc_gyr_data(&ois_dev->acc_data, reg_addr, ois_dev, 0);
break;
case BMI2_OIS_GYRO:
/* Update OIS gyroscope address */
reg_addr = BMI2_OIS_GYR_X_LSB_ADDR;
/* Get OIS gyroscope data */
rslt = get_ois_acc_gyr_data(&ois_dev->gyr_data, reg_addr, ois_dev, gyr_cross_sens_zx);
break;
default:
rslt = BMI2_OIS_E_INVALID_SENSOR;
break;
}
/* Return error if any of the get sensor data fails */
if (rslt != BMI2_OIS_OK)
{
break;
}
}
}
else
{
rslt = BMI2_OIS_E_NULL_PTR;
}
return rslt;
}
/***************************************************************************/
/*! Local Function Definitions
****************************************************************************/
/*!
* @brief This internal API gets the accelerometer and the gyroscope data.
*/
static int8_t get_ois_acc_gyr_data(struct bmi2_ois_sens_axes_data *ois_data,
uint8_t reg_addr,
const struct bmi2_ois_dev *ois_dev,
int16_t ois_gyr_cross_sens_zx)
{
/* Variable to define error */
int8_t rslt;
/* Variables to store MSB value */
uint8_t msb;
/* Variables to store LSB value */
uint8_t lsb;
/* Variables to store both MSB and LSB value */
uint16_t msb_lsb;
/* Variables to define index */
uint8_t index = 0;
/* Array to define data stored in register */
uint8_t reg_data[BMI2_OIS_ACC_GYR_NUM_BYTES] = { 0 };
/* Read the sensor data */
rslt = bmi2_ois_get_regs(reg_addr, reg_data, BMI2_OIS_ACC_GYR_NUM_BYTES, ois_dev);
if (rslt == BMI2_OIS_OK)
{
/* Read x-axis data */
lsb = reg_data[index++];
msb = reg_data[index++];
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
ois_data->x = (int16_t)msb_lsb;
/* Read y-axis data */
lsb = reg_data[index++];
msb = reg_data[index++];
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
ois_data->y = (int16_t)msb_lsb;
/* Read z-axis data */
lsb = reg_data[index++];
msb = reg_data[index++];
msb_lsb = ((uint16_t)msb << 8) | (uint16_t)lsb;
ois_data->z = (int16_t)msb_lsb;
comp_gyro_cross_axis_sensitivity(ois_data, ois_gyr_cross_sens_zx);
}
return rslt;
}
/*!
* @brief This internal API is used to validate the device structure pointer for
* null conditions.
*/
static int8_t null_ptr_check(const struct bmi2_ois_dev *ois_dev)
{
/* Variable to define error */
int8_t rslt = BMI2_OIS_OK;
if ((ois_dev == NULL) || (ois_dev->ois_read == NULL) || (ois_dev->ois_write == NULL) ||
(ois_dev->ois_delay_ms == NULL))
{
/* Device structure pointer is NULL */
rslt = BMI2_OIS_E_NULL_PTR;
}
return rslt;
}
/*!
* @brief This internal API corrects the gyroscope cross-axis sensitivity
* between the z and the x axis.
*/
static void comp_gyro_cross_axis_sensitivity(struct bmi2_ois_sens_axes_data *ois_data, int16_t ois_gyr_cross_sens_zx)
{
/* Get the compensated gyroscope x-axis */
ois_data->x = ois_data->x - (int16_t)(((int32_t)ois_gyr_cross_sens_zx * (int32_t)ois_data->z) / 512);
}

View File

@ -0,0 +1,311 @@
/**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi2_ois.h
* @date 2020-01-10
* @version v2.46.1
*
*//**
* Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved.
*
* BSD-3-Clause
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @file bmi2_ois.h
* @date 10/01/2020
* @version
*
*/
#ifndef BMI2_OIS_H_
#define BMI2_OIS_H_
/*! CPP guard */
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
/*! Header files
****************************************************************************/
#ifdef __KERNEL__
#include <linux/types.h>
#include <linux/kernel.h>
#else
#include <stdint.h>
#include <stddef.h>
#endif
/******************************************************************************/
/*! @name Macros */
/******************************************************************************/
/*! @name Utility macros */
#define BMI2_OIS_SET_BITS(reg_data, bitname, data) \
((reg_data & ~(bitname##_MASK)) | \
((data << bitname##_POS) & bitname##_MASK))
#define BMI2_OIS_GET_BITS(reg_data, bitname) \
((reg_data & (bitname##_MASK)) >> \
(bitname##_POS))
#define BMI2_SET_BIT_POS0(reg_data, bitname, data) \
((reg_data & ~(bitname##_MASK)) | \
(data & bitname##_MASK))
#define BMI2_GET_BIT_POS0(reg_data, bitname) (reg_data & (bitname##_MASK))
/*! @name To define success code */
#define BMI2_OIS_OK UINT8_C(0)
/*! @name To define error codes */
#define BMI2_OIS_E_NULL_PTR INT8_C(-1)
#define BMI2_OIS_E_COM_FAIL INT8_C(-2)
#define BMI2_OIS_E_INVALID_SENSOR INT8_C(-8)
/*! @name Mask definitions for SPI read/write address for OIS */
#define BMI2_OIS_SPI_RD_MASK UINT8_C(0x80)
#define BMI2_OIS_SPI_WR_MASK UINT8_C(0x7F)
/*! @name BMI2 OIS data bytes */
#define BMI2_OIS_ACC_GYR_NUM_BYTES UINT8_C(6)
/*! @name Macros to select sensor for OIS data read */
#define BMI2_OIS_ACCEL UINT8_C(0x01)
#define BMI2_OIS_GYRO UINT8_C(0x02)
/*! @name Macros to define OIS register addresses */
#define BMI2_OIS_CONFIG_ADDR UINT8_C(0x40)
#define BMI2_OIS_ACC_X_LSB_ADDR UINT8_C(0x0C)
#define BMI2_OIS_GYR_X_LSB_ADDR UINT8_C(0x12)
/*! @name Mask definitions for OIS configurations */
#define BMI2_OIS_GYR_EN_MASK UINT8_C(0x40)
#define BMI2_OIS_ACC_EN_MASK UINT8_C(0x80)
/*! @name Bit Positions for OIS configurations */
#define BMI2_OIS_GYR_EN_POS UINT8_C(0x06)
#define BMI2_OIS_ACC_EN_POS UINT8_C(0x07)
/*! Low pass filter configuration position and mask */
#define BMI2_OIS_LP_FILTER_EN_POS UINT8_C(0x00)
#define BMI2_OIS_LP_FILTER_EN_MASK UINT8_C(0x01)
#define BMI2_OIS_LP_FILTER_CONFIG_POS UINT8_C(0x01)
#define BMI2_OIS_LP_FILTER_CONFIG_MASK UINT8_C(0x06)
#define BMI2_OIS_LP_FILTER_MUTE_POS UINT8_C(0x05)
#define BMI2_OIS_LP_FILTER_MUTE_MASK UINT8_C(0x20)
/******************************************************************************/
/*! @name Function Pointers */
/******************************************************************************/
/*! For interfacing to the I2C or SPI read and write functions */
typedef int8_t (*bmi2_ois_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t len);
/*! For interfacing to the delay function */
typedef void (*bmi2_ois_delay_fptr_t)(uint32_t period);
/******************************************************************************/
/*! @name Structure Declarations */
/******************************************************************************/
/*! @name Structure to define accelerometer and gyroscope sensor axes for OIS */
struct bmi2_ois_sens_axes_data
{
/*! Data in x-axis */
int16_t x;
/*! Data in y-axis */
int16_t y;
/*! Data in z-axis */
int16_t z;
};
/*! @name Structure to define bmi2 OIS sensor configurations */
struct bmi2_ois_dev
{
/*! Device id of BMI2 */
uint8_t dev_id;
/*! Read function pointer */
bmi2_ois_com_fptr_t ois_read;
/*! Write function pointer */
bmi2_ois_com_fptr_t ois_write;
/*! Delay function pointer */
bmi2_ois_delay_fptr_t ois_delay_ms;
/*! Low pass filter en/dis */
uint8_t lp_filter_en;
/*! Low pass filter cut-off frequency */
uint8_t lp_filter_config;
/*! Low pass filter mute */
uint8_t lp_filter_mute;
/*! Accelerometer enable for OIS */
uint8_t acc_en;
/*! Gyroscope enable for OIS */
uint8_t gyr_en;
/*! Accelerometer data axes */
struct bmi2_ois_sens_axes_data acc_data;
/*! Gyroscope data axes */
struct bmi2_ois_sens_axes_data gyr_data;
};
/***************************************************************************/
/*! BMI2 OIS User Interface function prototypes
****************************************************************************/
/*!
* @brief This API reads the data from the given OIS register address of bmi2
* sensor.
*
* @param[in] ois_reg_addr : OIS register address from which data is read.
* @param[out] ois_reg_data : Pointer to data buffer where read data is stored.
* @param[in] data_len : No. of bytes of data to be read.
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
*
* @return Result of API execution status
* @retval zero -> Success / -ve value -> Error
*/
int8_t bmi2_ois_get_regs(uint8_t ois_reg_addr,
uint8_t *ois_reg_data,
uint16_t data_len,
const struct bmi2_ois_dev *ois_dev);
/*!
* @brief This API writes data to the given OIS register address of bmi2 sensor.
*
* @param[in] ois_reg_addr : OIS register address to which the data is written.
* @param[in] ois_reg_data : Pointer to data buffer in which data to be written
* is stored.
* @param[in] data_len : No. of bytes of data to be written.
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
*
* @return Result of API execution status
* @retval zero -> Success / -ve value -> Error
*/
int8_t bmi2_ois_set_regs(uint8_t ois_reg_addr,
uint8_t *ois_reg_data,
uint16_t data_len,
const struct bmi2_ois_dev *ois_dev);
/*!
* @brief This API enables/disables accelerometer/gyroscope data read through
* OIS interface.
*
* @param[in] ois_dev : Structure instance of bmi2_ois_dev.
*
* @return Result of API execution status
* @retval zero -> Success / -ve value -> Error
*/
int8_t bmi2_ois_set_config(const struct bmi2_ois_dev *ois_dev);
/*!
* @brief This API gets the status of accelerometer/gyroscope enable for data
* read through OIS interface.
*
* @param[in, out] ois_dev : Structure instance of bmi2_ois_dev.
*
* @note Enabling and disabling is done during OIS structure initialization.
*
* @return Result of API execution status
* @retval zero -> Success / -ve value -> Error
*/
int8_t bmi2_ois_get_config(struct bmi2_ois_dev *ois_dev);
/*!
* @brief This API reads accelerometer/gyroscope data through OIS interface.
*
* @param[in] sens_sel : Select sensor whose data is to be read.
* @param[in] n_sens : Number of sensors selected.
* @param[in, out] ois_dev : Structure instance of bmi2_ois_dev.
* @param[in] gyr_cross_sens_zx : Store the gyroscope cross sensitivity values taken from the bmi2xy
* (refer bmi2_ois example).
*
* sens_sel | Value
* ---------------|---------------
* BMI2_OIS_ACCEL | 0x01
* BMI2_OIS_GYRO | 0x02
*
* @return Result of API execution status
* @retval zero -> Success / -ve value -> Error.
*/
int8_t bmi2_ois_read_data(const uint8_t *sens_sel,
uint8_t n_sens,
struct bmi2_ois_dev *ois_dev,
int16_t gyr_cross_sens_zx);
/******************************************************************************/
/*! @name C++ Guard Macros */
/******************************************************************************/
#ifdef __cplusplus
}
#endif /* End of CPP guard */
#endif /* BMI2_OIS_H_ */

View File

@ -0,0 +1,177 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length);
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
/* Variable to define rslt */
int8_t rslt;
struct bmi2_dev dev;
/*To enable I2C interface*/
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/* To enable SPI interface*/
/* dev.read = spi_reg_read;
* dev.write = spi_reg_write;
* dev.delay_us = delay_us;
* dev.read_write_len = 4096;
* dev.intf = BMI2_SPI_INTERFACE;
* dev.dev_id = SPI_CS;
* dev.dummy_byte = 1;
*/
dev.config_file_ptr = NULL;
/* Initialize BMI2 */
rslt = bmi270_init(&dev);
print_rslt(rslt);
return 0;
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of us*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -0,0 +1,219 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_read(uint8_t i2c_add, uint8_t reg_add, uint8_t *regd_data, uint16_t length);
int8_t i2c_reg_write(uint8_t i2c_add, uint8_t reg_add, const uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_add, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_add, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
struct bmi2_dev dev;
/*! @name Structure to define type of sensor and their respective data */
struct bmi2_sensor_data sensor_data;
uint8_t sens_sel[2] = { BMI2_ACCEL, BMI2_GYRO };
/*variable to define rslt*/
int8_t rslt;
/*to enable i2c interface*/
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/*to enable spi interface*/
/* dev.read = spi_reg_read;
dev.write = spi_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 4096;
dev.intf = BMI2_SPI_INTERFACE;
dev.dev_id = SPI_CS;
dev.dummy_byte = 1;
*/
dev.config_file_ptr = NULL;
/*to Initialize bmi270*/
rslt = bmi270_init(&dev);
print_rslt(rslt);
rslt = bmi2_sensor_enable(&sens_sel[0], 1, &dev);
print_rslt(rslt);
rslt = bmi2_sensor_disable(&sens_sel[1], 1, &dev);
print_rslt(rslt);
sensor_data.type = BMI2_ACCEL;
dev.delay_us(100000);
printf("\nbefore CRT Accel x,y,z values\n");
/* read the accel data before CRT*/
rslt = bmi2_get_sensor_data(&sensor_data, 1, &dev);
print_rslt(rslt);
printf("\nX axes: %d, Y axes: %d, Z axes: %d \n", sensor_data.sens_data.acc.x, sensor_data.sens_data.acc.y, sensor_data.sens_data.acc.z );
/*brief This API is to run the CRT process*/
rslt = bmi2_do_crt(&dev);
print_rslt(rslt);
if(rslt == BMI2_OK)
{
printf("\nAfter CRT Accel x,y,z values\n");
/* read the accel data after CRT*/
rslt = bmi2_get_sensor_data(&sensor_data, 1, &dev);
print_rslt(rslt);
printf("X axes: %d, Y axes: %d, Z axes: %d",sensor_data.sens_data.acc.x, sensor_data.sens_data.acc.y, sensor_data.sens_data.acc.z );
}
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of us*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
case BMI2_E_CRT_ERROR:
printf("warning[%d] : CRT fail\r\n", rslt);
break;
case BMI2_E_ABORT_ERROR:
printf("warning[%d] : Abort eror\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -0,0 +1,230 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length);
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
/* Variable to define rslt */
int8_t rslt;
struct bmi2_dev dev;
struct bmi2_sens_config config;
/* Array to select sensors */
uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_NO_MOTION };
/* Variable to get any-motion status */
uint16_t no_mot_status = 0;
/* Select features and their pins to be mapped to */
struct bmi2_sens_int_config sens_int = { .type = BMI2_NO_MOTION, .hw_int_pin = BMI2_INT1 };
/*to enable the i2c interface*/
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/*to enable spi interface*/
/*
* ac_setup_interface(AC_SPI_STD);
* dev.read = ac_spi_read;
* dev.write = ac_spi_write;
* dev.delay_us = delay_us;
* dev.read_write_len = 4096;
* dev.intf = BMI2_SPI_INTERFACE;
* dev.dev_id = SPI_CS;
* dev.dummy_byte = 1;
*/
dev.config_file_ptr = NULL;
/*initialize bmi270 */
rslt = bmi270_init(&dev);
print_rslt(rslt);
/* Enable the selected sensors */
rslt = bmi2_sensor_enable(sens_list, 2, &dev);
print_rslt(rslt);
/* Configure type of feature */
config.type = BMI2_NO_MOTION;
/* Get default configurations for the type of feature selected */
rslt = bmi2_get_sensor_config(&config, 1, &dev);
print_rslt(rslt);
/* Set the new configuration */
rslt = bmi2_set_sensor_config(&config, 1, &dev);
print_rslt(rslt);
/* Set the new configuration */
rslt = bmi2_map_feat_int(&sens_int, 1, &dev);
print_rslt(rslt);
printf("Do not move the board\n");
while (1)
{
/* Clear buffer */
no_mot_status = 0;
dev.delay_us(50000);
/* Check the interrupt status of the no-motion */
rslt = bmi2_get_int_status(&no_mot_status, &dev);
print_rslt(rslt);
if (no_mot_status & BMI270_NO_MOT_STATUS_MASK)
{
printf("no_mot_status = %x\n", no_mot_status);
printf("No-motion interrupt generated");
break;
}
dev.delay_us(50000);
}
return 0;
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of us*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -0,0 +1,238 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length);
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
struct bmi2_dev dev;
struct bmi2_sensor_data sensor_data;
struct bmi2_sens_config config;
int8_t rslt;
/* Sensor type of sensor to select sensor */
uint8_t sensor_sel[2] = { BMI2_ACCEL, BMI2_STEP_COUNTER };
/* For status */
uint16_t step_status = 0;
/* Select features and their pins to be mapped to */
struct bmi2_sens_int_config sens_int = { .type = BMI2_STEP_COUNTER, .hw_int_pin = BMI2_INT2 };
/* Sensor type of sensor to get data */
sensor_data.type = BMI2_STEP_COUNTER;
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/* To enable SPI interface*/
/*
* dev.read = spi_reg_read;
* dev.write = spi_reg_write;
* dev.delay_us = delay_us;
* dev.read_write_len = 4096;
* dev.intf = BMI2_SPI_INTERFACE;
* dev.dev_id = SPI_CS;
* dev.dummy_byte = 1;
*/
/* Initialize by enabling firmware download */
dev.config_file_ptr = NULL;
rslt = bmi270_init(&dev);
print_rslt(rslt);
/* Enable the accelerometer and step-counter sensor */
rslt = bmi2_sensor_enable(sensor_sel, 2, &dev);
print_rslt(rslt);
/* Update the type of sensor for setting the configurations */
config.type = BMI2_STEP_COUNTER;
/* Get default configurations for the type of feature selected */
rslt = bmi2_get_sensor_config(&config, 1, &dev);
print_rslt(rslt);
/* Enable water-mark level for to get interrupt after 20 step counts */
config.cfg.step_counter.watermark_level = 1;
/* Set the configurations */
rslt = bmi2_set_sensor_config(&config, 1, &dev);
print_rslt(rslt);
/* Map the feature interrupt */
rslt = bmi2_map_feat_int(&sens_int, 1, &dev);
print_rslt(rslt);
printf("Move the board for step counter\n");
while (1)
{
/* Check the interrupt status of the step counter */
rslt = bmi2_get_int_status(&step_status, &dev);
print_rslt(rslt);
if (rslt == BMI2_OK)
{
if (step_status == BMI270_STEP_CNT_STATUS_MASK)
{
printf("Step detected\n");
/* Get step counter output */
rslt = bmi2_get_sensor_data(&sensor_data, 1, &dev);
print_rslt(rslt);
/* Print the step counter output */
printf("No of steps counted = %ld", sensor_data.sens_data.step_counter_output);
break;
}
}
dev.delay_us(50000);
}
return 0;
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of us*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -0,0 +1,244 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length);
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
struct bmi2_dev dev;
/* Variable to define rslt */
int8_t rslt;
/* Array to select sensors */
uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_WRIST_GESTURE };
/* Variable to get wrist gesture status */
uint16_t wrist_gest_status = 0;
/* Select features and their pins to be mapped to */
struct bmi2_sens_int_config sens_int = { .type = BMI2_WRIST_GESTURE, .hw_int_pin = BMI2_INT1 };
/* Sensor configuration structure */
struct bmi2_sens_config config = { 0 };
/* Sensor data structure */
struct bmi2_sensor_data sens_data = { 0 };
/*To enable I2C interface*/
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/* To enable SPI interface*/
/*
* dev.read = spi_reg_read;
* dev.write = spi_reg_write;
* dev.delay_us = delay_us;
* dev.read_write_len = 4096;
* dev.intf = BMI2_SPI_INTERFACE;
* dev.dev_id = SPI_CS;
* dev.dummy_byte = 1;
*/
dev.config_file_ptr = NULL;
/* Initialize BMI270 */
rslt = bmi270_init(&dev);
print_rslt(rslt);
/* Enable the selected sensors */
rslt = bmi2_sensor_enable(sens_list, 2, &dev);
print_rslt(rslt);
/* Configure type of feature */
config.type = BMI2_WRIST_GESTURE;
/* Get default configurations for the type of feature selected */
rslt = bmi2_get_sensor_config(&config, 1, &dev);
print_rslt(rslt);
if (rslt == BMI2_OK)
{
/* Arm Position where the device is attached */
config.cfg.wrist_gest.wearable_arm = BMI2_ARM_LEFT;
/* Set the new configuration along with interrupt mapping */
rslt = bmi2_set_sensor_config(&config, 1, &dev);
print_rslt(rslt);
}
/* Map the feature interrupt */
rslt = bmi2_map_feat_int(&sens_int, 1, &dev);
print_rslt(rslt);
printf("Flip the board in portrait landscape mode:\n");
while (1)
{
/* Check the interrupt status of the wrist gesture */
rslt = bmi2_get_int_status(&wrist_gest_status, &dev);
print_rslt(rslt);
if (rslt == BMI2_OK)
{
if (wrist_gest_status & BMI270_WRIST_GEST_STATUS_MASK)
{
printf("Wrist gesture detected\n");
/* Get wrist gesture output */
rslt = bmi2_get_sensor_data(&sens_data, 1, &dev);
print_rslt(rslt);
/* Print the wrist gesture output */
printf("wrist gesture = %d\r\n", sens_data.sens_data.wrist_gesture_output);
break;
}
dev.delay_us(100000);
}
return 0;
}
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of us*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -0,0 +1,235 @@
#include <stdio.h>
#include "bmi2.h"
#include "bmi270.h"
void delay_us(uint32_t period);
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length);
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length);
void print_rslt(int8_t rslt);
int main(void)
{
struct bmi2_dev dev;
/* Variable to define rslt */
int8_t rslt;
/* Array to select sensors */
uint8_t sens_list[2] = { BMI2_ACCEL, BMI2_WRIST_WEAR_WAKE_UP };
/* Variable to get wrist gesture status */
uint16_t wrist_wear_wakeup_status = 0;
/* Select features and their pins to be mapped to */
struct bmi2_sens_int_config sens_int = { .type = BMI2_WRIST_WEAR_WAKE_UP, .hw_int_pin = BMI2_INT1 };
/* Sensor configuration structure */
struct bmi2_sens_config config = { 0 };
/* Sensor data structure */
struct bmi2_sensor_data sens_data = { 0 };
dev.read = i2c_reg_read;
dev.write = i2c_reg_write;
dev.delay_us = delay_us;
dev.read_write_len = 128;
dev.intf = BMI2_I2C_INTERFACE;
dev.dev_id = BMI2_I2C_PRIM_ADDR;
/* To enable SPI interface*/
/* dev.read = spi_reg_read;
* dev.write = spi_reg_write;
* dev.delay_us = delay_us;
* dev.read_write_len = 4096;
* dev.intf = BMI2_SPI_INTERFACE;
* dev.dev_id = SPI_CS;
* dev.dummy_byte = 1;
*/
dev.config_file_ptr = NULL;
/* Initialize BMI2 */
rslt = bmi270_init(&dev);
print_rslt(rslt);
/* Enable the selected sensors */
rslt = bmi2_sensor_enable(sens_list, 2, &dev);
print_rslt(rslt);
/* Configure type of feature */
config.type = BMI2_WRIST_WEAR_WAKE_UP;
/* Get default configurations for the type of feature selected */
rslt = bmi2_get_sensor_config(&config, 1, &dev);
print_rslt(rslt);
if (rslt == BMI2_OK)
{
/* Set the new configuration along with interrupt mapping */
rslt = bmi2_set_sensor_config(&config, 1, &dev);
print_rslt(rslt);
}
/* Map the feature interrupt */
rslt = bmi2_map_feat_int(&sens_int, 1, &dev);
print_rslt(rslt);
printf("Lift the board in portrait landscape position and tilt in a particular direction\n");
while (1)
{
/* Check the interrupt status of the wrist gesture */
rslt = bmi2_get_int_status(&wrist_wear_wakeup_status, &dev);
print_rslt(rslt);
if (rslt == BMI2_OK)
{
if (wrist_wear_wakeup_status & BMI270_WRIST_WAKE_UP_STATUS_MASK)
{
printf("Wrist wear wakeup detected\n");
/* Get wrist gesture output */
rslt = bmi2_get_sensor_data(&sens_data, 1, &dev);
print_rslt(rslt);
/* Print the wrist gesture output */
printf("wrist gesture = %d\r\n", sens_data.sens_data.wrist_gesture_output);
break;
}
dev.delay_us(100000);
}
return 0;
}
}
/*!
* @brief Function that creates a mandatory delay required in some of the APIs such as "bma4_write_config_file",
* "bma4_write_regs", "bma4_set_accel_config" and so on.
*
* @param[in] period_us : the required wait time in microseconds.
* @return void.
*
*/
void delay_us(uint32_t period)
{
/* Wait for a period amount of ms*/
}
/*!
* @brief Function for writing the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose value is to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_write(uint8_t i2c_addr, uint8_t reg_addr, const uint8_t *reg_data, uint16_t length)
{
/* Write to registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through I2C bus.
*
* @param[in] i2c_addr : Sensor I2C address.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t i2c_reg_read(uint8_t i2c_addr, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using I2C. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for writing the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[in] reg_data : Pointer to the data buffer whose data has to be written.
* @param[in] length : No of bytes to write.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_write(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Write to registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Function for reading the sensor's registers through SPI bus.
*
* @param[in] cs : Chip select to enable the sensor.
* @param[in] reg_addr : Register address.
* @param[out] reg_data : Pointer to the data buffer to store the read data.
* @param[in] length : No of bytes to read.
*
* @return Status of execution
* @retval 0 -> Success
* @retval >0 -> Failure Info
*
*/
int8_t spi_reg_read(uint8_t cs, uint8_t reg_addr, uint8_t *reg_data, uint16_t length)
{
/* Read from registers using SPI. Return 0 for a successful execution. */
return 0;
}
/*!
* @brief Prints the execution status of the APIs.
*
* @param[in] api_name : name of the API whose execution status has to be printed.
* @param[in] rslt : error code returned by the API whose execution status has to be printed.
*
* @return void.
*/
void print_rslt(int8_t rslt)
{
switch (rslt)
{
case BMI2_OK:
/* Do nothing */
break;
case BMI2_E_NULL_PTR:
printf("Error [%d] : Null pointer\r\n", rslt);
break;
case BMI2_E_COM_FAIL:
printf("Error [%d] : Communication failure\r\n", rslt);
break;
case BMI2_E_DEV_NOT_FOUND:
printf("Error [%d] : Device not found\r\n", rslt);
break;
case BMI2_E_INVALID_SENSOR:
printf("Error [%d] : Invalid sensor\r\n", rslt);
break;
case BMI2_E_SELF_TEST_FAIL:
printf("Warning [%d] : Self test failed\r\n", rslt);
break;
case BMI2_E_INVALID_INT_PIN:
printf("warning [%d] : invalid int pin\r\n", rslt);
break;
default:
printf("Error [%d] : Unknown error code\r\n", rslt);
break;
}
}

View File

@ -188,7 +188,8 @@ COMMON_SRC = \
io/vtx_rtc6705.c \ io/vtx_rtc6705.c \
io/vtx_smartaudio.c \ io/vtx_smartaudio.c \
io/vtx_tramp.c \ io/vtx_tramp.c \
io/vtx_control.c io/vtx_control.c \
./lib/main/BoschSensortec/BMI270-Sensor-API/bmi270.c
COMMON_DEVICE_SRC = \ COMMON_DEVICE_SRC = \
$(CMSIS_SRC) \ $(CMSIS_SRC) \

View File

@ -127,14 +127,14 @@
const char * const lookupTableAccHardware[] = { const char * const lookupTableAccHardware[] = {
"AUTO", "NONE", "ADXL345", "MPU6050", "MMA8452", "BMA280", "LSM303DLHC", "AUTO", "NONE", "ADXL345", "MPU6050", "MMA8452", "BMA280", "LSM303DLHC",
"MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605", "MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605",
"BMI160", "FAKE" "BMI160", "BMI270", "FAKE"
}; };
// sync with gyroHardware_e // sync with gyroHardware_e
const char * const lookupTableGyroHardware[] = { const char * const lookupTableGyroHardware[] = {
"AUTO", "NONE", "MPU6050", "L3G4200D", "MPU3050", "L3GD20", "AUTO", "NONE", "MPU6050", "L3G4200D", "MPU3050", "L3GD20",
"MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605", "MPU6000", "MPU6500", "MPU9250", "ICM20601", "ICM20602", "ICM20608G", "ICM20649", "ICM20689", "ICM42605",
"BMI160", "FAKE" "BMI160", "BMI270", "FAKE"
}; };
#if defined(USE_SENSOR_NAMES) || defined(USE_BARO) #if defined(USE_SENSOR_NAMES) || defined(USE_BARO)

View File

@ -54,6 +54,7 @@ typedef enum {
GYRO_ICM20689, GYRO_ICM20689,
GYRO_ICM42605, GYRO_ICM42605,
GYRO_BMI160, GYRO_BMI160,
GYRO_BMI270,
GYRO_FAKE GYRO_FAKE
} gyroHardware_e; } gyroHardware_e;
@ -68,6 +69,7 @@ typedef enum {
GYRO_RATE_1_kHz, GYRO_RATE_1_kHz,
GYRO_RATE_1100_Hz, GYRO_RATE_1100_Hz,
GYRO_RATE_3200_Hz, GYRO_RATE_3200_Hz,
GYRO_RATE_6400_Hz,
GYRO_RATE_8_kHz, GYRO_RATE_8_kHz,
GYRO_RATE_9_kHz, GYRO_RATE_9_kHz,
GYRO_RATE_32_kHz, GYRO_RATE_32_kHz,

View File

@ -47,6 +47,7 @@
#include "drivers/accgyro/accgyro_mpu6050.h" #include "drivers/accgyro/accgyro_mpu6050.h"
#include "drivers/accgyro/accgyro_mpu6500.h" #include "drivers/accgyro/accgyro_mpu6500.h"
#include "drivers/accgyro/accgyro_spi_bmi160.h" #include "drivers/accgyro/accgyro_spi_bmi160.h"
#include "drivers/accgyro/accgyro_spi_bmi270.h"
#include "drivers/accgyro/accgyro_spi_icm20649.h" #include "drivers/accgyro/accgyro_spi_icm20649.h"
#include "drivers/accgyro/accgyro_spi_icm20689.h" #include "drivers/accgyro/accgyro_spi_icm20689.h"
#include "drivers/accgyro/accgyro_spi_icm42605.h" #include "drivers/accgyro/accgyro_spi_icm42605.h"
@ -205,17 +206,20 @@ static gyroSpiDetectFn_t gyroSpiDetectFnTable[] = {
#ifdef USE_GYRO_SPI_MPU9250 #ifdef USE_GYRO_SPI_MPU9250
mpu9250SpiDetect, mpu9250SpiDetect,
#endif #endif
#ifdef USE_GYRO_SPI_ICM20649
icm20649SpiDetect,
#endif
#ifdef USE_GYRO_SPI_ICM20689 #ifdef USE_GYRO_SPI_ICM20689
icm20689SpiDetect, // icm20689SpiDetect detects ICM20602 and ICM20689 icm20689SpiDetect, // icm20689SpiDetect detects ICM20602 and ICM20689
#endif #endif
#ifdef USE_ACCGYRO_BMI160
bmi160Detect,
#endif
#ifdef USE_ACCGYRO_BMI270
bmi270Detect,
#endif
#ifdef USE_GYRO_SPI_ICM42605 #ifdef USE_GYRO_SPI_ICM42605
icm42605SpiDetect, icm42605SpiDetect,
#endif #endif
#ifdef USE_ACCGYRO_BMI160 #ifdef USE_GYRO_SPI_ICM20649
bmi160Detect, icm20649SpiDetect,
#endif #endif
#ifdef USE_GYRO_L3GD20 #ifdef USE_GYRO_L3GD20
l3gd20Detect, l3gd20Detect,

View File

@ -201,6 +201,7 @@ typedef enum {
ICM_20689_SPI, ICM_20689_SPI,
ICM_42605_SPI, ICM_42605_SPI,
BMI_160_SPI, BMI_160_SPI,
BMI_270_SPI,
L3GD20_SPI, L3GD20_SPI,
} mpuSensor_e; } mpuSensor_e;

View File

@ -0,0 +1,455 @@
/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software under the terms of the
* GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Cleanflight and Betaflight are distributed in the hope that they
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#ifdef USE_ACCGYRO_BMI270
#include "drivers/accgyro/accgyro.h"
#include "drivers/accgyro/accgyro_spi_bmi270.h"
#include "drivers/bus_spi.h"
#include "drivers/exti.h"
#include "drivers/io.h"
#include "drivers/io_impl.h"
#include "drivers/nvic.h"
#include "drivers/sensor.h"
#include "drivers/time.h"
// Include the device config (microcode) that must be uploaded to the sensor
#include "../../../../lib/main/BoschSensortec/BMI270-Sensor-API/bmi270.h"
#define BMI270_SPI_DIVISOR 16
#define BMI270_FIFO_FRAME_SIZE 6
// BMI270 registers (not the complete list)
typedef enum {
BMI270_REG_CHIP_ID = 0x00,
BMI270_REG_ERR_REG = 0x02,
BMI270_REG_STATUS = 0x03,
BMI270_REG_ACC_DATA_X_LSB = 0x0C,
BMI270_REG_GYR_DATA_X_LSB = 0x12,
BMI270_REG_SENSORTIME_0 = 0x18,
BMI270_REG_SENSORTIME_1 = 0x19,
BMI270_REG_SENSORTIME_2 = 0x1A,
BMI270_REG_EVENT = 0x1B,
BMI270_REG_INT_STATUS_0 = 0x1C,
BMI270_REG_INT_STATUS_1 = 0x1D,
BMI270_REG_INTERNAL_STATUS = 0x21,
BMI270_REG_TEMPERATURE_LSB = 0x22,
BMI270_REG_TEMPERATURE_MSB = 0x23,
BMI270_REG_FIFO_LENGTH_LSB = 0x24,
BMI270_REG_FIFO_LENGTH_MSB = 0x25,
BMI270_REG_FIFO_DATA = 0x26,
BMI270_REG_ACC_CONF = 0x40,
BMI270_REG_ACC_RANGE = 0x41,
BMI270_REG_GYRO_CONF = 0x42,
BMI270_REG_GYRO_RANGE = 0x43,
BMI270_REG_AUX_CONF = 0x44,
BMI270_REG_FIFO_DOWNS = 0x45,
BMI270_REG_FIFO_WTM_0 = 0x46,
BMI270_REG_FIFO_WTM_1 = 0x47,
BMI270_REG_FIFO_CONFIG_0 = 0x48,
BMI270_REG_FIFO_CONFIG_1 = 0x49,
BMI270_REG_SATURATION = 0x4A,
BMI270_REG_INT1_IO_CTRL = 0x53,
BMI270_REG_INT2_IO_CTRL = 0x54,
BMI270_REG_INT_LATCH = 0x55,
BMI270_REG_INT1_MAP_FEAT = 0x56,
BMI270_REG_INT2_MAP_FEAT = 0x57,
BMI270_REG_INT_MAP_DATA = 0x58,
BMI270_REG_INIT_CTRL = 0x59,
BMI270_REG_INIT_DATA = 0x5E,
BMI270_REG_ACC_SELF_TEST = 0x6D,
BMI270_REG_GYR_SELF_TEST_AXES = 0x6E,
BMI270_REG_PWR_CONF = 0x7C,
BMI270_REG_PWR_CTRL = 0x7D,
BMI270_REG_CMD = 0x7E,
} bmi270Register_e;
// BMI270 register configuration values
typedef enum {
BMI270_VAL_CMD_SOFTRESET = 0xB6,
BMI270_VAL_CMD_FIFOFLUSH = 0xB0,
BMI270_VAL_PWR_CTRL = 0x0E, // enable gyro, acc and temp sensors
BMI270_VAL_PWR_CONF = 0x02, // disable advanced power save, enable FIFO self-wake
BMI270_VAL_ACC_CONF_ODR800 = 0x0B, // set acc sample rate to 800hz
BMI270_VAL_ACC_CONF_ODR1600 = 0x0C, // set acc sample rate to 1600hz
BMI270_VAL_ACC_CONF_BWP = 0x02, // set acc filter in normal mode
BMI270_VAL_ACC_CONF_HP = 0x01, // set acc in high performance mode
BMI270_VAL_ACC_RANGE_8G = 0x02, // set acc to 8G full scale
BMI270_VAL_ACC_RANGE_16G = 0x03, // set acc to 16G full scale
BMI270_VAL_GYRO_CONF_ODR3200 = 0x0D, // set gyro sample rate to 3200hz
BMI270_VAL_GYRO_CONF_BWP = 0x02, // set gyro filter in normal mode
BMI270_VAL_GYRO_CONF_NOISE_PERF = 0x01, // set gyro in high performance noise mode
BMI270_VAL_GYRO_CONF_FILTER_PERF = 0x01, // set gyro in high performance filter mode
BMI270_VAL_GYRO_RANGE_2000DPS = 0x08, // set gyro to 2000dps full scale
// for some reason you have to enable the ois_range bit (bit 3) for 2000dps as well
// or else the gyro scale will be 250dps when in prefiltered FIFO mode (not documented in datasheet!)
BMI270_VAL_INT_MAP_DATA_DRDY_INT1 = 0x04,// enable the data ready interrupt pin 1
BMI270_VAL_INT_MAP_FIFO_WM_INT1 = 0x02, // enable the FIFO watermark interrupt pin 1
BMI270_VAL_INT1_IO_CTRL_PINMODE = 0x0A, // active high, push-pull, output enabled, input disabled
BMI270_VAL_FIFO_CONFIG_0 = 0x00, // don't stop when full, disable sensortime frame
BMI270_VAL_FIFO_CONFIG_1 = 0x80, // only gyro data in FIFO, use headerless mode
BMI270_VAL_FIFO_DOWNS = 0x00, // select unfiltered gyro data with no downsampling (6.4KHz samples)
BMI270_VAL_FIFO_WTM_0 = 0x06, // set the FIFO watermark level to 1 gyro sample (6 bytes)
BMI270_VAL_FIFO_WTM_1 = 0x00, // FIFO watermark MSB
} bmi270ConfigValues_e;
// BMI270 register reads are 16bits with the first byte a "dummy" value 0
// that must be ignored. The result is in the second byte.
static uint8_t bmi270RegisterRead(const busDevice_t *bus, bmi270Register_e registerId)
{
uint8_t data[2] = { 0, 0 };
if (spiBusReadRegisterBuffer(bus, registerId, data, 2)) {
return data[1];
} else {
return 0;
}
}
static void bmi270RegisterWrite(const busDevice_t *bus, bmi270Register_e registerId, uint8_t value, unsigned delayMs)
{
spiBusWriteRegister(bus, registerId, value);
if (delayMs) {
delay(delayMs);
}
}
// Toggle the CS to switch the device into SPI mode.
// Device switches initializes as I2C and switches to SPI on a low to high CS transition
static void bmi270EnableSPI(const busDevice_t *bus)
{
IOLo(bus->busdev_u.spi.csnPin);
delay(1);
IOHi(bus->busdev_u.spi.csnPin);
delay(10);
}
uint8_t bmi270Detect(const busDevice_t *bus)
{
spiSetDivisor(bus->busdev_u.spi.instance, BMI270_SPI_DIVISOR);
bmi270EnableSPI(bus);
if (bmi270RegisterRead(bus, BMI270_REG_CHIP_ID) == BMI270_CHIP_ID) {
return BMI_270_SPI;
}
return MPU_NONE;
}
static void bmi270UploadConfig(const busDevice_t *bus)
{
bmi270RegisterWrite(bus, BMI270_REG_PWR_CONF, 0, 1);
bmi270RegisterWrite(bus, BMI270_REG_INIT_CTRL, 0, 1);
// Transfer the config file
IOLo(bus->busdev_u.spi.csnPin);
spiTransferByte(bus->busdev_u.spi.instance, BMI270_REG_INIT_DATA);
spiTransfer(bus->busdev_u.spi.instance, bmi270_config_file, NULL, BMI270_CONFIG_SIZE);
IOHi(bus->busdev_u.spi.csnPin);
delay(10);
bmi270RegisterWrite(bus, BMI270_REG_INIT_CTRL, 1, 1);
}
static void bmi270Config(const gyroDev_t *gyro)
{
const busDevice_t *bus = &gyro->bus;
// If running in hardware_lpf experimental mode then switch to FIFO-based,
// 6.4KHz sampling, unfiltered data vs. the default 3.2KHz with hardware filtering
#ifdef USE_GYRO_DLPF_EXPERIMENTAL
const bool fifoMode = (gyro->hardware_lpf == GYRO_HARDWARE_LPF_EXPERIMENTAL);
#else
const bool fifoMode = false;
#endif
// Perform a soft reset to set all configuration to default
// Delay 100ms before continuing configuration
bmi270RegisterWrite(bus, BMI270_REG_CMD, BMI270_VAL_CMD_SOFTRESET, 100);
// Toggle the chip into SPI mode
bmi270EnableSPI(bus);
bmi270UploadConfig(bus);
// Configure the FIFO
if (fifoMode) {
bmi270RegisterWrite(bus, BMI270_REG_FIFO_CONFIG_0, BMI270_VAL_FIFO_CONFIG_0, 1);
bmi270RegisterWrite(bus, BMI270_REG_FIFO_CONFIG_1, BMI270_VAL_FIFO_CONFIG_1, 1);
bmi270RegisterWrite(bus, BMI270_REG_FIFO_DOWNS, BMI270_VAL_FIFO_DOWNS, 1);
bmi270RegisterWrite(bus, BMI270_REG_FIFO_WTM_0, BMI270_VAL_FIFO_WTM_0, 1);
bmi270RegisterWrite(bus, BMI270_REG_FIFO_WTM_1, BMI270_VAL_FIFO_WTM_1, 1);
}
// Configure the accelerometer
bmi270RegisterWrite(bus, BMI270_REG_ACC_CONF, (BMI270_VAL_ACC_CONF_HP << 7) | (BMI270_VAL_ACC_CONF_BWP << 4) | BMI270_VAL_ACC_CONF_ODR800, 1);
// Configure the accelerometer full-scale range
bmi270RegisterWrite(bus, BMI270_REG_ACC_RANGE, BMI270_VAL_ACC_RANGE_16G, 1);
// Configure the gyro
bmi270RegisterWrite(bus, BMI270_REG_GYRO_CONF, (BMI270_VAL_GYRO_CONF_FILTER_PERF << 7) | (BMI270_VAL_GYRO_CONF_NOISE_PERF << 6) | (BMI270_VAL_GYRO_CONF_BWP << 4) | BMI270_VAL_GYRO_CONF_ODR3200, 1);
// Configure the gyro full-range scale
bmi270RegisterWrite(bus, BMI270_REG_GYRO_RANGE, BMI270_VAL_GYRO_RANGE_2000DPS, 1);
// Configure the gyro data ready interrupt
if (fifoMode) {
// Interrupt driven by FIFO watermark level
bmi270RegisterWrite(bus, BMI270_REG_INT_MAP_DATA, BMI270_VAL_INT_MAP_FIFO_WM_INT1, 1);
} else {
// Interrupt driven by data ready
bmi270RegisterWrite(bus, BMI270_REG_INT_MAP_DATA, BMI270_VAL_INT_MAP_DATA_DRDY_INT1, 1);
}
// Configure the behavior of the INT1 pin
bmi270RegisterWrite(bus, BMI270_REG_INT1_IO_CTRL, BMI270_VAL_INT1_IO_CTRL_PINMODE, 1);
// Configure the device for performance mode
bmi270RegisterWrite(bus, BMI270_REG_PWR_CONF, BMI270_VAL_PWR_CONF, 1);
// Enable the gyro, accelerometer and temperature sensor - disable aux interface
bmi270RegisterWrite(bus, BMI270_REG_PWR_CTRL, BMI270_VAL_PWR_CTRL, 1);
// Flush the FIFO
if (fifoMode) {
bmi270RegisterWrite(bus, BMI270_REG_CMD, BMI270_VAL_CMD_FIFOFLUSH, 1);
}
}
extiCallbackRec_t bmi270IntCallbackRec;
#if defined(USE_GYRO_EXTI) && defined(USE_MPU_DATA_READY_SIGNAL)
void bmi270ExtiHandler(extiCallbackRec_t *cb)
{
gyroDev_t *gyro = container_of(cb, gyroDev_t, exti);
gyro->dataReady = true;
}
static void bmi270IntExtiInit(gyroDev_t *gyro)
{
if (gyro->mpuIntExtiTag == IO_TAG_NONE) {
return;
}
IO_t mpuIntIO = IOGetByTag(gyro->mpuIntExtiTag);
IOInit(mpuIntIO, OWNER_GYRO_EXTI, 0);
EXTIHandlerInit(&gyro->exti, bmi270ExtiHandler);
EXTIConfig(mpuIntIO, &gyro->exti, NVIC_PRIO_MPU_INT_EXTI, IOCFG_IN_FLOATING, BETAFLIGHT_EXTI_TRIGGER_RISING);
EXTIEnable(mpuIntIO, true);
}
#endif
static bool bmi270AccRead(accDev_t *acc)
{
enum {
IDX_REG = 0,
IDX_SKIP,
IDX_ACCEL_XOUT_L,
IDX_ACCEL_XOUT_H,
IDX_ACCEL_YOUT_L,
IDX_ACCEL_YOUT_H,
IDX_ACCEL_ZOUT_L,
IDX_ACCEL_ZOUT_H,
BUFFER_SIZE,
};
uint8_t bmi270_rx_buf[BUFFER_SIZE];
static const uint8_t bmi270_tx_buf[BUFFER_SIZE] = {BMI270_REG_ACC_DATA_X_LSB | 0x80, 0, 0, 0, 0, 0, 0, 0};
IOLo(acc->bus.busdev_u.spi.csnPin);
spiTransfer(acc->bus.busdev_u.spi.instance, bmi270_tx_buf, bmi270_rx_buf, BUFFER_SIZE); // receive response
IOHi(acc->bus.busdev_u.spi.csnPin);
acc->ADCRaw[X] = (int16_t)((bmi270_rx_buf[IDX_ACCEL_XOUT_H] << 8) | bmi270_rx_buf[IDX_ACCEL_XOUT_L]);
acc->ADCRaw[Y] = (int16_t)((bmi270_rx_buf[IDX_ACCEL_YOUT_H] << 8) | bmi270_rx_buf[IDX_ACCEL_YOUT_L]);
acc->ADCRaw[Z] = (int16_t)((bmi270_rx_buf[IDX_ACCEL_ZOUT_H] << 8) | bmi270_rx_buf[IDX_ACCEL_ZOUT_L]);
return true;
}
static bool bmi270GyroReadRegister(gyroDev_t *gyro)
{
enum {
IDX_REG = 0,
IDX_SKIP,
IDX_GYRO_XOUT_L,
IDX_GYRO_XOUT_H,
IDX_GYRO_YOUT_L,
IDX_GYRO_YOUT_H,
IDX_GYRO_ZOUT_L,
IDX_GYRO_ZOUT_H,
BUFFER_SIZE,
};
uint8_t bmi270_rx_buf[BUFFER_SIZE];
static const uint8_t bmi270_tx_buf[BUFFER_SIZE] = {BMI270_REG_GYR_DATA_X_LSB | 0x80, 0, 0, 0, 0, 0, 0, 0};
IOLo(gyro->bus.busdev_u.spi.csnPin);
spiTransfer(gyro->bus.busdev_u.spi.instance, bmi270_tx_buf, bmi270_rx_buf, BUFFER_SIZE); // receive response
IOHi(gyro->bus.busdev_u.spi.csnPin);
gyro->gyroADCRaw[X] = (int16_t)((bmi270_rx_buf[IDX_GYRO_XOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_XOUT_L]);
gyro->gyroADCRaw[Y] = (int16_t)((bmi270_rx_buf[IDX_GYRO_YOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_YOUT_L]);
gyro->gyroADCRaw[Z] = (int16_t)((bmi270_rx_buf[IDX_GYRO_ZOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_ZOUT_L]);
return true;
}
#ifdef USE_GYRO_DLPF_EXPERIMENTAL
static bool bmi270GyroReadFifo(gyroDev_t *gyro)
{
enum {
IDX_REG = 0,
IDX_SKIP,
IDX_FIFO_LENGTH_L,
IDX_FIFO_LENGTH_H,
IDX_GYRO_XOUT_L,
IDX_GYRO_XOUT_H,
IDX_GYRO_YOUT_L,
IDX_GYRO_YOUT_H,
IDX_GYRO_ZOUT_L,
IDX_GYRO_ZOUT_H,
BUFFER_SIZE,
};
bool dataRead = false;
static const uint8_t bmi270_tx_buf[BUFFER_SIZE] = {BMI270_REG_FIFO_LENGTH_LSB | 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t bmi270_rx_buf[BUFFER_SIZE];
// Burst read the FIFO length followed by the next 6 bytes containing the gyro axis data for
// the first sample in the queue. It's possible for the FIFO to be empty so we need to check the
// length before using the sample.
IOLo(gyro->bus.busdev_u.spi.csnPin);
spiTransfer(gyro->bus.busdev_u.spi.instance, bmi270_tx_buf, bmi270_rx_buf, BUFFER_SIZE); // receive response
IOHi(gyro->bus.busdev_u.spi.csnPin);
int fifoLength = (uint16_t)((bmi270_rx_buf[IDX_FIFO_LENGTH_H] << 8) | bmi270_rx_buf[IDX_FIFO_LENGTH_L]);
if (fifoLength >= BMI270_FIFO_FRAME_SIZE) {
const int16_t gyroX = (int16_t)((bmi270_rx_buf[IDX_GYRO_XOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_XOUT_L]);
const int16_t gyroY = (int16_t)((bmi270_rx_buf[IDX_GYRO_YOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_YOUT_L]);
const int16_t gyroZ = (int16_t)((bmi270_rx_buf[IDX_GYRO_ZOUT_H] << 8) | bmi270_rx_buf[IDX_GYRO_ZOUT_L]);
// If the FIFO data is invalid then the returned values will be 0x8000 (-32768) (pg. 43 of datasheet).
// This shouldn't happen since we're only using the data if the FIFO length indicates
// that data is available, but this safeguard is needed to prevent bad things in
// case it does happen.
if ((gyroX != INT16_MIN) || (gyroY != INT16_MIN) || (gyroZ != INT16_MIN)) {
gyro->gyroADCRaw[X] = gyroX;
gyro->gyroADCRaw[Y] = gyroY;
gyro->gyroADCRaw[Z] = gyroZ;
dataRead = true;
}
fifoLength -= BMI270_FIFO_FRAME_SIZE;
}
// If there are additional samples in the FIFO then we don't use those for now and simply
// flush the FIFO. Under normal circumstances we only expect one sample in the FIFO since
// the gyro loop is running at the native sample rate of 6.4KHz.
// However the way the FIFO works in the sensor is that if a frame is partially read then
// it remains in the queue instead of bein removed. So if we ever got into a state where there
// was a partial frame or other unexpected data in the FIFO is may never get cleared and we
// would end up in a lock state of always re-reading the same partial or invalid sample.
if (fifoLength > 0) {
// Partial or additional frames left - flush the FIFO
bmi270RegisterWrite(&gyro->bus, BMI270_REG_CMD, BMI270_VAL_CMD_FIFOFLUSH, 0);
}
return dataRead;
}
#endif
static bool bmi270GyroRead(gyroDev_t *gyro)
{
#ifdef USE_GYRO_DLPF_EXPERIMENTAL
if (gyro->hardware_lpf == GYRO_HARDWARE_LPF_EXPERIMENTAL) {
// running in 6.4KHz FIFO mode
return bmi270GyroReadFifo(gyro);
} else
#endif
{
// running in 3.2KHz register mode
return bmi270GyroReadRegister(gyro);
}
}
static void bmi270SpiGyroInit(gyroDev_t *gyro)
{
bmi270Config(gyro);
#if defined(USE_GYRO_EXTI) && defined(USE_MPU_DATA_READY_SIGNAL)
bmi270IntExtiInit(gyro);
#endif
}
static void bmi270SpiAccInit(accDev_t *acc)
{
// sensor is configured during gyro init
acc->acc_1G = 512 * 4; // 16G sensor scale
}
bool bmi270SpiAccDetect(accDev_t *acc)
{
if (acc->mpuDetectionResult.sensor != BMI_270_SPI) {
return false;
}
acc->initFn = bmi270SpiAccInit;
acc->readFn = bmi270AccRead;
return true;
}
bool bmi270SpiGyroDetect(gyroDev_t *gyro)
{
if (gyro->mpuDetectionResult.sensor != BMI_270_SPI) {
return false;
}
gyro->initFn = bmi270SpiGyroInit;
gyro->readFn = bmi270GyroRead;
gyro->scale = 1.0f / 16.4f;
return true;
}
// Used to query the status register to determine what event caused the EXTI to fire.
// When in 3.2KHz mode the interrupt is mapped to the data ready state. However the data ready
// trigger will fire for both gyro and accelerometer. So it's necessary to check this register
// to determine which event caused the interrupt.
// When in 6.4KHz mode the interrupt is configured to be the FIFO watermark size of 6 bytes.
// Since in this mode we only put gyro data in the FIFO it's sufficient to check for the FIFO
// watermark reason as an idication of gyro data ready.
uint8_t bmi270InterruptStatus(gyroDev_t *gyro)
{
return bmi270RegisterRead(&gyro->bus, BMI270_REG_INT_STATUS_1);
}
#endif // USE_ACCGYRO_BMI270

View File

@ -0,0 +1,28 @@
/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software under the terms of the
* GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* Cleanflight and Betaflight are distributed in the hope that they
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "drivers/bus.h"
uint8_t bmi270Detect(const busDevice_t *bus);
bool bmi270SpiAccDetect(accDev_t *acc);
bool bmi270SpiGyroDetect(gyroDev_t *gyro);
uint8_t bmi270InterruptStatus(gyroDev_t *gyro);

View File

@ -58,6 +58,20 @@ uint16_t gyroSetSampleRate(gyroDev_t *gyro)
gyroSampleRateHz = 3200; gyroSampleRateHz = 3200;
accSampleRateHz = 800; accSampleRateHz = 800;
break; break;
case BMI_270_SPI:
#ifdef USE_GYRO_DLPF_EXPERIMENTAL
if (gyro->hardware_lpf == GYRO_HARDWARE_LPF_EXPERIMENTAL) {
// 6.4KHz sampling, but data is unfiltered (no hardware DLPF)
gyro->gyroRateKHz = GYRO_RATE_6400_Hz;
gyroSampleRateHz = 6400;
} else
#endif
{
gyro->gyroRateKHz = GYRO_RATE_3200_Hz;
gyroSampleRateHz = 3200;
}
accSampleRateHz = 800;
break;
case ICM_20649_SPI: case ICM_20649_SPI:
gyro->gyroRateKHz = GYRO_RATE_9_kHz; gyro->gyroRateKHz = GYRO_RATE_9_kHz;
gyroSampleRateHz = 9000; gyroSampleRateHz = 9000;

View File

@ -43,6 +43,7 @@
#include "drivers/accgyro/accgyro_mpu6050.h" #include "drivers/accgyro/accgyro_mpu6050.h"
#include "drivers/accgyro/accgyro_mpu6500.h" #include "drivers/accgyro/accgyro_mpu6500.h"
#include "drivers/accgyro/accgyro_spi_bmi160.h" #include "drivers/accgyro/accgyro_spi_bmi160.h"
#include "drivers/accgyro/accgyro_spi_bmi270.h"
#include "drivers/accgyro/accgyro_spi_icm20649.h" #include "drivers/accgyro/accgyro_spi_icm20649.h"
#include "drivers/accgyro/accgyro_spi_icm20689.h" #include "drivers/accgyro/accgyro_spi_icm20689.h"
#include "drivers/accgyro/accgyro_spi_icm42605.h" #include "drivers/accgyro/accgyro_spi_icm42605.h"
@ -292,6 +293,15 @@ retry:
FALLTHROUGH; FALLTHROUGH;
#endif #endif
#ifdef USE_ACCGYRO_BMI270
case ACC_BMI270:
if (bmi270SpiAccDetect(dev)) {
accHardware = ACC_BMI270;
break;
}
FALLTHROUGH;
#endif
#ifdef USE_FAKE_ACC #ifdef USE_FAKE_ACC
case ACC_FAKE: case ACC_FAKE:
if (fakeAccDetect(dev)) { if (fakeAccDetect(dev)) {

View File

@ -44,6 +44,7 @@ typedef enum {
ACC_ICM20689, ACC_ICM20689,
ACC_ICM42605, ACC_ICM42605,
ACC_BMI160, ACC_BMI160,
ACC_BMI270,
ACC_FAKE ACC_FAKE
} accelerationSensor_e; } accelerationSensor_e;

View File

@ -45,6 +45,7 @@
#include "drivers/accgyro/accgyro_mpu6050.h" #include "drivers/accgyro/accgyro_mpu6050.h"
#include "drivers/accgyro/accgyro_mpu6500.h" #include "drivers/accgyro/accgyro_mpu6500.h"
#include "drivers/accgyro/accgyro_spi_bmi160.h" #include "drivers/accgyro/accgyro_spi_bmi160.h"
#include "drivers/accgyro/accgyro_spi_bmi270.h"
#include "drivers/accgyro/accgyro_spi_icm20649.h" #include "drivers/accgyro/accgyro_spi_icm20649.h"
#include "drivers/accgyro/accgyro_spi_icm20689.h" #include "drivers/accgyro/accgyro_spi_icm20689.h"
#include "drivers/accgyro/accgyro_spi_icm20689.h" #include "drivers/accgyro/accgyro_spi_icm20689.h"
@ -352,6 +353,15 @@ STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev)
FALLTHROUGH; FALLTHROUGH;
#endif #endif
#ifdef USE_ACCGYRO_BMI270
case GYRO_BMI270:
if (bmi270SpiGyroDetect(dev)) {
gyroHardware = GYRO_BMI270;
break;
}
FALLTHROUGH;
#endif
#ifdef USE_FAKE_GYRO #ifdef USE_FAKE_GYRO
case GYRO_FAKE: case GYRO_FAKE:
if (fakeGyroDetect(dev)) { if (fakeGyroDetect(dev)) {
@ -376,7 +386,8 @@ STATIC_UNIT_TESTED gyroHardware_e gyroDetect(gyroDev_t *dev)
static void gyroPreInitSensor(const gyroDeviceConfig_t *config) static void gyroPreInitSensor(const gyroDeviceConfig_t *config)
{ {
#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \ #if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
|| defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
|| defined(USE_GYRO_SPI_ICM20689) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
mpuPreInit(config); mpuPreInit(config);
#else #else
UNUSED(config); UNUSED(config);
@ -386,7 +397,8 @@ static void gyroPreInitSensor(const gyroDeviceConfig_t *config)
static bool gyroDetectSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config) static bool gyroDetectSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *config)
{ {
#if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \ #if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) \
|| defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) || defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250) || defined(USE_GYRO_SPI_ICM20601) || defined(USE_GYRO_SPI_ICM20649) \
|| defined(USE_GYRO_SPI_ICM20689) || defined(USE_GYRO_L3GD20) || defined(USE_ACCGYRO_BMI160) || defined(USE_ACCGYRO_BMI270)
bool gyroFound = mpuDetect(&gyroSensor->gyroDev, config); bool gyroFound = mpuDetect(&gyroSensor->gyroDev, config);
@ -413,10 +425,10 @@ static void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *c
gyroSensor->gyroDev.gyroAlign = config->alignment; gyroSensor->gyroDev.gyroAlign = config->alignment;
buildRotationMatrixFromAlignment(&config->customAlignment, &gyroSensor->gyroDev.rotationMatrix); buildRotationMatrixFromAlignment(&config->customAlignment, &gyroSensor->gyroDev.rotationMatrix);
gyroSensor->gyroDev.mpuIntExtiTag = config->extiTag; gyroSensor->gyroDev.mpuIntExtiTag = config->extiTag;
gyroSensor->gyroDev.hardware_lpf = gyroConfig()->gyro_hardware_lpf;
// The targetLooptime gets set later based on the active sensor's gyroSampleRateHz and pid_process_denom // The targetLooptime gets set later based on the active sensor's gyroSampleRateHz and pid_process_denom
gyroSensor->gyroDev.gyroSampleRateHz = gyroSetSampleRate(&gyroSensor->gyroDev); gyroSensor->gyroDev.gyroSampleRateHz = gyroSetSampleRate(&gyroSensor->gyroDev);
gyroSensor->gyroDev.hardware_lpf = gyroConfig()->gyro_hardware_lpf;
gyroSensor->gyroDev.initFn(&gyroSensor->gyroDev); gyroSensor->gyroDev.initFn(&gyroSensor->gyroDev);
// As new gyros are supported, be sure to add them below based on whether they are subject to the overflow/inversion bug // As new gyros are supported, be sure to add them below based on whether they are subject to the overflow/inversion bug
@ -430,6 +442,7 @@ static void gyroInitSensor(gyroSensor_t *gyroSensor, const gyroDeviceConfig_t *c
case GYRO_MPU3050: case GYRO_MPU3050:
case GYRO_L3GD20: case GYRO_L3GD20:
case GYRO_BMI160: case GYRO_BMI160:
case GYRO_BMI270:
case GYRO_MPU6000: case GYRO_MPU6000:
case GYRO_MPU6500: case GYRO_MPU6500:
case GYRO_MPU9250: case GYRO_MPU9250:

View File

@ -44,6 +44,9 @@
#define USE_GYRO_SPI_MPU6500 #define USE_GYRO_SPI_MPU6500
#define USE_ACC_SPI_ICM20689 #define USE_ACC_SPI_ICM20689
#define USE_GYRO_SPI_ICM20689 #define USE_GYRO_SPI_ICM20689
#if (TARGET_FLASH_SIZE > 512)
#define USE_ACCGYRO_BMI270
#endif
// Other USE_ACCs and USE_GYROs should follow // Other USE_ACCs and USE_GYROs should follow
#define USE_MAG #define USE_MAG