From dc6b42962790e60914bf21ae650cacf9b965c207 Mon Sep 17 00:00:00 2001 From: szune Date: Mon, 11 Nov 2019 12:27:36 +0000 Subject: [PATCH] Move other projects under "projects" repository. --- app/build.gradle | 33 + app/src/main/AndroidManifest.xml | 23 + .../odroid/weatherboard/MainActivity.java | 120 + app/src/main/jni/Android.mk | 15 + app/src/main/jni/bme280-i2c.c | 98 + app/src/main/jni/bme280-i2c.h | 16 + app/src/main/jni/bme280.c | 2215 +++++++++++++++++ app/src/main/jni/bme280.h | 1704 +++++++++++++ app/src/main/jni/si1132.c | 140 ++ app/src/main/jni/si1132.h | 92 + app/src/main/jni/weather.c | 81 + .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 7658 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 3777 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 12516 bytes .../main/res/drawable-xxhdpi/ic_launcher.png | Bin 0 -> 24777 bytes app/src/main/res/layout/activity_main.xml | 106 + app/src/main/res/menu/main.xml | 11 + app/src/main/res/values-v11/styles.xml | 11 + app/src/main/res/values-v14/styles.xml | 12 + app/src/main/res/values-w820dp/dimens.xml | 10 + app/src/main/res/values/dimens.xml | 7 + app/src/main/res/values/strings.xml | 22 + app/src/main/res/values/styles.xml | 20 + build.gradle | 17 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54329 bytes gradle/wrapper/gradle-wrapper.properties | 5 + gradlew | 172 ++ gradlew.bat | 84 + import-summary.txt | 43 + local.properties | 9 + settings.gradle | 1 + 31 files changed, 5067 insertions(+) create mode 100644 app/build.gradle create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/com/hardkernel/odroid/weatherboard/MainActivity.java create mode 100644 app/src/main/jni/Android.mk create mode 100644 app/src/main/jni/bme280-i2c.c create mode 100644 app/src/main/jni/bme280-i2c.h create mode 100644 app/src/main/jni/bme280.c create mode 100644 app/src/main/jni/bme280.h create mode 100644 app/src/main/jni/si1132.c create mode 100644 app/src/main/jni/si1132.h create mode 100644 app/src/main/jni/weather.c create mode 100644 app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/menu/main.xml create mode 100644 app/src/main/res/values-v11/styles.xml create mode 100644 app/src/main/res/values-v14/styles.xml create mode 100644 app/src/main/res/values-w820dp/dimens.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 import-summary.txt create mode 100644 local.properties create mode 100644 settings.gradle diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..864de8e --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 19 + buildToolsVersion "28.0.3" + + externalNativeBuild { + ndkBuild { + path "src/main/jni/Android.mk" + } + + cmake { + version "3.10.2" + } + } + + defaultConfig { + applicationId "com.hardkernel.odroid.weatherboard" + minSdkVersion 19 + targetSdkVersion 19 + + ndk { + moduleName "weather" + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c978025 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/hardkernel/odroid/weatherboard/MainActivity.java b/app/src/main/java/com/hardkernel/odroid/weatherboard/MainActivity.java new file mode 100644 index 0000000..c1aa986 --- /dev/null +++ b/app/src/main/java/com/hardkernel/odroid/weatherboard/MainActivity.java @@ -0,0 +1,120 @@ +package com.hardkernel.odroid.weatherboard; + +import android.app.Activity; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.widget.CompoundButton; +import android.widget.TextView; +import android.widget.ToggleButton; + +public class MainActivity extends Activity { + + private final static String TAG = "weather"; + private final static String I2C_1_NODE = "/dev/i2c-1"; + private boolean mStopWeather; + private ToggleButton mBtn_Weather; + private TextView mTV_Temperature; + private TextView mTV_Humidity; + private TextView mTV_Pressure; + private TextView mTV_Altitude; + private Handler handler = new Handler(); + Runnable mRunnableWeather = new Runnable() { + + @Override + public void run() { + // TODO Auto-generated method stub + updateWeather(); + } + }; + + private TextView mTV_UV_index; + private TextView mTV_Visible; + private TextView mTV_IR; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + mBtn_Weather = (ToggleButton) findViewById(R.id.tb_weather); + mBtn_Weather.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + // TODO Auto-generated method stub + if (isChecked) { + if (openWeatherBoard(I2C_1_NODE) == -1) { + Log.e(TAG, "failed"); + return; + } + mStopWeather = false; + handler.postDelayed(mRunnableWeather, 300); + } else { + mStopWeather = true; + closeWeatherBoard(); + mTV_Temperature.setText("Temperature :"); + mTV_Humidity.setText("Humidity :"); + mTV_Pressure.setText("Pressure :"); + mTV_Altitude.setText("Altitude :"); + mTV_UV_index.setText("UV index :"); + mTV_Visible.setText("Visible :"); + mTV_IR.setText("IR :"); + } + } + }); + + mTV_Temperature = (TextView) findViewById(R.id.tv_temperature); + mTV_Humidity = (TextView) findViewById(R.id.tv_humidity); + mTV_Pressure = (TextView) findViewById(R.id.tv_pressure); + mTV_Altitude = (TextView) findViewById(R.id.tv_altitude); + + mTV_UV_index = (TextView) findViewById(R.id.tv_uv_index); + mTV_Visible = (TextView) findViewById(R.id.tv_visible); + mTV_IR = (TextView) findViewById(R.id.tv_ir); + } + + @Override + protected void onPause() { + // TODO Auto-generated method stub + super.onPause(); + mBtn_Weather.setChecked(false); + } + + private void updateWeather() { + if (mStopWeather == true) + return; + mTV_UV_index.setText("UV index : " + + String.format("%.2f", (double)getUVindex() / 100.0)); + mTV_Visible.setText("Visible : " + + String.format("%.0f", (double)getVisible()) + " Lux"); + mTV_IR.setText("IR : " + + String.format("%.0f", (double)getIR()) + " Lux"); + readyData(); + mTV_Temperature.setText("Temperature : " + + String.format("%.2f", getTemperature() / 100.0) + " °C"); + mTV_Humidity.setText("Humidity : " + + String.format("%.2f", getHumidity() / 1024.0) + " %"); + mTV_Pressure.setText("Pressure : " + + String.format("%.2f", getPressure() / 100.0) + " hPa"); + mTV_Altitude.setText("Altitude : " + getAltitude() + " m"); + + if (!mStopWeather) + handler.postDelayed(mRunnableWeather, 1000); + } + + public native int openWeatherBoard(String dev); + public native int closeWeatherBoard(); + public native void readyData(); + public native int getUVindex(); + public native float getVisible(); + public native float getIR(); + public native int getTemperature(); + public native int getPressure(); + public native int getHumidity(); + public native int getAltitude(); + + static { + System.loadLibrary("weather"); + } +} diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk new file mode 100644 index 0000000..ac584b9 --- /dev/null +++ b/app/src/main/jni/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_C_INCLUDES += \ + $(NDK_PATH)/platforms/android-21/arch-arm/usr/include + +LOCAL_MODULE := weather +LOCAL_SRC_FILES := \ + weather.c \ + bme280-i2c.c \ + bme280.c \ + si1132.c +LOCAL_LDLIBS := -ldl -llog + +include $(BUILD_SHARED_LIBRARY) diff --git a/app/src/main/jni/bme280-i2c.c b/app/src/main/jni/bme280-i2c.c new file mode 100644 index 0000000..d7fc6ec --- /dev/null +++ b/app/src/main/jni/bme280-i2c.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +#include "bme280-i2c.h" +#include +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +#define LOG_TAG "wpi_android" + + +s32 bme280_begin(const char *device) +{ + int status = 0; + s32 com_rslt = 0; + bme280Fd = -1; + + bme280Fd = open(device, O_RDWR); + if (bme280Fd < 0) { + printf("ERROR: bme280 open failed\n"); + return -1; + } + status = ioctl(bme280Fd, I2C_SLAVE, BME280_I2C_ADDRESS1); + if (status < 0) { + printf("ERROR: bme280 ioctl error\n"); + close(bme280Fd); + return -1; + } + + I2C_routine(); + + if (bme280_init(&bme280) < 0) { + return -1; + } + + com_rslt += bme280_set_power_mode(BME280_NORMAL_MODE); + com_rslt += bme280_set_oversamp_humidity(BME280_OVERSAMP_2X); + com_rslt += bme280_set_oversamp_pressure(BME280_OVERSAMP_2X); + com_rslt += bme280_set_oversamp_temperature(BME280_OVERSAMP_2X); + usleep(100000); + + return com_rslt; +} + +void bme280_end() +{ + if (bme280Fd) + close(bme280Fd); +} + +void bme280_readAltitude(int pressure, float *seaLevel, int *result) +{ + float atmospheric = (float)pressure/100.0; + *result = (int)(44330.0 * (1.0 - pow(atmospheric/ *seaLevel, 0.1903))); +} + +s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt) +{ + s32 iError = BME280_INIT_VALUE; + u8 stringpos = BME280_INIT_VALUE; + unsigned char wbuf[2]; + for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) { + wbuf[1] = *(reg_data + stringpos); + wbuf[0] = reg_addr + stringpos; + write(bme280Fd, wbuf, 2); + } + return (s8)iError; +} + +s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt) +{ + s32 iError = BME280_INIT_VALUE; + u8 stringpos = BME280_INIT_VALUE; + unsigned char rbuf[2]; + int i; + for (stringpos = BME280_INIT_VALUE; stringpos < cnt; stringpos++) { + rbuf[0] = reg_addr + stringpos; + write(bme280Fd, rbuf, 1); + read(bme280Fd, rbuf, 1); + if (rbuf[0] < 0) iError = -1; + else *(reg_data + stringpos) = rbuf[0]; + } + return (s8)iError; +} + +void BME280_delay_msek(u16 msek) +{ + usleep(msek*1000); +} + +s8 I2C_routine(void) { + bme280.bus_write = BME280_I2C_bus_write; + bme280.bus_read = BME280_I2C_bus_read; + bme280.dev_addr = BME280_I2C_ADDRESS1; + bme280.delay_msec = BME280_delay_msek; + + return BME280_INIT_VALUE; +} diff --git a/app/src/main/jni/bme280-i2c.h b/app/src/main/jni/bme280-i2c.h new file mode 100644 index 0000000..017c51a --- /dev/null +++ b/app/src/main/jni/bme280-i2c.h @@ -0,0 +1,16 @@ +#include "bme280.h" + +int bme280Fd; + +struct bme280_t bme280; + +s32 bme280_begin(const char *device); +void bme280_end(); +void bme280_readAltitude(int pressure, float *seaLevelult, int *result); + +s8 I2C_routine(void); + +s8 BME280_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt); +s8 BME280_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt); + +void BME280_delay_msek(u16 msek); diff --git a/app/src/main/jni/bme280.c b/app/src/main/jni/bme280.c new file mode 100644 index 0000000..cd60891 --- /dev/null +++ b/app/src/main/jni/bme280.c @@ -0,0 +1,2215 @@ +/* +**************************************************************************** +* Copyright (C) 2013 - 2015 Bosch Sensortec GmbH +* +* bme280.c +* Date: 2015/03/27 +* Revision: 2.0.4(Pressure and Temperature compensation code revision is 1.1 +* and Humidity compensation code revision is 1.0) +* +* Usage: Sensor Driver file for BME280 sensor +* +**************************************************************************** +* License: +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of the +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +* OR CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE +* +* The information provided is believed to be accurate and reliable. +* The copyright holder assumes no responsibility +* for the consequences of use +* of such information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of the copyright holder. +**************************************************************************/ + +#include "bme280.h" +static struct bme280_t *p_bme280; /**< pointer to BME280 */ + +/*! + * @brief This function is used for initialize + * the bus read and bus write functions + * and assign the chip id and I2C address of the BME280 sensor + * chip id is read in the register 0xD0 bit from 0 to 7 + * + * @param bme280 structure pointer. + * + * @note While changing the parameter of the bme280_t + * @note consider the following point: + * Changing the reference value of the parameter + * will changes the local copy or local reference + * make sure your changes will not + * affect the reference value of the parameter + * (Better case don't change the reference value of the parameter) + * + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_init(struct bme280_t *bme280) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + + p_bme280 = bme280; + /* assign BME280 ptr */ + com_rslt = p_bme280->BME280_BUS_READ_FUNC(p_bme280->dev_addr, + BME280_CHIP_ID_REG, &v_data_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* read Chip Id */ + p_bme280->chip_id = v_data_u8; + if (p_bme280->chip_id != 0x60) { + return -1; + } + + com_rslt += bme280_get_calib_param(); + /* readout bme280 calibparam structure */ + return com_rslt; +} +/*! + * @brief This API is used to read uncompensated temperature + * in the registers 0xFA, 0xFB and 0xFC + * @note 0xFA -> MSB -> bit from 0 to 7 + * @note 0xFB -> LSB -> bit from 0 to 7 + * @note 0xFC -> LSB -> bit from 4 to 7 + * + * @param v_uncomp_temperature_s32 : The value of uncompensated temperature + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_temperature( +s32 *v_uncomp_temperature_s32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* Array holding the MSB and LSb value + a_data_u8r[0] - Temperature MSB + a_data_u8r[1] - Temperature LSB + a_data_u8r[2] - Temperature XLSB + */ + u8 a_data_u8r[BME280_TEMPERATURE_DATA_SIZE] = { + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE}; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_TEMPERATURE_MSB_REG, + a_data_u8r, + BME280_TEMPERATURE_DATA_LENGTH); + *v_uncomp_temperature_s32 = (s32)((( + (u32) (a_data_u8r[BME280_TEMPERATURE_MSB_DATA])) + << BME280_SHIFT_BIT_POSITION_BY_12_BITS) | + (((u32)(a_data_u8r[BME280_TEMPERATURE_LSB_DATA])) + << BME280_SHIFT_BIT_POSITION_BY_04_BITS) + | ((u32)a_data_u8r[BME280_TEMPERATURE_XLSB_DATA] >> + BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + } + return com_rslt; +} +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note Returns the value in 0.01 degree Centigrade + * Output value of "5123" equals 51.23 DegC. + * + * + * + * @param v_uncomp_temperature_s32 : value of uncompensated temperature + * + * + * @return Returns the actual temperature + * +*/ +s32 bme280_compensate_temperature_int32(s32 v_uncomp_temperature_s32) +{ + s32 v_x1_u32r = BME280_INIT_VALUE; + s32 v_x2_u32r = BME280_INIT_VALUE; + s32 temperature = BME280_INIT_VALUE; + + /* calculate x1*/ + v_x1_u32r = + ((((v_uncomp_temperature_s32 + >> BME280_SHIFT_BIT_POSITION_BY_03_BITS) - + ((s32)p_bme280->cal_param.dig_T1 + << BME280_SHIFT_BIT_POSITION_BY_01_BIT))) * + ((s32)p_bme280->cal_param.dig_T2)) >> + BME280_SHIFT_BIT_POSITION_BY_11_BITS; + /* calculate x2*/ + v_x2_u32r = (((((v_uncomp_temperature_s32 + >> BME280_SHIFT_BIT_POSITION_BY_04_BITS) - + ((s32)p_bme280->cal_param.dig_T1)) + * ((v_uncomp_temperature_s32 >> BME280_SHIFT_BIT_POSITION_BY_04_BITS) - + ((s32)p_bme280->cal_param.dig_T1))) + >> BME280_SHIFT_BIT_POSITION_BY_12_BITS) * + ((s32)p_bme280->cal_param.dig_T3)) + >> BME280_SHIFT_BIT_POSITION_BY_14_BITS; + /* calculate t_fine*/ + p_bme280->cal_param.t_fine = v_x1_u32r + v_x2_u32r; + /* calculate temperature*/ + temperature = (p_bme280->cal_param.t_fine * 5 + 128) + >> BME280_SHIFT_BIT_POSITION_BY_08_BITS; + return temperature; +} +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note Returns the value with 500LSB/DegC centred around 24 DegC + * output value of "5123" equals(5123/500)+24 = 34.246DegC + * + * + * @param v_uncomp_temperature_s32: value of uncompensated temperature + * + * + * + * @return Return the actual temperature as s16 output + * +*/ +s16 bme280_compensate_temperature_int32_sixteen_bit_output( +s32 v_uncomp_temperature_s32) +{ + s16 temperature = BME280_INIT_VALUE; + + bme280_compensate_temperature_int32( + v_uncomp_temperature_s32); + temperature = (s16)(((( + p_bme280->cal_param.t_fine - 122880) * 25) + 128) + >> BME280_SHIFT_BIT_POSITION_BY_08_BITS); + + return temperature; +} +/*! + * @brief This API is used to read uncompensated pressure. + * in the registers 0xF7, 0xF8 and 0xF9 + * @note 0xF7 -> MSB -> bit from 0 to 7 + * @note 0xF8 -> LSB -> bit from 0 to 7 + * @note 0xF9 -> LSB -> bit from 4 to 7 + * + * + * + * @param v_uncomp_pressure_s32 : The value of uncompensated pressure + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_pressure( +s32 *v_uncomp_pressure_s32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* Array holding the MSB and LSb value + a_data_u8[0] - Pressure MSB + a_data_u8[1] - Pressure LSB + a_data_u8[2] - Pressure XLSB + */ + u8 a_data_u8[BME280_PRESSURE_DATA_SIZE] = { + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE}; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_PRESSURE_MSB_REG, + a_data_u8, BME280_PRESSURE_DATA_LENGTH); + *v_uncomp_pressure_s32 = (s32)(( + ((u32)(a_data_u8[BME280_PRESSURE_MSB_DATA])) + << BME280_SHIFT_BIT_POSITION_BY_12_BITS) | + (((u32)(a_data_u8[BME280_PRESSURE_LSB_DATA])) + << BME280_SHIFT_BIT_POSITION_BY_04_BITS) | + ((u32)a_data_u8[BME280_PRESSURE_XLSB_DATA] >> + BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + } + return com_rslt; +} +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pascal(Pa) + * Output value of "96386" equals 96386 Pa = + * 963.86 hPa = 963.86 millibar + * + * + * + * @param v_uncomp_pressure_s32 : value of uncompensated pressure + * + * + * + * @return Return the actual pressure output as u32 + * +*/ +u32 bme280_compensate_pressure_int32(s32 v_uncomp_pressure_s32) +{ + s32 v_x1_u32 = BME280_INIT_VALUE; + s32 v_x2_u32 = BME280_INIT_VALUE; + u32 v_pressure_u32 = BME280_INIT_VALUE; + + /* calculate x1*/ + v_x1_u32 = (((s32)p_bme280->cal_param.t_fine) + >> BME280_SHIFT_BIT_POSITION_BY_01_BIT) - (s32)64000; + /* calculate x2*/ + v_x2_u32 = (((v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_02_BITS) + * (v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_02_BITS) + ) >> BME280_SHIFT_BIT_POSITION_BY_11_BITS) + * ((s32)p_bme280->cal_param.dig_P6); + /* calculate x2*/ + v_x2_u32 = v_x2_u32 + ((v_x1_u32 * + ((s32)p_bme280->cal_param.dig_P5)) + << BME280_SHIFT_BIT_POSITION_BY_01_BIT); + /* calculate x2*/ + v_x2_u32 = (v_x2_u32 >> BME280_SHIFT_BIT_POSITION_BY_02_BITS) + + (((s32)p_bme280->cal_param.dig_P4) + << BME280_SHIFT_BIT_POSITION_BY_16_BITS); + /* calculate x1*/ + v_x1_u32 = (((p_bme280->cal_param.dig_P3 * + (((v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_02_BITS) * + (v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_02_BITS)) + >> BME280_SHIFT_BIT_POSITION_BY_13_BITS)) + >> BME280_SHIFT_BIT_POSITION_BY_03_BITS) + + ((((s32)p_bme280->cal_param.dig_P2) * + v_x1_u32) >> BME280_SHIFT_BIT_POSITION_BY_01_BIT)) + >> BME280_SHIFT_BIT_POSITION_BY_18_BITS; + /* calculate x1*/ + v_x1_u32 = ((((32768 + v_x1_u32)) * + ((s32)p_bme280->cal_param.dig_P1)) + >> BME280_SHIFT_BIT_POSITION_BY_15_BITS); + /* calculate pressure*/ + v_pressure_u32 = + (((u32)(((s32)1048576) - v_uncomp_pressure_s32) + - (v_x2_u32 >> BME280_SHIFT_BIT_POSITION_BY_12_BITS))) * 3125; + if (v_pressure_u32 + < 0x80000000) + /* Avoid exception caused by division by zero */ + if (v_x1_u32 != BME280_INIT_VALUE) + v_pressure_u32 = + (v_pressure_u32 + << BME280_SHIFT_BIT_POSITION_BY_01_BIT) / + ((u32)v_x1_u32); + else + return BME280_INVALID_DATA; + else + /* Avoid exception caused by division by zero */ + if (v_x1_u32 != BME280_INIT_VALUE) + v_pressure_u32 = (v_pressure_u32 + / (u32)v_x1_u32) * 2; + else + return BME280_INVALID_DATA; + + v_x1_u32 = (((s32)p_bme280->cal_param.dig_P9) * + ((s32)(((v_pressure_u32 >> BME280_SHIFT_BIT_POSITION_BY_03_BITS) + * (v_pressure_u32 >> BME280_SHIFT_BIT_POSITION_BY_03_BITS)) + >> BME280_SHIFT_BIT_POSITION_BY_13_BITS))) + >> BME280_SHIFT_BIT_POSITION_BY_12_BITS; + v_x2_u32 = (((s32)(v_pressure_u32 + >> BME280_SHIFT_BIT_POSITION_BY_02_BITS)) * + ((s32)p_bme280->cal_param.dig_P8)) + >> BME280_SHIFT_BIT_POSITION_BY_13_BITS; + v_pressure_u32 = (u32)((s32)v_pressure_u32 + + ((v_x1_u32 + v_x2_u32 + p_bme280->cal_param.dig_P7) + >> BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + + return v_pressure_u32; +} +/*! + * @brief This API is used to read uncompensated humidity. + * in the registers 0xF7, 0xF8 and 0xF9 + * @note 0xFD -> MSB -> bit from 0 to 7 + * @note 0xFE -> LSB -> bit from 0 to 7 + * + * + * + * @param v_uncomp_humidity_s32 : The value of uncompensated humidity + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_humidity( +s32 *v_uncomp_humidity_s32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* Array holding the MSB and LSb value + a_data_u8[0] - Humidity MSB + a_data_u8[1] - Humidity LSB + */ + u8 a_data_u8[BME280_HUMIDITY_DATA_SIZE] = { + BME280_INIT_VALUE, BME280_INIT_VALUE}; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_HUMIDITY_MSB_REG, a_data_u8, + BME280_HUMIDITY_DATA_LENGTH); + *v_uncomp_humidity_s32 = (s32)( + (((u32)(a_data_u8[BME280_HUMIDITY_MSB_DATA])) + << BME280_SHIFT_BIT_POSITION_BY_08_BITS)| + ((u32)(a_data_u8[BME280_HUMIDITY_LSB_DATA]))); + } + return com_rslt; +} +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note Returns the value in %rH as unsigned 32bit integer + * in Q22.10 format(22 integer 10 fractional bits). + * @note An output value of 42313 + * represents 42313 / 1024 = 41.321 %rH + * + * + * + * @param v_uncomp_humidity_s32: value of uncompensated humidity + * + * @return Return the actual relative humidity output as u32 + * +*/ +u32 bme280_compensate_humidity_int32(s32 v_uncomp_humidity_s32) +{ + s32 v_x1_u32 = BME280_INIT_VALUE; + + /* calculate x1*/ + v_x1_u32 = (p_bme280->cal_param.t_fine - ((s32)76800)); + /* calculate x1*/ + v_x1_u32 = (((((v_uncomp_humidity_s32 + << BME280_SHIFT_BIT_POSITION_BY_14_BITS) - + (((s32)p_bme280->cal_param.dig_H4) + << BME280_SHIFT_BIT_POSITION_BY_20_BITS) - + (((s32)p_bme280->cal_param.dig_H5) * v_x1_u32)) + + ((s32)16384)) >> BME280_SHIFT_BIT_POSITION_BY_15_BITS) + * (((((((v_x1_u32 * + ((s32)p_bme280->cal_param.dig_H6)) + >> BME280_SHIFT_BIT_POSITION_BY_10_BITS) * + (((v_x1_u32 * ((s32)p_bme280->cal_param.dig_H3)) + >> BME280_SHIFT_BIT_POSITION_BY_11_BITS) + ((s32)32768))) + >> BME280_SHIFT_BIT_POSITION_BY_10_BITS) + ((s32)2097152)) * + ((s32)p_bme280->cal_param.dig_H2) + 8192) >> 14)); + v_x1_u32 = (v_x1_u32 - (((((v_x1_u32 + >> BME280_SHIFT_BIT_POSITION_BY_15_BITS) * + (v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_15_BITS)) + >> BME280_SHIFT_BIT_POSITION_BY_07_BITS) * + ((s32)p_bme280->cal_param.dig_H1)) + >> BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + v_x1_u32 = (v_x1_u32 < 0 ? 0 : v_x1_u32); + v_x1_u32 = (v_x1_u32 > 419430400 ? + 419430400 : v_x1_u32); + return (u32)(v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_12_BITS); +} +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note Returns the value in %rH as unsigned 16bit integer + * @note An output value of 42313 + * represents 42313/512 = 82.643 %rH + * + * + * + * @param v_uncomp_humidity_s32: value of uncompensated humidity + * + * + * @return Return the actual relative humidity output as u16 + * +*/ +u16 bme280_compensate_humidity_int32_sixteen_bit_output( +s32 v_uncomp_humidity_s32) +{ + u32 v_x1_u32 = BME280_INIT_VALUE; + u16 v_x2_u32 = BME280_INIT_VALUE; + + v_x1_u32 = bme280_compensate_humidity_int32(v_uncomp_humidity_s32); + v_x2_u32 = (u16)(v_x1_u32 >> BME280_SHIFT_BIT_POSITION_BY_01_BIT); + return v_x2_u32; +} +/*! + * @brief This API used to read uncompensated + * pressure,temperature and humidity + * + * + * + * + * @param v_uncomp_pressure_s32: The value of uncompensated pressure. + * @param v_uncomp_temperature_s32: The value of uncompensated temperature + * @param v_uncomp_humidity_s32: The value of uncompensated humidity. + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_pressure_temperature_humidity( +s32 *v_uncomp_pressure_s32, +s32 *v_uncomp_temperature_s32, s32 *v_uncomp_humidity_s32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* Array holding the MSB and LSb value of + a_data_u8[0] - Pressure MSB + a_data_u8[1] - Pressure LSB + a_data_u8[1] - Pressure LSB + a_data_u8[1] - Temperature MSB + a_data_u8[1] - Temperature LSB + a_data_u8[1] - Temperature LSB + a_data_u8[1] - Humidity MSB + a_data_u8[1] - Humidity LSB + */ + u8 a_data_u8[BME280_DATA_FRAME_SIZE] = { + BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE}; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_PRESSURE_MSB_REG, + a_data_u8, BME280_ALL_DATA_FRAME_LENGTH); + /*Pressure*/ + *v_uncomp_pressure_s32 = (s32)(( + ((u32)(a_data_u8[ + BME280_DATA_FRAME_PRESSURE_MSB_BYTE])) + << BME280_SHIFT_BIT_POSITION_BY_12_BITS) | + (((u32)(a_data_u8[ + BME280_DATA_FRAME_PRESSURE_LSB_BYTE])) + << BME280_SHIFT_BIT_POSITION_BY_04_BITS) | + ((u32)a_data_u8[ + BME280_DATA_FRAME_PRESSURE_XLSB_BYTE] >> + BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + + /* Temperature */ + *v_uncomp_temperature_s32 = (s32)((( + (u32) (a_data_u8[ + BME280_DATA_FRAME_TEMPERATURE_MSB_BYTE])) + << BME280_SHIFT_BIT_POSITION_BY_12_BITS) | + (((u32)(a_data_u8[ + BME280_DATA_FRAME_TEMPERATURE_LSB_BYTE])) + << BME280_SHIFT_BIT_POSITION_BY_04_BITS) + | ((u32)a_data_u8[ + BME280_DATA_FRAME_TEMPERATURE_XLSB_BYTE] + >> BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + + /*Humidity*/ + *v_uncomp_humidity_s32 = (s32)(( + ((u32)(a_data_u8[ + BME280_DATA_FRAME_HUMIDITY_MSB_BYTE])) + << BME280_SHIFT_BIT_POSITION_BY_08_BITS)| + ((u32)(a_data_u8[ + BME280_DATA_FRAME_HUMIDITY_LSB_BYTE]))); + } + return com_rslt; +} +/*! + * @brief This API used to read true pressure, temperature and humidity + * + * + * + * + * @param v_pressure_u32 : The value of compensated pressure. + * @param v_temperature_s32 : The value of compensated temperature. + * @param v_humidity_u32 : The value of compensated humidity. + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_pressure_temperature_humidity( +u32 *v_pressure_u32, s32 *v_temperature_s32, u32 *v_humidity_u32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + s32 v_uncomp_pressure_s32 = BME280_INIT_VALUE; + s32 v_uncom_temperature_s32 = BME280_INIT_VALUE; + s32 v_uncom_humidity_s32 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + /* read the uncompensated pressure, + temperature and humidity*/ + com_rslt = + bme280_read_uncomp_pressure_temperature_humidity( + &v_uncomp_pressure_s32, &v_uncom_temperature_s32, + &v_uncom_humidity_s32); + /* read the true pressure, temperature and humidity*/ + *v_temperature_s32 = + bme280_compensate_temperature_int32( + v_uncom_temperature_s32); + *v_pressure_u32 = bme280_compensate_pressure_int32( + v_uncomp_pressure_s32); + *v_humidity_u32 = bme280_compensate_humidity_int32( + v_uncom_humidity_s32); + } + return com_rslt; +} +/*! + * @brief This API is used to + * calibration parameters used for calculation in the registers + * + * parameter | Register address | bit + *------------|------------------|---------------- + * dig_T1 | 0x88 and 0x89 | from 0 : 7 to 8: 15 + * dig_T2 | 0x8A and 0x8B | from 0 : 7 to 8: 15 + * dig_T3 | 0x8C and 0x8D | from 0 : 7 to 8: 15 + * dig_P1 | 0x8E and 0x8F | from 0 : 7 to 8: 15 + * dig_P2 | 0x90 and 0x91 | from 0 : 7 to 8: 15 + * dig_P3 | 0x92 and 0x93 | from 0 : 7 to 8: 15 + * dig_P4 | 0x94 and 0x95 | from 0 : 7 to 8: 15 + * dig_P5 | 0x96 and 0x97 | from 0 : 7 to 8: 15 + * dig_P6 | 0x98 and 0x99 | from 0 : 7 to 8: 15 + * dig_P7 | 0x9A and 0x9B | from 0 : 7 to 8: 15 + * dig_P8 | 0x9C and 0x9D | from 0 : 7 to 8: 15 + * dig_P9 | 0x9E and 0x9F | from 0 : 7 to 8: 15 + * dig_H1 | 0xA1 | from 0 to 7 + * dig_H2 | 0xE1 and 0xE2 | from 0 : 7 to 8: 15 + * dig_H3 | 0xE3 | from 0 to 7 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_calib_param(void) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 a_data_u8[BME280_CALIB_DATA_SIZE] = { + BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE, + BME280_INIT_VALUE, BME280_INIT_VALUE, BME280_INIT_VALUE}; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_TEMPERATURE_CALIB_DIG_T1_LSB_REG, + a_data_u8, + BME280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH); + + p_bme280->cal_param.dig_T1 = (u16)((( + (u16)((u8)a_data_u8[ + BME280_TEMPERATURE_CALIB_DIG_T1_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_TEMPERATURE_CALIB_DIG_T1_LSB]); + p_bme280->cal_param.dig_T2 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_TEMPERATURE_CALIB_DIG_T2_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_TEMPERATURE_CALIB_DIG_T2_LSB]); + p_bme280->cal_param.dig_T3 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_TEMPERATURE_CALIB_DIG_T3_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_TEMPERATURE_CALIB_DIG_T3_LSB]); + p_bme280->cal_param.dig_P1 = (u16)((( + (u16)((u8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P1_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P1_LSB]); + p_bme280->cal_param.dig_P2 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P2_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P2_LSB]); + p_bme280->cal_param.dig_P3 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P3_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P3_LSB]); + p_bme280->cal_param.dig_P4 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P4_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P4_LSB]); + p_bme280->cal_param.dig_P5 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P5_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P5_LSB]); + p_bme280->cal_param.dig_P6 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P6_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P6_LSB]); + p_bme280->cal_param.dig_P7 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P7_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P7_LSB]); + p_bme280->cal_param.dig_P8 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P8_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P8_LSB]); + p_bme280->cal_param.dig_P9 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_PRESSURE_CALIB_DIG_P9_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_PRESSURE_CALIB_DIG_P9_LSB]); + p_bme280->cal_param.dig_H1 = + a_data_u8[BME280_HUMIDITY_CALIB_DIG_H1]; + com_rslt += p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_HUMIDITY_CALIB_DIG_H2_LSB_REG, a_data_u8, + BME280_HUMIDITY_CALIB_DATA_LENGTH); + p_bme280->cal_param.dig_H2 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_HUMIDITY_CALIB_DIG_H2_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_08_BITS) + | a_data_u8[BME280_HUMIDITY_CALIB_DIG_H2_LSB]); + p_bme280->cal_param.dig_H3 = + a_data_u8[BME280_HUMIDITY_CALIB_DIG_H3]; + p_bme280->cal_param.dig_H4 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_HUMIDITY_CALIB_DIG_H4_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_04_BITS) | + (((u8)BME280_MASK_DIG_H4) & + a_data_u8[BME280_HUMIDITY_CALIB_DIG_H4_LSB])); + p_bme280->cal_param.dig_H5 = (s16)((( + (s16)((s8)a_data_u8[ + BME280_HUMIDITY_CALIB_DIG_H5_MSB])) << + BME280_SHIFT_BIT_POSITION_BY_04_BITS) | + (a_data_u8[BME280_HUMIDITY_CALIB_DIG_H4_LSB] >> + BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + p_bme280->cal_param.dig_H6 = + (s8)a_data_u8[BME280_HUMIDITY_CALIB_DIG_H6]; + } + return com_rslt; +} +/*! + * @brief This API is used to get + * the temperature oversampling setting in the register 0xF4 + * bits from 5 to 7 + * + * value | Temperature oversampling + * ---------------------|--------------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of temperature over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_temperature( +u8 *v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_value_u8 = BME280_GET_BITSLICE(v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE); + + p_bme280->oversamp_temperature = *v_value_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to set + * the temperature oversampling setting in the register 0xF4 + * bits from 5 to 7 + * + * value | Temperature oversampling + * ---------------------|--------------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of temperature over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_temperature( +u8 v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + u8 v_pre_config_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_data_u8 = p_bme280->ctrl_meas_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE, v_value_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous value + of configuration register*/ + v_pre_config_value_u8 = p_bme280->config_reg; + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &v_pre_config_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value + of humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous and updated value + of configuration register*/ + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + p_bme280->oversamp_temperature = v_value_u8; + /* read the control measurement register value*/ + com_rslt = bme280_read_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the control + configuration register value*/ + com_rslt += bme280_read_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to get + * the pressure oversampling setting in the register 0xF4 + * bits from 2 to 4 + * + * value | Pressure oversampling + * --------------------|-------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of pressure oversampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_pressure( +u8 *v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_value_u8 = BME280_GET_BITSLICE( + v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_PRESSURE); + + p_bme280->oversamp_pressure = *v_value_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to set + * the pressure oversampling setting in the register 0xF4 + * bits from 2 to 4 + * + * value | Pressure oversampling + * --------------------|-------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of pressure oversampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_pressure( +u8 v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + u8 v_pre_config_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_data_u8 = p_bme280->ctrl_meas_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_PRESSURE, v_value_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous value of + configuration register*/ + v_pre_config_value_u8 = p_bme280->config_reg; + com_rslt = bme280_write_register( + BME280_CONFIG_REG, + &v_pre_config_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous and updated value of + control measurement register*/ + bme280_write_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + p_bme280->oversamp_pressure = v_value_u8; + /* read the control measurement register value*/ + com_rslt = bme280_read_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the control + configuration register value*/ + com_rslt += bme280_read_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to get + * the humidity oversampling setting in the register 0xF2 + * bits from 0 to 2 + * + * value | Humidity oversampling + * ---------------------|------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of humidity over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_humidity( +u8 *v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_value_u8 = BME280_GET_BITSLICE( + v_data_u8, + BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY); + + p_bme280->oversamp_humidity = *v_value_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to set + * the humidity oversampling setting in the register 0xF2 + * bits from 0 to 2 + * + * value | Humidity oversampling + * ---------------------|------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of humidity over sampling + * + * + * + * @note The "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * register sets the humidity + * data acquisition options of the device. + * @note changes to this registers only become + * effective after a write operation to + * "BME280_CTRL_MEAS_REG" register. + * @note In the code automated reading and writing of + * "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * @note register first set the + * "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * and then read and write + * the "BME280_CTRL_MEAS_REG" register in the function. + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_humidity( +u8 v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 pre_ctrl_meas_value = BME280_INIT_VALUE; + u8 v_pre_config_value_u8 = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + /* write humidity oversampling*/ + v_data_u8 = p_bme280->ctrl_hum_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY, v_value_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous value of + configuration register*/ + v_pre_config_value_u8 = p_bme280->config_reg; + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &v_pre_config_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write the value of control humidity*/ + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + control measurement register*/ + pre_ctrl_meas_value = + p_bme280->ctrl_meas_reg; + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &pre_ctrl_meas_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt += + p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + /* Control humidity write will effective only + after the control measurement register*/ + pre_ctrl_meas_value = + p_bme280->ctrl_meas_reg; + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &pre_ctrl_meas_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } + p_bme280->oversamp_humidity = v_value_u8; + /* read the control measurement register value*/ + com_rslt += bme280_read_register(BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the control configuration register value*/ + com_rslt += bme280_read_register(BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief This API used to get the + * Operational Mode from the sensor in the register 0xF4 bit 0 and 1 + * + * + * + * @param v_power_mode_u8 : The value of power mode + * value | mode + * -----------------|------------------ + * 0x00 | BME280_SLEEP_MODE + * 0x01 and 0x02 | BME280_FORCED_MODE + * 0x03 | BME280_NORMAL_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_power_mode(u8 *v_power_mode_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_mode_u8r = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_POWER_MODE__REG, + &v_mode_u8r, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_power_mode_u8 = BME280_GET_BITSLICE(v_mode_u8r, + BME280_CTRL_MEAS_REG_POWER_MODE); + } + return com_rslt; +} +/*! + * @brief This API used to set the + * Operational Mode from the sensor in the register 0xF4 bit 0 and 1 + * + * + * + * @param v_power_mode_u8 : The value of power mode + * value | mode + * -----------------|------------------ + * 0x00 | BME280_SLEEP_MODE + * 0x01 and 0x02 | BME280_FORCED_MODE + * 0x03 | BME280_NORMAL_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_power_mode(u8 v_power_mode_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_mode_u8r = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + u8 v_pre_config_value_u8 = BME280_INIT_VALUE; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + if (v_power_mode_u8 <= BME280_NORMAL_MODE) { + v_mode_u8r = p_bme280->ctrl_meas_reg; + v_mode_u8r = + BME280_SET_BITSLICE(v_mode_u8r, + BME280_CTRL_MEAS_REG_POWER_MODE, + v_power_mode_u8); + com_rslt = bme280_get_power_mode( + &v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous value of + configuration register*/ + v_pre_config_value_u8 = + p_bme280->config_reg; + com_rslt = bme280_write_register( + BME280_CONFIG_REG, + &v_pre_config_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous and updated value of + control measurement register*/ + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &v_mode_u8r, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = + p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CTRL_MEAS_REG_POWER_MODE__REG, + &v_mode_u8r, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } + /* read the control measurement register value*/ + com_rslt = bme280_read_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the config register value*/ + com_rslt += bme280_read_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } else { + com_rslt = E_BME280_OUT_OF_RANGE; + } + } + return com_rslt; +} +/*! + * @brief Used to reset the sensor + * The value 0xB6 is written to the 0xE0 + * register the device is reset using the + * complete power-on-reset procedure. + * @note Soft reset can be easily set using bme280_set_softreset(). + * @note Usage Hint : bme280_set_softreset() + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_soft_rst(void) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_SOFT_RESET_CODE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_RST_REG, &v_data_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } + return com_rslt; +} +/*! + * @brief This API used to get the sensor + * SPI mode(communication type) in the register 0xF5 bit 0 + * + * + * + * @param v_enable_disable_u8 : The value of SPI enable + * value | Description + * --------|-------------- + * 0 | Disable + * 1 | Enable + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_spi3(u8 *v_enable_disable_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_SPI3_ENABLE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_enable_disable_u8 = BME280_GET_BITSLICE( + v_data_u8, + BME280_CONFIG_REG_SPI3_ENABLE); + } + return com_rslt; +} +/*! + * @brief This API used to set the sensor + * SPI mode(communication type) in the register 0xF5 bit 0 + * + * + * + * @param v_enable_disable_u8 : The value of SPI enable + * value | Description + * --------|-------------- + * 0 | Disable + * 1 | Enable + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_spi3(u8 v_enable_disable_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 pre_ctrl_meas_value = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_data_u8 = p_bme280->config_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CONFIG_REG_SPI3_ENABLE, v_enable_disable_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous and updated value of + configuration register*/ + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + control measurement register*/ + pre_ctrl_meas_value = + p_bme280->ctrl_meas_reg; + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &pre_ctrl_meas_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = + p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_SPI3_ENABLE__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + /* read the control measurement register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the control configuration register value*/ + com_rslt += bme280_read_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief This API is used to reads filter setting + * in the register 0xF5 bit 3 and 4 + * + * + * + * @param v_value_u8 : The value of IIR filter coefficient + * + * value | Filter coefficient + * -------------|------------------------- + * 0x00 | BME280_FILTER_COEFF_OFF + * 0x01 | BME280_FILTER_COEFF_2 + * 0x02 | BME280_FILTER_COEFF_4 + * 0x03 | BME280_FILTER_COEFF_8 + * 0x04 | BME280_FILTER_COEFF_16 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_filter(u8 *v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_FILTER__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_value_u8 = BME280_GET_BITSLICE(v_data_u8, + BME280_CONFIG_REG_FILTER); + } + return com_rslt; +} +/*! + * @brief This API is used to write filter setting + * in the register 0xF5 bit 3 and 4 + * + * + * + * @param v_value_u8 : The value of IIR filter coefficient + * + * value | Filter coefficient + * -------------|------------------------- + * 0x00 | BME280_FILTER_COEFF_OFF + * 0x01 | BME280_FILTER_COEFF_2 + * 0x02 | BME280_FILTER_COEFF_4 + * 0x03 | BME280_FILTER_COEFF_8 + * 0x04 | BME280_FILTER_COEFF_16 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_filter(u8 v_value_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 pre_ctrl_meas_value = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_data_u8 = p_bme280->config_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CONFIG_REG_FILTER, v_value_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous and updated value of + configuration register*/ + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + control measurement register*/ + pre_ctrl_meas_value = + p_bme280->ctrl_meas_reg; + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &pre_ctrl_meas_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = + p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_FILTER__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + /* read the control measurement register value*/ + com_rslt += bme280_read_register(BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the configuration register value*/ + com_rslt += bme280_read_register(BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief This API used to Read the + * standby duration time from the sensor in the register 0xF5 bit 5 to 7 + * + * @param v_standby_durn_u8 : The value of standby duration time value. + * value | standby duration + * -------------|----------------------- + * 0x00 | BME280_STANDBY_TIME_1_MS + * 0x01 | BME280_STANDBY_TIME_63_MS + * 0x02 | BME280_STANDBY_TIME_125_MS + * 0x03 | BME280_STANDBY_TIME_250_MS + * 0x04 | BME280_STANDBY_TIME_500_MS + * 0x05 | BME280_STANDBY_TIME_1000_MS + * 0x06 | BME280_STANDBY_TIME_2000_MS + * 0x07 | BME280_STANDBY_TIME_4000_MS + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_standby_durn(u8 *v_standby_durn_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_TSB__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + *v_standby_durn_u8 = BME280_GET_BITSLICE( + v_data_u8, BME280_CONFIG_REG_TSB); + } + return com_rslt; +} +/*! + * @brief This API used to write the + * standby duration time from the sensor in the register 0xF5 bit 5 to 7 + * + * @param v_standby_durn_u8 : The value of standby duration time value. + * value | standby duration + * -------------|----------------------- + * 0x00 | BME280_STANDBY_TIME_1_MS + * 0x01 | BME280_STANDBY_TIME_63_MS + * 0x02 | BME280_STANDBY_TIME_125_MS + * 0x03 | BME280_STANDBY_TIME_250_MS + * 0x04 | BME280_STANDBY_TIME_500_MS + * 0x05 | BME280_STANDBY_TIME_1000_MS + * 0x06 | BME280_STANDBY_TIME_2000_MS + * 0x07 | BME280_STANDBY_TIME_4000_MS + * + * @note Normal mode comprises an automated perpetual + * cycling between an (active) + * Measurement period and an (inactive) standby period. + * @note The standby time is determined by + * the contents of the register t_sb. + * Standby time can be set using BME280_STANDBY_TIME_125_MS. + * + * @note Usage Hint : bme280_set_standby_durn(BME280_STANDBY_TIME_125_MS) + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_standby_durn(u8 v_standby_durn_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 pre_ctrl_meas_value = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_data_u8 = p_bme280->config_reg; + v_data_u8 = + BME280_SET_BITSLICE(v_data_u8, + BME280_CONFIG_REG_TSB, v_standby_durn_u8); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous and updated value of + configuration register*/ + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of control + measurement register*/ + pre_ctrl_meas_value = + p_bme280->ctrl_meas_reg; + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &pre_ctrl_meas_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + com_rslt = + p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + BME280_CONFIG_REG_TSB__REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + /* read the control measurement register value*/ + com_rslt += bme280_read_register(BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the configuration register value*/ + com_rslt += bme280_read_register(BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + } + return com_rslt; +} +/* + * @brief Writes the working mode to the sensor + * + * + * + * + * @param v_work_mode_u8 : Mode to be set + * value | Working mode + * ----------|-------------------- + * 0 | BME280_ULTRALOWPOWER_MODE + * 1 | BME280_LOWPOWER_MODE + * 2 | BME280_STANDARDRESOLUTION_MODE + * 3 | BME280_HIGHRESOLUTION_MODE + * 4 | BME280_ULTRAHIGHRESOLUTION_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +/*BME280_RETURN_FUNCTION_TYPE bme280_set_work_mode(u8 v_work_mode_u8) +{ +BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; +u8 v_data_u8 = BME280_INIT_VALUE; +if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; +} else { + if (v_work_mode_u8 <= BME280_ULTRAHIGHRESOLUTION_MODE) { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + if (com_rslt == SUCCESS) { + switch (v_work_mode_u8) { + case BME280_ULTRALOWPOWER_MODE: + p_bme280->oversamp_temperature = + BME280_ULTRALOWPOWER_OSRS_T; + p_bme280->osrs_p = + BME280_ULTRALOWPOWER_OSRS_P; + break; + case BME280_LOWPOWER_MODE: + p_bme280->oversamp_temperature = + BME280_LOWPOWER_OSRS_T; + p_bme280->osrs_p = BME280_LOWPOWER_OSRS_P; + break; + case BME280_STANDARDRESOLUTION_MODE: + p_bme280->oversamp_temperature = + BME280_STANDARDRESOLUTION_OSRS_T; + p_bme280->osrs_p = + BME280_STANDARDRESOLUTION_OSRS_P; + break; + case BME280_HIGHRESOLUTION_MODE: + p_bme280->oversamp_temperature = + BME280_HIGHRESOLUTION_OSRS_T; + p_bme280->osrs_p = BME280_HIGHRESOLUTION_OSRS_P; + break; + case BME280_ULTRAHIGHRESOLUTION_MODE: + p_bme280->oversamp_temperature = + BME280_ULTRAHIGHRESOLUTION_OSRS_T; + p_bme280->osrs_p = + BME280_ULTRAHIGHRESOLUTION_OSRS_P; + break; + } + v_data_u8 = BME280_SET_BITSLICE(v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE, + p_bme280->oversamp_temperature); + v_data_u8 = BME280_SET_BITSLICE(v_data_u8, + BME280_CTRL_MEAS_REG_OVERSAMP_PRESSURE, + p_bme280->osrs_p); + com_rslt += p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + } else { + com_rslt = E_BME280_OUT_OF_RANGE; + } +} +return com_rslt; +}*/ +/*! + * @brief This API used to read uncompensated + * temperature,pressure and humidity in forced mode + * + * + * @param v_uncom_pressure_s32: The value of uncompensated pressure + * @param v_uncom_temperature_s32: The value of uncompensated temperature + * @param v_uncom_humidity_s32: The value of uncompensated humidity + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE +bme280_get_forced_uncomp_pressure_temperature_humidity( +s32 *v_uncom_pressure_s32, +s32 *v_uncom_temperature_s32, s32 *v_uncom_humidity_s32) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + u8 v_data_u8 = BME280_INIT_VALUE; + u8 v_waittime_u8r = BME280_INIT_VALUE; + u8 v_prev_pow_mode_u8 = BME280_INIT_VALUE; + u8 v_mode_u8r = BME280_INIT_VALUE; + u8 pre_ctrl_config_value = BME280_INIT_VALUE; + u8 v_pre_ctrl_hum_value_u8 = BME280_INIT_VALUE; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + v_mode_u8r = p_bme280->ctrl_meas_reg; + v_mode_u8r = + BME280_SET_BITSLICE(v_mode_u8r, + BME280_CTRL_MEAS_REG_POWER_MODE, BME280_FORCED_MODE); + com_rslt = bme280_get_power_mode(&v_prev_pow_mode_u8); + if (v_prev_pow_mode_u8 != BME280_SLEEP_MODE) { + com_rslt += bme280_set_soft_rst(); + p_bme280->delay_msec(BME280_3MS_DELAY); + /* write previous and updated value of + configuration register*/ + pre_ctrl_config_value = p_bme280->config_reg; + com_rslt += bme280_write_register( + BME280_CONFIG_REG, + &pre_ctrl_config_value, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write the force mode */ + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &v_mode_u8r, BME280_GEN_READ_WRITE_DATA_LENGTH); + } else { + /* write previous value of + humidity oversampling*/ + v_pre_ctrl_hum_value_u8 = + p_bme280->ctrl_hum_reg; + com_rslt += bme280_write_register( + BME280_CTRL_HUMIDITY_REG, + &v_pre_ctrl_hum_value_u8, + BME280_GEN_READ_WRITE_DATA_LENGTH); + /* write the force mode */ + com_rslt += bme280_write_register( + BME280_CTRL_MEAS_REG, + &v_mode_u8r, BME280_GEN_READ_WRITE_DATA_LENGTH); + } + bme280_compute_wait_time(&v_waittime_u8r); + p_bme280->delay_msec(v_waittime_u8r); + /* read the force-mode value of pressure + temperature and humidity*/ + com_rslt += + bme280_read_uncomp_pressure_temperature_humidity( + v_uncom_pressure_s32, v_uncom_temperature_s32, + v_uncom_humidity_s32); + + /* read the control humidity register value*/ + com_rslt += bme280_read_register( + BME280_CTRL_HUMIDITY_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_hum_reg = v_data_u8; + /* read the configuration register value*/ + com_rslt += bme280_read_register(BME280_CONFIG_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->config_reg = v_data_u8; + + /* read the control measurement register value*/ + com_rslt += bme280_read_register(BME280_CTRL_MEAS_REG, + &v_data_u8, BME280_GEN_READ_WRITE_DATA_LENGTH); + p_bme280->ctrl_meas_reg = v_data_u8; + } + return com_rslt; +} +/*! + * @brief + * This API write the data to + * the given register + * + * + * @param v_addr_u8 -> Address of the register + * @param v_data_u8 -> The data from the register + * @param v_len_u8 -> no of bytes to read + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_write_register(u8 v_addr_u8, +u8 *v_data_u8, u8 v_len_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_WRITE_FUNC( + p_bme280->dev_addr, + v_addr_u8, v_data_u8, v_len_u8); + } + return com_rslt; +} +/*! + * @brief + * This API reads the data from + * the given register + * + * + * @param v_addr_u8 -> Address of the register + * @param v_data_u8 -> The data from the register + * @param v_len_u8 -> no of bytes to read + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_read_register(u8 v_addr_u8, +u8 *v_data_u8, u8 v_len_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = ERROR; + /* check the p_bme280 structure pointer as NULL*/ + if (p_bme280 == BME280_NULL) { + return E_BME280_NULL_PTR; + } else { + com_rslt = p_bme280->BME280_BUS_READ_FUNC( + p_bme280->dev_addr, + v_addr_u8, v_data_u8, v_len_u8); + } + return com_rslt; +} +#ifdef BME280_ENABLE_FLOAT +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note returns the value in Degree centigrade + * @note Output value of "51.23" equals 51.23 DegC. + * + * + * + * @param v_uncom_temperature_s32 : value of uncompensated temperature + * + * + * + * @return Return the actual temperature in floating point + * +*/ +double bme280_compensate_temperature_double(s32 v_uncom_temperature_s32) +{ + double v_x1_u32 = BME280_INIT_VALUE; + double v_x2_u32 = BME280_INIT_VALUE; + double temperature = BME280_INIT_VALUE; + + v_x1_u32 = (((double)v_uncom_temperature_s32) / 16384.0 - + ((double)p_bme280->cal_param.dig_T1) / 1024.0) * + ((double)p_bme280->cal_param.dig_T2); + v_x2_u32 = ((((double)v_uncom_temperature_s32) / 131072.0 - + ((double)p_bme280->cal_param.dig_T1) / 8192.0) * + (((double)v_uncom_temperature_s32) / 131072.0 - + ((double)p_bme280->cal_param.dig_T1) / 8192.0)) * + ((double)p_bme280->cal_param.dig_T3); + p_bme280->cal_param.t_fine = (s32)(v_x1_u32 + v_x2_u32); + temperature = (v_x1_u32 + v_x2_u32) / 5120.0; + + + return temperature; +} +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns pressure in Pa as double. + * @note Output value of "96386.2" + * equals 96386.2 Pa = 963.862 hPa. + * + * + * @param v_uncom_pressure_s32 : value of uncompensated pressure + * + * + * @return Return the actual pressure in floating point + * +*/ +double bme280_compensate_pressure_double(s32 v_uncom_pressure_s32) +{ + double v_x1_u32 = BME280_INIT_VALUE; + double v_x2_u32 = BME280_INIT_VALUE; + double pressure = BME280_INIT_VALUE; + + v_x1_u32 = ((double)p_bme280->cal_param.t_fine / + 2.0) - 64000.0; + v_x2_u32 = v_x1_u32 * v_x1_u32 * + ((double)p_bme280->cal_param.dig_P6) / 32768.0; + v_x2_u32 = v_x2_u32 + v_x1_u32 * + ((double)p_bme280->cal_param.dig_P5) * 2.0; + v_x2_u32 = (v_x2_u32 / 4.0) + + (((double)p_bme280->cal_param.dig_P4) * 65536.0); + v_x1_u32 = (((double)p_bme280->cal_param.dig_P3) * + v_x1_u32 * v_x1_u32 / 524288.0 + + ((double)p_bme280->cal_param.dig_P2) * v_x1_u32) / 524288.0; + v_x1_u32 = (1.0 + v_x1_u32 / 32768.0) * + ((double)p_bme280->cal_param.dig_P1); + pressure = 1048576.0 - (double)v_uncom_pressure_s32; + /* Avoid exception caused by division by zero */ + if (v_x1_u32 != BME280_INIT_VALUE) + pressure = (pressure - (v_x2_u32 / 4096.0)) * 6250.0 / v_x1_u32; + else + return BME280_INVALID_DATA; + v_x1_u32 = ((double)p_bme280->cal_param.dig_P9) * + pressure * pressure / 2147483648.0; + v_x2_u32 = pressure * ((double)p_bme280->cal_param.dig_P8) / 32768.0; + pressure = pressure + (v_x1_u32 + v_x2_u32 + + ((double)p_bme280->cal_param.dig_P7)) / 16.0; + + return pressure; +} +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note returns the value in relative humidity (%rH) + * @note Output value of "42.12" equals 42.12 %rH + * + * @param v_uncom_humidity_s32 : value of uncompensated humidity + * + * + * + * @return Return the actual humidity in floating point + * +*/ +double bme280_compensate_humidity_double(s32 v_uncom_humidity_s32) +{ + double var_h = BME280_INIT_VALUE; + + var_h = (((double)p_bme280->cal_param.t_fine) - 76800.0); + if (var_h != BME280_INIT_VALUE) + var_h = (v_uncom_humidity_s32 - + (((double)p_bme280->cal_param.dig_H4) * 64.0 + + ((double)p_bme280->cal_param.dig_H5) / 16384.0 * var_h))* + (((double)p_bme280->cal_param.dig_H2) / 65536.0 * + (1.0 + ((double) p_bme280->cal_param.dig_H6) + / 67108864.0 * var_h * (1.0 + ((double) + p_bme280->cal_param.dig_H3) / 67108864.0 * var_h))); + else + return BME280_INVALID_DATA; + var_h = var_h * (1.0 - ((double) + p_bme280->cal_param.dig_H1)*var_h / 524288.0); + if (var_h > 100.0) + var_h = 100.0; + else if (var_h < 0.0) + var_h = 0.0; + return var_h; + +} +#endif +#if defined(BME280_ENABLE_INT64) && defined(BME280_64BITSUPPORT_PRESENT) +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pa as unsigned 32 bit + * integer in Q24.8 format (24 integer bits and + * 8 fractional bits). + * @note Output value of "24674867" + * represents 24674867 / 256 = 96386.2 Pa = 963.862 hPa + * + * + * + * @param v_uncom_pressure_s32 : value of uncompensated temperature + * + * + * @return Return the actual pressure in u32 + * +*/ +u32 bme280_compensate_pressure_int64(s32 v_uncom_pressure_s32) +{ + s64 v_x1_s64r = BME280_INIT_VALUE; + s64 v_x2_s64r = BME280_INIT_VALUE; + s64 pressure = BME280_INIT_VALUE; + + v_x1_s64r = ((s64)p_bme280->cal_param.t_fine) + - 128000; + v_x2_s64r = v_x1_s64r * v_x1_s64r * + (s64)p_bme280->cal_param.dig_P6; + v_x2_s64r = v_x2_s64r + ((v_x1_s64r * + (s64)p_bme280->cal_param.dig_P5) + << BME280_SHIFT_BIT_POSITION_BY_17_BITS); + v_x2_s64r = v_x2_s64r + + (((s64)p_bme280->cal_param.dig_P4) + << BME280_SHIFT_BIT_POSITION_BY_35_BITS); + v_x1_s64r = ((v_x1_s64r * v_x1_s64r * + (s64)p_bme280->cal_param.dig_P3) + >> BME280_SHIFT_BIT_POSITION_BY_08_BITS) + + ((v_x1_s64r * (s64)p_bme280->cal_param.dig_P2) + << BME280_SHIFT_BIT_POSITION_BY_12_BITS); + v_x1_s64r = (((((s64)1) + << BME280_SHIFT_BIT_POSITION_BY_47_BITS) + v_x1_s64r)) * + ((s64)p_bme280->cal_param.dig_P1) + >> BME280_SHIFT_BIT_POSITION_BY_33_BITS; + pressure = 1048576 - v_uncom_pressure_s32; + /* Avoid exception caused by division by zero */ + if (v_x1_s64r != BME280_INIT_VALUE) + #if defined __KERNEL__ + pressure = div64_s64((((pressure + << BME280_SHIFT_BIT_POSITION_BY_31_BITS) - v_x2_s64r) + * 3125), v_x1_s64r); + #else + pressure = (((pressure + << BME280_SHIFT_BIT_POSITION_BY_31_BITS) - v_x2_s64r) + * 3125) / v_x1_s64r; + #endif + else + return BME280_INVALID_DATA; + v_x1_s64r = (((s64)p_bme280->cal_param.dig_P9) * + (pressure >> BME280_SHIFT_BIT_POSITION_BY_13_BITS) * + (pressure >> BME280_SHIFT_BIT_POSITION_BY_13_BITS)) + >> BME280_SHIFT_BIT_POSITION_BY_25_BITS; + v_x2_s64r = (((s64)p_bme280->cal_param.dig_P8) * + pressure) >> BME280_SHIFT_BIT_POSITION_BY_19_BITS; + pressure = (((pressure + v_x1_s64r + + v_x2_s64r) >> BME280_SHIFT_BIT_POSITION_BY_08_BITS) + + (((s64)p_bme280->cal_param.dig_P7) + << BME280_SHIFT_BIT_POSITION_BY_04_BITS)); + + return (u32)pressure; +} +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pa. + * @note Output value of "12337434" + * @note represents 12337434 / 128 = 96386.2 Pa = 963.862 hPa + * + * + * + * @param v_uncom_pressure_s32 : value of uncompensated pressure + * + * + * @return the actual pressure in u32 + * +*/ +u32 bme280_compensate_pressure_int64_twentyfour_bit_output( +s32 v_uncom_pressure_s32) +{ + u32 pressure = BME280_INIT_VALUE; + + pressure = bme280_compensate_pressure_int64( + v_uncom_pressure_s32); + pressure = (u32)(pressure >> BME280_SHIFT_BIT_POSITION_BY_01_BIT); + return pressure; +} +#endif +/*! + * @brief Computing waiting time for sensor data read + * + * + * + * + * @param v_delaytime_u8 : The value of delay time for force mode + * + * + * @retval 0 -> Success + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_compute_wait_time(u8 +*v_delaytime_u8) +{ + /* used to return the communication result*/ + BME280_RETURN_FUNCTION_TYPE com_rslt = SUCCESS; + + *v_delaytime_u8 = (T_INIT_MAX + + T_MEASURE_PER_OSRS_MAX * + (((1 << + p_bme280->oversamp_temperature) + >> BME280_SHIFT_BIT_POSITION_BY_01_BIT) + + ((1 << p_bme280->oversamp_pressure) + >> BME280_SHIFT_BIT_POSITION_BY_01_BIT) + + ((1 << p_bme280->oversamp_humidity) + >> BME280_SHIFT_BIT_POSITION_BY_01_BIT)) + + (p_bme280->oversamp_pressure ? + T_SETUP_PRESSURE_MAX : 0) + + (p_bme280->oversamp_humidity ? + T_SETUP_HUMIDITY_MAX : 0) + 15) / 16; + return com_rslt; +} diff --git a/app/src/main/jni/bme280.h b/app/src/main/jni/bme280.h new file mode 100644 index 0000000..49817ab --- /dev/null +++ b/app/src/main/jni/bme280.h @@ -0,0 +1,1704 @@ +/** \mainpage +* +**************************************************************************** +* Copyright (C) 2013 - 2015 Bosch Sensortec GmbH +* +* File : bme280.h +* +* Date : 2015/03/27 +* +* Revision : 2.0.4(Pressure and Temperature compensation code revision is 1.1 +* and Humidity compensation code revision is 1.0) +* +* Usage: Sensor Driver for BME280 sensor +* +**************************************************************************** +* +* \section License +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of the +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +* OR CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE +* +* The information provided is believed to be accurate and reliable. +* The copyright holder assumes no responsibility +* for the consequences of use +* of such information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of the copyright holder. +**************************************************************************/ +/*! \file bme280.h + \brief BME280 Sensor Driver Support Header File */ +#ifndef __BME280_H__ +#define __BME280_H__ + + +/*! +* @brief The following definition uses for define the data types +* +* @note While porting the API please consider the following +* @note Please check the version of C standard +* @note Are you using Linux platform +*/ + +/*! +* @brief For the Linux platform support +* Please use the types.h for your data types definitions +*/ +#ifdef __KERNEL__ + +#include +#include +#define BME280_64BITSUPPORT_PRESENT +/* singed integer type*/ +typedef int8_t s8;/**< used for signed 8bit */ +typedef int16_t s16;/**< used for signed 16bit */ +typedef int32_t s32;/**< used for signed 32bit */ +typedef int64_t s64;/**< used for signed 64bit */ + +typedef u_int8_t u8;/**< used for unsigned 8bit */ +typedef u_int16_t u16;/**< used for unsigned 16bit */ +typedef u_int32_t u32;/**< used for unsigned 32bit */ +typedef u_int64_t u64;/**< used for unsigned 64bit */ + + + +#else /* ! __KERNEL__ */ +/********************************************************** +* These definition uses for define the C +* standard version data types +***********************************************************/ +# if !defined(__STDC_VERSION__) + +/************************************************ + * compiler is C11 C standard +************************************************/ +#if (__STDC_VERSION__ == 201112L) + +/************************************************/ +#include +/************************************************/ + +/*unsigned integer types*/ +typedef uint8_t u8;/**< used for unsigned 8bit */ +typedef uint16_t u16;/**< used for unsigned 16bit */ +typedef uint32_t u32;/**< used for unsigned 32bit */ +typedef uint64_t u64;/**< used for unsigned 64bit */ + +/*signed integer types*/ +typedef int8_t s8;/**< used for signed 8bit */ +typedef int16_t s16;/**< used for signed 16bit */ +typedef int32_t s32;/**< used for signed 32bit */ +typedef int64_t s64;/**< used for signed 64bit */ +#define BME280_64BITSUPPORT_PRESENT +/************************************************ + * compiler is C99 C standard +************************************************/ + +#elif (__STDC_VERSION__ == 199901L) + +/* stdint.h is a C99 supported c library. +which is used to fixed the integer size*/ +/************************************************/ +#include +/************************************************/ + +/*unsigned integer types*/ +typedef uint8_t u8;/**< used for unsigned 8bit */ +typedef uint16_t u16;/**< used for unsigned 16bit */ +typedef uint32_t u32;/**< used for unsigned 32bit */ +typedef uint64_t u64;/**< used for unsigned 64bit */ + +/*signed integer types*/ +typedef int8_t s8;/**< used for signed 8bit */ +typedef int16_t s16;/**< used for signed 16bit */ +typedef int32_t s32;/**< used for signed 32bit */ +typedef int64_t s64;/**< used for signed 64bit */ +#define BME280_64BITSUPPORT_PRESENT +/************************************************ + * compiler is C89 or other C standard +************************************************/ + +#else /* !defined(__STDC_VERSION__) */ +/*! +* @brief By default it is defined as 32 bit machine configuration +* define your data types based on your +* machine/compiler/controller configuration +*/ +#define MACHINE_32_BIT + +/*! @brief + * If your machine support 16 bit + * define the MACHINE_16_BIT + */ +#ifdef MACHINE_16_BIT +#include +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed long int s32;/**< used for signed 32bit */ + +#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL +typedef long int s64;/**< used for signed 64bit */ +typedef unsigned long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT +#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL) +typedef long long int s64;/**< used for signed 64bit */ +typedef unsigned long long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT +#else +#warning Either the correct data type for signed 64 bit integer \ +could not be found, or 64 bit integers are not supported in your environment. +#warning The API will only offer 32 bit pressure calculation.This will \ +slightly impede accuracy(noise of ~1 pascal RMS will be added to output). +#warning If 64 bit integers are supported on your platform, \ +please set s64 manually and "#define(BMPE80_64BITSUPPORT_PRESENT)" manually. +#endif + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned long int u32;/**< used for unsigned 32bit */ + +/* If your machine support 32 bit +define the MACHINE_32_BIT*/ +#elif defined MACHINE_32_BIT +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed int s32;/**< used for signed 32bit */ +typedef signed long long int s64;/**< used for signed 64bit */ + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned int u32;/**< used for unsigned 32bit */ +typedef unsigned long long int u64;/**< used for unsigned 64bit */ +/*! @brief + * If your machine support 64 bit + * define the MACHINE_64_BIT + */ +#define BME280_64BITSUPPORT_PRESENT + +/* If your machine support 64 bit +define the MACHINE_64_BIT*/ +#elif defined MACHINE_64_BIT +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed int s32;/**< used for signed 32bit */ +typedef signed long int s64;/**< used for signed 64bit */ + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned int u32;/**< used for unsigned 32bit */ +typedef unsigned long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT + +#else +#warning The data types defined above which not supported \ +define the data types manually +#endif +#endif + +/*** This else will execute for the compilers + * which are not supported the C standards + * Like C89/C99/C11***/ +#else +/*! +* @brief By default it is defined as 32 bit machine configuration +* define your data types based on your +* machine/compiler/controller configuration +*/ +#define MACHINE_32_BIT + +/* If your machine support 16 bit +define the MACHINE_16_BIT*/ +#ifdef MACHINE_16_BIT +#include +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed long int s32;/**< used for signed 32bit */ + +#if defined(LONG_MAX) && LONG_MAX == 0x7fffffffffffffffL +typedef long int s64;/**< used for signed 64bit */ +typedef unsigned long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT +#elif defined(LLONG_MAX) && (LLONG_MAX == 0x7fffffffffffffffLL) +typedef long long int s64;/**< used for signed 64bit */ +typedef unsigned long long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT +#else +#warning Either the correct data type for signed 64 bit integer \ +could not be found, or 64 bit integers are not supported in your environment. +#warning The API will only offer 32 bit pressure calculation.This will \ +slightly impede accuracy(noise of ~1 pascal RMS will be added to output). +#warning If 64 bit integers are supported on your platform, \ +please set s64 manually and "#define(BME280_64BITSUPPORT_PRESENT)" manually. +#endif + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned long int u32;/**< used for unsigned 32bit */ + +/*! @brief If your machine support 32 bit +define the MACHINE_32_BIT*/ +#elif defined MACHINE_32_BIT +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed int s32;/**< used for signed 32bit */ +typedef signed long long int s64;/**< used for signed 64bit */ + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned int u32;/**< used for unsigned 32bit */ +typedef unsigned long long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT + +/* If your machine support 64 bit +define the MACHINE_64_BIT*/ +#elif defined MACHINE_64_BIT +/*signed integer types*/ +typedef signed char s8;/**< used for signed 8bit */ +typedef signed short int s16;/**< used for signed 16bit */ +typedef signed int s32;/**< used for signed 32bit */ +typedef signed long int s64;/**< used for signed 64bit */ + +/*unsigned integer types*/ +typedef unsigned char u8;/**< used for unsigned 8bit */ +typedef unsigned short int u16;/**< used for unsigned 16bit */ +typedef unsigned int u32;/**< used for unsigned 32bit */ +typedef unsigned long int u64;/**< used for unsigned 64bit */ +#define BME280_64BITSUPPORT_PRESENT + +#else +#warning The data types defined above which not supported \ +define the data types manually +#endif +#endif +#endif +/********************************************/ +/**\name ENABLE FLATING OUTPUT */ +/**************************************/ +/*! +* @brief If the user wants to support floating point calculations, please set + the following define. If floating point + calculation is not wanted or allowed + (e.g. in Linux kernel), please do not set the define. */ +#define BME280_ENABLE_FLOAT +/*! +* @brief If the user wants to support 64 bit integer calculation + (needed for optimal pressure accuracy) please set + the following define. If int64 calculation is not wanted + (e.g. because it would include + large libraries), please do not set the define. */ +#define BME280_ENABLE_INT64 +/***************************************************************/ +/**\name BUS READ AND WRITE FUNCTION POINTERS */ +/***************************************************************/ +/*! + @brief Define the calling convention of YOUR bus communication routine. + @note This includes types of parameters. This example shows the + configuration for an SPI bus link. + + If your communication function looks like this: + + write_my_bus_xy(u8 device_addr, u8 register_addr, + u8 * data, u8 length); + + The BME280_WR_FUNC_PTR would equal: + + BME280_WR_FUNC_PTR s8 (* bus_write)(u8, + u8, u8 *, u8) + + Parameters can be mixed as needed refer to the + refer BME280_BUS_WRITE_FUNC macro. + + +*/ +/** defines the return parameter type of the BME280_WR_FUNCTION */ +#define BME280_BUS_WR_RETURN_TYPE s8 + +/* links the order of parameters defined in +BME280_BUS_WR_PARAM_TYPE to function calls used inside the API*/ +#define BME280_BUS_WR_PARAM_TYPES u8, u8,\ + u8 *, u8 + +/* links the order of parameters defined in +BME280_BUS_WR_PARAM_TYPE to function calls used inside the API*/ +#define BME280_BUS_WR_PARAM_ORDER(device_addr, register_addr,\ + register_data, wr_len) + +/* never change this line */ +#define BME280_BUS_WRITE_FUNC(device_addr, register_addr,\ +register_data, wr_len) bus_write(device_addr, register_addr,\ + register_data, wr_len) +/*! + @brief link macro between API function calls and bus read function + @note The bus write function can change since this is a + system dependant issue. + + If the bus_read parameter calling order is like: reg_addr, + reg_data, wr_len it would be as it is here. + + If the parameters are differently ordered or your communication + function like I2C need to know the device address, + you can change this macro accordingly. + + + BME280_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, wr_len)\ + bus_read(dev_addr, reg_addr, reg_data, wr_len) + + This macro lets all API functions call YOUR communication routine in a + way that equals your definition in the + refer BME280_WR_FUNC_PTR definition. + + @note: this macro also includes the "MSB='1' + for reading BME280 addresses. + +*/ +/*defines the return parameter type of the BME280_RD_FUNCTION +*/ +#define BME280_BUS_RD_RETURN_TYPE s8 + +/**\brief defines the calling parameter types of the BME280_RD_FUNCTION +*/ +#define BME280_BUS_RD_PARAM_TYPES (u8, u8,\ + u8 *, u8) + +/* links the order of parameters defined in \ +BME280_BUS_RD_PARAM_TYPE to function calls used inside the API +*/ +#define BME280_BUS_RD_PARAM_ORDER (device_addr, register_addr,\ + register_data) + +/* never change this line */ +#define BME280_BUS_READ_FUNC(device_addr, register_addr,\ + register_data, rd_len)bus_read(device_addr, register_addr,\ + register_data, rd_len) +/****************************************/ +/**\name DELAY */ +/****************************************/ +/* defines the return parameter type of the BME280_DELAY_FUNCTION +*/ +#define BME280_DELAY_RETURN_TYPE void + +/* defines the calling parameter types of the BME280_DELAY_FUNCTION +*/ +#define BME280_DELAY_PARAM_TYPES u16 +/***************************************************************/ +/**\name GET AND SET BITSLICE FUNCTIONS */ +/***************************************************************/ +/* never change this line */ +#define BME280_DELAY_FUNC(delay_in_msec)\ + delay_func(delay_in_msec) + +#define BME280_GET_BITSLICE(regvar, bitname)\ + ((regvar & bitname##__MSK) >> bitname##__POS) + +#define BME280_SET_BITSLICE(regvar, bitname, val)\ +((regvar & ~bitname##__MSK) | ((val< Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_init(struct bme280_t *bme280); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION UNCOMPENSATED TEMPERATURE */ +/**************************************************************/ +/*! + * @brief This API is used to read uncompensated temperature + * in the registers 0xFA, 0xFB and 0xFC + * @note 0xFA -> MSB -> bit from 0 to 7 + * @note 0xFB -> LSB -> bit from 0 to 7 + * @note 0xFC -> LSB -> bit from 4 to 7 + * + * @param v_uncomp_temperature_s32 : The value of uncompensated temperature + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_temperature( +s32 *v_uncomp_temperature_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION TRUE TEMPERATURE */ +/**************************************************************/ +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note Returns the value in 0.01 degree Centigrade + * Output value of "5123" equals 51.23 DegC. + * + * + * + * @param v_uncomp_temperature_s32 : value of uncompensated temperature + * + * + * @return Returns the actual temperature + * +*/ +s32 bme280_compensate_temperature_int32(s32 v_uncomp_temperature_s32); +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note Returns the value with 500LSB/DegC centred around 24 DegC + * output value of "5123" equals(5123/500)+24 = 34.246DegC + * + * + * @param v_uncomp_temperature_s32: value of uncompensated temperature + * + * + * + * @return Return the actual temperature as s16 output + * +*/ +s16 bme280_compensate_temperature_int32_sixteen_bit_output( +s32 v_uncomp_temperature_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION UNCOMPENSATED PRESSURE */ +/**************************************************************/ +/*! + * @brief This API is used to read uncompensated pressure. + * in the registers 0xF7, 0xF8 and 0xF9 + * @note 0xF7 -> MSB -> bit from 0 to 7 + * @note 0xF8 -> LSB -> bit from 0 to 7 + * @note 0xF9 -> LSB -> bit from 4 to 7 + * + * + * + * @param v_uncomp_pressure_s32 : The value of uncompensated pressure + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_pressure( +s32 *v_uncomp_pressure_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION TRUE PRESSURE */ +/**************************************************************/ +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pascal(Pa) + * Output value of "96386" equals 96386 Pa = + * 963.86 hPa = 963.86 millibar + * + * + * + * @param v_uncomp_pressure_s32 : value of uncompensated pressure + * + * + * + * @return Return the actual pressure output as u32 + * +*/ +u32 bme280_compensate_pressure_int32(s32 v_uncomp_pressure_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION UNCOMPENSATED HUMIDITY */ +/**************************************************************/ +/*! + * @brief This API is used to read uncompensated humidity. + * in the registers 0xF7, 0xF8 and 0xF9 + * @note 0xFD -> MSB -> bit from 0 to 7 + * @note 0xFE -> LSB -> bit from 0 to 7 + * + * + * + * @param v_uncomp_humidity_s32 : The value of uncompensated humidity + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_humidity( +s32 *v_uncomp_humidity_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION RELATIVE HUMIDITY */ +/**************************************************************/ +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note Returns the value in %rH as unsigned 32bit integer + * in Q22.10 format(22 integer 10 fractional bits). + * @note An output value of 42313 + * represents 42313 / 1024 = 41.321 %rH + * + * + * + * @param v_uncomp_humidity_s32: value of uncompensated humidity + * + * @return Return the actual relative humidity output as u32 + * +*/ +u32 bme280_compensate_humidity_int32(s32 v_uncomp_humidity_s32); +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note Returns the value in %rH as unsigned 16bit integer + * @note An output value of 42313 + * represents 42313/512 = 82.643 %rH + * + * + * + * @param v_uncomp_humidity_s32: value of uncompensated humidity + * + * + * @return Return the actual relative humidity output as u16 + * +*/ +u16 bme280_compensate_humidity_int32_sixteen_bit_output( +s32 v_uncomp_humidity_s32); +/**************************************************************/ +/**\name FUNCTION FOR INTIALIZATION UNCOMPENSATED PRESSURE, + TEMPERATURE AND HUMIDITY */ +/**************************************************************/ +/*! + * @brief This API used to read uncompensated + * pressure,temperature and humidity + * + * + * + * + * @param v_uncomp_pressure_s32: The value of uncompensated pressure. + * @param v_uncomp_temperature_s32: The value of uncompensated temperature + * @param v_uncomp_humidity_s32: The value of uncompensated humidity. + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_uncomp_pressure_temperature_humidity( +s32 *v_uncomp_pressure_s32, +s32 *v_uncomp_temperature_s32, s32 *v_uncomp_humidity_s32); +/**************************************************************/ +/**\name FUNCTION FOR TRUE UNCOMPENSATED PRESSURE, + TEMPERATURE AND HUMIDITY */ +/**************************************************************/ +/*! + * @brief This API used to read true pressure, temperature and humidity + * + * + * + * + * @param v_pressure_u32 : The value of compensated pressure. + * @param v_temperature_s32 : The value of compensated temperature. + * @param v_humidity_u32 : The value of compensated humidity. + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_read_pressure_temperature_humidity( +u32 *v_pressure_u32, s32 *v_temperature_s32, u32 *v_humidity_u32); +/**************************************************************/ +/**\name FUNCTION FOR CALIBRATION */ +/**************************************************************/ +/*! + * @brief This API is used to + * calibration parameters used for calculation in the registers + * + * parameter | Register address | bit + *------------|------------------|---------------- + * dig_T1 | 0x88 and 0x89 | from 0 : 7 to 8: 15 + * dig_T2 | 0x8A and 0x8B | from 0 : 7 to 8: 15 + * dig_T3 | 0x8C and 0x8D | from 0 : 7 to 8: 15 + * dig_P1 | 0x8E and 0x8F | from 0 : 7 to 8: 15 + * dig_P2 | 0x90 and 0x91 | from 0 : 7 to 8: 15 + * dig_P3 | 0x92 and 0x93 | from 0 : 7 to 8: 15 + * dig_P4 | 0x94 and 0x95 | from 0 : 7 to 8: 15 + * dig_P5 | 0x96 and 0x97 | from 0 : 7 to 8: 15 + * dig_P6 | 0x98 and 0x99 | from 0 : 7 to 8: 15 + * dig_P7 | 0x9A and 0x9B | from 0 : 7 to 8: 15 + * dig_P8 | 0x9C and 0x9D | from 0 : 7 to 8: 15 + * dig_P9 | 0x9E and 0x9F | from 0 : 7 to 8: 15 + * dig_H1 | 0xA1 | from 0 to 7 + * dig_H2 | 0xE1 and 0xE2 | from 0 : 7 to 8: 15 + * dig_H3 | 0xE3 | from 0 to 7 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_calib_param(void); +/**************************************************************/ +/**\name FUNCTION FOR TEMPERATURE OVER SAMPLING */ +/**************************************************************/ +/*! + * @brief This API is used to get + * the temperature oversampling setting in the register 0xF4 + * bits from 5 to 7 + * + * value | Temperature oversampling + * ---------------------|--------------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of temperature over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_temperature( +u8 *v_value_u8); +/*! + * @brief This API is used to set + * the temperature oversampling setting in the register 0xF4 + * bits from 5 to 7 + * + * value | Temperature oversampling + * ---------------------|--------------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of temperature over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_temperature( +u8 v_value_u8); +/**************************************************************/ +/**\name FUNCTION FOR PRESSURE OVER SAMPLING */ +/**************************************************************/ +/*! + * @brief This API is used to get + * the pressure oversampling setting in the register 0xF4 + * bits from 2 to 4 + * + * value | Pressure oversampling + * --------------------|-------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of pressure oversampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_pressure( +u8 *v_value_u8); +/*! + * @brief This API is used to set + * the pressure oversampling setting in the register 0xF4 + * bits from 2 to 4 + * + * value | Pressure oversampling + * --------------------|-------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of pressure oversampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_pressure( +u8 v_value_u8); +/**************************************************************/ +/**\name FUNCTION FOR HUMIDITY OVER SAMPLING */ +/**************************************************************/ +/*! + * @brief This API is used to get + * the humidity oversampling setting in the register 0xF2 + * bits from 0 to 2 + * + * value | Humidity oversampling + * ---------------------|------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of humidity over sampling + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_oversamp_humidity(u8 *v_value_u8); +/*! + * @brief This API is used to set + * the humidity oversampling setting in the register 0xF2 + * bits from 0 to 2 + * + * value | Humidity oversampling + * ---------------------|------------------------- + * 0x00 | Skipped + * 0x01 | BME280_OVERSAMP_1X + * 0x02 | BME280_OVERSAMP_2X + * 0x03 | BME280_OVERSAMP_4X + * 0x04 | BME280_OVERSAMP_8X + * 0x05,0x06 and 0x07 | BME280_OVERSAMP_16X + * + * + * @param v_value_u8 : The value of humidity over sampling + * + * + * + * @note The "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * register sets the humidity + * data acquisition options of the device. + * @note changes to this registers only become + * effective after a write operation to + * "BME280_CTRL_MEAS_REG" register. + * @note In the code automated reading and writing of + * "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * @note register first set the + * "BME280_CTRL_HUMIDITY_REG_OVERSAMP_HUMIDITY" + * and then read and write + * the "BME280_CTRL_MEAS_REG" register in the function. + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_oversamp_humidity( +u8 v_value_u8); +/**************************************************************/ +/**\name FUNCTION FOR POWER MODE*/ +/**************************************************************/ +/*! + * @brief This API used to get the + * Operational Mode from the sensor in the register 0xF4 bit 0 and 1 + * + * + * + * @param v_power_mode_u8 : The value of power mode + * value | mode + * -----------------|------------------ + * 0x00 | BME280_SLEEP_MODE + * 0x01 and 0x02 | BME280_FORCED_MODE + * 0x03 | BME280_NORMAL_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_power_mode(u8 *v_power_mode_u8); +/*! + * @brief This API used to set the + * Operational Mode from the sensor in the register 0xF4 bit 0 and 1 + * + * + * + * @param v_power_mode_u8 : The value of power mode + * value | mode + * -----------------|------------------ + * 0x00 | BME280_SLEEP_MODE + * 0x01 and 0x02 | BME280_FORCED_MODE + * 0x03 | BME280_NORMAL_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_power_mode(u8 v_power_mode_u8); +/**************************************************************/ +/**\name FUNCTION FOR SOFT RESET*/ +/**************************************************************/ +/*! + * @brief Used to reset the sensor + * The value 0xB6 is written to the 0xE0 + * register the device is reset using the + * complete power-on-reset procedure. + * @note Soft reset can be easily set using bme280_set_softreset(). + * @note Usage Hint : bme280_set_softreset() + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_soft_rst(void); +/**************************************************************/ +/**\name FUNCTION FOR SPI ENABLE*/ +/**************************************************************/ +/*! + * @brief This API used to get the sensor + * SPI mode(communication type) in the register 0xF5 bit 0 + * + * + * + * @param v_enable_disable_u8 : The value of SPI enable + * value | Description + * --------|-------------- + * 0 | Disable + * 1 | Enable + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_spi3(u8 *v_enable_disable_u8); +/*! + * @brief This API used to set the sensor + * SPI mode(communication type) in the register 0xF5 bit 0 + * + * + * + * @param v_enable_disable_u8 : The value of SPI enable + * value | Description + * --------|-------------- + * 0 | Disable + * 1 | Enable + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_spi3(u8 v_enable_disable_u8); +/**************************************************************/ +/**\name FUNCTION FOR IIR FILTER*/ +/**************************************************************/ +/*! + * @brief This API is used to reads filter setting + * in the register 0xF5 bit 3 and 4 + * + * + * + * @param v_value_u8 : The value of IIR filter coefficient + * + * value | Filter coefficient + * -------------|------------------------- + * 0x00 | BME280_FILTER_COEFF_OFF + * 0x01 | BME280_FILTER_COEFF_2 + * 0x02 | BME280_FILTER_COEFF_4 + * 0x03 | BME280_FILTER_COEFF_8 + * 0x04 | BME280_FILTER_COEFF_16 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_filter(u8 *v_value_u8); +/*! + * @brief This API is used to write filter setting + * in the register 0xF5 bit 3 and 4 + * + * + * + * @param v_value_u8 : The value of IIR filter coefficient + * + * value | Filter coefficient + * -------------|------------------------- + * 0x00 | BME280_FILTER_COEFF_OFF + * 0x01 | BME280_FILTER_COEFF_2 + * 0x02 | BME280_FILTER_COEFF_4 + * 0x03 | BME280_FILTER_COEFF_8 + * 0x04 | BME280_FILTER_COEFF_16 + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_filter(u8 v_value_u8); +/**************************************************************/ +/**\name FUNCTION FOR STANDBY DURATION*/ +/**************************************************************/ +/*! + * @brief This API used to Read the + * standby duration time from the sensor in the register 0xF5 bit 5 to 7 + * + * @param v_standby_durn_u8 : The value of standby duration time value. + * value | standby duration + * -------------|----------------------- + * 0x00 | BME280_STANDBY_TIME_1_MS + * 0x01 | BME280_STANDBY_TIME_63_MS + * 0x02 | BME280_STANDBY_TIME_125_MS + * 0x03 | BME280_STANDBY_TIME_250_MS + * 0x04 | BME280_STANDBY_TIME_500_MS + * 0x05 | BME280_STANDBY_TIME_1000_MS + * 0x06 | BME280_STANDBY_TIME_2000_MS + * 0x07 | BME280_STANDBY_TIME_4000_MS + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_get_standby_durn(u8 *v_standby_durn_u8); +/*! + * @brief This API used to write the + * standby duration time from the sensor in the register 0xF5 bit 5 to 7 + * + * @param v_standby_durn_u8 : The value of standby duration time value. + * value | standby duration + * -------------|----------------------- + * 0x00 | BME280_STANDBY_TIME_1_MS + * 0x01 | BME280_STANDBY_TIME_63_MS + * 0x02 | BME280_STANDBY_TIME_125_MS + * 0x03 | BME280_STANDBY_TIME_250_MS + * 0x04 | BME280_STANDBY_TIME_500_MS + * 0x05 | BME280_STANDBY_TIME_1000_MS + * 0x06 | BME280_STANDBY_TIME_2000_MS + * 0x07 | BME280_STANDBY_TIME_4000_MS + * + * @note Normal mode comprises an automated perpetual + * cycling between an (active) + * Measurement period and an (inactive) standby period. + * @note The standby time is determined by + * the contents of the register t_sb. + * Standby time can be set using BME280_STANDBY_TIME_125_MS. + * + * @note Usage Hint : bme280_set_standby_durn(BME280_STANDBY_TIME_125_MS) + * + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE bme280_set_standby_durn(u8 v_standby_durn_u8); +/**************************************************************/ +/**\name FUNCTION FOR WORK MODE*/ +/**************************************************************/ +/* + * @brief Writes the working mode to the sensor + * + * + * + * + * @param v_work_mode_u8 : Mode to be set + * value | Working mode + * ----------|-------------------- + * 0 | BME280_ULTRALOWPOWER_MODE + * 1 | BME280_LOWPOWER_MODE + * 2 | BME280_STANDARDRESOLUTION_MODE + * 3 | BME280_HIGHRESOLUTION_MODE + * 4 | BME280_ULTRAHIGHRESOLUTION_MODE + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +/*BME280_RETURN_FUNCTION_TYPE bme280_set_work_mode(u8 v_work_mode_u8);*/ +/**************************************************************/ +/**\name FUNCTION FOR FORCE MODE DATA READ*/ +/**************************************************************/ +/*! + * @brief This API used to read uncompensated + * temperature,pressure and humidity in forced mode + * + * + * @param v_uncom_pressure_s32: The value of uncompensated pressure + * @param v_uncom_temperature_s32: The value of uncompensated temperature + * @param v_uncom_humidity_s32: The value of uncompensated humidity + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * +*/ +BME280_RETURN_FUNCTION_TYPE +bme280_get_forced_uncomp_pressure_temperature_humidity( +s32 *v_uncom_pressure_s32, +s32 *v_uncom_temperature_s32, s32 *v_uncom_humidity_s32); +/**************************************************************/ +/**\name FUNCTION FOR COMMON READ AND WRITE */ +/**************************************************************/ +/*! + * @brief + * This API write the data to + * the given register + * + * + * @param v_addr_u8 -> Address of the register + * @param v_data_u8 -> The data from the register + * @param v_len_u8 -> no of bytes to read + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_write_register(u8 v_addr_u8, +u8 *v_data_u8, u8 v_len_u8); +/*! + * @brief + * This API reads the data from + * the given register + * + * + * @param v_addr_u8 -> Address of the register + * @param v_data_u8 -> The data from the register + * @param v_len_u8 -> no of bytes to read + * + * + * @return results of bus communication function + * @retval 0 -> Success + * @retval -1 -> Error + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_read_register(u8 v_addr_u8, +u8 *v_data_u8, u8 v_len_u8); +/**************************************************************/ +/**\name FUNCTION FOR FLOAT OUTPUT TEMPERATURE*/ +/**************************************************************/ +#ifdef BME280_ENABLE_FLOAT +/*! + * @brief Reads actual temperature from uncompensated temperature + * @note returns the value in Degree centigrade + * @note Output value of "51.23" equals 51.23 DegC. + * + * + * + * @param v_uncom_temperature_s32 : value of uncompensated temperature + * + * + * + * @return Return the actual temperature in floating point + * +*/ +double bme280_compensate_temperature_double( +s32 v_uncom_temperature_s32); +/**************************************************************/ +/**\name FUNCTION FOR FLOAT OUTPUT PRESSURE*/ +/**************************************************************/ +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns pressure in Pa as double. + * @note Output value of "96386.2" + * equals 96386.2 Pa = 963.862 hPa. + * + * + * @param v_uncom_pressure_s32 : value of uncompensated pressure + * + * + * @return Return the actual pressure in floating point + * +*/ +double bme280_compensate_pressure_double(s32 v_uncom_pressure_s32); +/**************************************************************/ +/**\name FUNCTION FOR FLOAT OUTPUT HUMIDITY*/ +/**************************************************************/ +/*! + * @brief Reads actual humidity from uncompensated humidity + * @note returns the value in relative humidity (%rH) + * @note Output value of "42.12" equals 42.12 %rH + * + * @param v_uncom_humidity_s32 : value of uncompensated humidity + * + * + * + * @return Return the actual humidity in floating point + * +*/ +double bme280_compensate_humidity_double(s32 v_uncom_humidity_s32); +#endif +/**************************************************************/ +/**\name FUNCTION FOR 64BIT OUTPUT PRESSURE*/ +/**************************************************************/ +#if defined(BME280_ENABLE_INT64) && defined(BME280_64BITSUPPORT_PRESENT) +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pa as unsigned 32 bit + * integer in Q24.8 format (24 integer bits and + * 8 fractional bits). + * @note Output value of "24674867" + * represents 24674867 / 256 = 96386.2 Pa = 963.862 hPa + * + * + * + * @param v_uncom_pressure_s32 : value of uncompensated temperature + * + * + * @return Return the actual pressure in u32 + * +*/ +u32 bme280_compensate_pressure_int64(s32 v_uncom_pressure_s32); +/**************************************************************/ +/**\name FUNCTION FOR 24BIT OUTPUT PRESSURE*/ +/**************************************************************/ +/*! + * @brief Reads actual pressure from uncompensated pressure + * @note Returns the value in Pa. + * @note Output value of "12337434" + * @note represents 12337434 / 128 = 96386.2 Pa = 963.862 hPa + * + * + * + * @param v_uncom_pressure_s32 : value of uncompensated pressure + * + * + * @return the actual pressure in u32 + * +*/ +u32 bme280_compensate_pressure_int64_twentyfour_bit_output( +s32 v_uncom_pressure_s32); +#endif +/**************************************************************/ +/**\name FUNCTION FOR WAIT PERIOD*/ +/**************************************************************/ +/*! + * @brief Computing waiting time for sensor data read + * + * + * + * + * @param v_delaytime_u8 : The value of delay time for force mode + * + * + * @retval 0 -> Success + * + * + */ +BME280_RETURN_FUNCTION_TYPE bme280_compute_wait_time(u8 +*v_delaytime_u8r); +#endif diff --git a/app/src/main/jni/si1132.c b/app/src/main/jni/si1132.c new file mode 100644 index 0000000..2099c7e --- /dev/null +++ b/app/src/main/jni/si1132.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include "si1132.h" + +int si1132_begin(const char *device) +{ + int status = 0; + si1132Fd = -1; + + si1132Fd = open(device, O_RDWR); + if (si1132Fd < 0) { + printf("ERROR: si1132 open failed\n"); + return -1; + } + + status = ioctl(si1132Fd, I2C_SLAVE, Si1132_ADDR); + if (status < 0) { + printf("ERROR: si1132 ioctl error\n"); + close(si1132Fd); + return -1; + } + + if (Si1132_I2C_read8(Si1132_REG_PARTID) != 0x32) { + printf("ERROR: si1132 read failed the PART ID\n"); + return -1; + } + + initialize(); + + return si1132Fd; +} + +void si1132_end() { + if (si1132Fd) + close(si1132Fd); +} + +void initialize(void) +{ + reset(); + + Si1132_I2C_write8(Si1132_REG_UCOEF0, 0x7B); + Si1132_I2C_write8(Si1132_REG_UCOEF1, 0x6B); + Si1132_I2C_write8(Si1132_REG_UCOEF2, 0x01); + Si1132_I2C_write8(Si1132_REG_UCOEF3, 0x00); + + Si1132_I2C_writeParam(Si1132_PARAM_CHLIST, Si1132_PARAM_CHLIST_ENUV | + Si1132_PARAM_CHLIST_ENALSIR | Si1132_PARAM_CHLIST_ENALSVIS); + Si1132_I2C_write8(Si1132_REG_INTCFG, Si1132_REG_INTCFG_INTOE); + Si1132_I2C_write8(Si1132_REG_IRQEN, Si1132_REG_IRQEN_ALSEVERYSAMPLE); + + Si1132_I2C_writeParam(Si1132_PARAM_ALSIRADCMUX, Si1132_PARAM_ADCMUX_SMALLIR); + usleep(10000); + // fastest clocks, clock div 1 + Si1132_I2C_writeParam(Si1132_PARAM_ALSIRADCGAIN, 0); + usleep(10000); + // take 511 clocks to measure + Si1132_I2C_writeParam(Si1132_PARAM_ALSIRADCCOUNTER, Si1132_PARAM_ADCCOUNTER_511CLK); + // in high range mode + Si1132_I2C_writeParam(Si1132_PARAM_ALSIRADCMISC, Si1132_PARAM_ALSIRADCMISC_RANGE); + usleep(10000); + // fastest clocks + Si1132_I2C_writeParam(Si1132_PARAM_ALSVISADCGAIN, 0); + usleep(10000); + // take 511 clocks to measure + Si1132_I2C_writeParam(Si1132_PARAM_ALSVISADCCOUNTER, Si1132_PARAM_ADCCOUNTER_511CLK); + //in high range mode (not normal signal) + Si1132_I2C_writeParam(Si1132_PARAM_ALSVISADCMISC, Si1132_PARAM_ALSVISADCMISC_VISRANGE); + usleep(10000); + + Si1132_I2C_write8(Si1132_REG_MEASRATE0, 0xFF); + Si1132_I2C_write8(Si1132_REG_COMMAND, Si1132_ALS_AUTO); +} + +void reset() +{ + Si1132_I2C_write8(Si1132_REG_MEASRATE0, 0); + Si1132_I2C_write8(Si1132_REG_MEASRATE1, 0); + Si1132_I2C_write8(Si1132_REG_IRQEN, 0); + Si1132_I2C_write8(Si1132_REG_IRQMODE1, 0); + Si1132_I2C_write8(Si1132_REG_IRQMODE2, 0); + Si1132_I2C_write8(Si1132_REG_INTCFG, 0); + Si1132_I2C_write8(Si1132_REG_IRQSTAT, 0xFF); + + Si1132_I2C_write8(Si1132_REG_COMMAND, Si1132_RESET); + usleep(10000); + Si1132_I2C_write8(Si1132_REG_HWKEY, 0x17); + + usleep(10000); +} + +void Si1132_readVisible(float *result) +{ + usleep(10000); + *result = ((Si1132_I2C_read16(0x22) - 256) / 0.282) * 14.5; +} + +void Si1132_readIR(float *result) +{ + usleep(10000); + *result = ((Si1132_I2C_read16(0x24) - 250) / 2.44) * 14.5; +} + +void Si1132_readUV(int *result) +{ + usleep(10000); + *result = (int)Si1132_I2C_read16(0x2c); +} + +unsigned char Si1132_I2C_read8(unsigned char reg) +{ + unsigned char ret; + write(si1132Fd, ®, 1); + read(si1132Fd, &ret, 1); + return ret; +} + +unsigned short Si1132_I2C_read16(unsigned char reg) +{ + unsigned char rbuf[2]; + write(si1132Fd, ®, 1); + read(si1132Fd, rbuf, 2); + return (unsigned short)(rbuf[0] | rbuf[1] << 8); +} + +void Si1132_I2C_write8(unsigned char reg, unsigned char val) +{ + unsigned char wbuf[2]; + wbuf[0] = reg; + wbuf[1] = val; + write(si1132Fd, wbuf, 2); +} + +void Si1132_I2C_writeParam(unsigned char param, unsigned char val) +{ + Si1132_I2C_write8(Si1132_REG_PARAMWR, val); + Si1132_I2C_write8(Si1132_REG_COMMAND, param | Si1132_PARAM_SET); +} diff --git a/app/src/main/jni/si1132.h b/app/src/main/jni/si1132.h new file mode 100644 index 0000000..ddeef2d --- /dev/null +++ b/app/src/main/jni/si1132.h @@ -0,0 +1,92 @@ +/* COMMANDS */ +#define Si1132_PARAM_QUERY 0x80 +#define Si1132_PARAM_SET 0xA0 +#define Si1132_NOP 0x00 +#define Si1132_RESET 0x01 +#define Si1132_BUSADDR 0x02 +#define Si1132_GET_CAL 0x12 +#define Si1132_ALS_FORCE 0x06 +#define Si1132_ALS_PAUSE 0x0A +#define Si1132_ALS_AUTO 0x0E + +/* Parameters */ +#define Si1132_PARAM_I2CADDR 0x00 +#define Si1132_PARAM_CHLIST 0x01 +#define Si1132_PARAM_CHLIST_ENUV 0x80 +#define Si1132_PARAM_CHLIST_ENAUX 0x40 +#define Si1132_PARAM_CHLIST_ENALSIR 0x20 +#define Si1132_PARAM_CHLIST_ENALSVIS 0x10 + +#define Si1132_PARAM_ALSENCODING 0x06 + +#define Si1132_PARAM_ALSIRADCMUX 0x0E +#define Si1132_PARAM_AUXADCMUX 0x0F + +#define Si1132_PARAM_ALSVISADCCOUNTER 0x10 +#define Si1132_PARAM_ALSVISADCGAIN 0x11 +#define Si1132_PARAM_ALSVISADCMISC 0x12 +#define Si1132_PARAM_ALSVISADCMISC_VISRANGE 0x20 + +#define Si1132_PARAM_ALSIRADCCOUNTER 0x1D +#define Si1132_PARAM_ALSIRADCGAIN 0x1E +#define Si1132_PARAM_ALSIRADCMISC 0x1F +#define Si1132_PARAM_ALSIRADCMISC_RANGE 0x20 + +#define Si1132_PARAM_ADCCOUNTER_511CLK 0x70 + +#define Si1132_PARAM_ADCMUX_SMALLIR 0x00 +#define Si1132_PARAM_ADCMUX_LARGEIR 0x03 + +/* REGISTERS */ +#define Si1132_REG_PARTID 0x00 +#define Si1132_REG_REVID 0x01 +#define Si1132_REG_SEQID 0x02 + +#define Si1132_REG_INTCFG 0x03 +#define Si1132_REG_INTCFG_INTOE 0x01 + +#define Si1132_REG_IRQEN 0x04 +#define Si1132_REG_IRQEN_ALSEVERYSAMPLE 0x01 + +#define Si1132_REG_IRQMODE1 0x05 +#define Si1132_REG_IRQMODE2 0x06 + +#define Si1132_REG_HWKEY 0x07 +#define Si1132_REG_MEASRATE0 0x08 +#define Si1132_REG_MEASRATE1 0x09 +#define Si1132_REG_UCOEF0 0x13 +#define Si1132_REG_UCOEF1 0x14 +#define Si1132_REG_UCOEF2 0x15 +#define Si1132_REG_UCOEF3 0x16 +#define Si1132_REG_PARAMWR 0x17 +#define Si1132_REG_COMMAND 0x18 +#define Si1132_REG_RESPONSE 0x20 +#define Si1132_REG_IRQSTAT 0x21 + +#define Si1132_REG_ALSVISDATA0 0x22 +#define Si1132_REG_ALSVISDATA1 0x23 +#define Si1132_REG_ALSIRDATA0 0x24 +#define Si1132_REG_ALSIRDATA1 0x25 +#define Si1132_REG_UVINDEX0 0x2C +#define Si1132_REG_UVINDEX1 0x2D +#define Si1132_REG_PARAMRD 0x2E +#define Si1132_REG_CHIPSTAT 0x30 + +#define Si1132_ADDR 0x60 + +int si1132Fd; + +int si1132_begin(const char *device); +void si1132_end(); +void initialize(void); +void reset(); + +void Si1132_readVisible(float *result); +void Si1132_readIR(float *result); +void Si1132_readUV(); + +unsigned char Si1132_I2C_read8(unsigned char reg); +unsigned short Si1132_I2C_read16(unsigned char reg); + +void Si1132_I2C_write8(unsigned char reg, unsigned char val); +void Si1132_I2C_writeParam(unsigned char param, unsigned char val); diff --git a/app/src/main/jni/weather.c b/app/src/main/jni/weather.c new file mode 100644 index 0000000..830b211 --- /dev/null +++ b/app/src/main/jni/weather.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include + +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +#define LOG_TAG "weather" + +#include +#include +#include + +#include +#include +#include + +int pressure; +int temperature; +int humidity; + +float SEALEVELPRESSURE_HPA = 1024.25; + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_openWeatherBoard(JNIEnv* env, jobject obj, jstring str) { + const char *i2c_dev = (*env)->GetStringUTFChars(env, str, 0); + int result = -1; + result = si1132_begin(i2c_dev); + if (result == -1) + return result; + result = bme280_begin(i2c_dev); + (*env)->ReleaseStringUTFChars(env, str, i2c_dev); + return result; +} + +void Java_com_hardkernel_odroid_weatherboard_MainActivity_closeWeatherBoard(JNIEnv* env, jobject obj) { + bme280_end(); + si1132_end(); +} + +void Java_com_hardkernel_odroid_weatherboard_MainActivity_bme280_end(JNIEnv* env, jobject obj) { + bme280_end(); +} + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_getUVindex(JNIEnv* env, jobject obj) { + int result = 0; + Si1132_readUV(&result); + return result; +} + +jfloat Java_com_hardkernel_odroid_weatherboard_MainActivity_getVisible(JNIEnv* env, jobject obj) { + float result = 0.0; + Si1132_readVisible(&result); + return result; +} + +jfloat Java_com_hardkernel_odroid_weatherboard_MainActivity_getIR(JNIEnv* env, jobject obj) { + float result = 0.0; + Si1132_readIR(&result); + return result; +} + +void Java_com_hardkernel_odroid_weatherboard_MainActivity_readyData(JNIEnv* env, jobject obj) { + bme280_read_pressure_temperature_humidity(&pressure, &temperature, &humidity); +} + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_getTemperature(JNIEnv* env, jobject obj) { + return temperature; +} + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_getPressure(JNIEnv* env, jobject obj) { + return pressure; +} + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_getHumidity(JNIEnv* env, jobject obj) { + return humidity; +} + +jint Java_com_hardkernel_odroid_weatherboard_MainActivity_getAltitude(JNIEnv* env, jobject obj) { + int result = 0; + bme280_readAltitude(pressure, &SEALEVELPRESSURE_HPA, &result); + return result; +} diff --git a/app/src/main/res/drawable-hdpi/ic_launcher.png b/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..288b66551d1efd1f13dd06f20a67534d2df57946 GIT binary patch literal 7658 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_launcher.png b/app/src/main/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d4fb7cd9d868f1d7d9964f1686dcbc018ef9495a GIT binary patch literal 12516 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..6f7e3a5 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml new file mode 100644 index 0000000..3416a3e --- /dev/null +++ b/app/src/main/res/menu/main.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/values-v11/styles.xml b/app/src/main/res/values-v11/styles.xml new file mode 100644 index 0000000..3c02242 --- /dev/null +++ b/app/src/main/res/values-v11/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/app/src/main/res/values-v14/styles.xml b/app/src/main/res/values-v14/styles.xml new file mode 100644 index 0000000..a91fd03 --- /dev/null +++ b/app/src/main/res/values-v14/styles.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/app/src/main/res/values-w820dp/dimens.xml b/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..f3e7020 --- /dev/null +++ b/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,10 @@ + + + + 64dp + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..55c1e59 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,7 @@ + + + + 16dp + 16dp + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..c277dbf --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,22 @@ + + + + WeatherBoard + Hello world! + Settings + + BME280 + SI1132 + Temperature + Pressure + UV index + Visible + IR + Humidity + °C + Altitude + /dev/i2c-1 + /dev/i2c-10 + /dev/i2c-3 + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..6ce89c7 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..19414bd --- /dev/null +++ b/build.gradle @@ -0,0 +1,17 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + google() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } +} + +allprojects { + repositories { + jcenter() + google() + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..f6b961fd5a86aa5fbfe90f707c3138408be7c718 GIT binary patch literal 54329 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

<5G2M1WZP5 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 F{|7XC?P&l2 literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9a4163a --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/import-summary.txt b/import-summary.txt new file mode 100644 index 0000000..dc15d1c --- /dev/null +++ b/import-summary.txt @@ -0,0 +1,43 @@ +ECLIPSE ANDROID PROJECT IMPORT SUMMARY +====================================== + +Ignored Files: +-------------- +The following files were *not* copied into the new Gradle project; you +should evaluate whether these are still needed in your project and if +so manually move them: + +* .idea\ +* .idea\codeStyles\ +* .idea\codeStyles\Project.xml +* .idea\modules.xml +* .idea\vcs.xml +* .idea\weatherboard.iml +* .idea\workspace.xml +* ic_launcher-web.png +* proguard-project.txt + +Moved Files: +------------ +Android Gradle projects use a different directory structure than ADT +Eclipse projects. Here's how the projects were restructured: + +* AndroidManifest.xml => app\src\main\AndroidManifest.xml +* jni\ => app\src\main\jni\ +* res\ => app\src\main\res\ +* src\ => app\src\main\java\ + +Next Steps: +----------- +You can now build the project. The Gradle project needs network +connectivity to download dependencies. + +Bugs: +----- +If for some reason your project does not build, and you determine that +it is due to a bug or limitation of the Eclipse to Gradle importer, +please file a bug at http://b.android.com with category +Component-Tools. + +(This import summary is for your information only, and can be deleted +after import once you are satisfied with the results.) diff --git a/local.properties b/local.properties new file mode 100644 index 0000000..ac3bbf9 --- /dev/null +++ b/local.properties @@ -0,0 +1,9 @@ +## This file must *NOT* be checked into Version Control Systems, +# as it contains information specific to your local configuration. +# +# Location of the SDK. This is only used by Gradle. +# For customization when using a Version Control System, please read the +# header note. +#Sun Mar 17 17:14:41 KST 2019 +ndk.dir=C\:\\Android\\sdk\\ndk-bundle +sdk.dir=C\:\\Android\\sdk diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..d3db109 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +include ':app'