mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
drivers: add support for ICP101XX and ICP201XX
This commit is contained in:
parent
9493008dbb
commit
21daa0f398
@ -9,7 +9,9 @@ menu "barometer"
|
||||
select DRIVERS_BAROMETER_LPS33HW
|
||||
select DRIVERS_BAROMETER_MS5611
|
||||
select DRIVERS_BAROMETER_MAIERTEK_MPC2520
|
||||
select DRIVERS_BAROMETER_GOERTEK_SPL06
|
||||
select DRIVERS_BAROMETER_GOERTEK_SPL06
|
||||
select DRIVERS_BAROMETER_INVENSENSE_ICP101XX
|
||||
select DRIVERS_BAROMETER_INVENSENSE_ICP201XX
|
||||
---help---
|
||||
Enable default set of barometer drivers
|
||||
rsource "*/Kconfig"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2022 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
|
||||
@ -31,5 +31,5 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
add_subdirectory(icp10100)
|
||||
add_subdirectory(icp10111)
|
||||
add_subdirectory(icp101xx)
|
||||
add_subdirectory(icp201xx)
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
menu "Invensense"
|
||||
menu "InvenSense"
|
||||
rsource "*/Kconfig"
|
||||
endmenu #Invensense
|
||||
endmenu #InvenSense
|
||||
|
||||
@ -1,378 +0,0 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
float temperature = _temperature_C;
|
||||
float pressure = _pressure_Pa; // to Pascal
|
||||
|
||||
// publish
|
||||
sensor_baro_s sensor_baro{};
|
||||
sensor_baro.timestamp_sample = now;
|
||||
sensor_baro.device_id = get_device_id();
|
||||
sensor_baro.pressure = pressure;
|
||||
sensor_baro.temperature = temperature;
|
||||
sensor_baro.error_count = perf_event_count(_bad_transfer_perf);
|
||||
sensor_baro.timestamp = hrt_absolute_time();
|
||||
_sensor_baro_pub.publish(sensor_baro);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2021-2022 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
|
||||
@ -32,14 +32,14 @@
|
||||
############################################################################
|
||||
|
||||
px4_add_module(
|
||||
MODULE drivers__barometer__invensense__icp10111
|
||||
MAIN icp10111
|
||||
MODULE drivers__invensense__icp101xx
|
||||
MAIN icp101xx
|
||||
COMPILE_FLAGS
|
||||
SRCS
|
||||
Inven_Sense_ICP10111_registers.hpp
|
||||
ICP10111.cpp
|
||||
ICP10111.hpp
|
||||
icp10111_main.cpp
|
||||
Inven_Sense_ICP101XX_registers.hpp
|
||||
ICP101XX.cpp
|
||||
ICP101XX.hpp
|
||||
icp101xx_main.cpp
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2021-2022 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
|
||||
@ -31,17 +31,17 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include "ICP10100.hpp"
|
||||
#include "ICP101XX.hpp"
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
ICP10100::ICP10100(const I2CSPIDriverConfig &config) :
|
||||
ICP101XX::ICP101XX(const I2CSPIDriverConfig &config) :
|
||||
I2C(config),
|
||||
I2CSPIDriver(config)
|
||||
{
|
||||
}
|
||||
|
||||
ICP10100::~ICP10100()
|
||||
ICP101XX::~ICP101XX()
|
||||
{
|
||||
perf_free(_reset_perf);
|
||||
perf_free(_sample_perf);
|
||||
@ -49,7 +49,7 @@ ICP10100::~ICP10100()
|
||||
}
|
||||
|
||||
int
|
||||
ICP10100::init()
|
||||
ICP101XX::init()
|
||||
{
|
||||
int ret = I2C::init();
|
||||
|
||||
@ -62,7 +62,7 @@ ICP10100::init()
|
||||
}
|
||||
|
||||
bool
|
||||
ICP10100::Reset()
|
||||
ICP101XX::Reset()
|
||||
{
|
||||
_state = STATE::RESET;
|
||||
ScheduleClear();
|
||||
@ -71,7 +71,7 @@ ICP10100::Reset()
|
||||
}
|
||||
|
||||
void
|
||||
ICP10100::print_status()
|
||||
ICP101XX::print_status()
|
||||
{
|
||||
I2CSPIDriverBase::print_status();
|
||||
perf_print_counter(_reset_perf);
|
||||
@ -80,7 +80,7 @@ ICP10100::print_status()
|
||||
}
|
||||
|
||||
int
|
||||
ICP10100::probe()
|
||||
ICP101XX::probe()
|
||||
{
|
||||
uint16_t ID = 0;
|
||||
read_response(Cmd::READ_ID, (uint8_t *)&ID, 2);
|
||||
@ -95,7 +95,7 @@ ICP10100::probe()
|
||||
}
|
||||
|
||||
void
|
||||
ICP10100::RunImpl()
|
||||
ICP101XX::RunImpl()
|
||||
{
|
||||
const hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
@ -276,7 +276,7 @@ ICP10100::RunImpl()
|
||||
}
|
||||
|
||||
bool
|
||||
ICP10100::Measure()
|
||||
ICP101XX::Measure()
|
||||
{
|
||||
/*
|
||||
From ds-000186-icp-101xx-v1.0.pdf, page 6, table 1
|
||||
@ -321,7 +321,7 @@ ICP10100::Measure()
|
||||
}
|
||||
|
||||
int8_t
|
||||
ICP10100::cal_crc(uint8_t seed, uint8_t data)
|
||||
ICP101XX::cal_crc(uint8_t seed, uint8_t data)
|
||||
{
|
||||
int8_t poly = 0x31;
|
||||
int8_t var2;
|
||||
@ -344,13 +344,13 @@ ICP10100::cal_crc(uint8_t seed, uint8_t data)
|
||||
}
|
||||
|
||||
int
|
||||
ICP10100::read_measure_results(uint8_t *buf, uint8_t len)
|
||||
ICP101XX::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)
|
||||
ICP101XX::read_response(Cmd cmd, uint8_t *buf, uint8_t len)
|
||||
{
|
||||
uint8_t buff[2];
|
||||
buff[0] = ((uint16_t)cmd >> 8) & 0xff;
|
||||
@ -359,7 +359,7 @@ ICP10100::read_response(Cmd cmd, uint8_t *buf, uint8_t len)
|
||||
}
|
||||
|
||||
int
|
||||
ICP10100::send_command(Cmd cmd)
|
||||
ICP101XX::send_command(Cmd cmd)
|
||||
{
|
||||
uint8_t buf[2];
|
||||
buf[0] = ((uint16_t)cmd >> 8) & 0xff;
|
||||
@ -368,7 +368,7 @@ ICP10100::send_command(Cmd cmd)
|
||||
}
|
||||
|
||||
int
|
||||
ICP10100::send_command(Cmd cmd, uint8_t *data, uint8_t len)
|
||||
ICP101XX::send_command(Cmd cmd, uint8_t *data, uint8_t len)
|
||||
{
|
||||
uint8_t buf[5];
|
||||
buf[0] = ((uint16_t)cmd >> 8) & 0xff;
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2021-2022 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
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Inven_Sense_ICP10111_registers.hpp"
|
||||
#include "Inven_Sense_ICP101XX_registers.hpp"
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <lib/drivers/device/i2c.h>
|
||||
@ -42,13 +42,13 @@
|
||||
#include <lib/perf/perf_counter.h>
|
||||
#include <px4_platform_common/i2c_spi_buses.h>
|
||||
|
||||
using namespace Inven_Sense_ICP10111;
|
||||
using namespace Inven_Sense_ICP101XX;
|
||||
|
||||
class ICP10111 : public device::I2C, public I2CSPIDriver<ICP10111>
|
||||
class ICP101XX : public device::I2C, public I2CSPIDriver<ICP101XX>
|
||||
{
|
||||
public:
|
||||
ICP10111(const I2CSPIDriverConfig &config);
|
||||
~ICP10111() override;
|
||||
ICP101XX(const I2CSPIDriverConfig &config);
|
||||
~ICP101XX() override;
|
||||
|
||||
static void print_usage();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2021-2022 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
|
||||
@ -32,9 +32,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file icp10111_registers.hpp
|
||||
* @file icp101xx_registers.hpp
|
||||
*
|
||||
* icp10111 registers.
|
||||
* icp101xx registers.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Inven_Sense_ICP10111
|
||||
namespace Inven_Sense_ICP101XX
|
||||
{
|
||||
static constexpr uint32_t I2C_SPEED = 100 * 1000; // 100 kHz I2C serial interface
|
||||
static constexpr uint8_t I2C_ADDRESS_DEFAULT = 0x63;
|
||||
@ -59,4 +59,4 @@ enum class Cmd : uint16_t {
|
||||
MEAS_ULN = 0x7866,
|
||||
SOFT_RESET = 0x805d
|
||||
};
|
||||
} // namespace Inven_Sense_ICP10111
|
||||
} // namespace Inven_Sense_ICP101XX
|
||||
5
src/drivers/barometer/invensense/icp101xx/Kconfig
Executable file
5
src/drivers/barometer/invensense/icp101xx/Kconfig
Executable file
@ -0,0 +1,5 @@
|
||||
menuconfig DRIVERS_BAROMETER_INVENSENSE_ICP101XX
|
||||
bool "icp101xx"
|
||||
default n
|
||||
---help---
|
||||
Enable support for icp101xx
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2021-2022 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
|
||||
@ -35,12 +35,12 @@
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
|
||||
#include "ICP10111.hpp"
|
||||
#include "ICP101XX.hpp"
|
||||
|
||||
void
|
||||
ICP10111::print_usage()
|
||||
ICP101XX::print_usage()
|
||||
{
|
||||
PRINT_MODULE_USAGE_NAME("icp10111", "driver");
|
||||
PRINT_MODULE_USAGE_NAME("icp101xx", "driver");
|
||||
PRINT_MODULE_USAGE_SUBCATEGORY("baro");
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
|
||||
@ -48,9 +48,9 @@ ICP10111::print_usage()
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
}
|
||||
|
||||
extern "C" int icp10111_main(int argc, char *argv[])
|
||||
extern "C" int icp101xx_main(int argc, char *argv[])
|
||||
{
|
||||
using ThisDriver = ICP10111;
|
||||
using ThisDriver = ICP101XX;
|
||||
BusCLIArguments cli{true, false};
|
||||
cli.i2c_address = I2C_ADDRESS_DEFAULT;
|
||||
cli.default_i2c_frequency = I2C_SPEED;
|
||||
@ -62,7 +62,7 @@ extern "C" int icp10111_main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP10111);
|
||||
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP101XX);
|
||||
|
||||
if (!strcmp(verb, "start")) {
|
||||
return ThisDriver::module_start(cli, iterator);
|
||||
@ -1,6 +1,6 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
# Copyright (c) 2022 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
|
||||
@ -32,14 +32,14 @@
|
||||
############################################################################
|
||||
|
||||
px4_add_module(
|
||||
MODULE drivers__barometer__invensense__icp10100
|
||||
MAIN icp10100
|
||||
MODULE drivers__invensense__icp201xx
|
||||
MAIN icp201xx
|
||||
COMPILE_FLAGS
|
||||
SRCS
|
||||
Inven_Sense_ICP10100_registers.hpp
|
||||
ICP10100.cpp
|
||||
ICP10100.hpp
|
||||
icp10100_main.cpp
|
||||
Inven_Sense_ICP201XX_registers.hpp
|
||||
ICP201XX.cpp
|
||||
ICP201XX.hpp
|
||||
icp201xx_main.cpp
|
||||
DEPENDS
|
||||
px4_work_queue
|
||||
)
|
||||
521
src/drivers/barometer/invensense/icp201xx/ICP201XX.cpp
Executable file
521
src/drivers/barometer/invensense/icp201xx/ICP201XX.cpp
Executable file
@ -0,0 +1,521 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2022 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 "ICP201XX.hpp"
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace time_literals;
|
||||
|
||||
ICP201XX::ICP201XX(const I2CSPIDriverConfig &config) :
|
||||
I2C(config),
|
||||
I2CSPIDriver(config)
|
||||
{
|
||||
}
|
||||
|
||||
ICP201XX::~ICP201XX()
|
||||
{
|
||||
perf_free(_reset_perf);
|
||||
perf_free(_sample_perf);
|
||||
perf_free(_bad_transfer_perf);
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::init()
|
||||
{
|
||||
int ret = I2C::init();
|
||||
|
||||
if (ret != PX4_OK) {
|
||||
DEVICE_DEBUG("I2C::init failed (%i)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return Reset() ? 0 : -1;
|
||||
}
|
||||
|
||||
bool
|
||||
ICP201XX::Reset()
|
||||
{
|
||||
_state = STATE::SOFT_RESET;
|
||||
ScheduleClear();
|
||||
ScheduleNow();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ICP201XX::print_status()
|
||||
{
|
||||
I2CSPIDriverBase::print_status();
|
||||
perf_print_counter(_reset_perf);
|
||||
perf_print_counter(_sample_perf);
|
||||
perf_print_counter(_bad_transfer_perf);
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::probe()
|
||||
{
|
||||
uint8_t device_id = 0;
|
||||
uint8_t ver = 0xFF;
|
||||
read_reg(Register::DEVICE_ID, &device_id);
|
||||
read_reg(Register::VERSION, &ver);
|
||||
|
||||
if (device_id != EXPECTED_DEVICE_ID) {
|
||||
DEVICE_DEBUG("unexpected device id 0x%02x", device_id);
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
if (ver != 0x00 && ver != 0xB2) {
|
||||
DEVICE_DEBUG("unexpected version 0x%02x", ver);
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ICP201XX::RunImpl()
|
||||
{
|
||||
const hrt_abstime now = hrt_absolute_time();
|
||||
|
||||
switch (_state) {
|
||||
case STATE::SOFT_RESET: {
|
||||
/* Stop the measurement */
|
||||
mode_select(0x00);
|
||||
|
||||
ScheduleDelayed(2_ms);
|
||||
|
||||
/* Flush FIFO */
|
||||
flush_fifo();
|
||||
|
||||
/* Mask all interrupts */
|
||||
write_reg(Register::FIFO_CONFIG, 0x00);
|
||||
write_reg(Register::INTERRUPT_MASK, 0xFF);
|
||||
|
||||
_reset_timestamp = now;
|
||||
_failure_count = 0;
|
||||
perf_count(_reset_perf);
|
||||
_state = STATE::OTP_BOOTUP_CFG;
|
||||
ScheduleDelayed(10_ms);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE::OTP_BOOTUP_CFG: {
|
||||
uint8_t reg_value = 0;
|
||||
uint8_t offset = 0, gain = 0, Hfosc = 0;
|
||||
uint8_t version = 0;
|
||||
uint8_t bootup_status = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* read version register */
|
||||
if (read_reg(Register::VERSION, &version) != PX4_OK) {
|
||||
ScheduleDelayed(10_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
if (version == 0xB2) {
|
||||
/* B2 version Asic is detected. Boot up sequence is not required for B2 Asic, so returning */
|
||||
_state = STATE::CONFIG;
|
||||
ScheduleDelayed(10_ms);
|
||||
}
|
||||
|
||||
/* Read boot up status and avoid re running boot up sequence if it is already done */
|
||||
if (read_reg(Register::OTP_MTP_OTP_STATUS2, &bootup_status) != PX4_OK) {
|
||||
ScheduleDelayed(10_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bootup_status & 0x01) {
|
||||
/* Boot up sequence is already done, not required to repeat boot up sequence */
|
||||
_state = STATE::CONFIG;
|
||||
ScheduleDelayed(10_ms);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Bring the ASIC in power mode to activate the OTP power domain and get access to the main registers */
|
||||
mode_select(0x04);
|
||||
usleep(4_ms);
|
||||
|
||||
/* Unlock the main registers */
|
||||
write_reg(Register::MASTER_LOCK, 0x1F);
|
||||
|
||||
/* Enable the OTP and the write switch */
|
||||
read_reg(Register::OTP_MTP_OTP_CFG1, ®_value);
|
||||
reg_value |= 0x03;
|
||||
write_reg(Register::OTP_MTP_OTP_CFG1, reg_value);
|
||||
usleep(10_us);
|
||||
|
||||
/* Toggle the OTP reset pin */
|
||||
read_reg(Register::OTP_DEBUG2, ®_value);
|
||||
reg_value |= 1 << 7;
|
||||
write_reg(Register::OTP_DEBUG2, reg_value);
|
||||
usleep(10_us);
|
||||
|
||||
read_reg(Register::OTP_DEBUG2, ®_value);
|
||||
reg_value &= ~(1 << 7);
|
||||
write_reg(Register::OTP_DEBUG2, reg_value);
|
||||
usleep(10_us);
|
||||
|
||||
/* Program redundant read */
|
||||
write_reg(Register::OTP_MTP_MRA_LSB, 0x04);
|
||||
write_reg(Register::OTP_MTP_MRA_MSB, 0x04);
|
||||
write_reg(Register::OTP_MTP_MRB_LSB, 0x21);
|
||||
write_reg(Register::OTP_MTP_MRB_MSB, 0x20);
|
||||
write_reg(Register::OTP_MTP_MR_LSB, 0x10);
|
||||
write_reg(Register::OTP_MTP_MR_MSB, 0x80);
|
||||
|
||||
/* Read the data from register */
|
||||
ret |= read_otp_data(0xF8, 0x10, &offset);
|
||||
ret |= read_otp_data(0xF9, 0x10, &gain);
|
||||
ret |= read_otp_data(0xFA, 0x10, &Hfosc);
|
||||
ScheduleDelayed(10_us);
|
||||
|
||||
/* Write OTP values to main registers */
|
||||
ret |= read_reg(Register::TRIM1_MSB, ®_value);
|
||||
|
||||
if (ret == 0) {
|
||||
reg_value = (reg_value & (~0x3F)) | (offset & 0x3F);
|
||||
ret |= write_reg(Register::TRIM1_MSB, reg_value);
|
||||
}
|
||||
|
||||
ret |= read_reg(Register::TRIM2_MSB, ®_value);
|
||||
|
||||
if (ret == 0) {
|
||||
reg_value = (reg_value & (~0x70)) | ((gain & 0x07) << 4);
|
||||
ret |= write_reg(Register::TRIM2_MSB, reg_value);
|
||||
}
|
||||
|
||||
ret |= read_reg(Register::TRIM2_LSB, ®_value);
|
||||
|
||||
if (ret == 0) {
|
||||
reg_value = (reg_value & (~0x7F)) | (Hfosc & 0x7F);
|
||||
ret |= write_reg(Register::TRIM2_LSB, reg_value);
|
||||
}
|
||||
|
||||
ScheduleDelayed(10_us);
|
||||
|
||||
/* Update boot up status to 1 */
|
||||
if (ret == 0) {
|
||||
ret |= read_reg(Register::OTP_MTP_OTP_STATUS2, ®_value);
|
||||
|
||||
if (ret == 0) {
|
||||
reg_value |= 0x01;
|
||||
ret |= write_reg(Register::OTP_MTP_OTP_STATUS2, reg_value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable OTP and write switch */
|
||||
read_reg(Register::OTP_MTP_OTP_CFG1, ®_value);
|
||||
reg_value &= ~0x03;
|
||||
write_reg(Register::OTP_MTP_OTP_CFG1, reg_value);
|
||||
|
||||
/* Lock the main register */
|
||||
write_reg(Register::MASTER_LOCK, 0x00);
|
||||
|
||||
/* Move to standby */
|
||||
mode_select(0x00);
|
||||
|
||||
ScheduleDelayed(10_ms);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE::CONFIG: {
|
||||
if (configure()) {
|
||||
_state = STATE::WAIT_READ;
|
||||
ScheduleDelayed(10_ms);
|
||||
|
||||
} else {
|
||||
if (hrt_elapsed_time(&_reset_timestamp) > 1000_ms) {
|
||||
PX4_WARN("Configure failed, resetting");
|
||||
_state = STATE::SOFT_RESET;
|
||||
|
||||
} else {
|
||||
PX4_WARN("Configure failed, retrying");
|
||||
}
|
||||
|
||||
ScheduleDelayed(100_ms);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE::WAIT_READ: {
|
||||
/*
|
||||
* If FIR filter is enabled, it will cause a settling effect on the first 14 pressure values.
|
||||
* Therefore the first 14 pressure output values are discarded.
|
||||
**/
|
||||
uint8_t fifo_packets = 0;
|
||||
uint8_t fifo_packets_to_skip = 14;
|
||||
|
||||
do {
|
||||
ScheduleDelayed(10_ms);
|
||||
read_reg(Register::FIFO_FILL, &fifo_packets);
|
||||
fifo_packets = (uint8_t)(fifo_packets & 0x1F);
|
||||
} while (fifo_packets >= fifo_packets_to_skip);
|
||||
|
||||
flush_fifo();
|
||||
fifo_packets = 0;
|
||||
|
||||
do {
|
||||
ScheduleDelayed(10_ms);
|
||||
read_reg(Register::FIFO_FILL, &fifo_packets);
|
||||
fifo_packets = (uint8_t)(fifo_packets & 0x1F);
|
||||
} while (fifo_packets == 0);
|
||||
|
||||
_state = STATE::READ;
|
||||
perf_begin(_sample_perf);
|
||||
ScheduleOnInterval(1_s / 30);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE::READ: {
|
||||
bool success = false;
|
||||
float pressure, temperature;
|
||||
|
||||
if (get_sensor_data(&pressure, &temperature)) {
|
||||
perf_end(_sample_perf);
|
||||
perf_begin(_sample_perf);
|
||||
|
||||
sensor_baro_s sensor_baro{};
|
||||
sensor_baro.timestamp_sample = now;
|
||||
sensor_baro.device_id = get_device_id();
|
||||
sensor_baro.pressure = pressure;
|
||||
sensor_baro.temperature = temperature;
|
||||
sensor_baro.error_count = perf_event_count(_bad_transfer_perf);
|
||||
sensor_baro.timestamp = hrt_absolute_time();
|
||||
_sensor_baro_pub.publish(sensor_baro);
|
||||
|
||||
success = true;
|
||||
|
||||
if (_failure_count > 0) {
|
||||
_failure_count--;
|
||||
}
|
||||
|
||||
} else {
|
||||
perf_count(_bad_transfer_perf);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
_failure_count++;
|
||||
|
||||
if (_failure_count > 10) {
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ICP201XX::dummy_reg()
|
||||
{
|
||||
do {
|
||||
uint8_t reg = (uint8_t)Register::EMPTY;
|
||||
uint8_t val = 0;
|
||||
transfer((uint8_t *)®, 1, &val, 1);
|
||||
} while (0);
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::read_reg(Register reg, uint8_t *buf, uint8_t len)
|
||||
{
|
||||
int ret;
|
||||
ret = transfer((uint8_t *)®, 1, buf, len);
|
||||
dummy_reg();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::read_reg(Register reg, uint8_t *val)
|
||||
{
|
||||
return read_reg(reg, val, 1);
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::write_reg(Register reg, uint8_t val)
|
||||
{
|
||||
uint8_t data[2] = { (uint8_t)reg, val };
|
||||
int ret;
|
||||
ret = transfer(data, sizeof(data), nullptr, 0);
|
||||
dummy_reg();
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::mode_select(uint8_t mode)
|
||||
{
|
||||
uint8_t mode_sync_status = 0;
|
||||
|
||||
do {
|
||||
read_reg(Register::DEVICE_STATUS, &mode_sync_status, 1);
|
||||
|
||||
if (mode_sync_status & 0x01) {
|
||||
break;
|
||||
}
|
||||
|
||||
ScheduleDelayed(500_us);
|
||||
} while (1);
|
||||
|
||||
if (write_reg(Register::MODE_SELECT, mode) != PX4_OK) {
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
int
|
||||
ICP201XX::read_otp_data(uint8_t addr, uint8_t cmd, uint8_t *val)
|
||||
{
|
||||
uint8_t otp_status = 0xFF;
|
||||
|
||||
/* Write the address content and read command */
|
||||
if (write_reg(Register::OTP_MTP_OTP_ADDR, addr) != PX4_OK) {
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
if (write_reg(Register::OTP_MTP_OTP_CMD, cmd) != PX4_OK) {
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
/* Wait for the OTP read to finish Monitor otp_status */
|
||||
do {
|
||||
read_reg(Register::OTP_MTP_OTP_STATUS, &otp_status);
|
||||
|
||||
if (otp_status == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ScheduleDelayed(1_us);
|
||||
} while (1);
|
||||
|
||||
/* Read the data from register */
|
||||
if (read_reg(Register::OTP_MTP_RD_DATA, val) != PX4_OK) {
|
||||
return PX4_ERROR;
|
||||
}
|
||||
|
||||
return PX4_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
ICP201XX::get_sensor_data(float *pressure, float *temperature)
|
||||
{
|
||||
bool success = false;
|
||||
uint8_t fifo_packets = 0;
|
||||
uint8_t fifo_data[96] {0};
|
||||
int32_t data_temp[16] {0};
|
||||
int32_t data_press[16] {0};
|
||||
|
||||
if (read_reg(Register::FIFO_FILL, &fifo_packets) == PX4_OK) {
|
||||
fifo_packets = (uint8_t)(fifo_packets & 0x1F);
|
||||
|
||||
if (fifo_packets > 0 && fifo_packets <= 16 && !read_reg(Register::FIFO_BASE, fifo_data, fifo_packets * 2 * 3)) {
|
||||
uint8_t offset = 0;
|
||||
|
||||
for (uint8_t i = 0; i < fifo_packets; i++) {
|
||||
data_press[i] = (int32_t)(((fifo_data[offset + 2] & 0x0f) << 16) | (fifo_data[offset + 1] << 8) | fifo_data[offset]) ;
|
||||
offset += 3;
|
||||
data_temp[i] = (int32_t)(((fifo_data[offset + 2] & 0x0f) << 16) | (fifo_data[offset + 1] << 8) | fifo_data[offset]) ;
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
*pressure = 0;
|
||||
*temperature = 0;
|
||||
|
||||
for (uint8_t i = 0; i < fifo_packets; i++) {
|
||||
/** P = (POUT/2^17)*40kPa + 70kPa **/
|
||||
if (data_press[i] & 0x080000) {
|
||||
data_press[i] |= 0xFFF00000;
|
||||
}
|
||||
|
||||
*pressure += ((float)(data_press[i]) * 40 / 131072) + 70;
|
||||
|
||||
/* T = (TOUT/2^18)*65C + 25C */
|
||||
if (data_temp[i] & 0x080000) {
|
||||
data_temp[i] |= 0xFFF00000;
|
||||
}
|
||||
|
||||
*temperature += ((float)(data_temp[i]) * 65 / 262144) + 25;
|
||||
}
|
||||
|
||||
*pressure = *pressure * 1000 / fifo_packets;
|
||||
*temperature = *temperature / fifo_packets;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool
|
||||
ICP201XX::configure()
|
||||
{
|
||||
uint8_t reg_value = 0;
|
||||
|
||||
/* Initiate Triggered Operation: Stay in Standby mode */
|
||||
reg_value |= (reg_value & (~0x10)) | ((uint8_t)_forced_meas_trigger << 4);
|
||||
|
||||
/* Power Mode Selection: Normal Mode */
|
||||
reg_value |= (reg_value & (~0x04)) | ((uint8_t)_power_mode << 2);
|
||||
|
||||
/* FIFO Readout Mode Selection: Pressure first. */
|
||||
reg_value |= (reg_value & (~0x03)) | ((uint8_t)(_fifo_readout_mode));
|
||||
|
||||
/* Measurement Configuration: Mode2*/
|
||||
reg_value |= (reg_value & (~0xE0)) | (((uint8_t)_op_mode) << 5);
|
||||
|
||||
/* Measurement Mode Selection: Continuous Measurements (duty cycled) */
|
||||
reg_value |= (reg_value & (~0x08)) | ((uint8_t)_meas_mode << 3);
|
||||
|
||||
if (mode_select(reg_value) != PX4_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICP201XX::flush_fifo()
|
||||
{
|
||||
uint8_t reg_value;
|
||||
|
||||
if (read_reg(Register::FIFO_FILL, ®_value) != PX4_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
reg_value |= 0x80;
|
||||
|
||||
if (write_reg(Register::FIFO_FILL, reg_value) != PX4_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (C) 2022 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
|
||||
@ -33,7 +33,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Inven_Sense_ICP10100_registers.hpp"
|
||||
#include "Inven_Sense_ICP201XX_registers.hpp"
|
||||
|
||||
#include <drivers/drv_hrt.h>
|
||||
#include <lib/drivers/device/i2c.h>
|
||||
@ -42,13 +42,13 @@
|
||||
#include <lib/perf/perf_counter.h>
|
||||
#include <px4_platform_common/i2c_spi_buses.h>
|
||||
|
||||
using namespace Inven_Sense_ICP10100;
|
||||
using namespace Inven_Sense_ICP201XX;
|
||||
|
||||
class ICP10100 : public device::I2C, public I2CSPIDriver<ICP10100>
|
||||
class ICP201XX : public device::I2C, public I2CSPIDriver<ICP201XX>
|
||||
{
|
||||
public:
|
||||
ICP10100(const I2CSPIDriverConfig &config);
|
||||
~ICP10100() override;
|
||||
ICP201XX(const I2CSPIDriverConfig &config);
|
||||
~ICP201XX() override;
|
||||
|
||||
static void print_usage();
|
||||
|
||||
@ -62,13 +62,15 @@ private:
|
||||
|
||||
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);
|
||||
int read_reg(Register reg, uint8_t *val);
|
||||
int read_reg(Register reg, uint8_t *buf, uint8_t len);
|
||||
int write_reg(Register reg, uint8_t val);
|
||||
int read_otp_data(uint8_t addr, uint8_t cmd, uint8_t *dat);
|
||||
bool get_sensor_data(float *pressure, float *temperature);
|
||||
int mode_select(uint8_t mode);
|
||||
void dummy_reg();
|
||||
bool flush_fifo();
|
||||
bool configure();
|
||||
|
||||
uORB::PublicationMulti<sensor_baro_s> _sensor_baro_pub{ORB_ID(sensor_baro)};
|
||||
|
||||
@ -79,21 +81,37 @@ private:
|
||||
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,
|
||||
SOFT_RESET = 0,
|
||||
OTP_BOOTUP_CFG,
|
||||
CONFIG,
|
||||
WAIT_READ,
|
||||
READ
|
||||
} _state{STATE::RESET};
|
||||
} _state{STATE::SOFT_RESET};
|
||||
|
||||
enum class MODE : uint8_t {
|
||||
FAST,
|
||||
NORMAL,
|
||||
ACCURATE,
|
||||
VERY_ACCURATE
|
||||
} _mode{MODE::VERY_ACCURATE};
|
||||
enum class OP_MODE : uint8_t {
|
||||
OP_MODE0 = 0, /* Mode 0: Bw:6.25 Hz ODR: 25Hz */
|
||||
OP_MODE1, /* Mode 1: Bw:30 Hz ODR: 120Hz */
|
||||
OP_MODE2, /* Mode 2: Bw:10 Hz ODR: 40Hz */
|
||||
OP_MODE3, /* Mode 3: Bw:0.5 Hz ODR: 2Hz */
|
||||
OP_MODE4, /* Mode 4: User configurable Mode */
|
||||
} _op_mode{OP_MODE::OP_MODE2};
|
||||
enum class FIFO_READOUT_MODE : uint8_t {
|
||||
FIFO_READOUT_MODE_PRES_TEMP = 0, /* Pressure and temperature as pair and address wraps to the start address of the Pressure value ( pressure first ) */
|
||||
FIFO_READOUT_MODE_TEMP_ONLY = 1, /* Temperature only reporting */
|
||||
FIFO_READOUT_MODE_TEMP_PRES = 2, /* Pressure and temperature as pair and address wraps to the start address of the Temperature value ( Temperature first ) */
|
||||
FIFO_READOUT_MODE_PRES_ONLY = 3 /* Pressure only reporting */
|
||||
} _fifo_readout_mode{FIFO_READOUT_MODE::FIFO_READOUT_MODE_PRES_TEMP};
|
||||
enum class POWER_MODE : uint8_t {
|
||||
POWER_MODE_NORMAL = 0, /* Normal Mode: Device is in standby and goes to active mode during the execution of a measurement */
|
||||
POWER_MODE_ACTIVE = 1 /* Active Mode: Power on DVDD and enable the high frequency clock */
|
||||
} _power_mode{POWER_MODE::POWER_MODE_NORMAL};
|
||||
enum MEAS_MODE : uint8_t {
|
||||
MEAS_MODE_FORCED_TRIGGER = 0, /* Force trigger mode based on icp201xx_forced_meas_trigger_t **/
|
||||
MEAS_MODE_CONTINUOUS = 1 /* Continuous measurements based on selected mode ODR settings*/
|
||||
} _meas_mode{MEAS_MODE::MEAS_MODE_CONTINUOUS};
|
||||
enum FORCED_MEAS_TRIGGER : uint8_t {
|
||||
FORCE_MEAS_STANDBY = 0, /* Stay in Stand by */
|
||||
FORCE_MEAS_TRIGGER_FORCE_MEAS = 1 /* Trigger for forced measurements */
|
||||
} _forced_meas_trigger{FORCED_MEAS_TRIGGER::FORCE_MEAS_STANDBY};
|
||||
};
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2022 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
|
||||
@ -32,9 +32,9 @@
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file icp10100_registers.hpp
|
||||
* @file icp201xx_registers.hpp
|
||||
*
|
||||
* icp10100 registers.
|
||||
* icp201xx registers.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -42,21 +42,45 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Inven_Sense_ICP10100
|
||||
namespace Inven_Sense_ICP201XX
|
||||
{
|
||||
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 EXPECTED_DEVICE_ID = 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
|
||||
enum class Register : uint8_t {
|
||||
EMPTY = 0x00,
|
||||
TRIM1_MSB = 0x05,
|
||||
TRIM2_LSB = 0x06,
|
||||
TRIM2_MSB = 0x07,
|
||||
DEVICE_ID = 0x0C,
|
||||
OTP_MTP_OTP_CFG1 = 0xAC,
|
||||
OTP_MTP_MR_LSB = 0xAD,
|
||||
OTP_MTP_MR_MSB = 0xAE,
|
||||
OTP_MTP_MRA_LSB = 0xAF,
|
||||
OTP_MTP_MRA_MSB = 0xB0,
|
||||
OTP_MTP_MRB_LSB = 0xB1,
|
||||
OTP_MTP_MRB_MSB = 0xB2,
|
||||
OTP_MTP_OTP_ADDR = 0xB5,
|
||||
OTP_MTP_OTP_CMD = 0xB6,
|
||||
OTP_MTP_RD_DATA = 0xB8,
|
||||
OTP_MTP_OTP_STATUS = 0xB9,
|
||||
OTP_DEBUG2 = 0xBC,
|
||||
MASTER_LOCK = 0xBE,
|
||||
OTP_MTP_OTP_STATUS2 = 0xBF,
|
||||
MODE_SELECT = 0xC0,
|
||||
INTERRUPT_STATUS = 0xC1,
|
||||
INTERRUPT_MASK = 0xC2,
|
||||
FIFO_CONFIG = 0xC3,
|
||||
FIFO_FILL = 0xC4,
|
||||
SPI_MODE = 0xC5,
|
||||
PRESS_ABS_LSB = 0xC7,
|
||||
PRESS_ABS_MSB = 0xC8,
|
||||
PRESS_DELTA_LSB = 0xC9,
|
||||
PRESS_DELTA_MSB = 0xCA,
|
||||
DEVICE_STATUS = 0xCD,
|
||||
I3C_INFO = 0xCE,
|
||||
VERSION = 0xD3,
|
||||
FIFO_BASE = 0xFA
|
||||
};
|
||||
} // namespace Inven_Sense_ICP10100
|
||||
} // namespace Inven_Sense_ICP201XX
|
||||
5
src/drivers/barometer/invensense/icp201xx/Kconfig
Executable file
5
src/drivers/barometer/invensense/icp201xx/Kconfig
Executable file
@ -0,0 +1,5 @@
|
||||
menuconfig DRIVERS_BAROMETER_INVENSENSE_ICP201XX
|
||||
bool "icp201xx"
|
||||
default n
|
||||
---help---
|
||||
Enable support for icp201xx
|
||||
@ -1,6 +1,6 @@
|
||||
/****************************************************************************
|
||||
*
|
||||
* Copyright (c) 2021 PX4 Development Team. All rights reserved.
|
||||
* Copyright (c) 2022 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
|
||||
@ -35,12 +35,12 @@
|
||||
#include <px4_platform_common/getopt.h>
|
||||
#include <px4_platform_common/module.h>
|
||||
|
||||
#include "ICP10100.hpp"
|
||||
#include "ICP201XX.hpp"
|
||||
|
||||
void
|
||||
ICP10100::print_usage()
|
||||
ICP201XX::print_usage()
|
||||
{
|
||||
PRINT_MODULE_USAGE_NAME("icp10100", "driver");
|
||||
PRINT_MODULE_USAGE_NAME("icp201xx", "driver");
|
||||
PRINT_MODULE_USAGE_SUBCATEGORY("baro");
|
||||
PRINT_MODULE_USAGE_COMMAND("start");
|
||||
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
|
||||
@ -48,9 +48,9 @@ ICP10100::print_usage()
|
||||
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
|
||||
}
|
||||
|
||||
extern "C" int icp10100_main(int argc, char *argv[])
|
||||
extern "C" int icp201xx_main(int argc, char *argv[])
|
||||
{
|
||||
using ThisDriver = ICP10100;
|
||||
using ThisDriver = ICP201XX;
|
||||
BusCLIArguments cli{true, false};
|
||||
cli.i2c_address = I2C_ADDRESS_DEFAULT;
|
||||
cli.default_i2c_frequency = I2C_SPEED;
|
||||
@ -62,7 +62,7 @@ extern "C" int icp10100_main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP10100);
|
||||
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_ICP201XX);
|
||||
|
||||
if (!strcmp(verb, "start")) {
|
||||
return ThisDriver::module_start(cli, iterator);
|
||||
@ -216,8 +216,8 @@
|
||||
#define DRV_FLOW_DEVTYPE_PX4FLOW 0xB5
|
||||
#define DRV_FLOW_DEVTYPE_PAA3905 0xB6
|
||||
|
||||
#define DRV_BARO_DEVTYPE_ICP10100 0xC0
|
||||
#define DRV_BARO_DEVTYPE_ICP10111 0xC1
|
||||
#define DRV_BARO_DEVTYPE_ICP101XX 0xB7
|
||||
#define DRV_BARO_DEVTYPE_ICP201XX 0xB8
|
||||
|
||||
#define DRV_DEVTYPE_UNUSED 0xff
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user