1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
use embedded_interfaces::codegen::interface_objects;
use embedded_interfaces::registers::{i2c::codecs::OneByteRegAddrCodec, spi::codecs::standard_codec::StandardCodec};
pub type BME280SpiCodec = StandardCodec<1, 6, 0, 7, true, 0>;
pub type BME280I2cCodec = OneByteRegAddrCodec;
interface_objects! {
register_defaults {
codec_error = (),
i2c_codec = BME280I2cCodec,
spi_codec = BME280SpiCodec,
}
register_devices [ super::BME280Common ]
/// Known chip ids
enum Chip: u8{8} {
/// A BMP280 production sample
0x56 BMP280Sample1,
/// A BMP280 production sample
0x57 BMP280Sample2,
/// A mass-produced BMP280
0x58 BMP280,
/// A mass-produced BME280
0x60 BME280,
/// Unknown chip id
_ Invalid(u8),
}
/// Reset magic values
enum ResetMagic: u8{8} {
/// Magic value to reset the device
0xb6 Reset,
/// Invalid reset magic
_ Invalid(u8),
}
/// Oversampling settings for temperature, pressure, and humidity measurements.
/// See sections 3.4ff of the manual for measurement flow and recommended values.
#[allow(non_camel_case_types)]
enum Oversampling: u8{3} {
/// Disables this output. Measurement data will be returned as 0x80000.
0b000 Disabled,
/// Disables oversampling.
/// Without IIR filtering, this sets the resolution of temperature and pressure measurements
/// to 16 bits.
0b001 X_1,
/// Configures 2x oversampling.
/// This increases the resolution of temperature and pressure measurements to 17 bits without
/// IIR filtering.
0b010 X_2,
/// Configures 4x oversampling.
/// This increases the resolution of temperature and pressure measurements to 18 bits without
/// IIR filtering.
0b011 X_4,
/// Configures 8x oversampling.
/// This increases the resolution of temperature and pressure measurements to 19 bits without
/// IIR filtering.
0b100 X_8,
/// Configures 16x oversampling.
/// This increases the resolution of temperature and pressure measurements to 20 bits,
/// regardless of IIR filtering.
0b101 X_16,
/// Unknown oversampling setting.
_ Invalid(u8),
}
/// Sensor operating mode
enum SensorMode: u8{2} {
/// Sleep mode is entered by default after power on reset. In sleep mode, no measurements are
/// performed and power consumption is at a minimum. All registers are accessible.
/// There are no special restrictions on interface timings.
0b00 Sleep,
/// In forced mode, a single measurement is performed in accordance to the selected measurement and
/// filter options. When the measurement is finished, the sensor returns to sleep mode and the
/// measurement results can be obtained from the data registers. For a next measurement, forced mode
/// needs to be selected again. Using forced mode is recommended
/// for applications which require low sampling rate or host-based synchronization.
0b01 Forced,
/// Normal mode comprises an automated perpetual cycling between an (active) measurement period
/// and an (inactive) standby period. The measurements are performed in accordance to the selected
/// measurement and filter options. The standby time is determined by the standby_time setting
/// in the Config register and can be set to between 0.5 and 1000 ms.
0b11 Normal,
/// Invalid sensor mode
_ Invalid(u8),
}
/// The standby time between measurements in Normal sensor mode.
#[allow(non_camel_case_types)]
enum StandbyTime: u8{3} {
/// 0.5ms
0b000 T_0_5,
/// 62.5ms
0b001 T_62_5,
/// 125ms
0b010 T_125,
/// 250ms
0b011 T_250,
/// 500ms
0b100 T_500,
/// 1000ms
0b101 T_1000,
/// 10ms (BME280 only)
0b110 T_10,
/// 20ms (BME280 only)
0b111 T_20,
}
/// Lowpass filter settings for pressure and temperature values.
/// Enabling any filter option increases the resolution of the
/// respective measured quantity to 20 bits.
enum IIRFilter: u8{3} {
/// Disables the IIR filter (default).
/// The resolution of pressure and temperature measurements is dictated by their respective
/// oversampling settings.
0b000 Disabled,
/// Sets the IIR filter coefficient to 2.
0b001 Coefficient2,
/// Sets the IIR filter coefficient to 4.
0b010 Coefficient4,
/// Sets the IIR filter coefficient to 8.
0b011 Coefficient8,
/// Sets the IIR filter coefficient to 16.
0b100 Coefficient16,
/// Invalid coefficient
_ Invalid(u8),
}
/// The chip identification number. This number can
/// be read as soon as the device finished the power-on-reset.
register Id(addr = 0xd0, mode = r, size = 1) {
chip: Chip = Chip::Invalid(0),
}
/// The reset register. If the value 0xB6 is written to the register,
/// the device is reset using the complete power-on-reset procedure.
/// Writing other values than 0xB6 has no effect.
register Reset(addr = 0xe0, mode = w, size = 1) {
magic: ResetMagic = ResetMagic::Reset,
}
/// The humidity control register. Changes to this register only become effective
/// after a write to the ControlMeasurement register!
register ControlHumidity(addr = 0xf2, mode = rw, size = 1) {
/// Reserved bits
_: u8{5},
/// Controls oversampling of humidity data.
/// The default is 1x, i.e., no oversampling.
oversampling: Oversampling = Oversampling::X_1,
}
/// The status register.
register Status(addr = 0xf3, mode = r, size = 1) {
/// Reserved bits
_: u8{4},
/// Automatically set to `1` whenever a conversion is running and back to `0` when the results have been transferred to the data registers.
measuring: bool = false,
/// Reserved bits
_: u8{2},
/// Automatically set to `1` when the NVM data is being copied to image registers and back to `0` when the
/// copying is done. The data are copied at power-on-reset and before every conversion.
update: bool = false,
}
/// The measurement control register sets the pressure and temperature
/// data acquisition options of the device. The register needs to be written
/// after changing ControlHumidity for those changes to become effective.
register ControlMeasurement(addr = 0xf4, mode = rw, size = 1) {
/// Controls oversampling of temperature data.
temperature_oversampling: Oversampling = Oversampling::Disabled,
/// Controls oversampling of pressure data.
pressure_oversampling: Oversampling = Oversampling::Disabled,
/// Controls operating mode of the sensor.
sensor_mode: SensorMode = SensorMode::Sleep,
}
/// The config register sets the rate, filter and interface options of the device.
/// Writes to this register in Normal mode may be ignored.
/// In Sleep mode writes are not ignored.
register Config(addr = 0xf5, mode = rw, size = 1) {
/// Controls inactive duration t_standby in Normal sensor mode.
standby_time: StandbyTime = StandbyTime::T_0_5,
/// Controls the time constant of the IIR filter.
filter: IIRFilter = IIRFilter::Disabled,
/// Reserved bit
_: bool,
/// Whether to enable the SPI 3-wire interface.
spi_3wire: bool = false,
}
/// Device-internal calibration registers (section 1)
register TrimmingParameters1(addr = 0x88, mode = r, size = 26) {
dig_t1: u16{le},
dig_t2: i16{le},
dig_t3: i16{le},
dig_p1: u16{le},
dig_p2: i16{le},
dig_p3: i16{le},
dig_p4: i16{le},
dig_p5: i16{le},
dig_p6: i16{le},
dig_p7: i16{le},
dig_p8: i16{le},
dig_p9: i16{le},
/// Reserved byte
_: u8,
dig_h1: u8,
}
/// Device-internal calibration registers (section 2)
register TrimmingParameters2(addr = 0xe1, mode = r, size = 7) {
dig_h2: i16{le},
dig_h3: u8,
dig_h4_msb: i8,
dig_h5_lsn_h4_lsn: i8,
dig_h5_msb: i8,
dig_h6: i8,
}
/// This register contains the raw pressure measurement
register Pressure(addr = 0xf7, mode = r, size = 3) {
/// The raw pressure measurement
value: u32{20} = 1 << 19,
/// Reserved bits
_: u8{4},
}
/// This register contains the raw temperature measurement
register Temperature(addr = 0xfa, mode = r, size = 3) {
/// The raw temperature measurement
value: u32{20} = 1 << 19,
/// Reserved bits
_: u8{4},
}
/// This register contains the raw humidity measurement
register Humidity(addr = 0xfd, mode = r, size = 2) {
/// The raw humidity measurement
value: u16 = 1 << 15,
}
/// Burst register read of pressure and temperature
register BurstMeasurementsPT(addr = 0xf7, mode = r, size = 6) {
pressure: PressureUnpacked,
temperature: TemperatureUnpacked,
}
/// Burst register read of pressure, temperature and humidity
register BurstMeasurementsPTH(addr = 0xf7, mode = r, size = 8) {
pressure: PressureUnpacked,
temperature: TemperatureUnpacked,
humidity: HumidityUnpacked,
}
}
impl Oversampling {
/// Returns the oversampling factor (1 for X_1, 16 for X_16)
pub fn factor(&self) -> u32 {
match self {
Oversampling::Disabled => 0,
Oversampling::X_1 => 1,
Oversampling::X_2 => 2,
Oversampling::X_4 => 4,
Oversampling::X_8 => 8,
Oversampling::X_16 => 16,
Oversampling::Invalid(_) => 0,
}
}
}
impl StandbyTime {
/// Standby time in microseconds.
pub fn time_us(&self) -> u32 {
match self {
StandbyTime::T_0_5 => 500,
StandbyTime::T_62_5 => 62_500,
StandbyTime::T_125 => 125_000,
StandbyTime::T_250 => 250_000,
StandbyTime::T_500 => 500_000,
StandbyTime::T_1000 => 1_000_000,
StandbyTime::T_10 => 10_000,
StandbyTime::T_20 => 20_000,
}
}
}