From 258a563dd50785b76457b8a8b24267f8a34a45c2 Mon Sep 17 00:00:00 2001 From: CUAVmengxiao Date: Wed, 3 Nov 2021 15:16:11 +0800 Subject: [PATCH] barometer: Add ICP10100 and ICP1011 --- src/drivers/barometer/CMakeLists.txt | 1 + .../barometer/invensense/CMakeLists.txt | 35 ++ .../invensense/icp10100/CMakeLists.txt | 46 +++ .../invensense/icp10100/ICP10100.cpp | 375 ++++++++++++++++++ .../invensense/icp10100/ICP10100.hpp | 98 +++++ .../Inven_Sense_ICP10100_registers.hpp | 62 +++ .../invensense/icp10100/icp10100_main.cpp | 79 ++++ .../invensense/icp10111/CMakeLists.txt | 46 +++ .../invensense/icp10111/ICP10111.cpp | 375 ++++++++++++++++++ .../invensense/icp10111/ICP10111.hpp | 98 +++++ .../Inven_Sense_ICP10111_registers.hpp | 62 +++ .../invensense/icp10111/icp10111_main.cpp | 79 ++++ 12 files changed, 1356 insertions(+) create mode 100755 src/drivers/barometer/invensense/CMakeLists.txt create mode 100755 src/drivers/barometer/invensense/icp10100/CMakeLists.txt create mode 100755 src/drivers/barometer/invensense/icp10100/ICP10100.cpp create mode 100755 src/drivers/barometer/invensense/icp10100/ICP10100.hpp create mode 100755 src/drivers/barometer/invensense/icp10100/Inven_Sense_ICP10100_registers.hpp create mode 100755 src/drivers/barometer/invensense/icp10100/icp10100_main.cpp create mode 100755 src/drivers/barometer/invensense/icp10111/CMakeLists.txt create mode 100755 src/drivers/barometer/invensense/icp10111/ICP10111.cpp create mode 100755 src/drivers/barometer/invensense/icp10111/ICP10111.hpp create mode 100755 src/drivers/barometer/invensense/icp10111/Inven_Sense_ICP10111_registers.hpp create mode 100755 src/drivers/barometer/invensense/icp10111/icp10111_main.cpp diff --git a/src/drivers/barometer/CMakeLists.txt b/src/drivers/barometer/CMakeLists.txt index 037daaf269..9758809286 100644 --- a/src/drivers/barometer/CMakeLists.txt +++ b/src/drivers/barometer/CMakeLists.txt @@ -41,3 +41,4 @@ add_subdirectory(lps33hw) add_subdirectory(maiertek) add_subdirectory(ms5611) #add_subdirectory(tcbp001ta) # only for users who really need this +add_subdirectory(invensense) diff --git a/src/drivers/barometer/invensense/CMakeLists.txt b/src/drivers/barometer/invensense/CMakeLists.txt new file mode 100755 index 0000000000..1060e92e66 --- /dev/null +++ b/src/drivers/barometer/invensense/CMakeLists.txt @@ -0,0 +1,35 @@ +############################################################################ +# +# Copyright (c) 2021 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER 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. +# +############################################################################ + +add_subdirectory(icp10100) +add_subdirectory(icp10111) diff --git a/src/drivers/barometer/invensense/icp10100/CMakeLists.txt b/src/drivers/barometer/invensense/icp10100/CMakeLists.txt new file mode 100755 index 0000000000..edacba9ccd --- /dev/null +++ b/src/drivers/barometer/invensense/icp10100/CMakeLists.txt @@ -0,0 +1,46 @@ +############################################################################ +# +# Copyright (c) 2021 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER 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. +# +############################################################################ + +px4_add_module( + MODULE drivers__invensense__icp10100 + MAIN icp10100 + COMPILE_FLAGS + SRCS + Inven_Sense_ICP10100_registers.hpp + ICP10100.cpp + ICP10100.hpp + icp10100_main.cpp + DEPENDS + drivers_barometer + px4_work_queue + ) diff --git a/src/drivers/barometer/invensense/icp10100/ICP10100.cpp b/src/drivers/barometer/invensense/icp10100/ICP10100.cpp new file mode 100755 index 0000000000..00780fcd64 --- /dev/null +++ b/src/drivers/barometer/invensense/icp10100/ICP10100.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#include "ICP10100.hpp" + +using namespace time_literals; + +ICP10100::ICP10100(const I2CSPIDriverConfig &config) : + I2C(config), + I2CSPIDriver(config), + _px4_baro(get_device_id()) +{ +} + +ICP10100::~ICP10100() +{ + perf_free(_reset_perf); + perf_free(_sample_perf); + perf_free(_bad_transfer_perf); +} + +int +ICP10100::init() +{ + int ret = I2C::init(); + + if (ret != PX4_OK) { + DEVICE_DEBUG("I2C::init failed (%i)", ret); + return ret; + } + + return Reset() ? 0 : -1; +} + +bool +ICP10100::Reset() +{ + _state = STATE::RESET; + ScheduleClear(); + ScheduleNow(); + return true; +} + +void +ICP10100::print_status() +{ + I2CSPIDriverBase::print_status(); + perf_print_counter(_reset_perf); + perf_print_counter(_sample_perf); + perf_print_counter(_bad_transfer_perf); +} + +int +ICP10100::probe() +{ + uint16_t ID = 0; + read_response(Cmd::READ_ID, (uint8_t *)&ID, 2); + uint8_t PROD_ID = (ID >> 8) & 0x3f; + + if (PROD_ID != Product_ID) { + DEVICE_DEBUG("unexpected PROD_ID 0x%02x", PROD_ID); + return PX4_ERROR; + } + + return PX4_OK; +} + +void +ICP10100::RunImpl() +{ + const hrt_abstime now = hrt_absolute_time(); + + switch (_state) { + case STATE::RESET: + // Software Reset + send_command(Cmd::SOFT_RESET); + _reset_timestamp = now; + _failure_count = 0; + _state = STATE::WAIT_FOR_RESET; + perf_count(_reset_perf); + ScheduleDelayed(100_ms); // Power On Reset: max 100ms + break; + + case STATE::WAIT_FOR_RESET: { + // check product id + uint16_t ID = 0; + read_response(Cmd::READ_ID, (uint8_t *)&ID, 2); + uint8_t PROD_ID = (ID >> 8) & 0x3f; // Product ID Bits 5:0 + + if (PROD_ID == Product_ID) { + // if reset succeeded then read otp + _state = STATE::READ_OTP; + ScheduleDelayed(10_ms); // Time to coefficients are available. + + } else { + // RESET not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Reset failed, retrying"); + _state = STATE::RESET; + ScheduleDelayed(100_ms); + + } else { + PX4_DEBUG("Reset not complete, check again in 10 ms"); + ScheduleDelayed(10_ms); + } + } + } + break; + + case STATE::READ_OTP: { + // read otp + uint8_t addr_otp_cmd[3] = {0x00, 0x66, 0x9c}; + uint8_t otp_buf[3]; + uint8_t crc; + bool success = true; + + send_command(Cmd::SET_ADDR, addr_otp_cmd, 3); + + for (uint8_t i = 0; i < 4; i++) { + read_response(Cmd::READ_OTP, otp_buf, 3); + + crc = 0xFF; + + for (int j = 0; j < 2; j++) { + crc = (uint8_t)cal_crc(crc, otp_buf[j]); + } + + if (crc != otp_buf[2]) { + success = false; + break; + } + + _scal[i] = (otp_buf[0] << 8) | otp_buf[1]; + } + + if (success) { + _state = STATE::MEASURE; + + } else { + _state = STATE::RESET; + } + + ScheduleDelayed(10_ms); + } + break; + + case STATE::MEASURE: + if (Measure()) { + // if configure succeeded then start measurement cycle + _state = STATE::READ; + perf_begin(_sample_perf); + ScheduleDelayed(_measure_interval); + + } else { + // MEASURE not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Measure failed, resetting"); + _state = STATE::RESET; + + } else { + PX4_DEBUG("Measure failed, retrying"); + } + + ScheduleDelayed(_measure_interval); + } + + break; + + case STATE::READ: { + uint8_t comp_data[9] {}; + bool success = false; + + if (read_measure_results(comp_data, 9) == PX4_OK) { + perf_end(_sample_perf); + + uint16_t _raw_t = (comp_data[0] << 8) | comp_data[1]; + uint32_t L_res_buf3 = comp_data[3]; // expand result bytes to 32bit to fix issues on 8-bit MCUs + uint32_t L_res_buf4 = comp_data[4]; + uint32_t L_res_buf6 = comp_data[6]; + uint32_t _raw_p = (L_res_buf3 << 16) | (L_res_buf4 << 8) | L_res_buf6; + + // constants for presure calculation + static constexpr float _pcal[3] = { 45000.0, 80000.0, 105000.0 }; + static constexpr float _lut_lower = 3.5 * 0x100000; // 1<<20 + static constexpr float _lut_upper = 11.5 * 0x100000; // 1<<20 + static constexpr float _quadr_factor = 1 / 16777216.0; + static constexpr float _offst_factor = 2048.0; + + // calculate temperature + float _temperature_C = -45.f + 175.f / 65536.f * _raw_t; + + // calculate pressure + float t = (float)(_raw_t - 32768); + float s1 = _lut_lower + (float)(_scal[0] * t * t) * _quadr_factor; + float s2 = _offst_factor * _scal[3] + (float)(_scal[1] * t * t) * _quadr_factor; + float s3 = _lut_upper + (float)(_scal[2] * t * t) * _quadr_factor; + float c = (s1 * s2 * (_pcal[0] - _pcal[1]) + + s2 * s3 * (_pcal[1] - _pcal[2]) + + s3 * s1 * (_pcal[2] - _pcal[0])) / + (s3 * (_pcal[0] - _pcal[1]) + + s1 * (_pcal[1] - _pcal[2]) + + s2 * (_pcal[2] - _pcal[0])); + float a = (_pcal[0] * s1 - _pcal[1] * s2 - (_pcal[1] - _pcal[0]) * c) / (s1 - s2); + float b = (_pcal[0] - a) * (s1 + c); + float _pressure_Pa = a + b / (c + _raw_p); + + const hrt_abstime nowx = hrt_absolute_time(); + float temperature = _temperature_C; + float pressure = _pressure_Pa; // to Pascal + pressure = pressure / 100.0f; // to mbar + + _px4_baro.set_error_count(perf_event_count(_bad_transfer_perf)); + _px4_baro.set_temperature(temperature); + _px4_baro.update(nowx, pressure); + + success = true; + + if (_failure_count > 0) { + _failure_count--; + } + + _state = STATE::MEASURE; + + } else { + perf_count(_bad_transfer_perf); + } + + if (!success) { + _failure_count++; + + // full reset if things are failing consistently + if (_failure_count > 10) { + Reset(); + return; + } + } + + ScheduleDelayed(1000_ms / 8 - _measure_interval); // 8Hz + } + + break; + } +} + +bool +ICP10100::Measure() +{ + /* + From ds-000186-icp-101xx-v1.0.pdf, page 6, table 1 + + Sensor Measurement Max Time + Mode Time (Forced) + Low Power (LP) 1.6 ms 1.8 ms + Normal (N) 5.6 ms 6.3 ms + Low Noise (LN) 20.8 ms 23.8 ms + Ultra Low Noise(ULN) 83.2 ms 94.5 ms + */ + Cmd cmd; + + switch (_mode) { + case MODE::FAST: + cmd = Cmd::MEAS_LP; + _measure_interval = 2_ms; + break; + + case MODE::ACCURATE: + cmd = Cmd::MEAS_LN; + _measure_interval = 24_ms; + break; + + case MODE::VERY_ACCURATE: + cmd = Cmd::MEAS_ULN; + _measure_interval = 95_ms; + break; + + case MODE::NORMAL: + default: + cmd = Cmd::MEAS_N; + _measure_interval = 7_ms; + break; + } + + if (send_command(cmd) != PX4_OK) { + return false; + } + + return true; +} + +int8_t +ICP10100::cal_crc(uint8_t seed, uint8_t data) +{ + int8_t poly = 0x31; + int8_t var2; + uint8_t i; + + for (i = 0; i < 8; i++) { + if ((seed & 0x80) ^ (data & 0x80)) { + var2 = 1; + + } else { + var2 = 0; + } + + seed = (seed & 0x7F) << 1; + data = (data & 0x7F) << 1; + seed = seed ^ (uint8_t)(poly * var2); + } + + return (int8_t)seed; +} + +int +ICP10100::read_measure_results(uint8_t *buf, uint8_t len) +{ + return transfer(nullptr, 0, buf, len); +} + +int +ICP10100::read_response(Cmd cmd, uint8_t *buf, uint8_t len) +{ + uint8_t buff[2]; + buff[0] = ((uint16_t)cmd >> 8) & 0xff; + buff[1] = (uint16_t)cmd & 0xff; + return transfer(&buff[0], 2, buf, len); +} + +int +ICP10100::send_command(Cmd cmd) +{ + uint8_t buf[2]; + buf[0] = ((uint16_t)cmd >> 8) & 0xff; + buf[1] = (uint16_t)cmd & 0xff; + return transfer(buf, sizeof(buf), nullptr, 0); +} + +int +ICP10100::send_command(Cmd cmd, uint8_t *data, uint8_t len) +{ + uint8_t buf[5]; + buf[0] = ((uint16_t)cmd >> 8) & 0xff; + buf[1] = (uint16_t)cmd & 0xff; + memcpy(&buf[2], data, len); + return transfer(&buf[0], len + 2, nullptr, 0); +} diff --git a/src/drivers/barometer/invensense/icp10100/ICP10100.hpp b/src/drivers/barometer/invensense/icp10100/ICP10100.hpp new file mode 100755 index 0000000000..542c0003db --- /dev/null +++ b/src/drivers/barometer/invensense/icp10100/ICP10100.hpp @@ -0,0 +1,98 @@ +/**************************************************************************** + * + * Copyright (C) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#pragma once + +#include "Inven_Sense_ICP10100_registers.hpp" + +#include +#include +#include +#include +#include + +using namespace Inven_Sense_ICP10100; + +class ICP10100 : public device::I2C, public I2CSPIDriver +{ +public: + ICP10100(const I2CSPIDriverConfig &config); + ~ICP10100() override; + + static void print_usage(); + + void RunImpl(); + + int init() override; + void print_status() override; + +private: + int probe() override; + + bool Reset(); + + bool Measure(); + + int8_t cal_crc(uint8_t seed, uint8_t data); + int read_measure_results(uint8_t *buf, uint8_t len); + int read_response(Cmd cmd, uint8_t *buf, uint8_t len); + int send_command(Cmd cmd); + int send_command(Cmd cmd, uint8_t *data, uint8_t len); + + PX4Barometer _px4_baro; + + perf_counter_t _reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": reset")}; + perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")}; + perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")}; + + hrt_abstime _reset_timestamp{0}; + int _failure_count{0}; + + unsigned _measure_interval{0}; + int16_t _scal[4]; + + enum class STATE : uint8_t { + RESET, + WAIT_FOR_RESET, + READ_OTP, + MEASURE, + READ + } _state{STATE::RESET}; + + enum class MODE : uint8_t { + FAST, + NORMAL, + ACCURATE, + VERY_ACCURATE + } _mode{MODE::VERY_ACCURATE}; +}; diff --git a/src/drivers/barometer/invensense/icp10100/Inven_Sense_ICP10100_registers.hpp b/src/drivers/barometer/invensense/icp10100/Inven_Sense_ICP10100_registers.hpp new file mode 100755 index 0000000000..558b7f14d1 --- /dev/null +++ b/src/drivers/barometer/invensense/icp10100/Inven_Sense_ICP10100_registers.hpp @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file icp10100_registers.hpp + * + * icp10100 registers. + * + */ + +#pragma once + +#include + +namespace Inven_Sense_ICP10100 +{ +static constexpr uint32_t I2C_SPEED = 100 * 1000; // 100 kHz I2C serial interface +static constexpr uint8_t I2C_ADDRESS_DEFAULT = 0x63; + +static constexpr uint8_t Product_ID = 0x08; + +enum class Cmd : uint16_t { + READ_ID = 0xefc8, + SET_ADDR = 0xc595, + READ_OTP = 0xc7f7, + MEAS_LP = 0x609c, + MEAS_N = 0x6825, + MEAS_LN = 0x70df, + MEAS_ULN = 0x7866, + SOFT_RESET = 0x805d +}; +} // namespace Inven_Sense_ICP10100 diff --git a/src/drivers/barometer/invensense/icp10100/icp10100_main.cpp b/src/drivers/barometer/invensense/icp10100/icp10100_main.cpp new file mode 100755 index 0000000000..de4c0aa25e --- /dev/null +++ b/src/drivers/barometer/invensense/icp10100/icp10100_main.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#include +#include +#include + +#include "ICP10100.hpp" + +void +ICP10100::print_usage() +{ + PRINT_MODULE_USAGE_NAME("icp10100", "driver"); + PRINT_MODULE_USAGE_SUBCATEGORY("baro"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false); + PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x63); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); +} + +extern "C" int icp10100_main(int argc, char *argv[]) +{ + using ThisDriver = ICP10100; + BusCLIArguments cli{true, false}; + cli.i2c_address = I2C_ADDRESS_DEFAULT; + cli.default_i2c_frequency = I2C_SPEED; + + const char *verb = cli.parseDefaultArguments(argc, argv); + + if (!verb) { + ThisDriver::print_usage(); + return -1; + } + + BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP10100); + + if (!strcmp(verb, "start")) { + return ThisDriver::module_start(cli, iterator); + + } else if (!strcmp(verb, "stop")) { + return ThisDriver::module_stop(iterator); + + } else if (!strcmp(verb, "status")) { + return ThisDriver::module_status(iterator); + } + + ThisDriver::print_usage(); + return -1; +} diff --git a/src/drivers/barometer/invensense/icp10111/CMakeLists.txt b/src/drivers/barometer/invensense/icp10111/CMakeLists.txt new file mode 100755 index 0000000000..bc8f5258bc --- /dev/null +++ b/src/drivers/barometer/invensense/icp10111/CMakeLists.txt @@ -0,0 +1,46 @@ +############################################################################ +# +# Copyright (c) 2021 PX4 Development Team. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. Neither the name PX4 nor the names of its contributors may be +# used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER 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. +# +############################################################################ + +px4_add_module( + MODULE drivers__invensense__icp10111 + MAIN icp10111 + COMPILE_FLAGS + SRCS + Inven_Sense_ICP10111_registers.hpp + ICP10111.cpp + ICP10111.hpp + icp10111_main.cpp + DEPENDS + drivers_barometer + px4_work_queue + ) diff --git a/src/drivers/barometer/invensense/icp10111/ICP10111.cpp b/src/drivers/barometer/invensense/icp10111/ICP10111.cpp new file mode 100755 index 0000000000..2403906dd5 --- /dev/null +++ b/src/drivers/barometer/invensense/icp10111/ICP10111.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#include "ICP10111.hpp" + +using namespace time_literals; + +ICP10111::ICP10111(const I2CSPIDriverConfig &config) : + I2C(config), + I2CSPIDriver(config), + _px4_baro(get_device_id()) +{ +} + +ICP10111::~ICP10111() +{ + perf_free(_reset_perf); + perf_free(_sample_perf); + perf_free(_bad_transfer_perf); +} + +int +ICP10111::init() +{ + int ret = I2C::init(); + + if (ret != PX4_OK) { + DEVICE_DEBUG("I2C::init failed (%i)", ret); + return ret; + } + + return Reset() ? 0 : -1; +} + +bool +ICP10111::Reset() +{ + _state = STATE::RESET; + ScheduleClear(); + ScheduleNow(); + return true; +} + +void +ICP10111::print_status() +{ + I2CSPIDriverBase::print_status(); + perf_print_counter(_reset_perf); + perf_print_counter(_sample_perf); + perf_print_counter(_bad_transfer_perf); +} + +int +ICP10111::probe() +{ + uint16_t ID = 0; + read_response(Cmd::READ_ID, (uint8_t *)&ID, 2); + uint8_t PROD_ID = (ID >> 8) & 0x3f; + + if (PROD_ID != Product_ID) { + DEVICE_DEBUG("unexpected PROD_ID 0x%02x", PROD_ID); + return PX4_ERROR; + } + + return PX4_OK; +} + +void +ICP10111::RunImpl() +{ + const hrt_abstime now = hrt_absolute_time(); + + switch (_state) { + case STATE::RESET: + // Software Reset + send_command(Cmd::SOFT_RESET); + _reset_timestamp = now; + _failure_count = 0; + _state = STATE::WAIT_FOR_RESET; + perf_count(_reset_perf); + ScheduleDelayed(100_ms); // Power On Reset: max 100ms + break; + + case STATE::WAIT_FOR_RESET: { + // check product id + uint16_t ID = 0; + read_response(Cmd::READ_ID, (uint8_t *)&ID, 2); + uint8_t PROD_ID = (ID >> 8) & 0x3f; // Product ID Bits 5:0 + + if (PROD_ID == Product_ID) { + // if reset succeeded then read otp + _state = STATE::READ_OTP; + ScheduleDelayed(10_ms); // Time to coefficients are available. + + } else { + // RESET not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Reset failed, retrying"); + _state = STATE::RESET; + ScheduleDelayed(100_ms); + + } else { + PX4_DEBUG("Reset not complete, check again in 10 ms"); + ScheduleDelayed(10_ms); + } + } + } + break; + + case STATE::READ_OTP: { + // read otp + uint8_t addr_otp_cmd[3] = {0x00, 0x66, 0x9c}; + uint8_t otp_buf[3]; + uint8_t crc; + bool success = true; + + send_command(Cmd::SET_ADDR, addr_otp_cmd, 3); + + for (uint8_t i = 0; i < 4; i++) { + read_response(Cmd::READ_OTP, otp_buf, 3); + + crc = 0xFF; + + for (int j = 0; j < 2; j++) { + crc = (uint8_t)cal_crc(crc, otp_buf[j]); + } + + if (crc != otp_buf[2]) { + success = false; + break; + } + + _scal[i] = (otp_buf[0] << 8) | otp_buf[1]; + } + + if (success) { + _state = STATE::MEASURE; + + } else { + _state = STATE::RESET; + } + + ScheduleDelayed(10_ms); + } + break; + + case STATE::MEASURE: + if (Measure()) { + // if configure succeeded then start measurement cycle + _state = STATE::READ; + perf_begin(_sample_perf); + ScheduleDelayed(_measure_interval); + + } else { + // MEASURE not complete + if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) { + PX4_DEBUG("Measure failed, resetting"); + _state = STATE::RESET; + + } else { + PX4_DEBUG("Measure failed, retrying"); + } + + ScheduleDelayed(_measure_interval); + } + + break; + + case STATE::READ: { + uint8_t comp_data[9] {}; + bool success = false; + + if (read_measure_results(comp_data, 9) == PX4_OK) { + perf_end(_sample_perf); + + uint16_t _raw_t = (comp_data[0] << 8) | comp_data[1]; + uint32_t L_res_buf3 = comp_data[3]; // expand result bytes to 32bit to fix issues on 8-bit MCUs + uint32_t L_res_buf4 = comp_data[4]; + uint32_t L_res_buf6 = comp_data[6]; + uint32_t _raw_p = (L_res_buf3 << 16) | (L_res_buf4 << 8) | L_res_buf6; + + // constants for presure calculation + static constexpr float _pcal[3] = { 45000.0, 80000.0, 105000.0 }; + static constexpr float _lut_lower = 3.5 * 0x100000; // 1<<20 + static constexpr float _lut_upper = 11.5 * 0x100000; // 1<<20 + static constexpr float _quadr_factor = 1 / 16777216.0; + static constexpr float _offst_factor = 2048.0; + + // calculate temperature + float _temperature_C = -45.f + 175.f / 65536.f * _raw_t; + + // calculate pressure + float t = (float)(_raw_t - 32768); + float s1 = _lut_lower + (float)(_scal[0] * t * t) * _quadr_factor; + float s2 = _offst_factor * _scal[3] + (float)(_scal[1] * t * t) * _quadr_factor; + float s3 = _lut_upper + (float)(_scal[2] * t * t) * _quadr_factor; + float c = (s1 * s2 * (_pcal[0] - _pcal[1]) + + s2 * s3 * (_pcal[1] - _pcal[2]) + + s3 * s1 * (_pcal[2] - _pcal[0])) / + (s3 * (_pcal[0] - _pcal[1]) + + s1 * (_pcal[1] - _pcal[2]) + + s2 * (_pcal[2] - _pcal[0])); + float a = (_pcal[0] * s1 - _pcal[1] * s2 - (_pcal[1] - _pcal[0]) * c) / (s1 - s2); + float b = (_pcal[0] - a) * (s1 + c); + float _pressure_Pa = a + b / (c + _raw_p); + + const hrt_abstime nowx = hrt_absolute_time(); + float temperature = _temperature_C; + float pressure = _pressure_Pa; // to Pascal + pressure = pressure / 100.0f; // to mbar + + _px4_baro.set_error_count(perf_event_count(_bad_transfer_perf)); + _px4_baro.set_temperature(temperature); + _px4_baro.update(nowx, pressure); + + success = true; + + if (_failure_count > 0) { + _failure_count--; + } + + _state = STATE::MEASURE; + + } else { + perf_count(_bad_transfer_perf); + } + + if (!success) { + _failure_count++; + + // full reset if things are failing consistently + if (_failure_count > 10) { + Reset(); + return; + } + } + + ScheduleDelayed(1000_ms / 8 - _measure_interval); // 8Hz + } + + break; + } +} + +bool +ICP10111::Measure() +{ + /* + From ds-000186-icp-101xx-v1.0.pdf, page 6, table 1 + + Sensor Measurement Max Time + Mode Time (Forced) + Low Power (LP) 1.6 ms 1.8 ms + Normal (N) 5.6 ms 6.3 ms + Low Noise (LN) 20.8 ms 23.8 ms + Ultra Low Noise(ULN) 83.2 ms 94.5 ms + */ + Cmd cmd; + + switch (_mode) { + case MODE::FAST: + cmd = Cmd::MEAS_LP; + _measure_interval = 2_ms; + break; + + case MODE::ACCURATE: + cmd = Cmd::MEAS_LN; + _measure_interval = 24_ms; + break; + + case MODE::VERY_ACCURATE: + cmd = Cmd::MEAS_ULN; + _measure_interval = 95_ms; + break; + + case MODE::NORMAL: + default: + cmd = Cmd::MEAS_N; + _measure_interval = 7_ms; + break; + } + + if (send_command(cmd) != PX4_OK) { + return false; + } + + return true; +} + +int8_t +ICP10111::cal_crc(uint8_t seed, uint8_t data) +{ + int8_t poly = 0x31; + int8_t var2; + uint8_t i; + + for (i = 0; i < 8; i++) { + if ((seed & 0x80) ^ (data & 0x80)) { + var2 = 1; + + } else { + var2 = 0; + } + + seed = (seed & 0x7F) << 1; + data = (data & 0x7F) << 1; + seed = seed ^ (uint8_t)(poly * var2); + } + + return (int8_t)seed; +} + +int +ICP10111::read_measure_results(uint8_t *buf, uint8_t len) +{ + return transfer(nullptr, 0, buf, len); +} + +int +ICP10111::read_response(Cmd cmd, uint8_t *buf, uint8_t len) +{ + uint8_t buff[2]; + buff[0] = ((uint16_t)cmd >> 8) & 0xff; + buff[1] = (uint16_t)cmd & 0xff; + return transfer(&buff[0], 2, buf, len); +} + +int +ICP10111::send_command(Cmd cmd) +{ + uint8_t buf[2]; + buf[0] = ((uint16_t)cmd >> 8) & 0xff; + buf[1] = (uint16_t)cmd & 0xff; + return transfer(buf, sizeof(buf), nullptr, 0); +} + +int +ICP10111::send_command(Cmd cmd, uint8_t *data, uint8_t len) +{ + uint8_t buf[5]; + buf[0] = ((uint16_t)cmd >> 8) & 0xff; + buf[1] = (uint16_t)cmd & 0xff; + memcpy(&buf[2], data, len); + return transfer(&buf[0], len + 2, nullptr, 0); +} diff --git a/src/drivers/barometer/invensense/icp10111/ICP10111.hpp b/src/drivers/barometer/invensense/icp10111/ICP10111.hpp new file mode 100755 index 0000000000..01db28fa28 --- /dev/null +++ b/src/drivers/barometer/invensense/icp10111/ICP10111.hpp @@ -0,0 +1,98 @@ +/**************************************************************************** + * + * Copyright (C) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#pragma once + +#include "Inven_Sense_ICP10111_registers.hpp" + +#include +#include +#include +#include +#include + +using namespace Inven_Sense_ICP10111; + +class ICP10111 : public device::I2C, public I2CSPIDriver +{ +public: + ICP10111(const I2CSPIDriverConfig &config); + ~ICP10111() override; + + static void print_usage(); + + void RunImpl(); + + int init() override; + void print_status() override; + +private: + int probe() override; + + bool Reset(); + + bool Measure(); + + int8_t cal_crc(uint8_t seed, uint8_t data); + int read_measure_results(uint8_t *buf, uint8_t len); + int read_response(Cmd cmd, uint8_t *buf, uint8_t len); + int send_command(Cmd cmd); + int send_command(Cmd cmd, uint8_t *data, uint8_t len); + + PX4Barometer _px4_baro; + + perf_counter_t _reset_perf{perf_alloc(PC_COUNT, MODULE_NAME": reset")}; + perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")}; + perf_counter_t _bad_transfer_perf{perf_alloc(PC_COUNT, MODULE_NAME": bad transfer")}; + + hrt_abstime _reset_timestamp{0}; + int _failure_count{0}; + + unsigned _measure_interval{0}; + int16_t _scal[4]; + + enum class STATE : uint8_t { + RESET, + WAIT_FOR_RESET, + READ_OTP, + MEASURE, + READ + } _state{STATE::RESET}; + + enum class MODE : uint8_t { + FAST, + NORMAL, + ACCURATE, + VERY_ACCURATE + } _mode{MODE::VERY_ACCURATE}; +}; diff --git a/src/drivers/barometer/invensense/icp10111/Inven_Sense_ICP10111_registers.hpp b/src/drivers/barometer/invensense/icp10111/Inven_Sense_ICP10111_registers.hpp new file mode 100755 index 0000000000..907fa1b324 --- /dev/null +++ b/src/drivers/barometer/invensense/icp10111/Inven_Sense_ICP10111_registers.hpp @@ -0,0 +1,62 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/** + * @file icp10111_registers.hpp + * + * icp10111 registers. + * + */ + +#pragma once + +#include + +namespace Inven_Sense_ICP10111 +{ +static constexpr uint32_t I2C_SPEED = 100 * 1000; // 100 kHz I2C serial interface +static constexpr uint8_t I2C_ADDRESS_DEFAULT = 0x63; + +static constexpr uint8_t Product_ID = 0x08; + +enum class Cmd : uint16_t { + READ_ID = 0xefc8, + SET_ADDR = 0xc595, + READ_OTP = 0xc7f7, + MEAS_LP = 0x609c, + MEAS_N = 0x6825, + MEAS_LN = 0x70df, + MEAS_ULN = 0x7866, + SOFT_RESET = 0x805d +}; +} // namespace Inven_Sense_ICP10111 diff --git a/src/drivers/barometer/invensense/icp10111/icp10111_main.cpp b/src/drivers/barometer/invensense/icp10111/icp10111_main.cpp new file mode 100755 index 0000000000..c7cfb3d2ce --- /dev/null +++ b/src/drivers/barometer/invensense/icp10111/icp10111_main.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** + * + * Copyright (c) 2021 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER 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. + * + ****************************************************************************/ + +#include +#include +#include + +#include "ICP10111.hpp" + +void +ICP10111::print_usage() +{ + PRINT_MODULE_USAGE_NAME("icp10111", "driver"); + PRINT_MODULE_USAGE_SUBCATEGORY("baro"); + PRINT_MODULE_USAGE_COMMAND("start"); + PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false); + PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x63); + PRINT_MODULE_USAGE_DEFAULT_COMMANDS(); +} + +extern "C" int icp10111_main(int argc, char *argv[]) +{ + using ThisDriver = ICP10111; + BusCLIArguments cli{true, false}; + cli.i2c_address = I2C_ADDRESS_DEFAULT; + cli.default_i2c_frequency = I2C_SPEED; + + const char *verb = cli.parseDefaultArguments(argc, argv); + + if (!verb) { + ThisDriver::print_usage(); + return -1; + } + + BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP10111); + + if (!strcmp(verb, "start")) { + return ThisDriver::module_start(cli, iterator); + + } else if (!strcmp(verb, "stop")) { + return ThisDriver::module_stop(iterator); + + } else if (!strcmp(verb, "status")) { + return ThisDriver::module_status(iterator); + } + + ThisDriver::print_usage(); + return -1; +}