Paparazzi UAS v7.1_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
spa06.c File Reference

Driver for the Goertek SPA06-003 / SPL06-001 barometer (I2C or SPI) More...

+ Include dependency graph for spa06.c:

Go to the source code of this file.

Macros

#define SPL06_PRESSURE_OVERSAMPLING   SPL06_OVERSAMPLING_64X_P
 
#define SPL06_TEMPERATURE_OVERSAMPLING   SPL06_OVERSAMPLING_1X_T
 
#define SPA06_BROKEN_RETRY_US   5000000
 retry a failed/absent sensor every 5s instead of giving up forever
 
#define SPA06_MAX_ERROR_CNT   10
 consecutive transaction failures before escalating
 
#define SPA06_PRESSURE_MIN_PA   30000.0f
 specified measurement range is 300-1200 hPa,
 
#define SPA06_PRESSURE_MAX_PA   120000.0f
 anything outside means the data got corrupted
 

Functions

static void parse_sensor_data (struct spa06_t *spa, volatile uint8_t *data)
 Extract the raw 24-bit pressure and temperature measurements.
 
static void parse_calib_data (struct spa06_t *spa, volatile uint8_t *coef)
 Unpack one chunk of calibration coefficient bytes.
 
static void compensate_pressure (struct spa06_t *spa)
 Convert raw measurements into pressure [Pa] and temperature [deg C].
 
static bool spa06_config (struct spa06_t *spa)
 Configure the spa06 device register by register.
 
static bool spa06_get_calib (struct spa06_t *spa)
 Request the calibration coefficients, one chunk per call.
 
static int32_t raw_value_scale_factor (uint8_t oversampling)
 Scale factor for raw values at a given oversampling setting.
 
static void spa06_register_write (struct spa06_t *spa, uint8_t reg, uint8_t value)
 Write a single register over the configured bus (SPI or I2C)
 
static void spa06_register_read (struct spa06_t *spa, uint8_t reg, uint16_t size)
 Read consecutive registers over the configured bus (SPI or I2C)
 
static int32_t getTwosComplement (uint32_t raw, uint8_t length)
 Sign-extend a raw two's complement value of arbitrary bit length.
 
void spa06_init (struct spa06_t *spa)
 Initialize the spa06 sensor instance.
 
void spa06_periodic (struct spa06_t *spa)
 Should be called periodically to request sensor readings.
 
void spa06_event (struct spa06_t *spa)
 Should be called in the event thread.
 

Detailed Description

Driver for the Goertek SPA06-003 / SPL06-001 barometer (I2C or SPI)

Non-blocking state machine driver:

* UNINIT (soft reset + 40ms wait) -> IDLE (chip ID) -> INIT_OK (wait ready)
*   -> GET_COEF_SRCE -> GET_CALIB (3 chunks) -> CONFIGURE (4 writes)
*   -> READ_STATUS_REG <-> READ_DATA_REGS (looping)
* 

spa06_periodic() submits at most one bus transaction per call and spa06_event() consumes the result and advances the state machine. The device type (SPA06 vs SPL06) is detected from the chip ID and decides whether the additional c31/c40 calibration coefficients are used.

Definition in file spa06.c.

Macro Definition Documentation

◆ SPA06_BROKEN_RETRY_US

#define SPA06_BROKEN_RETRY_US   5000000

retry a failed/absent sensor every 5s instead of giving up forever

Definition at line 49 of file spa06.c.

◆ SPA06_MAX_ERROR_CNT

#define SPA06_MAX_ERROR_CNT   10

consecutive transaction failures before escalating

Definition at line 50 of file spa06.c.

◆ SPA06_PRESSURE_MAX_PA

#define SPA06_PRESSURE_MAX_PA   120000.0f

anything outside means the data got corrupted

Definition at line 52 of file spa06.c.

◆ SPA06_PRESSURE_MIN_PA

#define SPA06_PRESSURE_MIN_PA   30000.0f

specified measurement range is 300-1200 hPa,

Definition at line 51 of file spa06.c.

◆ SPL06_PRESSURE_OVERSAMPLING

#define SPL06_PRESSURE_OVERSAMPLING   SPL06_OVERSAMPLING_64X_P

Definition at line 45 of file spa06.c.

◆ SPL06_TEMPERATURE_OVERSAMPLING

#define SPL06_TEMPERATURE_OVERSAMPLING   SPL06_OVERSAMPLING_1X_T

Definition at line 46 of file spa06.c.

Function Documentation

◆ compensate_pressure()

static void compensate_pressure ( struct spa06_t spa)
static

Convert raw measurements into pressure [Pa] and temperature [deg C].

Parameters
spaThe spa06 instance

Implements the compensation formulas of the datasheet (sections 4.9.1 and 4.9.2) using the factory calibration coefficients. The scale factors are tied to the configured oversampling; keep SPL06_*_OVERSAMPLING and spa06_config() in sync.

Definition at line 441 of file spa06.c.

