You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by vi...@apache.org on 2018/04/10 18:27:38 UTC
[mynewt-core] branch master updated: add driver for ms5840 pressure
sensor (#998)
This is an automated email from the ASF dual-hosted git repository.
vipulrahane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push:
new cab7512 add driver for ms5840 pressure sensor (#998)
cab7512 is described below
commit cab75128b49a4768af0a6377017ef24be274fe1b
Author: matthewwarnes <36...@users.noreply.github.com>
AuthorDate: Tue Apr 10 19:27:35 2018 +0100
add driver for ms5840 pressure sensor (#998)
---
hw/drivers/sensors/ms5840/include/ms5840/ms5840.h | 172 ++++++
hw/drivers/sensors/ms5840/pkg.yml | 37 ++
hw/drivers/sensors/ms5840/src/ms5840.c | 690 ++++++++++++++++++++++
hw/drivers/sensors/ms5840/src/ms5840_priv.h | 113 ++++
hw/sensor/creator/pkg.yml | 2 +
hw/sensor/creator/src/sensor_creator.c | 59 ++
hw/sensor/creator/syscfg.yml | 3 +
7 files changed, 1076 insertions(+)
diff --git a/hw/drivers/sensors/ms5840/include/ms5840/ms5840.h b/hw/drivers/sensors/ms5840/include/ms5840/ms5840.h
new file mode 100644
index 0000000..97f45fc
--- /dev/null
+++ b/hw/drivers/sensors/ms5840/include/ms5840/ms5840.h
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+
+#ifndef __MS5840_H__
+#define __MS5840_H__
+
+#include <os/os.h>
+#include "os/os_dev.h"
+#include "sensor/sensor.h"
+
+#define MS5840_I2C_ADDRESS 0x76
+#define MS5840_NUMBER_COEFFS 7
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct ms5840_pdd {
+ uint16_t eeprom_coeff[MS5840_NUMBER_COEFFS + 1];
+};
+
+struct ms5840_cfg {
+ uint8_t mc_s_temp_res_osr;
+ uint8_t mc_s_press_res_osr;
+ sensor_type_t mc_s_mask;
+};
+
+struct ms5840 {
+ struct os_dev dev;
+ struct sensor sensor;
+ struct ms5840_cfg cfg;
+ struct ms5840_pdd pdd;
+ os_time_t last_read_time;
+};
+
+#define MS5840_RES_OSR_256 0x0
+#define MS5840_RES_OSR_512 0x2
+#define MS5840_RES_OSR_1024 0x4
+#define MS5840_RES_OSR_2048 0x6
+#define MS5840_RES_OSR_4096 0x8
+#define MS5840_RES_OSR_8192 0xA
+
+/**
+ * Initialize the ms5840.
+ *
+ * @param dev Pointer to the ms5840_dev device descriptor
+ *
+ * @return 0 on success, and non-zero error code on failure
+ */
+int
+ms5840_init(struct os_dev *dev, void *arg);
+
+/**
+ * Reads the temperature ADC value
+ *
+ * @param the sensor interface
+ * @param raw adc temperature value
+ * @param resolution osr
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_get_rawtemp(struct sensor_itf *itf, uint32_t *rawtemp,
+ uint8_t res_osr);
+
+/**
+ * Reads the pressure ADC value
+ *
+ * @param the sensor interface
+ * @param raw adc pressure value
+ * @param resolution osr
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_get_rawpress(struct sensor_itf *itf, uint32_t *rawpress,
+ uint8_t res_osr);
+
+/**
+ * Resets the MS5840 chip
+ *
+ * @param The sensor interface
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_reset(struct sensor_itf *itf);
+
+/**
+ * Configure MS5840 sensor
+ *
+ * @param Sensor device MS5840 structure
+ * @param Sensor device MS5840 config
+ *
+ * @return 0 on success, and non-zero error code on failure
+ */
+int
+ms5840_config(struct ms5840 *ms5840, struct ms5840_cfg *cfg);
+
+/**
+ * crc4 check for MS5840 EEPROM
+ *
+ * @param buffer containing EEPROM coefficients
+ * @param crc to compare with
+ *
+ * return 0 on success (CRC is OK), non-zero on failure
+ */
+int
+ms5840_crc_check(uint16_t *prom, uint8_t crc);
+
+/**
+ * Reads the ms5840 EEPROM coefficients for computation and
+ * does a CRC check on them
+ *
+ * @param the sensor interface
+ * @param buffer to fill up the coefficients
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_read_eeprom(struct sensor_itf *itf, uint16_t *coeff);
+
+/**
+ * Compensate for pressure using coefficients from the EEPROM
+ *
+ * @param ptr to coefficients
+ * @param first order compensated temperature
+ * @param raw pressure
+ * @param deltat temperature
+ *
+ * @return second order temperature compensated pressure
+ */
+float
+ms5840_compensate_pressure(uint16_t *coeffs, int32_t temp,
+ uint32_t rawpress, int32_t deltat);
+
+/**
+ * Compensate for temperature using coefficients from the EEPROM
+ *
+ * @param ptr to coefficients
+ * @param compensated temperature
+ * @param raw temperature
+ * @param optional ptr to fill up first order compensated temperature
+ * @param optional ptr to fill up delta temperature
+ *
+ * @return second order temperature compensated temperature
+ */
+float
+ms5840_compensate_temperature(uint16_t *coeffs, uint32_t rawtemp,
+ int32_t *comptemp, int32_t *deltat);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MS5840_H__ */
diff --git a/hw/drivers/sensors/ms5840/pkg.yml b/hw/drivers/sensors/ms5840/pkg.yml
new file mode 100644
index 0000000..c75b205
--- /dev/null
+++ b/hw/drivers/sensors/ms5840/pkg.yml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+pkg.name: hw/drivers/sensors/ms5840
+pkg.description: Driver for the MS5840 pressure sensor
+pkg.author: "Vipul Rahane <vi...@runtime.io>"
+pkg.homepage: "http://www.runtime.io/"
+pkg.keywords:
+ - TE connectivity
+ - ms5840
+ - i2c
+ - sensor
+
+pkg.deps:
+ - "@apache-mynewt-core/kernel/os"
+ - "@apache-mynewt-core/hw/hal"
+ - "@apache-mynewt-core/hw/sensor"
+
+pkg.req_apis:
+ - stats
+ - log
diff --git a/hw/drivers/sensors/ms5840/src/ms5840.c b/hw/drivers/sensors/ms5840/src/ms5840.c
new file mode 100644
index 0000000..3205d35
--- /dev/null
+++ b/hw/drivers/sensors/ms5840/src/ms5840.c
@@ -0,0 +1,690 @@
+/*
+ * 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "defs/error.h"
+#include "os/os.h"
+#include "sysinit/sysinit.h"
+#include "hal/hal_i2c.h"
+#include "sensor/sensor.h"
+#include "ms5840/ms5840.h"
+#include "sensor/temperature.h"
+#include "sensor/pressure.h"
+#include "ms5840_priv.h"
+#include "os/os_cputime.h"
+#include "console/console.h"
+#include "log/log.h"
+#include "stats/stats.h"
+
+static uint16_t cnv_time[6] = {
+ MS5840_CNV_TIME_OSR_256,
+ MS5840_CNV_TIME_OSR_512,
+ MS5840_CNV_TIME_OSR_1024,
+ MS5840_CNV_TIME_OSR_2048,
+ MS5840_CNV_TIME_OSR_4096,
+ MS5840_CNV_TIME_OSR_8192
+};
+
+/* Define the stats section and records */
+STATS_SECT_START(ms5840_stat_section)
+ STATS_SECT_ENTRY(read_errors)
+ STATS_SECT_ENTRY(write_errors)
+ STATS_SECT_ENTRY(eeprom_crc_errors)
+STATS_SECT_END
+
+/* Define stat names for querying */
+STATS_NAME_START(ms5840_stat_section)
+ STATS_NAME(ms5840_stat_section, read_errors)
+ STATS_NAME(ms5840_stat_section, write_errors)
+ STATS_NAME(ms5840_stat_section, eeprom_crc_errors)
+STATS_NAME_END(ms5840_stat_section)
+
+/* Global variable used to hold stats data */
+STATS_SECT_DECL(ms5840_stat_section) g_ms5840stats;
+
+#define LOG_MODULE_MS5840 (5840)
+#define MS5840_INFO(...) LOG_INFO(&_log, LOG_MODULE_MS5840, __VA_ARGS__)
+#define MS5840_ERR(...) LOG_ERROR(&_log, LOG_MODULE_MS5840, __VA_ARGS__)
+static struct log _log;
+
+/* Exports for the sensor API */
+static int ms5840_sensor_read(struct sensor *, sensor_type_t,
+ sensor_data_func_t, void *, uint32_t);
+static int ms5840_sensor_get_config(struct sensor *, sensor_type_t,
+ struct sensor_cfg *);
+static int ms5840_sensor_set_config(struct sensor *, void *);
+
+static const struct sensor_driver g_ms5840_sensor_driver = {
+ .sd_read = ms5840_sensor_read,
+ .sd_get_config = ms5840_sensor_get_config,
+ .sd_set_config = ms5840_sensor_set_config,
+};
+
+/**
+ * Expects to be called back through os_dev_create().
+ *
+ * @param The device object associated with ms5840
+ * @param Argument passed to OS device init, unused
+ *
+ * @return 0 on success, non-zero error on failure.
+ */
+int
+ms5840_init(struct os_dev *dev, void *arg)
+{
+ struct ms5840 *ms5840;
+ struct sensor *sensor;
+ struct sensor_itf *itf;
+ int rc;
+
+ if (!arg || !dev) {
+ rc = SYS_ENODEV;
+ goto err;
+ }
+
+ ms5840 = (struct ms5840 *)dev;
+
+ log_register(dev->od_name, &_log, &log_console_handler, NULL, LOG_SYSLEVEL);
+
+ sensor = &ms5840->sensor;
+
+ itf = SENSOR_GET_ITF(sensor);
+
+ /* Initialise the stats entry */
+ rc = stats_init(
+ STATS_HDR(g_ms5840stats),
+ STATS_SIZE_INIT_PARMS(g_ms5840stats, STATS_SIZE_32),
+ STATS_NAME_INIT_PARMS(ms5840_stat_section));
+ SYSINIT_PANIC_ASSERT(rc == 0);
+ /* Register the entry with the stats registry */
+ rc = stats_register(dev->od_name, STATS_HDR(g_ms5840stats));
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ rc = sensor_init(sensor, dev);
+ if (rc != 0) {
+ goto err;
+ }
+
+ /* Add the driver with all the supported type */
+ rc = sensor_set_driver(sensor, SENSOR_TYPE_AMBIENT_TEMPERATURE |
+ SENSOR_TYPE_PRESSURE,
+ (struct sensor_driver *)&g_ms5840_sensor_driver);
+ if (rc) {
+ goto err;
+ }
+
+ /* Set the interface */
+ rc = sensor_set_interface(sensor, arg);
+ if (rc) {
+ goto err;
+ }
+
+ rc = sensor_mgr_register(sensor);
+ if (rc) {
+ goto err;
+ }
+
+ rc = ms5840_read_eeprom(itf, ms5840->pdd.eeprom_coeff);
+ if (rc) {
+ goto err;
+ }
+
+ return 0;
+err:
+ return rc;
+
+}
+
+static int
+ms5840_sensor_read(struct sensor *sensor, sensor_type_t type,
+ sensor_data_func_t data_func, void *data_arg, uint32_t timeout)
+{
+ uint32_t rawtemp;
+ uint32_t rawpress;
+ int32_t comptemp;
+ int32_t deltat;
+ float temperature;
+ float pressure;
+ struct sensor_itf *itf;
+ struct ms5840 *ms5840;
+ struct ms5840_cfg *cfg;
+
+ int rc;
+ union {
+ struct sensor_temp_data std;
+ struct sensor_press_data spd;
+ } databuf;
+
+ if (!(type & SENSOR_TYPE_PRESSURE) &&
+ !(type & SENSOR_TYPE_AMBIENT_TEMPERATURE)) {
+ rc = SYS_EINVAL;
+ goto err;
+ }
+
+ itf = SENSOR_GET_ITF(sensor);
+
+ ms5840 = (struct ms5840 *)SENSOR_GET_DEVICE(sensor);
+
+ cfg = &(ms5840->cfg);
+
+ temperature = pressure = 0;
+
+ /* Get a new pressure sample */
+ if (type & SENSOR_TYPE_PRESSURE) {
+ rc = ms5840_get_rawtemp(itf, &rawtemp, cfg->mc_s_temp_res_osr);
+ if (rc) {
+ goto err;
+ }
+
+ rc = ms5840_get_rawpress(itf, &rawpress, cfg->mc_s_press_res_osr);
+ if (rc) {
+ goto err;
+ }
+
+ /* compensate using temperature and pressure coefficients
+ * competemp is the first order compensated temperature
+ * which is used as input to the pressure compensation
+ */
+ temperature = ms5840_compensate_temperature(ms5840->pdd.eeprom_coeff, rawtemp,
+ &comptemp, &deltat);
+ pressure = ms5840_compensate_pressure(ms5840->pdd.eeprom_coeff, comptemp,
+ rawpress, deltat);
+
+ databuf.spd.spd_press = pressure;
+ databuf.spd.spd_press_is_valid = 1;
+
+ /* Call data function */
+ rc = data_func(sensor, data_arg, &databuf.spd, SENSOR_TYPE_PRESSURE);
+ if (rc) {
+ goto err;
+ }
+ }
+
+ /* Get a new temperature sample */
+ if (type & SENSOR_TYPE_AMBIENT_TEMPERATURE) {
+ if (!temperature) {
+ rc = ms5840_get_rawtemp(itf, &rawtemp, cfg->mc_s_temp_res_osr);
+ if (rc) {
+ goto err;
+ }
+
+ temperature = ms5840_compensate_temperature(ms5840->pdd.eeprom_coeff, rawtemp,
+ NULL, NULL);
+ }
+
+ databuf.std.std_temp = temperature;
+ databuf.std.std_temp_is_valid = 1;
+
+ /* Call data function */
+ rc = data_func(sensor, data_arg, &databuf.std,
+ SENSOR_TYPE_AMBIENT_TEMPERATURE);
+ if (rc) {
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ return rc;
+}
+
+static int
+ms5840_sensor_get_config(struct sensor *sensor, sensor_type_t type,
+ struct sensor_cfg *cfg)
+{
+ int rc;
+
+ if (!(type & SENSOR_TYPE_PRESSURE) ||
+ !(type & SENSOR_TYPE_AMBIENT_TEMPERATURE)) {
+ rc = SYS_EINVAL;
+ goto err;
+ }
+
+ cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT;
+
+ return (0);
+err:
+ return (rc);
+}
+
+static int
+ms5840_sensor_set_config(struct sensor *sensor, void *cfg)
+{
+ struct ms5840* ms5840 = (struct ms5840 *)SENSOR_GET_DEVICE(sensor);
+
+ return ms5840_config(ms5840, (struct ms5840_cfg*)cfg);
+}
+
+/**
+ * Configure MS5840 sensor
+ *
+ * @param Sensor device MS5840 structure
+ * @param Sensor device MS5840 config
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_config(struct ms5840 *ms5840, struct ms5840_cfg *cfg)
+{
+ int rc;
+ struct sensor_itf *itf;
+
+ itf = SENSOR_GET_ITF(&(ms5840->sensor));
+
+ rc = ms5840_reset(itf);
+ if (rc) {
+ goto err;
+ }
+
+ rc = sensor_set_type_mask(&(ms5840->sensor), cfg->mc_s_mask);
+ if (rc) {
+ goto err;
+ }
+
+ ms5840->cfg.mc_s_temp_res_osr = cfg->mc_s_temp_res_osr;
+
+ ms5840->cfg.mc_s_press_res_osr = cfg->mc_s_press_res_osr;
+
+ ms5840->cfg.mc_s_mask = cfg->mc_s_mask;
+
+ return 0;
+err:
+ return (rc);
+}
+
+/**
+ * Write multiple length data to MS5840 sensor over I2C
+ *
+ * @param The sensor interface
+ * @param register address
+ * @param variable length payload
+ * @param length of the payload to write
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *buffer,
+ uint8_t len)
+{
+ int rc;
+
+ struct hal_i2c_master_data data_struct = {
+ .address = itf->si_addr,
+ .len = 1,
+ .buffer = &addr
+ };
+
+ /* Register write */
+ rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1);
+ if (rc) {
+ MS5840_ERR("I2C write command write failed at address 0x%02X\n",
+ data_struct.address);
+ STATS_INC(g_ms5840stats, write_errors);
+ goto err;
+ }
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Read multiple length data from MS5840 sensor over I2C
+ *
+ * @param The sensor interface
+ * @param register address
+ * @param variable length buffer
+ * @param length of the payload to read
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *buffer,
+ uint8_t len)
+{
+ int rc;
+ uint8_t payload[3] = {addr, 0, 0};
+
+ struct hal_i2c_master_data data_struct = {
+ .address = itf->si_addr,
+ .len = 1,
+ .buffer = payload
+ };
+
+ /* Clear the supplied buffer */
+ memset(buffer, 0, len);
+
+ /* Command write */
+ rc = hal_i2c_master_write(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1);
+ if (rc) {
+ MS5840_ERR("I2C read command write failed at address 0x%02X\n",
+ data_struct.address);
+ STATS_INC(g_ms5840stats, write_errors);
+ goto err;
+ }
+
+ /* Read len bytes back */
+ memset(payload, 0, sizeof(payload));
+ data_struct.len = len;
+ rc = hal_i2c_master_read(itf->si_num, &data_struct, OS_TICKS_PER_SEC / 10, 1);
+ if (rc) {
+ MS5840_ERR("Failed to read from 0x%02X:0x%02X\n", data_struct.address, addr);
+ STATS_INC(g_ms5840stats, read_errors);
+ goto err;
+ }
+
+ /* Copy the I2C results into the supplied buffer */
+ memcpy(buffer, payload, len);
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Reads the ms5840 EEPROM coefficients for computation and
+ * does a CRC check on them
+ *
+ * @param the sensor interface
+ * @param buffer to fill up the coefficients
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_read_eeprom(struct sensor_itf *itf, uint16_t *coeff)
+{
+ int idx;
+ int rc;
+ uint16_t payload[MS5840_NUMBER_COEFFS];
+
+ for(idx = 0; idx < MS5840_NUMBER_COEFFS; idx++) {
+ rc = ms5840_readlen(itf, MS5840_CMD_PROM_READ_ADDR0 + idx * 2,
+ (uint8_t *)(payload + idx), 2);
+ if (rc) {
+ goto err;
+ }
+
+ payload[idx] = (((payload[idx] & 0xFF00) >> 8)|
+ ((payload[idx] & 0x00FF) << 8));
+ }
+
+ rc = ms5840_crc_check(payload, (payload[MS5840_IDX_CRC] & 0xF000) >> 12);
+ if (rc) {
+ rc = SYS_EINVAL;
+ MS5840_ERR("Failure in CRC, 0x%02X\n",
+ payload[MS5840_IDX_CRC] & 0xF000 >> 12);
+ STATS_INC(g_ms5840stats, eeprom_crc_errors);
+ goto err;
+ }
+
+ memcpy(coeff, payload, sizeof(payload));
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Compensate for pressure using coefficients from the EEPROM
+ *
+ * @param ptr to coefficients
+ * @param first order compensated temperature
+ * @param raw pressure
+ * @param deltat temperature
+ *
+ * @return second order temperature compensated pressure
+ */
+float
+ms5840_compensate_pressure(uint16_t *coeffs, int32_t temp,
+ uint32_t rawpress, int32_t deltat)
+{
+ int64_t off, sens, off2, sens2;
+
+ off2 = sens2 = 0;
+
+ /* off = off_T1 + TCO * dt */
+ off = ((int64_t)(coeffs[MS5840_IDX_PRESS_OFF]) << 17) +
+ (((int64_t)(coeffs[MS5840_IDX_TEMP_COEFF_PRESS_OFF]) * deltat) >> 6);
+
+ /* sensitivity at actual temperature = sens_T1 + TCS * dt */
+ sens = ((int64_t)coeffs[MS5840_IDX_PRESS_SENS] << 16) +
+ (((int64_t)coeffs[MS5840_IDX_TEMP_COEFF_PRESS_SENS] * deltat) >> 7);
+
+ /* second order temperature compensation */
+ if(temp < 1000) {
+ /* low temperature */
+ off2 = (35 * ((int64_t)temp - 2000) * ((int64_t)temp - 2000)) >> 3;
+ sens2 = (63 * ((int64_t)temp - 2000) * ((int64_t)temp - 2000)) >> 5;
+ } else if (temp < 2000) {
+ off2 = (30 * ((int64_t)temp - 2000) * ((int64_t)temp - 2000)) >> 8;
+ }
+
+ off2 = off - off2;
+
+ sens2 = sens - sens2;
+
+ /* temperature compensated second order pressure = D1 * sens - off */
+ return ((float)(((rawpress * sens2) >> 21) - off2)/32768);
+}
+
+/**
+ * Compensate for temperature using coefficients from the EEPROM
+ *
+ * @param ptr to coefficients
+ * @param compensated temperature
+ * @param raw temperature
+ * @param optional ptr to fill up first order compensated temperature
+ * @param optional ptr to fill up delta temperature
+ *
+ * @return second order temperature compensated temperature
+ */
+float
+ms5840_compensate_temperature(uint16_t *coeffs, uint32_t rawtemp,
+ int32_t *comptemp, int32_t *deltat)
+{
+ int32_t dt, temp;
+ int64_t t2;
+
+ t2 = 0;
+
+ /* difference between actual and reference temperature = D2 - Tref */
+ dt = (int32_t)rawtemp - ((int32_t)coeffs[MS5840_IDX_REF_TEMP] << 8);
+
+ /* actual temperature = 2000 + dt * tempsens */
+ temp = 2000 + ((int64_t)((int64_t)dt * (int64_t)coeffs[MS5840_IDX_TEMP_COEFF_TEMP]) >> 23);
+
+ if (comptemp) {
+ *comptemp = temp;
+ }
+
+ if (deltat) {
+ *deltat = dt;
+ }
+
+ if(temp < 1000) {
+ /* low temperature */
+ t2 = (11 * (int64_t)dt * (int64_t)dt) >> 35;
+ }
+
+ /* second order temperature */
+ return (((float)temp - t2)/100);
+}
+
+/**
+ * Triggers conversion and reads ADC value
+ *
+ * @param the sensor interface
+ * @param cmd used for conversion, considers temperature, pressure and OSR
+ * @param ptr to ADC value
+ *
+ * @return 0 on success, non-zero on failure
+ */
+static int
+ms5840_get_raw_data(struct sensor_itf *itf, uint8_t cmd, uint32_t *data)
+{
+ int rc;
+ uint8_t payload[3] = {0};
+
+ /* send conversion command based on OSR, temperature and pressure */
+ rc = ms5840_writelen(itf, cmd, payload, 0);
+ if (rc) {
+ goto err;
+ }
+
+ /* delay conversion depending on resolution */
+ os_cputime_delay_usecs(cnv_time[(cmd & MS5840_CNV_OSR_MASK)/2]);
+
+ /* read adc value */
+ rc = ms5840_readlen(itf, MS5840_CMD_ADC_READ, payload, 3);
+ if (rc) {
+ goto err;
+ }
+
+ *data = ((uint32_t)payload[0] << 16) | ((uint32_t)payload[1] << 8) | payload[2];
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Reads the temperature ADC value
+ *
+ * @param the sensor interface
+ * @param raw adc temperature value
+ * @param resolution osr
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_get_rawtemp(struct sensor_itf *itf, uint32_t *rawtemp,
+ uint8_t res_osr)
+{
+ uint8_t cmd;
+ uint32_t tmp;
+ int rc;
+
+ /* read temperature ADC value */
+ cmd = res_osr | MS5840_CMD_TEMP;
+ rc = ms5840_get_raw_data(itf, cmd, &tmp);
+ if (rc) {
+ goto err;
+ }
+
+ *rawtemp = tmp;
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Reads the pressure ADC value
+ *
+ * @param the sensor interface
+ * @param raw adc pressure value
+ * @param resolution osr
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_get_rawpress(struct sensor_itf *itf, uint32_t *rawpress,
+ uint8_t res_osr)
+{
+ uint8_t cmd;
+ uint32_t tmp;
+ int rc;
+
+ /* read pressure ADC value */
+ cmd = res_osr | MS5840_CMD_PRESS;
+ rc = ms5840_get_raw_data(itf, cmd, &tmp);
+ if (rc) {
+ goto err;
+ }
+
+ *rawpress = tmp;
+
+ return 0;
+err:
+ return rc;
+}
+
+/**
+ * Resets the MS5840 chip
+ *
+ * @param the sensor interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+ms5840_reset(struct sensor_itf *itf)
+{
+ uint8_t txdata;
+
+ txdata = 0;
+
+ return ms5840_writelen(itf, MS5840_CMD_RESET, &txdata, 0);
+}
+
+/**
+ * crc4 check for MS5840 EEPROM
+ *
+ * @param buffer containing EEPROM coefficients
+ * @param crc to compare with
+ *
+ * return 0 on success (CRC is OK), non-zero on failure
+ */
+int
+ms5840_crc_check(uint16_t *prom, uint8_t crc)
+{
+ uint8_t cnt, bit;
+ uint16_t rem, crc_read;
+
+ rem = 0x00;
+ crc_read = prom[0];
+ prom[MS5840_NUMBER_COEFFS] = 0;
+
+ /* Clear the CRC byte */
+ prom[0] = (0x0FFF & prom[0]);
+
+ for(cnt = 0; cnt < (MS5840_NUMBER_COEFFS + 1) * 2; cnt++) {
+ /* Get next byte */
+ if (cnt%2 == 1) {
+ rem ^= (prom[cnt>>1] & 0x00FF);
+ } else {
+ rem ^= (prom[cnt>>1] >> 8);
+ }
+
+ for(bit = 8; bit > 0; bit--) {
+ if(rem & 0x8000) {
+ rem = (rem << 1) ^ 0x3000;
+ } else {
+ rem <<= 1;
+ }
+ }
+ }
+
+ rem >>= 12;
+ prom[0] = crc_read;
+
+ return (rem != crc);
+}
diff --git a/hw/drivers/sensors/ms5840/src/ms5840_priv.h b/hw/drivers/sensors/ms5840/src/ms5840_priv.h
new file mode 100644
index 0000000..dfd33a8
--- /dev/null
+++ b/hw/drivers/sensors/ms5840/src/ms5840_priv.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#ifndef __MS5840_PRIV_H__
+#define __MS5840_PRIV_H__
+
+/* Commands */
+#define MS5840_CMD_RESET 0x1E
+/* Max conversion time: 0.56 ms ; 0.11 mbar RMS resolution */
+#define MS5840_CMD_D1_256 MS5840_CMD_PRESS|MS5840_RES_OSR_256
+/* Max conversion time: 1.10 ms : 0.062 mbar RMS resolution */
+#define MS5840_CMD_D1_512 MS5840_CMD_PRESS|MS5840_RES_OSR_512
+/* Max conversion time: 2.17 ms : 0.039 mbar RMS resolution */
+#define MS5840_CMD_D1_1024 MS5840_CMD_PRESS|MS5840_RES_OSR_1024
+/* Max conversion time: 4.32 ms ; 0.028 mbar RMS resolution */
+#define MS5840_CMD_D1_2048 MS5840_CMD_PRESS|MS5840_RES_OSR_2048
+/* Max conversion time: 8.61 ms : 0.021 mbar RMS resolution */
+#define MS5840_CMD_D1_4096 MS5840_CMD_PRESS|MS5840_RES_OSR_4096
+/* Max conversion time: 17.2 ms : 0.016 mbar RMS resolution */
+#define MS5840_CMD_D1_8192 MS5840_CMD_PRESS|MS5840_RES_OSR_8192
+/* Max conversion time: 0.56 ms : 0.012 °C RMS resolution */
+#define MS5840_CMD_D2_256 MS5840_CMD_TEMP|MS5840_RES_OSR_256
+/* Max conversion time: 1.10 ms : 0.009 °C RMS resolution */
+#define MS5840_CMD_D2_512 MS5840_CMD_TEMP|MS5840_RES_OSR_512
+/* Max conversion time: 2.17 ms : 0.006 °C RMS resolution */
+#define MS5840_CMD_D2_1024 MS5840_CMD_TEMP|MS5840_RES_OSR_1024
+/* Max conversion time: 4.32 ms ; 0.004 °C RMS resolution */
+#define MS5840_CMD_D2_2048 MS5840_CMD_TEMP|MS5840_RES_OSR_2048
+/* Max conversion time: 8.61 ms : 0.003 °C RMS resolution */
+#define MS5840_CMD_D2_4096 MS5840_CMD_TEMP|MS5840_RES_OSR_4096
+/* Max conversion time: 17.2 ms : 0.002 °C RMS resolution */
+#define MS5840_CMD_D2_8192 MS5840_CMD_TEMP|MS5840_RES_OSR_8192
+
+#define MS5840_CMD_ADC_READ 0x00
+#define MS5840_CMD_PRESS 0x40
+#define MS5840_CMD_TEMP 0x50
+#define MS5840_CMD_PROM_READ 0xA0
+
+/* PROM Address commands */
+#define MS5840_CMD_PROM_READ_ADDR0 0xA0
+#define MS5840_CMD_PROM_READ_ADDR1 0xA2
+#define MS5840_CMD_PROM_READ_ADDR2 0xA4
+#define MS5840_CMD_PROM_READ_ADDR3 0xA6
+#define MS5840_CMD_PROM_READ_ADDR4 0xA8
+#define MS5840_CMD_PROM_READ_ADDR5 0xAA
+#define MS5840_CMD_PROM_READ_ADDR6 0xAC
+#define MS5840_CMD_PROM_READ_ADDR7 0xAE
+
+/* Conversion time in micro seconds */
+#define MS5840_CNV_TIME_OSR_256 560
+#define MS5840_CNV_TIME_OSR_512 1100
+#define MS5840_CNV_TIME_OSR_1024 2170
+#define MS5840_CNV_TIME_OSR_2048 4320
+#define MS5840_CNV_TIME_OSR_4096 8610
+#define MS5840_CNV_TIME_OSR_8192 17200
+
+/* Coefficient EEPROM indexes for temperature and pressure compensation */
+#define MS5840_IDX_CRC 0
+#define MS5840_IDX_PRESS_SENS 1
+#define MS5840_IDX_PRESS_OFF 2
+#define MS5840_IDX_TEMP_COEFF_PRESS_SENS 3
+#define MS5840_IDX_TEMP_COEFF_PRESS_OFF 4
+#define MS5840_IDX_REF_TEMP 5
+#define MS5840_IDX_TEMP_COEFF_TEMP 6
+#define MS5840_NUMBER_COEFFS 7
+
+#define MS5840_CNV_OSR_MASK 0x0F
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Write multiple length data to MS5840 sensor over I2C
+ *
+ * @param The sensor interface
+ * @param register address
+ * @param variable length payload
+ * @param length of the payload to write
+ */
+int ms5840_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload, uint8_t len);
+
+/**
+ * Read multiple length data from MS5840 sensor over I2C
+ *
+ * @param The sensor interface
+ * @param register address
+ * @param variable length payload
+ * @param length of the payload to read
+ */
+int ms5840_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload, uint8_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MS5840_PRIV_H_ */
diff --git a/hw/sensor/creator/pkg.yml b/hw/sensor/creator/pkg.yml
index 3039501..1c6a2ec 100644
--- a/hw/sensor/creator/pkg.yml
+++ b/hw/sensor/creator/pkg.yml
@@ -40,6 +40,8 @@ pkg.deps.TCS34725_OFB:
- hw/drivers/sensors/tcs34725
pkg.deps.MS5837_OFB:
- hw/drivers/sensors/ms5837
+pkg.deps.MS5840_OFB:
+ - hw/drivers/sensors/ms5840
pkg.deps.MCU_NATIVE:
- hw/drivers/sensors/sim
pkg.deps.BMP280_OFB:
diff --git a/hw/sensor/creator/src/sensor_creator.c b/hw/sensor/creator/src/sensor_creator.c
index 7a5ed79..3c7b0f3 100644
--- a/hw/sensor/creator/src/sensor_creator.c
+++ b/hw/sensor/creator/src/sensor_creator.c
@@ -48,6 +48,10 @@
#include <ms5837/ms5837.h>
#endif
+#if MYNEWT_VAL(MS5840_OFB)
+#include <ms5840/ms5840.h>
+#endif
+
#if MYNEWT_VAL(BMP280_OFB)
#include <bmp280/bmp280.h>
#endif
@@ -102,6 +106,10 @@ static struct bme280 bme280;
static struct ms5837 ms5837;
#endif
+#if MYNEWT_VAL(MS5840_OFB)
+static struct ms5840 ms5840;
+#endif
+
#if MYNEWT_VAL(BMP280_OFB)
static struct bmp280 bmp280;
#endif
@@ -218,6 +226,16 @@ static struct sensor_itf i2c_0_itf_ms = {
};
#endif
+#if MYNEWT_VAL(I2C_0) && MYNEWT_VAL(MS5840_OFB)
+static struct sensor_itf i2c_0_itf_ms = {
+ .si_type = SENSOR_ITF_I2C,
+ .si_num = 0,
+ /* HW I2C address for the MS5840 */
+ .si_addr = 0x76
+};
+#endif
+
+
#if MYNEWT_VAL(I2C_0) && MYNEWT_VAL(BMA253_OFB)
static struct sensor_itf i2c_0_itf_lis = {
.si_type = SENSOR_ITF_I2C,
@@ -293,6 +311,38 @@ config_ms5837_sensor(void)
}
#endif
+/**
+ * MS5840 Sensor default configuration used by the creator package
+ *
+ * @return 0 on success, non-zero on failure
+ */
+#if MYNEWT_VAL(MS5840_OFB)
+static int
+config_ms5840_sensor(void)
+{
+ int rc;
+ struct os_dev *dev;
+ struct ms5840_cfg mscfg;
+
+ dev = (struct os_dev *) os_dev_open("ms5840_0", OS_TIMEOUT_NEVER, NULL);
+ assert(dev != NULL);
+
+ memset(&mscfg, 0, sizeof(mscfg));
+
+
+ mscfg.mc_s_temp_res_osr = MS5840_RES_OSR_256;
+ mscfg.mc_s_press_res_osr = MS5840_RES_OSR_256;
+ mscfg.mc_s_mask = SENSOR_TYPE_AMBIENT_TEMPERATURE|
+ SENSOR_TYPE_PRESSURE;
+
+ rc = ms5840_config((struct ms5840 *)dev, &mscfg);
+
+ os_dev_close(dev);
+ return rc;
+}
+#endif
+
+
/* Sensor default configuration used by the creator package */
/**
@@ -838,6 +888,15 @@ sensor_dev_create(void)
assert(rc == 0);
#endif
+#if MYNEWT_VAL(MS5840_OFB)
+ rc = os_dev_create((struct os_dev *) &ms5840, "ms5840_0",
+ OS_DEV_INIT_PRIMARY, 0, ms5840_init, (void *)&i2c_0_itf_ms);
+ assert(rc == 0);
+
+ rc = config_ms5840_sensor();
+ assert(rc == 0);
+#endif
+
#if MYNEWT_VAL(BMP280_OFB)
rc = os_dev_create((struct os_dev *) &bmp280, "bmp280_0",
OS_DEV_INIT_PRIMARY, 0, bmp280_init, (void *)&i2c_0_itf_bmp);
diff --git a/hw/sensor/creator/syscfg.yml b/hw/sensor/creator/syscfg.yml
index 1f76199..2d750c8 100644
--- a/hw/sensor/creator/syscfg.yml
+++ b/hw/sensor/creator/syscfg.yml
@@ -40,6 +40,9 @@ syscfg.defs:
MS5837_OFB:
description: 'MS5837 is present'
value : 0
+ MS5840_OFB:
+ description: 'MS5840 is present'
+ value : 0
BMP280_OFB:
description: 'BMP280 is present'
value : 0
--
To stop receiving notification emails like this one, please contact
vipulrahane@apache.org.