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.