diff --git a/src/drivers/barometer/CMakeLists.txt b/src/drivers/barometer/CMakeLists.txt index eaa73ef982..b7ec8312f6 100644 --- a/src/drivers/barometer/CMakeLists.txt +++ b/src/drivers/barometer/CMakeLists.txt @@ -39,3 +39,4 @@ add_subdirectory(lps22hb) add_subdirectory(lps33hw) #add_subdirectory(mpl3115a2) # not ready for general inclusion add_subdirectory(ms5611) +#add_subdirectory(tcbp001ta) # only for users who really need this diff --git a/src/drivers/barometer/tcbp001ta/CMakeLists.txt b/src/drivers/barometer/tcbp001ta/CMakeLists.txt new file mode 100644 index 0000000000..56a8badfe0 --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/CMakeLists.txt @@ -0,0 +1,44 @@ +############################################################################ +# +# Copyright (c) 2020 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__barometer__tcbp001ta + MAIN tcbp001ta + SRCS + tcbp001ta.cpp + tcbp001ta_spi.cpp + tcbp001ta_main.cpp + DEPENDS + drivers_barometer + px4_work_queue + ) diff --git a/src/drivers/barometer/tcbp001ta/defines.h b/src/drivers/barometer/tcbp001ta/defines.h new file mode 100644 index 0000000000..64e316bded --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/defines.h @@ -0,0 +1,179 @@ +/**************************************************************************** + * + * Copyright (C) 2020 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 tcbp001ta/defines.h + * + * Shared defines for the TCBP001TA barometer driver. + * + * @author Xiaowei Zhao + * @author Stone White + * + */ + +#pragma once + +#include + +#define TCBP001TA_ADDR_CAL 0x10 /* address of calibration data */ + +#define TCBP001TA_ADDR_DATA 0x00 /* address of presure data */ +#define TCBP001TA_ADDR_PRS_DATA 0X00 /* address of presure data */ +#define TCBP001TA_ADDR_TMP_DATA 0x03 /* address of tempature data */ + +#define TCBP001TA_ADDR_PRS_CFG 0x06 +#define TCBP001TA_ADDR_TMP_CFG 0x07 +#define TCBP001TA_ADDR_MEAS_CFG 0x08 +#define TCBP001TA_ADDR_CFG_REG 0x09 + +#define TCBP001TA_ADDR_INT_STS 0x0A +#define TCBP001TA_ADDR_FIFO_STS 0x0B +#define TCBP001TA_ADDR_RESET 0x0C /* reset */ +#define TCBP001TA_ADDR_ID 0x0D /* product and revision ID */ + +#define TCBP001TA_ADDR_TMP_COEF_SRCE 0x28 + +#define TCBP001TA_VALUE_ID 0x10 /* chip id */ +#define TCBP001TA_VALUE_RESET 0x89 /* reset */ + +#define TCBP001TA_PRS_TMP_RATE_1 (0x0 << 4) +#define TCBP001TA_PRS_TMP_RATE_2 (0x1 << 4) +#define TCBP001TA_PRS_TMP_RATE_4 (0x2 << 4) +#define TCBP001TA_PRS_TMP_RATE_8 (0x3 << 4) +#define TCBP001TA_PRS_TMP_RATE_16 (0x4 << 4) +#define TCBP001TA_PRS_TMP_RATE_32 (0x5 << 4) +#define TCBP001TA_PRS_TMP_RATE_64 (0x6 << 4) +#define TCBP001TA_PRS_TMP_RATE_128 (0x7 << 4) + +#define TCBP001TA_PRS_TMP_PRC 0x0 +#define TCBP001TA_PRS_TMP_PRC_2 0x1 +#define TCBP001TA_PRS_TMP_PRC_4 0x2 +#define TCBP001TA_PRS_TMP_PRC_8 0x3 +#define TCBP001TA_PRS_TMP_PRC_16 0x4 +#define TCBP001TA_PRS_TMP_PRC_32 0x5 +#define TCBP001TA_PRS_TMP_PRC_64 0x6 +#define TCBP001TA_PRS_TMP_PRC_128 0x7 + +#define TCBP001TA_TMP_EXT_ASIC 0x00 +#define TCBP001TA_TMP_EXT_MEMS 0x80 + +#define TCBP001TA_MT_INIT 6400 /* max measure time of initial p + t in us */ +#define TCBP001TA_MT 2300 /* max measure time of p or t in us */ + +#define POW_2_23_MINUS_1 0x7FFFFF //implies 2^23-1 +#define POW_2_24 0x1000000 +#define POW_2_15_MINUS_1 0x7FFF +#define POW_2_16 0x10000 +#define POW_2_11_MINUS_1 0x7FF +#define POW_2_12 0x1000 +#define POW_2_20 0x100000 +#define POW_2_19_MINUS_1 524287 + +namespace tcbp001ta +{ + +#pragma pack(push,1) +struct calibration_s { + uint8_t c0_h; + uint8_t c0l_1h; + uint8_t c1l; + uint8_t c00h; + uint8_t c00m; + uint8_t c00l_10h; + uint8_t c10m; + uint8_t c10l; + uint8_t c01h; + uint8_t c01l; + uint8_t c11h; + uint8_t c11l; + uint8_t c20h; + uint8_t c20l; + uint8_t c21h; + uint8_t c21l; + uint8_t c30h; + uint8_t c30l; +}; //calibration data + +struct data_s { + uint8_t p_msb; + uint8_t p_lsb; + uint8_t p_xlsb; + + uint8_t t_msb; + uint8_t t_lsb; + uint8_t t_xlsb; +}; // data +#pragma pack(pop) + +struct fcalibration_s { + int16_t c0; // 12bit + int16_t c1; // 12bit + int32_t c00; // 20bit + int32_t c10; // 20bit + int16_t c01; // 16bit + int16_t c11; // 16bit + int16_t c20; // 16bit + int16_t c21; // 16bit + int16_t c30; // 16bit +}; + +class ITCBP001TA +{ +public: + virtual ~ITCBP001TA() = default; + + virtual int init() = 0; + + // read reg value + virtual uint8_t get_reg(uint8_t addr) = 0; + + // write reg value + virtual int set_reg(uint8_t value, uint8_t addr) = 0; + + // bulk read of data into buffer, return same pointer + virtual tcbp001ta::data_s *get_data(uint8_t addr) = 0; + + // bulk read of calibration data into buffer, return same pointer + virtual tcbp001ta::calibration_s *get_calibration(uint8_t addr) = 0; + + virtual uint32_t get_device_id() const = 0; + +}; + +} /* namespace */ + + +/* interface factories */ +extern tcbp001ta::ITCBP001TA *tcbp001ta_spi_interface(uint8_t busnum, uint32_t device); +extern tcbp001ta::ITCBP001TA *tcbp001ta_i2c_interface(uint8_t busnum, uint32_t device); +typedef tcbp001ta::ITCBP001TA *(*TCBP001TA_constructor)(uint8_t, uint32_t); diff --git a/src/drivers/barometer/tcbp001ta/tcbp001ta.cpp b/src/drivers/barometer/tcbp001ta/tcbp001ta.cpp new file mode 100644 index 0000000000..a04f9ed939 --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/tcbp001ta.cpp @@ -0,0 +1,322 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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 tcbp001ta.cpp + * + * Driver for TCBP001TA barometer. + * + * @author Xiaowei Zhao + * @author Stone White + * + */ + +#include "tcbp001ta.hpp" + +TCBP001TA::TCBP001TA(tcbp001ta::ITCBP001TA *interface) : + ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())), + _px4_baro(interface->get_device_id()), + _interface(interface), + _sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": sample")), + _measure_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": measure")), + _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comms errors")) +{ + _px4_baro.set_device_type(DRV_BARO_DEVTYPE_TCBP001TA); +} + +TCBP001TA::~TCBP001TA() +{ + // make sure we are truly inactive + Stop(); + + // free perf counters + perf_free(_sample_perf); + perf_free(_measure_perf); + perf_free(_comms_errors); + + delete _interface; +} + +int +TCBP001TA::init() +{ + // reset sensor + _interface->set_reg(TCBP001TA_VALUE_RESET, TCBP001TA_ADDR_RESET); + usleep(10000); + + // check id + if (_interface->get_reg(TCBP001TA_ADDR_ID) != TCBP001TA_VALUE_ID) { + PX4_WARN("id of your baro is not: 0x%02x", TCBP001TA_VALUE_ID); + return -EIO; + } + + // Presure write [0x6 | (0x3 << 4)] to 0x06 + _interface->set_reg(TCBP001TA_PRS_TMP_PRC_64 | TCBP001TA_PRS_TMP_RATE_8, TCBP001TA_ADDR_PRS_CFG); + + // Temperature write [0x80 | 0x1 | (0x2 << 4)] to 0x07 + _interface->set_reg(TCBP001TA_TMP_EXT_MEMS | TCBP001TA_PRS_TMP_PRC_2 | TCBP001TA_PRS_TMP_RATE_4, + TCBP001TA_ADDR_TMP_CFG); + + // write 0x00 to 0x09 + _interface->set_reg(0x00, TCBP001TA_ADDR_CFG_REG); + + tmp_osr_scale_coeff = TCBP001TA_get_scaling_coef(0); + prs_osr_scale_coeff = TCBP001TA_get_scaling_coef(0); + + // get calibration and pre process them + _cal = _interface->get_calibration(TCBP001TA_ADDR_CAL); + + if (_cal == nullptr) { + PX4_INFO("init failed"); + return -EIO; + } + + _fcal.c0 = (_cal->c0_h << 4) + ((_cal->c0l_1h >> 4) & 0x0F); + + if (_fcal.c0 > POW_2_11_MINUS_1) { + _fcal.c0 = _fcal.c0 - POW_2_12; + } + + _fcal.c1 = (_cal->c1l + ((_cal->c0l_1h & 0x0F) << 8)); + + if (_fcal.c1 > POW_2_11_MINUS_1) { + _fcal.c1 = _fcal.c1 - POW_2_12; + } + + _fcal.c00 = ((_cal->c00m << 4) + (_cal->c00h << 12)) + ((_cal->c00l_10h >> 4) & 0x0F); + + if (_fcal.c00 > POW_2_19_MINUS_1) { + _fcal.c00 = _fcal.c00 - POW_2_20; + } + + _fcal.c10 = ((_cal->c00l_10h & 0x0F) << 16) + _cal->c10l + (_cal->c10m << 8); + + if (_fcal.c10 > POW_2_19_MINUS_1) { + _fcal.c10 = _fcal.c10 - POW_2_20; + } + + _fcal.c01 = (_cal->c01l + (_cal->c01h << 8)); + //if(_fcal.c01 > POW_2_15_MINUS_1) + //_fcal.c01 = _fcal.c01 - POW_2_16; + + _fcal.c11 = (_cal->c11l + (_cal->c11h << 8)); + //if(_fcal.c11 > POW_2_15_MINUS_1) + //_fcal.c11 = _fcal.c11 - POW_2_16; + + _fcal.c20 = (_cal->c20l + (_cal->c20h << 8)); + //if(_fcal.c20 > POW_2_15_MINUS_1) + //_fcal.c20 = _fcal.c20 - POW_2_16; + + _fcal.c21 = (_cal->c21l + (_cal->c21h << 8)); + //if(_fcal.c21 > POW_2_15_MINUS_1) + //_fcal.c21 = _fcal.c21 - POW_2_16; + + _fcal.c30 = (_cal->c30l + (_cal->c30h << 8)); + //if(_fcal.c30 > POW_2_15_MINUS_1) + //_fcal.c30 = _fcal.c30 - POW_2_16; + + Start(); + + return OK; +} + +void +TCBP001TA::Start() +{ + // reset the report ring and state machine + _collect_phase = false; + + // schedule a cycle to start things + ScheduleNow(); +} + +void +TCBP001TA::Stop() +{ + ScheduleClear(); +} + +void +TCBP001TA::Run() +{ + if (_collect_phase) { + collect(); + + } else { + measure(); + } + + ScheduleDelayed(_measure_interval); +} + +int +TCBP001TA::measure() +{ + perf_begin(_measure_perf); + + _collect_phase = true; + + // start measure + //int ret = _interface->set_reg(_curr_ctrl | TCBP001TA_CTRL_MODE_FORCE, TCBP001TA_ADDR_CTRL); + + //if (ret != OK) { + //perf_count(_comms_errors); + //perf_cancel(_measure_perf); + //return -EIO; + //} + perf_end(_measure_perf); + + return OK; +} + +int +TCBP001TA::collect() +{ + perf_begin(_sample_perf); + + _collect_phase = false; + // this should be fairly close to the end of the conversion, so the best approximation of the time + const hrt_abstime timestamp_sample = hrt_absolute_time(); + + //write 0x02 to reg 0x08 Temperature + _interface->set_reg(0x02, TCBP001TA_ADDR_MEAS_CFG); + + tcbp001ta::data_s *data_temp = _interface->get_data(TCBP001TA_ADDR_TMP_DATA); + + if (data_temp == nullptr) { + perf_count(_comms_errors); + perf_cancel(_sample_perf); + return -EIO; + } + + uint32_t p_raw = (data_temp->p_msb << 16 | data_temp->p_lsb << 8) + (data_temp->p_xlsb); + + //write 0x01 to reg 0x08 Pressure + _interface->set_reg(0x01, TCBP001TA_ADDR_MEAS_CFG); + + tcbp001ta::data_s *data_pres = _interface->get_data(TCBP001TA_ADDR_PRS_DATA); + + if (data_pres == nullptr) { + perf_count(_comms_errors); + perf_cancel(_sample_perf); + return -EIO; + } + + uint32_t t_raw = (data_pres->t_msb << 16 | data_pres->t_lsb << 8) + (data_pres->t_xlsb); + + // PX4_INFO("p raw %f", p_raw); + // PX4_INFO("t raw %f", t_raw); + // PX4_INFO("data 0 %d data 1 %d data2 %d", data_temp->p_msb, data_temp->p_lsb, data_temp->p_xlsb); + // PX4_INFO("data 3 %d data 4 %d data5 %d", data_pres->t_msb, data_pres->t_lsb, data_pres->t_xlsb); + + // Temperature + float Traw_sc = (float)t_raw / (float)(tmp_osr_scale_coeff); + + const float T = (_fcal.c0 / 2.0f) + (float)(_fcal.c1 * Traw_sc); + + // Pressure + float Praw_sc = (float) p_raw / (float)(prs_osr_scale_coeff); + + const float P = _fcal.c00 + + Praw_sc * (_fcal.c10 + Praw_sc * (_fcal.c20 + Praw_sc * _fcal.c30)) + + Praw_sc * _fcal.c01 + + Praw_sc * Praw_sc * (_fcal.c11 + Praw_sc * _fcal.c21); + + _px4_baro.set_error_count(perf_event_count(_comms_errors)); + _px4_baro.set_temperature(T); + + float pressure = P / 100.0f; // to mbar + // PX4_INFO("press %f", double(pressure)); + _px4_baro.update(timestamp_sample, pressure); + + perf_end(_sample_perf); + + return OK; +} + +void +TCBP001TA::print_info() +{ + perf_print_counter(_sample_perf); + perf_print_counter(_measure_perf); + perf_print_counter(_comms_errors); + + _px4_baro.print_status(); +} + +uint32_t +TCBP001TA::TCBP001TA_get_scaling_coef(uint8_t osr) +{ + uint32_t scaling_coeff; + + switch (osr) { + + case 0: + scaling_coeff = 524288; + break; + + case 1: + scaling_coeff = 1572864; + break; + + case 2: + scaling_coeff = 3670016; + break; + + case 3: + scaling_coeff = 7864320; + break; + + case 4: + scaling_coeff = 253952; + break; + + case 5: + scaling_coeff = 516096; + break; + + case 6: + scaling_coeff = 1040384; + break; + + case 7: + scaling_coeff = 2088960; + break; + + default: + scaling_coeff = 524288; + break; + } + + return scaling_coeff; +} diff --git a/src/drivers/barometer/tcbp001ta/tcbp001ta.hpp b/src/drivers/barometer/tcbp001ta/tcbp001ta.hpp new file mode 100644 index 0000000000..c736e05fa6 --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/tcbp001ta.hpp @@ -0,0 +1,82 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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 "defines.h" + +#include +#include +#include +#include +#include + +class TCBP001TA : public px4::ScheduledWorkItem +{ +public: + TCBP001TA(tcbp001ta::ITCBP001TA *interface); + virtual ~TCBP001TA(); + + int init(); + void print_info(); + + uint32_t tmp_osr_scale_coeff; + uint32_t prs_osr_scale_coeff; + + uint32_t TCBP001TA_get_scaling_coef(uint8_t osr); + +private: + void Run() override; + void Start(); + void Stop(); + + int measure(); //start measure + int collect(); //get results and publish + + PX4Barometer _px4_baro; + + tcbp001ta::ITCBP001TA *_interface; + + // set config, recommended settings + //static constexpr uint8_t _curr_ctrl{TCBP001TA_CTRL_P16 | TCBP001TA_CTRL_T2}; + static constexpr uint32_t _measure_interval{TCBP001TA_MT_INIT + TCBP001TA_MT *(16 - 1 + 2 - 1)}; + + bool _collect_phase{false}; + + perf_counter_t _sample_perf; + perf_counter_t _measure_perf; + perf_counter_t _comms_errors; + + tcbp001ta::calibration_s *_cal{nullptr}; //stored calibration constants + tcbp001ta::fcalibration_s _fcal{}; //pre processed calibration constants +}; diff --git a/src/drivers/barometer/tcbp001ta/tcbp001ta_main.cpp b/src/drivers/barometer/tcbp001ta/tcbp001ta_main.cpp new file mode 100644 index 0000000000..4121b57310 --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/tcbp001ta_main.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** + * + * Copyright (c) 2020 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 "tcbp001ta.hpp" + +enum class TCBP001TA_BUS { + + SPI_INTERNAL = 0 +}; + +namespace tcbp001ta +{ + +// list of supported bus configurations +struct tcbp001ta_bus_option { + TCBP001TA_BUS busid; + TCBP001TA_constructor interface_constructor; + uint8_t busnum; + uint32_t address; + TCBP001TA *dev; +} bus_options[] = { + + { TCBP001TA_BUS::SPI_INTERNAL, &tcbp001ta_spi_interface, PX4_SPI_BUS_BARO, PX4_SPIDEV_BARO, nullptr }, +}; + +// find a bus structure for a busid +static struct tcbp001ta_bus_option *find_bus(TCBP001TA_BUS busid) +{ + for (tcbp001ta_bus_option &bus_option : bus_options) { + if (( + busid == bus_option.busid) && bus_option.dev != nullptr) { + + return &bus_option; + } + } + + return nullptr; +} + +static bool start_bus(tcbp001ta_bus_option &bus) +{ + tcbp001ta::ITCBP001TA *interface = bus.interface_constructor(bus.busnum, bus.address); + + if ((interface == nullptr) || (interface->init() != PX4_OK)) { + PX4_WARN("no device on bus %u", (unsigned)bus.busid); + delete interface; + return false; + } + + TCBP001TA *dev = new TCBP001TA(interface); + + if (dev == nullptr) { + PX4_ERR("driver allocate failed"); + delete interface; + return false; + } + + if (dev->init() != PX4_OK) { + PX4_ERR("driver start failed"); + delete dev; // TCBP001TA deletes the interface + return false; + } + + bus.dev = dev; + + return true; +} + +static int start(TCBP001TA_BUS busid) +{ + for (tcbp001ta_bus_option &bus_option : bus_options) { + if (bus_option.dev != nullptr) { + // this device is already started + PX4_WARN("already started"); + continue; + } + + if (bus_option.busid != busid) { + // not the one that is asked for + continue; + } + + if (start_bus(bus_option)) { + return PX4_OK; + } + } + + return PX4_ERROR; +} + +static int stop(TCBP001TA_BUS busid) +{ + tcbp001ta_bus_option *bus = find_bus(busid); + + if (bus != nullptr && bus->dev != nullptr) { + delete bus->dev; + bus->dev = nullptr; + + } else { + PX4_WARN("driver not running"); + return PX4_ERROR; + } + + return PX4_OK; +} + +static int status(TCBP001TA_BUS busid) +{ + tcbp001ta_bus_option *bus = find_bus(busid); + + if (bus != nullptr && bus->dev != nullptr) { + bus->dev->print_info(); + return PX4_OK; + } + + PX4_WARN("driver not running"); + return PX4_ERROR; +} + +static int usage() +{ + PX4_INFO("missing command: try 'start', 'stop', 'status'"); + PX4_INFO("options:"); + PX4_INFO(" -X (i2c external bus)"); + PX4_INFO(" -I (i2c internal bus)"); + PX4_INFO(" -s (spi internal bus)"); + PX4_INFO(" -S (spi external bus)"); + + return 0; +} + +} // namespace + +extern "C" int tcbp001ta_main(int argc, char *argv[]) +{ + int myoptind = 1; + // int ch; + // const char *myoptarg = nullptr; + + TCBP001TA_BUS busid; + busid = TCBP001TA_BUS::SPI_INTERNAL; + + + + // if (myoptind >= argc) { + // return tcbp001ta::usage(); + // } + + const char *verb = argv[myoptind]; + + if (!strcmp(verb, "start")) { + PX4_INFO("start"); + return tcbp001ta::start(busid); + + } else if (!strcmp(verb, "stop")) { + return tcbp001ta::stop(busid); + + } else if (!strcmp(verb, "status")) { + return tcbp001ta::status(busid); + } + + return tcbp001ta::usage(); +} diff --git a/src/drivers/barometer/tcbp001ta/tcbp001ta_spi.cpp b/src/drivers/barometer/tcbp001ta/tcbp001ta_spi.cpp new file mode 100644 index 0000000000..66580c5b87 --- /dev/null +++ b/src/drivers/barometer/tcbp001ta/tcbp001ta_spi.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** + * + * Copyright (c) 2016-2019 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 tcbp001ta_spi.cpp + * + * SPI interface for TCBP001TA. + * + * @author Xiaowei Zhao + * @author Stone White + * + */ + +#include "defines.h" + +#include +#include + + +/* SPI protocol address bits */ +#define DIR_READ (1<<7) //for set +#define DIR_WRITE ~(1<<7) //for clear + +#pragma pack(push,1) +struct spi_data_s { + uint8_t addr; + struct tcbp001ta::data_s data; +}; + +struct spi_calibration_s { + uint8_t addr; + struct tcbp001ta::calibration_s cal; +}; +#pragma pack(pop) + +class TCBP001TA_SPI: public device::SPI, public tcbp001ta::ITCBP001TA +{ +public: + TCBP001TA_SPI(uint8_t bus, uint32_t device); + virtual ~TCBP001TA_SPI() override = default; + + int init() override { return SPI::init(); } + + uint8_t get_reg(uint8_t addr) override; + int set_reg(uint8_t value, uint8_t addr) override; + + tcbp001ta::data_s *get_data(uint8_t addr) override; + tcbp001ta::calibration_s *get_calibration(uint8_t addr) override; + + uint32_t get_device_id() const override { return device::SPI::get_device_id(); } + +private: + spi_calibration_s _cal{}; + spi_data_s _data{}; +}; + +tcbp001ta::ITCBP001TA * +tcbp001ta_spi_interface(uint8_t busnum, uint32_t device) +{ + return new TCBP001TA_SPI(busnum, device); +} + +TCBP001TA_SPI::TCBP001TA_SPI(uint8_t bus, uint32_t device) : + SPI("TCBP001TA_SPI", nullptr, bus, device, SPIDEV_MODE3, 10 * 1000 * 1000) +{ +} + +uint8_t +TCBP001TA_SPI::get_reg(uint8_t addr) +{ + uint8_t cmd[2] = { (uint8_t)(addr | DIR_READ), 0}; // set MSB bit + transfer(&cmd[0], &cmd[0], 2); + + return cmd[1]; +} + +int +TCBP001TA_SPI::set_reg(uint8_t value, uint8_t addr) +{ + uint8_t cmd[2] = { (uint8_t)(addr & DIR_WRITE), value}; // clear MSB bit + return transfer(&cmd[0], nullptr, 2); +} + +tcbp001ta::data_s * +TCBP001TA_SPI::get_data(uint8_t addr) +{ + _data.addr = (uint8_t)(addr | DIR_READ); // set MSB bit + // PX4_INFO("addr %02x", addr); + // PX4_INFO("addr %02x", _data.addr); + + if (transfer((uint8_t *)&_data, (uint8_t *)&_data, sizeof(spi_data_s)) == OK) { + // PX4_INFO("t xlsb data %d", _data.data.t_xlsb); + // PX4_INFO("t msb data %d", _data.data.t_msb); + // PX4_INFO("t lsb data %d", _data.data.t_lsb); + // PX4_INFO("p xlsb data %d", _data.data.p_xlsb); + // PX4_INFO("p msb data %d", _data.data.p_msb); + // PX4_INFO("p lsb data %d", _data.data.p_lsb); + return &(_data.data); + + } else { + return nullptr; + } +} + +tcbp001ta::calibration_s * +TCBP001TA_SPI::get_calibration(uint8_t addr) +{ + _cal.addr = addr | DIR_READ; + + if (transfer((uint8_t *)&_cal, (uint8_t *)&_cal, sizeof(spi_calibration_s)) == OK) { + return &(_cal.cal); + + } else { + return nullptr; + } +} diff --git a/src/drivers/drv_sensor.h b/src/drivers/drv_sensor.h index 3ad7e1d399..25695f7f1f 100644 --- a/src/drivers/drv_sensor.h +++ b/src/drivers/drv_sensor.h @@ -106,6 +106,7 @@ #define DRV_DIFF_PRESS_DEVTYPE_SDP32 0x4A #define DRV_DIFF_PRESS_DEVTYPE_SDP33 0x4B #define DRV_BARO_DEVTYPE_LPS33HW 0x4C +#define DRV_BARO_DEVTYPE_TCBP001TA 0x4D #define DRV_BARO_DEVTYPE_MPL3115A2 0x51 #define DRV_ACC_DEVTYPE_FXOS8701C 0x52