1#![no_std]
2
3#[cfg(feature = "async")]
4use embedded_hal_async::i2c::I2c as AsyncI2c;
5
6use embedded_hal::i2c::I2c;
7
8pub struct ADS111x<I2C, const MODEL: u8> {
9 address: Address,
10 i2c: I2C,
11 pub config: Config,
12}
13
14pub type ADS1115<I2C> = ADS111x<I2C, 5>;
15pub type ADS1114<I2C> = ADS111x<I2C, 4>;
16pub type ADS1113<I2C> = ADS111x<I2C, 3>;
17
18#[cfg(feature = "async")]
19impl<I2C> ADS1113<I2C> {
20 pub fn new(i2c: I2C, config: Config) -> Self {
21 Self {
22 address: Address::Ground,
23 i2c,
24 config,
25 }
26 }
27}
28
29impl<I2C: I2c> ADS1113<I2C> {
30 fn read_channel_raw(&mut self) -> Result<i16, I2C::Error> {
31 let mut config = [(1 << 7) | 1, (self.config.data_rate as u8)];
32 let mut data = [0u8; 2];
33
34 self.i2c
35 .write(self.address as u8, &[0x01, config[0], config[1]])?;
36
37 loop {
38 self.i2c
39 .write_read(self.address as u8, &[0x01], &mut config)?;
40 if (config[0] & 0x80) != 0 {
41 break;
42 }
43 }
44
45 self.i2c
46 .write_read(self.address as u8, &[0x00], &mut data)?;
47 Ok(i16::from_be_bytes(data))
48 }
49
50 pub fn read_adc(&mut self) -> Result<i16, I2C::Error> {
51 self.read_channel_raw()
52 }
53}
54
55#[cfg(feature = "async")]
56impl<I2C: AsyncI2c> ADS1113<I2C> {
57 async fn read_channel_asyncraw(&mut self) -> Result<i16, I2C::Error> {
58 let mut config = [(1 << 7) | 1, (self.config.data_rate as u8)];
59 let mut data = [0u8; 2];
60
61 self.i2c
62 .write(self.address as u8, &[0x01, config[0], config[1]])
63 .await?;
64
65 loop {
66 self.i2c
67 .write_read(self.address as u8, &[0x01], &mut config)
68 .await?;
69 if (config[0] & 0x80) != 0 {
70 break;
71 }
72 }
73
74 self.i2c
75 .write_read(self.address as u8, &[0x00], &mut data)
76 .await?;
77 Ok(i16::from_be_bytes(data))
78 }
79
80 pub async fn read_asyncadc(&mut self) -> Result<i16, I2C::Error> {
81 self.read_channel_asyncraw().await
82 }
83}
84
85impl<I2C> ADS1114<I2C> {
86 pub fn new(i2c: I2C, config: Config) -> Self {
87 Self {
88 address: Address::Ground,
89 i2c,
90 config,
91 }
92 }
93}
94
95impl<I2C: I2c> ADS1114<I2C> {
96 pub fn enable_conversion_ready_pin(&mut self) -> Result<(), I2C::Error> {
99 self.i2c.write(self.address as u8, &[0x03, 0x80, 0x00])?;
101 self.i2c.write(self.address as u8, &[0x02, 0x00, 0x00])?;
103 Ok(())
104 }
105
106 fn read_channel_raw(&mut self) -> Result<i16, I2C::Error> {
107 let mut config = [
108 (self.config.gain as u8) | (1 << 7) | 1,
109 (self.config.comp_que as u8)
110 | (self.config.comp_lat as u8)
111 | (self.config.comp_pol as u8)
112 | (self.config.comp_mode as u8)
113 | (self.config.data_rate as u8),
114 ];
115 let mut data = [0u8; 2];
116
117 self.i2c
118 .write(self.address as u8, &[0x01, config[0], config[1]])?;
119
120 loop {
121 self.i2c
122 .write_read(self.address as u8, &[0x01], &mut config)?;
123 if (config[0] & 0x80) != 0 {
124 break;
125 }
126 }
127
128 self.i2c
129 .write_read(self.address as u8, &[0x00], &mut data)?;
130 Ok(i16::from_be_bytes(data))
131 }
132
133 pub fn read_adc(&mut self) -> Result<i16, I2C::Error> {
134 self.read_channel_raw()
135 }
136}
137
138#[cfg(feature = "async")]
139impl<I2C: AsyncI2c> ADS1114<I2C> {
140 pub async fn enable_async_conversion_ready_pin(&mut self) -> Result<(), I2C::Error> {
143 self.i2c
145 .write(self.address as u8, &[0x03, 0x80, 0x00])
146 .await?;
147 self.i2c
149 .write(self.address as u8, &[0x02, 0x00, 0x00])
150 .await?;
151 Ok(())
152 }
153
154 async fn read_channel_asyncraw(&mut self) -> Result<i16, I2C::Error> {
155 let mut config = [
156 (self.config.gain as u8) | (1 << 7) | 1,
157 (self.config.comp_que as u8)
158 | (self.config.comp_lat as u8)
159 | (self.config.comp_pol as u8)
160 | (self.config.comp_mode as u8)
161 | (self.config.data_rate as u8),
162 ];
163 let mut data = [0u8; 2];
164
165 self.i2c
166 .write(self.address as u8, &[0x01, config[0], config[1]])
167 .await?;
168
169 loop {
170 self.i2c
171 .write_read(self.address as u8, &[0x01], &mut config)
172 .await?;
173 if (config[0] & 0x80) != 0 {
174 break;
175 }
176 }
177
178 self.i2c
179 .write_read(self.address as u8, &[0x00], &mut data)
180 .await?;
181 Ok(i16::from_be_bytes(data))
182 }
183
184 pub async fn read_asyncadc(&mut self) -> Result<i16, I2C::Error> {
185 self.read_channel_asyncraw().await
186 }
187}
188
189impl<I2C> ADS1115<I2C> {
190 pub fn new(address: Address, i2c: I2C, config: Config) -> Self {
191 Self {
192 address,
193 i2c,
194 config,
195 }
196 }
197}
198
199impl<I2C: I2c> ADS1115<I2C> {
200 pub fn enable_conversion_ready_pin(&mut self) -> Result<(), I2C::Error> {
203 self.i2c.write(self.address as u8, &[0x03, 0x80, 0x00])?;
205 self.i2c.write(self.address as u8, &[0x02, 0x00, 0x00])?;
207 Ok(())
208 }
209
210 fn read_channel_raw(&mut self, mux: u8) -> Result<i16, I2C::Error> {
211 let mut config = [
212 (self.config.gain as u8) | (1 << 7) | (mux << 4) | 1,
213 (self.config.comp_que as u8)
214 | (self.config.comp_lat as u8)
215 | (self.config.comp_pol as u8)
216 | (self.config.comp_mode as u8)
217 | (self.config.data_rate as u8),
218 ];
219 let mut data = [0u8; 2];
220
221 self.i2c
222 .write(self.address as u8, &[0x01, config[0], config[1]])?;
223
224 loop {
225 self.i2c
226 .write_read(self.address as u8, &[0x01], &mut config)?;
227 if (config[0] & 0x80) != 0 {
228 break;
229 }
230 }
231
232 self.i2c
233 .write_read(self.address as u8, &[0x00], &mut data)?;
234 Ok(i16::from_be_bytes(data))
235 }
236
237 pub fn read_adc_a0(&mut self) -> Result<i16, I2C::Error> {
238 self.read_channel_raw(0b100)
239 }
240
241 pub fn read_adc_a1(&mut self) -> Result<i16, I2C::Error> {
242 self.read_channel_raw(0b101)
243 }
244
245 pub fn read_adc_a2(&mut self) -> Result<i16, I2C::Error> {
246 self.read_channel_raw(0b110)
247 }
248
249 pub fn read_adc_a3(&mut self) -> Result<i16, I2C::Error> {
250 self.read_channel_raw(0b111)
251 }
252
253 pub fn read_adc_a0n1(&mut self) -> Result<i16, I2C::Error> {
254 self.read_channel_raw(0b000)
255 }
256
257 pub fn read_adc_a0n3(&mut self) -> Result<i16, I2C::Error> {
258 self.read_channel_raw(0b001)
259 }
260
261 pub fn read_adc_a1n3(&mut self) -> Result<i16, I2C::Error> {
262 self.read_channel_raw(0b010)
263 }
264
265 pub fn read_adc_a2n3(&mut self) -> Result<i16, I2C::Error> {
266 self.read_channel_raw(0b011)
267 }
268
269 pub fn read_4adc(&mut self) -> Result<[i16; 4], I2C::Error> {
270 let mut values = [0i16; 4];
271 for (i, val) in values.iter_mut().enumerate() {
272 *val = self.read_channel_raw(0b100 + i as u8)?;
273 }
274 Ok(values)
275 }
276}
277
278#[cfg(feature = "async")]
279impl<I2C: AsyncI2c> ADS1115<I2C> {
280 pub async fn enable_async_conversion_ready_pin(&mut self) -> Result<(), I2C::Error> {
283 self.i2c
285 .write(self.address as u8, &[0x03, 0x80, 0x00])
286 .await?;
287 self.i2c
289 .write(self.address as u8, &[0x02, 0x00, 0x00])
290 .await?;
291 Ok(())
292 }
293
294 async fn read_channel_asyncraw(&mut self, mux: u8) -> Result<i16, I2C::Error> {
295 let mut config = [
296 (self.config.gain as u8) | (1 << 7) | (mux << 4) | 1,
297 (self.config.comp_que as u8)
298 | (self.config.comp_lat as u8)
299 | (self.config.comp_pol as u8)
300 | (self.config.comp_mode as u8)
301 | (self.config.data_rate as u8),
302 ];
303 let mut data = [0u8; 2];
304
305 self.i2c
306 .write(self.address as u8, &[0x01, config[0], config[1]])
307 .await?;
308
309 loop {
310 self.i2c
311 .write_read(self.address as u8, &[0x01], &mut config)
312 .await?;
313 if (config[0] & 0x80) != 0 {
314 break;
315 }
316 }
317
318 self.i2c
319 .write_read(self.address as u8, &[0x00], &mut data)
320 .await?;
321 Ok(i16::from_be_bytes(data))
322 }
323
324 pub async fn read_async_adc_a0(&mut self) -> Result<i16, I2C::Error> {
325 self.read_channel_asyncraw(0b100).await
326 }
327
328 pub async fn read_async_adc_a1(&mut self) -> Result<i16, I2C::Error> {
329 self.read_channel_asyncraw(0b101).await
330 }
331
332 pub async fn read_async_adc_a2(&mut self) -> Result<i16, I2C::Error> {
333 self.read_channel_asyncraw(0b110).await
334 }
335
336 pub async fn read_async_adc_a3(&mut self) -> Result<i16, I2C::Error> {
337 self.read_channel_asyncraw(0b111).await
338 }
339
340 pub async fn read_async_adc_a0n1(&mut self) -> Result<i16, I2C::Error> {
341 self.read_channel_asyncraw(0b000).await
342 }
343
344 pub async fn read_async_adc_a0n3(&mut self) -> Result<i16, I2C::Error> {
345 self.read_channel_asyncraw(0b001).await
346 }
347
348 pub async fn read_async_adc_a1n3(&mut self) -> Result<i16, I2C::Error> {
349 self.read_channel_asyncraw(0b010).await
350 }
351
352 pub async fn read_async_adc_a2n3(&mut self) -> Result<i16, I2C::Error> {
353 self.read_channel_asyncraw(0b011).await
354 }
355
356 pub async fn read_async_4adc(&mut self) -> Result<[i16; 4], I2C::Error> {
357 let mut values = [0i16; 4];
358 for (i, val) in values.iter_mut().enumerate() {
359 *val = self.read_channel_asyncraw(0b100 + i as u8).await?;
360 }
361 Ok(values)
362 }
363}
364
365#[derive(Debug, Clone, Copy, Default)]
373pub struct Config {
374 pub gain: Gain,
375 pub data_rate: DataRate,
376 pub comp_mode: CompMode,
377 pub comp_pol: CompPol,
378 pub comp_lat: CompLat,
379 pub comp_que: CompQue,
380}
381
382impl Config {
383 pub fn with_gain(self, gain: Gain) -> Self {
384 Self { gain, ..self }
385 }
386
387 pub fn with_data_rate(self, data_rate: DataRate) -> Self {
388 Self { data_rate, ..self }
389 }
390
391 pub fn with_comp_mode(self, comp_mode: CompMode) -> Self {
392 Self { comp_mode, ..self }
393 }
394
395 pub fn with_comp_pol(self, comp_pol: CompPol) -> Self {
396 Self { comp_pol, ..self }
397 }
398
399 pub fn with_comp_lat(self, comp_lat: CompLat) -> Self {
400 Self { comp_lat, ..self }
401 }
402
403 pub fn with_comp_que(self, comp_que: CompQue) -> Self {
404 Self { comp_que, ..self }
405 }
406}
407
408#[derive(Debug, Clone, Copy, Default)]
413#[repr(u8)]
414pub enum Gain {
416 #[default]
417 V6_144 = 0,
418 V4_096 = 1 << 1,
419 V2_048 = 2 << 1,
420 V1_024 = 3 << 1,
421 V0_512 = 4 << 1,
422 V0_256 = 5 << 1,
423}
424
425#[derive(Debug, Clone, Copy, Default)]
429#[repr(u8)]
430pub enum DataRate {
432 SPS8 = 0,
433 SPS16 = 1 << 5,
434 SPS32 = 2 << 5,
435 SPS64 = 3 << 5,
436 SPS128 = 4 << 5,
437 SPS250 = 5 << 5,
438 SPS475 = 6 << 5,
439 #[default]
440 SPS860 = 7 << 5,
441}
442
443#[derive(Debug, Clone, Copy, Default)]
446#[repr(u8)]
447pub enum CompMode {
449 #[default]
450 Traditional = 0,
451 Window = 1 << 4,
452}
453
454#[derive(Debug, Clone, Copy, Default)]
457#[repr(u8)]
458pub enum CompPol {
460 #[default]
461 ActiveLow = 0,
462 ActiveHigh = 1 << 3,
463}
464
465#[derive(Debug, Clone, Copy, Default)]
468#[repr(u8)]
469pub enum CompLat {
471 #[default]
472 NonLatching = 0,
473 Latching = 1 << 2,
474}
475
476#[derive(Debug, Clone, Copy, Default)]
479#[repr(u8)]
480pub enum CompQue {
482 OneConversion = 0,
483 TwoConversions = 1,
484 FourConversions = 2,
485 #[default]
486 DisableComparator = 3,
487}
488
489#[derive(Debug, Clone, Copy, Default)]
490#[repr(u8)]
491pub enum Address {
492 #[default]
493 Ground = 0b1001000,
494 VDD = 0b1001001,
495 SDA = 0b1001010,
496 SCL = 0b1001011,
497}