References foo, raw_value_scale_factor(), SPL06_PRESSURE_OVERSAMPLING, and SPL06_TEMPERATURE_OVERSAMPLING.

Referenced by spa06_event().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getTwosComplement()

static int32_t getTwosComplement ( uint32_t  raw,
uint8_t  length 
)
static

Sign-extend a raw two's complement value of arbitrary bit length.

Parameters
rawUnsigned register value holding the two's complement number
lengthNumber of significant bits (e.g. 12, 16, 20, 24)
Returns
Sign-extended signed value

Definition at line 639 of file spa06.c.

Referenced by parse_calib_data(), and parse_sensor_data().

+ Here is the caller graph for this function:

◆ parse_calib_data()

static void parse_calib_data ( struct spa06_t spa,
volatile uint8_t coef 
)
static

Unpack one chunk of calibration coefficient bytes.

Parameters
spaThe spa06 instance, calib_idx selects which chunk is being parsed
coefThe coefficient bytes as read by spa06_get_calib()

The coefficients are packed as mixed 12/16/20 bit two's complement values, see the COEF register description in the datasheet. Called once per chunk (in reading order); increments calib_idx itself. The SPA06-only c31/c40 coefficients are zeroed on the SPL06 so that a single compensation formula can serve both devices.

Definition at line 379 of file spa06.c.

References foo, getTwosComplement(), and SPA06.

Referenced by spa06_event().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parse_sensor_data()

static void parse_sensor_data ( struct spa06_t spa,
volatile uint8_t data 
)
static

Extract the raw 24-bit pressure and temperature measurements.

Parameters
spaThe spa06 instance
dataThe 6 result bytes (registers 0x00-0x05, burst-read in one transaction)

Definition at line 361 of file spa06.c.

References foo, and getTwosComplement().

Referenced by spa06_event().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ raw_value_scale_factor()

static int32_t raw_value_scale_factor ( uint8_t  oversampling)
static

Scale factor for raw values at a given oversampling setting.

Parameters
oversamplingOversampling register code (0-7, see SPL06_OVERSAMPLING_*)
Returns
Compensation scale factor from the datasheet, -1 for an invalid code

Note the values are not monotonic: settings above 8x store shifted results (see SPL06_*_RESULT_BIT_SHIFT) and therefore use smaller factors.

Definition at line 551 of file spa06.c.

References foo.

Referenced by compensate_pressure().

+ Here is the caller graph for this function:

◆ spa06_config()

static bool spa06_config ( struct spa06_t spa)
static

Configure the spa06 device register by register.

Writes PRS_CFG, TMP_CFG (including the calibration temperature source read earlier), the result bit shifts (mandatory for oversampling > 8x) and finally enables continuous measurements. Only one register is written per call; config_idx tracks the progress.

Parameters
spaThe spa06 instance
Returns
true When the configuration is completed
false Still busy configuring

Definition at line 469 of file spa06.c.

References foo, spa06_register_write(), SPL06_MEAS_CON_PRE_TEM, SPL06_PRES_RATE_4HZ, SPL06_PRESSURE_OVERSAMPLING, SPL06_PRESSURE_RESULT_BIT_SHIFT, SPL06_REG_INT_AND_FIFO_CFG, SPL06_REG_MODE_AND_STATUS, SPL06_REG_PRESSURE_CFG, SPL06_REG_TEMPERATURE_CFG, SPL06_TEMP_RATE_4HZ, SPL06_TEMPERATURE_OVERSAMPLING, and SPL06_TEMPERATURE_RESULT_BIT_SHIFT.

Referenced by spa06_periodic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spa06_event()

void spa06_event ( struct spa06_t spa)

Should be called in the event thread.

Handle finished transactions and publish measurements; call from the event loop.

  • Configures the sensor and reads the responses
  • Parses the responses and publishes plausibility-checked measurements through data_available

On a failed transaction it counts consecutive errors, escalating from a simple retry to a full re-initialization (SPA06_MAX_ERROR_CNT) and, while uninitialized, to a timed backoff. During initialization the I2C address is hot-swapped between the two possible assignments on every failure.

Parameters
spaThe spa06 instance

Definition at line 230 of file spa06.c.

References compensate_pressure(), foo, get_sys_time_usec(), I2CTransDone, I2CTransFailed, I2CTransSuccess, parse_calib_data(), parse_sensor_data(), SPA06, SPA06_CHIP_ID, SPA06_I2C, SPA06_I2C_ADDR, SPA06_I2C_ADDR_ALT, SPA06_MAX_ERROR_CNT, SPA06_PRESSURE_MAX_PA, SPA06_PRESSURE_MIN_PA, SPA06_SPI, SPA06_STATUS_CONFIGURE, SPA06_STATUS_GET_CALIB, SPA06_STATUS_GET_COEF_SRCE, SPA06_STATUS_IDLE, SPA06_STATUS_INIT_OK, SPA06_STATUS_READ_DATA_REGS, SPA06_STATUS_READ_STATUS_REG, SPA06_STATUS_UNINIT, SPITransDone, SPITransFailed, SPITransSuccess, SPL06, SPL06_CHIP_ID, SPL06_COEF_SRCE_BIT_TMP_COEF_SRCE, SPL06_MEAS_CFG_COEFFS_RDY, SPL06_MEAS_CFG_PRESSURE_RDY, SPL06_MEAS_CFG_SENSOR_RDY, SPL06_MEAS_CFG_TEMPERATURE_RDY, and status.

