1use crate::{
6 device_type::{DeviceCapabilities, DeviceType},
7 errors::*,
8 registers::*,
9};
10use heapless::Vec;
11
12pub const AD7124_DEFAULT_TIMEOUT_MS: u32 = 5000; #[derive(Debug)]
17pub struct AD7124Core {
18 device_type: DeviceType,
20 capabilities: DeviceCapabilities,
22 config: AD7124Config,
24 initialized: bool,
26 reference_voltage: f32,
28 crc_enabled: bool,
30 channel_configs: [ChannelConfig; 16],
33 setup_configs: [SetupConfig; 8],
35}
36
37#[derive(Debug, Clone, Copy)]
39pub struct AD7124Config {
40 pub operating_mode: OperatingMode,
42 pub power_mode: PowerMode,
44 pub clock_source: ClockSource,
46 pub reference_source: ReferenceSource,
48 pub internal_ref_enabled: bool,
50 pub data_ready_output_enabled: bool,
52}
53
54impl Default for AD7124Config {
55 fn default() -> Self {
56 Self {
57 operating_mode: OperatingMode::Continuous,
58 power_mode: PowerMode::FullPower,
59 clock_source: ClockSource::Internal,
60 reference_source: ReferenceSource::Internal,
61 internal_ref_enabled: true,
62 data_ready_output_enabled: true,
63 }
64 }
65}
66
67#[derive(Debug, Clone, Copy)]
69pub struct ChannelConfig {
70 pub enabled: bool,
72 pub positive_input: ChannelInput,
74 pub negative_input: ChannelInput,
76 pub setup_index: u8,
78}
79
80impl Default for ChannelConfig {
81 fn default() -> Self {
82 Self {
83 enabled: false,
84 positive_input: ChannelInput::Ain0,
85 negative_input: ChannelInput::Ain1,
86 setup_index: 0,
87 }
88 }
89}
90
91#[derive(Debug, Clone, Copy)]
93pub struct FilterConfig {
94 pub filter_type: FilterType,
96 pub output_data_rate: u16,
98 pub single_cycle: bool,
100 pub reject_60hz: bool,
102}
103
104impl Default for FilterConfig {
105 fn default() -> Self {
106 Self {
107 filter_type: FilterType::Sinc4,
108 output_data_rate: 50, single_cycle: false,
110 reject_60hz: true,
111 }
112 }
113}
114
115#[derive(Debug, Clone, Copy)]
117pub struct SetupConfig {
118 pub pga_gain: PgaGain,
120 pub reference_source: ReferenceSource,
122 pub bipolar: bool,
124 pub burnout_current: BurnoutCurrent,
126 pub reference_buffers_enabled: bool,
128 pub input_buffers_enabled: bool,
130}
131
132impl Default for SetupConfig {
133 fn default() -> Self {
134 Self {
135 pga_gain: PgaGain::Gain1,
136 reference_source: ReferenceSource::Internal,
137 bipolar: true,
138 burnout_current: BurnoutCurrent::Off,
139 reference_buffers_enabled: true,
140 input_buffers_enabled: true,
141 }
142 }
143}
144
145#[derive(Debug)]
147pub struct CommandSequence {
148 commands: Vec<(Register, u32), 16>, }
151
152impl CommandSequence {
153 pub fn new() -> Self {
155 Self {
156 commands: Vec::new(),
157 }
158 }
159
160 pub fn add_write(&mut self, register: Register, value: u32) -> Result<(), AD7124CoreError> {
162 self.commands
163 .push((register, value))
164 .map_err(|_| AD7124CoreError::BufferOverflow)
165 }
166
167 pub fn commands(&self) -> &[(Register, u32)] {
169 &self.commands
170 }
171
172 pub fn clear(&mut self) {
174 self.commands.clear();
175 }
176}
177
178impl AD7124Core {
179 pub fn new(device_type: DeviceType) -> Result<Self, AD7124CoreError> {
181 let capabilities = DeviceCapabilities::for_device(device_type);
182
183 Ok(Self {
184 device_type,
185 capabilities,
186 config: AD7124Config::default(),
187 initialized: false,
188 reference_voltage: 2.5, crc_enabled: false,
190 channel_configs: [ChannelConfig::default(); 16],
192 setup_configs: [SetupConfig::default(); 8],
193 })
194 }
195
196 pub fn initialization_sequence(&self) -> Result<CommandSequence, AD7124CoreError> {
198 let mut sequence = CommandSequence::new();
199
200 sequence.add_write(Register::AdcCtrl, 0x8000)?; let adc_ctrl = self.build_adc_control_value()?;
205 sequence.add_write(Register::AdcCtrl, adc_ctrl)?;
206
207 let io_ctrl1 = 0x000000; sequence.add_write(Register::IoCtrl1, io_ctrl1)?;
210
211 Ok(sequence)
212 }
213
214 pub fn configure_channel(
216 &self,
217 channel: u8,
218 config: ChannelConfig,
219 ) -> Result<CommandSequence, AD7124CoreError> {
220 if !self.capabilities.validate_channel(channel) {
221 return Err(AD7124CoreError::InvalidParameter);
222 }
223
224 let mut sequence = CommandSequence::new();
225 let register = match channel {
226 0 => Register::Channel0,
227 1 => Register::Channel1,
228 2 => Register::Channel2,
229 3 => Register::Channel3,
230 4 => Register::Channel4,
231 5 => Register::Channel5,
232 6 => Register::Channel6,
233 7 => Register::Channel7,
234 _ => return Err(AD7124CoreError::InvalidParameter),
235 };
236
237 let channel_value = self.build_channel_value(config)?;
238 sequence.add_write(register, channel_value)?;
239
240 Ok(sequence)
241 }
242
243 pub fn configure_setup(
245 &self,
246 setup_index: u8,
247 config: SetupConfig,
248 ) -> Result<CommandSequence, AD7124CoreError> {
249 if setup_index > 7 {
250 return Err(AD7124CoreError::InvalidParameter);
251 }
252
253 let mut sequence = CommandSequence::new();
254 let register = match setup_index {
255 0 => Register::Config0,
256 1 => Register::Config1,
257 2 => Register::Config2,
258 3 => Register::Config3,
259 4 => Register::Config4,
260 5 => Register::Config5,
261 6 => Register::Config6,
262 7 => Register::Config7,
263 _ => return Err(AD7124CoreError::InvalidParameter),
264 };
265
266 let config_value = self.build_setup_value(config)?;
267 sequence.add_write(register, config_value)?;
268
269 Ok(sequence)
270 }
271
272 pub fn configure_filter(
274 &self,
275 setup_index: u8,
276 config: FilterConfig,
277 ) -> Result<CommandSequence, AD7124CoreError> {
278 if setup_index > 7 {
279 return Err(AD7124CoreError::InvalidParameter);
280 }
281
282 let mut sequence = CommandSequence::new();
283 let register = match setup_index {
284 0 => Register::Filter0,
285 1 => Register::Filter1,
286 2 => Register::Filter2,
287 3 => Register::Filter3,
288 4 => Register::Filter4,
289 5 => Register::Filter5,
290 6 => Register::Filter6,
291 7 => Register::Filter7,
292 _ => return Err(AD7124CoreError::InvalidParameter),
293 };
294
295 let filter_value = self.build_filter_value(config)?;
296 sequence.add_write(register, filter_value)?;
297
298 Ok(sequence)
299 }
300
301 pub fn verify_device_id(&self, id: u8) -> Result<DeviceType, AD7124CoreError> {
303 let device_type = DeviceType::from_device_id(id);
304 if device_type == DeviceType::Unknown {
305 return Err(AD7124CoreError::InvalidDeviceId);
306 }
307 Ok(device_type)
308 }
309
310 pub fn raw_to_voltage(
312 &self,
313 raw_data: u32,
314 pga_gain: PgaGain,
315 bipolar: bool,
316 ) -> Result<f32, AD7124CoreError> {
317 if raw_data > 0xFFFFFF {
318 return Err(AD7124CoreError::ValueOutOfRange);
320 }
321
322 let gain = pga_gain.value() as f32;
323 let full_scale = if bipolar {
324 0x800000 as f32 } else {
326 0xFFFFFF as f32 };
328
329 let voltage = if bipolar {
330 let signed_data = raw_data as i32 - 0x800000;
332 (signed_data as f32 / full_scale) * self.reference_voltage / gain
333 } else {
334 (raw_data as f32 / full_scale) * self.reference_voltage / gain
336 };
337
338 Ok(voltage)
339 }
340
341 pub fn config(&self) -> &AD7124Config {
343 &self.config
344 }
345
346 pub fn set_config(&mut self, config: AD7124Config) {
348 self.config = config;
349 }
350
351 pub fn capabilities(&self) -> &DeviceCapabilities {
353 &self.capabilities
354 }
355
356 pub fn device_type(&self) -> DeviceType {
358 self.device_type
359 }
360
361 pub fn is_initialized(&self) -> bool {
363 self.initialized
364 }
365
366 pub fn set_initialized(&mut self) {
368 self.initialized = true;
369 }
370
371 pub fn set_reference_voltage(&mut self, voltage: f32) -> Result<(), AD7124CoreError> {
373 if voltage <= 0.0 || voltage > 5.0 {
374 return Err(AD7124CoreError::ValueOutOfRange);
375 }
376 self.reference_voltage = voltage;
377 Ok(())
378 }
379
380 pub fn reference_voltage(&self) -> f32 {
382 self.reference_voltage
383 }
384
385 pub fn set_crc_enabled(&mut self, enabled: bool) {
387 self.crc_enabled = enabled;
388 }
389
390 pub fn is_crc_enabled(&self) -> bool {
392 self.crc_enabled
393 }
394
395 fn build_adc_control_value(&self) -> Result<u32, AD7124CoreError> {
397 let mut value = 0u32;
398
399 value |= (self.config.operating_mode as u32) & 0x07;
401
402 value |= ((self.config.power_mode as u32) & 0x03) << 6;
404
405 value |= ((self.config.clock_source as u32) & 0x03) << 4;
407
408 if self.config.internal_ref_enabled {
411 value |= 1 << 8;
412 }
413
414 if self.config.data_ready_output_enabled {
416 value |= 1 << 9;
417 }
418
419 Ok(value)
420 }
421
422 pub fn build_adc_control_value_public(&self) -> u32 {
424 self.build_adc_control_value().unwrap_or(0)
425 }
426
427 fn build_channel_value(&self, config: ChannelConfig) -> Result<u32, AD7124CoreError> {
428 let mut value = 0u32;
429
430 if config.enabled {
432 value |= 1 << 15;
433 }
434
435 value |= ((config.setup_index as u32) & 0x07) << 12;
437
438 value |= ((config.positive_input as u32) & 0x1F) << 5;
440
441 value |= (config.negative_input as u32) & 0x1F;
443
444 Ok(value)
445 }
446
447 fn build_setup_value(&self, config: SetupConfig) -> Result<u32, AD7124CoreError> {
448 let mut value = 0u32;
449
450 if config.bipolar {
452 value |= 1 << 11;
453 }
454
455 if config.reference_source == ReferenceSource::Internal {
458 value |= 0x0010; } else {
460 let ref_source_bits = ((config.reference_source as u32) & 0x03) << 4;
462 value |= ref_source_bits;
463 }
464
465 value |= (config.pga_gain as u32) & 0x07;
467
468 value |= ((config.burnout_current as u32) & 0x03) << 8;
470
471 if config.reference_buffers_enabled {
473 value |= 0x03 << 6;
474 }
475
476 if config.input_buffers_enabled {
478 value |= 0x03 << 4;
479 }
480
481 Ok(value)
482 }
483
484 fn build_filter_value(&self, config: FilterConfig) -> Result<u32, AD7124CoreError> {
485 let mut value = 0u32;
486
487 value |= ((config.filter_type as u32) & 0x07) << 21;
489
490 value |= (config.output_data_rate as u32) & 0x7FF;
492
493 if config.single_cycle {
495 value |= 1 << 20;
496 }
497
498 if config.reject_60hz {
500 value |= 1 << 14;
501 }
502
503 if config.reject_60hz {
505 value |= 1 << 13;
506 }
507
508 Ok(value)
509 }
510
511 pub fn get_channel_register(channel: u8) -> Result<Register, AD7124CoreError> {
518 match channel {
519 0 => Ok(Register::Channel0),
520 1 => Ok(Register::Channel1),
521 2 => Ok(Register::Channel2),
522 3 => Ok(Register::Channel3),
523 4 => Ok(Register::Channel4),
524 5 => Ok(Register::Channel5),
525 6 => Ok(Register::Channel6),
526 7 => Ok(Register::Channel7),
527 _ => Err(AD7124CoreError::InvalidParameter),
528 }
529 }
530
531 pub fn get_config_register(setup: u8) -> Result<Register, AD7124CoreError> {
533 match setup {
534 0 => Ok(Register::Config0),
535 1 => Ok(Register::Config1),
536 2 => Ok(Register::Config2),
537 3 => Ok(Register::Config3),
538 4 => Ok(Register::Config4),
539 5 => Ok(Register::Config5),
540 6 => Ok(Register::Config6),
541 7 => Ok(Register::Config7),
542 _ => Err(AD7124CoreError::InvalidParameter),
543 }
544 }
545
546 pub fn get_filter_register(setup: u8) -> Result<Register, AD7124CoreError> {
548 match setup {
549 0 => Ok(Register::Filter0),
550 1 => Ok(Register::Filter1),
551 2 => Ok(Register::Filter2),
552 3 => Ok(Register::Filter3),
553 4 => Ok(Register::Filter4),
554 5 => Ok(Register::Filter5),
555 6 => Ok(Register::Filter6),
556 7 => Ok(Register::Filter7),
557 _ => Err(AD7124CoreError::InvalidParameter),
558 }
559 }
560
561 pub fn get_channel_config(&self, channel: u8) -> Option<&ChannelConfig> {
563 if channel >= 16 {
564 return None;
565 }
566 Some(&self.channel_configs[channel as usize])
567 }
568
569 pub fn update_channel_config(
571 &mut self,
572 channel: u8,
573 config: ChannelConfig,
574 ) -> Result<(), AD7124CoreError> {
575 if !self.capabilities.validate_channel(channel) {
576 return Err(AD7124CoreError::InvalidParameter);
577 }
578
579 self.channel_configs[channel as usize] = config;
580 Ok(())
581 }
582
583 pub fn get_setup_config(&self, setup_index: u8) -> Option<&SetupConfig> {
585 if setup_index >= 8 {
586 return None;
587 }
588 Some(&self.setup_configs[setup_index as usize])
589 }
590
591 pub fn update_setup_config(
593 &mut self,
594 setup_index: u8,
595 config: SetupConfig,
596 ) -> Result<(), AD7124CoreError> {
597 if setup_index >= 8 {
598 return Err(AD7124CoreError::InvalidParameter);
599 }
600
601 self.setup_configs[setup_index as usize] = config;
602 Ok(())
603 }
604
605 pub fn raw_to_voltage_with_setup(
607 &self,
608 raw_data: u32,
609 _setup: u8,
610 bipolar: bool,
611 gain: PgaGain,
612 vref: f32,
613 ) -> f32 {
614 let full_scale = if bipolar {
615 0x800000 as f32 } else {
617 0xFFFFFF as f32 };
619
620 let gain_value = gain.gain_value();
621
622 if bipolar {
623 let signed_data = (raw_data as i32) - 0x800000; (signed_data as f32 / full_scale) * vref / gain_value
626 } else {
627 (raw_data as f32 / full_scale) * vref / gain_value
629 }
630 }
631
632 pub fn get_default_timeout() -> u32 {
634 AD7124_DEFAULT_TIMEOUT_MS
635 }
636
637 pub fn validate_channel(&self, channel: u8) -> bool {
639 self.capabilities.validate_channel(channel)
640 }
641
642 pub fn build_adc_control_register(&self) -> u32 {
644 self.build_adc_control_value().unwrap_or(0)
645 }
646
647 pub fn build_channel_config_value(config: ChannelConfig) -> u32 {
649 let mut value = 0u32;
650
651 if config.enabled {
653 value |= 1 << 15;
654 }
655
656 value |= ((config.setup_index as u32) & 0x07) << 12;
658
659 value |= ((config.positive_input as u32) & 0x1F) << 5;
661
662 value |= (config.negative_input as u32) & 0x1F;
664
665 value
666 }
667
668 pub fn build_setup_config_value(config: SetupConfig) -> u32 {
670 let mut value = 0u32;
671
672 if config.bipolar {
674 value |= 1 << 11;
675 }
676
677 if config.reference_source == ReferenceSource::Internal {
680 value |= 0x0010; } else {
682 let ref_source_bits = ((config.reference_source as u32) & 0x03) << 4;
684 value |= ref_source_bits;
685 }
686
687 value |= (config.pga_gain as u32) & 0x07;
689
690 value |= ((config.burnout_current as u32) & 0x03) << 8;
692
693 if config.reference_buffers_enabled {
695 value |= 0x03 << 6;
696 }
697
698 if config.input_buffers_enabled {
700 value |= 0x03 << 4;
701 }
702
703 value
704 }
705
706 pub fn build_filter_config_value(config: FilterConfig) -> u32 {
708 let mut value = 0u32;
709
710 value |= ((config.filter_type as u32) & 0x07) << 21;
712
713 value |= (config.output_data_rate as u32) & 0x7FF;
715
716 if config.single_cycle {
718 value |= 1 << 20;
719 }
720
721 if config.reject_60hz {
723 value |= 1 << 14;
724 }
725
726 if config.reject_60hz {
728 value |= 1 << 13;
729 }
730
731 value
732 }
733}
734
735impl Default for AD7124Core {
736 fn default() -> Self {
737 Self::new(DeviceType::AD7124_8).unwrap()
738 }
739}