2022-01-22 17:47:49 +01:00
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* drivers/sensors/ms56xx_uorb.c
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
|
|
* this work for additional information regarding copyright ownership. The
|
|
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
|
|
* "License"); you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <nuttx/nuttx.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <fixedmath.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
#include <nuttx/fs/fs.h>
|
|
|
|
#include <nuttx/signal.h>
|
|
|
|
#include <nuttx/kmalloc.h>
|
|
|
|
#include <nuttx/kthread.h>
|
2022-09-06 08:18:45 +02:00
|
|
|
#include <nuttx/mutex.h>
|
2022-01-22 17:47:49 +01:00
|
|
|
#include <nuttx/semaphore.h>
|
|
|
|
#include <nuttx/i2c/i2c_master.h>
|
|
|
|
#include <nuttx/sensors/sensor.h>
|
2023-11-28 02:06:04 +01:00
|
|
|
#include <nuttx/sensors/ms56xx.h>
|
2022-01-22 17:47:49 +01:00
|
|
|
#include <nuttx/sensors/msxxxx_crc4.h>
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
#if defined(CONFIG_SENSORS_MS56XX) && \
|
2022-01-22 17:47:49 +01:00
|
|
|
(defined(CONFIG_I2C) || defined(CONFIG_SPI))
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
#define MS56XX_CMD_RESET 0x1e
|
|
|
|
#define MS56XX_CMD_START_ADC_READ 0x00
|
|
|
|
#define MS56XX_CMD_CONV_D1_OSR_256 0x40 /* D1 = uncompensated pressure */
|
|
|
|
#define MS56XX_CMD_CONV_D1_OSR_512 0x42
|
|
|
|
#define MS56XX_CMD_CONV_D1_OSR_1024 0x44
|
|
|
|
#define MS56XX_CMD_CONV_D1_OSR_2048 0x46
|
|
|
|
#define MS56XX_CMD_CONV_D1_OSR_4096 0x48
|
|
|
|
#define MS56XX_CMD_CONV_D2_OSR_256 0x50 /* D2 = uncompensated pressure */
|
|
|
|
#define MS56XX_CMD_CONV_D2_OSR_512 0x52
|
|
|
|
#define MS56XX_CMD_CONV_D2_OSR_1024 0x54
|
|
|
|
#define MS56XX_CMD_CONV_D2_OSR_2048 0x56
|
|
|
|
#define MS56XX_CMD_CONV_D2_OSR_4096 0x58
|
|
|
|
#define MS56XX_CMD_ADC_READ 0x00
|
|
|
|
#define MS56XX_CMD_ADC_PROM_READ(i) (0xa0 + (i)*2) /* 0xA0 - 0xAE */
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Type Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_calib_s
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
uint16_t reversed;
|
|
|
|
uint16_t c1;
|
|
|
|
uint16_t c2;
|
|
|
|
uint16_t c3;
|
|
|
|
uint16_t c4;
|
|
|
|
uint16_t c5;
|
|
|
|
uint16_t c6;
|
|
|
|
uint16_t crc;
|
|
|
|
};
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_dev_s
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
FAR struct sensor_lowerhalf_s sensor_lower;
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
#ifdef CONFIG_MS56XX_I2C
|
2022-09-06 08:18:45 +02:00
|
|
|
FAR struct i2c_master_s *i2c; /* I2C interface */
|
|
|
|
uint8_t addr; /* I2C address */
|
2022-01-22 17:47:49 +01:00
|
|
|
#endif
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
#ifdef CONFIG_MS56XX_SPI
|
2022-09-06 08:18:45 +02:00
|
|
|
FAR struct spi_dev_s *spi; /* SPI interface */
|
2022-01-22 17:47:49 +01:00
|
|
|
#endif
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
enum ms56xx_model_e model; /* Model of MS56XX */
|
2022-09-06 08:18:45 +02:00
|
|
|
uint32_t freq; /* Bus Frequency I2C/SPI */
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_calib_s calib; /* Calib. params from ROM */
|
2024-09-19 11:27:18 +02:00
|
|
|
uint32_t interval; /* Polling interval */
|
2023-11-28 02:06:04 +01:00
|
|
|
bool enabled; /* Enable/Disable MS56XX */
|
2022-09-06 08:18:45 +02:00
|
|
|
sem_t run; /* Locks measure cycle */
|
|
|
|
mutex_t lock; /* Manages exclusive to device */
|
2022-01-22 17:47:49 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Function Prototypes
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_sendcmd(FAR struct ms56xx_dev_s *priv,
|
2022-01-22 17:47:49 +01:00
|
|
|
uint8_t cmd);
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_read16(FAR struct ms56xx_dev_s *priv,
|
2022-01-22 17:47:49 +01:00
|
|
|
FAR uint8_t *regval);
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_read24(FAR struct ms56xx_dev_s *priv,
|
2022-01-22 17:47:49 +01:00
|
|
|
FAR uint8_t *regval);
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int32_t ms56xx_compensate_temp(FAR struct ms56xx_dev_s *priv,
|
2023-12-20 03:28:40 +01:00
|
|
|
uint32_t temp_raw, int32_t *deltat);
|
2023-11-28 02:06:04 +01:00
|
|
|
static uint32_t ms56xx_compensate_press(FAR struct ms56xx_dev_s *priv,
|
2023-11-28 06:46:48 +01:00
|
|
|
uint32_t press, uint32_t dt,
|
2023-12-20 03:11:55 +01:00
|
|
|
int32_t *temp);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static unsigned long ms56xx_curtime(void);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/* Sensor methods */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_set_interval(FAR struct sensor_lowerhalf_s *lower,
|
2022-04-14 05:58:35 +02:00
|
|
|
FAR struct file *filep,
|
2024-09-19 11:27:18 +02:00
|
|
|
FAR uint32_t *period_us);
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_activate(FAR struct sensor_lowerhalf_s *lower,
|
2022-04-14 05:58:35 +02:00
|
|
|
FAR struct file *filep, bool enable);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
#if 0 /* Please read below */
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_fetch(FAR struct sensor_lowerhalf_s *lower,
|
2022-01-22 17:47:49 +01:00
|
|
|
FAR char *buffer, size_t buflen);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static const struct sensor_ops_s g_sensor_ops =
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
.activate = ms56xx_activate,
|
|
|
|
.fetch = NULL, /* ms56xx_fetch */
|
|
|
|
.set_interval = ms56xx_set_interval,
|
2022-01-22 17:47:49 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_curtime
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description: Helper to get current timestamp.
|
|
|
|
*
|
|
|
|
* Return:
|
|
|
|
* Timestamp in microseconds
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static unsigned long ms56xx_curtime(void)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
|
2022-02-22 18:35:23 +01:00
|
|
|
clock_systime_timespec(&ts);
|
2022-01-22 17:47:49 +01:00
|
|
|
return 1000000ull * ts.tv_sec + ts.tv_nsec / 1000;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_sendcmd
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2023-11-28 02:06:04 +01:00
|
|
|
* Send a command (8-bit) to MS56XX
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_sendcmd(FAR struct ms56xx_dev_s *priv, uint8_t cmd)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
struct i2c_msg_s msg;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
msg.frequency = priv->freq;
|
|
|
|
msg.addr = priv->addr;
|
|
|
|
msg.flags = 0;
|
|
|
|
msg.buffer = &cmd;
|
|
|
|
msg.length = 1;
|
|
|
|
|
|
|
|
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("I2C_TRANSFER failed: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_read16
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2023-11-28 02:06:04 +01:00
|
|
|
* Read 16-bit from a MS56XX register
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_read16(FAR struct ms56xx_dev_s *priv, FAR uint8_t *regval)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
struct i2c_msg_s msg;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
msg.frequency = priv->freq;
|
|
|
|
msg.addr = priv->addr;
|
|
|
|
msg.flags = I2C_M_READ;
|
|
|
|
msg.buffer = regval;
|
|
|
|
msg.length = 2;
|
|
|
|
|
|
|
|
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("I2C_TRANSFER failed: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_read24
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2023-11-28 02:06:04 +01:00
|
|
|
* Read 24-bit from a MS56XX register
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_read24(FAR struct ms56xx_dev_s *priv, uint8_t *regval)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
struct i2c_msg_s msg;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
msg.frequency = priv->freq;
|
|
|
|
msg.addr = priv->addr;
|
|
|
|
msg.flags = I2C_M_READ;
|
|
|
|
msg.buffer = regval;
|
|
|
|
msg.length = 3;
|
|
|
|
|
|
|
|
ret = I2C_TRANSFER(priv->i2c, &msg, 1);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("I2C_TRANSFER failed: %d\n", ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static inline void baro_measure_read(FAR struct ms56xx_dev_s *priv,
|
2022-03-25 11:10:24 +01:00
|
|
|
FAR struct sensor_baro *baro)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
uint32_t press;
|
2023-12-20 03:28:40 +01:00
|
|
|
uint32_t temp_raw;
|
|
|
|
int32_t temp;
|
2022-01-22 17:47:49 +01:00
|
|
|
int32_t deltat;
|
|
|
|
int ret;
|
|
|
|
uint8_t buffer[3];
|
|
|
|
|
|
|
|
/* Enforce exclusive access */
|
|
|
|
|
2022-09-06 08:18:45 +02:00
|
|
|
ret = nxmutex_lock(&priv->lock);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send command to start a D1 (pressure) conversion */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_CONV_D1_OSR_4096);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("Fail to send cmd MS56XX_CMD_CONV_D1_OSR_4096!\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait data acquisition */
|
|
|
|
|
|
|
|
up_udelay(10000);
|
|
|
|
|
|
|
|
/* Send command to start a read sequence */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_START_ADC_READ);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("Fail to send cmd MS56XX_CMD_START_ADC_READ!\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait data get ready */
|
|
|
|
|
|
|
|
up_udelay(4000);
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_read24(priv, buffer);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("Fail to read pressure!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
press = (uint32_t) buffer[0] << 16 |
|
|
|
|
(uint32_t) buffer[1] << 8 |
|
|
|
|
(uint32_t) buffer[2];
|
|
|
|
|
|
|
|
/* Send command to start a D2 (temperature) conversion */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_CONV_D2_OSR_4096);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("Fail to send cmd MS56XX_CMD_CONV_D2_OSR_4096!\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait data acquisition */
|
|
|
|
|
|
|
|
up_udelay(10000);
|
|
|
|
|
|
|
|
/* Send command to start a read sequence */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_START_ADC_READ);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("Fail to send cmd MS56XX_CMD_START_ADC_READ!\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait data get ready */
|
|
|
|
|
|
|
|
up_udelay(4000);
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_read24(priv, buffer);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("Fail to read temperature!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-20 03:28:40 +01:00
|
|
|
temp_raw = (uint32_t) buffer[0] << 16 |
|
|
|
|
(uint32_t) buffer[1] << 8 |
|
|
|
|
(uint32_t) buffer[2];
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2022-09-06 08:18:45 +02:00
|
|
|
/* Release the mutex */
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2022-09-06 08:18:45 +02:00
|
|
|
nxmutex_unlock(&priv->lock);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/* Compensate the temp/press with calibration data */
|
|
|
|
|
2023-12-20 03:28:40 +01:00
|
|
|
temp = ms56xx_compensate_temp(priv, temp_raw, &deltat);
|
2023-12-20 03:11:55 +01:00
|
|
|
press = ms56xx_compensate_press(priv, press, deltat, &temp);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
baro->timestamp = ms56xx_curtime();
|
2022-01-22 17:47:49 +01:00
|
|
|
baro->pressure = press / 100.0f;
|
|
|
|
baro->temperature = temp / 100.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_thread
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description: Thread for performing interval measurement cycle and data
|
|
|
|
* read.
|
|
|
|
*
|
|
|
|
* Parameter:
|
2024-03-05 05:17:50 +01:00
|
|
|
* argc - Number of arguments
|
2022-01-22 17:47:49 +01:00
|
|
|
* argv - Pointer to argument list
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_thread(int argc, char **argv)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
FAR struct ms56xx_dev_s *priv = (FAR struct ms56xx_dev_s *)
|
2023-07-25 14:08:53 +02:00
|
|
|
((uintptr_t)strtoul(argv[1], NULL, 16));
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2022-03-25 11:10:24 +01:00
|
|
|
struct sensor_baro baro_data;
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (!priv->enabled)
|
|
|
|
{
|
|
|
|
/* Waiting to be woken up */
|
|
|
|
|
|
|
|
ret = nxsem_wait(&priv->run);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
baro_measure_read(priv, &baro_data);
|
|
|
|
|
|
|
|
priv->sensor_lower.push_event(priv->sensor_lower.priv, &baro_data,
|
2022-03-25 11:10:24 +01:00
|
|
|
sizeof(struct sensor_baro));
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/* Sleeping thread before fetching the next sensor data */
|
|
|
|
|
|
|
|
nxsig_usleep(priv->interval);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_initialize
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2023-11-28 02:06:04 +01:00
|
|
|
* Initialize MS56XX device
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_initialize(FAR struct ms56xx_dev_s *priv)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
uint16_t prom[8];
|
|
|
|
uint8_t data[2];
|
|
|
|
uint8_t crc;
|
|
|
|
int i;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Get calibration data. */
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_RESET);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("ms56xx reset failed\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We have to wait before the prom is ready is be read */
|
|
|
|
|
|
|
|
up_udelay(10000);
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_sendcmd(priv, MS56XX_CMD_ADC_PROM_READ(i));
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("ms56xx_sendcmd failed\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_read16(priv, data);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("ms56xx_read16 failed\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
prom[i] = (uint16_t) data[0] << 8 | (uint16_t) data[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the 4-bit CRC from PROM */
|
|
|
|
|
|
|
|
crc = (uint8_t)(prom[7] & 0xf);
|
|
|
|
|
|
|
|
/* Verify if the calculated CRC is equal to PROM's CRC */
|
|
|
|
|
|
|
|
if (crc != msxxxx_crc4(prom, 7, 0xff))
|
|
|
|
{
|
|
|
|
snerr("ERROR: Calculated CRC different from PROM's CRC!\n");
|
|
|
|
return -ENODEV;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fill read calibration coefficients */
|
|
|
|
|
|
|
|
priv->calib.c1 = prom[1];
|
|
|
|
priv->calib.c2 = prom[2];
|
|
|
|
priv->calib.c3 = prom[3];
|
|
|
|
priv->calib.c4 = prom[4];
|
|
|
|
priv->calib.c5 = prom[5];
|
|
|
|
priv->calib.c6 = prom[6];
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_compensate_temp
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* calculate compensate temperature
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* temp - uncompensate value of temperature.
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* calculate result of compensate temperature.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int32_t ms56xx_compensate_temp(FAR struct ms56xx_dev_s *priv,
|
2023-12-20 03:28:40 +01:00
|
|
|
uint32_t temp_raw, int32_t *deltat)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_calib_s *c = &priv->calib;
|
2022-01-22 17:47:49 +01:00
|
|
|
int32_t dt;
|
2023-12-20 03:28:40 +01:00
|
|
|
int32_t temp;
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/* dt = d1 - c5 * 256 */
|
|
|
|
|
2023-12-20 03:28:40 +01:00
|
|
|
dt = temp_raw - ((int32_t) c->c5 << 8);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
/* temp = 2000 + (dt * c6) / 8388608 */
|
|
|
|
|
|
|
|
temp = 2000 + (((int64_t) (dt * c->c6)) >> 23);
|
|
|
|
|
|
|
|
/* Save dt that will be used for pressure calibration */
|
|
|
|
|
|
|
|
*deltat = dt;
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_compensate_press
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* calculate compensate pressure
|
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* press - uncompensate value of pressure.
|
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* calculate result of compensate pressure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static uint32_t ms56xx_compensate_press(FAR struct ms56xx_dev_s *priv,
|
2023-11-28 06:46:48 +01:00
|
|
|
uint32_t press, uint32_t dt,
|
2023-12-20 03:11:55 +01:00
|
|
|
int32_t *temp)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_calib_s *c = &priv->calib;
|
|
|
|
int64_t off = 0;
|
|
|
|
int64_t sens = 0;
|
2023-11-28 06:46:48 +01:00
|
|
|
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
|
|
|
|
int64_t off2 = 0;
|
|
|
|
int64_t sens2 = 0;
|
2023-12-20 03:11:55 +01:00
|
|
|
int64_t t2 = 0;
|
2023-11-28 06:46:48 +01:00
|
|
|
uint64_t delta;
|
|
|
|
#endif
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
switch (priv->model)
|
|
|
|
{
|
|
|
|
case MS56XX_MODEL_MS5607:
|
|
|
|
off = ((int64_t) c->c2 << 17) + ((int64_t) (c->c4 * dt) >> 6);
|
|
|
|
sens = ((int64_t) c->c1 << 16) + ((int64_t) (c->c3 * dt) >> 7);
|
2023-11-28 06:46:48 +01:00
|
|
|
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
|
2023-12-20 03:11:55 +01:00
|
|
|
if (*temp < 2000)
|
2023-11-28 06:46:48 +01:00
|
|
|
{
|
|
|
|
/* Low temperature */
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
t2 = ((dt * dt) >> 31);
|
|
|
|
delta = *temp - 2000;
|
2023-11-28 06:46:48 +01:00
|
|
|
delta *= delta;
|
|
|
|
off2 = (61 * delta) >> 4;
|
|
|
|
sens2 = 2 * delta;
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
if (*temp < -1500)
|
2023-11-28 06:46:48 +01:00
|
|
|
{
|
|
|
|
/* Very low temperature */
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
delta = *temp + 1500;
|
2023-11-28 06:46:48 +01:00
|
|
|
delta *= delta;
|
|
|
|
off2 += 15 * delta;
|
|
|
|
sens2 += 8 * delta;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2023-11-28 02:06:04 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case MS56XX_MODEL_MS5611:
|
|
|
|
off = ((int64_t) c->c2 << 16) + ((int64_t) (c->c4 * dt) >> 7);
|
|
|
|
sens = ((int64_t) c->c1 << 15) + ((int64_t) (c->c3 * dt) >> 8);
|
2023-11-28 06:46:48 +01:00
|
|
|
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
|
2023-12-20 03:11:55 +01:00
|
|
|
if (*temp < 2000)
|
2023-11-28 06:46:48 +01:00
|
|
|
{
|
|
|
|
/* Low temperature */
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
t2 = ((dt * dt) >> 31);
|
|
|
|
delta = *temp - 2000;
|
2023-11-28 06:46:48 +01:00
|
|
|
delta *= delta;
|
|
|
|
off2 = (5 * delta) >> 1;
|
|
|
|
sens2 = (5 * delta) >> 2;
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
if (*temp < -1500)
|
2023-11-28 06:46:48 +01:00
|
|
|
{
|
|
|
|
/* Very low temperature */
|
|
|
|
|
2023-12-20 03:11:55 +01:00
|
|
|
delta = *temp + 1500;
|
2023-11-28 06:46:48 +01:00
|
|
|
delta *= delta;
|
|
|
|
off2 += 7 * delta;
|
|
|
|
sens2 += (11 * delta) >> 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2023-11-28 02:06:04 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2023-11-28 06:46:48 +01:00
|
|
|
#if defined(CONFIG_MS56XX_SECOND_ORDER_COMPENSATE)
|
2023-12-20 03:11:55 +01:00
|
|
|
*temp -= t2;
|
2023-11-28 06:46:48 +01:00
|
|
|
off -= off2;
|
|
|
|
sens -= sens2;
|
|
|
|
#endif
|
2023-11-28 02:06:04 +01:00
|
|
|
press = (((press * sens) >> 21) - off) >> 15;
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
return press;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_set_interval
|
2022-01-22 17:47:49 +01:00
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_set_interval(FAR struct sensor_lowerhalf_s *lower,
|
2022-04-14 05:58:35 +02:00
|
|
|
FAR struct file *filep,
|
2024-09-19 11:27:18 +02:00
|
|
|
FAR uint32_t *period_us)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
FAR struct ms56xx_dev_s *priv = container_of(lower,
|
|
|
|
FAR struct ms56xx_dev_s,
|
2022-01-22 17:47:49 +01:00
|
|
|
sensor_lower);
|
|
|
|
|
|
|
|
priv->interval = *period_us;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_activate
|
2022-01-22 17:47:49 +01:00
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_activate(FAR struct sensor_lowerhalf_s *lower,
|
2022-04-14 05:58:35 +02:00
|
|
|
FAR struct file *filep, bool enable)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
|
|
|
bool start_thread = false;
|
2023-11-28 02:06:04 +01:00
|
|
|
struct ms56xx_dev_s *priv = (FAR struct ms56xx_dev_s *)lower;
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
if (enable)
|
|
|
|
{
|
|
|
|
if (!priv->enabled)
|
|
|
|
{
|
|
|
|
start_thread = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->enabled = enable;
|
|
|
|
|
|
|
|
if (start_thread)
|
|
|
|
{
|
|
|
|
/* Wake up the thread */
|
|
|
|
|
|
|
|
nxsem_post(&priv->run);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_fetch
|
2022-01-22 17:47:49 +01:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/* N.B. When fetch is enabled the sensortest doesn't respect the
|
|
|
|
* interval (-i) parameter, so let keep it comment until further
|
|
|
|
* discussion about the "issue".
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if 0
|
2023-11-28 02:06:04 +01:00
|
|
|
static int ms56xx_fetch(FAR struct sensor_lowerhalf_s *lower,
|
2022-01-22 17:47:49 +01:00
|
|
|
FAR char *buffer, size_t buflen)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
FAR struct ms56xx_dev_s *priv = container_of(lower,
|
|
|
|
FAR struct ms56xx_dev_s,
|
2022-01-22 17:47:49 +01:00
|
|
|
sensor_lower);
|
2022-03-25 11:10:24 +01:00
|
|
|
struct sensor_baro baro_data;
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
if (buflen != sizeof(baro_data))
|
|
|
|
{
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
baro_measure_read(priv, &baro_data);
|
|
|
|
|
|
|
|
memcpy(buffer, &baro_data, sizeof(baro_data));
|
|
|
|
|
|
|
|
return buflen;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
2023-11-28 02:06:04 +01:00
|
|
|
* Name: ms56xx_register
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Description:
|
2023-11-28 02:06:04 +01:00
|
|
|
* Register the MS56XX character device
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Input Parameters:
|
|
|
|
* i2c - An instance of the I2C interface to use to communicate with
|
2023-11-28 02:06:04 +01:00
|
|
|
* MS56XX
|
2022-01-22 17:47:49 +01:00
|
|
|
* devno - Instance number for driver
|
2023-11-28 02:06:04 +01:00
|
|
|
* addr - The I2C address of the MS56XX.
|
|
|
|
* model - The MS56XX model.
|
2022-01-22 17:47:49 +01:00
|
|
|
*
|
|
|
|
* Returned Value:
|
|
|
|
* Zero (OK) on success; a negated errno value on failure.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
int ms56xx_register(FAR struct i2c_master_s *i2c, int devno, uint8_t addr,
|
|
|
|
enum ms56xx_model_e model)
|
2022-01-22 17:47:49 +01:00
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
FAR struct ms56xx_dev_s *priv;
|
2022-01-22 17:47:49 +01:00
|
|
|
FAR char *argv[2];
|
|
|
|
char arg1[32];
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
/* Initialize the MS56XX device structure */
|
2022-01-22 17:47:49 +01:00
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
priv = kmm_zalloc(sizeof(struct ms56xx_dev_s));
|
2022-01-22 17:47:49 +01:00
|
|
|
if (priv == NULL)
|
|
|
|
{
|
|
|
|
snerr("Failed to allocate instance\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
priv->i2c = i2c;
|
|
|
|
priv->addr = addr;
|
2023-11-28 02:06:04 +01:00
|
|
|
priv->model = model;
|
|
|
|
priv->freq = CONFIG_MS56XX_I2C_FREQUENCY;
|
2022-01-22 17:47:49 +01:00
|
|
|
priv->interval = 1000000; /* Default interval 1s */
|
|
|
|
|
|
|
|
nxsem_init(&priv->run, 0, 0);
|
2022-09-06 08:18:45 +02:00
|
|
|
nxmutex_init(&priv->lock);
|
2022-01-22 17:47:49 +01:00
|
|
|
|
|
|
|
priv->sensor_lower.ops = &g_sensor_ops;
|
|
|
|
priv->sensor_lower.type = SENSOR_TYPE_BAROMETER;
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = ms56xx_initialize(priv);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
2023-11-28 02:06:04 +01:00
|
|
|
snerr("Failed to initialize physical device ms56xx:%d\n", ret);
|
2022-10-16 18:50:59 +02:00
|
|
|
nxmutex_destroy(&priv->lock);
|
2022-09-06 08:18:45 +02:00
|
|
|
nxsem_destroy(&priv->run);
|
2022-01-22 17:47:49 +01:00
|
|
|
kmm_free(priv);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register the character driver */
|
|
|
|
|
|
|
|
ret = sensor_register(&priv->sensor_lower, devno);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("Failed to register driver: %d\n", ret);
|
2022-10-16 18:50:59 +02:00
|
|
|
nxmutex_destroy(&priv->lock);
|
2022-09-06 08:18:45 +02:00
|
|
|
nxsem_destroy(&priv->run);
|
2022-01-22 17:47:49 +01:00
|
|
|
kmm_free(priv);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create thread for polling sensor data */
|
|
|
|
|
2023-07-25 14:08:53 +02:00
|
|
|
snprintf(arg1, 16, "%p", priv);
|
2022-01-22 17:47:49 +01:00
|
|
|
argv[0] = arg1;
|
|
|
|
argv[1] = NULL;
|
2023-11-28 02:06:04 +01:00
|
|
|
ret = kthread_create("ms56xx_thread", SCHED_PRIORITY_DEFAULT,
|
|
|
|
CONFIG_MS56XX_THREAD_STACKSIZE,
|
|
|
|
ms56xx_thread, argv);
|
2022-01-22 17:47:49 +01:00
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
snerr("Failed to create the notification kthread!\n");
|
|
|
|
sensor_unregister(&priv->sensor_lower, devno);
|
2022-10-16 18:50:59 +02:00
|
|
|
nxmutex_destroy(&priv->lock);
|
2022-09-06 08:18:45 +02:00
|
|
|
nxsem_destroy(&priv->run);
|
2022-01-22 17:47:49 +01:00
|
|
|
kmm_free(priv);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-11-28 02:06:04 +01:00
|
|
|
sninfo("MS56XX driver loaded successfully!\n");
|
2022-01-22 17:47:49 +01:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|