Betaflight DPS368 Barometer Driver Porting Guide

Draft

Openflyworld Technical Documentation

1. Overview

Openflyworld flight controllers use the Infineon DPS368 digital barometric pressure sensor. However, the Betaflight firmware version used by Openflyworld does not provide a dedicated driver for this sensor.

Due to similarities between the DPS368 and DPS310 sensors, the existing Betaflight DPS310 driver is commonly used as a compatibility workaround.

To provide dedicated support for the DPS368, Openflyworld has adapted the existing Betaflight DPS310 driver to create a DPS368-specific driver.

The DPS368 driver is based on the original Betaflight DPS310 driver. It was developed by following the DPS310 driver’s code structure and implementation, with modifications made to support the DPS368 sensor. It is not an independently developed driver written entirely from scratch.

2. Purpose of This Document

This document summarizes the modifications required to port the DPS310 driver for DPS368 support.

It is intended for developers and Openflyworld customers who wish to:

  • Recompile Betaflight firmware for Openflyworld flight controllers.
  • Integrate the DPS368 driver into their own Betaflight source code.
  • Understand the changes made to the original DPS310 driver.
  • Maintain or update customized Betaflight firmware.

3. Important Notes

Driver Origin and Attribution

The DPS368 driver is a derivative implementation based on the existing DPS310 driver from the open-source Betaflight project.

Openflyworld acknowledges the original Betaflight developers and contributors for their work on the DPS310 driver.

The DPS368 adaptation should retain applicable original copyright notices and comply with the licensing requirements of the Betaflight project.

Compatibility

This driver is an Openflyworld modification and should not be considered part of the official Betaflight firmware unless it has been accepted into the upstream project.

Users compiling customized firmware should verify compatibility with their specific Betaflight version and flight controller hardware.

4. DPS368 Driver Porting Procedure

4.1 `src/main/drivers/barometer/barometer.h`

Change: Add `BARO_DPS368` enum entry inside `baroSensor_e`

Why: This enum defines all supported barometer hardware IDs for Betaflight CLI, sensor detection and configuration storage.

“`

typedef enum {

    BARO_DEFAULT = 0,

    BARO_NONE = 1,

    BARO_BMP085 = 2,

    BARO_MS5611 = 3,

    BARO_BMP280 = 4,

    BARO_LPS = 5,

    BARO_QMP6988 = 6,

    BARO_BMP388 = 7,

    BARO_DPS310 = 8,

    BARO_2SMPB_02B = 9,

    BARO_LPS22DF = 10,

    BARO_VIRTUAL = 11,

    BARO_DPS368 = 12, // <<< Added

} baroSensor_e;

“`

 4.2 `src/main/sensors/barometer.c`

Change: Add `case BARO_DPS368:` in barometer detection switch block

Why: When Betaflight scans barometer sensors or user manually sets `baro_hardware = DPS368`, this branch invokes `baroDPS368Detect()` probe function.

“`

case BARO_DPS310:

#if defined(USE_BARO_DPS310)

    if (baroDPS310Detect(&baro.dev)) {

        baroHardware = BARO_DPS310;

        return true;

    }

#endif

break;

case BARO_DPS368: // <<< Added

#if defined(USE_BARO_DPS368)

    if (baroDPS368Detect(&baro.dev)) {

        baroHardware = BARO_DPS368;

        return true;

    }

#endif

break;

“`

 4.3 `mk/source.mk`

Change: Add driver source file entry under barometer source list

Why: Makefile build script, tells compiler to compile `barometer_dps368.c` only when `USE_BARO_DPS368` is enabled.

“`

drivers/barometer/barometer_dps310.c \

drivers/barometer/barometer_dps368.c \ # <<< Added

“`

 4.4 Target `config.h` (your target header, e.g STM32H743 target)

Change: Add compile macro definition

Why: Enable conditional compilation for DPS368 driver, only build this driver when this macro exists.

