1#![no_std]
2#![no_main]
3use embedded_hal::digital::{ErrorType, InputPin};
4use embedded_hal::spi::SpiDevice;
5
6#[cfg(feature = "defmt")]
7use defmt::debug;
8use embedded_hal::delay::DelayNs;
9
10pub const BYTES_PER_SAMPLE: u8 = 4;
11
12pub const SPI_MASTER_DUMMY: u8 = 0xFF;
14pub const RESET: u8 = 0x06;
15pub const START: u8 = 0x08;
16pub const WREG: u8 = 0x40;
17pub const RREG: u8 = 0x20;
18
19pub const CONFIG_REG0_ADDRESS: u8 = 0x00;
21pub const CONFIG_REG1_ADDRESS: u8 = 0x01;
22pub const CONFIG_REG2_ADDRESS: u8 = 0x02;
23pub const CONFIG_REG3_ADDRESS: u8 = 0x03;
24
25pub const REG_CONFIG3_IDAC1_ROUTING_MASK: u8 = 0xE0;
26pub const REG_CONFIG3_IDAC2_ROUTING_MASK: u8 = 0x1C;
27pub const REG_CONFIG2_VREF_MASK: u8 = 0xC0;
28pub const REG_CONFIG2_FIR_MASK: u8 = 0x30;
29pub const REG_CONFIG2_IDAC_CURRENT_MASK: u8 = 0x07;
30pub const REG_CONFIG1_MODE_MASK: u8 = 0x18;
31pub const REG_CONFIG1_DR_MASK: u8 = 0xE0;
32pub const REG_CONFIG0_PGA_GAIN_MASK: u8 = 0x0E;
33pub const REG_CONFIG0_MUX_MASK: u8 = 0xF0;
34
35pub const IDAC1_DISABLE: u8 = 0x00;
36pub const IDAC1_AIN0: u8 = 0x20;
37pub const IDAC1_AIN1: u8 = 0x40;
38pub const IDAC1_AIN2: u8 = 0x60;
39pub const IDAC1_AIN3: u8 = 0x80;
40pub const IDAC1_REFP0: u8 = 0xA0;
41pub const IDAC1_REFN0: u8 = 0xC0;
42pub const IDAC1_RESERVED: u8 = 0xE0;
43
44pub const IDAC2_DISABLE: u8 = 0x00;
45pub const IDAC2_AIN0: u8 = 0x04;
46pub const IDAC2_AIN1: u8 = 0x08;
47pub const IDAC2_AIN2: u8 = 0x60;
48pub const IDAC2_AIN3: u8 = 0x0C;
49pub const IDAC2_REFP0: u8 = 0x10;
50pub const IDAC2_REFN0: u8 = 0x14;
51pub const IDAC2_RESERVED: u8 = 0x1C;
52
53pub const IDAC_OFF: u8 = 0x00;
54pub const IDAC_10: u8 = 0x01;
55pub const IDAC_50: u8 = 0x02;
56pub const IDAC_100: u8 = 0x03;
57pub const IDAC_250: u8 = 0x04;
58pub const IDAC_500: u8 = 0x05;
59pub const IDAC_1000: u8 = 0x06;
60pub const IDAC_1500: u8 = 0x07;
61
62pub const FIR_OFF: u8 = 0x00;
63pub const FIR_5060: u8 = 0x10;
64pub const FIR_50HZ: u8 = 0x20;
65pub const FIR_60HZ: u8 = 0x30;
66
67pub const VREF_2048: u8 = 0x00;
68pub const VREF_REFP0: u8 = 0x40;
69pub const VREF_AIN0: u8 = 0x80;
70pub const VREF_ANALOG: u8 = 0xC0;
71
72pub const MODE_NORMAL: u8 = 0x00;
73pub const MODE_DUTY_CYCLE: u8 = 0x08;
74pub const MODE_TURBO: u8 = 0x10;
75pub const MODE_RESERVED: u8 = 0x18;
76
77pub const DR_20SPS: u8 = 0x00;
78pub const DR_45SPS: u8 = 0x02;
79pub const DR_90SPS: u8 = 0x04;
80pub const DR_175SPS: u8 = 0x06;
81pub const DR_330SPS: u8 = 0x08;
82pub const DR_600SPS: u8 = 0xA0;
83pub const DR_1000SPS: u8 = 0xC0;
84
85pub const PGA_GAIN_1: u8 = 0x00;
86pub const PGA_GAIN_2: u8 = 0x02;
87pub const PGA_GAIN_4: u8 = 0x04;
88pub const PGA_GAIN_8: u8 = 0x06;
89pub const PGA_GAIN_16: u8 = 0x08;
90pub const PGA_GAIN_32: u8 = 0x0A;
91pub const PGA_GAIN_64: u8 = 0x0C;
92pub const PGA_GAIN_128: u8 = 0x0E;
93
94pub const MUX_AIN0_AIN1: u8 = 0x00;
95pub const MUX_AIN0_AIN2: u8 = 0x10;
96pub const MUX_AIN0_AIN3: u8 = 0x20;
97pub const MUX_AIN1_AIN2: u8 = 0x30;
98pub const MUX_AIN1_AIN3: u8 = 0x40;
99pub const MUX_AIN2_AIN3: u8 = 0x50;
100pub const MUX_AIN1_AIN0: u8 = 0x60;
101pub const MUX_AIN3_AIN2: u8 = 0x70;
102pub const MUX_AIN0_AVSS: u8 = 0x80;
103pub const MUX_AIN1_AVSS: u8 = 0x90;
104pub const MUX_AIN2_AVSS: u8 = 0xA0;
105pub const MUX_AIN3_AVSS: u8 = 0xB0;
106
107pub const MUX_SE_CH0: u8 = 0x80;
108pub const MUX_SE_CH1: u8 = 0x90;
109pub const MUX_SE_CH2: u8 = 0xA0;
110pub const MUX_SE_CH3: u8 = 0xB0;
111
112pub const VREF_MASK: u8 = (1 << 6) | (1 << 7);
113pub const VREF_INT: u8 = 0 << 6;
114pub const VREF_EXT: u8 = 1 << 6;
115
116pub struct ADS1220<SPI, DR> {
117 spi: SPI,
118 dr: DR,
119 m_config_reg0: u8,
120 m_config_reg1: u8,
121 m_config_reg2: u8,
122 m_config_reg3: u8,
123}
124
125#[derive(Copy, Clone, Debug)]
126pub enum ADS1220Error<SPI, DR> {
127 Spi(SPI),
128 Dr(DR),
129 }
131
132impl<SPI, DR> ADS1220<SPI, DR>
133where
134 SPI: SpiDevice,
135 DR: InputPin,
136{
137 pub fn new(
138 spi: SPI,
139 dr: DR,
140 ) -> Self {
141 ADS1220 {
142 spi,
143 dr,
144 m_config_reg0: 0x00,
145 m_config_reg1: 0x00,
146 m_config_reg2: 0x00,
147 m_config_reg3: 0x00,
148 }
149 }
150
151 pub fn write_register(&mut self, address: u8, value: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
152 self.spi.write(&[WREG | (address << 2)]).map_err(ADS1220Error::Spi)?;
153 self.spi.write(&mut [value]).map_err(ADS1220Error::Spi)?;
154 Ok(())
155 }
156
157 pub fn read_register(&mut self, address: u8) -> Result<u8, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
158 let mut result: [u8; 1] = [0x00];
159 self.spi.write(&[RREG | (address << 2)]).map_err(ADS1220Error::Spi)?;
160 self.spi.write(&[SPI_MASTER_DUMMY]).map_err(ADS1220Error::Spi)?;
161 self.spi.read(&mut result).map_err(ADS1220Error::Spi)?;
162 Ok(result[0])
163 }
164
165 pub fn begin(&mut self, delay: &mut dyn DelayNs) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
166 self.reset()?;
167 delay.delay_us(50);
168
169 self.m_config_reg0 = 0x00; self.m_config_reg1 = 0x04; self.m_config_reg2 = 0x10; self.m_config_reg3 = 0x00; self.write_register(CONFIG_REG0_ADDRESS, self.m_config_reg0)?;
175 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)?;
176 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)?;
177 self.write_register(CONFIG_REG3_ADDRESS, self.m_config_reg3)?;
178 Ok(())
179 }
180
181 #[cfg(feature = "defmt")]
182 pub fn print_register_values(&mut self) {
183 let config_reg0 = self.read_register(CONFIG_REG0_ADDRESS).unwrap();
184 let config_reg1 = self.read_register(CONFIG_REG1_ADDRESS).unwrap();
185 let config_reg2 = self.read_register(CONFIG_REG2_ADDRESS).unwrap();
186 let config_reg3 = self.read_register(CONFIG_REG3_ADDRESS).unwrap();
187
188 debug!("Config_Reg : ");
189 debug!("{:#04X}", config_reg0);
190 debug!("{:#04X}", config_reg1);
191 debug!("{:#04X}", config_reg2);
192 debug!("{:#04X}", config_reg3);
193 }
194
195 pub fn spi_command(&mut self, data: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
196 self.spi.write(&mut [data]).map_err(ADS1220Error::Spi)?;
197 Ok(())
198 }
199
200 pub fn reset(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
201 self.spi_command(RESET)
202 }
203
204 pub fn start_conv(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
205 self.spi_command(START)
206 }
207
208 pub fn select_mux_channels(&mut self, channels_conf: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
209 self.m_config_reg0 &= !REG_CONFIG0_MUX_MASK;
210 self.m_config_reg0 |= channels_conf;
211 self.write_register(CONFIG_REG0_ADDRESS, self.m_config_reg0)
212 }
213
214 pub fn set_pga_gain(&mut self, pga_gain: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
215 self.m_config_reg0 &= !REG_CONFIG0_PGA_GAIN_MASK;
216 self.m_config_reg0 |= pga_gain;
217 self.write_register(CONFIG_REG0_ADDRESS, self.m_config_reg0)
218 }
219
220 pub fn pga_on(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
221 self.m_config_reg0 &= !(1 << (0));
222 self.write_register(CONFIG_REG0_ADDRESS, self.m_config_reg0)
223 }
224
225 pub fn pga_off(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
226 self.m_config_reg0 |= !(1 << (0));
227 self.write_register(CONFIG_REG0_ADDRESS, self.m_config_reg0)
228 }
229
230 pub fn set_data_rate(&mut self, data_rate: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
231 self.m_config_reg1 &= !REG_CONFIG1_DR_MASK;
232 self.m_config_reg1 |= data_rate;
233 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
234 }
235
236 pub fn set_operation_mode(&mut self, mode: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
237 self.m_config_reg1 &= !REG_CONFIG1_MODE_MASK;
238 self.m_config_reg1 |= mode;
239 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
240 }
241
242 pub fn set_conv_mode_single_shot(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
243 self.m_config_reg1 |= !(1 << (2));
244 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
245 }
246
247 pub fn set_conv_mode_continuous(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
248 self.m_config_reg1 |= 1 << (2);
249 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
250 }
251
252 pub fn temp_sensor_mode_disable(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
253 self.m_config_reg1 &= !(1 << (1));
254 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
255 }
256
257 pub fn temp_sensor_mode_enable(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
258 self.m_config_reg1 |= 1 << (1);
259 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
260 }
261
262 pub fn current_sources_off(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
263 self.m_config_reg1 &= !(1 << (0));
264 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
265 }
266
267 pub fn current_sources_on(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
268 self.m_config_reg1 |= 1 << (0);
269 self.write_register(CONFIG_REG1_ADDRESS, self.m_config_reg1)
270 }
271
272 pub fn set_vref(&mut self, vref: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
273 self.m_config_reg2 &= !REG_CONFIG2_VREF_MASK;
274 self.m_config_reg2 |= vref;
275 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
276 }
277
278 pub fn set_fir_filter(&mut self, filter: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
279 self.m_config_reg2 &= !REG_CONFIG2_FIR_MASK;
280 self.m_config_reg2 |= filter;
281 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
282 }
283
284 pub fn low_side_switch_open(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
285 self.m_config_reg2 &= !(1 << (3));
286 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
287 }
288
289 pub fn low_side_switch_closed(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
290 self.m_config_reg2 |= 1 << (3);
291 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
292 }
293
294 pub fn set_idac_current(&mut self, idac_current: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
295 self.m_config_reg2 &= !REG_CONFIG2_IDAC_CURRENT_MASK;
296 self.m_config_reg2 |= idac_current;
297 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
298 }
299
300 pub fn set_idac1_route(&mut self, idac1_routing: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
301 self.m_config_reg3 &= !REG_CONFIG3_IDAC1_ROUTING_MASK;
302 self.m_config_reg3 |= idac1_routing;
303 self.write_register(CONFIG_REG3_ADDRESS, self.m_config_reg3)
304 }
305
306 pub fn set_idac2_route(&mut self, idac2_routing: u8) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
307 self.m_config_reg3 &= !REG_CONFIG3_IDAC2_ROUTING_MASK;
308 self.m_config_reg3 |= idac2_routing;
309 self.write_register(CONFIG_REG3_ADDRESS, self.m_config_reg3)
310 }
311
312 pub fn set_drdy_mode_default(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
313 self.m_config_reg3 &= !(1 << (3));
314 self.write_register(CONFIG_REG3_ADDRESS, self.m_config_reg3)
315 }
316
317 pub fn set_drdy_mode_dout(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
318 self.m_config_reg3 |= 1 << (3);
319 self.write_register(CONFIG_REG3_ADDRESS, self.m_config_reg3)
320 }
321
322 pub fn set_internal_reference(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
323 self.m_config_reg2 &= !VREF_MASK;
324 self.m_config_reg2 |= VREF_INT;
325 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
326 }
327
328 pub fn set_external_reference(&mut self) -> Result<(), ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
329 self.m_config_reg2 &= !VREF_MASK;
330 self.m_config_reg2 |= VREF_EXT;
331 self.write_register(CONFIG_REG2_ADDRESS, self.m_config_reg2)
332 }
333
334 pub fn get_config_reg(&mut self) -> Result<[u8; 4], ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
335 self.m_config_reg0 = self.read_register(CONFIG_REG0_ADDRESS)?;
336 self.m_config_reg1 = self.read_register(CONFIG_REG1_ADDRESS)?;
337 self.m_config_reg2 = self.read_register(CONFIG_REG2_ADDRESS)?;
338 self.m_config_reg3 = self.read_register(CONFIG_REG3_ADDRESS)?;
339
340 Ok([
341 self.m_config_reg0,
342 self.m_config_reg1,
343 self.m_config_reg2,
344 self.m_config_reg3
345 ])
346 }
347
348 pub fn wait_for_data(&mut self, delay: &mut dyn DelayNs, mut timeout_ms: u64) -> bool {
349 while self.dr.is_high().unwrap() {
350 if timeout_ms > 0 {
351 delay.delay_ms(1);
352 timeout_ms -= 1;
353 } else {
354 return false;
355 }
356 }
357 true
358 }
359
360 pub fn read_data(&mut self) -> Result<[u8; 3], ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
361 let mut buf: [u8; 3] = [0x00; 3];
362 self.spi.read(&mut buf).map_err(ADS1220Error::Spi)?;
363 Ok(buf)
364 }
365
366 pub fn data_to_int(&mut self, data: [u8; 3]) -> i32 {
367 let mut result: i32;
368 result = data[0] as i32;
369 result = (result << 8) | data[1] as i32;
370 result = (result << 8) | data[2] as i32;
371
372 if (data[0] & (1 << 7)) == 0 {
373 result |= 0xFF000000u32 as i32;
374 }
375 result
376 }
377
378 pub fn read_wait_for_data(&mut self, delay: &mut dyn DelayNs) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
379 if !self.wait_for_data(delay, 60) {
380 return Ok(0);
381 }
382 self.read_data().map(|t| self.data_to_int(t))
383 }
384
385 pub fn read_data_samples(&mut self) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
386 let mut buf: [u8; 3] = [0x00; 3];
387 let result: i32;
388 let mut bit24: i32;
389
390 self.spi.read(&mut buf).map_err(ADS1220Error::Spi)?;
391
392 bit24 = buf[0] as i32;
393 bit24 = (bit24 << 8) | buf[1] as i32;
394 bit24 = (bit24 << 8) | buf[2] as i32;
395 bit24 = bit24 << 8;
396 result = bit24 >> 8;
397 Ok(result)
398 }
399
400 pub fn read_single_shot(&mut self) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
401 self.start_conv()?;
402 self.read_data().map(|t| self.data_to_int(t))
403 }
404
405 pub fn read_single_shot_wait_for_data(&mut self, delay: &mut dyn DelayNs) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
406 self.start_conv()?;
407 self.read_wait_for_data(delay)
408 }
409
410 pub fn read_single_shot_single_ended(&mut self, channels_conf: u8) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
411 self.select_mux_channels(channels_conf)?;
412 self.read_single_shot()
413 }
414
415 pub fn read_single_shot_single_ended_wait_for_data(&mut self, delay: &mut dyn DelayNs, channels_conf: u8) -> Result<i32, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
416 self.select_mux_channels(channels_conf)?;
417 self.read_single_shot_wait_for_data(delay)
418 }
419
420 pub fn data_ready(&mut self) -> Result<bool, ADS1220Error<SPI::Error, <DR as ErrorType>::Error>> {
421 self.dr.is_low().map_err(ADS1220Error::Dr)
422 }
423
424 #[cfg(feature = "defmt")]
425 pub fn status(&mut self) {
426 let ready = self.data_ready().unwrap();
428 let pending = if ready { BYTES_PER_SAMPLE } else { 0 };
429 debug!("ads1220 status: ready={}, pending_bytes={:#X}", ready, pending)
430 }
431}