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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
use embedded_interfaces::codegen::interface_objects;
use embedded_interfaces::registers::i2c::codecs::OneByteRegAddrCodec;
use uom::si::f64::ThermodynamicTemperature;
use uom::si::thermodynamic_temperature::degree_celsius;
pub type TMP117I2cCodec = OneByteRegAddrCodec;
pub const DEVICE_ID_VALID: u16 = 0x117;
interface_objects! {
register_defaults {
codec_error = (),
i2c_codec = TMP117I2cCodec,
spi_codec = embedded_interfaces::registers::spi::codecs::unsupported_codec::UnsupportedCodec::<()>,
}
register_devices [ super::TMP117 ]
/// Temperature alert flag.
enum AlertFlag: u8{1} {
/// The alert is unset.
0 Cleared,
/// The associated alert was triggered.
1 Set,
}
/// Conversion mode.
enum ConversionMode: u8{2} {
/// Continuous conversion (power-up default)
0b00 Continuous,
/// Shutdown
0b01 Shutdown,
/// This is the same as Continuous and will read back as Continuous.
0b10 Continuous2,
/// Oneshot conversion
0b11 Oneshot,
}
/// Conversion cycle time.
#[allow(non_camel_case_types)]
enum ConversionCycleTime: u8{3} {
/// 15.5ms
0b000 T_15_5,
/// 125ms
0b001 T_125,
/// 250ms
0b010 T_250,
/// 500ms
0b011 T_500,
/// 1s (power-up default)
0b100 T_1000,
/// 4s
0b101 T_4000,
/// 8s
0b110 T_8000,
/// 16s
0b111 T_16000,
}
/// Conversion averaging modes.
#[allow(non_camel_case_types)]
enum AveragingMode: u8{2} {
/// Disables averaging.
0b00 X_1,
/// Configures 8x sample averaging. This is the power-on default.
/// Minimum conversion time is 125ms, even if a lower conversion cycle is selected.
0b01 X_8,
/// Configures 32x sample averaging.
/// Minimum conversion time is 500ms, even if a lower conversion cycle is selected.
0b10 X_32,
/// Configures 64x sample averaging.
/// Minimum conversion time is 1s, even if a lower conversion cycle is selected.
0b11 X_64,
}
/// Therm/Alert mode.
enum AlertThermMode: u8{1} {
/// In this mode, the device compares the conversion result at the end of every
/// conversion with the values in the low limit register and high limit register.
/// If the temperature result exceeds the value in the high limit register,
/// the high alert status flag in the configuration register is set. On the other hand,
/// if the temperature result is lower than the value in the low limit register,
/// the low alert status flag in the configuration register is set.
/// This is the power-on default.
///
/// This mode effectively makes the device behave like a window limit detector.
/// Thus this mode can be used in applications where detecting if the temperature
/// goes outside of the specified range is necessary.
0 Alert,
/// In this mode, the device compares the conversion result at the end of every conversion
/// with the values in the low limit register and high limit register and sets the high alert
/// status flag in the configuration register if the temperature exceeds the value in the
/// high limit register. When set, the device clears the high alert status flag if the conversion
/// result goes below the value in the low limit register.
///
/// Thus, the difference between the high and low limits effectively acts like a hysteresis.
/// In this mode, the low alert status flag is disabled and always reads 0. Unlike the alert
/// mode, I2C reads of the configuration register do not affect the status bits. The high alert
/// status flag is only set or cleared at the end of conversions based on the value of the
/// temperature result compared to the high and low limits.
1 Therm,
}
/// Alert pin polarity.
enum AlertPinPolarity: u8{1} {
/// Power-on default.
0 ActiveLow,
1 ActiveHigh,
}
/// Alert pin mode.
enum AlertPinMode: u8{1} {
/// Alert pin reflects the status of the alert flags. (Set if any alert is set).
0 AnyAlert,
/// Alert pin reflects the status of the data-ready flag.
1 DataReady,
}
/// EEPROM lock mode.
enum EepromLockMode: u8{1} {
/// EEPROM is locked for programming: writes to all EEPROM addresses
/// (such as configuration, limits, and EEPROM locations 1-4) are written
/// to registers in digital logic and are not programmed in the EEPROM
0 Locked,
/// EEPROM unlocked for programming: any writes to programmable registers
/// program the respective location in the EEPROM
1 Unlocked,
}
/// At the end of every conversion, the device updates the temperature
/// register with the conversion result. Following a reset, the temperature
/// register reads –256°C until the first conversion, including averaging, is complete.
register Temperature(addr = 0b0000, mode = r, size = 2) {
/// The temperature in °C with a resolution of 7.8125m°C/LSB.
raw_temperature: i16 = i16::MIN => {
quantity: ThermodynamicTemperature,
unit: degree_celsius,
lsb: 1f64 / 128f64,
},
}
/// The device configuration register.
register Configuration(addr = 0b0001, mode = rw, size = 2) {
/// Set when the conversion result is higher than the high limit.
/// This flag is cleared on read except in Therm mode, where it is
/// cleared when the conversion result is lower than the hysteresis.
alert_high: AlertFlag = AlertFlag::Cleared,
/// Set when the conversion result is lower than the low limit.
/// In Therm mode, this flag is always cleared.
/// This flag is cleared on read.
alert_low: AlertFlag = AlertFlag::Cleared,
/// This flag indicates that the conversion is complete and the
/// temperature register can be read. Every time the temperature
/// register or configuration register is read, this bit is cleared. This
/// bit is set at the end of the conversion when the temperature
/// register is updated. Data ready can be monitored on the ALERT
/// pin by setting the alert_pin_mode to AlertPinMode::DataReady.
data_ready: bool = false,
/// The value of the flag indicates that the EEPROM is busy during programming or power-up.
eeprom_busy: bool = false,
/// Temperature conversion mode (operating mode).
/// This can be persisted in the EEPROM to set the power-up default,
/// except for the oneshot mode.
conversion_mode: ConversionMode = ConversionMode::Continuous,
/// Amount of time to wait between conversions.
/// If the time to complete the conversions needed for a given averaging setting is
/// higher than the conversion setting cycle time, there will be no stand by time
/// in the conversion cycle. See AveragingMode.
/// This bit can be persisted into the EEPROM.
/// This can be persisted in the EEPROM to set the power-up default.
conversion_cycle_time: ConversionCycleTime = ConversionCycleTime::T_1000,
/// Determines the number of conversion results that are collected
/// and averaged before updating the temperature register.
/// The average is an accumulated average and not a running average.
/// This can be persisted in the EEPROM to set the power-up default.
averaging_mode: AveragingMode = AveragingMode::X_8,
/// Therm/alert mode select.
/// This can be persisted in the EEPROM to set the power-up default.
alert_therm_mode: AlertThermMode = AlertThermMode::Alert,
/// Polarity of the alert pin.
/// This can be persisted in the EEPROM to set the power-up default.
alert_pin_polarity: AlertPinPolarity = AlertPinPolarity::ActiveLow,
/// Alert pin output mode.
/// This can be persisted in the EEPROM to set the power-up default.
alert_pin_mode: AlertPinMode = AlertPinMode::AnyAlert,
/// Triggers a soft-reset when set. Always reads back as `false`.
soft_reset: bool = false,
/// Reserved bit
_: u8{1},
}
/// This register stores the high limit for comparison with the temperature result
/// with a resolution is 7.8125m°C/LSB. The range of the register is ±256°C.
/// Following power-up or a general-call reset, the high-limit register is loaded with the
/// stored value from the EEPROM. The factory default reset value is 6000h (192°C).
register TemperatureLimitHigh(addr = 0b0010, mode = rw, size = 2) {
/// The temperature limit in °C with a resolution of 7.8125m°C/LSB.
raw_temperature_limit: i16 = 0x6000 => {
quantity: ThermodynamicTemperature,
unit: degree_celsius,
lsb: 1f64 / 128f64,
},
}
/// This register stores the low limit for comparison with the temperature result
/// with a resolution is 7.8125m°C/LSB. The range of the register is ±256°C.
/// Following power-up or a general-call reset, the low-limit register is loaded with the
/// stored value from the EEPROM. The factory default reset value is 8000h (-256°C).
register TemperatureLimitLow(addr = 0b0011, mode = rw, size = 2) {
/// The temperature limit in °C with a resolution of 7.8125m°C/LSB.
raw_temperature_limit: i16 = i16::MIN => {
quantity: ThermodynamicTemperature,
unit: degree_celsius,
lsb: 1f64 / 128f64,
},
}
/// The EEPROM unlock register.
register EepromUnlock(addr = 0b0100, mode = rw, size = 2) {
/// EEPROM lock mode. Defaults to locked on power-on.
lock_mode: EepromLockMode = EepromLockMode::Locked,
/// This flag is the mirror of the EEPROM busy flag (bit 12) in the configuration register.
/// - `false` indicates that the EEPROM is ready, which means that the EEPROM has finished
/// the last transaction and is ready to accept new commands.
/// - `true` indicates that the EEPROM is busy, which means that the EEPROM is currently
/// completing a programming operation or performing power-up on reset load
busy: bool = false,
/// Reserved bits
_: u16{14},
}
/// This is a 16-bit register that be used as a scratch pad by the customer to store general-
/// purpose data. This register has a corresponding EEPROM location. Writes to this address when the EEPROM is
/// locked write data into the register and not to the EEPROM. Writes to this register when the EEPROM is unlocked
/// causes the corresponding EEPROM location to be programmed.
///
/// To support NIST traceability do not delete or reprogram the EEPROM1 register.
register Eeprom1(addr = 0b0101, mode = rw, size = 2) {
/// The data stored in this register
data: [u8; 2] = [0u8; 2],
}
/// This is a 16-bit register that be used as a scratch pad by the customer to store general-
/// purpose data. This register has a corresponding EEPROM location. Writes to this address when the EEPROM is
/// locked write data into the register and not to the EEPROM. Writes to this register when the EEPROM is unlocked
/// causes the corresponding EEPROM location to be programmed.
///
/// To support NIST traceability do not delete or reprogram the EEPROM2 register.
register Eeprom2(addr = 0b0110, mode = rw, size = 2) {
/// The data stored in this register
data: [u8; 2] = [0u8; 2],
}
/// This register may be used as a user-defined temperature offset register during system calibration.
/// The offset will be added to the temperature result after linearization. It has a same resolution
/// of 7.8125 m°C/LSB and same range of ±256°C as the temperature result register. If the added result
/// exceeds value boundaries, then the temperature result will clamp to the maximum or minimum value.
register TemperatureOffset(addr = 0b0111, mode = rw, size = 2) {
/// The temperature offset in °C with a resolution of 7.8125m°C/LSB.
raw_temperature_offset: i16 = 0 => {
quantity: ThermodynamicTemperature,
unit: degree_celsius,
lsb: 1f64 / 128f64,
},
}
/// This is a 16-bit register that be used as a scratch pad by the customer to store general-
/// purpose data. This register has a corresponding EEPROM location. Writes to this address when the EEPROM is
/// locked write data into the register and not to the EEPROM. Writes to this register when the EEPROM is unlocked
/// causes the corresponding EEPROM location to be programmed.
///
/// To support NIST traceability do not delete or reprogram the EEPROM3 register.
register Eeprom3(addr = 0b1000, mode = rw, size = 2) {
/// The data stored in this register
data: [u8; 2] = [0u8; 2],
}
/// The device-id and revision register.
register DeviceIdRevision(addr = 0b1111, mode = r, size = 2) {
/// Indicates the revision number of the device. 0 indicates the first revision.
device_revision: u8{4} = 0x0,
/// The indentifier of this this device. The factory default is DEVICE_ID_VALID (0x117).
device_id: u16{12} = 0x117,
}
}
impl ConversionCycleTime {
/// Conversion cycle time in microseconds.
pub fn interval_us(&self) -> u32 {
match self {
ConversionCycleTime::T_15_5 => 15_500,
ConversionCycleTime::T_125 => 125_000,
ConversionCycleTime::T_250 => 250_000,
ConversionCycleTime::T_500 => 500_000,
ConversionCycleTime::T_1000 => 1_000_000,
ConversionCycleTime::T_4000 => 4_000_000,
ConversionCycleTime::T_8000 => 8_000_000,
ConversionCycleTime::T_16000 => 16_000_000,
}
}
}
impl AveragingMode {
/// Returns the averaging factor
pub fn factor(&self) -> u8 {
match self {
AveragingMode::X_1 => 1,
AveragingMode::X_8 => 8,
AveragingMode::X_32 => 32,
AveragingMode::X_64 => 64,
}
}
}