diff --git a/libraries/AP_Baro/AP_Baro.cpp b/libraries/AP_Baro/AP_Baro.cpp
index 3748519599..d42d6b993e 100644
--- a/libraries/AP_Baro/AP_Baro.cpp
+++ b/libraries/AP_Baro/AP_Baro.cpp
@@ -35,6 +35,7 @@
#include "AP_Baro_KellerLD.h"
#include "AP_Baro_MS5611.h"
#include "AP_Baro_LPS25H.h"
+#include "AP_Baro_ICM20789.h"
#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_QFLIGHT
#include "AP_Baro_qflight.h"
#endif
diff --git a/libraries/AP_Baro/AP_Baro_ICM20789.cpp b/libraries/AP_Baro/AP_Baro_ICM20789.cpp
new file mode 100644
index 0000000000..0213420d67
--- /dev/null
+++ b/libraries/AP_Baro/AP_Baro_ICM20789.cpp
@@ -0,0 +1,318 @@
+/*
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include "AP_Baro_ICM20789.h"
+
+#include
+#include
+
+#include
+#include
+
+extern const AP_HAL::HAL &hal;
+
+/*
+ CMD_READ options. The draft datasheet doesn't specify, but it seems
+ Mode_1 has a conversion interval of 2ms. Mode_3 has a conversion
+ interval of 20ms. Both seem to produce equally as smooth results, so
+ presumably Mode_3 is doing internal averaging
+ */
+#define CMD_READ_PT_MODE_1 0x401A
+#define CMD_READ_PT_MODE_3 0x5059
+#define CMD_READ_TP_MODE_1 0x609C
+#define CMD_READ_TP_MODE_3 0x70DF
+
+#define CONVERSION_INTERVAL_MODE_1 2000
+#define CONVERSION_INTERVAL_MODE_3 20000
+
+// setup for Mode_3
+#define CMD_READ_PT CMD_READ_PT_MODE_3
+#define CONVERSION_INTERVAL CONVERSION_INTERVAL_MODE_3
+
+#define CMD_SOFT_RESET 0x805D
+#define CMD_READ_ID 0xEFC8
+
+#define debug(fmt, args...) hal.console->printf(fmt, ##args)
+
+/*
+ constructor
+ */
+AP_Baro_ICM20789::AP_Baro_ICM20789(AP_Baro &baro, AP_HAL::OwnPtr _dev)
+ : AP_Baro_Backend(baro)
+ , dev(std::move(_dev))
+{
+}
+
+AP_Baro_Backend *AP_Baro_ICM20789::probe(AP_Baro &baro,
+ AP_HAL::OwnPtr dev)
+{
+ debug("Probing for ICM20789 baro\n");
+ if (!dev) {
+ return nullptr;
+ }
+ AP_Baro_ICM20789 *sensor = new AP_Baro_ICM20789(baro, std::move(dev));
+ if (!sensor || !sensor->init()) {
+ delete sensor;
+ return nullptr;
+ }
+ return sensor;
+}
+
+
+bool AP_Baro_ICM20789::spi_init(void)
+{
+ dev_icm->set_read_flag(0x80);
+
+ dev_icm->set_speed(AP_HAL::Device::SPEED_LOW);
+ uint8_t whoami = 0;
+ uint8_t v;
+
+ dev_icm->read_registers(0x6A, &v, 1);
+ dev_icm->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ dev_icm->write_register(0x6A, 0x10);
+ dev_icm->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ dev_icm->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ dev_icm->write_register(0x23, 0x00);
+ dev_icm->write_register(0x6B, 0x41);
+
+ dev_icm->read_registers(0x75, &whoami, 1);
+
+ // wait for sensor to settle
+ hal.scheduler->delay(100);
+
+ dev_icm->read_registers(0x75, &whoami, 1);
+
+ dev_icm->write_register(0x37, 0x00);
+ dev_icm->write_register(0x6A, 0x10);
+ return true;
+}
+
+bool AP_Baro_ICM20789::init()
+{
+ if (!dev) {
+ return false;
+ }
+
+ debug("Looking for 20789 baro\n");
+
+ if (!dev->get_semaphore()->take(0)) {
+ AP_HAL::panic("PANIC: AP_Baro_ICM20789: failed to take serial semaphore for init");
+ }
+
+#ifdef HAL_INS_MPU60x0_NAME
+ /*
+ Pressure sensor data can be accessed in the following mode:
+ Bypass Mode: Set register INT_PIN_CFG (Address: 55 (Decimal); 37 (Hex)) bit 1 to value 1
+ and I2C_MST_EN bit is 0 Address: 106 (Decimal); 6A (Hex)).
+ Pressure sensor data can then be accessed using the procedure described in Section 10.
+ */
+ debug("Setting up IMU\n");
+ dev_icm = hal.spi->get_device(HAL_INS_MPU60x0_NAME);
+
+ if (!dev_icm->get_semaphore()->take(0)) {
+ AP_HAL::panic("PANIC: AP_Baro_ICM20789: failed to take serial semaphore ICM");
+ }
+
+ if (!spi_init()) {
+ debug("ICM20789: failed to initialise SPI device\n");
+ goto failed;
+ }
+
+ dev_icm->get_semaphore()->give();
+#endif // HAL_INS_MPU60x0_NAME
+
+ if (!send_cmd16(CMD_SOFT_RESET)) {
+ debug("ICM20789: reset failed\n");
+ goto failed;
+ }
+
+ // wait for sensor to settle
+ hal.scheduler->delay(10);
+
+ if (!read_calibration_data()) {
+ debug("ICM20789: read_calibration_data failed\n");
+ goto failed;
+ }
+
+ // start a reading
+ if (!send_cmd16(CMD_READ_PT)) {
+ debug("ICM20789: start read failed\n");
+ goto failed;
+ }
+
+ dev->set_retries(0);
+
+ instance = _frontend.register_sensor();
+
+ dev->get_semaphore()->give();
+
+ debug("ICM20789: startup OK\n");
+
+ // use 10ms to ensure we don't lose samples, with max lag of 10ms
+ dev->register_periodic_callback(CONVERSION_INTERVAL/2, FUNCTOR_BIND_MEMBER(&AP_Baro_ICM20789::timer, void));
+
+ return true;
+
+ failed:
+ dev_icm->get_semaphore()->give();
+ dev->get_semaphore()->give();
+ return false;
+}
+
+bool AP_Baro_ICM20789::send_cmd16(uint16_t cmd)
+{
+ uint8_t cmd_b[2] = { uint8_t(cmd >> 8), uint8_t(cmd & 0xFF) };
+ return dev->transfer(cmd_b, 2, nullptr, 0);
+}
+
+bool AP_Baro_ICM20789::read_calibration_data(void)
+{
+ // setup for OTP read
+ const uint8_t cmd[5] = { 0xC5, 0x95, 0x00, 0x66, 0x9C };
+ if (!dev->transfer(cmd, sizeof(cmd), nullptr, 0)) {
+ debug("ICM20789: read cal1 failed\n");
+ return false;
+ }
+ for (uint8_t i=0; i<4; i++) {
+ if (!send_cmd16(0xC7F7)) {
+ debug("ICM20789: read cal2[%u] failed\n", i);
+ return false;
+ }
+ uint8_t d[3];
+ if (!dev->transfer(nullptr, 0, d, sizeof(d))) {
+ debug("ICM20789: read cal3[%u] failed\n", i);
+ return false;
+ }
+ sensor_constants[i] = int16_t((d[0]<<8) | d[1]);
+ debug("sensor_constants[%u]=%d\n", i, sensor_constants[i]);
+ }
+ return true;
+}
+
+void AP_Baro_ICM20789::calculate_conversion_constants(const float p_Pa[3], const float p_LUT[3],
+ float &A, float &B, float &C)
+{
+ C = (p_LUT[0] * p_LUT[1] * (p_Pa[0] - p_Pa[1]) +
+ p_LUT[1] * p_LUT[2] * (p_Pa[1] - p_Pa[2]) +
+ p_LUT[2] * p_LUT[0] * (p_Pa[2] - p_Pa[0])) /
+ (p_LUT[2] * (p_Pa[0] - p_Pa[1]) +
+ p_LUT[0] * (p_Pa[1] - p_Pa[2]) +
+ p_LUT[1] * (p_Pa[2] - p_Pa[0]));
+ A = (p_Pa[0] * p_LUT[0] - p_Pa[1] * p_LUT[1] - (p_Pa[1] - p_Pa[0]) * C) / (p_LUT[0] - p_LUT[1]);
+ B = (p_Pa[0] - A) * (p_LUT[0] + C);
+}
+
+/*
+ Convert an output from a calibrated sensor to a pressure in Pa.
+ Arguments:
+ p_LSB -- Raw pressure data from sensor
+ T_LSB -- Raw temperature data from sensor
+*/
+float AP_Baro_ICM20789::get_pressure(uint32_t p_LSB, uint32_t T_LSB)
+{
+ float t = T_LSB - 32768.0;
+ float s[3];
+ s[0] = LUT_lower + float(sensor_constants[0] * t * t) * quadr_factor;
+ s[1] = offst_factor * sensor_constants[3] + float(sensor_constants[1] * t * t) * quadr_factor;
+ s[2] = LUT_upper + float(sensor_constants[2] * t * t) * quadr_factor;
+ float A, B, C;
+ calculate_conversion_constants(p_Pa_calib, s, A, B, C);
+ return A + B / (C + p_LSB);
+}
+
+
+static struct {
+ uint32_t Praw, Traw;
+ float T, P;
+} dd;
+
+void AP_Baro_ICM20789::convert_data(uint32_t Praw, uint32_t Traw)
+{
+ // temperature is easy
+ float T = -45 + (175.0 / (1U<<16)) * Traw;
+
+ // pressure involves a few more calculations
+ float P = get_pressure(Praw, Traw);
+
+ if (isinf(P) || isnan(P)) {
+ // really bad data
+ return;
+ }
+
+ if (_sem->take(0)) {
+ dd.Praw = Praw;
+ dd.Traw = Traw;
+ dd.P = P;
+ dd.T = T;
+
+ accum.psum += P;
+ accum.tsum += T;
+ accum.count++;
+ _sem->give();
+ }
+}
+
+void AP_Baro_ICM20789::timer(void)
+{
+ uint8_t d[9] {};
+ if (dev->transfer(nullptr, 0, d, sizeof(d))) {
+ // ignore CRC bytes for now
+ uint32_t Praw = (uint32_t(d[0]) << 16) | (uint32_t(d[1]) << 8) | d[3];
+ uint32_t Traw = (uint32_t(d[6]) << 8) | d[7];
+
+ convert_data(Praw, Traw);
+ send_cmd16(CMD_READ_PT);
+ last_measure_us = AP_HAL::micros();
+ } else {
+ if (AP_HAL::micros() - last_measure_us > CONVERSION_INTERVAL*3) {
+ // lost a sample
+ send_cmd16(CMD_READ_PT);
+ last_measure_us = AP_HAL::micros();
+ }
+ }
+}
+
+void AP_Baro_ICM20789::update()
+{
+ if (_sem->take(HAL_SEMAPHORE_BLOCK_FOREVER)) {
+ if (accum.count > 0) {
+ _copy_to_frontend(instance, accum.psum/accum.count, accum.tsum/accum.count);
+ accum.psum = accum.tsum = 0;
+ accum.count = 0;
+ }
+ _sem->give();
+#if 0
+ // useful for debugging
+ DataFlash_Class::instance()->Log_Write("ICMB", "TimeUS,Traw,Praw,P,T", "QIIff",
+ AP_HAL::micros64(),
+ dd.Traw, dd.Praw, dd.P, dd.T);
+#endif
+ }
+}
+
diff --git a/libraries/AP_Baro/AP_Baro_ICM20789.h b/libraries/AP_Baro/AP_Baro_ICM20789.h
new file mode 100644
index 0000000000..40a63f3eac
--- /dev/null
+++ b/libraries/AP_Baro/AP_Baro_ICM20789.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include "AP_Baro_Backend.h"
+
+#include
+#include
+#include
+
+#ifndef HAL_BARO_ICM20789_I2C_ADDR
+// the baro is on a separate I2C address from the IMU, even though in
+// the same package
+#define HAL_BARO_ICM20789_I2C_ADDR 0x63
+#endif
+
+class AP_Baro_ICM20789 : public AP_Baro_Backend
+{
+public:
+ void update();
+
+ static AP_Baro_Backend *probe(AP_Baro &baro, AP_HAL::OwnPtr dev);
+
+private:
+ AP_Baro_ICM20789(AP_Baro &baro, AP_HAL::OwnPtr dev);
+ virtual ~AP_Baro_ICM20789(void) {};
+
+ bool init();
+ bool send_cmd16(uint16_t cmd);
+
+ bool read_calibration_data(void);
+
+ void convert_data(uint32_t Praw, uint32_t Traw);
+
+ void calculate_conversion_constants(const float p_Pa[3], const float p_LUT[3],
+ float &A, float &B, float &C);
+ float get_pressure(uint32_t p_LSB, uint32_t T_LSB);
+
+ bool spi_init(void);
+
+ void timer(void);
+
+ // calibration data
+ int16_t sensor_constants[4];
+
+ uint8_t instance;
+ AP_HAL::OwnPtr dev;
+ AP_HAL::OwnPtr dev_icm;
+
+ // time last read command was sent
+ uint32_t last_measure_us;
+
+ // accumulation structure, protected by _sem
+ struct {
+ float tsum;
+ float psum;
+ uint32_t count;
+ } accum;
+
+ // conversion constants. Thanks to invensense for including python
+ // sample code in the datasheet!
+ const float p_Pa_calib[3] = {45000.0, 80000.0, 105000.0};
+ const float LUT_lower = 3.5 * (1U<<20);
+ const float LUT_upper = 11.5 * (1U<<20);
+ const float quadr_factor = 1 / 16777216.0;
+ const float offst_factor = 2048.0;
+};
diff --git a/libraries/AP_Baro/examples/ICM20789/ICM20789.cpp b/libraries/AP_Baro/examples/ICM20789/ICM20789.cpp
new file mode 100644
index 0000000000..f5811b60a5
--- /dev/null
+++ b/libraries/AP_Baro/examples/ICM20789/ICM20789.cpp
@@ -0,0 +1,291 @@
+/*
+ minimal test program for ICM20789 baro with IMU on SPI and baro on I2C
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+const AP_HAL::HAL& hal = AP_HAL::get_HAL();
+
+static AP_HAL::OwnPtr i2c_dev;
+static AP_HAL::OwnPtr spi_dev;
+static AP_HAL::OwnPtr lidar_dev;
+
+// SPI registers
+#define MPUREG_WHOAMI 0x75
+#define MPUREG_USER_CTRL 0x6A
+#define MPUREG_PWR_MGMT_1 0x6B
+
+#define MPUREG_INT_PIN_CFG 0x37
+# define BIT_BYPASS_EN 0x02
+# define BIT_INT_RD_CLEAR 0x10 // clear the interrupt when any read occurs
+# define BIT_LATCH_INT_EN 0x20 // latch data ready pin
+
+#define BIT_USER_CTRL_I2C_MST_EN 0x20 // Enable MPU to act as the I2C Master to external slave sensors
+#define BIT_PWR_MGMT_1_DEVICE_RESET 0x80 // reset entire device
+#define BIT_USER_CTRL_I2C_IF_DIS 0x10 // Disable primary I2C interface and enable hal.spi->interface
+#define BIT_PWR_MGMT_1_CLK_XGYRO 0x01 // PLL with X axis gyroscope reference
+#define BIT_PWR_MGMT_1_CLK_ZGYRO 0x03 // PLL with Z axis gyroscope reference
+
+// baro commands
+#define CMD_SOFT_RESET 0x805D
+#define CMD_READ_ID 0xEFC8
+
+static void spi_init()
+{
+ // SPI reads have flag 0x80 set
+ spi_dev->set_read_flag(0x80);
+
+ // run the SPI bus at low speed
+ spi_dev->set_speed(AP_HAL::Device::SPEED_LOW);
+
+ uint8_t whoami = 0;
+ uint8_t v;
+
+ spi_dev->write_register(0x6B, 0x01);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6C, 0x3f);
+ spi_dev->write_register(0xF5, 0x00);
+ spi_dev->write_register(0x19, 0x09);
+ spi_dev->write_register(0xEA, 0x00);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x23, 0x00);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x1D, 0xC0);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x1A, 0xC0);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x38, 0x01);
+
+ spi_dev->read_registers(0x6A, &v, 1);
+ printf("reg 0x6A=0x%02x\n", v);
+ spi_dev->read_registers(0x6B, &v, 1);
+ printf("reg 0x6B=0x%02x\n", v);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x23, 0x00);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x41);
+ spi_dev->write_register(0x6C, 0x3f);
+ spi_dev->write_register(0x6B, 0x41);
+
+ spi_dev->read_registers(0x6A, &v, 1);
+ printf("reg 0x6A=0x%02x\n", v);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x23, 0x00);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->read_registers(0x6A, &v, 1);
+ printf("reg 0x6A=0x%02x\n", v);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x23, 0x00);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x41);
+ spi_dev->write_register(0x6C, 0x3f);
+ spi_dev->write_register(0x6B, 0x41);
+
+ spi_dev->read_registers(0x6A, &v, 1);
+ printf("reg 0x6A=0x%02x\n", v);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6A, 0x10);
+ spi_dev->write_register(0x6B, 0x41);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x6B, 0x01);
+
+ hal.scheduler->delay(1);
+ spi_dev->write_register(0x23, 0x00);
+ spi_dev->write_register(0x6B, 0x41);
+
+ // print the WHOAMI
+ spi_dev->read_registers(MPUREG_WHOAMI, &whoami, 1);
+ printf("20789 SPI whoami: 0x%02x\n", whoami);
+
+ // wait for sensor to settle
+ hal.scheduler->delay(100);
+
+ // dump registers
+ printf("ICM20789 registers\n");
+#if 0
+ for (uint8_t reg = 0; reg<0x80; reg++) {
+ v=0;
+ spi_dev->read_registers(reg, &v, 1);
+ printf("%02x:%02x ", (unsigned)reg, (unsigned)v);
+ if ((reg+1) % 16 == 0) {
+ printf("\n");
+ }
+ }
+ printf("\n");
+#endif
+
+ spi_dev->get_semaphore()->give();
+}
+
+
+/*
+ send a 16 bit command to the baro
+ */
+static bool send_cmd16(uint16_t cmd)
+{
+ uint8_t cmd_b[2] = { uint8_t(cmd >> 8), uint8_t(cmd & 0xFF) };
+ return i2c_dev->transfer(cmd_b, 2, nullptr, 0);
+}
+
+/*
+ read baro calibration data
+ */
+static bool read_calibration_data(void)
+{
+ // setup for OTP read
+ const uint8_t cmd[5] = { 0xC5, 0x95, 0x00, 0x66, 0x9C };
+ if (!i2c_dev->transfer(cmd, sizeof(cmd), nullptr, 0)) {
+ return false;
+ }
+ for (uint8_t i=0; i<4; i++) {
+ if (!send_cmd16(0xC7F7)) {
+ return false;
+ }
+ uint8_t d[3];
+ if (!i2c_dev->transfer(nullptr, 0, d, sizeof(d))) {
+ return false;
+ }
+ uint16_t c = int16_t((d[0]<<8) | d[1]);
+ printf("sensor_constants[%u]=%d\n", i, c);
+ }
+ return true;
+}
+
+// initialise baro on i2c
+static void i2c_init(void)
+{
+ if (!i2c_dev->get_semaphore()->take(0)) {
+ AP_HAL::panic("Failed to get baro semaphore");
+ }
+
+ if (send_cmd16(CMD_READ_ID)) {
+ printf("ICM20789: read ID ******\n");
+ uint8_t id[3] {};
+ if (!i2c_dev->transfer(nullptr, 0, id, 3)) {
+ printf("ICM20789: failed to read ID\n");
+ }
+ printf("ICM20789: ID %02x %02x %02x\n", id[0], id[1], id[2]);
+ } else {
+ printf("ICM20789 read ID failed\n");
+ }
+
+ if (send_cmd16(CMD_SOFT_RESET)) {
+ printf("ICM20789: reset OK ************###########*********!!!!!!!!\n");
+ } else {
+ printf("ICM20789 baro reset failed\n");
+ }
+ hal.scheduler->delay(1);
+
+
+ read_calibration_data();
+
+ i2c_dev->get_semaphore()->give();
+
+ printf("checking lidar\n");
+ if (!lidar_dev->get_semaphore()->take(0)) {
+ AP_HAL::panic("Failed to get lidar semaphore");
+ }
+
+ uint8_t regs[3] = { 0xC0, 0xC1, 0xC2 };
+ for (uint8_t i=0; iread_registers(regs[i], &v, 1);
+ printf("0x%02x : 0x%02x\n", regs[i], v);
+ }
+ lidar_dev->get_semaphore()->give();
+}
+
+void setup()
+{
+ printf("ICM20789 test\n");
+
+ AP_BoardConfig{}.init();
+
+ hal.scheduler->delay(1000);
+
+#ifdef HAL_INS_MPU60x0_NAME
+ spi_dev = std::move(hal.spi->get_device(HAL_INS_MPU60x0_NAME));
+
+ if (!spi_dev->get_semaphore()->take(0)) {
+ AP_HAL::panic("Failed to get spi semaphore");
+ }
+
+
+ i2c_dev = std::move(hal.i2c_mgr->get_device(1, 0x63));
+ lidar_dev = std::move(hal.i2c_mgr->get_device(1, 0x29));
+
+ while (true) {
+ spi_init();
+ i2c_init();
+ hal.scheduler->delay(1000);
+ }
+#endif
+}
+
+
+void loop()
+{
+}
+
+AP_HAL_MAIN();
diff --git a/libraries/AP_Baro/examples/ICM20789/wscript b/libraries/AP_Baro/examples/ICM20789/wscript
new file mode 100644
index 0000000000..719ec151ba
--- /dev/null
+++ b/libraries/AP_Baro/examples/ICM20789/wscript
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+def build(bld):
+ bld.ap_example(
+ use='ap',
+ )