“`

#define USE_BARO_DPS368

“`

 4.5 `src/main/drivers/barometer/barometer_dps368.c` (NEW FILE)

Change: Create new driver source file

Why: Full DPS368 read, coefficient parsing, measurement setup and sensor detection logic. The driver reuses Betaflight native bus API (I2C). Extra register check for `COEF_SRCE (0x28)` to separate DPS310 / DPS368.

—

Full source of `barometer_dps368.c`

“`

/*

 * This file is part of Betaflight.

 *

 * This Source Code Form is subject to the terms of the Mozilla Public

 * License, v. 2.0. If a copy of the MPL was not distributed with this file,

 * You can obtain one at [http://mozilla.org/MPL/2.0/](http://mozilla.org/MPL/2.0/).

 *

 * Alternatively, the contents of this file may be used under the terms

 * of the GNU General Public License Version 3, as described below:

 *

 * This file is free software: you may copy, redistribute and/or modify

 * it under the terms of the GNU General Public License as published by the

 * Free Software Foundation, either version 3 of the License, or (at your

 * option) any later version.

 *

 * This file is distributed in the hope that it will be useful, but

 * WITHOUT ANY WARRANTY; without even the implied warranty of

 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General

 * Public License for more details.

 *

 * You should have received a copy of the GNU General Public License

 * along with this program. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).

 *

 */

#include <stdbool.h>

#include <stdint.h>

#include <string.h>

#include “platform.h”

#include “build/build_config.h”

#include “build/debug.h”

#include “common/utils.h”

#include “common/maths.h”

#include “drivers/io.h”

#include “drivers/bus.h”

#include “drivers/bus_spi.h”

#include “drivers/time.h”

#include “drivers/barometer/barometer.h”

#if defined(USE_BARO) && defined(USE_BARO_DPS368)

#define DPS368_I2C_ADDR             0x77

#define DPS368_REG_PSR_B2           0x00

#define DPS368_REG_TMP_B2           0x03

#define DPS368_REG_PRS_CFG          0x06

#define DPS368_REG_TMP_CFG          0x07

#define DPS368_REG_MEAS_CFG         0x08

#define DPS368_REG_RESET            0x0C

#define DPS368_REG_ID               0x0D

#define DPS368_REG_COEF             0x10

#define DPS368_REG_COEF_SRCE        0x28

#define DPS368_CHIP_ID              (0x10)

#define DPS368_RESET_BIT_SOFT_RST   (0x09)

typedef struct {

    int32_t c0;

    int32_t c1;

    int32_t c00;

    int32_t c01;

    int32_t c10;

    int32_t c11;

    int32_t c20;

    int32_t c21;

    int32_t c30;

} dps368Coef_t;

static dps368Coef_t dpsCoef;

static int32_t rawTemp;

static int32_t rawPress;

/

 * @brief Read multiple bytes from register buffer

 * @param dev extDevice bus handle

 * @param reg target register address

 * @param data output buffer

 * @param len number of bytes to read

 * @return true on success

 */

static bool dps368ReadRegisterBuffer(extDevice_t *dev, uint8_t reg, uint8_t *data, uint8_t len)

{

    return busReadRegisterBuffer(dev, reg, data, len);

}

/

 * @brief Write single byte to register

 * @param dev extDevice bus handle

 * @param reg target register address

 * @param data value to write

 * @return true on success

 */

static bool dps368WriteRegister(extDevice_t *dev, uint8_t reg, uint8_t data)

{

    return busWriteRegister(dev, reg, data);

}

/

 * @brief Perform software reset on DPS368

 * @param dev extDevice bus handle

 */

static void dps368Reset(extDevice_t *dev)

{

    dps368WriteRegister(dev, DPS368_REG_RESET, DPS368_RESET_BIT_SOFT_RST);

    delay(10);

}

/

 * @brief Read and parse calibration coefficients

 * @param dev extDevice bus handle

 * @return true if coefficients read successfully

 */

static bool dps368ReadCoefficients(extDevice_t *dev)

{

    uint8_t raw[18];

    if (!dps368ReadRegisterBuffer(dev, DPS368_REG_COEF, raw, 18)) {

        return false;

    }

    dpsCoef.c0  = ((int16_t)((raw[0] << 4) | (raw[1] >> 4)));

    if (dpsCoef.c0 & 0x800)  dpsCoef.c0  -= 0x1000;

    dpsCoef.c1  = ((int16_t)(((raw[1] & 0x0F) << 8) | raw[2]));

    if (dpsCoef.c1 & 0x800)  dpsCoef.c1  -= 0x1000;

    dpsCoef.c00 = ((int32_t)((raw[3] << 12) | (raw[4] << 4) | (raw[5] >> 4)));

    if (dpsCoef.c00 & 0x80000) dpsCoef.c00 -= 0x100000;

    dpsCoef.c01 = ((int32_t)(((raw[5] & 0x0F) << 16) | (raw[6] << 8) | raw[7]));

    if (dpsCoef.c01 & 0x80000) dpsCoef.c01 -= 0x100000;

    dpsCoef.c10 = ((int32_t)((raw[8] << 12) | (raw[9] << 4) | (raw[10] >> 4)));

    if (dpsCoef.c10 & 0x80000) dpsCoef.c10 -= 0x100000;

    dpsCoef.c11 = ((int32_t)(((raw[10] & 0x0F) << 16) | (raw[11] << 8) | raw[12]));

    if (dpsCoef.c11 & 0x80000) dpsCoef.c11 -= 0x100000;

    dpsCoef.c20 = ((int32_t)((raw[13] << 12) | (raw[14] << 4) | (raw[15] >> 4)));

    if (dpsCoef.c20 & 0x80000) dpsCoef.c20 -= 0x100000;

    dpsCoef.c21 = ((int32_t)(((raw[15] & 0x0F) << 16) | (raw[16] << 8) | raw[17]));

    if (dpsCoef.c21 & 0x80000) dpsCoef.c21 -= 0x100000;

    dpsCoef.c30 = ((int16_t)((raw[17] << 4)));

    return true;

}

/

 * @brief Prepare temperature sensor before read

 * @param baro barometer device handle

 * @return true on success

 */

static bool dps368StartUT(baroDev_t *baro)

{

    UNUSED(baro);

    return true;

}

/

 * @brief Read raw temperature sample

 * @param baro barometer device handle

 * @return true on success

 */

static bool dps368ReadUT(baroDev_t *baro)

{

    extDevice_t *dev = &baro->dev;

    uint8_t buf[3];

    if (!dps368ReadRegisterBuffer(dev, DPS368_REG_TMP_B2, buf, 3)) {

        return false;

    }

    rawTemp = (int32_t)((buf[0] << 16) | (buf[1] << 8) | buf[2]);

    if (rawTemp & 0x800000) rawTemp -= 0x1000000;

    return true;

}

/

 * @brief Wait for temperature measurement ready

 * @param baro barometer device handle

 * @return true on measurement ready

 */

static bool dps368GetUT(baroDev_t *baro)

{

    UNUSED(baro);

    return true;

}

/

 * @brief Prepare pressure sensor before read

 * @param baro barometer device handle

 * @return true on success

 */

static bool dps368StartUP(baroDev_t *baro)

{

    UNUSED(baro);

    return true;

}

/

 * @brief Read raw pressure sample

 * @param baro barometer device handle

 * @return true on success

 */

static bool dps368ReadUP(baroDev_t *baro)

{

    extDevice_t *dev = &baro->dev;

    uint8_t buf[3];

    if (!dps368ReadRegisterBuffer(dev, DPS368_REG_PSR_B2, buf, 3)) {

        return false;

    }

    rawPress = (int32_t)((buf[0] << 16) | (buf[1] << 8) | buf[2]);

    if (rawPress & 0x800000) rawPress -= 0x1000000;

    return true;

}

/

 * @brief Wait for pressure measurement ready

 * @param baro barometer device handle

 * @return true on measurement ready

 */

static bool dps368GetUP(baroDev_t *baro)

{

    UNUSED(baro);

    return true;

}

/

 * @brief Calculate compensated pressure and temperature

 * @param pressure output pressure in centi-Pascal

 * @param temperature output temperature in centi-degree Celsius

 */

static void dps368Calculate(int32_t *pressure, int32_t *temperature)

{

    const float tRawScaled = rawTemp / 1048576.0f;

    const float pRawScaled = rawPress / 1048576.0f;

    const float temp = dpsCoef.c0 * 0.5f + dpsCoef.c1 * tRawScaled;

    const float press = dpsCoef.c00

        + pRawScaled * (dpsCoef.c10 + pRawScaled * (dpsCoef.c20 + pRawScaled * dpsCoef.c30))

        + tRawScaled * (dpsCoef.c01 + pRawScaled * (dpsCoef.c11 + pRawScaled * dpsCoef.c21));

    *temperature = (int32_t)(temp * 100.0f);

    *pressure    = (int32_t)(press * 100.0f);

}

/

 * @brief DPS368 sensor detection and initialization

 * @param baro barometer device handle

 * @return true if DPS368 detected and initialized

 * @note DPS310 and DPS368 share same chip ID 0x10.

 * DPS310 has COEF_SRCE register(0x28), DPS368 does NOT have this register.

 * Read 0x28, if returns not 0xFF, treat it as DPS310 and reject.

 */

bool baroDPS368Detect(baroDev_t *baro)

{

    extDevice_t *dev = &baro->dev;

    uint8_t chipId = busReadRegister(dev, DPS368_REG_ID);

    if (chipId != DPS368_CHIP_ID)

    {

        return false;

    }

    // Distinguish DPS310 from DPS368

    uint8_t coefSrce = busReadRegister(dev, DPS368_REG_COEF_SRCE);

    if (coefSrce != 0xFF)

    {

        // Register exists, this is DPS310

        return false;

    }

    dps368Reset(dev);

    if (!dps368ReadCoefficients(dev))

    {

        return false;

    }

    // Configure oversampling: Pressure OSR16, Temperature OSR16

    if (!dps368WriteRegister(dev, DPS368_REG_PRS_CFG, 0x06)) { return false; }

    if (!dps368WriteRegister(dev, DPS368_REG_TMP_CFG, 0x86)) { return false; }

    if (!dps368WriteRegister(dev, DPS368_REG_MEAS_CFG, 0x07)){ return false; }

    baro->ut_delay = 25000;

    baro->start_ut = dps368StartUT;

    baro->read_ut  = dps368ReadUT;

    baro->get_ut   = dps368GetUT;

    baro->start_up = dps368StartUP;

    baro->read_up  = dps368ReadUP;

    baro->get_up   = dps368GetUP;

    baro->calculate = dps368Calculate;

    baro->combined_read = true;

    return true;

}

#endif

“`

3. CLI usage

“`

# Manual selection

set baro_hardware = DPS368

set baro_bustype = I2C

set baro_i2c_device = 2

set baro_i2c_address = 119

save

“`

5. Known limitation & upstream note

1. DPS310 and DPS368 have identical Chip ID `0x10`. The differentiation method relies on reading register `0x28`. I2C read of non-existing register returns `0xFF` on this bus driver.

2. If your hardware/I2C implementation returns different value for missing register, detection logic needs adjustment.

3. This driver is I2C-only for now. SPI support can be added later following DPS310 SPI pattern.

 6. Next step for upstream PR

1. Add `barometer_dps368.h` header (optional, match DPS310 structure)

2. Add CLI string table entry for DPS368 (so `set baro_hardware` auto complete works)

3. Add target `#define USE_BARO_DPS368` into default target config if needed