diff --git a/boards/mro/ctrl-zero-f7/default.cmake b/boards/mro/ctrl-zero-f7/default.cmake index dd9135c078..361dba7da1 100644 --- a/boards/mro/ctrl-zero-f7/default.cmake +++ b/boards/mro/ctrl-zero-f7/default.cmake @@ -19,7 +19,7 @@ px4_add_board( DRIVERS adc #barometer # all available barometer drivers - #barometer/dps310 + barometer/dps310 batt_smbus camera_capture camera_trigger diff --git a/boards/mro/ctrl-zero-f7/init/rc.board_sensors b/boards/mro/ctrl-zero-f7/init/rc.board_sensors index 6910c01254..d7125724d2 100644 --- a/boards/mro/ctrl-zero-f7/init/rc.board_sensors +++ b/boards/mro/ctrl-zero-f7/init/rc.board_sensors @@ -18,7 +18,7 @@ bmi088 -A -R 10 start bmi088 -G -R 10 start # Interal DPS310 (barometer) -dps310 start +dps310 -s start # Possible external compasses ist8310 -C -b 1 start diff --git a/src/drivers/barometer/CMakeLists.txt b/src/drivers/barometer/CMakeLists.txt index 1619bce117..5c466e7cee 100644 --- a/src/drivers/barometer/CMakeLists.txt +++ b/src/drivers/barometer/CMakeLists.txt @@ -33,6 +33,7 @@ add_subdirectory(bmp280) add_subdirectory(bmp388) +add_subdirectory(dps310) add_subdirectory(lps22hb) #add_subdirectory(lps25h) # not ready for general inclusion #add_subdirectory(mpl3115a2) # not ready for general inclusion diff --git a/src/drivers/barometer/dps310/CMakeLists.txt b/src/drivers/barometer/dps310/CMakeLists.txt new file mode 100644 index 0000000000..088e56e6b5 --- /dev/null +++ b/src/drivers/barometer/dps310/CMakeLists.txt @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (c) 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. +# +############################################################################ +px4_add_module( + MODULE drivers__barometer__dps310 + MAIN dps310 + SRCS + DPS310.cpp + DPS310.hpp + DPS310_I2C.cpp + DPS310_SPI.cpp + dps310_main.cpp + DEPENDS + drivers_barometer + px4_work_queue + ) diff --git a/src/drivers/barometer/dps310/DPS310.cpp b/src/drivers/barometer/dps310/DPS310.cpp new file mode 100644 index 0000000000..c9073af825 --- /dev/null +++ b/src/drivers/barometer/dps310/DPS310.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** + * + * Copyright (c) 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. + * + ****************************************************************************/ + +#include "DPS310.hpp" + +using namespace Infineon_DPS310; + +namespace dps310 +{ + +template +static void getTwosComplement(T &raw, uint8_t length) +{ + if (raw & ((T)1 << (length - 1))) { + raw -= (T)1 << length; + } +} + +DPS310::DPS310(device::Device *interface) : + ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())), + _px4_barometer(interface->get_device_id()), + _interface(interface), + _sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")), + _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comm errors")) +{ + _px4_barometer.set_device_type(DRV_DEVTYPE_DPS310); +} + +DPS310::~DPS310() +{ + stop(); + + perf_free(_sample_perf); + perf_free(_comms_errors); + + delete _interface; +} + +int +DPS310::init() +{ + if (RegisterRead(Register::ID) != Infineon_DPS310::REV_AND_PROD_ID) { + PX4_ERR("Product_ID mismatch"); + return PX4_ERROR; + } + + if (reset() != OK) { + PX4_DEBUG("reset failed"); + return PX4_ERROR; + } + + start(); + + return PX4_OK; +} + +int +DPS310::reset() +{ + // Soft Reset + RegisterSetBits(Register::RESET, RESET_BIT::SOFT_RST); + usleep(40000); // 40 milliseconds + + const uint8_t mode_and_status = RegisterRead(Register::MEAS_CFG); + + bool coefficients_ready = mode_and_status & MEAS_CFG_BIT::COEF_RDY; + bool sensor_ready = mode_and_status & MEAS_CFG_BIT::SENSOR_RDY; + + if (!coefficients_ready) { + PX4_ERR("Coefficients are not available"); + return PX4_ERROR; + } + + if (!sensor_ready) { + PX4_ERR("Sensor initialization not complete"); + return PX4_ERROR; + } + + // 1. Read the pressure calibration coefficients (c00, c10, c20, c30, c01, c11, and c21) from the Calibration Coefficient register. + // Note: The coefficients read from the coefficient register are 2's complement numbers. + uint8_t coef[18] {}; + + if (_interface->read((uint8_t)Register::COEF, coef, 18)) { + return PX4_ERROR; + } + + // first element of coef[18] corresponds to register 0x10 + + // 0x11 c0 [3:0] + 0x10 c0 [11:4] + _calibration.c0 = ((uint32_t)coef[0] << 4) | (((uint32_t)coef[1] >> 4) & 0x0F); + getTwosComplement(_calibration.c0, 12); + + // 0x11 c1 [11:8] + 0x12 c1 [7:0] + _calibration.c1 = (((uint32_t)coef[1] & 0x0F) << 8) | (uint32_t)coef[2]; + getTwosComplement(_calibration.c1, 12); + + // 0x13 c00 [19:12] + 0x14 c00 [11:4] + 0x15 c00 [3:0] + _calibration.c00 = ((uint32_t)coef[3] << 12) | ((uint32_t)coef[4] << 4) | (((uint32_t)coef[5] >> 4) & 0x0F); + getTwosComplement(_calibration.c00, 20); + + // 0x15 c10 [19:16] + 0x16 c10 [15:8] + 0x17 c10 [7:0] + _calibration.c10 = (((uint32_t)coef[5] & 0x0F) << 16) | ((uint32_t)coef[6] << 8) | (uint32_t)coef[7]; + getTwosComplement(_calibration.c10, 20); + + // 0x18 c01 [15:8] + 0x19 c01 [7:0] + _calibration.c01 = ((uint32_t)coef[8] << 8) | (uint32_t)coef[9]; + getTwosComplement(_calibration.c01, 16); + + // 0x1A c11 [15:8] + 0x1B c11 [7:0] + _calibration.c11 = ((uint32_t)coef[8] << 8) | (uint32_t)coef[9]; + getTwosComplement(_calibration.c11, 16); + + // 0x1C c20 [15:8] + 0x1D c20 [7:0] + _calibration.c20 = ((uint32_t)coef[12] << 8) | (uint32_t)coef[13]; + getTwosComplement(_calibration.c20, 16); + + // 0x1E c21 [15:8] + 0x1F c21 [7:0] + _calibration.c21 = ((uint32_t)coef[14] << 8) | (uint32_t)coef[15]; + getTwosComplement(_calibration.c21, 16); + + // 0x20 c30 [15:8] + 0x21 c30 [7:0] + _calibration.c30 = ((uint32_t)coef[16] << 8) | (uint32_t)coef[17]; + getTwosComplement(_calibration.c30, 16); + + + // PRS_CFG: pressure measurement rate (32 Hz) and oversampling (16 time standard) + RegisterSetBits(Register::PRS_CFG, PRS_CFG_BIT::PM_RATE_32HZ | PRS_CFG_BIT::PM_PRC_16); + + // TMP_CFG: temperature measurement rate (32 Hz) and oversampling (16 times) + const uint8_t TMP_COEF_SRCE = RegisterRead(Register::COEF_SRCE) & COEF_SRCE_BIT::TMP_COEF_SRCE; + RegisterSetBits(Register::TMP_CFG, TMP_CFG_BIT::TMP_RATE_32HZ | TMP_CFG_BIT::TMP_PRC_16 | TMP_COEF_SRCE); + + // CFG_REG: set pressure and temperature result bit-shift (required when the oversampling rate is >8 times) + RegisterSetBits(Register::CFG_REG, CFG_REG_BIT::T_SHIFT | CFG_REG_BIT::P_SHIFT); + + // MEAS_CFG: Continous pressure and temperature measurement + RegisterSetBits(Register::MEAS_CFG, MEAS_CFG_BIT::MEAS_CTRL_CONT); + + return PX4_OK; +} + +void +DPS310::start() +{ + // run at twice the sample rate to capture all new data + ScheduleOnInterval(1000000 / SAMPLE_RATE / 2); +} + +void +DPS310::stop() +{ + ScheduleClear(); +} + +void +DPS310::Run() +{ + perf_begin(_sample_perf); + + // check if pressure ready + bool pressure_ready = RegisterRead(Register::MEAS_CFG) & MEAS_CFG_BIT::PRS_RDY; + + if (!pressure_ready) { + perf_end(_sample_perf); + return; + } + + + // 2. Choose scaling factors kT (for temperature) and kP (for pressure) based on the chosen precision rate. The scaling factors are listed in Table 9. + static constexpr float kT = 253952; // 16 times (Standard) + static constexpr float kP = 253952; // 16 times (Standard) + + + // 3. Read the pressure and temperature result from the registers + + // Read PSR_B2, PSR_B1, PSR_B0, TMP_B2, TMP_B1, TMP_B0 + uint8_t buf[6] {}; + const hrt_abstime timestamp_sample = hrt_absolute_time(); + + if (_interface->read((uint8_t)Register::PSR_B2, buf, 6) != PX4_OK) { + perf_count(_comms_errors); + perf_end(_sample_perf); + return; + } + + int32_t Praw = (buf[0] << 16) + (buf[1] << 8) + buf[2]; + getTwosComplement(Praw, 24); + + int32_t Traw = (buf[3] << 16) + (buf[4] << 8) + buf[5]; + getTwosComplement(Traw, 24); + + + // 4. Calculate scaled measurement results. + const float Praw_sc = Praw / kP; + const float Traw_sc = Traw / kT; + + + // 5. Calculate compensated measurement results. + const auto &c00 = _calibration.c00; + const auto &c01 = _calibration.c01; + const auto &c10 = _calibration.c10; + const auto &c11 = _calibration.c11; + const auto &c20 = _calibration.c20; + const auto &c21 = _calibration.c21; + const auto &c30 = _calibration.c30; + + const float Pcomp = c00 + Praw_sc * (c10 + Praw_sc * (c20 + Praw_sc * c30)) + Traw_sc * c01 + Traw_sc * Praw_sc * + (c11 + Praw_sc * c21); + + const auto &c0 = _calibration.c0; + const auto &c1 = _calibration.c1; + + const float Tcomp = c0 * 0.5f + c1 * Traw_sc; + + _px4_barometer.set_error_count(perf_event_count(_comms_errors)); + _px4_barometer.set_temperature(Tcomp); + _px4_barometer.update(timestamp_sample, Pcomp / 100.0f); // Pascals -> Millibar + + perf_end(_sample_perf); +} + +uint8_t +DPS310::RegisterRead(Register reg) +{ + uint8_t buf{}; + _interface->read((uint8_t)reg, &buf, 1); + + return buf; +} + +void +DPS310::RegisterWrite(Register reg, uint8_t value) +{ + _interface->write((uint8_t)reg, &value, 1); +} + +void +DPS310::RegisterSetBits(Register reg, uint8_t setbits) +{ + uint8_t val = RegisterRead(reg); + + if (!(val & setbits)) { + val |= setbits; + RegisterWrite(reg, val); + } +} + +void +DPS310::RegisterClearBits(Register reg, uint8_t clearbits) +{ + uint8_t val = RegisterRead(reg); + + if (val & clearbits) { + val &= !clearbits; + RegisterWrite(reg, val); + } +} + +void +DPS310::print_info() +{ + perf_print_counter(_sample_perf); + perf_print_counter(_comms_errors); + + _px4_barometer.print_status(); +} + +} // namespace dps310 diff --git a/src/drivers/barometer/dps310/DPS310.hpp b/src/drivers/barometer/dps310/DPS310.hpp new file mode 100644 index 0000000000..19e7ead3e3 --- /dev/null +++ b/src/drivers/barometer/dps310/DPS310.hpp @@ -0,0 +1,90 @@ +/**************************************************************************** + * + * Copyright (c) 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 DPS310.cpp + * + * Driver for the Infineon DPS310 barometer connected via I2C or SPI. + */ + +#pragma once + +#include +#include +#include +#include + +#include "Infineon_DPS310_Registers.hpp" + +namespace dps310 +{ + +using Infineon_DPS310::CalibrationCoefficients; +using Infineon_DPS310::Register; + +class DPS310 : public px4::ScheduledWorkItem +{ +public: + DPS310(device::Device *interface); + virtual ~DPS310(); + + int init(); + + void print_info(); + +private: + + void Run() override; + + void start(); + void stop(); + int reset(); + + uint8_t RegisterRead(Register reg); + void RegisterWrite(Register reg, uint8_t val); + void RegisterSetBits(Register reg, uint8_t setbits); + void RegisterClearBits(Register reg, uint8_t clearbits); + + static constexpr uint32_t SAMPLE_RATE{32}; // + + PX4Barometer _px4_barometer; + + device::Device *_interface; + + CalibrationCoefficients _calibration{}; + + perf_counter_t _sample_perf; + perf_counter_t _comms_errors; +}; + +} // namespace dps310 diff --git a/src/drivers/barometer/dps310/DPS310_I2C.cpp b/src/drivers/barometer/dps310/DPS310_I2C.cpp new file mode 100644 index 0000000000..d8b4f20527 --- /dev/null +++ b/src/drivers/barometer/dps310/DPS310_I2C.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** + * + * Copyright (c) 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 DPS310_I2C.cpp + * + * I2C interface for DPS310 + */ + +#include + +namespace dps310 +{ + +device::Device *DPS310_I2C_interface(uint8_t bus, uint32_t address); + +class DPS310_I2C : public device::I2C +{ +public: + DPS310_I2C(uint8_t bus, uint32_t address); + virtual ~DPS310_I2C() = default; + + virtual int read(unsigned address, void *data, unsigned count); + virtual int write(unsigned address, void *data, unsigned count); + +}; + +device::Device * +DPS310_I2C_interface(uint8_t bus, uint32_t address) +{ + return new DPS310_I2C(bus, address); +} + +DPS310_I2C::DPS310_I2C(uint8_t bus, uint32_t address) : + I2C("DPS310_I2C", nullptr, bus, address, 400000) +{ +} + +int +DPS310_I2C::read(unsigned address, void *data, unsigned count) +{ + uint8_t cmd = address; + return transfer(&cmd, 1, (uint8_t *)data, count); +} + +int +DPS310_I2C::write(unsigned address, void *data, unsigned count) +{ + uint8_t buf[32]; + + if (sizeof(buf) < (count + 1)) { + return -EIO; + } + + buf[0] = address; + memcpy(&buf[1], data, count); + + return transfer(&buf[0], count + 1, nullptr, 0); +} + +} // namespace dps310 diff --git a/src/drivers/barometer/dps310/DPS310_SPI.cpp b/src/drivers/barometer/dps310/DPS310_SPI.cpp new file mode 100644 index 0000000000..101e9494f6 --- /dev/null +++ b/src/drivers/barometer/dps310/DPS310_SPI.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** + * + * Copyright (c) 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 DPS310_SPI.cpp + * + * SPI interface for DPS310 + */ + +#include + +namespace dps310 +{ + +/* SPI protocol address bits */ +#define DIR_READ (1<<7) +#define DIR_WRITE (0<<7) + +device::Device *DPS310_SPI_interface(uint8_t bus, uint32_t device); + +class DPS310_SPI : public device::SPI +{ +public: + DPS310_SPI(uint8_t bus, uint32_t device); + virtual ~DPS310_SPI() = default; + + virtual int read(unsigned address, void *data, unsigned count); + virtual int write(unsigned address, void *data, unsigned count); + +}; + +device::Device * +DPS310_SPI_interface(uint8_t bus, uint32_t device) +{ + return new DPS310_SPI(bus, device); +} + +DPS310_SPI::DPS310_SPI(uint8_t bus, uint32_t device) : + SPI("DPS310_SPI", nullptr, bus, device, SPIDEV_MODE3, 10 * 1000 * 1000) +{ +} + +int +DPS310_SPI::read(unsigned address, void *data, unsigned count) +{ + uint8_t buf[32]; + + if (sizeof(buf) < (count + 1)) { + return -EIO; + } + + buf[0] = address | DIR_READ; + + int ret = transfer(&buf[0], &buf[0], count + 1); + memcpy(data, &buf[1], count); + return ret; +} + +int +DPS310_SPI::write(unsigned address, void *data, unsigned count) +{ + uint8_t buf[32]; + + if (sizeof(buf) < (count + 1)) { + return -EIO; + } + + buf[0] = address | DIR_WRITE; + memcpy(&buf[1], data, count); + + return transfer(&buf[0], &buf[0], count + 1); +} + +} // namespace dps310 diff --git a/src/drivers/barometer/dps310/Infineon_DPS310_Registers.hpp b/src/drivers/barometer/dps310/Infineon_DPS310_Registers.hpp new file mode 100644 index 0000000000..323a1c2a6a --- /dev/null +++ b/src/drivers/barometer/dps310/Infineon_DPS310_Registers.hpp @@ -0,0 +1,122 @@ +/**************************************************************************** + * + * Copyright (c) 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. + * + ****************************************************************************/ + +#pragma once + +// TODO: move to a central header +static constexpr uint8_t Bit0 = (1 << 0); +static constexpr uint8_t Bit1 = (1 << 1); +static constexpr uint8_t Bit2 = (1 << 2); +static constexpr uint8_t Bit3 = (1 << 3); +static constexpr uint8_t Bit4 = (1 << 4); +static constexpr uint8_t Bit5 = (1 << 5); +static constexpr uint8_t Bit6 = (1 << 6); +static constexpr uint8_t Bit7 = (1 << 7); + +namespace Infineon_DPS310 +{ + +static constexpr uint8_t REV_AND_PROD_ID = 0x10; + +enum class +Register : uint8_t { + + PSR_B2 = 0x00, + PSR_B1 = 0x01, + PSR_B0 = 0x02, + TMP_B2 = 0x03, + TMP_B1 = 0x04, + TMP_B0 = 0x05, + PRS_CFG = 0x06, + TMP_CFG = 0x07, + MEAS_CFG = 0x08, + CFG_REG = 0x09, + + RESET = 0x0C, + ID = 0x0D, + + COEF = 0x10, + // c0 = 0x10 + // . + // c30 = 0x21 + + COEF_SRCE = 0x28, + +}; + +enum PRS_CFG_BIT : uint8_t { + PM_RATE_32HZ = Bit6 | Bit4, // 101 - 32 measurements pr. sec. + PM_PRC_16 = Bit2, // 0100 - 16 times (Standard). +}; + +enum TMP_CFG_BIT : uint8_t { + TMP_EXT = Bit7, + TMP_RATE_32HZ = Bit6 | Bit4, // 101 - 32 measurements pr. sec. + TMP_PRC_16 = Bit2, // 0100 - 16 times. +}; + +enum CFG_REG_BIT : uint8_t { + T_SHIFT = Bit3, + P_SHIFT = Bit2, +}; + +enum MEAS_CFG_BIT : uint8_t { + COEF_RDY = Bit7, + SENSOR_RDY = Bit6, + TMP_RDY = Bit5, + PRS_RDY = Bit4, + + MEAS_CTRL_CONT = Bit2 | Bit1 | Bit0, // 111 - Continous pressure and temperature measurement +}; + +enum RESET_BIT : uint8_t { + SOFT_RST = Bit3 | Bit0, // Write '1001' to generate a soft reset +}; + +enum COEF_SRCE_BIT : uint8_t { + TMP_COEF_SRCE = Bit7, // TMP_COEF_SRCE +}; + +struct CalibrationCoefficients { + 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 +}; + +} // namespace Infineon_DPS310 diff --git a/src/drivers/barometer/dps310/dps310_main.cpp b/src/drivers/barometer/dps310/dps310_main.cpp new file mode 100644 index 0000000000..b6ff30e78c --- /dev/null +++ b/src/drivers/barometer/dps310/dps310_main.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** + * + * Copyright (c) 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. + * + ****************************************************************************/ + +#include "DPS310.hpp" + +#include + +namespace dps310 +{ + +enum class DPS310_BUS { + ALL = 0, + I2C_INTERNAL, + I2C_EXTERNAL, + SPI_INTERNAL, + SPI_EXTERNAL +}; + +extern device::Device *DPS310_SPI_interface(uint8_t bus, uint32_t device); +extern device::Device *DPS310_I2C_interface(uint8_t bus, uint32_t device); +typedef device::Device *(*DPS310_constructor)(uint8_t, uint32_t); + +struct dps310_bus_option { + DPS310_BUS busid; + DPS310_constructor interface_constructor; + uint8_t busnum; + uint32_t address; + DPS310 *dev; +} bus_options[] = { +#if defined(PX4_SPI_BUS_2) && defined(PX4_SPIDEV_BARO) + { DPS310_BUS::SPI_INTERNAL, &DPS310_SPI_interface, PX4_SPI_BUS_2, PX4_SPIDEV_BARO, nullptr }, +#endif +#if defined(PX4_I2C_BUS_EXPANSION) && defined(PX4_I2C_OBDEV_DPS310) + { DPS310_BUS::I2C_EXTERNAL, &DPS310_I2C_interface, PX4_I2C_BUS_EXPANSION, PX4_I2C_OBDEV_DPS310, nullptr }, +#endif +}; + +// find a bus structure for a busid +static dps310_bus_option *find_bus(DPS310_BUS busid) +{ + for (dps310_bus_option &bus_option : bus_options) { + if ((busid == DPS310_BUS::ALL || + busid == bus_option.busid) && bus_option.dev != nullptr) { + + return &bus_option; + } + } + + return nullptr; +} + +static bool start_bus(dps310_bus_option &bus) +{ + device::Device *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; + } + + DPS310 *dev = new DPS310(interface); + + if (dev == nullptr || dev->init() != PX4_OK) { + PX4_ERR("driver start failed"); + delete dev; + return false; + } + + bus.dev = dev; + + return true; +} + +static int start(DPS310_BUS busid) +{ + for (dps310_bus_option &bus_option : bus_options) { + if (bus_option.dev != nullptr) { + // this device is already started + PX4_WARN("already started"); + continue; + } + + if (busid != DPS310_BUS::ALL && 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(DPS310_BUS busid) +{ + dps310_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(DPS310_BUS busid) +{ + dps310_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 dsp310 + +extern "C" int dps310_main(int argc, char *argv[]) +{ + int myoptind = 1; + int ch; + const char *myoptarg = nullptr; + + using namespace dps310; + + DPS310_BUS busid = DPS310_BUS::ALL; + + while ((ch = px4_getopt(argc, argv, "XISs", &myoptind, &myoptarg)) != EOF) { + switch (ch) { + case 'X': + busid = DPS310_BUS::I2C_EXTERNAL; + break; + + case 'I': + busid = DPS310_BUS::I2C_INTERNAL; + break; + + case 'S': + busid = DPS310_BUS::SPI_EXTERNAL; + break; + + case 's': + busid = DPS310_BUS::SPI_INTERNAL; + break; + + default: + return usage(); + } + } + + if (myoptind >= argc) { + return usage(); + } + + const char *verb = argv[myoptind]; + + if (!strcmp(verb, "start")) { + return start(busid); + + } else if (!strcmp(verb, "stop")) { + return stop(busid); + + } else if (!strcmp(verb, "status")) { + return status(busid); + } + + return usage(); +} diff --git a/src/drivers/drv_sensor.h b/src/drivers/drv_sensor.h index a6464af4d4..20c90f6844 100644 --- a/src/drivers/drv_sensor.h +++ b/src/drivers/drv_sensor.h @@ -116,6 +116,7 @@ #define DRV_BARO_DEVTYPE_BAROSIM 0x65 #define DRV_DEVTYPE_BMI088 0x66 #define DRV_DEVTYPE_BMP388 0x67 +#define DRV_DEVTYPE_DPS310 0x68 /* * ioctl() definitions