1#![doc = include_str!("../README.md")]
2#![no_std]
3#![deny(missing_docs)]
4
5use device_register::{EditRegister, ReadRegister, WriteRegister};
6use embedded_hal::{
7 delay::DelayNs,
8 i2c::{I2c, SevenBitAddress},
9};
10pub use error::Error;
11use register::*;
12use tmp117_ll::Tmp117LL;
13
14pub mod asynchronous;
15pub mod error;
16pub mod register;
17pub mod tmp117_ll;
18
19pub const CELCIUS_CONVERSION: f32 = 0.0078125;
21
22pub enum Alert {
24 None,
26
27 High,
29
30 Low,
32
33 HighLow,
35}
36
37#[derive(Default)]
39pub struct ContinuousConfig {
40 pub average: Average,
42
43 pub conversion: Conversion,
45
46 pub high: Option<f32>,
48
49 pub low: Option<f32>,
51
52 pub offset: Option<f32>,
54}
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
57#[derive(Copy, Clone, PartialEq, Eq, Debug)]
58pub struct Id {
59 pub device: u16,
61 pub revision: u8,
63}
64
65pub struct Tmp117<T, E> {
68 tmp_ll: Tmp117LL<T, E>,
69}
70
71impl<T, E> Tmp117<T, E>
72where
73 T: I2c<SevenBitAddress, Error = E>,
74 E: embedded_hal::i2c::Error,
75{
76 pub fn new(i2c: T, addr: u8) -> Self {
78 Tmp117::<T, E> {
79 tmp_ll: Tmp117LL::new(i2c, addr),
80 }
81 }
82
83 pub fn new_from_ll(tmp_ll: Tmp117LL<T, E>) -> Self {
85 Tmp117::<T, E> { tmp_ll }
86 }
87
88 pub fn id(&mut self) -> Result<Id, Error<E>> {
90 let id: DeviceID = self.tmp_ll.read()?;
91 Ok(Id {
92 device: id.device_id().into(),
93 revision: id.revision().into(),
94 })
95 }
96
97 fn wait_eeprom(&mut self) -> Result<(), Error<E>> {
98 let mut configuration: Configuration = self.tmp_ll.read()?;
99 while configuration.eeprom_busy() {
100 configuration = self.tmp_ll.read()?;
101 }
102
103 Ok(())
104 }
105
106 fn read_temp_raw(&mut self) -> Result<f32, Error<E>> {
107 let temp: Temperature = self.tmp_ll.read()?;
108
109 let val = (u16::from(temp) as i16) as f32 * CELCIUS_CONVERSION;
111 Ok(val)
112 }
113
114 fn check_alert(&mut self) -> Result<Alert, Error<E>> {
115 let config: Configuration = self.tmp_ll.read()?;
116 if config.high_alert() && config.low_alert() {
117 Ok(Alert::HighLow)
118 } else if config.high_alert() {
119 Ok(Alert::High)
120 } else if config.low_alert() {
121 Ok(Alert::Low)
122 } else {
123 Ok(Alert::None)
124 }
125 }
126
127 fn wait_for_data(&mut self) -> Result<(), Error<E>> {
128 loop {
130 let config: Configuration = self.tmp_ll.read()?;
131 if config.data_ready() {
132 break;
133 }
134 }
135 Ok(())
136 }
137
138 fn wait_for_alert(&mut self) -> Result<Alert, Error<E>> {
139 loop {
140 let alert = self.check_alert();
141 if let Ok(Alert::None) = alert {
142 continue;
143 } else {
144 return alert;
145 }
146 }
147 }
148
149 fn set_continuous(
150 &mut self,
151 config: ContinuousConfig,
152 ) -> Result<ContinuousHandler<'_, T, E>, Error<E>> {
153 if let Some(val) = config.high {
154 let high: HighLimit = ((val / CELCIUS_CONVERSION) as u16).into();
155 self.tmp_ll.write(high)?;
156 }
157 if let Some(val) = config.low {
158 let low: LowLimit = ((val / CELCIUS_CONVERSION) as u16).into();
159 self.tmp_ll.write(low)?;
160 }
161 if let Some(val) = config.offset {
162 let off: TemperatureOffset = ((val / CELCIUS_CONVERSION) as u16).into();
163 self.tmp_ll.write(off)?;
164 }
165
166 self.tmp_ll.edit(|r: &mut Configuration| {
167 r.set_mode(ConversionMode::Continuous);
168 r.set_polarity(Polarity::ActiveLow);
169 r.set_average(config.average);
170 r.set_conversion(config.conversion);
171 })?;
172
173 Ok(ContinuousHandler { tmp117: self })
174 }
175
176 fn set_oneshot(&mut self, average: Average) -> Result<(), Error<E>> {
177 self.tmp_ll.edit(|r: &mut Configuration| {
178 r.set_mode(ConversionMode::OneShot);
179 r.set_polarity(Polarity::ActiveLow);
180 r.set_average(average);
181 })?;
182 Ok(())
183 }
184
185 fn set_shutdown(&mut self) -> Result<(), Error<E>> {
186 self.tmp_ll.edit(|r: &mut Configuration| {
187 r.set_mode(ConversionMode::Shutdown);
188 })?;
189 Ok(())
190 }
191
192 pub fn reset<D>(&mut self, delay: &mut D) -> Result<(), Error<E>>
194 where
195 D: DelayNs,
196 {
197 self.tmp_ll.edit(|r: &mut Configuration| {
198 r.set_reset(true);
199 })?;
200 delay.delay_ms(2);
201 self.set_shutdown()?;
202 Ok(())
203 }
204
205 pub fn write_eeprom(&mut self, values: [u16; 3]) -> Result<(), Error<E>> {
207 self.wait_eeprom()?;
208 self.tmp_ll.write(UEEPROM1::from(values[0]))?;
209
210 self.wait_eeprom()?;
211 self.tmp_ll.write(UEEPROM2::from(values[1]))?;
212
213 self.wait_eeprom()?;
214 self.tmp_ll.write(UEEPROM3::from(values[2]))?;
215
216 Ok(())
217 }
218
219 pub fn read_eeprom(&mut self) -> Result<[u16; 3], Error<E>> {
221 let u1: UEEPROM1 = self.tmp_ll.read()?;
222 let u2: UEEPROM2 = self.tmp_ll.read()?;
223 let u3: UEEPROM3 = self.tmp_ll.read()?;
224
225 Ok([u1.into(), u2.into(), u3.into()])
226 }
227
228 pub fn oneshot(&mut self, average: Average) -> Result<f32, Error<E>> {
230 self.set_oneshot(average)?;
231 self.wait_for_data()?;
232 let data = self.read_temp_raw()?;
233 Ok(data)
234 }
235
236 pub fn continuous<F>(&mut self, config: ContinuousConfig, f: F) -> Result<(), Error<E>>
240 where
241 F: FnOnce(ContinuousHandler<'_, T, E>) -> Result<(), Error<E>>,
242 {
243 let handler = self.set_continuous(config)?;
244 f(handler)?;
245 self.set_shutdown()
246 }
247}
248
249pub struct ContinuousHandler<'a, T, E> {
251 tmp117: &'a mut Tmp117<T, E>,
252}
253
254impl<'a, T, E> ContinuousHandler<'a, T, E>
255where
256 T: I2c<SevenBitAddress, Error = E>,
257 E: embedded_hal::i2c::Error,
258{
259 pub fn read_temp(&mut self) -> Result<f32, Error<E>> {
261 let config: Configuration = self.tmp117.tmp_ll.read()?;
262 if !config.data_ready() {
263 return Err(Error::DataNotReady);
264 }
265
266 let val = self.tmp117.read_temp_raw()?;
267 Ok(val)
268 }
269
270 pub fn wait_temp(&mut self) -> Result<f32, Error<E>> {
272 self.tmp117.wait_for_data()?;
273 let val = self.tmp117.read_temp_raw()?;
274 Ok(val)
275 }
276
277 pub fn get_alert(&mut self) -> Result<Alert, Error<E>> {
279 let val = self.tmp117.check_alert()?;
280 Ok(val)
281 }
282
283 pub fn wait_alert(&mut self) -> Result<Alert, Error<E>> {
285 let val = self.tmp117.wait_for_alert()?;
286 Ok(val)
287 }
288}