Referenced by baro_spa06_event().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spa06_get_calib()

static bool spa06_get_calib ( struct spa06_t spa)
static

Request the calibration coefficients, one chunk per call.

The coefficients are read in three chunks because the chip returns a read failure when reading the whole block at once over I2C. The last chunk is device-dependent: the SPA06 has two extra coefficients (c31/c40) in registers that do not exist on the SPL06. Parsing happens in spa06_event() via parse_calib_data(), which advances calib_idx.

Parameters
spaThe spa06 instance
Returns
true When all coefficients have been requested
false Still busy reading

Definition at line 523 of file spa06.c.

References foo, SPA06, spa06_register_read(), and SPL06_REG_CALIB_COEFFS_START.

Referenced by spa06_periodic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spa06_init()

void spa06_init ( struct spa06_t spa)

Initialize the spa06 sensor instance.

Initialize the driver instance, expects bus and i2c/spi members to be pre-filled.

Parameters
spaThe structure containing the configuration of the spa06 instance

Definition at line 71 of file spa06.c.

References foo, I2CTransDone, SPA06_SPI, SPA06_STATUS_UNINIT, SPA06_UNKNOWN, SPICphaEdge2, SPICpolIdleHigh, SPIDiv16, SPIDss8bit, SPIMSBFirst, SPISelectUnselect, and SPITransDone.

Referenced by baro_spa06_init().

+ Here is the caller graph for this function:

◆ spa06_periodic()

void spa06_periodic ( struct spa06_t spa)

Should be called periodically to request sensor readings.

Run the state machine, submits at most one bus transaction; call periodically.

  • First detects the sensor using WHO_AM_I reading
  • Configures the sensor according the users requested configuration
  • Requests a sensor reading

Submits at most one bus transaction per call and does nothing while a transaction is still in flight. A persistently failing or absent sensor is retried after a SPA06_BROKEN_RETRY_US backoff instead of spamming the bus.

Parameters
spaThe spa06 instance

Definition at line 131 of file spa06.c.

References foo, get_sys_time_usec(), I2CTransDone, SPA06_BROKEN_RETRY_US, spa06_config(), spa06_get_calib(), SPA06_I2C, spa06_register_read(), spa06_register_write(), SPA06_SPI, SPA06_STATUS_CONFIGURE, SPA06_STATUS_GET_CALIB, SPA06_STATUS_GET_COEF_SRCE, SPA06_STATUS_IDLE, SPA06_STATUS_INIT_OK, SPA06_STATUS_READ_DATA_REGS, SPA06_STATUS_READ_STATUS_REG, SPA06_STATUS_UNINIT, SPITransDone, SPL06_PRESSURE_LEN, SPL06_REG_CHIP_ID, SPL06_REG_COEF_SRCE, SPL06_REG_MODE_AND_STATUS, SPL06_REG_PRESSURE_B2, SPL06_REG_RST, SPL06_RESET_BIT_SOFT_RST, and SPL06_TEMPERATURE_LEN.

Referenced by baro_spa06_periodic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spa06_register_read()

static void spa06_register_read ( struct spa06_t spa,
uint8_t  reg,
uint16_t  size 
)
static

Read consecutive registers over the configured bus (SPI or I2C)

Parameters
spaThe spa06 instance
regThe first register address (auto-incremented by the sensor)
sizeThe number of registers to read

The response ends up in rx_buffer (which already hides the SPI dummy byte). Requests larger than the receive buffer are rejected. Silently does nothing while a transaction is still in flight.

Definition at line 608 of file spa06.c.

References foo, I2C_BUF_LEN, i2c_transceive(), I2CTransDone, SPA06_SPI, spi_submit(), SPITransDone, and SPL06_READ_FLAG.

Referenced by spa06_get_calib(), and spa06_periodic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ spa06_register_write()

static void spa06_register_write ( struct spa06_t spa,
uint8_t  reg,
uint8_t  value 
)
static

Write a single register over the configured bus (SPI or I2C)

Parameters
spaThe spa06 instance
regThe register address (bit 7 is masked off for the SPI write command)
valueThe value to write to the register

Silently does nothing while a transaction is still in flight; callers are driven by the periodic/event pair, so the write is simply retried later.

Definition at line 577 of file spa06.c.

References foo, i2c_transmit(), I2CTransDone, SPA06_SPI, spi_submit(), and SPITransDone.

Referenced by spa06_config(), and spa06_periodic().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: