diff --git a/bmi08a.c b/bmi08a.c index 7cb7007..98c41ab 100644 --- a/bmi08a.c +++ b/bmi08a.c @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi08a.c - * @date 2020-06-26 - * @version v1.5.3 + * @date 2020-12-11 + * @version v1.5.5 * */ @@ -67,191 +67,195 @@ struct bmi08a_selftest_delta_limit /**\name Feature configuration file */ const uint8_t bmi08x_config_file[] = { - 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x4b, 0x01, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, 0x2e, 0xc8, 0x2e, 0x00, - 0x2e, 0x80, 0x2e, 0xa7, 0x00, 0x80, 0x2e, 0x83, 0x00, 0x80, 0x2e, 0x15, 0x01, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0, - 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0x9c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xf6, + 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x48, 0xb4, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x6d, 0xb4, 0xc8, 0x2e, 0x00, + 0x2e, 0x80, 0x2e, 0xd4, 0xb3, 0x80, 0x2e, 0xb0, 0xb3, 0x80, 0x2e, 0x12, 0xb4, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0, + 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0xfe, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x79, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x50, 0x80, 0x7f, - 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, - 0x2e, 0x43, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, - 0x12, 0xb2, 0x40, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, - 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, - 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x29, 0xf0, 0x08, - 0xbc, 0x0f, 0xb8, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0x90, 0x1b, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, - 0x0e, 0xb8, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x2e, 0x04, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x01, 0xb2, 0x0d, 0x2f, 0x01, - 0x2e, 0x63, 0x00, 0x01, 0x90, 0x04, 0x2f, 0x98, 0x2e, 0xa6, 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x63, 0x00, 0x01, 0x2e, - 0x37, 0xf0, 0x21, 0x2e, 0x37, 0xf0, 0x02, 0x2d, 0x98, 0x2e, 0x7e, 0xb3, 0x80, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, - 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, - 0xc8, 0x2e, 0x40, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x80, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0x10, 0x24, 0x80, - 0x00, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x0a, 0x21, 0x2e, 0x06, 0xf0, 0x00, 0x3e, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x08, - 0x51, 0x30, 0x01, 0x0a, 0x21, 0x2e, 0x06, 0xf0, 0xb8, 0x2e, 0x00, 0x31, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0xaa, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x03, + 0xb1, 0x12, 0x24, 0x67, 0x00, 0x90, 0x42, 0x81, 0x42, 0xba, 0x82, 0xd1, 0x7f, 0xe2, 0x7f, 0x98, 0x2e, 0x3c, 0xb0, + 0xd1, 0x6f, 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x4c, 0x2f, 0xe1, 0x6f, 0x44, 0x86, 0x03, 0x2e, 0x67, 0x00, 0xc2, + 0x40, 0xf7, 0x86, 0x4a, 0x04, 0xc1, 0x42, 0x00, 0x2e, 0xc2, 0x40, 0x80, 0xac, 0x01, 0x2f, 0x23, 0x2e, 0x63, 0x00, + 0xd1, 0x40, 0xd2, 0x40, 0x0a, 0x0f, 0x01, 0x2f, 0x40, 0xac, 0x02, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x63, 0x00, 0xfe, + 0x82, 0xc2, 0x40, 0x43, 0x40, 0xd3, 0x04, 0x46, 0x84, 0xc3, 0x7f, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, + 0xc1, 0x6f, 0xc3, 0x40, 0xe0, 0x7f, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x72, + 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, 0xd1, 0x6f, 0xe0, 0x7f, 0x00, 0x2e, + 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, + 0x40, 0xc3, 0x40, 0xd1, 0x6f, 0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x00, 0x2e, + 0x40, 0x42, 0x98, 0x2e, 0xa5, 0xb0, 0x11, 0x30, 0x23, 0x2e, 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0xaa, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xed, 0x8f, 0xd9, 0x31, 0x00, 0x00, 0xc6, 0x01, 0x8c, 0x03, 0xc6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x60, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xfe, 0xbb, - 0xb7, 0x05, 0xa6, 0x7f, 0xd3, 0x7f, 0xc4, 0x7f, 0xb5, 0x7f, 0x14, 0x24, 0x89, 0xf0, 0x3f, 0x8b, 0x03, 0x41, 0x44, - 0x41, 0xb8, 0xbd, 0x9c, 0x0b, 0xa3, 0x6f, 0x14, 0x24, 0x19, 0x00, 0xb3, 0x11, 0x43, 0x8b, 0x16, 0x43, 0x00, 0x2e, - 0x67, 0x41, 0x46, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb3, 0x11, 0x16, 0x43, 0x43, 0x8d, 0x00, 0x2e, 0xa5, 0x41, 0x86, - 0x41, 0xd8, 0xbe, 0x6e, 0x0b, 0xeb, 0x10, 0x03, 0x43, 0x13, 0x30, 0x27, 0x2e, 0x18, 0x00, 0x03, 0x31, 0x27, 0x2e, - 0xb8, 0xf0, 0xf6, 0x6f, 0xe7, 0x6f, 0xc4, 0x6f, 0xb5, 0x6f, 0xd3, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x80, - 0x7f, 0x91, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, - 0x01, 0x2e, 0xb9, 0xf0, 0x60, 0x7f, 0x10, 0x30, 0x61, 0x6f, 0x08, 0x08, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0x47, - 0xb1, 0x10, 0x30, 0x21, 0x2e, 0xb9, 0xf0, 0x21, 0x2e, 0x5f, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, - 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0x98, 0x2e, 0xe6, 0xb0, 0x20, - 0x26, 0x98, 0x2e, 0xe5, 0x00, 0x98, 0x2e, 0x98, 0x01, 0x98, 0x2e, 0xfc, 0x00, 0x98, 0x2e, 0xe9, 0x00, 0x01, 0x2e, - 0x40, 0xf0, 0x21, 0x2e, 0x24, 0x00, 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xa0, 0x01, 0x21, 0x30, 0x10, - 0x24, 0x19, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x05, 0x2e, 0x18, 0x00, 0x80, 0xb2, 0x02, 0x30, 0x05, 0x2f, - 0x23, 0x2e, 0x5f, 0xf0, 0x25, 0x2e, 0x18, 0x00, 0x98, 0x2e, 0x00, 0xb0, 0x98, 0x2e, 0x8a, 0xb2, 0xec, 0x2d, 0x10, - 0x30, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, 0x1a, 0x24, 0x26, 0x00, 0x80, 0x2e, 0x70, 0x01, 0x10, 0x50, 0x01, 0x2e, - 0x55, 0xf0, 0xf0, 0x7f, 0x00, 0x2e, 0xf0, 0x6f, 0x21, 0x2e, 0x55, 0xf0, 0xf0, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xf4, - 0x7f, 0xe3, 0x7f, 0xd2, 0x7f, 0xc1, 0x7f, 0x12, 0x30, 0x03, 0x2e, 0x4e, 0x00, 0x91, 0x14, 0x92, 0x7f, 0x00, 0x31, - 0xc4, 0x6f, 0x95, 0x6f, 0xe3, 0x6f, 0xa5, 0x0f, 0x70, 0x84, 0x01, 0x04, 0x14, 0x2f, 0xd5, 0x6f, 0x00, 0xa9, 0x01, - 0x2f, 0xa5, 0x7f, 0x21, 0x2d, 0xdd, 0x04, 0xb3, 0x7f, 0x40, 0xb2, 0xb3, 0x6f, 0x1c, 0x18, 0x06, 0x2f, 0x50, 0xa0, - 0x01, 0x2f, 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x6e, 0x00, 0xa1, 0x7f, 0x11, 0x2d, 0xf7, - 0x6f, 0xfb, 0x05, 0xb7, 0x7f, 0x25, 0x05, 0xb5, 0x6f, 0x2c, 0x18, 0x40, 0xb2, 0x06, 0x2f, 0x50, 0xa0, 0x01, 0x2f, - 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x5e, 0x00, 0xa1, 0x7f, 0x00, 0x2e, 0xa0, 0x6f, 0x90, - 0x5f, 0xb8, 0x2e, 0x10, 0x24, 0x60, 0x00, 0x11, 0x24, 0x52, 0xf0, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, - 0x00, 0x2e, 0x12, 0x40, 0x42, 0x42, 0x42, 0x82, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x7e, 0x80, 0xa8, - 0xb4, 0x01, 0x42, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0xb0, 0x50, - 0xf0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x02, 0xbc, 0x0f, 0xb8, 0xe0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, - 0x01, 0x01, 0xbc, 0x0f, 0xb8, 0xd0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x0f, 0xb8, 0xc0, 0x7f, 0x02, 0x30, - 0xe6, 0x6f, 0xd4, 0x6f, 0xc3, 0x6f, 0x80, 0x91, 0x04, 0x2f, 0x00, 0x91, 0x02, 0x2f, 0xc0, 0xb2, 0x90, 0x2e, 0xe2, - 0xb0, 0xf0, 0x6f, 0x0b, 0x2e, 0x82, 0x00, 0x01, 0x82, 0x40, 0x91, 0x14, 0x2f, 0x41, 0x87, 0x27, 0x2e, 0x82, 0x00, - 0x00, 0x40, 0x21, 0x2e, 0x1f, 0x00, 0x53, 0x40, 0x10, 0x24, 0x20, 0x00, 0x13, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x01, - 0x42, 0x25, 0x2e, 0x1c, 0x00, 0x25, 0x2e, 0x1d, 0x00, 0x25, 0x2e, 0x22, 0x00, 0x50, 0x5f, 0xb8, 0x2e, 0x0b, 0x2e, - 0x00, 0x01, 0xd5, 0xbe, 0xd5, 0xba, 0xb5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x01, 0x01, 0xd3, 0xbe, 0xd3, 0xba, 0xa5, - 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x00, 0x01, 0xd4, 0xbe, 0xdf, 0xba, 0x95, 0x7f, 0x00, 0x2e, 0x95, 0x6f, 0x0f, 0x2e, - 0x1e, 0x00, 0x3d, 0x1a, 0x05, 0x2f, 0x25, 0x2e, 0x1c, 0x00, 0x25, 0x2e, 0x1d, 0x00, 0x2b, 0x2e, 0x1e, 0x00, 0x82, - 0x7f, 0x72, 0x7f, 0x80, 0x91, 0x62, 0x7f, 0x01, 0x2f, 0x06, 0x30, 0x07, 0x2d, 0x06, 0x40, 0x0f, 0x2e, 0x1f, 0x00, - 0xb7, 0x05, 0x80, 0xa9, 0xd6, 0x05, 0xb7, 0x23, 0x86, 0x7f, 0x00, 0x91, 0x01, 0x2f, 0x04, 0x30, 0x07, 0x2d, 0x44, - 0x40, 0x0d, 0x2e, 0x20, 0x00, 0x26, 0x05, 0x00, 0xa9, 0x94, 0x05, 0x26, 0x23, 0x74, 0x7f, 0xc0, 0x90, 0x01, 0x2f, - 0x00, 0x2e, 0x09, 0x2d, 0x02, 0x86, 0x00, 0x2e, 0xc3, 0x40, 0x09, 0x2e, 0x21, 0x00, 0xdc, 0x04, 0xc0, 0xa8, 0x93, - 0x04, 0x9a, 0x22, 0x62, 0x7f, 0x12, 0x30, 0x84, 0x6f, 0xb3, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x08, 0x2f, 0x74, 0x6f, - 0x63, 0x0f, 0x14, 0x30, 0x04, 0x2f, 0x64, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x00, 0x2f, 0x04, 0x30, 0x54, 0x7f, 0x40, - 0x91, 0x0b, 0x2e, 0x1c, 0x00, 0x54, 0x6f, 0xa3, 0x6f, 0x6a, 0x29, 0x1d, 0x2f, 0x00, 0x91, 0x06, 0x30, 0x14, 0x24, - 0x20, 0x00, 0x0d, 0x2f, 0x2d, 0x2e, 0x1c, 0x00, 0x05, 0x2e, 0x1d, 0x00, 0x81, 0x84, 0x25, 0x2e, 0x1d, 0x00, 0x05, - 0x2e, 0x1d, 0x00, 0x53, 0x0e, 0x2b, 0x2f, 0x2d, 0x2e, 0x22, 0x00, 0x29, 0x2d, 0x2b, 0x2e, 0x1c, 0x00, 0x2d, 0x2e, - 0x1d, 0x00, 0x0b, 0x2e, 0x1c, 0x00, 0x6b, 0x0e, 0x20, 0x2f, 0x25, 0x2e, 0x22, 0x00, 0x1e, 0x2d, 0x00, 0xb3, 0x05, - 0x2f, 0x02, 0x30, 0x25, 0x2e, 0x1c, 0x00, 0x25, 0x2e, 0x22, 0x00, 0x08, 0x2d, 0x2b, 0x2e, 0x1c, 0x00, 0x09, 0x2e, - 0x1c, 0x00, 0x63, 0x0e, 0x01, 0x2f, 0x25, 0x2e, 0x22, 0x00, 0x02, 0x40, 0x25, 0x2e, 0x1f, 0x00, 0x31, 0x25, 0x00, - 0x2e, 0xd5, 0x40, 0x12, 0x24, 0x20, 0x00, 0x42, 0x25, 0x95, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x83, 0x42, 0x00, 0x2e, - 0x05, 0x2e, 0x22, 0x00, 0x80, 0xb2, 0x0d, 0x2f, 0x00, 0x40, 0x21, 0x2e, 0x1f, 0x00, 0x50, 0x40, 0x10, 0x43, 0x00, - 0x2e, 0x40, 0x40, 0x00, 0x43, 0x20, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x02, 0x2d, 0x25, 0x2e, 0x82, 0x00, 0x50, 0x5f, - 0xb8, 0x2e, 0x20, 0x50, 0x00, 0x30, 0xe0, 0x7f, 0xfb, 0x7f, 0x11, 0x24, 0xb1, 0xf0, 0x42, 0x40, 0x43, 0x30, 0x93, - 0x0a, 0x42, 0x42, 0x58, 0x82, 0x12, 0x24, 0xaf, 0x00, 0x62, 0x42, 0x12, 0x24, 0xff, 0x00, 0x42, 0x42, 0x69, 0x82, - 0x72, 0x3c, 0x43, 0x40, 0x9a, 0x08, 0x83, 0x32, 0x93, 0x0a, 0x42, 0x42, 0x42, 0x82, 0x02, 0x3f, 0x43, 0x40, 0x9a, - 0x08, 0x52, 0x42, 0x0b, 0x31, 0x4b, 0x42, 0x7e, 0x82, 0x52, 0x31, 0x42, 0x42, 0x11, 0x24, 0xfe, 0x00, 0x05, 0x2e, - 0x40, 0xf0, 0x51, 0x08, 0x5e, 0x90, 0x27, 0x2f, 0x11, 0x24, 0x00, 0x02, 0x12, 0x24, 0x05, 0x80, 0x13, 0x24, 0xff, - 0xb7, 0x1b, 0x24, 0x00, 0xb0, 0x04, 0x30, 0x05, 0x30, 0x56, 0x32, 0x6e, 0x1a, 0x00, 0x2f, 0xa5, 0x34, 0x69, 0x1a, - 0x01, 0x2f, 0x5b, 0x25, 0x00, 0x2e, 0x56, 0x41, 0x26, 0x0d, 0x06, 0x30, 0xcf, 0xbb, 0x41, 0xbe, 0xc0, 0x91, 0x01, - 0x2f, 0x00, 0x2e, 0x01, 0x2d, 0x22, 0x0d, 0x81, 0x8d, 0x90, 0xa1, 0xf5, 0x2f, 0xeb, 0x0e, 0xe8, 0x2f, 0x01, 0x2e, - 0x25, 0x00, 0x20, 0x1a, 0x05, 0x2f, 0x20, 0x30, 0xe0, 0x7f, 0x03, 0x2d, 0x30, 0x30, 0xe0, 0x7f, 0x00, 0x2e, 0xe0, - 0x6f, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0xa0, 0x01, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, - 0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x40, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x5c, 0xb2, 0x12, 0x24, 0x4f, 0x00, 0x90, - 0x42, 0x81, 0x42, 0xba, 0x82, 0xd1, 0x7f, 0xe2, 0x7f, 0x98, 0x2e, 0xa9, 0xb1, 0xd1, 0x6f, 0x00, 0x2e, 0x41, 0x40, - 0x40, 0xb2, 0x4c, 0x2f, 0xe1, 0x6f, 0x44, 0x86, 0x03, 0x2e, 0x4f, 0x00, 0xc2, 0x40, 0xf7, 0x86, 0x4a, 0x04, 0xc1, - 0x42, 0x00, 0x2e, 0xc2, 0x40, 0x80, 0xac, 0x01, 0x2f, 0x23, 0x2e, 0x4b, 0x00, 0xd1, 0x40, 0xd2, 0x40, 0x0a, 0x0f, - 0x01, 0x2f, 0x40, 0xac, 0x02, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x4b, 0x00, 0xfe, 0x82, 0xc2, 0x40, 0x43, 0x40, 0xd3, - 0x04, 0x46, 0x84, 0xc3, 0x7f, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc1, 0x6f, 0xc3, 0x40, 0xe0, 0x7f, - 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0xaa, 0x01, 0xe1, 0x6f, 0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, - 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, 0xd1, 0x6f, 0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0xaa, 0x01, - 0xe1, 0x6f, 0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, 0xd1, 0x6f, 0xe0, - 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0xaa, 0x01, 0xe1, 0x6f, 0x00, 0x2e, 0x40, 0x42, 0x98, 0x2e, 0xe6, 0x01, - 0x11, 0x30, 0x23, 0x2e, 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0x02, 0x01, 0x8e, 0xbc, 0x01, - 0x2e, 0x4a, 0x00, 0x9e, 0xb8, 0x01, 0x1a, 0x5f, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8, 0x21, 0x2e, - 0x4a, 0x00, 0x03, 0x2e, 0x4a, 0x00, 0x43, 0xb2, 0x10, 0x24, 0x4d, 0x00, 0x3c, 0x2f, 0x42, 0xb2, 0x22, 0x2f, 0x41, - 0xb2, 0x06, 0x2f, 0x01, 0x30, 0x11, 0x42, 0x01, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, - 0x24, 0x00, 0x5f, 0x90, 0x62, 0x30, 0x11, 0x24, 0x81, 0x00, 0x07, 0x2f, 0x30, 0x25, 0x34, 0x37, 0xd4, 0x42, 0xc2, - 0x42, 0xfe, 0x86, 0x00, 0x2e, 0xc1, 0x42, 0x00, 0x2e, 0x07, 0x2e, 0x24, 0x00, 0xde, 0x90, 0x35, 0x2f, 0x63, 0x36, - 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x24, 0x00, 0x5f, 0xb2, 0x52, - 0x30, 0x21, 0x32, 0x0a, 0x2f, 0x07, 0x2e, 0x24, 0x00, 0xde, 0x90, 0x24, 0x2f, 0x23, 0x31, 0x13, 0x42, 0x02, 0x42, - 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x32, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, - 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x24, 0x00, 0x5f, 0xb2, 0x42, 0x30, 0x11, 0x31, 0x0a, 0x2f, 0x07, 0x2e, 0x24, 0x00, - 0xde, 0x90, 0x0c, 0x2f, 0xa3, 0x30, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x63, - 0x31, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x12, 0x24, 0x59, 0x00, 0x90, 0x40, - 0x84, 0x82, 0x20, 0x50, 0x50, 0x42, 0x77, 0x80, 0x82, 0x40, 0x42, 0x42, 0xfb, 0x7f, 0x05, 0x82, 0x00, 0x40, 0x40, - 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x77, 0x84, - 0x00, 0x2e, 0x90, 0x40, 0x84, 0x82, 0x82, 0x40, 0x50, 0x42, 0x77, 0x80, 0x42, 0x42, 0x05, 0x82, 0x00, 0x40, 0x40, - 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x82, - 0xe1, 0x7f, 0x98, 0x2e, 0x5c, 0xb2, 0xe2, 0x6f, 0x00, 0x2e, 0x90, 0x42, 0x81, 0x42, 0xbc, 0x82, 0x10, 0x24, 0x33, - 0xf0, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, - 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x22, 0x40, 0x00, 0x40, 0x28, 0xbd, 0x10, 0x0a, 0x40, - 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x11, 0x24, 0x28, 0xf0, 0x50, 0x50, 0x60, 0x40, 0xf0, 0x7f, - 0x51, 0x25, 0x60, 0x40, 0xe0, 0x7f, 0x00, 0x2e, 0x41, 0x40, 0xd1, 0x7f, 0x00, 0x2e, 0xe2, 0x6f, 0xd0, 0x6f, 0x00, - 0xb2, 0xf3, 0x6f, 0xa8, 0xb8, 0x28, 0xbe, 0x59, 0x0a, 0x20, 0x0a, 0x01, 0x2f, 0xb0, 0x5f, 0xb8, 0x2e, 0x45, 0x41, - 0xc5, 0x7f, 0x00, 0x2e, 0xc5, 0x6f, 0x40, 0x91, 0x09, 0x2f, 0x05, 0x2e, 0x28, 0xf0, 0xb2, 0x7f, 0x00, 0x2e, 0xb2, - 0x6f, 0x1a, 0x1a, 0x07, 0x2f, 0xf0, 0x3f, 0x13, 0x25, 0x05, 0x2d, 0x15, 0x1a, 0x02, 0x2f, 0x10, 0x24, 0xff, 0x00, - 0x20, 0x0a, 0xb0, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0x03, 0x01, 0x8f, 0xbc, 0x01, 0x2e, 0x23, 0x00, 0x9f, 0xb8, 0x01, - 0x1a, 0x12, 0x2f, 0x01, 0x2e, 0x03, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x21, 0x2e, 0x23, 0x00, 0x11, 0x30, 0x05, 0x2e, - 0x23, 0x00, 0x51, 0x08, 0xd2, 0x3f, 0x01, 0x2e, 0x07, 0xf0, 0x02, 0x08, 0x91, 0xbc, 0x01, 0x0a, 0x21, 0x2e, 0x07, - 0xf0, 0xb8, 0x2e, 0xb8, 0x2e, 0x10, 0x50, 0x12, 0x24, 0x6e, 0x00, 0x00, 0x30, 0x1b, 0x2d, 0xf1, 0x6f, 0xd1, 0x00, - 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x8c, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, - 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x8c, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, - 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x41, 0x82, 0xf1, 0x7f, 0xb4, 0x84, 0xf1, 0x6f, 0x43, 0xa2, 0xe1, 0x2f, 0xf0, - 0x5f, 0xb8, 0x2e, 0xc0, 0x50, 0x92, 0x7f, 0xfb, 0x7f, 0x81, 0x7f, 0x00, 0x30, 0x60, 0x7f, 0x70, 0x7f, 0x50, 0x7f, - 0x00, 0x2e, 0x03, 0x2e, 0x04, 0x01, 0x9d, 0xbc, 0x9e, 0xb8, 0x41, 0x7f, 0x00, 0x2e, 0x42, 0x6f, 0x52, 0x7f, 0xe2, - 0x7f, 0x00, 0x2e, 0x83, 0x6f, 0xc4, 0x82, 0xd3, 0x7f, 0x0c, 0x2d, 0x55, 0x6f, 0x7f, 0x89, 0xdc, 0x01, 0x9d, 0x01, - 0xcb, 0x41, 0x8b, 0x43, 0xcc, 0x01, 0x4d, 0x01, 0xc7, 0x41, 0x47, 0x43, 0x54, 0x7f, 0x00, 0x2e, 0x54, 0x6f, 0x00, - 0xab, 0xf0, 0x2f, 0x9b, 0x6f, 0x8a, 0x00, 0x4b, 0x42, 0xc2, 0x7f, 0xb1, 0x7f, 0x50, 0x7f, 0x7c, 0x80, 0xa0, 0x7f, - 0x13, 0x24, 0x09, 0x01, 0x3f, 0x2d, 0x50, 0x6f, 0x18, 0x01, 0xc8, 0x84, 0xc8, 0x00, 0x50, 0x00, 0x05, 0x41, 0xc7, - 0x40, 0x44, 0x40, 0x61, 0x6f, 0x73, 0x6f, 0x2f, 0x18, 0x00, 0xb3, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89, - 0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, 0xfc, 0x11, 0xae, 0x0b, 0x4e, - 0x00, 0xdf, 0x02, 0x61, 0x7f, 0x73, 0x7f, 0xb4, 0x84, 0x01, 0x82, 0xd1, 0x00, 0x88, 0x80, 0xa2, 0x6f, 0x11, 0x01, - 0x81, 0x00, 0xc3, 0x40, 0x05, 0x41, 0x84, 0x40, 0x1d, 0x18, 0x72, 0x6f, 0x00, 0xb3, 0x63, 0x6f, 0x0b, 0x2f, 0x10, - 0xa1, 0x03, 0x2f, 0x30, 0x89, 0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, - 0xfc, 0x11, 0xae, 0x0b, 0xde, 0x04, 0x97, 0x06, 0x63, 0x7f, 0x72, 0x7f, 0x51, 0x7f, 0x3c, 0x86, 0xb1, 0x6f, 0xe2, - 0x6f, 0x50, 0x6f, 0x42, 0x0e, 0xbc, 0x2f, 0xe0, 0x6f, 0xc8, 0x82, 0x98, 0x00, 0x48, 0x00, 0xc0, 0x6f, 0x83, 0x40, - 0x04, 0x40, 0x42, 0x40, 0x61, 0x6f, 0x70, 0x6f, 0x80, 0xb2, 0x1c, 0x18, 0x0b, 0x2f, 0x90, 0xa0, 0x03, 0x2f, 0xb0, - 0x84, 0xba, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x03, 0x31, 0xda, 0x04, 0xfb, 0x14, 0x32, 0x13, 0xfa, 0x11, 0xa3, 0x0b, - 0x4e, 0x00, 0x07, 0x02, 0x61, 0x7f, 0x70, 0x7f, 0x00, 0x2e, 0x72, 0x6f, 0x80, 0xa8, 0x60, 0x6f, 0xd1, 0x6f, 0x13, - 0x2f, 0x80, 0x90, 0x03, 0x2f, 0x13, 0x24, 0xff, 0x7f, 0x43, 0x0f, 0x0d, 0x2f, 0xbf, 0xa0, 0x07, 0x2f, 0xbf, 0x90, - 0x03, 0x2f, 0x12, 0x24, 0x00, 0x80, 0x42, 0x0e, 0x01, 0x2f, 0x40, 0x42, 0x07, 0x2d, 0x10, 0x24, 0x00, 0x80, 0x40, - 0x42, 0x03, 0x2d, 0x10, 0x24, 0xff, 0x7f, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0x40, 0x5f, 0x40, 0x40, 0xb8, 0x2e, - 0x11, 0x24, 0x63, 0x00, 0x30, 0x50, 0x10, 0x30, 0x50, 0x42, 0xfb, 0x7f, 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, - 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, - 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x3c, 0x80, 0x42, 0x42, 0x7e, - 0x84, 0xe0, 0x7f, 0x86, 0x82, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0xcb, 0xb2, 0xd1, 0x6f, 0x7d, 0x82, - 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x0d, 0x82, 0x02, 0x40, 0xd1, 0x7f, 0x98, 0x2e, 0xcb, 0xb2, 0xd1, 0x6f, 0x76, - 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x14, 0x82, 0x02, 0x40, 0xd1, 0x7f, 0x98, 0x2e, 0xcb, 0xb2, 0xd1, 0x6f, - 0x6f, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0xe1, 0x6f, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, - 0x2e, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, - 0x00, 0x2e, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x50, 0xf0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x02, 0xbc, + 0x0f, 0xb8, 0xe0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x01, 0xbc, 0x0f, 0xb8, 0xd0, 0x7f, 0x00, 0x2e, 0x01, + 0x2e, 0x01, 0x01, 0x0f, 0xb8, 0xc0, 0x7f, 0x02, 0x30, 0xe6, 0x6f, 0xd4, 0x6f, 0xc3, 0x6f, 0x80, 0x91, 0x04, 0x2f, + 0x00, 0x91, 0x02, 0x2f, 0xc0, 0xb2, 0x90, 0x2e, 0xf6, 0x01, 0xf0, 0x6f, 0x0b, 0x2e, 0x24, 0x00, 0x01, 0x82, 0x40, + 0x91, 0x14, 0x2f, 0x41, 0x87, 0x27, 0x2e, 0x24, 0x00, 0x00, 0x40, 0x21, 0x2e, 0x1b, 0x00, 0x53, 0x40, 0x10, 0x24, + 0x1c, 0x00, 0x13, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x01, 0x42, 0x25, 0x2e, 0x18, 0x00, 0x25, 0x2e, 0x19, 0x00, 0x25, + 0x2e, 0x1e, 0x00, 0x50, 0x5f, 0xb8, 0x2e, 0x0b, 0x2e, 0x00, 0x01, 0xd5, 0xbe, 0xd5, 0xba, 0xb5, 0x7f, 0x00, 0x2e, + 0x0b, 0x2e, 0x01, 0x01, 0xd3, 0xbe, 0xd3, 0xba, 0xa5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x00, 0x01, 0xd4, 0xbe, 0xdf, + 0xba, 0x95, 0x7f, 0x00, 0x2e, 0x95, 0x6f, 0x0f, 0x2e, 0x1a, 0x00, 0x3d, 0x1a, 0x05, 0x2f, 0x25, 0x2e, 0x18, 0x00, + 0x25, 0x2e, 0x19, 0x00, 0x2b, 0x2e, 0x1a, 0x00, 0x80, 0x91, 0x01, 0x2f, 0x06, 0x30, 0x07, 0x2d, 0x06, 0x40, 0x0f, + 0x2e, 0x1b, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xd6, 0x05, 0xb7, 0x23, 0x86, 0x7f, 0x00, 0x91, 0x01, 0x2f, 0x04, 0x30, + 0x07, 0x2d, 0x44, 0x40, 0x0d, 0x2e, 0x1c, 0x00, 0x26, 0x05, 0x00, 0xa9, 0x94, 0x05, 0x26, 0x23, 0x74, 0x7f, 0xc0, + 0x90, 0x01, 0x2f, 0x00, 0x2e, 0x09, 0x2d, 0x02, 0x86, 0x00, 0x2e, 0xc3, 0x40, 0x09, 0x2e, 0x1d, 0x00, 0xdc, 0x04, + 0xc0, 0xa8, 0x93, 0x04, 0x9a, 0x22, 0x62, 0x7f, 0x12, 0x30, 0x84, 0x6f, 0xb3, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x08, + 0x2f, 0x74, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x04, 0x2f, 0x64, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x00, 0x2f, 0x04, 0x30, + 0x54, 0x7f, 0x40, 0x91, 0x0b, 0x2e, 0x18, 0x00, 0x54, 0x6f, 0xa3, 0x6f, 0x6a, 0x29, 0x1d, 0x2f, 0x00, 0x91, 0x06, + 0x30, 0x14, 0x24, 0x1c, 0x00, 0x0d, 0x2f, 0x2d, 0x2e, 0x18, 0x00, 0x05, 0x2e, 0x19, 0x00, 0x81, 0x84, 0x25, 0x2e, + 0x19, 0x00, 0x05, 0x2e, 0x19, 0x00, 0x53, 0x0e, 0x2b, 0x2f, 0x2d, 0x2e, 0x1e, 0x00, 0x29, 0x2d, 0x2b, 0x2e, 0x18, + 0x00, 0x2d, 0x2e, 0x19, 0x00, 0x0b, 0x2e, 0x18, 0x00, 0x6b, 0x0e, 0x20, 0x2f, 0x25, 0x2e, 0x1e, 0x00, 0x1e, 0x2d, + 0x00, 0xb3, 0x05, 0x2f, 0x02, 0x30, 0x25, 0x2e, 0x18, 0x00, 0x25, 0x2e, 0x1e, 0x00, 0x08, 0x2d, 0x2b, 0x2e, 0x18, + 0x00, 0x09, 0x2e, 0x18, 0x00, 0x63, 0x0e, 0x01, 0x2f, 0x25, 0x2e, 0x1e, 0x00, 0x02, 0x40, 0x25, 0x2e, 0x1b, 0x00, + 0x31, 0x25, 0x00, 0x2e, 0xd5, 0x40, 0x12, 0x24, 0x1c, 0x00, 0x42, 0x25, 0x95, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x83, + 0x42, 0x00, 0x2e, 0x05, 0x2e, 0x1e, 0x00, 0x80, 0xb2, 0x0d, 0x2f, 0x00, 0x40, 0x21, 0x2e, 0x1b, 0x00, 0x50, 0x40, + 0x10, 0x43, 0x00, 0x2e, 0x40, 0x40, 0x00, 0x43, 0x20, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x02, 0x2d, 0x25, 0x2e, 0x24, + 0x00, 0x50, 0x5f, 0xb8, 0x2e, 0x40, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x80, 0x2e, 0x18, 0x00, 0x70, 0x50, + 0xf4, 0x7f, 0xe3, 0x7f, 0xd2, 0x7f, 0xc1, 0x7f, 0x12, 0x30, 0x03, 0x2e, 0x66, 0x00, 0x91, 0x14, 0x92, 0x7f, 0x00, + 0x31, 0xc4, 0x6f, 0x95, 0x6f, 0xe3, 0x6f, 0xa5, 0x0f, 0x70, 0x84, 0x01, 0x04, 0x14, 0x2f, 0xd5, 0x6f, 0x00, 0xa9, + 0x01, 0x2f, 0xa5, 0x7f, 0x21, 0x2d, 0xdd, 0x04, 0xb3, 0x7f, 0x40, 0xb2, 0xb3, 0x6f, 0x1c, 0x18, 0x06, 0x2f, 0x50, + 0xa0, 0x01, 0x2f, 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x6e, 0x00, 0xa1, 0x7f, 0x11, 0x2d, + 0xf7, 0x6f, 0xfb, 0x05, 0xb7, 0x7f, 0x25, 0x05, 0xb5, 0x6f, 0x2c, 0x18, 0x40, 0xb2, 0x06, 0x2f, 0x50, 0xa0, 0x01, + 0x2f, 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x5e, 0x00, 0xa1, 0x7f, 0x00, 0x2e, 0xa0, 0x6f, + 0x90, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0x02, 0x01, 0x8e, 0xbc, 0x01, 0x2e, 0x62, 0x00, 0x9e, 0xb8, 0x01, 0x1a, 0x5f, + 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8, 0x21, 0x2e, 0x62, 0x00, 0x03, 0x2e, 0x62, 0x00, 0x43, 0xb2, + 0x10, 0x24, 0x65, 0x00, 0x3c, 0x2f, 0x42, 0xb2, 0x22, 0x2f, 0x41, 0xb2, 0x06, 0x2f, 0x01, 0x30, 0x11, 0x42, 0x01, + 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0x90, 0x62, 0x30, 0x11, 0x24, + 0x81, 0x00, 0x07, 0x2f, 0x30, 0x25, 0x34, 0x37, 0xd4, 0x42, 0xc2, 0x42, 0xfe, 0x86, 0x00, 0x2e, 0xc1, 0x42, 0x00, + 0x2e, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x35, 0x2f, 0x63, 0x36, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, + 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0xb2, 0x52, 0x30, 0x21, 0x32, 0x0a, 0x2f, 0x07, 0x2e, 0x9d, + 0x00, 0xde, 0x90, 0x24, 0x2f, 0x23, 0x31, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, + 0x03, 0x32, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, + 0xb2, 0x42, 0x30, 0x11, 0x31, 0x0a, 0x2f, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x0c, 0x2f, 0xa3, 0x30, 0x13, 0x42, + 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x63, 0x31, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, + 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x10, 0x24, 0x78, 0x00, 0x11, 0x24, 0x52, 0xf0, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, + 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x42, 0x42, 0x42, 0x82, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x7e, + 0x80, 0xa8, 0xb4, 0x01, 0x42, 0xb8, 0x2e, 0x12, 0x24, 0x71, 0x00, 0x90, 0x40, 0x84, 0x82, 0x20, 0x50, 0x50, 0x42, + 0x77, 0x80, 0x82, 0x40, 0x42, 0x42, 0xfb, 0x7f, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, + 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x77, 0x84, 0x00, 0x2e, 0x90, 0x40, 0x84, 0x82, + 0x82, 0x40, 0x50, 0x42, 0x77, 0x80, 0x42, 0x42, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, + 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x82, 0xe1, 0x7f, 0x98, 0x2e, 0x03, 0xb1, + 0xe2, 0x6f, 0x00, 0x2e, 0x90, 0x42, 0x81, 0x42, 0xbc, 0x82, 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, 0x40, 0xb8, + 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, + 0x52, 0x42, 0x00, 0x2e, 0x22, 0x40, 0x00, 0x40, 0x28, 0xbd, 0x10, 0x0a, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xe0, + 0x5f, 0xb8, 0x2e, 0x11, 0x24, 0x28, 0xf0, 0x50, 0x50, 0x60, 0x40, 0xf0, 0x7f, 0x51, 0x25, 0x60, 0x40, 0xe0, 0x7f, + 0x00, 0x2e, 0x41, 0x40, 0xd1, 0x7f, 0x00, 0x2e, 0xe2, 0x6f, 0xd0, 0x6f, 0x00, 0xb2, 0xf3, 0x6f, 0xa8, 0xb8, 0x28, + 0xbe, 0x59, 0x0a, 0x20, 0x0a, 0x01, 0x2f, 0xb0, 0x5f, 0xb8, 0x2e, 0x45, 0x41, 0xc5, 0x7f, 0x00, 0x2e, 0xc5, 0x6f, + 0x40, 0x91, 0x09, 0x2f, 0x05, 0x2e, 0x28, 0xf0, 0xb2, 0x7f, 0x00, 0x2e, 0xb2, 0x6f, 0x1a, 0x1a, 0x07, 0x2f, 0xf0, + 0x3f, 0x13, 0x25, 0x05, 0x2d, 0x15, 0x1a, 0x02, 0x2f, 0x10, 0x24, 0xff, 0x00, 0x20, 0x0a, 0xb0, 0x5f, 0xb8, 0x2e, + 0x01, 0x2e, 0x03, 0x01, 0x8f, 0xbc, 0x01, 0x2e, 0x1f, 0x00, 0x9f, 0xb8, 0x01, 0x1a, 0x12, 0x2f, 0x01, 0x2e, 0x03, + 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x21, 0x2e, 0x1f, 0x00, 0x11, 0x30, 0x05, 0x2e, 0x1f, 0x00, 0x51, 0x08, 0xd2, 0x3f, + 0x01, 0x2e, 0x07, 0xf0, 0x02, 0x08, 0x91, 0xbc, 0x01, 0x0a, 0x21, 0x2e, 0x07, 0xf0, 0xb8, 0x2e, 0xb8, 0x2e, 0x50, + 0x50, 0xf2, 0x7f, 0xe1, 0x7f, 0x01, 0x30, 0xd1, 0x7f, 0xc1, 0x7f, 0x10, 0x24, 0x91, 0x04, 0xf2, 0x6f, 0xe3, 0x6f, + 0x1c, 0x2d, 0xc4, 0x6f, 0x9c, 0x01, 0xd5, 0x6f, 0x86, 0x41, 0x6e, 0x0d, 0xd5, 0x7f, 0xb1, 0x7f, 0x0e, 0x2d, 0xd6, + 0x6f, 0xef, 0xba, 0x61, 0xbf, 0x40, 0x91, 0x01, 0x2f, 0xd6, 0x7f, 0x03, 0x2d, 0x70, 0x0d, 0xd5, 0x7f, 0x00, 0x2e, + 0xb5, 0x6f, 0x41, 0x8b, 0xb5, 0x7f, 0x00, 0x2e, 0xb5, 0x6f, 0x50, 0xa3, 0xee, 0x2f, 0x01, 0x89, 0xc4, 0x7f, 0x00, + 0x2e, 0xc4, 0x6f, 0x62, 0x0e, 0xe0, 0x2f, 0xd0, 0x6f, 0xb0, 0x5f, 0xb8, 0x2e, 0x90, 0x50, 0xd3, 0x7f, 0xfb, 0x7f, + 0xc2, 0x7f, 0xb1, 0x7f, 0x11, 0x30, 0xa1, 0x7f, 0x1a, 0x25, 0xc2, 0x6f, 0x72, 0x7f, 0x77, 0x82, 0xb2, 0x6f, 0x82, + 0x7f, 0xe2, 0x7f, 0x22, 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0x90, 0x7f, 0x00, 0x2e, 0xe1, 0x6f, 0xd0, 0x6f, 0x41, 0x16, + 0x92, 0x6f, 0x01, 0x08, 0x51, 0x08, 0x48, 0x1a, 0x01, 0x2f, 0x01, 0x30, 0xa1, 0x7f, 0x00, 0x2e, 0xfb, 0x6f, 0xa0, + 0x6f, 0x70, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xe3, 0x7f, 0xfb, 0x7f, 0xc1, 0x7f, 0xd2, 0x7f, 0x1a, 0x25, 0xc0, 0x6f, + 0xd2, 0x6f, 0x90, 0x7f, 0xa2, 0x7f, 0x79, 0x82, 0xe2, 0x6f, 0xb2, 0x7f, 0x32, 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0xfb, + 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0xb0, 0x50, 0xa4, 0x7f, 0xfb, 0x7f, 0x93, 0x7f, 0x82, 0x7f, 0x71, 0x7f, 0x00, 0x30, + 0xa1, 0x6f, 0xe1, 0x7f, 0x40, 0x42, 0x00, 0x2e, 0x92, 0x6f, 0x83, 0x6f, 0x71, 0x6f, 0xd3, 0x7f, 0xc2, 0x7f, 0xb1, + 0x7f, 0x98, 0x2e, 0x7a, 0xb1, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0xb2, 0x1e, 0x2f, 0xb1, 0x6f, 0xf2, 0x30, + 0x8a, 0x08, 0x13, 0x24, 0xf0, 0x00, 0x4b, 0x08, 0x24, 0xbd, 0x94, 0xb8, 0x51, 0x0a, 0x51, 0x7f, 0x00, 0x2e, 0x51, + 0x6f, 0x81, 0x16, 0xd3, 0x6f, 0x9a, 0x08, 0xc4, 0x6f, 0xe1, 0x08, 0xe1, 0x6f, 0x93, 0x0a, 0x42, 0x42, 0x12, 0x24, + 0x00, 0xff, 0x43, 0x40, 0x9a, 0x08, 0x14, 0x24, 0xff, 0x00, 0xdc, 0x08, 0xb8, 0xbd, 0x28, 0xb9, 0x9a, 0x0a, 0x42, + 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0x50, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xd4, 0x7f, 0xfb, 0x7f, 0xc3, 0x7f, 0xa1, 0x7f, + 0xb2, 0x7f, 0x02, 0x30, 0x92, 0x7f, 0x00, 0x2e, 0x05, 0x2e, 0x20, 0x00, 0xc4, 0x6f, 0x80, 0xb2, 0x0c, 0x2f, 0x81, + 0x90, 0x1a, 0x2f, 0xd2, 0x6f, 0x07, 0x2e, 0x21, 0x00, 0xa1, 0x32, 0x98, 0x2e, 0xaf, 0xb1, 0x02, 0x30, 0x25, 0x2e, + 0x20, 0x00, 0x92, 0x7f, 0x10, 0x2d, 0xa1, 0x6f, 0xb2, 0x6f, 0xe4, 0x7f, 0xa3, 0x32, 0x98, 0x2e, 0x9c, 0xb1, 0x21, + 0x2e, 0x21, 0x00, 0xe2, 0x6f, 0x03, 0x2e, 0x21, 0x00, 0x81, 0x42, 0x12, 0x30, 0x25, 0x2e, 0x20, 0x00, 0x92, 0x7f, + 0x00, 0x2e, 0xfb, 0x6f, 0x90, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0x00, 0x30, 0xf0, 0x7f, 0x12, 0x24, 0x86, + 0x00, 0x1b, 0x2d, 0xf1, 0x6f, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, + 0x8c, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x8c, 0x84, 0xd1, + 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x41, 0x82, 0xf1, 0x7f, 0xb4, 0x84, + 0xf1, 0x6f, 0x43, 0xa2, 0xe1, 0x2f, 0xf0, 0x5f, 0xb8, 0x2e, 0xc0, 0x50, 0x92, 0x7f, 0xfb, 0x7f, 0x81, 0x7f, 0x00, + 0x30, 0x60, 0x7f, 0x70, 0x7f, 0x50, 0x7f, 0x00, 0x2e, 0x03, 0x2e, 0x04, 0x01, 0x9d, 0xbc, 0x9e, 0xb8, 0x41, 0x7f, + 0x00, 0x2e, 0x42, 0x6f, 0x52, 0x7f, 0xe2, 0x7f, 0x00, 0x2e, 0x83, 0x6f, 0xc4, 0x82, 0xd3, 0x7f, 0x0c, 0x2d, 0x55, + 0x6f, 0x7f, 0x89, 0xdc, 0x01, 0x9d, 0x01, 0xcb, 0x41, 0x8b, 0x43, 0xcc, 0x01, 0x4d, 0x01, 0xc7, 0x41, 0x47, 0x43, + 0x54, 0x7f, 0x00, 0x2e, 0x54, 0x6f, 0x00, 0xab, 0xf0, 0x2f, 0x9b, 0x6f, 0x8a, 0x00, 0x4b, 0x42, 0xc2, 0x7f, 0xb1, + 0x7f, 0x50, 0x7f, 0x7c, 0x80, 0xa0, 0x7f, 0x13, 0x24, 0x09, 0x01, 0x3f, 0x2d, 0x50, 0x6f, 0x18, 0x01, 0xc8, 0x84, + 0xc8, 0x00, 0x50, 0x00, 0x05, 0x41, 0xc7, 0x40, 0x44, 0x40, 0x61, 0x6f, 0x73, 0x6f, 0x2f, 0x18, 0x00, 0xb3, 0x0b, + 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89, 0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, + 0xbe, 0x15, 0xfc, 0x11, 0xae, 0x0b, 0x4e, 0x00, 0xdf, 0x02, 0x61, 0x7f, 0x73, 0x7f, 0xb4, 0x84, 0x01, 0x82, 0xd1, + 0x00, 0x88, 0x80, 0xa2, 0x6f, 0x11, 0x01, 0x81, 0x00, 0xc3, 0x40, 0x05, 0x41, 0x84, 0x40, 0x1d, 0x18, 0x72, 0x6f, + 0x00, 0xb3, 0x63, 0x6f, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89, 0xbc, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x74, + 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, 0xfc, 0x11, 0xae, 0x0b, 0xde, 0x04, 0x97, 0x06, 0x63, 0x7f, 0x72, 0x7f, + 0x51, 0x7f, 0x3c, 0x86, 0xb1, 0x6f, 0xe2, 0x6f, 0x50, 0x6f, 0x42, 0x0e, 0xbc, 0x2f, 0xe0, 0x6f, 0xc8, 0x82, 0x98, + 0x00, 0x48, 0x00, 0xc0, 0x6f, 0x83, 0x40, 0x04, 0x40, 0x42, 0x40, 0x61, 0x6f, 0x70, 0x6f, 0x80, 0xb2, 0x1c, 0x18, + 0x0b, 0x2f, 0x90, 0xa0, 0x03, 0x2f, 0xb0, 0x84, 0xba, 0x11, 0xce, 0x17, 0x06, 0x2d, 0x03, 0x31, 0xda, 0x04, 0xfb, + 0x14, 0x32, 0x13, 0xfa, 0x11, 0xa3, 0x0b, 0x4e, 0x00, 0x07, 0x02, 0x61, 0x7f, 0x70, 0x7f, 0x00, 0x2e, 0x72, 0x6f, + 0x80, 0xa8, 0x60, 0x6f, 0xd1, 0x6f, 0x13, 0x2f, 0x80, 0x90, 0x03, 0x2f, 0x13, 0x24, 0xff, 0x7f, 0x43, 0x0f, 0x0d, + 0x2f, 0xbf, 0xa0, 0x07, 0x2f, 0xbf, 0x90, 0x03, 0x2f, 0x12, 0x24, 0x00, 0x80, 0x42, 0x0e, 0x01, 0x2f, 0x40, 0x42, + 0x07, 0x2d, 0x10, 0x24, 0x00, 0x80, 0x40, 0x42, 0x03, 0x2d, 0x10, 0x24, 0xff, 0x7f, 0x40, 0x42, 0x00, 0x2e, 0xfb, + 0x6f, 0x40, 0x5f, 0x40, 0x40, 0xb8, 0x2e, 0x11, 0x24, 0x7b, 0x00, 0x30, 0x50, 0x10, 0x30, 0x50, 0x42, 0xfb, 0x7f, + 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, + 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, + 0x9a, 0x0a, 0x3c, 0x80, 0x42, 0x42, 0x7e, 0x84, 0xe0, 0x7f, 0x86, 0x82, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, + 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x7d, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x0d, 0x82, 0x02, 0x40, 0xd1, 0x7f, + 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x76, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x14, 0x82, 0x02, 0x40, 0xd1, + 0x7f, 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x6f, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0xe1, 0x6f, 0x12, 0x40, + 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x00, + 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0x01, 0x2e, + 0x55, 0xf0, 0xf0, 0x7f, 0x00, 0x2e, 0xf0, 0x6f, 0x21, 0x2e, 0x55, 0xf0, 0xf0, 0x5f, 0xb8, 0x2e, 0x20, 0x50, 0x00, + 0x30, 0xe0, 0x7f, 0xfb, 0x7f, 0x11, 0x24, 0xb1, 0xf0, 0x42, 0x40, 0x43, 0x30, 0x93, 0x0a, 0x42, 0x42, 0x58, 0x82, + 0x12, 0x24, 0xaf, 0x00, 0x62, 0x42, 0x12, 0x24, 0xff, 0x00, 0x42, 0x42, 0x69, 0x82, 0x72, 0x3c, 0x43, 0x40, 0x9a, + 0x08, 0x83, 0x32, 0x93, 0x0a, 0x42, 0x42, 0x42, 0x82, 0x02, 0x3f, 0x43, 0x40, 0x9a, 0x08, 0x52, 0x42, 0x0b, 0x31, + 0x4b, 0x42, 0x7e, 0x82, 0x72, 0x31, 0x42, 0x42, 0x00, 0x2e, 0x03, 0x2e, 0x40, 0xf0, 0x5f, 0xb2, 0x03, 0x2f, 0x03, + 0x2e, 0x40, 0xf0, 0x5e, 0x90, 0x27, 0x2f, 0x11, 0x24, 0x00, 0x02, 0x12, 0x24, 0x05, 0x80, 0x13, 0x24, 0xff, 0xb7, + 0x1b, 0x24, 0x00, 0xb0, 0x04, 0x30, 0x05, 0x30, 0x56, 0x32, 0x6e, 0x1a, 0x00, 0x2f, 0x25, 0x36, 0x69, 0x1a, 0x01, + 0x2f, 0x5b, 0x25, 0x00, 0x2e, 0x56, 0x41, 0x26, 0x0d, 0x06, 0x30, 0xcf, 0xbb, 0x41, 0xbe, 0xc0, 0x91, 0x01, 0x2f, + 0x00, 0x2e, 0x01, 0x2d, 0x22, 0x0d, 0x81, 0x8d, 0x90, 0xa1, 0xf5, 0x2f, 0xeb, 0x0e, 0xe8, 0x2f, 0x01, 0x2e, 0x25, + 0x00, 0x20, 0x1a, 0x05, 0x2f, 0x20, 0x30, 0xe0, 0x7f, 0x03, 0x2d, 0x30, 0x30, 0xe0, 0x7f, 0x00, 0x2e, 0xe0, 0x6f, + 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0x43, 0xb3, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb, + 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, + 0x91, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x43, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, 0x7f, 0x00, + 0x2e, 0x60, 0x6f, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0xb9, 0xb0, 0x40, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, + 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, + 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f, 0xf6, 0x7f, + 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x29, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, + 0x90, 0x1b, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x2e, 0x04, 0x01, + 0x0f, 0xbc, 0x0f, 0xb8, 0x01, 0xb2, 0x0d, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x01, 0x90, 0x04, 0x2f, 0x98, 0x2e, 0x1a, + 0xb2, 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, 0x01, 0x2e, 0x37, 0xf0, 0x21, 0x2e, 0x37, 0xf0, 0x02, 0x2d, 0x98, 0x2e, + 0xf3, 0xb2, 0x80, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, + 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0x60, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, + 0x0f, 0x2e, 0x01, 0xf0, 0xfe, 0xbf, 0xfe, 0xbb, 0xb7, 0x05, 0xa6, 0x7f, 0xd3, 0x7f, 0xc4, 0x7f, 0xb5, 0x7f, 0x14, + 0x24, 0x89, 0xf0, 0x3f, 0x8b, 0x03, 0x41, 0x44, 0x41, 0xb8, 0xbd, 0x9c, 0x0b, 0xa3, 0x6f, 0x14, 0x24, 0x9a, 0x00, + 0xb3, 0x11, 0x43, 0x8b, 0x16, 0x43, 0x00, 0x2e, 0x67, 0x41, 0x46, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb3, 0x11, 0x16, + 0x43, 0x43, 0x8d, 0x00, 0x2e, 0xa5, 0x41, 0x86, 0x41, 0xd8, 0xbe, 0x6e, 0x0b, 0xeb, 0x10, 0x03, 0x43, 0x13, 0x30, + 0x27, 0x2e, 0x22, 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0xe7, 0x6f, 0xc4, 0x6f, 0xb5, 0x6f, 0xd3, + 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0x91, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, + 0xa2, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0xb9, 0xf0, 0x60, 0x7f, 0x10, 0x30, 0x61, 0x6f, 0x08, + 0x08, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0x9e, 0x00, 0x10, 0x30, 0x21, 0x2e, 0xb9, 0xf0, 0x21, 0x2e, 0x5f, 0xf0, + 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, + 0x5f, 0xc8, 0x2e, 0x20, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x56, 0x32, 0x0f, 0x2e, 0x58, 0xf0, 0x7e, 0x1a, 0x02, 0x2f, + 0x16, 0x30, 0x2d, 0x2e, 0x23, 0x00, 0x16, 0x24, 0x80, 0x00, 0x2d, 0x2e, 0xb9, 0xf0, 0xe7, 0x6f, 0xf6, 0x6f, 0xe0, + 0x5f, 0xc8, 0x2e, 0x30, 0x50, 0x04, 0x30, 0xd4, 0x7f, 0xe4, 0x7f, 0xfb, 0x7f, 0x13, 0x24, 0x26, 0xf0, 0xc2, 0x40, + 0xc1, 0x86, 0xe4, 0x7f, 0xd2, 0x7f, 0x00, 0x2e, 0xd1, 0x40, 0x18, 0xbc, 0x18, 0xba, 0xd2, 0x6f, 0xe1, 0x6f, 0x90, + 0x0a, 0x0c, 0x0b, 0xd2, 0x7f, 0xe4, 0x7f, 0x00, 0x2e, 0xe4, 0x6f, 0xc3, 0x40, 0xe3, 0x0a, 0xdb, 0x6f, 0xdb, 0x7f, + 0xe3, 0x7f, 0x13, 0x24, 0x15, 0x01, 0xe2, 0x6f, 0x09, 0x2e, 0x16, 0x01, 0xd1, 0x6f, 0x98, 0x2e, 0xea, 0xb1, 0x21, + 0x2e, 0x58, 0xf0, 0x98, 0x2e, 0x43, 0xb3, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x98, 0x2e, 0x4d, 0xb3, 0x20, 0x26, + 0x98, 0x2e, 0xfa, 0x01, 0x98, 0x2e, 0xf5, 0xb4, 0x98, 0x2e, 0xf1, 0xb4, 0x98, 0x2e, 0xde, 0xb4, 0x98, 0x2e, 0xf9, + 0xb4, 0x01, 0x2e, 0x40, 0xf0, 0x21, 0x2e, 0x9d, 0x00, 0x10, 0x30, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0x43, 0xb3, + 0x21, 0x30, 0x10, 0x24, 0x9a, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x05, 0x2e, 0x22, 0x00, 0x80, 0xb2, 0x02, + 0x30, 0x05, 0x2f, 0x23, 0x2e, 0x5f, 0xf0, 0x25, 0x2e, 0x22, 0x00, 0x98, 0x2e, 0x17, 0x01, 0x98, 0x2e, 0x31, 0xb1, + 0x01, 0x2e, 0x23, 0x00, 0x01, 0x90, 0x00, 0x30, 0xe7, 0x2f, 0x21, 0x2e, 0x23, 0x00, 0x98, 0x2e, 0x80, 0xb4, 0xe3, + 0x2d, 0x80, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0x10, 0x24, 0x80, 0x00, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x0a, 0x21, 0x2e, + 0x06, 0xf0, 0x00, 0x3e, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x08, 0x51, 0x30, 0x01, 0x0a, 0x21, 0x2e, 0x06, 0xf0, 0xb8, + 0x2e, 0x00, 0x31, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x10, 0x30, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, 0x10, 0x24, + 0x80, 0x00, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, 0x1a, 0x24, 0x26, 0x00, 0x80, 0x2e, 0xab, 0xb4, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, @@ -386,11 +390,7 @@ const uint8_t bmi08x_config_file[] = { 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, - 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, - 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, - 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, - 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00 }; /****************************************************************************/ @@ -828,6 +828,7 @@ int8_t bmi08a_write_config_file(struct bmi08x_dev *dev) /* Config loading disable*/ uint8_t config_load = BMI08X_DISABLE; uint8_t current_acc_pwr_ctrl = BMI08X_DISABLE; + uint8_t aps_disable = BMI08X_DISABLE; uint16_t index = 0; uint8_t reg_data = 0; @@ -840,19 +841,26 @@ int8_t bmi08a_write_config_file(struct bmi08x_dev *dev) /* Check whether the read/write length is valid */ if (dev->read_write_len > 0) { - /* deactivate accel, otherwise post processing can not be enabled safely */ - rslt = get_regs(BMI08X_REG_ACCEL_PWR_CTRL, ¤t_acc_pwr_ctrl, 1, dev); + /* Get accel status */ + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_PWR_CTRL, ¤t_acc_pwr_ctrl, 1, dev); if (rslt == BMI08X_OK) { - rslt = set_regs(BMI08X_REG_ACCEL_PWR_CTRL, &config_load, 1, dev); + /* Disable advanced power save mode */ + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_PWR_CONF, &aps_disable, 1, dev); + if (rslt == BMI08X_OK) { - /*delay required to switch power modes*/ - dev->delay_us(BMI08X_MS_TO_US(BMI08X_POWER_CONFIG_DELAY), dev->intf_ptr_accel); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_PWR_CTRL, &config_load, 1, dev); + + if (rslt == BMI08X_OK) + { + /* Delay required to switch power modes */ + dev->delay_us(BMI08X_MS_TO_US(BMI08X_POWER_CONFIG_DELAY), dev->intf_ptr_accel); - /* Disable config loading*/ - rslt = set_regs(BMI08X_REG_ACCEL_INIT_CTRL, &config_load, 1, dev); + /* Disable config loading */ + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_INIT_CTRL, &config_load, 1, dev); + } } } @@ -872,7 +880,7 @@ int8_t bmi08a_write_config_file(struct bmi08x_dev *dev) /* Enable config loading and FIFO mode */ config_load = BMI08X_ENABLE; - rslt = set_regs(BMI08X_REG_ACCEL_INIT_CTRL, &config_load, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_INIT_CTRL, &config_load, 1, dev); if (rslt == BMI08X_OK) { @@ -880,7 +888,7 @@ int8_t bmi08a_write_config_file(struct bmi08x_dev *dev) dev->delay_us(BMI08X_MS_TO_US(BMI08X_ASIC_INIT_TIME_MS), dev->intf_ptr_accel); /* Check for config initialization status (1 = OK)*/ - rslt = get_regs(BMI08X_REG_ACCEL_INTERNAL_STAT, ®_data, 1, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_INTERNAL_STAT, ®_data, 1, dev); } } @@ -890,11 +898,12 @@ int8_t bmi08a_write_config_file(struct bmi08x_dev *dev) } else { - /* reactivate accel */ - rslt = set_regs(BMI08X_REG_ACCEL_PWR_CTRL, ¤t_acc_pwr_ctrl, 1, dev); + /* Restore accel */ + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_PWR_CTRL, ¤t_acc_pwr_ctrl, 1, dev); + if (rslt == BMI08X_OK) { - /*delay required to switch power modes*/ + /* Delay required to switch power modes */ dev->delay_us(BMI08X_MS_TO_US(BMI08X_POWER_CONFIG_DELAY), dev->intf_ptr_accel); } } @@ -929,7 +938,7 @@ int8_t bmi08a_write_feature_config(uint8_t reg_addr, const uint16_t *reg_data, u if (rslt == BMI08X_OK) { /* Read feature space up to the given feature position */ - rslt = bmi08a_get_regs(BMI08X_ACCEL_FEATURE_CFG_REG, &feature_data[0], read_length, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_FEATURE_CFG, &feature_data[0], read_length, dev); if (rslt == BMI08X_OK) { @@ -942,7 +951,7 @@ int8_t bmi08a_write_feature_config(uint8_t reg_addr, const uint16_t *reg_data, u } /* Write back updated feature space */ - rslt = bmi08a_set_regs(BMI08X_ACCEL_FEATURE_CFG_REG, &feature_data[0], read_length, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_FEATURE_CFG, &feature_data[0], read_length, dev); } } @@ -1029,7 +1038,7 @@ int8_t bmi08a_get_error_status(struct bmi08x_err_reg *err_reg, struct bmi08x_dev if (err_reg != NULL) { /* Read the error codes */ - rslt = get_regs(BMI08X_REG_ACCEL_ERR, &data, 1, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_ERR, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -1064,7 +1073,7 @@ int8_t bmi08a_get_status(uint8_t *status, struct bmi08x_dev *dev) if ((rslt == BMI08X_OK) && (status != NULL)) { /* Read the status */ - rslt = get_regs(BMI08X_REG_ACCEL_STATUS, &data, 1, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_STATUS, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -1110,7 +1119,7 @@ int8_t bmi08a_soft_reset(struct bmi08x_dev *dev) if (dev->intf == BMI08X_SPI_INTF) { /* Dummy SPI read operation of Chip-ID */ - rslt = get_regs(BMI08X_REG_ACCEL_CHIP_ID, &data, 1, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_CHIP_ID, &data, 1, dev); } } } @@ -1134,7 +1143,7 @@ int8_t bmi08a_get_meas_conf(struct bmi08x_dev *dev) /* Proceed if null check is fine */ if (rslt == BMI08X_OK) { - rslt = get_regs(BMI08X_REG_ACCEL_CONF, data, 2, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_CONF, data, 2, dev); if (rslt == BMI08X_OK) { @@ -1206,7 +1215,7 @@ int8_t bmi08a_set_meas_conf(struct bmi08x_dev *dev) if ((!is_odr_invalid) && (!is_bw_invalid) && (!is_range_invalid)) { /* Read accel config. register */ - rslt = get_regs(BMI08X_REG_ACCEL_CONF, data, 2, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_CONF, data, 2, dev); if (rslt == BMI08X_OK) { /* Update data with new odr and bw values */ @@ -1245,7 +1254,7 @@ int8_t bmi08a_get_power_mode(struct bmi08x_dev *dev) /* Proceed if null check is fine */ if (rslt == BMI08X_OK) { - rslt = get_regs(BMI08X_REG_ACCEL_PWR_CONF, &data, 1, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_PWR_CONF, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -1335,7 +1344,7 @@ int8_t bmi08a_get_data(struct bmi08x_sensor_data *accel, struct bmi08x_dev *dev) if ((rslt == BMI08X_OK) && (accel != NULL)) { /* Read accel sensor data */ - rslt = get_regs(BMI08X_REG_ACCEL_X_LSB, data, 6, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_X_LSB, data, 6, dev); if (rslt == BMI08X_OK) { @@ -1380,12 +1389,12 @@ int8_t bmi08a_set_int_config(const struct bmi08x_accel_int_channel_cfg *int_conf { switch (int_config->int_type) { - case BMI08X_ACCEL_DATA_RDY_INT: + case BMI08X_ACCEL_INT_DATA_RDY: /* Data ready interrupt */ rslt = set_accel_data_ready_int(int_config, dev); break; - case BMI08X_ACCEL_SYNC_DATA_RDY_INT: + case BMI08X_ACCEL_INT_SYNC_DATA_RDY: /* synchronized data ready interrupt */ rslt = set_accel_sync_data_ready_int(int_config, dev); @@ -1395,12 +1404,12 @@ int8_t bmi08a_set_int_config(const struct bmi08x_accel_int_channel_cfg *int_conf /* input for synchronization on accel */ rslt = set_accel_sync_input(int_config, dev); break; - case BMI08X_FIFO_WM_INT: + case BMI08X_ACCEL_INT_FIFO_WM: /* FIFO watermark interrupt */ rslt = set_fifo_wm_int(int_config, dev); break; - case BMI08X_FIFO_FULL_INT: + case BMI08X_ACCEL_INT_FIFO_FULL: /* FIFO full interrupt */ rslt = set_fifo_full_int(int_config, dev); @@ -1436,7 +1445,7 @@ int8_t bmi08a_get_sensor_temperature(struct bmi08x_dev *dev, int32_t *sensor_tem if ((rslt == BMI08X_OK) && (sensor_temp != NULL)) { /* Read sensor temperature */ - rslt = get_regs(BMI08X_REG_TEMP_MSB, data, 2, dev); + rslt = bmi08a_get_regs(BMI08X_REG_TEMP_MSB, data, 2, dev); if (rslt == BMI08X_OK) { @@ -1483,7 +1492,7 @@ int8_t bmi08a_get_sensor_time(struct bmi08x_dev *dev, uint32_t *sensor_time) if ((rslt == BMI08X_OK) && (sensor_time != NULL)) { /* Read 3-byte sensor time */ - rslt = get_regs(BMI08X_REG_ACCEL_SENSORTIME_0, data, 3, dev); + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_SENSORTIME_0, data, 3, dev); if (rslt == BMI08X_OK) { @@ -1672,7 +1681,7 @@ int8_t bmi08a_read_fifo_data(struct bmi08x_fifo_frame *fifo, struct bmi08x_dev * /* Get sensor enable status, of which the data * is to be read */ - fifo->data_enable = (uint16_t)((uint16_t)config_data & BMI08X_ACCEL_EN_MASK); + fifo->acc_data_enable = (uint16_t)((uint16_t)config_data & BMI08X_ACCEL_EN_MASK); } } else @@ -2020,6 +2029,30 @@ int8_t bmi08a_set_data_sync_int_config(const struct bmi08x_int_cfg *int_config, return rslt; } +/*! + * @brief This internal API gets accel feature interrupt status + */ +int8_t bmi08a_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t status = 0; + + if (int_status != NULL) + { + rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_INT_STAT_1, &status, 1, dev); + if (rslt == BMI08X_OK) + { + (*int_status) = status; + } + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; +} + /*****************************************************************************/ /* Static function definition */ @@ -2164,7 +2197,7 @@ static int8_t set_int_pin_config(const struct bmi08x_accel_int_channel_cfg *int_ } /* Write to interrupt pin configuration register */ - rslt = set_regs(reg_addr, &data, 1, dev); + rslt = bmi08a_set_regs(reg_addr, &data, 1, dev); } } else @@ -2217,7 +2250,7 @@ static int8_t set_accel_data_ready_int(const struct bmi08x_accel_int_channel_cfg if (rslt == BMI08X_OK) { /* Write to interrupt map register */ - rslt = set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); } } } @@ -2265,7 +2298,7 @@ static int8_t set_accel_sync_data_ready_int(const struct bmi08x_accel_int_channe } /* Write to interrupt map register */ - rslt = set_regs(reg_addr, &data, 1, dev); + rslt = bmi08a_set_regs(reg_addr, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -2306,16 +2339,16 @@ static int8_t stream_transfer_write(const uint8_t *stream_data, uint16_t index, uint8_t asic_lsb = ((index / 2) & 0x0F); /* Write to feature config register */ - rslt = set_regs(BMI08X_ACCEL_RESERVED_5B_REG, &asic_lsb, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_RESERVED_5B, &asic_lsb, 1, dev); if (rslt == BMI08X_OK) { /* Write to feature config register */ - rslt = set_regs(BMI08X_ACCEL_RESERVED_5C_REG, &asic_msb, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_RESERVED_5C, &asic_msb, 1, dev); if (rslt == BMI08X_OK) { /* Write to feature config registers */ - rslt = set_regs(BMI08X_ACCEL_FEATURE_CFG_REG, (uint8_t *)stream_data, dev->read_write_len, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_FEATURE_CFG, (uint8_t *)stream_data, dev->read_write_len, dev); } } @@ -2371,7 +2404,7 @@ static int8_t positive_excited_accel(struct bmi08x_sensor_data *accel_pos, struc uint8_t reg_data = BMI08X_ACCEL_POSITIVE_SELF_TEST; /* Enable positive excitation for all 3 axes */ - rslt = set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); if (rslt == BMI08X_OK) { /* Read accel data after 50ms delay */ @@ -2391,7 +2424,7 @@ static int8_t negative_excited_accel(struct bmi08x_sensor_data *accel_neg, struc uint8_t reg_data = BMI08X_ACCEL_NEGATIVE_SELF_TEST; /* Enable negative excitation for all 3 axes */ - rslt = set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); if (rslt == BMI08X_OK) { /* Read accel data after 50ms delay */ @@ -2402,7 +2435,7 @@ static int8_t negative_excited_accel(struct bmi08x_sensor_data *accel_neg, struc { /* Disable self test */ reg_data = BMI08X_ACCEL_SWITCH_OFF_SELF_TEST; - rslt = set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_SELF_TEST, ®_data, 1, dev); } } @@ -2810,7 +2843,7 @@ static int8_t set_fifo_wm_int(const struct bmi08x_accel_int_channel_cfg *int_con if (rslt == BMI08X_OK) { /* Write to interrupt map register */ - rslt = set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); } } } @@ -2860,7 +2893,7 @@ static int8_t set_fifo_full_int(const struct bmi08x_accel_int_channel_cfg *int_c if (rslt == BMI08X_OK) { /* Write to interrupt map register */ - rslt = set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); + rslt = bmi08a_set_regs(BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, &data, 1, dev); } } } diff --git a/bmi08g.c b/bmi08g.c index c270dd0..e0812eb 100644 --- a/bmi08g.c +++ b/bmi08g.c @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi08g.c - * @date 2020-06-26 - * @version v1.5.3 + * @date 2020-12-11 + * @version v1.5.5 * */ @@ -113,6 +113,19 @@ static int8_t set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, */ static int8_t set_gyro_data_ready_int(const struct bmi08x_gyro_int_channel_cfg *int_config, struct bmi08x_dev *dev); +/*! + * @brief This API sets the FIFO full, FIFO watermark interrupts for gyro sensor + * + * @param[in] int_config : Structure instance of bmi08x_gyro_int_channel_cfg. + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + * + */ +static int8_t set_fifo_int(const struct bmi08x_gyro_int_channel_cfg *int_config, struct bmi08x_dev *dev); + /*! * @brief This API configures the pins which fire the * interrupt signal when any interrupt occurs. @@ -147,6 +160,47 @@ static int8_t set_int_pin_config(const struct bmi08x_gyro_int_channel_cfg *int_c */ static int8_t set_gyro_selftest(uint8_t selftest, struct bmi08x_dev *dev); +/*! + * @brief This internal API is used to get fifo data byte count + * + * + * @param[in] fifo : Structure instance of bmi08x_gyr_fifo_config. + * @param[out] frame_size : Size of the frame with respect to axis selected + * @param[out] fifo_data_byte : Stores the number of bytes to be read + * + */ +static void get_fifo_data_length(const struct bmi08x_gyr_fifo_config *fifo, int8_t frame_size, + uint16_t *fifo_data_byte); + +/*! + * @brief This internal API computes the number of bytes of gyroscope FIFO data + * which is to be parsed. + * + * @param[out] len : Number of bytes to be parsed. + * @param[in] gyr_count : Number of gyroscope frames to be read. + * @param[in] fifo_conf : Structure instance of bmi08x_gyr_fifo_config. + * @param[in] fifo : Structure instance of bmi08x_fifo_frame. + * + */ +static void parse_fifo_gyro_len(uint16_t *len, + const uint16_t *gyr_count, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo); + +/*! + * @brief This internal API computes the number of bytes of gyroscope FIFO data + * which is to be parsed in header-less mode. + * + * @param[out] gyro : Structure instance of bmi08x_sensor_data. + * @param[in,out] data_index : Index value of number of bytes + * @param[in] fifo_conf : Structure instance of bmi08x_gyr_fifo_config. + * @param[in] fifo : Structure instance of bmi08x_fifo_frame. + */ +static void unpack_gyro_data(struct bmi08x_sensor_data *gyro, + uint16_t *data_index, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo); + /****************************************************************************/ /**\name Extern Declarations @@ -278,7 +332,7 @@ int8_t bmi08g_soft_reset(struct bmi08x_dev *dev) { /* Reset gyro device */ data = BMI08X_SOFT_RESET_CMD; - rslt = set_regs(BMI08X_REG_GYRO_SOFTRESET, &data, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_SOFTRESET, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -305,7 +359,7 @@ int8_t bmi08g_get_meas_conf(struct bmi08x_dev *dev) /* Proceed if null check is fine */ if (rslt == BMI08X_OK) { - rslt = get_regs(BMI08X_REG_GYRO_RANGE, data, 2, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_RANGE, data, 2, dev); if (rslt == BMI08X_OK) { @@ -354,26 +408,26 @@ int8_t bmi08g_set_meas_conf(struct bmi08x_dev *dev) if ((!is_odr_invalid) && (!is_range_invalid)) { /* Read range value from the range register */ - rslt = get_regs(BMI08X_REG_GYRO_BANDWIDTH, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_BANDWIDTH, &data, 1, dev); if (rslt == BMI08X_OK) { data = BMI08X_SET_BITS_POS_0(data, BMI08X_GYRO_BW, odr); /* Write odr value to odr register */ - rslt = set_regs(BMI08X_REG_GYRO_BANDWIDTH, &data, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_BANDWIDTH, &data, 1, dev); if (rslt == BMI08X_OK) { /* Read range value from the range register */ - rslt = get_regs(BMI08X_REG_GYRO_RANGE, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_RANGE, &data, 1, dev); if (rslt == BMI08X_OK) { data = BMI08X_SET_BITS_POS_0(data, BMI08X_GYRO_RANGE, range); /* Write range value to range register */ - rslt = set_regs(BMI08X_REG_GYRO_RANGE, &data, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_RANGE, &data, 1, dev); } } } @@ -405,7 +459,7 @@ int8_t bmi08g_get_power_mode(struct bmi08x_dev *dev) /* Proceed if null check is fine */ if (rslt == BMI08X_OK) { - rslt = get_regs(BMI08X_REG_GYRO_LPM1, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_LPM1, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -433,15 +487,15 @@ int8_t bmi08g_set_power_mode(struct bmi08x_dev *dev) if (rslt == BMI08X_OK) { /*read the previous power state*/ - rslt = get_regs(BMI08X_REG_GYRO_LPM1, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_LPM1, &data, 1, dev); if (rslt == BMI08X_OK) { power_mode = dev->gyro_cfg.power; - /*switching between normal mode and the suspend modes is allowed, it is not possible to switch - * between suspend and deep suspend and vice versa. Check for invalid power switching (i.e) - * deep suspend to suspend */ + /* Switching between normal mode and the suspend modes is allowed, it is not possible to switch + * between suspend and deep suspend and vice versa. Check for invalid power switching, + * (i.e) deep suspend to suspend */ if ((power_mode == BMI08X_GYRO_PM_SUSPEND) && (data == BMI08X_GYRO_PM_DEEP_SUSPEND)) { /* Updating the status */ @@ -459,7 +513,7 @@ int8_t bmi08g_set_power_mode(struct bmi08x_dev *dev) if (is_power_switching_mode_valid) { /* Write power to power register */ - rslt = set_regs(BMI08X_REG_GYRO_LPM1, &power_mode, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_LPM1, &power_mode, 1, dev); if (rslt == BMI08X_OK) { @@ -497,7 +551,7 @@ int8_t bmi08g_get_data(struct bmi08x_sensor_data *gyro, struct bmi08x_dev *dev) if ((rslt == BMI08X_OK) && (gyro != NULL)) { /* read gyro sensor data */ - rslt = get_regs(BMI08X_REG_GYRO_X_LSB, data, 6, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_X_LSB, data, 6, dev); if (rslt == BMI08X_OK) { @@ -543,12 +597,17 @@ int8_t bmi08g_set_int_config(const struct bmi08x_gyro_int_channel_cfg *int_confi switch (int_config->int_type) { - case BMI08X_GYRO_DATA_RDY_INT: - { + case BMI08X_GYRO_INT_DATA_RDY: + /* Data ready interrupt */ rslt = set_gyro_data_ready_int(int_config, dev); - } - break; + break; + case BMI08X_GYRO_INT_FIFO_WM: + case BMI08X_GYRO_INT_FIFO_FULL: + + /* FIFO interrupt */ + rslt = set_fifo_int(int_config, dev); + break; default: rslt = BMI08X_E_INVALID_CONFIG; @@ -587,7 +646,7 @@ int8_t bmi08g_perform_selftest(struct bmi08x_dev *dev) while (loop_break) { /* Read self-test register to check if self-test ready bit is set */ - rslt = get_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -609,7 +668,7 @@ int8_t bmi08g_perform_selftest(struct bmi08x_dev *dev) if (rslt == BMI08X_OK) { /* Read self-test register to check for self-test Ok bit */ - rslt = get_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); if (rslt == BMI08X_OK) { @@ -630,6 +689,206 @@ int8_t bmi08g_perform_selftest(struct bmi08x_dev *dev) return rslt; } +/*! + * @brief This internal API gets gyro data ready interrupt status + */ +int8_t bmi08g_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t status = 0; + + if (int_status != NULL) + { + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_INT_STAT_1, &status, 1, dev); + if (rslt == BMI08X_OK) + { + (*int_status) = status; + } + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to get fifo overrun. + */ +int8_t bmi08g_get_fifo_overrun(uint8_t *fifo_overrun, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t reg_data = 0; + + if (fifo_overrun != NULL) + { + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_FIFO_STATUS, ®_data, 1, dev); + + if (rslt == BMI08X_OK) + { + *fifo_overrun = BMI08X_GET_BITS(reg_data, BMI08X_GYRO_FIFO_OVERRUN); + } + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to get fifo configuration of the sensor. + */ +int8_t bmi08g_get_fifo_config(struct bmi08x_gyr_fifo_config *fifo_conf, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t fifo_config[2] = { 0 }; + uint8_t reg_data = 0; + + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_FIFO_CONFIG0, fifo_config, 2, dev); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_FIFO_STATUS, ®_data, 1, dev); + + if (rslt == BMI08X_OK) + { + fifo_conf->tag = BMI08X_GET_BITS(fifo_config[0], BMI08X_GYRO_FIFO_TAG); + + fifo_conf->wm_level = BMI08X_GET_BITS_POS_0(fifo_config[0], BMI08X_GYRO_FIFO_WM_LEVEL); + + fifo_conf->mode = BMI08X_GET_BITS(fifo_config[1], BMI08X_GYRO_FIFO_MODE); + + fifo_conf->data_select = BMI08X_GET_BITS_POS_0(fifo_config[1], BMI08X_GYRO_FIFO_DATA_SELECT); + + fifo_conf->frame_count = BMI08X_GET_BITS_POS_0(reg_data, BMI08X_GYRO_FIFO_FRAME_COUNT); + } + } + + return rslt; +} + +/*! + * @brief This API is used to get fifo configuration of the sensor. + */ +int8_t bmi08g_set_fifo_config(const struct bmi08x_gyr_fifo_config *fifo_conf, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t fifo_config[2] = { 0 }; + + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_FIFO_CONFIG0, fifo_config, 2, dev); + + if (rslt == BMI08X_OK) + { + fifo_config[0] = BMI08X_SET_BITS(fifo_config[0], BMI08X_GYRO_FIFO_TAG, fifo_conf->tag); + + fifo_config[0] = BMI08X_SET_BITS_POS_0(fifo_config[0], BMI08X_GYRO_FIFO_WM_LEVEL, fifo_conf->wm_level); + + fifo_config[1] = BMI08X_SET_BITS_POS_0(fifo_config[1], BMI08X_GYRO_FIFO_DATA_SELECT, fifo_conf->data_select); + + fifo_config[1] = BMI08X_SET_BITS(fifo_config[1], BMI08X_GYRO_FIFO_MODE, fifo_conf->mode); + + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_FIFO_CONFIG0, fifo_config, 2, dev); + } + + return rslt; +} + +/*! + * @brief This API gets the length of FIFO data available in the sensor in + * bytes. + */ +int8_t bmi08g_get_fifo_length(const struct bmi08x_gyr_fifo_config *fifo_config, struct bmi08x_fifo_frame *fifo) +{ + int8_t rslt = BMI08X_OK; + uint16_t fifo_data_byte_count = 0; + + if ((fifo != NULL) && (fifo_config != NULL)) + { + if (fifo_config->data_select == BMI08X_GYRO_FIFO_XYZ_AXIS_ENABLED) + { + get_fifo_data_length(fifo_config, BMI08X_GYRO_FIFO_XYZ_AXIS_FRAME_SIZE, &fifo_data_byte_count); + } + else + { + get_fifo_data_length(fifo_config, BMI08X_GYRO_FIFO_SINGLE_AXIS_FRAME_SIZE, &fifo_data_byte_count); + } + + if (fifo->length > fifo_data_byte_count) + { + fifo->length = fifo_data_byte_count; + } + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to read the fifo data from the sensor. + */ +int8_t bmi08g_read_fifo_data(const struct bmi08x_fifo_frame *fifo, struct bmi08x_dev *dev) +{ + int8_t rslt = BMI08X_OK; + + if (fifo != NULL) + { + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_FIFO_DATA, fifo->data, fifo->length, dev); + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; +} + +/*! + * @brief This API is used to extract gyroscope data from fifo. + */ +void bmi08g_extract_gyro(struct bmi08x_sensor_data *gyro_data, + const uint16_t *gyro_length, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo) +{ + uint16_t data_index = 0; + uint16_t gyro_index = 0; + uint16_t data_read_length = 0; + + /* Get the number of gyro bytes to be read */ + parse_fifo_gyro_len(&data_read_length, gyro_length, fifo_conf, fifo); + + for (; data_index < data_read_length;) + { + unpack_gyro_data(&gyro_data[gyro_index], &data_index, fifo_conf, fifo); + gyro_index++; + } +} + +int8_t bmi08g_enable_watermark(uint8_t enable, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t reg_data; + + if (enable) + { + reg_data = BMI08X_GYRO_FIFO_WM_ENABLE_VAL; + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_FIFO_WM_ENABLE, ®_data, 1, dev); + } + else + { + reg_data = BMI08X_GYRO_FIFO_WM_DISABLE_VAL; + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_FIFO_WM_ENABLE, ®_data, 1, dev); + } + + return rslt; +} + /*****************************************************************************/ /* Static function definition */ @@ -674,7 +933,7 @@ static int8_t get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct reg_addr = (reg_addr | BMI08X_SPI_RD_MASK); } - /* read a gyro register */ + /* Read gyro register */ dev->intf_rslt = dev->read(reg_addr, reg_data, len, dev->intf_ptr_gyro); if (dev->intf_rslt != BMI08X_INTF_RET_SUCCESS) @@ -692,6 +951,7 @@ static int8_t get_regs(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, struct static int8_t set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, struct bmi08x_dev *dev) { int8_t rslt = BMI08X_OK; + uint8_t count = 0; if (dev->intf == BMI08X_SPI_INTF) { @@ -699,13 +959,39 @@ static int8_t set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, reg_addr = (reg_addr & BMI08X_SPI_WR_MASK); } - /* write to a gyro register */ - dev->intf_rslt = dev->write(reg_addr, reg_data, len, dev->intf_ptr_gyro); + /* SPI write requires to set The MSB of reg_addr as 0 + * but in default the MSB is always 0 + */ + if (len == 1) + { + dev->intf_rslt = dev->write(reg_addr, reg_data, len, dev->intf_ptr_gyro); - if (dev->intf_rslt != BMI08X_INTF_RET_SUCCESS) + if (dev->intf_rslt != BMI08X_INTF_RET_SUCCESS) + { + /* Failure case */ + rslt = BMI08X_E_COM_FAIL; + } + } + + /* Burst write is not allowed thus we split burst case write + * into single byte writes Thus user can write multiple bytes + * with ease + */ + if (len > 1) { - /* Updating the error */ - rslt = BMI08X_E_COM_FAIL; + for (count = 0; count < len; count++) + { + dev->intf_rslt = dev->write(reg_addr, ®_data[count], 1, dev->intf_ptr_gyro); + + reg_addr++; + + if (dev->intf_rslt != BMI08X_INTF_RET_SUCCESS) + { + /* Failure case */ + rslt = BMI08X_E_COM_FAIL; + break; + } + } } return rslt; @@ -761,7 +1047,76 @@ static int8_t set_gyro_data_ready_int(const struct bmi08x_gyro_int_channel_cfg * } /* write data to interrupt map register */ - rslt = set_regs(BMI08X_REG_GYRO_INT3_INT4_IO_MAP, &data[0], 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_INT3_INT4_IO_MAP, &data[0], 1, dev); + + if (rslt == BMI08X_OK) + { + /* Configure interrupt pin */ + rslt = set_int_pin_config(int_config, dev); + + if (rslt == BMI08X_OK) + { + /* Write data to interrupt control register */ + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_INT_CTRL, &data[1], 1, dev); + } + } + } + } + + return rslt; +} + +/*! + * @brief This API sets the data ready interrupt for gyro sensor. + */ +static int8_t set_fifo_int(const struct bmi08x_gyro_int_channel_cfg *int_config, struct bmi08x_dev *dev) +{ + int8_t rslt; + uint8_t conf, data[2] = { 0 }; + + /* Read interrupt map register */ + rslt = get_regs(BMI08X_REG_GYRO_INT3_INT4_IO_MAP, &data[0], 1, dev); + + if (rslt == BMI08X_OK) + { + conf = int_config->int_pin_cfg.enable_int_pin; + + switch (int_config->int_channel) + { + case BMI08X_INT_CHANNEL_3: + + /* Data to enable new data ready interrupt */ + data[0] = BMI08X_SET_BITS(data[0], BMI08X_GYRO_FIFO_INT3, conf); + break; + + case BMI08X_INT_CHANNEL_4: + + /* Data to enable new data ready interrupt */ + data[0] = BMI08X_SET_BITS(data[0], BMI08X_GYRO_FIFO_INT4, conf); + break; + + default: + rslt = BMI08X_E_INVALID_INPUT; + break; + } + + if (rslt == BMI08X_OK) + { + /* Condition to check disabling the interrupt in single channel when both + * interrupts channels are enabled*/ + if (data[0] & BMI08X_GYRO_MAP_FIFO_BOTH_INT3_INT4) + { + /* Updating the data */ + /* Data to enable new data ready interrupt */ + data[1] = BMI08X_GYRO_FIFO_INT_ENABLE_VAL; + } + else + { + data[1] = BMI08X_GYRO_FIFO_INT_DISABLE_VAL; + } + + /* write data to interrupt map register */ + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_INT3_INT4_IO_MAP, &data[0], 1, dev); if (rslt == BMI08X_OK) { @@ -771,7 +1126,7 @@ static int8_t set_gyro_data_ready_int(const struct bmi08x_gyro_int_channel_cfg * if (rslt == BMI08X_OK) { /* write data to interrupt control register */ - rslt = set_regs(BMI08X_REG_GYRO_INT_CTRL, &data[1], 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_INT_CTRL, &data[1], 1, dev); } } } @@ -816,7 +1171,7 @@ static int8_t set_int_pin_config(const struct bmi08x_gyro_int_channel_cfg *int_c } /* write to interrupt configuration register */ - rslt = set_regs(BMI08X_REG_GYRO_INT3_INT4_IO_CONF, &data, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_INT3_INT4_IO_CONF, &data, 1, dev); } return rslt; @@ -843,7 +1198,7 @@ static int8_t set_gyro_selftest(uint8_t selftest, struct bmi08x_dev *dev) data = BMI08X_SET_BITS_POS_0(data, BMI08X_GYRO_SELF_TEST_EN, selftest); /* write self test input value to self-test register */ - rslt = set_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); + rslt = bmi08g_set_regs(BMI08X_REG_GYRO_SELF_TEST, &data, 1, dev); } } else @@ -854,4 +1209,85 @@ static int8_t set_gyro_selftest(uint8_t selftest, struct bmi08x_dev *dev) return rslt; } +/*! + * @brief This internal API is used to get fifo data length. + */ +static void get_fifo_data_length(const struct bmi08x_gyr_fifo_config *fifo, int8_t frame_size, uint16_t *fifo_data_byte) +{ + if (fifo->tag) + { + *fifo_data_byte = (uint16_t)(fifo->frame_count * (frame_size + 2)); + } + else + { + *fifo_data_byte = (uint16_t)(fifo->frame_count * frame_size); + } +} + +/*! + * @brief This internal API is used to get length of gyroscope data in fifo. + */ +static void parse_fifo_gyro_len(uint16_t *len, + const uint16_t *gyr_count, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo) +{ + if (fifo_conf->tag == 0) + { + *len = fifo->length; + } + else if ((fifo_conf->tag == 1)) + { + if (fifo_conf->data_select == BMI08X_GYRO_FIFO_XYZ_AXIS_ENABLED) + { + *len = (uint16_t)((*gyr_count) * BMI08X_GYRO_FIFO_XYZ_AXIS_FRAME_SIZE); + } + else + { + *len = (uint16_t)((*gyr_count) * BMI08X_GYRO_FIFO_SINGLE_AXIS_FRAME_SIZE); + } + } +} + +/*! + * @brief This internal API is used to unpack the gyroscope data. + */ +static void unpack_gyro_data(struct bmi08x_sensor_data *gyro, + uint16_t *data_index, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo) +{ + /* Variables to store LSB value */ + uint16_t data_lsb; + + /* Variables to store MSB value */ + uint16_t data_msb; + + uint16_t idx; + + idx = *data_index; + + /* Gyroscope x data */ + data_lsb = fifo->data[idx++]; + data_msb = fifo->data[idx++]; + gyro->x = (int16_t)((data_msb << 8) | data_lsb); + + /* Gyroscope y data */ + data_lsb = fifo->data[idx++]; + data_msb = fifo->data[idx++]; + gyro->y = (int16_t)((data_msb << 8) | data_lsb); + + /* Gyroscope z data */ + data_lsb = fifo->data[idx++]; + data_msb = fifo->data[idx++]; + gyro->z = (int16_t)((data_msb << 8) | data_lsb); + + if (fifo_conf->tag == 1) + { + idx += 2; + } + + *data_index = idx; +} + /*! @endcond */ diff --git a/bmi08x.h b/bmi08x.h index 0f86a41..a69a414 100644 --- a/bmi08x.h +++ b/bmi08x.h @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi08x.h - * @date 2020-06-26 - * @version v1.5.3 + * @date 2020-12-11 + * @version v1.5.5 * */ @@ -603,12 +603,12 @@ int8_t bmi08a_get_synchronized_data(struct bmi08x_sensor_data *accel, /** * \ingroup bmi08ag - * \defgroup bmi08aApiSyncInt Synchronize interrupt - * @brief Configuring synchronization of interrupt + * \defgroup bmi08aApiInt interrupt + * @brief Configuring Interrupts */ /*! - * \ingroup bmi08aApiSyncInt + * \ingroup bmi08aApiInt * \page bmi08a_api_bmi08a_set_data_sync_int_config bmi08a_set_data_sync_int_config * \code * int8_t bmi08a_set_data_sync_int_config(const struct bmi08x_int_cfg *int_config, const struct bmi08x_dev *dev); @@ -628,6 +628,33 @@ int8_t bmi08a_get_synchronized_data(struct bmi08x_sensor_data *accel, */ int8_t bmi08a_set_data_sync_int_config(const struct bmi08x_int_cfg *int_config, struct bmi08x_dev *dev); +/*! + * \ingroup bmi08aApiInt + * \page bmi08a_api_bmi08a_get_data_int_status bmi08a_get_data_int_status + * \code + * int8_t bmi08a_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev); + * \endcode + * @details This API is to get accel feature interrupt status + * + * @param[out] int_status : Variable to store interrupt status + * @param[in] dev : Structure instance of bmi08x_dev + * + *@verbatim + *----------------------------------------- + * int_status | Interrupt + *----------------------------------------- + * 0x01 | Fifo full + * 0x02 | Fifo watermark + * 0x08 | Accel data ready + *------------------------------------------ + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi08a_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev); + /*********************** BMI088 Gyroscope function prototypes ****************************/ /** @@ -872,6 +899,32 @@ int8_t bmi08g_get_data(struct bmi08x_sensor_data *gyro, struct bmi08x_dev *dev); */ int8_t bmi08g_set_int_config(const struct bmi08x_gyro_int_channel_cfg *int_config, struct bmi08x_dev *dev); +/*! + * \ingroup bmi08gApiIntconfig + * \page bmi08g_api_bmi08g_get_data_int_status bmi08g_get_data_int_status + * \code + * int8_t bmi08g_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev); + * \endcode + * @details This API is to get accel feature interrupt status + * + * @param[out] int_status : Variable to store interrupt status + * @param[in] dev : Structure instance of bmi08x_dev + * + *@verbatim + *---------------------------------------------- + * int_status | Interrupt + *---------------------------------------------- + * 0x08 | Gyro data ready + * 0x10 | Fifo full, Fifo watermark + *---------------------------------------------- + *@endverbatim + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval < 0 -> Fail + */ +int8_t bmi08g_get_data_int_status(uint8_t *int_status, struct bmi08x_dev *dev); + /** * \ingroup bmi08ag * \defgroup bmi08gApiSelftest Gyro self test @@ -898,12 +951,163 @@ int8_t bmi08g_perform_selftest(struct bmi08x_dev *dev); /** * \ingroup bmi08ag - * \defgroup bmi08gApiFifo FIFO operations + * \defgroup bmi08gApiFIFO FIFO + * @brief Access and extract FIFO gyro data + */ + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_get_fifo_config bmi08g_get_fifo_config + * \code + * int8_t bmi08g_get_fifo_config(struct bmi08x_gyr_fifo_config *fifo_conf, , struct bmi08x_dev *dev); + * \endcode + * @details This API is used to get the fifo configurations like fifo mode, fifo data select, etc + * + * @param[in] fifo_conf : Structure pointer to fifo configurations + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_get_fifo_config(struct bmi08x_gyr_fifo_config *fifo_conf, struct bmi08x_dev *dev); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_set_fifo_config bmi08g_set_fifo_config + * \code + * int8_t bmi08g_set_fifo_config(const struct bmi08x_gyr_fifo_config *fifo_conf, , struct bmi08x_dev *dev); + * \endcode + * @details This API is used to set the fifo configurations like fifo mode, fifo data select, etc + * + * @param[in] fifo_conf : Structure pointer to fifo configurations + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_set_fifo_config(const struct bmi08x_gyr_fifo_config *fifo_conf, struct bmi08x_dev *dev); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_get_fifo_length bmi08g_get_fifo_length + * \code + * int8_t bmi08g_get_fifo_length(const struct bmi08x_gyr_fifo_config *fifo_config, struct bmi08x_fifo_frame *fifo); + * \endcode + * @details This API is used to get fifo length + * + * @param[in] fifo_config : Structure instance of bmi08x_gyr_fifo_config + * @param[in] fifo : Structure instance of bmi08x_fifo_frame. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_get_fifo_length(const struct bmi08x_gyr_fifo_config *fifo_config, struct bmi08x_fifo_frame *fifo); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_read_fifo_data bmi08g_read_fifo_data + * \code + * int8_t bmi08g_read_fifo_data(const struct bmi08x_gyr_fifo_config *fifo, struct bmi08x_dev *dev); + * \endcode + * @details This API reads FIFO data. + * + * @param[in, out] fifo : Structure instance of bmi08x_fifo_frame + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @note APS has to be disabled before calling this function. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_read_fifo_data(const struct bmi08x_fifo_frame *fifo, struct bmi08x_dev *dev); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_extract_gyro bmi08g_extract_gyro + * \code + * void bmi08g_extract_gyro(struct bmi08x_sensor_data *gyro_data, + * const uint16_t *gyro_length, + * const struct bmi08x_gyr_fifo_config *fifo_conf, + * const struct bmi08x_fifo_frame *fifo); + * \endcode + * @details This API parses and extracts the gyroscope frames from FIFO data read by the + * "bmi08g_read_fifo_data" API and stores it in the "gyro_data" + * structure instance. + * + * @param[out] gyro_data : Structure instance of bmi08x_sensor_data + * where the parsed data bytes are stored. + * @param[in,out] gyro_length : Number of gyroscope frames. + * @param[in,out] fifo_conf : Structure instance of bmi08x_gyr_fifo_config + * @param[in,out] fifo : Structure instance of bmi08x_fifo_frame + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +void bmi08g_extract_gyro(struct bmi08x_sensor_data *gyro_data, + const uint16_t *gyro_length, + const struct bmi08x_gyr_fifo_config *fifo_conf, + const struct bmi08x_fifo_frame *fifo); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_get_fifo_overrun bmi08g_get_fifo_overrun + * \code + * int8_t bmi08g_get_fifo_overrun(uint8_t *fifo_overrun, struct bmi08x_dev *dev); + * \endcode + * @details This API is used to get the fifo over run + * in the register 0x0E bit 7 + * + * @param[in,out] fifo_overrun : The value of fifo over run + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_get_fifo_overrun(uint8_t *fifo_overrun, struct bmi08x_dev *dev); + +/*! + * \ingroup bmi08gApiFIFO + * \page bmi08g_api_bmi08g_enable_watermark bmi08g_enable_watermark + * \code + * int8_t bmi08g_enable_watermark(uint8_t enable, struct bmi08x_dev *dev); + * \endcode + * @details This API is used to set fifo watermark enable/disable + * in the register 0x1E bit 7 + * + * @param[in,out] enable : The value of fifo watermark enable/disable + * @param[in] dev : Structure instance of bmi08x_dev. + * + * @return Result of API execution status + * @retval 0 -> Success + * @retval >0 -> Warning + * @retval <0 -> Fail + */ +int8_t bmi08g_enable_watermark(uint8_t enable, struct bmi08x_dev *dev); + +/*********************************************************************************/ +/* Accel APIs */ +/*********************************************************************************/ + +/** + * \ingroup bmi08ag + * \defgroup bmi08aApiFifo FIFO operations * @brief FIFO operations of the sensor */ /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_set_fifo_config bmi08a_set_fifo_config * \code * int8_t bmi08a_set_fifo_config(const struct bmi08x_accel_fifo_config *config, const struct bmi08x_dev *dev); @@ -921,7 +1125,7 @@ int8_t bmi08g_perform_selftest(struct bmi08x_dev *dev); int8_t bmi08a_set_fifo_config(const struct bmi08x_accel_fifo_config *config, struct bmi08x_dev *dev); /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_get_fifo_config bmi08a_get_fifo_config * \code * int8_t bmi08a_get_fifo_config(struct bmi08x_accel_fifo_config *config, const struct bmi08x_dev *dev); @@ -939,7 +1143,7 @@ int8_t bmi08a_set_fifo_config(const struct bmi08x_accel_fifo_config *config, str int8_t bmi08a_get_fifo_config(struct bmi08x_accel_fifo_config *config, struct bmi08x_dev *dev); /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_read_fifo_data bmi08a_read_fifo_data * \code * int8_t bmi08a_read_fifo_data(struct bmi08x_fifo_frame *fifo, const struct bmi08x_dev *dev); @@ -959,7 +1163,7 @@ int8_t bmi08a_get_fifo_config(struct bmi08x_accel_fifo_config *config, struct bm int8_t bmi08a_read_fifo_data(struct bmi08x_fifo_frame *fifo, struct bmi08x_dev *dev); /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_get_fifo_length bmi08a_get_fifo_length * \code * int8_t bmi08a_get_fifo_length(uint16_t *fifo_length, const struct bmi08x_dev *dev); @@ -982,7 +1186,7 @@ int8_t bmi08a_read_fifo_data(struct bmi08x_fifo_frame *fifo, struct bmi08x_dev * int8_t bmi08a_get_fifo_length(uint16_t *fifo_length, struct bmi08x_dev *dev); /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_get_fifo_wm bmi08a_get_fifo_wm * \code * int8_t bmi08a_get_fifo_wm(uint16_t *wm, const struct bmi08x_dev *dev); @@ -1000,7 +1204,7 @@ int8_t bmi08a_get_fifo_length(uint16_t *fifo_length, struct bmi08x_dev *dev); int8_t bmi08a_get_fifo_wm(uint16_t *wm, struct bmi08x_dev *dev); /*! - * \ingroup bmi08gApiFifo + * \ingroup bmi08aApiFifo * \page bmi08a_api_bmi08a_set_fifo_wm bmi08a_set_fifo_wm * \code * int8_t bmi08a_set_fifo_wm(uint16_t wm, const struct bmi08x_dev *dev); @@ -1081,7 +1285,7 @@ int8_t bmi08a_get_fifo_down_sample(uint8_t *fifo_downs, struct bmi08x_dev *dev); /*! * \ingroup bmi08aApiFIFODown - * \page bmi08g_api_bmi08a_set_fifo_down_sample bmi08a_set_fifo_down_sample + * \page bmi08a_api_bmi08a_set_fifo_down_sample bmi08a_set_fifo_down_sample * \code * int8_t bmi08a_set_fifo_down_sample(uint8_t fifo_downs, const struct bmi08x_dev *dev); * \endcode diff --git a/bmi08x_defs.h b/bmi08x_defs.h index d7ab1b0..327496c 100644 --- a/bmi08x_defs.h +++ b/bmi08x_defs.h @@ -31,8 +31,8 @@ * POSSIBILITY OF SUCH DAMAGE. * * @file bmi08x_defs.h -* @date 2020-06-26 -* @version v1.5.3 +* @date 2020-12-11 +* @version v1.5.5 * */ @@ -206,6 +206,11 @@ /**\name Accel Soft reset register */ #define BMI08X_REG_ACCEL_SOFTRESET UINT8_C(0x7E) +/**\name Feature Config related Registers */ +#define BMI08X_REG_ACCEL_RESERVED_5B UINT8_C(0x5B) +#define BMI08X_REG_ACCEL_RESERVED_5C UINT8_C(0x5C) +#define BMI08X_REG_ACCEL_FEATURE_CFG UINT8_C(0x5E) + /**\name BMI085 Accel unique chip identifier */ #define BMI085_ACCEL_CHIP_ID UINT8_C(0x1F) @@ -216,13 +221,14 @@ #define BMI08X_ACCEL_I2C_ADDR_PRIMARY UINT8_C(0x18) #define BMI08X_ACCEL_I2C_ADDR_SECONDARY UINT8_C(0x19) -/**\name Feature Config related Registers */ -#define BMI08X_ACCEL_RESERVED_5B_REG UINT8_C(0x5B) -#define BMI08X_ACCEL_RESERVED_5C_REG UINT8_C(0x5C) -#define BMI08X_ACCEL_FEATURE_CFG_REG UINT8_C(0x5E) - /**\name Interrupt masks */ #define BMI08X_ACCEL_DATA_READY_INT UINT8_C(0x80) +#define BMI08X_ACCEL_FIFO_WM_INT UINT8_C(0x02) +#define BMI08X_ACCEL_FIFO_FULL_INT UINT8_C(0x01) + +#define BMI08X_GYRO_DATA_READY_INT UINT8_C(0x80) +#define BMI08X_GYRO_FIFO_WM_INT UINT8_C(0x10) +#define BMI08X_GYRO_FIFO_FULL_INT UINT8_C(0x10) /**\name Accel Bandwidth */ #define BMI08X_ACCEL_BW_OSR4 UINT8_C(0x00) @@ -356,6 +362,9 @@ /**\name Gyro Interrupt status register */ #define BMI08X_REG_GYRO_INT_STAT_1 UINT8_C(0x0A) +/**\name Gyro FIFO status register */ +#define BMI08X_REG_GYRO_FIFO_STATUS UINT8_C(0x0E) + /**\name Gyro Range register */ #define BMI08X_REG_GYRO_RANGE UINT8_C(0x0F) @@ -377,9 +386,21 @@ /**\name Gyro Interrupt Map register */ #define BMI08X_REG_GYRO_INT3_INT4_IO_MAP UINT8_C(0x18) +/**\name Gyro FIFO watermark enable register */ +#define BMI08X_REG_GYRO_FIFO_WM_ENABLE UINT8_C(0x1E) + /**\name Gyro Self test register */ #define BMI08X_REG_GYRO_SELF_TEST UINT8_C(0x3C) +/**\name Gyro Fifo Config 0 register */ +#define BMI08X_REG_GYRO_FIFO_CONFIG0 UINT8_C(0x3D) + +/**\name Gyro Fifo Config 1 register */ +#define BMI08X_REG_GYRO_FIFO_CONFIG1 UINT8_C(0x3E) + +/**\name Gyro Fifo Data register */ +#define BMI08X_REG_GYRO_FIFO_DATA UINT8_C(0x3F) + /**\name Gyro unique chip identifier */ #define BMI08X_GYRO_CHIP_ID UINT8_C(0x0F) @@ -413,11 +434,18 @@ /**\name Gyro data ready interrupt enable value */ #define BMI08X_GYRO_DRDY_INT_DISABLE_VAL UINT8_C(0x00) #define BMI08X_GYRO_DRDY_INT_ENABLE_VAL UINT8_C(0x80) +#define BMI08X_GYRO_FIFO_INT_DISABLE_VAL UINT8_C(0x00) +#define BMI08X_GYRO_FIFO_INT_ENABLE_VAL UINT8_C(0x40) +#define BMI08X_GYRO_FIFO_WM_ENABLE_VAL UINT8_C(0x80) +#define BMI08X_GYRO_FIFO_WM_DISABLE_VAL UINT8_C(0x00) /**\name Gyro data ready map values */ #define BMI08X_GYRO_MAP_DRDY_TO_INT3 UINT8_C(0x01) #define BMI08X_GYRO_MAP_DRDY_TO_INT4 UINT8_C(0x80) #define BMI08X_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4 UINT8_C(0x81) +#define BMI08X_GYRO_MAP_FIFO_INT3 UINT8_C(0x04) +#define BMI08X_GYRO_MAP_FIFO_INT4 UINT8_C(0x20) +#define BMI08X_GYRO_MAP_FIFO_BOTH_INT3_INT4 UINT8_C(0x24) /**\name Gyro Soft reset delay */ #define BMI08X_GYRO_SOFTRESET_DELAY UINT8_C(30) @@ -483,6 +511,37 @@ #define BMI08X_GYRO_SELF_TEST_RESULT_POS UINT8_C(2) #define BMI08X_GYRO_SELF_TEST_FUNCTION_POS UINT8_C(3) +/**\name Gyro Fifo configurations */ +#define BMI08X_GYRO_FIFO_OVERRUN_MASK UINT8_C(0x80) +#define BMI08X_GYRO_FIFO_OVERRUN_POS UINT8_C(0x07) +#define BMI08X_GYRO_FIFO_MODE_MASK UINT8_C(0xC0) +#define BMI08X_GYRO_FIFO_MODE_POS UINT8_C(0x06) +#define BMI08X_GYRO_FIFO_TAG_MASK UINT8_C(0x80) +#define BMI08X_GYRO_FIFO_TAG_POS UINT8_C(0x07) +#define BMI08X_GYRO_FIFO_DATA_SELECT_MASK UINT8_C(0x03) +#define BMI08X_GYRO_FIFO_FRAME_COUNT_MASK UINT8_C(0x7F) +#define BMI08X_GYRO_FIFO_WM_LEVEL_MASK UINT8_C(0x7F) + +/*! @name Gyro Fifo interrupt map */ +#define BMI08X_GYRO_FIFO_INT3_MASK UINT8_C(0x04) +#define BMI08X_GYRO_FIFO_INT3_POS UINT8_C(0x02) +#define BMI08X_GYRO_FIFO_INT4_MASK UINT8_C(0x20) +#define BMI08X_GYRO_FIFO_INT4_POS UINT8_C(0x05) + +/**\name Gyro FIFO definitions */ +#define BMI08X_GYRO_FIFO_TAG_ENABLED UINT8_C(0x01) +#define BMI08X_GYRO_FIFO_TAG_DISABLED UINT8_C(0x00) +#define BMI08X_GYRO_FIFO_MODE_BYPASS UINT8_C(0x00) +#define BMI08X_GYRO_FIFO_MODE UINT8_C(0x01) +#define BMI08X_GYRO_FIFO_MODE_STREAM UINT8_C(0x02) +#define BMI08X_GYRO_FIFO_XYZ_AXIS_ENABLED UINT8_C(0x00) +#define BMI08X_GYRO_FIFO_X_AXIS_ENABLED UINT8_C(0x01) +#define BMI08X_GYRO_FIFO_Y_AXIS_ENABLED UINT8_C(0x02) +#define BMI08X_GYRO_FIFO_Z_AXIS_ENABLED UINT8_C(0x03) +#define BMI08X_GYRO_FIFO_XYZ_AXIS_FRAME_SIZE UINT8_C(0x06) +#define BMI08X_GYRO_FIFO_SINGLE_AXIS_FRAME_SIZE UINT8_C(0x02) +#define BMI08X_GYRO_FIFO_1KB_BUFFER UINT16_C(1024) + /*************************** Common Macros for both Accel and Gyro *****************************/ /**\name SPI read/write mask to configure address */ #define BMI08X_SPI_RD_MASK UINT8_C(0x80) @@ -703,7 +762,7 @@ enum bmi08x_variant { * @retval 0 for Success * @retval Non-zero for Failure */ -typedef BMI08X_INTF_RET_TYPE (*bmi08x_read_fptr_t)(uint8_t reg_addr, uint8_t *read_data, uint32_t len, void *intf_ptr); +typedef BMI08X_INTF_RET_TYPE (*bmi08x_read_fptr_t)(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); /*! * @brief Bus communication function pointer which should be mapped to @@ -718,7 +777,7 @@ typedef BMI08X_INTF_RET_TYPE (*bmi08x_read_fptr_t)(uint8_t reg_addr, uint8_t *re * @retval Non-zero for Failure * */ -typedef BMI08X_INTF_RET_TYPE (*bmi08x_write_fptr_t)(uint8_t reg_addr, const uint8_t *read_data, uint32_t len, +typedef BMI08X_INTF_RET_TYPE (*bmi08x_write_fptr_t)(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); /*! @@ -837,15 +896,15 @@ enum bmi08x_gyro_int_channel { * @brief Enum to select accelerometer interrupts */ enum bmi08x_accel_int_types { - BMI08X_ACCEL_DATA_RDY_INT, + BMI08X_ACCEL_INT_DATA_RDY, /* Accel data ready interrupt */ - BMI08X_ACCEL_SYNC_DATA_RDY_INT, + BMI08X_ACCEL_INT_SYNC_DATA_RDY, /* Accel synchronized data ready interrupt */ BMI08X_ACCEL_SYNC_INPUT, /* Accel FIFO watermark interrupt */ - BMI08X_FIFO_WM_INT, + BMI08X_ACCEL_INT_FIFO_WM, /* Accel FIFO full interrupt */ - BMI08X_FIFO_FULL_INT + BMI08X_ACCEL_INT_FIFO_FULL }; /*! @@ -853,7 +912,11 @@ enum bmi08x_accel_int_types { */ enum bmi08x_gyro_int_types { /* Gyro data ready interrupt */ - BMI08X_GYRO_DATA_RDY_INT + BMI08X_GYRO_INT_DATA_RDY, + /* Gyro FIFO watermark interrupt */ + BMI08X_GYRO_INT_FIFO_WM, + /* Gyro FIFO full interrupt */ + BMI08X_GYRO_INT_FIFO_FULL }; /*! @@ -867,21 +930,21 @@ struct bmi08x_int_pin_cfg * - BMI08X_INT_ACTIVE_LOW * - BMI08X_INT_ACTIVE_HIGH */ - uint8_t lvl : 1; + uint8_t lvl; /*! interrupt pin mode configuration * Assignable macros : * - BMI08X_INT_MODE_PUSH_PULL * - BMI08X_INT_MODE_OPEN_DRAIN */ - uint8_t output_mode : 1; + uint8_t output_mode; /*! Enable interrupt pin * Assignable Macros : * - BMI08X_ENABLE * - BMI08X_DISABLE */ - uint8_t enable_int_pin : 1; + uint8_t enable_int_pin; }; /*! @@ -933,7 +996,7 @@ struct bmi08x_int_cfg }; /*! - * @brief accel fifo configurations + * @brief Accel Fifo configurations */ struct bmi08x_accel_fifo_config { @@ -950,6 +1013,27 @@ struct bmi08x_accel_fifo_config uint8_t int2_en; }; +/*! + * @brief Gyro Fifo configurations + */ +struct bmi08x_gyr_fifo_config +{ + /*! FIFO mode selection */ + uint8_t mode; + + /*! Selection of axis for data */ + uint8_t data_select; + + /*! Tag to include/exclude interrupt in FIFO data bytes */ + uint8_t tag; + + /*! Frame count of fifo data */ + uint8_t frame_count; + + /*! Water-mark level for FIFO */ + uint16_t wm_level; +}; + /*! @name Structure to define FIFO frame configuration */ struct bmi08x_fifo_frame { @@ -960,11 +1044,17 @@ struct bmi08x_fifo_frame uint16_t length; /*! Enables type of data to be streamed - accelerometer */ - uint16_t data_enable; + uint16_t acc_data_enable; + + /*! Enables type of data to be streamed - gyroscope */ + uint16_t gyr_data_enable; /*! To index accelerometer bytes */ uint16_t acc_byte_start_idx; + /*! To index gyroscope bytes */ + uint16_t gyr_byte_start_idx; + /*! FIFO sensor time */ uint32_t sensor_time; @@ -980,11 +1070,14 @@ struct bmi08x_fifo_frame /*! Accelerometer frame length */ uint8_t acc_frm_len; - /*! Accelerometer frame length */ - uint8_t all_frm_len; + /*! Gyro frame length */ + uint8_t gyr_frm_len; /*! FIFO accelerometer configurations */ - struct bmi08x_accel_fifo_config fifo_conf; + struct bmi08x_accel_fifo_config acc_fifo_conf; + + /*! FIFO gyroscope configurations */ + struct bmi08x_gyr_fifo_config gyr_fifo_conf; }; /*! diff --git a/examples/accel_fifo_full/Makefile b/examples/accel_fifo_full/Makefile new file mode 100644 index 0000000..11a321f --- /dev/null +++ b/examples/accel_fifo_full/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_fifo_full.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/accel_fifo_full/accel_fifo_full.c b/examples/accel_fifo_full/accel_fifo_full.c new file mode 100644 index 0000000..3dfd5c4 --- /dev/null +++ b/examples/accel_fifo_full/accel_fifo_full.c @@ -0,0 +1,311 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file accel_fifo_full.c + * @brief Example file how to read bmi08x accel FIFO full data + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*********************************************************************/ +/* Macros */ +/*********************************************************************/ + +/* Buffer size allocated to store raw FIFO data for accel */ +#define BMI08X_ACC_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1024) + +/* Length of data to be read from FIFO for accel */ +#define BMI08X_ACC_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1024) + +/* Number of Accel frames to be extracted from FIFO */ +#define BMI08X_ACC_FIFO_FULL_EXTRACTED_DATA_FRAME_COUNT UINT8_C(100) + +/*********************************************************************/ +/* Global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! @brief variable to hold the bmi08x accel data */ +struct bmi08x_sensor_data bmi08x_accel[100] = { { 0 } }; + +/*! bmi08x accel int config */ +struct bmi08x_accel_int_channel_cfg accel_int_config; + +/*********************************************************************/ +/* Static function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initialize the bmi08x sensor with default + */ +static int8_t init_bmi08x(void); + +/*********************************************************************/ +/* Functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; + +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_FIFO_FULL; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_FIFO_FULL; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(void) +{ + int8_t rslt; + + uint8_t status = 0; + + /* Initialize FIFO frame structure */ + struct bmi08x_fifo_frame fifo_frame = { 0 }; + + /* To configure the FIFO accel configurations */ + struct bmi08x_accel_fifo_config config; + + /* Number of bytes of FIFO data */ + uint8_t fifo_data[BMI08X_ACC_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Number of accelerometer frames */ + uint16_t accel_length = BMI08X_ACC_FIFO_FULL_EXTRACTED_DATA_FRAME_COUNT; + + /* Variable to index bytes */ + uint16_t idx = 0; + + uint8_t try = 1; + + /* Variable to store sensor time value */ + uint32_t sensor_time; + + /* Variable to store available fifo length */ + uint16_t fifo_length; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + /* Enable data ready interrupts */ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + printf("Accel FIFO full interrupt data\n"); + + if (rslt == BMI08X_OK) + { + /* Update FIFO structure */ + fifo_frame.data = fifo_data; + fifo_frame.length = BMI08X_ACC_FIFO_RAW_DATA_USER_LENGTH; + + config.accel_en = BMI08X_ENABLE; + + /* Set FIFO configuration by enabling accelerometer */ + rslt = bmi08a_set_fifo_config(&config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_fifo_config", rslt); + + while (try <= 3) + { + rslt = bmi08a_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_data_int_status", rslt); + + if (status & BMI08X_ACCEL_FIFO_FULL_INT) + { + printf("\nIteration : %d\n", try); + + accel_length = BMI08X_ACC_FIFO_FULL_EXTRACTED_DATA_FRAME_COUNT; + + rslt = bmi08a_get_fifo_length(&fifo_length, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_fifo_length", rslt); + + printf("FIFO buffer size : %d\n", fifo_frame.length); + printf("FIFO length available : %d\n\n", fifo_length); + + printf("Requested data frames before parsing: %d\n", accel_length); + + if (rslt == BMI08X_OK) + { + /* Delay to read FIFO with microcontroller */ + bmi08xdev.delay_us(1000, bmi08xdev.intf_ptr_accel); + + /* Read FIFO data */ + rslt = bmi08a_read_fifo_data(&fifo_frame, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_read_fifo_data", rslt); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer */ + rslt = bmi08a_extract_accel(bmi08x_accel, &accel_length, &fifo_frame, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_extract_accel", rslt); + + printf("Parsed accelerometer frames: %d\n", accel_length); + + /* Print the parsed accelerometer data from the FIFO buffer */ + for (idx = 0; idx < accel_length; idx++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", + idx, + bmi08x_accel[idx].x, + bmi08x_accel[idx].y, + bmi08x_accel[idx].z); + } + + rslt = bmi08a_get_sensor_time(&bmi08xdev, &sensor_time); + bmi08x_error_codes_print_result("bmi08a_get_sensor_time", rslt); + + printf("Sensor time : %lu\n", sensor_time); + } + + try++; + } + } + } + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + + bmi08x_coines_deinit(); + + return rslt; +} diff --git a/examples/accel_fifo_watermark/Makefile b/examples/accel_fifo_watermark/Makefile new file mode 100644 index 0000000..44d92d8 --- /dev/null +++ b/examples/accel_fifo_watermark/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= accel_fifo_watermark.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/accel_fifo_watermark/accel_fifo_watermark.c b/examples/accel_fifo_watermark/accel_fifo_watermark.c new file mode 100644 index 0000000..3be38ad --- /dev/null +++ b/examples/accel_fifo_watermark/accel_fifo_watermark.c @@ -0,0 +1,329 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file accel_fifo_watermark.c + * @brief Example file how to read bmi08x accel FIFO watermark data + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*********************************************************************/ +/* Macros */ +/*********************************************************************/ + +/* Buffer size allocated to store raw FIFO data for accel */ +#define BMI08X_ACC_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(1024) + +/* Length of data to be read from FIFO for accel */ +#define BMI08X_ACC_FIFO_RAW_DATA_USER_LENGTH UINT16_C(1024) + +/* Watermark level for accel */ +#define BMI08X_ACC_FIFO_WATERMARK_LEVEL UINT8_C(500) + +/* Number of Accel frames to be extracted from FIFO */ + +/* (Each frame has 7 bytes: 1 byte header + 6 bytes accel data) + * Watermark level / Frame size = 500 / 7 = 71 + * Extra frames given to obtain sensortime + */ +#define BMI08X_ACC_FIFO_WM_EXTRACTED_DATA_FRAME_COUNT UINT8_C(75) + +/*********************************************************************/ +/* Global variables */ +/*********************************************************************/ +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! @brief variable to hold the bmi08x accel data */ +struct bmi08x_sensor_data bmi08x_accel[100] = { { 0 } }; + +/*! bmi08x accel int config */ +struct bmi08x_accel_int_channel_cfg accel_int_config; + +/*********************************************************************/ +/* Static function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initialize the bmi08x sensor with default + */ +static int8_t init_bmi08x(void); + +/*********************************************************************/ +/* Functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; + +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_2; + accel_int_config.int_type = BMI08X_ACCEL_INT_FIFO_WM; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_FIFO_WM; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(void) +{ + int8_t rslt; + + uint8_t status = 0; + + /* Variable to set water mark level */ + uint16_t wml = 0; + + /* Initialize FIFO frame structure */ + struct bmi08x_fifo_frame fifo_frame = { 0 }; + + /* To configure the FIFO accel configurations */ + struct bmi08x_accel_fifo_config config; + + /* Number of bytes of FIFO data */ + uint8_t fifo_data[BMI08X_ACC_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Number of accelerometer frames */ + uint16_t accel_length = BMI08X_ACC_FIFO_WM_EXTRACTED_DATA_FRAME_COUNT; + + /* Variable to index bytes */ + uint16_t idx = 0; + + uint8_t try = 1; + + /* Variable to store sensor time value */ + uint32_t sensor_time; + + /* Variable to store available fifo length */ + uint16_t fifo_length; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + /*Enable data ready interrupts*/ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + printf("Accel FIFO watermark interrupt data\n"); + if (rslt == BMI08X_OK) + { + /* Set water mark level */ + rslt = bmi08a_set_fifo_wm(BMI08X_ACC_FIFO_WATERMARK_LEVEL, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_fifo_wm", rslt); + + /* Update FIFO structure */ + fifo_frame.data = fifo_data; + fifo_frame.length = BMI08X_ACC_FIFO_RAW_DATA_USER_LENGTH; + + config.accel_en = BMI08X_ENABLE; + + /* Set FIFO configuration by enabling accelerometer */ + rslt = bmi08a_set_fifo_config(&config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_fifo_config", rslt); + + while (try <= 3) + { + rslt = bmi08a_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_data_int_status", rslt); + + if (status & BMI08X_ACCEL_FIFO_WM_INT) + { + printf("\nIteration : %d\n", try); + + accel_length = BMI08X_ACC_FIFO_WM_EXTRACTED_DATA_FRAME_COUNT; + + rslt = bmi08a_get_fifo_length(&fifo_length, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_fifo_length", rslt); + + rslt = bmi08a_get_fifo_wm(&wml, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_fifo_length", rslt); + + printf("Watermark level : %d\n", wml); + + printf("FIFO buffer size : %d\n", fifo_frame.length); + printf("FIFO length available : %d\n", fifo_length); + + printf("Requested data frames before parsing: %d\n", accel_length); + + if (rslt == BMI08X_OK) + { + /* Delay to read FIFO with microcontroller */ + bmi08xdev.delay_us(1000, bmi08xdev.intf_ptr_accel); + + /* Read FIFO data */ + rslt = bmi08a_read_fifo_data(&fifo_frame, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_read_fifo_data", rslt); + + /* Parse the FIFO data to extract accelerometer data from the FIFO buffer */ + rslt = bmi08a_extract_accel(bmi08x_accel, &accel_length, &fifo_frame, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_extract_accel", rslt); + + printf("Parsed accelerometer frames: %d\n", accel_length); + + /* Print the parsed accelerometer data from the FIFO buffer */ + for (idx = 0; idx < accel_length; idx++) + { + printf("ACCEL[%d] X : %d\t Y : %d\t Z : %d\n", + idx, + bmi08x_accel[idx].x, + bmi08x_accel[idx].y, + bmi08x_accel[idx].z); + } + + rslt = bmi08a_get_sensor_time(&bmi08xdev, &sensor_time); + bmi08x_error_codes_print_result("bmi08a_get_sensor_time", rslt); + + printf("Sensor time : %lu\n", sensor_time); + } + + try++; + } + } + } + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + + bmi08x_coines_deinit(); + + return rslt; +} diff --git a/examples/common/common.c b/examples/common/common.c new file mode 100644 index 0000000..bf635dd --- /dev/null +++ b/examples/common/common.c @@ -0,0 +1,264 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "coines.h" +#include "bmi08x_defs.h" + +/******************************************************************************/ +/*! Macro definitions */ + +#define BMI08X_READ_WRITE_LEN UINT8_C(46) + +/*! BMI085 shuttle id */ +#define BMI085_SHUTTLE_ID UINT16_C(0x46) + +/*! BMI088 shuttle id */ +#define BMI088_SHUTTLE_ID UINT16_C(0x66) + +/******************************************************************************/ +/*! Static variable definition */ + +/*! Variable that holds the I2C device address or SPI chip selection for accel */ +uint8_t acc_dev_add; + +/*! Variable that holds the I2C device address or SPI chip selection for gyro */ +uint8_t gyro_dev_add; + +/******************************************************************************/ +/*! User interface functions */ + +/*! + * I2C read function map to COINES platform + */ +BMI08X_INTF_RET_TYPE bmi08x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_i2c(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * I2C write function map to COINES platform + */ +BMI08X_INTF_RET_TYPE bmi08x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_i2c(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * SPI read function map to COINES platform + */ +BMI08X_INTF_RET_TYPE bmi08x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_read_spi(dev_addr, reg_addr, reg_data, (uint16_t)len); +} + +/*! + * SPI write function map to COINES platform + */ +BMI08X_INTF_RET_TYPE bmi08x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr) +{ + uint8_t dev_addr = *(uint8_t*)intf_ptr; + + return coines_write_spi(dev_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)len); +} + +/*! + * Delay function map to COINES platform + */ +void bmi08x_delay_us(uint32_t period, void *intf_ptr) +{ + coines_delay_usec(period); +} + +/*! + * @brief Function to select the interface between SPI and I2C. + * Also to initialize coines platform + */ +int8_t bmi08x_interface_init(struct bmi08x_dev *bmi08x, uint8_t intf, uint8_t variant) +{ + int8_t rslt = BMI08X_OK; + struct coines_board_info board_info; + + if (bmi08x != NULL) + { + int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB); + if (result < COINES_SUCCESS) + { + printf( + "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" + " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); + exit(result); + } + + result = coines_get_board_info(&board_info); + +#if defined(PC) + setbuf(stdout, NULL); +#endif + + if (result == COINES_SUCCESS) + { + if ((board_info.shuttle_id != BMI085_SHUTTLE_ID) && (board_info.shuttle_id != BMI088_SHUTTLE_ID)) + { + printf("! Warning invalid sensor shuttle \n ," "This application will not support this sensor \n"); + exit(COINES_E_FAILURE); + } + } + + coines_set_shuttleboard_vdd_vddio_config(0, 0); + coines_delay_usec(10000); + + /* Bus configuration : I2C */ + if (intf == BMI08X_I2C_INTF) + { + printf("I2C Interface \n"); + + /* To initialize the user I2C function */ + acc_dev_add = BMI08X_ACCEL_I2C_ADDR_PRIMARY; + gyro_dev_add = BMI08X_GYRO_I2C_ADDR_PRIMARY; + bmi08x->intf = BMI08X_I2C_INTF; + bmi08x->read = bmi08x_i2c_read; + bmi08x->write = bmi08x_i2c_write; + + /* SDO pin is made low for selecting I2C address 0x76*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_8, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + + /* set the sensor interface as I2C with 400kHz speed + Use I2C Fast mode (400kHz) for reliable operation with high ODR/sampling time + See Readme.txt - NOTE section for details*/ + coines_config_i2c_bus(COINES_I2C_BUS_0, COINES_I2C_FAST_MODE); + coines_delay_msec(10); + + /* PS pin is made high for selecting I2C protocol (gyroscope)*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_9, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + } + /* Bus configuration : SPI */ + else if (intf == BMI08X_SPI_INTF) + { + printf("SPI Interface \n"); + + /* To initialize the user SPI function */ + bmi08x->intf = BMI08X_SPI_INTF; + bmi08x->read = bmi08x_spi_read; + bmi08x->write = bmi08x_spi_write; + + /* SPI chip select pin for Accel (CSB1_A) */ + acc_dev_add = COINES_SHUTTLE_PIN_8; + + /* SPI chip select pin for Gyro (CSB2_G) */ + gyro_dev_add = COINES_SHUTTLE_PIN_14; + + /* CSB1 pin is made high for selecting SPI protocol (accelerometer)*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_8, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + + /* CS pin is made high for selecting SPI protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_14, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_HIGH); + + /* PS pin is made low for selecting SPI protocol*/ + coines_set_pin_config(COINES_SHUTTLE_PIN_9, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); + coines_delay_msec(10); + coines_config_spi_bus(COINES_SPI_BUS_0, COINES_SPI_SPEED_5_MHZ, COINES_SPI_MODE3); + } + + /* Selection of bmi085 or bmi088 sensor variant */ + bmi08x->variant = variant; + + /* Assign accel device address to accel interface pointer */ + bmi08x->intf_ptr_accel = &acc_dev_add; + + /* Assign gyro device address to gyro interface pointer */ + bmi08x->intf_ptr_gyro = &gyro_dev_add; + + /* Configure delay in microseconds */ + bmi08x->delay_us = bmi08x_delay_us; + + /* Configure max read/write length (in bytes) ( Supported length depends on target machine) */ + bmi08x->read_write_len = BMI08X_READ_WRITE_LEN; + + coines_delay_usec(10000); + + coines_set_shuttleboard_vdd_vddio_config(3300, 3300); + + coines_delay_usec(10000); + } + else + { + rslt = BMI08X_E_NULL_PTR; + } + + return rslt; + +} + +/*! + * @brief Prints the execution status of the APIs. + */ +void bmi08x_error_codes_print_result(const char api_name[], int8_t rslt) +{ + if (rslt != BMI08X_OK) + { + printf("%s\t", api_name); + if (rslt == BMI08X_E_NULL_PTR) + { + printf("Error [%d] : Null pointer\r\n", rslt); + } + else if (rslt == BMI08X_E_COM_FAIL) + { + printf("Error [%d] : Communication failure\r\n", rslt); + } + else if (rslt == BMI08X_E_DEV_NOT_FOUND) + { + printf("Error [%d] : Device not found\r\n", rslt); + } + else if (rslt == BMI08X_E_OUT_OF_RANGE) + { + printf("Error [%d] : Out of Range\r\n", rslt); + } + else if (rslt == BMI08X_E_INVALID_INPUT) + { + printf("Error [%d] : Invalid input\r\n", rslt); + } + else if (rslt == BMI08X_E_CONFIG_STREAM_ERROR) + { + printf("Error [%d] : Config stream error\r\n", rslt); + } + else if (rslt == BMI08X_E_RD_WR_LENGTH_INVALID) + { + printf("Error [%d] : Invalid Read write length\r\n", rslt); + } + else if (rslt == BMI08X_E_INVALID_CONFIG) + { + printf("Error [%d] : Invalid config\r\n", rslt); + } + else if (rslt == BMI08X_E_FEATURE_NOT_SUPPORTED) + { + printf("Error [%d] : Feature not supported\r\n", rslt); + } + else + { + printf("Error [%d] : Unknown error code\r\n", rslt); + } + } +} + +/*! + * @brief Deinitializes coines platform + * + * @return void. + */ +void bmi08x_coines_deinit(void) +{ + coines_close_comm_intf(COINES_COMM_INTF_USB); +} diff --git a/examples/generic/common/bmi08x_common.h b/examples/common/common.h similarity index 78% rename from examples/generic/common/bmi08x_common.h rename to examples/common/common.h index 2ae558f..96b5fe4 100644 --- a/examples/generic/common/bmi08x_common.h +++ b/examples/common/common.h @@ -1,137 +1,128 @@ -/**\ - * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - **/ - -#ifndef BMI08X_COMMON_H -#define BMI08X_COMMON_H - -/*! CPP guard */ -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "bmi08x_defs.h" - -/*! - * @brief Function for initialization of I2C bus - * - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -int8_t user_i2c_init(void); - -/*! - * @brief Function for initialization of SPI bus - * - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -int8_t user_spi_init(void); - -/*! - * @brief Function for reading the sensor's registers through SPI bus. - * - * @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. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI08X_INTF_RET_SUCCESS -> Success - * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t user_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); - -/*! - * @brief Function for reading the sensor's registers through I2C bus. - * - * @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. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI08X_INTF_RET_SUCCESS -> Success - * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); - -/*! - * @brief Function for writing the sensor's registers through SPI bus. - * - * @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. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI08X_INTF_RET_SUCCESS -> Success - * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t user_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); - -/*! - * @brief Function for writing the sensor's registers through I2C bus. - * - * @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. - * @param[in] intf_ptr : Interface pointer - * - * @return Status of execution - * @retval = BMI08X_INTF_RET_SUCCESS -> Success - * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info - * - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); - -/*! - * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the - * APIs. - * - * @param[in] period_us : The required wait time in microsecond. - * @param[in] intf_ptr : Interface pointer - * - * @return void. - * - */ -void user_delay(uint32_t period_us, void *intf_ptr); - -/*! - * @brief Function to select the interface between SPI and I2C. - * - * @param[in] bma : Structure instance of bmi08x_dev - * @param[in] intf : Interface selection parameter - * For I2C : BMI08X_I2C_INTF - * For SPI : BMI08X_SPI_INTF - * @param[in] variant : Sensor variant parameter - * For BMI085 : BMI085_VARIANT - * For BMI088 : BMI088_VARIANT - * - * @return Status of execution - * @retval 0 -> Success - * @retval < 0 -> Failure Info - */ -int8_t bmi08x_interface_init(struct bmi08x_dev *bma, uint8_t intf, uint8_t variant); - -/*! - * @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 bmi08x_error_codes_print_result(const char api_name[], int8_t rslt); - -#ifdef __cplusplus -} -#endif /* End of CPP guard */ - -#endif /* BMI08X_COMMON_H */ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + **/ + +#ifndef COMMON_H +#define COMMON_H + +/*! CPP guard */ +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "bmi08x_defs.h" + +/*! + * @brief Function for reading the sensor's registers through I2C bus. + * + * @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. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI08X_INTF_RET_SUCCESS -> Success + * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI08X_INTF_RET_TYPE bmi08x_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through I2C bus. + * + * @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. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI08X_INTF_RET_SUCCESS -> Success + * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI08X_INTF_RET_TYPE bmi08x_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for reading the sensor's registers through SPI bus. + * + * @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. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI08X_INTF_RET_SUCCESS -> Success + * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI08X_INTF_RET_TYPE bmi08x_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief Function for writing the sensor's registers through SPI bus. + * + * @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. + * @param[in] intf_ptr : Interface pointer + * + * @return Status of execution + * @retval = BMI08X_INTF_RET_SUCCESS -> Success + * @retval != BMI08X_INTF_RET_SUCCESS -> Failure Info + * + */ +BMI08X_INTF_RET_TYPE bmi08x_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t len, void *intf_ptr); + +/*! + * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the + * APIs. + * + * @param[in] period_us : The required wait time in microsecond. + * @param[in] intf_ptr : Interface pointer + * + * @return void. + * + */ +void bmi08x_delay_us(uint32_t period, void *intf_ptr); + +/*! + * @brief Function to select the interface between SPI and I2C. + * + * @param[in] bma : Structure instance of bmi08x_dev + * @param[in] intf : Interface selection parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * @param[in] variant : Sensor variant parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + * + * @return Status of execution + * @retval 0 -> Success + * @retval < 0 -> Failure Info + */ +int8_t bmi08x_interface_init(struct bmi08x_dev *bma, uint8_t intf, uint8_t variant); + +/*! + * @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 bmi08x_error_codes_print_result(const char api_name[], int8_t rslt); + +/*! + * @brief Deinitializes coines platform + * + * @return void. + */ +void bmi08x_coines_deinit(void); + +#ifdef __cplusplus +} +#endif /* End of CPP guard */ + +#endif /* COMMON_H */ diff --git a/examples/generic/accel_read_fifo_data/accel_read_fifo_data.c b/examples/generic/accel_read_fifo_data/accel_read_fifo_data.c deleted file mode 100644 index 3f2f74f..0000000 --- a/examples/generic/accel_read_fifo_data/accel_read_fifo_data.c +++ /dev/null @@ -1,226 +0,0 @@ -/** - * Copyright (C) 2020 Bosch Sensortec GmbH - * - * SPDX-License-Identifier: BSD-3-Clause - * - * @file bmi08x_read_from_fifo.c - * @brief Sample code to read BMI08x sensor data from FIFO - * - */ - -/*********************************************************************/ -/* system header files */ -/*********************************************************************/ -#include -#include -#include - -/*********************************************************************/ -/* own header files */ -/*********************************************************************/ -#include "bmi08x.h" -#include "bmi08x_common.h" - -/*********************************************************************/ -/* Macro definitions */ -/*********************************************************************/ - -/*! Earth's gravity in m/s^2 */ -#define GRAVITY_EARTH (9.80665f) - -/*********************************************************************/ -/* Global variables */ -/*********************************************************************/ - -/*! @brief This structure containing relevant bmi08x info */ -struct bmi08x_dev bmi08xdev; - -/*! @brief variable to hold the bmi08x accel data */ -struct bmi08x_sensor_data bmi08x_accel; - -/*! @brief variable to hold the bmi08x gyro data */ -struct bmi08x_sensor_data bmi08x_gyro; - -/*! - * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for - * range 2G, 4G, 8G or 16G. - * - * @param[in] val : LSB from each axis. - * @param[in] g_range : Gravity range. - * @param[in] bit_width : Resolution for accel. - * - * @return Gravity. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); - -/*! - * @brief Main Function where the execution getting started to test the code. - * - * @return status - * - */ -int main(void) -{ - int8_t rslt; - - /* To configure the FIFO accel configurations */ - struct bmi08x_accel_fifo_config config; - - /* Read the x,y,z axis data */ - struct bmi08x_sensor_data bmi08x_accel[100] = { { 0 } }; - - /* Initialize FIFO frame structure */ - struct bmi08x_fifo_frame fifo_frame = { 0 }; - - /* Initialize interrupt configurations */ - struct bmi08x_accel_int_channel_cfg int_config; - - /* Number of accelerometer frames */ - uint16_t accel_length = 100; - - /* Number of bytes of FIFO data */ - uint8_t fifo_data[1024] = { 0 }; - - /* Variable to set water mark level */ - uint16_t wml = 0; - - /* Variable to index bytes */ - uint16_t idx = 0; - - uint8_t pwr_data; - - float x, y, z; - - /* Function to select interface between SPI and I2C, according to that the device structure gets updated */ - - /* Interface given as parameter - * For I2C : BMI08X_I2C_INTF - * For SPI : BMI08X_SPI_INTF - * Sensor variant given as parameter - * For BMI085 : BMI085_VARIANT - * For BMI088 : BMI088_VARIANT - */ - rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); - bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); - - if (rslt == BMI08X_OK) - { - /* Initialize bmi08a */ - rslt = bmi08a_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_init", rslt); - - /* Initialize bmi08g */ - rslt = bmi08g_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_init", rslt); - - /* To get power mode */ - rslt = bmi08a_get_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_get_power_mode", rslt); - - /* Switch on accelerometer */ - bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; - rslt = bmi08a_set_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); - - /* To uploads the bmi08a config file */ - rslt = bmi08a_load_config_file(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_load_config_file", rslt); - - rslt = bmi08a_get_regs(BMI08X_REG_ACCEL_PWR_CONF, &pwr_data, 1, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_get_regs", rslt); - - bmi08xdev.delay_us(BMI08X_MS_TO_US(50), bmi08xdev.intf_ptr_accel); - - bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; - bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_200_HZ; - - /* set odr,bandwidth and range */ - rslt = bmi08a_set_meas_conf(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); - - bmi08xdev.delay_us(BMI08X_MS_TO_US(100), bmi08xdev.intf_ptr_accel); - - /* Configure the Interrupt configurations (int_channel,int_type, int_pin_config_level, - * output and enable int pin) */ - int_config.int_channel = BMI08X_INT_CHANNEL_1; - int_config.int_type = BMI08X_FIFO_WM_INT; - int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - - /* Set the interrupt configuration */ - rslt = bmi08a_set_int_config(&int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); - - /* Set water mark(aka 6 frames, each 7 bytes: 1 byte header + 6 bytes accel data) */ - wml = 1000; - rslt = bmi08a_set_fifo_wm(wml, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_fifo_wm", rslt); - - printf("watermark_data: %d\n", wml); - - /* Update FIFO structure */ - fifo_frame.data = fifo_data; - fifo_frame.length = 1024; - - config.accel_en = BMI08X_ENABLE; - - /* Set FIFO configuration by enabling accelerometer */ - rslt = bmi08a_set_fifo_config(&config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_fifo_config", rslt); - - bmi08xdev.delay_us(BMI08X_MS_TO_US(1000), bmi08xdev.intf_ptr_accel); - - /* Read FIFO data */ - rslt = bmi08a_read_fifo_data(&fifo_frame, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_read_fifo_data", rslt); - - if (rslt == BMI08X_OK) - { - printf("Requested data frames before parsing: %d\t\n", accel_length); - - /* Parse the FIFO data to extract accelerometer data from the FIFO buffer */ - rslt = bmi08a_extract_accel(bmi08x_accel, &accel_length, &fifo_frame, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_extract_accel", rslt); - - printf("Parsed accelerometer frames: %d\r\n", accel_length); - - printf("Accel data in LSB units and Gravity data in m/s^2\n"); - - /* Print the parsed accelerometer data from the FIFO buffer */ - for (idx = 0; idx < accel_length; idx++) - { - printf("ACCEL[%d] X : %d raw LSB\t Y : %d raw LSB\t Z : %d raw LSB\n", - idx, - bmi08x_accel[idx].x, - bmi08x_accel[idx].y, - bmi08x_accel[idx].z); - - /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(bmi08x_accel[idx].x, 2, 16); - y = lsb_to_mps2(bmi08x_accel[idx].y, 2, 16); - z = lsb_to_mps2(bmi08x_accel[idx].z, 2, 16); - - /* Print the data in m/s2. */ - printf("\t Gravity-x = %4.2f, Gravity-y = %4.2f, Gravity-z = %4.2f\n", x, y, z); - } - } - } - - return rslt; -} - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) -{ - float gravity; - - uint32_t half_scale = ((1 << bit_width) / 2); - - gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); - - return gravity; -} diff --git a/examples/generic/common/bmi08x_common.c b/examples/generic/common/bmi08x_common.c deleted file mode 100644 index 831ae09..0000000 --- a/examples/generic/common/bmi08x_common.c +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright (C) 2020 Bosch Sensortec GmbH. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#include -#include -#include - -#include "bmi08x_defs.h" - -/******************************************************************************/ -/*! Macro definitions */ -#define BMI08X_READ_WRITE_LEN UINT8_C(46) - -/******************************************************************************/ -/*! Static variable definition */ - -/*! Variable that holds the I2C device address or SPI chip selection for accel */ -uint8_t acc_dev_add; - -/*! Variable that holds the I2C device address or SPI chip selection for gyro */ -uint8_t gyro_dev_add; - -/******************************************************************************/ -/*! User interface functions */ - -/*! - * @brief Function for initialization of I2C bus. - */ -int8_t user_i2c_init(void) -{ - - /* Implement I2C bus initialization according to the target machine. */ - return 0; -} - -/*! - * @brief Function for initialization of SPI bus. - */ -int8_t user_spi_init(void) -{ - - /* Implement SPI bus initialization according to the target machine. */ - return 0; -} - -/*! - * @brief Function for reading the sensor's registers through SPI bus. - */ -int8_t user_spi_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) -{ - - /* Implement the SPI read routine according to the target machine. */ - return 0; -} - -/*! - * @brief Function for reading the sensor's registers through I2C bus. - */ -int8_t user_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) -{ - - /* Implement the I2C read routine according to the target machine. */ - return 0; -} - -/*! - * @brief Function for writing the sensor's registers through SPI bus. - */ -int8_t user_spi_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) -{ - - /* Implement the SPI write routine according to the target machine. */ - return 0; -} - -/*! - * @brief Function for writing the sensor's registers through I2C bus. - */ -int8_t user_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) -{ - - /* Implement the I2C write routine according to the target machine. */ - return 0; -} - -/*! - * @brief This function provides the delay for required time (Microseconds) as per the input provided in some of the - * APIs. - */ -void user_delay(uint32_t period_us, void *intf_ptr) -{ - /* Implement the delay routine according to the target machine. */ -} - -/*! - * @brief Function to select the interface between SPI and I2C. - */ -int8_t bmi08x_interface_init(struct bmi08x_dev *bmi08x, uint8_t intf, uint8_t variant) -{ - int8_t rslt = BMI08X_OK; - - if (bmi08x != NULL) - { - /* Bus configuration : I2C */ - if (intf == BMI08X_I2C_INTF) - { - printf("I2C Interface \n"); - - /* To initialize the user I2C function */ - user_i2c_init(); - - /* To initialize the user I2C function */ - acc_dev_add = BMI08X_ACCEL_I2C_ADDR_PRIMARY; - gyro_dev_add = BMI08X_GYRO_I2C_ADDR_PRIMARY; - bmi08x->intf = BMI08X_I2C_INTF; - bmi08x->read = user_i2c_read; - bmi08x->write = user_i2c_write; - } - - /* Bus configuration : SPI */ - else if (intf == BMI08X_SPI_INTF) - { - printf("SPI Interface \n"); - - /* To initialize the user SPI function */ - user_spi_init(); - - /* To initialize the user SPI function */ - bmi08x->intf = BMI08X_SPI_INTF; - bmi08x->read = user_spi_read; - bmi08x->write = user_spi_write; - - /* SPI chip select pin for Accel */ - acc_dev_add = 0; - - /* SPI chip select pin for Gyro */ - gyro_dev_add = 1; - } - - /* Selection of bmi085 or bmi088 sensor variant */ - bmi08x->variant = variant; - - /* Assign accel device address to accel interface pointer */ - bmi08x->intf_ptr_accel = &acc_dev_add; - - /* Assign gyro device address to gyro interface pointer */ - bmi08x->intf_ptr_gyro = &gyro_dev_add; - - /* Configure delay in microseconds */ - bmi08x->delay_us = user_delay; - - /* Configure max read/write length (in bytes) ( Supported length depends on target machine) */ - bmi08x->read_write_len = BMI08X_READ_WRITE_LEN; - - } - else - { - rslt = BMI08X_E_NULL_PTR; - } - - return rslt; - -} - -/*! - * @brief Prints the execution status of the APIs. - */ -void bmi08x_error_codes_print_result(const char api_name[], int8_t rslt) -{ - if (rslt != BMI08X_OK) - { - printf("%s\t", api_name); - if (rslt & BMI08X_E_NULL_PTR) - { - printf("Error [%d] : Null pointer\r\n", rslt); - } - else if (rslt & BMI08X_E_COM_FAIL) - { - printf("Error [%d] : Communication failure\r\n", rslt); - } - else if (rslt & BMI08X_E_DEV_NOT_FOUND) - { - printf("Error [%d] : Device not found\r\n", rslt); - } - else if (rslt & BMI08X_E_OUT_OF_RANGE) - { - printf("Error [%d] : Out of Range\r\n", rslt); - } - else if (rslt & BMI08X_E_INVALID_INPUT) - { - printf("Error [%d] : Invalid input\r\n", rslt); - } - else if (rslt & BMI08X_E_CONFIG_STREAM_ERROR) - { - printf("Error [%d] : Config stream error\r\n", rslt); - } - else if (rslt & BMI08X_E_RD_WR_LENGTH_INVALID) - { - printf("Error [%d] : Invalid Read write length\r\n", rslt); - } - else if (rslt & BMI08X_E_INVALID_CONFIG) - { - printf("Error [%d] : Invalid config\r\n", rslt); - } - else if (rslt & BMI08X_E_FEATURE_NOT_SUPPORTED) - { - printf("Error [%d] : Feature not supported\r\n", rslt); - } - else - { - printf("Error [%d] : Unknown error code\r\n", rslt); - } - } -} diff --git a/examples/gyro_fifo_full/Makefile b/examples/gyro_fifo_full/Makefile new file mode 100644 index 0000000..c5b2194 --- /dev/null +++ b/examples/gyro_fifo_full/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro_fifo_full.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/gyro_fifo_full/gyro_fifo_full.c b/examples/gyro_fifo_full/gyro_fifo_full.c new file mode 100644 index 0000000..73de3d8 --- /dev/null +++ b/examples/gyro_fifo_full/gyro_fifo_full.c @@ -0,0 +1,282 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file gyro_fifo_full.c + * @brief Example file how to read bmi08x gyro FIFO watermark data + */ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi08x.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macros */ + +/* Buffer size allocated to store raw FIFO data */ +#define BMI08X_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(600) + +/* Length of data to be read from FIFO */ +#define BMI08X_FIFO_RAW_DATA_USER_LENGTH UINT16_C(600) + +/* Number of Gyro frames to be extracted from FIFO */ +#define BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT UINT8_C(100) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! @brief variable to hold the bmi08x gyro data */ +struct bmi08x_sensor_data bmi08x_gyro[100] = { { 0 } }; + +/*! bmi08x gyro int config */ +struct bmi08x_gyro_int_channel_cfg gyro_int_config; + +/******************************************************************************/ +/*! Static Functions */ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_100_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_2G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; /* Bandwidth and OSR are same */ + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_32_ODR_100_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_125_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_32_ODR_100_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_FIFO_FULL; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable gyro fifo interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg*)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_FIFO_FULL; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable gyro fifo interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg*)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + + return rslt; +} + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable */ + int8_t rslt; + + /* Gyroscope fifo configurations */ + struct bmi08x_gyr_fifo_config gyr_conf = { 0 }; + + /* Fifo frame structure */ + struct bmi08x_fifo_frame fifo = { 0 }; + + /* Number of gyroscope frames */ + uint16_t gyro_length = BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT; + + /* Variable to index bytes */ + uint16_t idx = 0; + + /* Variable that holds loop count of fifo example */ + uint8_t try = 1; + + /* Variable that holds interrupt status */ + uint8_t status = 0; + + /* Number of bytes of FIFO data */ + uint8_t fifo_data[BMI08X_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + if (rslt == BMI08X_OK) + { + /* Enable data ready interrupts */ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + printf("Gyro FIFO full interrupt data\n"); + if (rslt == BMI08X_OK) + { + gyr_conf.mode = BMI08X_GYRO_FIFO_MODE; + gyr_conf.tag = BMI08X_GYRO_FIFO_TAG_DISABLED; + + rslt = bmi08g_set_fifo_config(&gyr_conf, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_fifo_config", rslt); + + /* Update FIFO structure */ + fifo.data = fifo_data; + fifo.length = BMI08X_FIFO_RAW_DATA_USER_LENGTH; + + while (try <= 3) + { + rslt = bmi08g_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_fifo_config", rslt); + + if (status & BMI08X_GYRO_FIFO_FULL_INT) + { + printf("\nIteration : %d\n", try); + + gyro_length = BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT; + + rslt = bmi08g_get_fifo_config(&gyr_conf, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_get_fifo_config", rslt); + + rslt = bmi08g_get_fifo_length(&gyr_conf, &fifo); + bmi08x_error_codes_print_result("bmi08g_get_fifo_length", rslt); + + /* Delay to read FIFO with microcontroller */ + bmi08xdev.delay_us(1000, bmi08xdev.intf_ptr_gyro); + + /* Read FIFO data */ + rslt = bmi08g_read_fifo_data(&fifo, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_read_fifo_data", rslt); + + printf("FIFO buffer size : %d\n", BMI08X_FIFO_RAW_DATA_BUFFER_SIZE); + printf("FIFO length available : %d\n\n", fifo.length); + + printf("Requested data frames before parsing: %d\n", gyro_length); + + /* Parse the FIFO data to extract gyroscope data from the FIFO buffer */ + bmi08g_extract_gyro(bmi08x_gyro, &gyro_length, &gyr_conf, &fifo); + bmi08x_error_codes_print_result("bmi08g_extract_gyro", rslt); + + printf("Parsed gyroscope frames: %d\n", gyr_conf.frame_count); + + /* Print the parsed gyroscope data from the FIFO buffer */ + for (idx = 0; idx < gyr_conf.frame_count; idx++) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + idx, + bmi08x_gyro[idx].x, + bmi08x_gyro[idx].y, + bmi08x_gyro[idx].z); + } + + try++; + } + } + } + } + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + + bmi08x_coines_deinit(); + + return rslt; +} diff --git a/examples/gyro_fifo_watermark/Makefile b/examples/gyro_fifo_watermark/Makefile new file mode 100644 index 0000000..38f2c1f --- /dev/null +++ b/examples/gyro_fifo_watermark/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= gyro_fifo_watermark.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/gyro_fifo_watermark/gyro_fifo_watermark.c b/examples/gyro_fifo_watermark/gyro_fifo_watermark.c new file mode 100644 index 0000000..5944785 --- /dev/null +++ b/examples/gyro_fifo_watermark/gyro_fifo_watermark.c @@ -0,0 +1,299 @@ +/**\ + * Copyright (c) 2020 Bosch Sensortec GmbH. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file gyro_fifo_watermark.c + * @brief Example file how to read bmi08x gyro FIFO watermark data + */ + +/******************************************************************************/ +/*! Header Files */ +#include +#include "bmi08x.h" +#include "common.h" +#include "coines.h" + +/******************************************************************************/ +/*! Macros */ + +/* Buffer size allocated to store raw FIFO data */ +#define BMI08X_FIFO_RAW_DATA_BUFFER_SIZE UINT16_C(600) + +/* Length of data to be read from FIFO */ +#define BMI08X_FIFO_RAW_DATA_USER_LENGTH UINT16_C(600) + +/* Watermark level */ +#define BMI08X_FIFO_WATERMARK_LEVEL UINT8_C(50) + +/* Number of Gyro frames to be extracted from FIFO */ +#define BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT UINT8_C(100) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! @brief variable to hold the bmi08x gyro data */ +struct bmi08x_sensor_data bmi08x_gyro[100] = { { 0 } }; + +/*! bmi08x gyro int config */ +struct bmi08x_gyro_int_channel_cfg gyro_int_config; + +/******************************************************************************/ +/*! Static Functions */ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_100_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_2G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_3G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; /* Bandwidth and OSR are same */ + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_32_ODR_100_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_125_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_32_ODR_100_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_FIFO_WM; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable gyro fifo interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg*)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + + rslt = bmi08g_enable_watermark(BMI08X_ENABLE, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_enable_watermark", rslt); + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_FIFO_WM; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable gyro fifo interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg*)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + + rslt = bmi08g_enable_watermark(BMI08X_DISABLE, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_enable_watermark", rslt); + + return rslt; +} + +/******************************************************************************/ +/*! Functions */ + +/* This function starts the execution of program. */ +int main(void) +{ + /* Status of api are returned to this variable */ + int8_t rslt; + + /* Gyroscope fifo configurations */ + struct bmi08x_gyr_fifo_config gyr_conf = { 0 }; + + /* Fifo frame structure */ + struct bmi08x_fifo_frame fifo = { 0 }; + + /* Number of gyroscope frames */ + uint16_t gyro_length = BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT; + + /* Variable to index bytes */ + uint16_t idx = 0; + + /* Variable that holds loop count of fifo example */ + uint8_t try = 1; + + /* Variable that holds interrupt status */ + uint8_t status = 0; + + /* Number of bytes of FIFO data */ + uint8_t fifo_data[BMI08X_FIFO_RAW_DATA_BUFFER_SIZE] = { 0 }; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + if (rslt == BMI08X_OK) + { + /* Enable data ready interrupts */ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + printf("Gyro FIFO watermark interrupt data\n"); + + if (rslt == BMI08X_OK) + { + gyr_conf.mode = BMI08X_GYRO_FIFO_MODE; + gyr_conf.wm_level = BMI08X_FIFO_WATERMARK_LEVEL; + gyr_conf.tag = BMI08X_GYRO_FIFO_TAG_ENABLED; + + rslt = bmi08g_set_fifo_config(&gyr_conf, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_fifo_config", rslt); + + /* Update FIFO structure */ + fifo.data = fifo_data; + fifo.length = BMI08X_FIFO_RAW_DATA_USER_LENGTH; + + while (try <= 3) + { + rslt = bmi08g_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_fifo_config", rslt); + + if (status & BMI08X_GYRO_FIFO_WM_INT) + { + printf("\nIteration : %d\n", try); + printf("Watermark level : %d (Indicates frame number) \n\n", gyr_conf.wm_level); + + gyro_length = BMI08X_FIFO_EXTRACTED_DATA_FRAME_COUNT; + + rslt = bmi08g_get_fifo_config(&gyr_conf, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_get_fifo_config", rslt); + + rslt = bmi08g_get_fifo_length(&gyr_conf, &fifo); + bmi08x_error_codes_print_result("bmi08g_get_fifo_length", rslt); + + /* Delay to read FIFO with microcontroller */ + bmi08xdev.delay_us(1000, bmi08xdev.intf_ptr_gyro); + + /* Read FIFO data */ + rslt = bmi08g_read_fifo_data(&fifo, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_read_fifo_data", rslt); + + printf("FIFO buffer size : %d\n", BMI08X_FIFO_RAW_DATA_USER_LENGTH); + printf("FIFO length available : %d\n\n", fifo.length); + + printf("Requested data frames before parsing: %d\n", gyro_length); + + /* Parse the FIFO data to extract gyroscope data from the FIFO buffer */ + bmi08g_extract_gyro(bmi08x_gyro, &gyro_length, &gyr_conf, &fifo); + bmi08x_error_codes_print_result("bmi08g_extract_gyro", rslt); + + printf("Parsed gyroscope frames: %d\n", gyr_conf.frame_count); + + /* Print the parsed gyroscope data from the FIFO buffer */ + for (idx = 0; idx < gyr_conf.frame_count; idx++) + { + if (((bmi08x_gyro[idx].x) != 0) && ((bmi08x_gyro[idx].y) != 0) && + ((bmi08x_gyro[idx].z) != 0)) + { + printf("GYRO[%d] X : %d\t Y : %d\t Z : %d\n", + idx, + bmi08x_gyro[idx].x, + bmi08x_gyro[idx].y, + bmi08x_gyro[idx].z); + + } + } + + try++; + } + } + } + } + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + + bmi08x_coines_deinit(); + + return rslt; +} diff --git a/examples/interrupt_streaming_pc/Makefile b/examples/interrupt_streaming_pc/Makefile new file mode 100644 index 0000000..b0ad29e --- /dev/null +++ b/examples/interrupt_streaming_pc/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= interrupt_streaming_pc.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/interrupt_streaming_pc/interrupt_streaming_pc.c b/examples/interrupt_streaming_pc/interrupt_streaming_pc.c new file mode 100644 index 0000000..3404a77 --- /dev/null +++ b/examples/interrupt_streaming_pc/interrupt_streaming_pc.c @@ -0,0 +1,612 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file interrupt_streaming.c + * @brief Example file to stream bmi08x sensor data using LIB COINES + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*! @brief Sample file how to stream bmi08x sensor data based on data ready interrupt using LIB COINES */ + +/*********************************************************************/ +/* macro definitions */ +/*********************************************************************/ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! accel streaming response buffer */ +uint8_t bmi08x_accel_stream_buffer[COINES_STREAM_RSP_BUF_SIZE]; + +/*! gyro streaming response buffer */ +uint8_t bmi08x_gyro_stream_buffer[COINES_STREAM_RSP_BUF_SIZE]; + +/*! bmi08x accel int config */ +struct bmi08x_accel_int_channel_cfg accel_int_config; + +/*! bmi08x gyro int config */ +struct bmi08x_gyro_int_channel_cfg gyro_int_config; + +/*!accel streaming configuration */ +struct coines_streaming_config accel_stream_config; + +/*! gyro stream configuration*/ +struct coines_streaming_config gyro_stream_config; + +/*! streaming accel sensor register block */ +struct coines_streaming_blocks accel_stream_block; + +/*! streaming gyro sensor register block */ +struct coines_streaming_blocks gyro_stream_block; + +/*********************************************************************/ +/* function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Gravity. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This internal API is used to send stream settings + */ +static void send_stream_settings(void); + +/*! + * @brief This internal API is used to read sensor data + */ +void read_sensor_data(void); + +/*! + * @brief This internal API is used to initialize the bmi08x sensor + */ +static int8_t init_bmi08x(void); + +/*! + * @brief This internal API is used to enable the bmi08x interrupt + */ +static int8_t enable_bmi08x_interrupt(); + +/*! + * @brief This internal API is used to disable the bmi08x interrupt + */ +static int8_t disable_bmi08x_interrupt(); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to send stream settings + * + * @param[in] void + * + * @return void + * + */ +static void send_stream_settings() +{ + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + accel_stream_config.intf = COINES_SENSOR_INTF_I2C; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + accel_stream_config.intf = COINES_SENSOR_INTF_SPI; + } + + accel_stream_config.i2c_bus = COINES_I2C_BUS_0; /*if intf is I2C */ + accel_stream_config.spi_bus = COINES_SPI_BUS_0; /* if intf is SPI */ + + /*for I2C */ + accel_stream_config.dev_addr = BMI08X_ACCEL_I2C_ADDR_PRIMARY; + accel_stream_config.cs_pin = COINES_SHUTTLE_PIN_8; + accel_stream_config.int_pin = COINES_SHUTTLE_PIN_21; + accel_stream_config.int_timestamp = 1; + accel_stream_block.no_of_blocks = 1; + accel_stream_block.reg_start_addr[0] = BMI08X_REG_ACCEL_X_LSB; /*accel data start address */ + + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + accel_stream_block.no_of_data_bytes[0] = 6; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + accel_stream_block.no_of_data_bytes[0] = 7; /* actual data length is 6 bytes 1 byte needed to initiate the spi + * communication */ + } + + coines_config_streaming(1, &accel_stream_config, &accel_stream_block); + + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + gyro_stream_config.intf = COINES_SENSOR_INTF_I2C; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + gyro_stream_config.intf = COINES_SENSOR_INTF_SPI; + } + + gyro_stream_config.i2c_bus = COINES_I2C_BUS_0; /*if intf is I2C */ + gyro_stream_config.spi_bus = COINES_SPI_BUS_0; /* if intf is SPI */ + + /*for I2C */ + gyro_stream_config.dev_addr = BMI08X_GYRO_I2C_ADDR_PRIMARY; + gyro_stream_config.cs_pin = COINES_SHUTTLE_PIN_14; + gyro_stream_config.int_pin = COINES_SHUTTLE_PIN_22; + gyro_stream_config.int_timestamp = 1; + gyro_stream_block.no_of_blocks = 1; + gyro_stream_block.reg_start_addr[0] = BMI08X_REG_GYRO_X_LSB; /*gyro data start address */ + gyro_stream_block.no_of_data_bytes[0] = 6; + + coines_config_streaming(2, &gyro_stream_config, &gyro_stream_block); +} + +/*! + * @brief This internal API is used to read sensor data + * + * @param[in] void + * + * @return void + * + */ +void read_sensor_data() +{ + int16_t rslt; + uint8_t lsb, msb; + int16_t ax, ay, az, gx, gy, gz; + uint32_t valid_sample_count = 0; + uint32_t packet_count = 0; + uint64_t accel_time_stamp = 0; + uint64_t gyro_time_stamp = 0; + int idx = 0; + int buffer_index = 0; + float x = 0.0, y = 0.0, z = 0.0; + + if (bmi08xdev.accel_cfg.power == BMI08X_ACCEL_PM_ACTIVE) + { + memset(&bmi08x_accel_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE); + rslt = coines_read_stream_sensor_data(1, 1, &bmi08x_accel_stream_buffer[0], &valid_sample_count); + if (rslt == COINES_SUCCESS) + { + buffer_index = 0; + printf("\nACCEL DATA \n"); + printf("Accel data in LSB units and Gravity data in m/s^2\n"); + printf("Accel data range : 16G for BMI085 and 24G for BMI088\n\n"); + + if (valid_sample_count > 100) + { + valid_sample_count = 100; + } + + for (idx = 0; idx < valid_sample_count; idx++) + { + packet_count = 0; + + packet_count |= bmi08x_accel_stream_buffer[buffer_index++] << 24; + packet_count |= bmi08x_accel_stream_buffer[buffer_index++] << 16; + packet_count |= bmi08x_accel_stream_buffer[buffer_index++] << 8; + packet_count |= bmi08x_accel_stream_buffer[buffer_index++]; + if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + buffer_index++; /*dummy byte; */ + } + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + ax = (msb << 8) | lsb; + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + ay = (msb << 8) | lsb; + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + az = (msb << 8) | lsb; + + if (accel_stream_config.int_timestamp) + { + accel_time_stamp = 0; + + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++] << 40; + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++] << 32; + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++] << 24; + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++] << 16; + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++] << 8; + accel_time_stamp |= (uint64_t)bmi08x_accel_stream_buffer[buffer_index++]; + } + + /* Timestamp in microseconds can be obtained by following formula + * Timestamp(us) = (48bit_timestamp / 30) + */ + printf("ACCEL[%d] Acc_Raw_X : %5d Acc_Raw_Y : %5d Acc_Raw_Z : %5d T(us) : %ld ", + packet_count, + ax, + ay, + az, + (long)(accel_time_stamp / 30)); + + if (bmi08xdev.variant == BMI085_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 16G range. */ + x = lsb_to_mps2(ax, 16, 16); + y = lsb_to_mps2(ay, 16, 16); + z = lsb_to_mps2(az, 16, 16); + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 24G range. */ + x = lsb_to_mps2(ax, 24, 16); + y = lsb_to_mps2(ay, 24, 16); + z = lsb_to_mps2(az, 24, 16); + } + + /* Print the data in m/s2. */ + printf("\t Acc_ms2_X = %4.2f Acc_ms2_Y = %4.2f Acc_ms2_Z = %4.2f\n", x, y, z); + } + } + } + + if (bmi08xdev.gyro_cfg.power == BMI08X_GYRO_PM_NORMAL) + { + memset(&bmi08x_gyro_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE); + rslt = coines_read_stream_sensor_data(2, 1, &bmi08x_gyro_stream_buffer[0], &valid_sample_count); + if (rslt == COINES_SUCCESS) + { + buffer_index = 0; + printf("\n\nGYRO DATA \n"); + printf("Gyro data in LSB units and degrees per second\n"); + printf("Gyro data range : 250 dps for BMI085 and BMI088\n\n"); + + if (valid_sample_count > 100) + { + valid_sample_count = 100; + } + + for (idx = 0; idx < valid_sample_count; idx++) + { + + packet_count = 0; + + packet_count |= bmi08x_gyro_stream_buffer[buffer_index++] << 24; + packet_count |= bmi08x_gyro_stream_buffer[buffer_index++] << 16; + packet_count |= bmi08x_gyro_stream_buffer[buffer_index++] << 8; + packet_count |= bmi08x_gyro_stream_buffer[buffer_index++]; + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gx = (msb << 8) | lsb; + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gy = (msb << 8) | lsb; + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gz = (msb << 8) | lsb; + + if (gyro_stream_config.int_timestamp) + { + gyro_time_stamp = 0; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++] << 40; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++] << 32; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++] << 24; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++] << 16; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++] << 8; + gyro_time_stamp |= (uint64_t)bmi08x_gyro_stream_buffer[buffer_index++]; + } + + /* Timestamp in microseconds can be obtained by following formula + * Timestamp(us) = (48bit_timestamp / 30) + */ + printf("GYRO[%d] Gyr_Raw_X : %5d Gyr_Raw_Y : %5d Gyr_Raw_Z : %5d T(us) : %ld ", + packet_count, + gx, + gy, + gz, + (long)(gyro_time_stamp / 30)); + + /* Converting lsb to degree per second for 16 bit gyro at 250 dps range. */ + x = lsb_to_dps(gx, 250, 16); + y = lsb_to_dps(gy, 250, 16); + z = lsb_to_dps(gz, 250, 16); + + /* Print the data in dps. */ + printf("\t Gyr_DPS_X = %4.2f Gyr_DPS_Y = %4.2f Gyr_DPS_Z = %4.2f\n", x, y, z); + } + } + } +} + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + printf("BMI08x initialization success !\n"); + printf("Accel chip ID - 0x%x\n", bmi08xdev.accel_chip_id); + printf("Gyro chip ID - 0x%x\n", bmi08xdev.gyro_chip_id); + coines_delay_msec(100); + + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + + if ((rslt == BMI08X_OK) && + (bmi08xdev.accel_cfg.power == BMI08X_ACCEL_PM_SUSPEND && + (bmi08xdev.gyro_cfg.power == BMI08X_GYRO_PM_SUSPEND || + bmi08xdev.gyro_cfg.power == BMI08X_GYRO_PM_DEEP_SUSPEND))) + { + printf("Accel and gyro sensors are in suspend mode\n Use them in active/normal mode !!"); + } + } + + return rslt; +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_DATA_RDY; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + if (rslt == BMI08X_OK) + { + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_DATA_RDY; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable gyro data ready interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + } + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_DATA_RDY; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + if (rslt == BMI08X_OK) + { + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_DATA_RDY; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable gyro data ready interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + } + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(void) +{ + int8_t rslt; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + /* Initialize the sensor */ + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + /* Send streaming settings */ + send_stream_settings(); + + /* Enables 48-bit system timer */ + coines_trigger_timer(COINES_TIMER_START, COINES_TIMESTAMP_ENABLE); + + /* Wait for 10 ms */ + coines_delay_msec(10); + + /* Start interrupt streaming */ + coines_start_stop_streaming(COINES_STREAMING_MODE_INTERRUPT, COINES_STREAMING_START); + + /* Enable data ready interrupts */ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + if (rslt == BMI08X_OK) + { + /* Read sensor data */ + read_sensor_data(); + + /* Stop interrupt streaming */ + coines_start_stop_streaming(COINES_STREAMING_MODE_INTERRUPT, COINES_STREAMING_STOP); + + /* Stop timer */ + coines_trigger_timer(COINES_TIMER_STOP, COINES_TIMESTAMP_DISABLE); + + /* Wait for 100 ms */ + coines_delay_msec(100); + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + } + + bmi08x_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) +{ + float gravity; + + float half_scale = ((1 << bit_width) / 2.0f); + + gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); + + return gravity; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); +} diff --git a/examples/polling_streaming_pc/Makefile b/examples/polling_streaming_pc/Makefile new file mode 100644 index 0000000..425d106 --- /dev/null +++ b/examples/polling_streaming_pc/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= polling_streaming_pc.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/polling_streaming_pc/polling_streaming_pc.c b/examples/polling_streaming_pc/polling_streaming_pc.c new file mode 100644 index 0000000..d791482 --- /dev/null +++ b/examples/polling_streaming_pc/polling_streaming_pc.c @@ -0,0 +1,419 @@ +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file polling_streaming.c + * @brief Example file to stream bmi08x sensor data using LIB COINES + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*********************************************************************/ +/* macro definitions */ +/*********************************************************************/ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ + +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! accel streaming response buffer */ +uint8_t bmi08x_accel_stream_buffer[COINES_STREAM_RSP_BUF_SIZE]; + +/*! gyro streaming response buffer */ +uint8_t bmi08x_gyro_stream_buffer[COINES_STREAM_RSP_BUF_SIZE]; + +/*********************************************************************/ +/* function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Gravity. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This internal API is used to initialize the bmi08x sensor with default + */ +static int8_t init_bmi08x(void); + +/*! + * @brief This internal API is used to send stream settings + */ +static void send_stream_settings(void); + +/*! This internal API is used to read sensor data */ +void read_sensor_data(void); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to send stream settings + * + * @param[in] void + * + * @return void + * + */ +static void send_stream_settings(void) +{ + struct coines_streaming_config stream_config; + + struct coines_streaming_blocks stream_block; + + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + stream_config.intf = COINES_SENSOR_INTF_I2C; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + stream_config.intf = COINES_SENSOR_INTF_SPI; + } + + stream_config.i2c_bus = COINES_I2C_BUS_0; /* if intf is I2C */ + stream_config.spi_bus = COINES_SPI_BUS_0; /* if intf is SPI */ + + /* For I2C */ + stream_config.dev_addr = BMI08X_ACCEL_I2C_ADDR_PRIMARY; + stream_config.cs_pin = COINES_SHUTTLE_PIN_8; + stream_config.sampling_time = 625; /* 1.6 khz */ + + /* 1 micro second / 2 milli second */ + stream_config.sampling_units = COINES_SAMPLING_TIME_IN_MICRO_SEC; /* micro second */ + stream_block.no_of_blocks = 1; + stream_block.reg_start_addr[0] = BMI08X_REG_ACCEL_X_LSB; /* Accel data start address */ + + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + stream_block.no_of_data_bytes[0] = 6; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + /* Actual data length is 6 bytes 1 byte needed to + * initiate the SPI communication */ + stream_block.no_of_data_bytes[0] = 7; + } + + coines_config_streaming(1, &stream_config, &stream_block); + + if (bmi08xdev.intf == BMI08X_I2C_INTF) + { + stream_config.intf = COINES_SENSOR_INTF_I2C; + } + else if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + stream_config.intf = COINES_SENSOR_INTF_SPI; + } + + stream_config.i2c_bus = COINES_I2C_BUS_0; /* if intf is I2C */ + stream_config.spi_bus = COINES_SPI_BUS_0; /* if intf is SPI */ + + /* For I2C */ + stream_config.dev_addr = BMI08X_GYRO_I2C_ADDR_PRIMARY; + stream_config.cs_pin = COINES_SHUTTLE_PIN_14; + stream_config.sampling_time = 500; /* 2 Khz */ + + /* 1 micro second / 2 milli second */ + stream_config.sampling_units = COINES_SAMPLING_TIME_IN_MICRO_SEC; /* micro second */ + stream_block.no_of_blocks = 1; + stream_block.reg_start_addr[0] = BMI08X_REG_GYRO_X_LSB; /* gyro data start address */ + stream_block.no_of_data_bytes[0] = 6; + + coines_config_streaming(2, &stream_config, &stream_block); +} + +/*! + * @brief This internal API is used to read sensor data + * + * @param[in] void + * + * @return void + * + */ +void read_sensor_data(void) +{ + int16_t rslt; + uint8_t lsb, msb; + int16_t ax, ay, az, gx, gy, gz; + uint32_t valid_sample_count = 0; + int idx = 0; + int buffer_index = 0; + float x = 0.0, y = 0.0, z = 0.0; + + memset(&bmi08x_accel_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE); + rslt = coines_read_stream_sensor_data(1, 1, &bmi08x_accel_stream_buffer[0], &valid_sample_count); + if (rslt == COINES_SUCCESS) + { + buffer_index = 0; + printf("\nACCEL DATA \n"); + printf("Accel data in LSB units and Gravity data in m/s^2\n"); + printf("Accel data range : 16G for BMI085 and 24G for BMI088\n\n"); + + if (valid_sample_count > 100) + { + valid_sample_count = 100; + } + + for (idx = 0; idx < valid_sample_count; idx++) + { + if (bmi08xdev.intf == BMI08X_SPI_INTF) + { + buffer_index++; /*dummy byte; ignore for SPI */ + } + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + ax = (msb << 8) | lsb; + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + ay = (msb << 8) | lsb; + + lsb = bmi08x_accel_stream_buffer[buffer_index++]; + msb = bmi08x_accel_stream_buffer[buffer_index++]; + az = (msb << 8) | lsb; + + printf("ACCEL[%d] Acc_Raw_X : %-5d Acc_Raw_Y : %-5d Acc_Raw_Z : %-5d ", idx, ax, ay, az); + + if (bmi08xdev.variant == BMI085_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 16G range. */ + x = lsb_to_mps2(ax, 16, 16); + y = lsb_to_mps2(ay, 16, 16); + z = lsb_to_mps2(az, 16, 16); + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 24G range. */ + x = lsb_to_mps2(ax, 24, 16); + y = lsb_to_mps2(ay, 24, 16); + z = lsb_to_mps2(az, 24, 16); + } + + /* Print the data in m/s2. */ + printf("\t Acc_ms2_X = %4.2f Acc_ms2_Y = %4.2f Acc_ms2_Z = %4.2f\n", x, y, z); + } + } + + memset(&bmi08x_gyro_stream_buffer[0], 0, COINES_STREAM_RSP_BUF_SIZE); + rslt = coines_read_stream_sensor_data(2, 1, &bmi08x_gyro_stream_buffer[0], &valid_sample_count); + if (rslt == COINES_SUCCESS) + { + buffer_index = 0; + printf("\n\nGYRO DATA \n"); + printf("Gyro data in LSB units and degrees per second\n"); + printf("Gyro data range : 250 dps for BMI085 and BMI088\n\n"); + + if (valid_sample_count > 100) + { + valid_sample_count = 100; + } + + for (idx = 0; idx < valid_sample_count; idx++) + { + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gx = (msb << 8) | lsb; + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gy = (msb << 8) | lsb; + + lsb = bmi08x_gyro_stream_buffer[buffer_index++]; + msb = bmi08x_gyro_stream_buffer[buffer_index++]; + gz = (msb << 8) | lsb; + + printf("GYRO[%d] Gyr_Raw_X : %-5d Gyr_Raw_Y : %-5d Gyr_Raw_Z : %-5d ", idx, gx, gy, gz); + + /* Converting lsb to degree per second for 16 bit gyro at 250 dps range. */ + x = lsb_to_dps(gx, 250, 16); + y = lsb_to_dps(gy, 250, 16); + z = lsb_to_dps(gz, 250, 16); + + /* Print the data in dps. */ + printf("\t Gyr_DPS_X = %4.2f Gyr_DPS_Y = %4.2f Gyr_DPS_Z = %4.2f\n", x, y, z); + } + } +} + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + coines_delay_msec(100); + + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(void) +{ + int8_t rslt; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + if (rslt == BMI08X_OK) + { + /* Send streaming settings */ + send_stream_settings(); + + /* Start polling streaming */ + coines_start_stop_streaming(COINES_STREAMING_MODE_POLLING, COINES_STREAMING_START); + + /* Read sensor data */ + read_sensor_data(); + + /* Stop polling streaming */ + coines_start_stop_streaming(COINES_STREAMING_MODE_POLLING, COINES_STREAMING_STOP); + + /* Wait for 100 ms */ + coines_delay_msec(100); + } + } + + bmi08x_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) +{ + float gravity; + + float half_scale = ((1 << bit_width) / 2.0f); + + gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); + + return gravity; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); +} diff --git a/examples/read_sensor_data/Makefile b/examples/read_sensor_data/Makefile new file mode 100644 index 0000000..34bb165 --- /dev/null +++ b/examples/read_sensor_data/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_sensor_data.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c \ +../common/common.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk \ No newline at end of file diff --git a/examples/generic/read_sensor_data/read_sensor_data.c b/examples/read_sensor_data/read_sensor_data.c similarity index 63% rename from examples/generic/read_sensor_data/read_sensor_data.c rename to examples/read_sensor_data/read_sensor_data.c index 646037a..98f25d9 100644 --- a/examples/generic/read_sensor_data/read_sensor_data.c +++ b/examples/read_sensor_data/read_sensor_data.c @@ -1,340 +1,383 @@ -/** - * Copyright (C) 2018 Bosch Sensortec GmbH - * - * SPDX-License-Identifier: BSD-3-Clause - * - * @file bmi08x_read_sensor_data.c - * @brief Sample file how to read bmi08x sensor data - * - */ - -/*********************************************************************/ -/* system header files */ -/*********************************************************************/ -#include -#include -#include - -/*********************************************************************/ -/* own header files */ -/*********************************************************************/ -#include "bmi08x.h" -#include "bmi08x_common.h" - -/*********************************************************************/ -/* macro definitions */ -/*********************************************************************/ - -/*! Earth's gravity in m/s^2 */ -#define GRAVITY_EARTH (9.80665f) - -/*********************************************************************/ -/* global variables */ -/*********************************************************************/ -/*! @brief This structure containing relevant bmi08x info */ -struct bmi08x_dev bmi08xdev; - -/*! @brief variable to hold the bmi08x accel data */ -struct bmi08x_sensor_data bmi08x_accel; - -/*! @brief variable to hold the bmi08x gyro data */ -struct bmi08x_sensor_data bmi08x_gyro; - -/*! bmi08x accel int config */ -struct bmi08x_accel_int_channel_cfg accel_int_config; - -/*! bmi08x gyro int config */ -struct bmi08x_gyro_int_channel_cfg gyro_int_config; - -/*********************************************************************/ -/* static function declarations */ -/*********************************************************************/ - -/*! - * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for - * range 2G, 4G, 8G or 16G. - * - * @param[in] val : LSB from each axis. - * @param[in] g_range : Gravity range. - * @param[in] bit_width : Resolution for accel. - * - * @return Gravity. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - * - * @param[in] val : LSB from each axis. - * @param[in] dps : Degree per second. - * @param[in] bit_width : Resolution for gyro. - * - * @return Degree per second. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); - -/*! - * @brief This internal API is used to initialize the bmi08x sensor with default - */ -static int8_t init_bmi08x(void); - -/*********************************************************************/ -/* functions */ -/*********************************************************************/ - -/*! - * @brief This internal API is used to initializes the bmi08x sensor - * settings like power mode and OSRS settings. - * - * @param[in] void - * - * @return void - * - */ -static int8_t init_bmi08x(void) -{ - int8_t rslt; - - rslt = bmi08a_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_init", rslt); - - if (rslt == BMI08X_OK) - { - rslt = bmi08g_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_init", rslt); - } - - if (rslt == BMI08X_OK) - { - bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; - - if (bmi08xdev.variant == BMI085_VARIANT) - { - bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; - } - else if (bmi08xdev.variant == BMI088_VARIANT) - { - bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; - } - - bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; /*user_accel_power_modes[user_bmi088_accel_low_power]; */ - bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; /* Bandwidth and OSR are same */ - - rslt = bmi08a_set_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_accel); - rslt = bmi08a_set_meas_conf(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_accel); - - bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; - bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; - bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; - bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; - - rslt = bmi08g_set_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_gyro); - - rslt = bmi08g_set_meas_conf(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_gyro); - } - - return rslt; - -} - -/*! - * @brief This API is used to enable bmi08x interrupt - * - * @param[in] void - * - * @return void - * - */ -static int8_t enable_bmi08x_interrupt() -{ - int8_t rslt; - - /*set accel interrupt pin configuration*/ - accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; - accel_int_config.int_type = BMI08X_ACCEL_DATA_RDY_INT; - accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - - /*Enable accel data ready interrupt channel*/ - rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); - - if (rslt == BMI08X_OK) - { - /*set gyro interrupt pin configuration*/ - gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; - gyro_int_config.int_type = BMI08X_GYRO_DATA_RDY_INT; - gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - - /*Enable gyro data ready interrupt channel*/ - rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); - } - - return rslt; -} - -/*! - * @brief This API is used to disable bmi08x interrupt - * - * @param[in] void - * - * @return void - * - */ -static int8_t disable_bmi08x_interrupt() -{ - int8_t rslt; - - /*set accel interrupt pin configuration*/ - accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; - accel_int_config.int_type = BMI08X_ACCEL_DATA_RDY_INT; - accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - - /*Disable accel data ready interrupt channel*/ - rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); - - if (rslt == BMI08X_OK) - { - /*set gyro interrupt pin configuration*/ - gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; - gyro_int_config.int_type = BMI08X_GYRO_DATA_RDY_INT; - gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - - /*Disable gyro data ready interrupt channel*/ - rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); - } - - return rslt; -} - -/*! - * @brief Main Function where the execution getting started to test the code. - * - * @return status - * - */ -int main(void) -{ - int8_t rslt; - - uint8_t times_to_read = 0; - float x, y, z; - - /* Interface given as parameter - * For I2C : BMI08X_I2C_INTF - * For SPI : BMI08X_SPI_INTF - * Sensor variant given as parameter - * For BMI085 : BMI085_VARIANT - * For BMI088 : BMI088_VARIANT - */ - rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_SPI_INTF, BMI085_VARIANT); - - if (rslt == BMI08X_OK) - { - rslt = init_bmi08x(); - - /*Enable data ready interrupts*/ - rslt = enable_bmi08x_interrupt(); - - if (rslt == BMI08X_OK) - { - printf("\nACCEL DATA\n"); - printf("Accel data in LSB units and Gravity data in m/s^2\n"); - while (times_to_read < 10) - { - rslt = bmi08a_get_data(&bmi08x_accel, &bmi08xdev); - printf("ACCEL[%d] X : %d raw LSB\t Y : %d raw LSB\t Z : %d raw LSB\n", - times_to_read, - bmi08x_accel.x, - bmi08x_accel.y, - bmi08x_accel.z); - - /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(bmi08x_accel.x, 2, 16); - y = lsb_to_mps2(bmi08x_accel.y, 2, 16); - z = lsb_to_mps2(bmi08x_accel.z, 2, 16); - - /* Print the data in m/s2. */ - printf("\t Gravity-x = %4.2f, Gravity-y = %4.2f, Gravity-z = %4.2f\n", x, y, z); - - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_accel); - times_to_read = times_to_read + 1; - } - - times_to_read = 0; - - printf("\n\nGYRO DATA\n"); - printf("Gyro data in LSB units and degrees per second\n"); - while (times_to_read < 10) - { - rslt = bmi08g_get_data(&bmi08x_gyro, &bmi08xdev); - printf("GYRO[%d] X : %d raw LSB\t Y : %d raw LSB\t Z : %d raw LSB\n", - times_to_read, - bmi08x_gyro.x, - bmi08x_gyro.y, - bmi08x_gyro.z); - - /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(bmi08x_gyro.x, 2000, 16); - y = lsb_to_dps(bmi08x_gyro.y, 2000, 16); - z = lsb_to_dps(bmi08x_gyro.z, 2000, 16); - - /* Print the data in dps. */ - printf("\t DPS-x = %4.2f, DPS-y = %4.2f, DPS-z = %4.2f\n", x, y, z); - - bmi08xdev.delay_us(10, bmi08xdev.intf_ptr_gyro); - times_to_read = times_to_read + 1; - } - } - - /*disable data ready interrupts*/ - rslt = disable_bmi08x_interrupt(); - } - - return rslt; -} - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) -{ - float gravity; - - uint32_t half_scale = ((1 << bit_width) / 2); - - gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); - - return gravity; -} - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); -} +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file read_sensor_data.c + * @brief Example file how to read bmi08x sensor data using LIB COINES + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*********************************************************************/ +/* macro definitions */ +/*********************************************************************/ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! @brief variable to hold the bmi08x accel data */ +struct bmi08x_sensor_data bmi08x_accel; + +/*! @brief variable to hold the bmi08x gyro data */ +struct bmi08x_sensor_data bmi08x_gyro; + +/*! bmi08x accel int config */ +struct bmi08x_accel_int_channel_cfg accel_int_config; + +/*! bmi08x gyro int config */ +struct bmi08x_gyro_int_channel_cfg gyro_int_config; + +/*********************************************************************/ +/* static function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Gravity. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This internal API is used to initialize the bmi08x sensor with default + */ +static int8_t init_bmi08x(void); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor + * settings like power mode and OSRS settings. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + } + + if (rslt == BMI08X_OK) + { + bmi08xdev.accel_cfg.odr = BMI08X_ACCEL_ODR_1600_HZ; + + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; /*user_accel_power_modes[user_bmi088_accel_low_power]; */ + bmi08xdev.accel_cfg.bw = BMI08X_ACCEL_BW_NORMAL; /* Bandwidth and OSR are same */ + + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08a_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_meas_conf", rslt); + coines_delay_msec(10); + + bmi08xdev.gyro_cfg.odr = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_250_DPS; + bmi08xdev.gyro_cfg.bw = BMI08X_GYRO_BW_230_ODR_2000_HZ; + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + coines_delay_msec(10); + + rslt = bmi08g_set_meas_conf(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_meas_conf", rslt); + coines_delay_msec(10); + } + + return rslt; + +} + +/*! + * @brief This API is used to enable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t enable_bmi08x_interrupt() +{ + int8_t rslt; + uint8_t data = 0; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_DATA_RDY; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + if (rslt == BMI08X_OK) + { + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_DATA_RDY; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Enable gyro data ready interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + + rslt = bmi08g_get_regs(BMI08X_REG_GYRO_INT3_INT4_IO_MAP, &data, 1, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_get_regs", rslt); + } + + return rslt; +} + +/*! + * @brief This API is used to disable bmi08x interrupt + * + * @param[in] void + * + * @return void + * + */ +static int8_t disable_bmi08x_interrupt() +{ + int8_t rslt; + + /* Set accel interrupt pin configuration */ + accel_int_config.int_channel = BMI08X_INT_CHANNEL_1; + accel_int_config.int_type = BMI08X_ACCEL_INT_DATA_RDY; + accel_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + accel_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + accel_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable accel data ready interrupt channel */ + rslt = bmi08a_set_int_config((const struct bmi08x_accel_int_channel_cfg*)&accel_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_int_config", rslt); + + if (rslt == BMI08X_OK) + { + /* Set gyro interrupt pin configuration */ + gyro_int_config.int_channel = BMI08X_INT_CHANNEL_3; + gyro_int_config.int_type = BMI08X_GYRO_INT_DATA_RDY; + gyro_int_config.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + gyro_int_config.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + gyro_int_config.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Disable gyro data ready interrupt channel */ + rslt = bmi08g_set_int_config((const struct bmi08x_gyro_int_channel_cfg *)&gyro_int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_int_config", rslt); + } + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(void) +{ + int8_t rslt; + + uint8_t times_to_read = 0; + float x = 0.0, y = 0.0, z = 0.0; + uint8_t status = 0; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + if (rslt == BMI08X_OK) + { + rslt = init_bmi08x(); + bmi08x_error_codes_print_result("init_bmi08x", rslt); + + /* Enable data ready interrupts */ + rslt = enable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("enable_bmi08x_interrupt", rslt); + + if (rslt == BMI08X_OK) + { + printf("\nACCEL DATA\n"); + printf("Accel data in LSB units and Gravity data in m/s^2\n"); + printf("Accel data range : 16G for BMI085 and 24G for BMI088\n\n"); + + while (times_to_read < 10) + { + rslt = bmi08a_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_data_int_status", rslt); + + if (status & BMI08X_ACCEL_DATA_READY_INT) + { + rslt = bmi08a_get_data(&bmi08x_accel, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_data", rslt); + + printf("ACCEL[%d] Acc_Raw_X : %d Acc_Raw_Y : %d Acc_Raw_Z : %d ", + times_to_read, + bmi08x_accel.x, + bmi08x_accel.y, + bmi08x_accel.z); + + if (bmi08xdev.variant == BMI085_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 16G range. */ + x = lsb_to_mps2(bmi08x_accel.x, 16, 16); + y = lsb_to_mps2(bmi08x_accel.y, 16, 16); + z = lsb_to_mps2(bmi08x_accel.z, 16, 16); + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 24G range. */ + x = lsb_to_mps2(bmi08x_accel.x, 24, 16); + y = lsb_to_mps2(bmi08x_accel.y, 24, 16); + z = lsb_to_mps2(bmi08x_accel.z, 24, 16); + } + + /* Print the data in m/s2. */ + printf("\t Acc_ms2_X = %4.2f, Acc_ms2_Y = %4.2f, Acc_ms2_Z = %4.2f\n", x, y, z); + + coines_delay_msec(10); + times_to_read = times_to_read + 1; + } + } + + times_to_read = 0; + + printf("\n\nGYRO DATA\n"); + printf("Gyro data in LSB units and degrees per second\n"); + printf("Gyro data range : 250 dps for BMI085 and BMI088\n\n"); + + while (times_to_read < 10) + { + rslt = bmi08g_get_data_int_status(&status, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_get_data_int_status", rslt); + + if (status & BMI08X_GYRO_DATA_READY_INT) + { + rslt = bmi08g_get_data(&bmi08x_gyro, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_get_data", rslt); + + printf("GYRO[%d] Gyr_Raw_X : %d Gyr_Raw_Y : %d Gyr_Raw_Z : %d ", + times_to_read, + bmi08x_gyro.x, + bmi08x_gyro.y, + bmi08x_gyro.z); + + /* Converting lsb to degree per second for 16 bit gyro at 250 dps range. */ + x = lsb_to_dps(bmi08x_gyro.x, 250, 16); + y = lsb_to_dps(bmi08x_gyro.y, 250, 16); + z = lsb_to_dps(bmi08x_gyro.z, 250, 16); + + /* Print the data in dps. */ + printf("\t Gyr_DPS_X = %4.2f , Gyr_DPS_Y = %4.2f , Gyr_DPS_Z = %4.2f\n", x, y, z); + + coines_delay_msec(10); + times_to_read = times_to_read + 1; + } + } + } + + /* Disable data ready interrupts */ + rslt = disable_bmi08x_interrupt(); + bmi08x_error_codes_print_result("disable_bmi08x_interrupt", rslt); + } + + bmi08x_coines_deinit(); + + return rslt; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) +{ + float gravity; + + float half_scale = ((1 << bit_width) / 2.0f); + + gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); + + return gravity; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); +} diff --git a/examples/read_synchronized_data_mcu/Makefile b/examples/read_synchronized_data_mcu/Makefile new file mode 100644 index 0000000..070e3e8 --- /dev/null +++ b/examples/read_synchronized_data_mcu/Makefile @@ -0,0 +1,16 @@ +COINES_INSTALL_PATH ?= ../../../.. + +EXAMPLE_FILE ?= read_synchronized_data_mcu.c + +API_LOCATION ?= ../.. + +C_SRCS += \ +../common/common.c \ +$(API_LOCATION)/bmi08a.c \ +$(API_LOCATION)/bmi08g.c + +INCLUDEPATHS += \ +$(API_LOCATION) \ +../common + +include $(COINES_INSTALL_PATH)/coines.mk diff --git a/examples/generic/Readme.txt b/examples/read_synchronized_data_mcu/Readme.txt similarity index 98% rename from examples/generic/Readme.txt rename to examples/read_synchronized_data_mcu/Readme.txt index 20e3255..7f224ca 100644 --- a/examples/generic/Readme.txt +++ b/examples/read_synchronized_data_mcu/Readme.txt @@ -1,11 +1,11 @@ -To know more about Data Synchronization feature of BMI08x read 'DataSync.md' file in 'sensorAPI/bmi08x' folder. - -Short the INT1 and INT3 pins on the shuttle board before running the example. -(INT1 and INT3 are 2 pins which project on top of the BMI08x shuttle board) - -* Works for both BMI085 and BMI088 -* Update path where arm-none-eabi-gcc.exe exists to PATH environmental variable -* Command to run : mingw32-make TARGET=APP20 download -* In hterm, enable DTR signal to view output -* Various commands to run COINES examples : https://github.com/BoschSensortec/COINES/tree/master/template/c - +To know more about Data Synchronization feature of BMI08x read 'DataSync.md' file in 'sensorAPI/bmi08x' folder. + +Short the INT1 and INT3 pins on the shuttle board before running the example. +(INT1 and INT3 are 2 pins which project on top of the BMI08x shuttle board) + +* Works for both BMI085 and BMI088 +* Update path where arm-none-eabi-gcc.exe exists to PATH environmental variable +* Command to run : mingw32-make TARGET=APP20 download +* In hterm, enable DTR signal to view output +* Various commands to run COINES examples : https://github.com/BoschSensortec/COINES/tree/master/template/c + diff --git a/examples/generic/read_synchronized_data/bmi08x_read_synchronized_data_mcu.c b/examples/read_synchronized_data_mcu/read_synchronized_data_mcu.c similarity index 67% rename from examples/generic/read_synchronized_data/bmi08x_read_synchronized_data_mcu.c rename to examples/read_synchronized_data_mcu/read_synchronized_data_mcu.c index 1efa3a2..46e3728 100644 --- a/examples/generic/read_synchronized_data/bmi08x_read_synchronized_data_mcu.c +++ b/examples/read_synchronized_data_mcu/read_synchronized_data_mcu.c @@ -1,426 +1,448 @@ -/** - * Copyright (C) 2018 Bosch Sensortec GmbH - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 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. - * - * Neither the name of the copyright holder nor the names of the - * 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 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 - * - * The information provided is believed to be accurate and reliable. - * The copyright holder assumes no responsibility - * for the consequences of use - * of such information nor for any infringement of patents or - * other rights of third parties which may result from its use. - * No license is granted by implication or otherwise under any patent or - * patent rights of the copyright holder. - * - * @file read_synchronized_data_mcu.c - * @brief Sample file how to read bmi08x synchronized sensor data - * - */ - -/*********************************************************************/ -/* system header files */ -/*********************************************************************/ -#include -#include -#include -#include - -/*********************************************************************/ -/* own header files */ -/*********************************************************************/ -#include "bmi08x.h" -#include "bmi08x_common.h" - -/*********************************************************************/ -/* macro definitions */ -/*********************************************************************/ - -/*! Earth's gravity in m/s^2 */ -#define GRAVITY_EARTH (9.80665f) - -/*********************************************************************/ -/* global variables */ -/*********************************************************************/ -unsigned char data_sync_int = false; - -/*! @brief This structure containing relevant bmi08x info */ -struct bmi08x_dev bmi08xdev; - -/*! bmi08x int config */ -struct bmi08x_int_cfg int_config; - -/*Data Sync configuration object*/ -struct bmi08x_data_sync_cfg sync_cfg; - -/*! @brief variable to hold the bmi08x accel data */ -struct bmi08x_sensor_data bmi08x_accel; - -/*! @brief variable to hold the bmi08x gyro data */ -struct bmi08x_sensor_data bmi08x_gyro; - -/*********************************************************************/ -/* function declarations */ -/*********************************************************************/ - -/*! - * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for - * range 2G, 4G, 8G or 16G. - * - * @param[in] val : LSB from each axis. - * @param[in] g_range : Gravity range. - * @param[in] bit_width : Resolution for accel. - * - * @return Gravity. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - * - * @param[in] val : LSB from each axis. - * @param[in] dps : Degree per second. - * @param[in] bit_width : Resolution for gyro. - * - * @return Degree per second. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); - -/*! - * @brief This internal API is used to initialize the bmi08x sensor - */ -static int8_t init_bmi08x(void); - -/*! - * @brief BMI08x data sync. interrupt callback - */ -void bmi08x_data_sync_int(); - -/*********************************************************************/ -/* functions */ -/*********************************************************************/ - -/*! - * @brief This internal API is used to initializes the bmi08x sensor with default. - * - * @param[in] void - * - * @return void - * - */ -static int8_t init_bmi08x(void) -{ - int8_t rslt; - - /* Initialize bmi08a */ - rslt = bmi08a_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_init", rslt); - - /* Initialize bmi08g */ - rslt = bmi08g_init(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_init", rslt); - - if (rslt == BMI08X_OK) - { - printf("BMI08x initialization success!\n"); - printf("Accel chip ID - 0x%x\n", bmi08xdev.accel_chip_id); - printf("Gyro chip ID - 0x%x\n", bmi08xdev.gyro_chip_id); - - /* Reset the accelerometer */ - rslt = bmi08a_soft_reset(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_soft_reset", rslt); - - /* Wait for 1 ms - delay taken care inside the function*/ - - /*! Max read/write length (maximum supported length is 32). - To be set by the user */ - bmi08xdev.read_write_len = 32; - - /*set accel power mode */ - bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; - rslt = bmi08a_set_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); - - if (rslt == BMI08X_OK) - { - bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; - rslt = bmi08g_set_power_mode(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); - } - - if ((bmi08xdev.accel_cfg.power == BMI08X_ACCEL_PM_ACTIVE) && - (bmi08xdev.gyro_cfg.power == BMI08X_GYRO_PM_NORMAL)) - { - printf("Uploading BMI08X data synchronization feature config !\n"); - - /*API uploads the bmi08x config file onto the device*/ - if (rslt == BMI08X_OK) - { - rslt = bmi08a_load_config_file(&bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_load_config_file", rslt); - - /* Wait for 150ms to enable the data synchronization --delay taken care inside the function */ - if (rslt == BMI08X_OK) - { - /*for data synchronization bandwidth and odr will be configured based on the selected sync mode */ - if (bmi08xdev.variant == BMI085_VARIANT) - { - /*assign accel range setting*/ - bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_4G; - } - else if (bmi08xdev.variant == BMI088_VARIANT) - { - bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; - } - - /*assign gyro range setting*/ - bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_2000_DPS; - - /*! Mode (0 = off, 1 = 400Hz, 2 = 1kHz, 3 = 2kHz) */ - sync_cfg.mode = BMI08X_ACCEL_DATA_SYNC_MODE_400HZ; - - rslt = bmi08a_configure_data_synchronization(sync_cfg, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_configure_data_synchronization", rslt); - } - } - - if (rslt == BMI08X_OK) - { - printf("BMI08x data synchronization feature configured !\n"); - } - else - { - printf("BMI08x data synchronization feature configuration failure!\n"); - } - } - } - - return rslt; -} - -/*! - * @brief This internal API is used to enable data synchronization interrupt. - * - * @return int8_t - * - */ -static int8_t enable_bmi08x_data_synchronization_interrupt() -{ - int8_t rslt = BMI08X_OK; - - /*set accel interrupt pin configuration*/ - /*configure host data ready interrupt */ - int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_1; - int_config.accel_int_config_1.int_type = BMI08X_ACCEL_SYNC_INPUT; - int_config.accel_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.accel_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.accel_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - - /*configure Accel syncronization input interrupt pin */ - int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_2; - int_config.accel_int_config_2.int_type = BMI08X_ACCEL_SYNC_DATA_RDY_INT; - int_config.accel_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.accel_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.accel_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - - /*set gyro interrupt pin configuration*/ - int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_3; - int_config.gyro_int_config_1.int_type = BMI08X_GYRO_DATA_RDY_INT; - int_config.gyro_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; - int_config.gyro_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.gyro_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - - int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_4; - int_config.gyro_int_config_2.int_type = BMI08X_GYRO_DATA_RDY_INT; - int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - int_config.gyro_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.gyro_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - - /* Enable synchronization interrupt pin */ - rslt = bmi08a_set_data_sync_int_config(&int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_data_sync_int_config", rslt); - - return rslt; -} - -/*! - * @brief This internal API is used to disable data synchronization interrupt. - * - * @param[in] void - * - * @return int8_t - * - */ -static int8_t disable_bmi08x_data_synchronization_interrupt() -{ - int8_t rslt; - - /*turn off the sync feature*/ - sync_cfg.mode = BMI08X_ACCEL_DATA_SYNC_MODE_OFF; - - rslt = bmi08a_configure_data_synchronization(sync_cfg, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_configure_data_synchronization", rslt); - - /* Wait for 150ms to enable the data synchronization --delay taken care inside the function */ - /* configure synchronization interrupt pins */ - if (rslt == BMI08X_OK) - { - /*set accel interrupt pin configuration*/ - /*configure host data ready interrupt */ - int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_1; - int_config.accel_int_config_1.int_type = BMI08X_ACCEL_SYNC_INPUT; - int_config.accel_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.accel_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.accel_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - - /*configure Accel synchronization input interrupt pin */ - int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_2; - int_config.accel_int_config_2.int_type = BMI08X_ACCEL_SYNC_DATA_RDY_INT; - int_config.accel_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.accel_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.accel_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - - /*set gyro interrupt pin configuration*/ - int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_3; - int_config.gyro_int_config_1.int_type = BMI08X_GYRO_DATA_RDY_INT; - int_config.gyro_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.gyro_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - int_config.gyro_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - - int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_4; - int_config.gyro_int_config_2.int_type = BMI08X_GYRO_DATA_RDY_INT; - int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; - int_config.gyro_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; - int_config.gyro_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; - - /* Disable synchronization interrupt pin */ - rslt = bmi08a_set_data_sync_int_config(&int_config, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_set_data_sync_int_config", rslt); - } - - return rslt; -} - -/*! - * @brief Main Function where the execution getting started to test the code. - * - * @return status - * - */ -int main(int argc, char *argv[]) -{ - int8_t rslt; - float x, y, z; - - /* Interface given as parameter - * For I2C : BMI08X_I2C_INTF - * For SPI : BMI08X_SPI_INTF - * Sensor variant given as parameter - * For BMI085 : BMI085_VARIANT - * For BMI088 : BMI088_VARIANT - */ - rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); - bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); - - /*initialize the sensors*/ - init_bmi08x(); - - /*Enable data ready interrupts*/ - enable_bmi08x_data_synchronization_interrupt(); - - if (data_sync_int == true) - { - data_sync_int = false; - - rslt = bmi08a_get_synchronized_data(&bmi08x_accel, &bmi08x_gyro, &bmi08xdev); - bmi08x_error_codes_print_result("bmi08a_get_synchronized_data", rslt); - - printf("\nACCEL X : %d\t Y : %d\t Z : %d\t;\t GYRO X : %d\t Y : %d\t Z : %d\t Timestamp : %lu\n", - bmi08x_accel.x, - bmi08x_accel.y, - bmi08x_accel.z, - bmi08x_gyro.x, - bmi08x_gyro.y, - bmi08x_gyro.z); - - /* Converting lsb to meter per second squared for 16 bit accelerometer at 2G range. */ - x = lsb_to_mps2(bmi08x_accel.x, 2, 16); - y = lsb_to_mps2(bmi08x_accel.y, 2, 16); - z = lsb_to_mps2(bmi08x_accel.z, 2, 16); - - /* Print the data in m/s2. */ - printf("Gravity-x = %4.2f, Gravity-y = %4.2f, Gravity-z = %4.2f\t", x, y, z); - - /* Converting lsb to degree per second for 16 bit gyro at 2000dps range. */ - x = lsb_to_dps(bmi08x_gyro.x, 2000, 16); - y = lsb_to_dps(bmi08x_gyro.y, 2000, 16); - z = lsb_to_dps(bmi08x_gyro.z, 2000, 16); - - /* Print the data in dps. */ - printf("DPS-x = %4.2f, DPS-y = %4.2f, DPS-z = %4.2f\n", x, y, z); - } - - /*disable data ready interrupts*/ - disable_bmi08x_data_synchronization_interrupt(); - - return rslt; -} - -/* BMI08x data sync. interrupt callback */ -void bmi08x_data_sync_int() -{ - data_sync_int = true; -} - -/*! - * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at - * range 2G, 4G, 8G or 16G. - */ -static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) -{ - float gravity; - - uint32_t half_scale = ((1 << bit_width) / 2); - - gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); - - return gravity; -} - -/*! - * @brief This function converts lsb to degree per second for 16 bit gyro at - * range 125, 250, 500, 1000 or 2000dps. - */ -static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) -{ - float half_scale = ((float)(1 << bit_width) / 2.0f); - - return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); -} +/** + * Copyright (C) 2020 Bosch Sensortec GmbH + * + * SPDX-License-Identifier: BSD-3-Clause + * + * @file read_synchronized_data_mcu.c + * @brief Example file how to read bmi08x sensor data using LIB COINES + * + */ + +/*********************************************************************/ +/* system header files */ +/*********************************************************************/ +#include +#include +#include +#include + +/*********************************************************************/ +/* own header files */ +/*********************************************************************/ +#include "coines.h" +#include "bmi08x.h" +#include "common.h" + +/*********************************************************************/ +/* macro definitions */ +/*********************************************************************/ + +/*! Earth's gravity in m/s^2 */ +#define GRAVITY_EARTH (9.80665f) + +/*********************************************************************/ +/* global variables */ +/*********************************************************************/ +unsigned char data_sync_int = false; + +/*! @brief This structure containing relevant bmi08x info */ +struct bmi08x_dev bmi08xdev; + +/*! bmi08x int config */ +struct bmi08x_int_cfg int_config; + +/*Data Sync configuration object*/ +struct bmi08x_data_sync_cfg sync_cfg; + +/*! @brief variable to hold the bmi08x accel data */ +struct bmi08x_sensor_data bmi08x_accel; + +/*! @brief variable to hold the bmi08x gyro data */ +struct bmi08x_sensor_data bmi08x_gyro; + +/*********************************************************************/ +/* function declarations */ +/*********************************************************************/ + +/*! + * @brief This internal function converts lsb to meter per second squared for 16 bit accelerometer for + * range 2G, 4G, 8G or 16G. + * + * @param[in] val : LSB from each axis. + * @param[in] g_range : Gravity range. + * @param[in] bit_width : Resolution for accel. + * + * @return Gravity. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width); + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + * + * @param[in] val : LSB from each axis. + * @param[in] dps : Degree per second. + * @param[in] bit_width : Resolution for gyro. + * + * @return Degree per second. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width); + +/*! + * @brief This internal API is used to initialize the bmi08x sensor + */ +static int8_t init_bmi08x(void); + +/*! + * @brief BMI08x data sync. interrupt callback + */ +void bmi08x_data_sync_int(); + +/*********************************************************************/ +/* functions */ +/*********************************************************************/ + +/*! + * @brief This internal API is used to initializes the bmi08x sensor with default. + * + * @param[in] void + * + * @return void + * + */ +static int8_t init_bmi08x(void) +{ + int8_t rslt; + + /* Initialize bmi08a */ + rslt = bmi08a_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_init", rslt); + + /* Initialize bmi08g */ + rslt = bmi08g_init(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_init", rslt); + + if (rslt == BMI08X_OK) + { + printf("BMI08x initialization success!\n"); + printf("Accel chip ID - 0x%x\n", bmi08xdev.accel_chip_id); + printf("Gyro chip ID - 0x%x\n", bmi08xdev.gyro_chip_id); + + /* Reset the accelerometer */ + rslt = bmi08a_soft_reset(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_soft_reset", rslt); + + /* Max read/write length (maximum supported length is 32). + To be set by the user */ + bmi08xdev.read_write_len = 32; + + /* Set accel power mode */ + bmi08xdev.accel_cfg.power = BMI08X_ACCEL_PM_ACTIVE; + rslt = bmi08a_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_power_mode", rslt); + + if (rslt == BMI08X_OK) + { + bmi08xdev.gyro_cfg.power = BMI08X_GYRO_PM_NORMAL; + rslt = bmi08g_set_power_mode(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08g_set_power_mode", rslt); + } + + if ((bmi08xdev.accel_cfg.power == BMI08X_ACCEL_PM_ACTIVE) && + (bmi08xdev.gyro_cfg.power == BMI08X_GYRO_PM_NORMAL)) + { + printf("Uploading BMI08X data synchronization feature config !\n"); + + /* API uploads the bmi08x config file onto the device */ + if (rslt == BMI08X_OK) + { + rslt = bmi08a_load_config_file(&bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_load_config_file", rslt); + + /* Wait for 150ms to enable the data synchronization --delay taken care inside the function */ + if (rslt == BMI08X_OK) + { + /* Assign accel range setting */ + if (bmi08xdev.variant == BMI085_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI085_ACCEL_RANGE_16G; + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + bmi08xdev.accel_cfg.range = BMI088_ACCEL_RANGE_24G; + } + + /* Assign gyro range setting */ + bmi08xdev.gyro_cfg.range = BMI08X_GYRO_RANGE_2000_DPS; + + /* Mode (0 = off, 1 = 400Hz, 2 = 1kHz, 3 = 2kHz) */ + sync_cfg.mode = BMI08X_ACCEL_DATA_SYNC_MODE_400HZ; + + rslt = bmi08a_configure_data_synchronization(sync_cfg, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_configure_data_synchronization", rslt); + } + } + + if (rslt == BMI08X_OK) + { + printf("BMI08x data synchronization feature configured !\n\n"); + } + else + { + printf("BMI08x data synchronization feature configuration failure!\n\n"); + } + } + } + + return rslt; +} + +/*! + * @brief This internal API is used to enable data synchronization interrupt. + * + * @return int8_t + * + */ +static int8_t enable_bmi08x_data_synchronization_interrupt() +{ + int8_t rslt = BMI08X_OK; + + /* Set accel interrupt pin configuration */ + /* Configure host data ready interrupt */ + #if defined(MCU_APP20) + int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_1; + #elif defined(MCU_APP30) + int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_2; + #endif + int_config.accel_int_config_1.int_type = BMI08X_ACCEL_SYNC_INPUT; + int_config.accel_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + int_config.accel_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.accel_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Configure Accel syncronization input interrupt pin */ + #if defined(MCU_APP20) + int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_2; + #elif defined(MCU_APP30) + int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_1; + #endif + int_config.accel_int_config_2.int_type = BMI08X_ACCEL_INT_SYNC_DATA_RDY; + int_config.accel_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + int_config.accel_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.accel_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + + /* Set gyro interrupt pin configuration */ + #if defined(MCU_APP20) + int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_3; + #elif defined(MCU_APP30) + int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_4; + #endif + int_config.gyro_int_config_1.int_type = BMI08X_GYRO_INT_DATA_RDY; + int_config.gyro_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_ENABLE; + int_config.gyro_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.gyro_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + + #if defined(MCU_APP20) + int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_4; + #elif defined(MCU_APP30) + int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_3; + #endif + int_config.gyro_int_config_2.int_type = BMI08X_GYRO_INT_DATA_RDY; + int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + int_config.gyro_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.gyro_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + + /* Enable synchronization interrupt pin */ + rslt = bmi08a_set_data_sync_int_config(&int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_data_sync_int_config", rslt); + + return rslt; +} + +/*! + * @brief This internal API is used to disable data synchronization interrupt. + * + * @param[in] void + * + * @return int8_t + * + */ +static int8_t disable_bmi08x_data_synchronization_interrupt() +{ + int8_t rslt; + + /*turn off the sync feature*/ + sync_cfg.mode = BMI08X_ACCEL_DATA_SYNC_MODE_OFF; + + rslt = bmi08a_configure_data_synchronization(sync_cfg, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_configure_data_synchronization", rslt); + + /* Wait for 150ms to enable the data synchronization --delay taken care inside the function */ + /* configure synchronization interrupt pins */ + if (rslt == BMI08X_OK) + { + /* Set accel interrupt pin configuration */ + /* Configure host data ready interrupt */ + #if defined(MCU_APP20) + int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_1; + #elif defined(MCU_APP30) + int_config.accel_int_config_1.int_channel = BMI08X_INT_CHANNEL_2; + #endif + int_config.accel_int_config_1.int_type = BMI08X_ACCEL_SYNC_INPUT; + int_config.accel_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + int_config.accel_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.accel_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Configure Accel synchronization input interrupt pin */ + #if defined(MCU_APP20) + int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_2; + #elif defined(MCU_APP30) + int_config.accel_int_config_2.int_channel = BMI08X_INT_CHANNEL_1; + #endif + int_config.accel_int_config_2.int_type = BMI08X_ACCEL_INT_SYNC_DATA_RDY; + int_config.accel_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + int_config.accel_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.accel_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + /* Set gyro interrupt pin configuration */ + #if defined(MCU_APP20) + int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_3; + #elif defined(MCU_APP30) + int_config.gyro_int_config_1.int_channel = BMI08X_INT_CHANNEL_4; + #endif + int_config.gyro_int_config_1.int_type = BMI08X_GYRO_INT_DATA_RDY; + int_config.gyro_int_config_1.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.gyro_int_config_1.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + int_config.gyro_int_config_1.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + + #if defined(MCU_APP20) + int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_4; + #elif defined(MCU_APP30) + int_config.gyro_int_config_2.int_channel = BMI08X_INT_CHANNEL_3; + #endif + int_config.gyro_int_config_2.int_type = BMI08X_GYRO_INT_DATA_RDY; + int_config.gyro_int_config_2.int_pin_cfg.enable_int_pin = BMI08X_DISABLE; + int_config.gyro_int_config_2.int_pin_cfg.lvl = BMI08X_INT_ACTIVE_HIGH; + int_config.gyro_int_config_2.int_pin_cfg.output_mode = BMI08X_INT_MODE_PUSH_PULL; + + /* Disable synchronization interrupt pin */ + rslt = bmi08a_set_data_sync_int_config(&int_config, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_set_data_sync_int_config", rslt); + } + + return rslt; +} + +/*! + * @brief Main Function where the execution getting started to test the code. + * + * @return status + * + */ +int main(int argc, char *argv[]) +{ + int8_t rslt; + float x = 0.0, y = 0.0, z = 0.0; + + /* Interface given as parameter + * For I2C : BMI08X_I2C_INTF + * For SPI : BMI08X_SPI_INTF + * Sensor variant given as parameter + * For BMI085 : BMI085_VARIANT + * For BMI088 : BMI088_VARIANT + */ + rslt = bmi08x_interface_init(&bmi08xdev, BMI08X_I2C_INTF, BMI085_VARIANT); + bmi08x_error_codes_print_result("bmi08x_interface_init", rslt); + + /* Initialize the sensors */ + init_bmi08x(); + +#if defined(MCU_APP20) + coines_attach_interrupt(COINES_SHUTTLE_PIN_20, bmi08x_data_sync_int, COINES_PIN_INTERRUPT_FALLING_EDGE); +#elif defined(MCU_APP30) + coines_attach_interrupt(COINES_MINI_SHUTTLE_PIN_1_6, bmi08x_data_sync_int, COINES_PIN_INTERRUPT_FALLING_EDGE); +#endif + + /* Enable data ready interrupts */ + enable_bmi08x_data_synchronization_interrupt(); + uint32_t start_time = coines_get_millis(); + + printf("Accel data range : 16G for BMI085 and 24G for BMI088\n"); + printf("Gyro data range : 250 dps for BMI085 and BMI088\n\n"); + + /* Run data synchronization for 100ms before disabling interrupts */ + while (coines_get_millis() - start_time < 100) + { + if (data_sync_int == true) + { + data_sync_int = false; + + rslt = bmi08a_get_synchronized_data(&bmi08x_accel, &bmi08x_gyro, &bmi08xdev); + bmi08x_error_codes_print_result("bmi08a_get_synchronized_data", rslt); + + printf( + "\nACCEL Acc_Raw_X : %d Acc_Raw_Y : %d Acc_Raw_Z : %d ; GYRO Gyr_Raw_X : %d Gyr_Raw_Y : %d Gyr_Raw_Z : %d Timestamp : %lu\n", + bmi08x_accel.x, + bmi08x_accel.y, + bmi08x_accel.z, + bmi08x_gyro.x, + bmi08x_gyro.y, + bmi08x_gyro.z, + coines_get_millis() - start_time); + + if (bmi08xdev.variant == BMI085_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 16G range. */ + x = lsb_to_mps2(bmi08x_accel.x, 16, 16); + y = lsb_to_mps2(bmi08x_accel.y, 16, 16); + z = lsb_to_mps2(bmi08x_accel.z, 16, 16); + } + else if (bmi08xdev.variant == BMI088_VARIANT) + { + /* Converting lsb to meter per second squared for 16 bit accelerometer at 24G range. */ + x = lsb_to_mps2(bmi08x_accel.x, 24, 16); + y = lsb_to_mps2(bmi08x_accel.y, 24, 16); + z = lsb_to_mps2(bmi08x_accel.z, 24, 16); + } + + /* Print the data in m/s2. */ + printf("Acc_ms2_X = %4.2f Acc_ms2_Y = %4.2f Acc_ms2_Z = %4.2f ", x, y, z); + + /* Converting lsb to degree per second for 16 bit gyro at 250 dps range. */ + x = lsb_to_dps(bmi08x_gyro.x, 250, 16); + y = lsb_to_dps(bmi08x_gyro.y, 250, 16); + z = lsb_to_dps(bmi08x_gyro.z, 250, 16); + + /* Print the data in dps. */ + printf("\t Gyr_DPS_X = %4.2f Gyr_DPS_Y = %4.2f Gyr_DPS_Z = %4.2f\n", x, y, z); + } + } + + /* Disable data ready interrupts */ + disable_bmi08x_data_synchronization_interrupt(); + + bmi08x_coines_deinit(); + + return rslt; +} + +/* BMI08x data sync. interrupt callback */ +void bmi08x_data_sync_int() +{ + data_sync_int = true; +} + +/*! + * @brief This function converts lsb to meter per second squared for 16 bit accelerometer at + * range 2G, 4G, 8G or 16G. + */ +static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width) +{ + float gravity; + + float half_scale = ((1 << bit_width) / 2.0f); + + gravity = (float)((GRAVITY_EARTH * val * g_range) / half_scale); + + return gravity; +} + +/*! + * @brief This function converts lsb to degree per second for 16 bit gyro at + * range 125, 250, 500, 1000 or 2000dps. + */ +static float lsb_to_dps(int16_t val, float dps, uint8_t bit_width) +{ + float half_scale = ((float)(1 << bit_width) / 2.0f); + + return (dps / ((half_scale) + BMI08X_GYRO_RANGE_2000_DPS)) * (val); +}