|
| 1 | +// Copyright (C) 2022 David Lao. All rights reserved. |
| 2 | +// Use of this source code is governed by a MIT-style license that can be found |
| 3 | +// in the LICENSE file. |
| 4 | +
|
| 5 | +import binary |
| 6 | +import serial.device as serial |
| 7 | +import serial.registers as serial |
| 8 | + |
| 9 | +I2C_ADDRESS ::= 0x77 |
| 10 | + |
| 11 | +// |
| 12 | +// Driver for the Bosch BMP180 environmental sensor with I2C interface |
| 13 | +// |
| 14 | +class Driver: |
| 15 | + static CAL_COEF_AC1_ ::= 0xAA |
| 16 | + static CAL_COEF_AC2_ ::= 0xAC |
| 17 | + static CAL_COEF_AC3_ ::= 0xAE |
| 18 | + static CAL_COEF_AC4_ ::= 0xB0 |
| 19 | + static CAL_COEF_AC5_ ::= 0xB2 |
| 20 | + static CAL_COEF_AC6_ ::= 0xB4 |
| 21 | + static CAL_COEF_B1_ ::= 0xB6 |
| 22 | + static CAL_COEF_B2_ ::= 0xB8 |
| 23 | + static CAL_COEF_MB_ ::= 0xBA |
| 24 | + static CAL_COEF_MC_ ::= 0xBC |
| 25 | + static CAL_COEF_MD_ ::= 0xBE |
| 26 | + |
| 27 | + static REG_CONTROL_ ::= 0xF4 |
| 28 | + static REG_TEMPDATA_ ::= 0xF6 |
| 29 | + static REG_PRESSUREDATA_ ::= 0xF6 |
| 30 | + static REG_READTEMP_CMD_ ::= 0x2E |
| 31 | + static REG_READPRESSURE_CMD_ ::= 0x34 |
| 32 | + |
| 33 | + static REG_CHIPID_ ::= 0xD0 |
| 34 | + |
| 35 | + reg_/serial.Registers ::= ? |
| 36 | + |
| 37 | + ac1 := null |
| 38 | + ac2 := null |
| 39 | + ac3 := null |
| 40 | + ac4 := null |
| 41 | + ac5 := null |
| 42 | + ac6 := null |
| 43 | + b1 := null |
| 44 | + b2 := null |
| 45 | + mb := null |
| 46 | + mc := null |
| 47 | + md := null |
| 48 | + |
| 49 | + // hardware pressure sampling accuracy modes |
| 50 | + // 0 = ultra low power, 1 = standard, 2 = high resolution, 3 ultra high resolution |
| 51 | + oversampling := 1 |
| 52 | + |
| 53 | + constructor dev/serial.Device: |
| 54 | + reg_ = dev.registers |
| 55 | + |
| 56 | + tries := 5 |
| 57 | + while (reg_.read_u8 REG_CHIPID_) != 0x55: |
| 58 | + tries-- |
| 59 | + if tries == 0: throw "INVALID_CHIP" |
| 60 | + sleep --ms=1 |
| 61 | + |
| 62 | + // read calibration coefficients |
| 63 | + ac1 = reg_.read_i16_be CAL_COEF_AC1_ |
| 64 | + ac2 = reg_.read_i16_be CAL_COEF_AC2_ |
| 65 | + ac3 = reg_.read_i16_be CAL_COEF_AC3_ |
| 66 | + ac4 = reg_.read_u16_be CAL_COEF_AC4_ |
| 67 | + ac5 = reg_.read_u16_be CAL_COEF_AC5_ |
| 68 | + ac6 = reg_.read_u16_be CAL_COEF_AC6_ |
| 69 | + b1 = reg_.read_i16_be CAL_COEF_B1_ |
| 70 | + b2 = reg_.read_i16_be CAL_COEF_B2_ |
| 71 | + mb = reg_.read_i16_be CAL_COEF_MB_ |
| 72 | + mc = reg_.read_i16_be CAL_COEF_MC_ |
| 73 | + md = reg_.read_i16_be CAL_COEF_MD_ |
| 74 | + |
| 75 | + // Reads the temperature and returns it in degrees Celsius |
| 76 | + read_temperature: |
| 77 | + ut := read_raw_temperature_ |
| 78 | + b5 := compute_b5_ ut |
| 79 | + t := (b5 + 8) / 16.0 |
| 80 | + t = t / 10.0 |
| 81 | + return t |
| 82 | + |
| 83 | + // Reads the barometric pressure and returns it in Pascals |
| 84 | + read_pressure: |
| 85 | + ut := read_raw_temperature_ |
| 86 | + b5 := compute_b5_ ut |
| 87 | + up := read_raw_pressure_ |
| 88 | + |
| 89 | + b6 := b5 - 4000 |
| 90 | + x1 := (b2 * ((b6 * b6) >> 12)) >> 11 |
| 91 | + x2 := (ac2 * b6) >> 11 |
| 92 | + x3 := x1 + x2 |
| 93 | + b3 := (((ac1 * 4 + x3) << oversampling) + 2) / 4 |
| 94 | + |
| 95 | + x1 = (ac3 * b6) >> 13 |
| 96 | + x2 = (b1 * ((b6 * b6) >> 12)) >> 16 |
| 97 | + x3 = ((x1 + x3) + 2) >> 2 |
| 98 | + b4 := (ac4 * (x3 + 32768)) >> 15 |
| 99 | + b7 := (up - b3) * (50000 >> oversampling) |
| 100 | + |
| 101 | + p := null |
| 102 | + if b7 < 0x80000000: |
| 103 | + p = (b7 * 2) / b4 |
| 104 | + else: |
| 105 | + p = (b7 / b4) * 2 |
| 106 | + |
| 107 | + x1 = (p >> 8) * (p >> 8) |
| 108 | + x1 = (x1 * 3038) >> 16 |
| 109 | + x2 = (-7357 * p) >> 16 |
| 110 | + |
| 111 | + p = p + ((x1 + x2 + 3791) >> 4) |
| 112 | + return p |
| 113 | + |
| 114 | + // compute b5 |
| 115 | + compute_b5_ ut: |
| 116 | + x1 := (ut - ac6) * ac5 >> 15 |
| 117 | + x2 := (mc << 11) / (x1 + md) |
| 118 | + return x1 + x2 |
| 119 | + |
| 120 | + // read uncompensated temperature value |
| 121 | + read_raw_temperature_ : |
| 122 | + reg_.write_u8 REG_CONTROL_ REG_READTEMP_CMD_ |
| 123 | + sleep --ms=5 |
| 124 | + ut := reg_.read_u16_be REG_TEMPDATA_ |
| 125 | + return ut |
| 126 | + |
| 127 | + // read uncompensated pressure value |
| 128 | + read_raw_pressure_ : |
| 129 | + reg_.write_u8 REG_CONTROL_ (REG_READPRESSURE_CMD_ + (oversampling << 6)) |
| 130 | + sleep --ms=5 |
| 131 | + up := reg_.read_u24_be REG_PRESSUREDATA_ |
| 132 | + up >>= (8 - oversampling) |
| 133 | + return up |
0 commit comments