qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

bme280.c (7452B)


      1 /* Copyright 2021 rate
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 2 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     15  */
     16 #include <stdint.h>
     17 #include "bme280.h"
     18 #include "i2c_master.h"
     19 
     20 #define BME280_ADDRESS (0x76<<1)
     21 
     22 #define BME280_REG_CALIB00   (0x88)
     23 #define BME280_REG_CALIB25   (0xA1)
     24 #define BME280_REG_CALIB26   (0xE1)
     25 #define BME280_REG_CTRL_HUM  (0xF2)
     26 #define BME280_REG_CTRL_MEAS (0xF4)
     27 #define BME280_REG_CONFIG    (0xF5)
     28 #define BME280_REG_PRESS_MSB (0xf7)
     29 
     30 #define I2C_BME280_TIMEOUT (20)
     31 
     32 /* BME280 configurator values */
     33 /* [2:0]         Humidity oversampling
     34  * 000           Skipped
     35  * 001           oversampling x1
     36  * 010           oversampling x2
     37  * 011           oversampling x4
     38  * 100           oversampling x8
     39  * 101,others    oversampling x16
     40  */
     41 #define BME280_CTRL_HUM_VAL (0x01)
     42 
     43 
     44 /* [7:5]         Pressure oversampling
     45  * 000           Skipped
     46  * 001           oversampling x1
     47  * 010           oversampling x2
     48  * 011           oversampling x4
     49  * 100           oversampling x8
     50  * 101,others    oversampling x16
     51  * [4:2]         Temperature oversampling
     52  * 000           Skipped
     53  * 001           oversampling x1
     54  * 010           oversampling x2
     55  * 011           oversampling x4
     56  * 100           oversampling x8
     57  * 101,others    oversampling x16
     58  * [1:0]         Mode
     59  * 00            Sleep mode
     60  * 11            Normal mode
     61  */
     62 #define BME280_CTRL_MEAS_VAL (0x27)
     63 
     64 /* [7:5]        t_standby[ms]
     65  * 000          0.5
     66  * 001          62.5
     67  * 010          125
     68  * 011          250
     69  * 100          500
     70  * 101          1000
     71  * 110          10
     72  * 111          20
     73  * [4:2]        Filter corefficient
     74  * 000          Filter off
     75  * 001          2
     76  * 010          4
     77  * 011          8
     78  * 100,others   16
     79  * [0]          SPI interface
     80  * 0            4-wire
     81  * 1            3-wire
     82  */
     83 #define BME280_CONFIG_VAL (0xA0)
     84 
     85 static void readTrim(void);
     86 static void readData(void);
     87 static int32_t calibration_T(int32_t adc_T);
     88 static uint32_t calibration_P(int32_t adc_P);
     89 static uint32_t calibration_H(int32_t adc_H);
     90 
     91 static uint32_t hum_raw,temp_raw,pres_raw;
     92 static uint16_t dig_T1;
     93 static int16_t dig_T2, dig_T3;
     94 static uint16_t dig_P1;
     95 static int16_t dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9;
     96 static uint8_t dig_H1, dig_H3;
     97 static int16_t dig_H2, dig_H4, dig_H5;
     98 static int8_t dig_H6;
     99 static int32_t t_fine;
    100 
    101 /* Private */
    102 static void readTrim(void) {
    103     uint8_t data[32];
    104 
    105     i2c_read_register(BME280_ADDRESS, BME280_REG_CALIB00, &data[0], 24, I2C_BME280_TIMEOUT);
    106     i2c_read_register(BME280_ADDRESS, BME280_REG_CALIB25, &data[25], 1, I2C_BME280_TIMEOUT);
    107     i2c_read_register(BME280_ADDRESS, BME280_REG_CALIB26, &data[25], 7, I2C_BME280_TIMEOUT);
    108 
    109     dig_T1 = (data[1] << 8) | data[0];
    110     dig_T2 = (data[3] << 8) | data[2];
    111     dig_T3 = (data[5] << 8) | data[4];
    112     dig_P1 = (data[7] << 8) | data[6];
    113     dig_P2 = (data[9] << 8) | data[8];
    114     dig_P3 = (data[11]<< 8) | data[10];
    115     dig_P4 = (data[13]<< 8) | data[12];
    116     dig_P5 = (data[15]<< 8) | data[14];
    117     dig_P6 = (data[17]<< 8) | data[16];
    118     dig_P7 = (data[19]<< 8) | data[18];
    119     dig_P8 = (data[21]<< 8) | data[20];
    120     dig_P9 = (data[23]<< 8) | data[22];
    121     dig_H1 = data[24];
    122     dig_H2 = (data[26]<< 8) | data[25];
    123     dig_H3 = data[27];
    124     dig_H4 = (data[28]<< 4) | (0x0F & data[29]);
    125     dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
    126     dig_H6 = data[31];
    127 
    128     return;
    129 }
    130 
    131 static void readData(void) {
    132     uint8_t data[8];
    133 
    134     i2c_read_register(BME280_ADDRESS, 0xF7, &data[0], 8, I2C_BME280_TIMEOUT);
    135 
    136     pres_raw = data[0];
    137     pres_raw = (pres_raw<<8) | data[1];
    138     pres_raw = (pres_raw<<4) | (data[2] >> 4);
    139 
    140     temp_raw = data[3];
    141     temp_raw = (temp_raw<<8) | data[4];
    142     temp_raw = (temp_raw<<4) | (data[5] >> 4);
    143 
    144     hum_raw  = data[6];
    145     hum_raw  = (hum_raw << 8) | data[7];
    146 
    147     return;
    148 }
    149 
    150 static int32_t calibration_T(int32_t adc_T) {
    151     int32_t var1, var2, T;
    152     var1 = ((((adc_T >> 3) - ((int32_t)dig_T1<<1))) * ((int32_t)dig_T2)) >> 11;
    153     var2 = (((((adc_T >> 4) - ((int32_t)dig_T1)) * ((adc_T>>4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
    154 
    155     t_fine = var1 + var2;
    156     T = (t_fine * 5 + 128) >> 8;
    157 
    158     return T;
    159 }
    160 
    161 static uint32_t calibration_P(int32_t adc_P) {
    162     int32_t var1, var2;
    163     uint32_t P;
    164 
    165     var1 = (((int32_t)t_fine)>>1) - (int32_t)64000;
    166     var2 = (((var1>>2) * (var1>>2)) >> 11) * ((int32_t)dig_P6);
    167     var2 = var2 + ((var1*((int32_t)dig_P5))<<1);
    168     var2 = (var2>>2)+(((int32_t)dig_P4)<<16);
    169     var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + ((((int32_t)dig_P2) * var1)>>1))>>18;
    170     var1 = ((((32768+var1))*((int32_t)dig_P1))>>15);
    171     if (var1 == 0) {
    172         return 0;
    173     }
    174     P = (((uint32_t)(((int32_t)1048576)-adc_P)-(var2>>12)))*3125;
    175     if( P < 0x80000000 ) {
    176        P = (P << 1) / ((uint32_t) var1);
    177     } else {
    178         P = (P / (uint32_t)var1) * 2;
    179     }
    180     var1 = (((int32_t)dig_P9) * ((int32_t)(((P>>3) * (P>>3))>>13)))>>12;
    181     var2 = (((int32_t)(P>>2)) * ((int32_t)dig_P8))>>13;
    182     P = (uint32_t)((int32_t)P + ((var1 + var2 + dig_P7) >> 4));
    183 
    184     return P;
    185 }
    186 
    187 static uint32_t calibration_H(int32_t adc_H) {
    188     int32_t v_x1;
    189 
    190     v_x1 = (t_fine - ((int32_t)76800));
    191     v_x1 = (((((adc_H << 14) -(((int32_t)dig_H4) << 20) - (((int32_t)dig_H5) * v_x1)) +
    192               ((int32_t)16384)) >> 15) * (((((((v_x1 * ((int32_t)dig_H6)) >> 10) *
    193               (((v_x1 * ((int32_t)dig_H3)) >> 11) + ((int32_t) 32768))) >> 10) + (( int32_t)2097152)) *
    194               ((int32_t) dig_H2) + 8192) >> 14));
    195     v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((int32_t)dig_H1)) >> 4));
    196     v_x1 = (v_x1 < 0 ? 0 : v_x1);
    197     v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
    198 
    199     return (uint32_t)(v_x1 >> 12);
    200 }
    201 
    202 /* Public */
    203 void bme280_init(void) {
    204     uint8_t ctrl_hum_reg;
    205     uint8_t ctrl_meas_reg;
    206     uint8_t config_reg;
    207 
    208     ctrl_hum_reg = BME280_CTRL_HUM_VAL;
    209     ctrl_meas_reg = BME280_CTRL_MEAS_VAL;
    210     config_reg = BME280_CONFIG_VAL;
    211 
    212     i2c_init();
    213     i2c_write_register(BME280_ADDRESS, BME280_REG_CTRL_HUM, &ctrl_hum_reg, 1, I2C_BME280_TIMEOUT);
    214     i2c_write_register(BME280_ADDRESS, BME280_REG_CTRL_MEAS, &ctrl_meas_reg, 1, I2C_BME280_TIMEOUT);
    215     i2c_write_register(BME280_ADDRESS, BME280_REG_CONFIG, &config_reg, 1, I2C_BME280_TIMEOUT);
    216     readTrim();
    217 
    218     return;
    219 }
    220 
    221 void bme280_exec(void) {
    222     readData();
    223 
    224     return;
    225 }
    226 
    227 double bme280_getTemp(void) {
    228     double temp_act;
    229     int32_t temp_cal;
    230 
    231     temp_cal = calibration_T(temp_raw);
    232     temp_act = (double)temp_cal / 100.0;
    233 
    234     return temp_act;
    235 }
    236 
    237 double bme280_getPress(void) {
    238     double press_act;
    239     uint32_t press_cal;
    240 
    241     press_cal = calibration_P(pres_raw);
    242     press_act = (double)press_cal / 100.0;
    243 
    244     return press_act;
    245 }
    246 
    247 double bme280_getHum(void) {
    248     double hum_act;
    249     uint32_t hum_cal;
    250 
    251     hum_cal = calibration_H(hum_raw);
    252     hum_act = (double)hum_cal / 1024.0;
    253 
    254     return hum_act;
    255 }