1#![no_std]
23#![allow(dead_code)]
24
25extern crate embedded_hal as hal;
26#[macro_use]
27extern crate nb;
28
29use core::fmt::Debug;
30
31use hal::spi::FullDuplex;
32use hal::digital::v2::{InputPin, OutputPin};
33
34
35const SW_RST: u8 = 0x04;
37
38mod registers {
42 pub const CONTROL0: u8 = 0x00;
43 pub const LED2STC: u8 = 0x01;
44 pub const LED2ENDC: u8 = 0x02;
45 pub const LED2LEDSTC: u8 = 0x03;
46 pub const LED2LEDENDC: u8 = 0x04;
47 pub const ALED2STC: u8 = 0x05;
48 pub const ALED2ENDC: u8 = 0x06;
49
50 pub const LED1STC: u8 = 0x07;
51 pub const LED1ENDC: u8 = 0x08;
52 pub const LED1LEDSTC: u8 = 0x09;
53 pub const LED1LEDENDC: u8 = 0x0A;
54 pub const ALED1STC: u8 = 0x0B;
55 pub const ALED1ENDC: u8 = 0x0C;
56
57 pub const LED2CONVST: u8 = 0x0D;
58 pub const LED2CONVEND: u8 = 0x0E;
59 pub const ALED2CONVST: u8 = 0x0F;
60 pub const ALED2CONVEND: u8 = 0x10;
61
62 pub const LED1CONVST: u8 = 0x11;
63 pub const LED1CONVEND: u8 = 0x12;
64 pub const ALED1CONVST: u8 = 0x13;
65 pub const ALED1CONVEND: u8 = 0x14;
66
67 pub const ADCRSTSTCT0: u8 = 0x15;
68 pub const ADCRSTENDCT0: u8 = 0x16;
69 pub const ADCRSTSTCT1: u8 = 0x17;
70 pub const ADCRSTENDCT1: u8 = 0x18;
71 pub const ADCRSTSTCT2: u8 = 0x19;
72 pub const ADCRSTENDCT2: u8 = 0x1A;
73 pub const ADCRSTSTCT3: u8 = 0x1B;
74 pub const ADCRSTENDCT3: u8 = 0x1C;
75
76 pub const PRPCOUNT: u8 = 0x1D;
77
78 pub const CONTROL1: u8 = 0x1E;
79 pub const TIAGAIN: u8 = 0x20;
80 pub const TIA_AMB_GAIN: u8 = 0x21;
81 pub const LEDCNTRL: u8 = 0x22;
82 pub const CONTROL2: u8 = 0x23;
83
84 pub const ALARM: u8 = 0x29;
85 pub const LED2VAL: u8 = 0x2A;
86 pub const ALED2VAL: u8 = 0x2B;
87 pub const LED1VAL: u8 = 0x2C;
88 pub const ALED1VAL: u8 = 0x2D;
89 pub const LED2_ALED2VAL: u8 = 0x2E;
90 pub const LED1_ALED1VAL: u8 = 0x2F;
91
92 pub const DIAG: u8 = 0x30;
93}
94
95pub struct Afe4400<SPI: FullDuplex<u8>, IN: InputPin, OUT: OutputPin> {
97 pub spi: SPI,
98 pub diag_end: Option<IN>,
99 pub adc_done: Option<IN>,
100 pub led_err: Option<IN>,
101 pub sensor_err: Option<IN>,
102 pub afe_pdn: OUT,
103 pub adc_rdy: IN
104}
105
106pub enum LEDSource {
107 LED,
108 AMB,
109 LEDAMB,
110}
111
112#[derive(Debug)]
116pub enum Error<E: Debug> {
117 SelfCheckFail,
118 InvalidSetting,
119 Other(E),
120}
121
122impl<E: Debug> From<E> for Error<E> {
123 fn from(error: E) -> Self {
124 Error::Other(error)
125 }
126}
127
128type SpiError<SPI> = <SPI as FullDuplex<u8>>::Error;
129type AfeError<SPI> = Error<SpiError<SPI>>;
130
131impl<SPI, IN, OUT> Afe4400<SPI, IN, OUT>
132 where SPI: FullDuplex<u8>,
133 IN: InputPin,
134 OUT: OutputPin,
135 <SPI as FullDuplex<u8>>::Error: Debug
136{
137
138 pub fn write_data(&mut self, register: u8, data: u32) -> Result<(), AfeError<SPI>> {
144 block!(self.spi.send(register))?;
145 let first_transfer = ((data >> 16) & 0xFF) as u8;
146 let second_transfer = ((data >> 8) & 0xFF) as u8;
147 let third_transfer = (data & 0xFF) as u8;
148 block!(self.spi.send(first_transfer))?;
149 block!(self.spi.send(second_transfer))?;
150 block!(self.spi.send(third_transfer))?;
151 Ok(())
152 }
153
154 pub fn read_data(&mut self, register: u8) -> Result<u32, AfeError<SPI>> {
160 self.write_data(registers::CONTROL0, 0x01 as u32)?;
161 block!(self.spi.send(register))?;
162 let mut register_data: u32 = 0;
163 for _ in 0..3 {
164 register_data = register_data << 8;
165 register_data |= block!(self.spi.read())? as u32;
166 }
167 self.write_data(registers::CONTROL0, 0x00 as u32)?;
168 Ok(register_data)
169 }
170
171 #[allow(overflowing_literals)]
172 fn get_led_data(&mut self, led_register: u8) -> Result<i32, AfeError<SPI>> {
173 let mut value = self.read_data(led_register)? as i32;
174 if value & 0x00200000 != 0 {
175 value |= 0xFFC00000;
176 }
177 Ok(value)
178 }
179
180 pub fn get_led1_data(&mut self, source: LEDSource) -> Result<i32, AfeError<SPI>> {
182 match source {
183 LEDSource::LED => self.get_led_data(registers::LED1VAL),
184 LEDSource::AMB => self.get_led_data(registers::ALED1VAL),
185 LEDSource::LEDAMB => self.get_led_data(registers::LED1_ALED1VAL),
186 }
187 }
188
189 pub fn get_led2_data(&mut self, source: LEDSource) -> Result<i32, AfeError<SPI>> {
191 match source {
192 LEDSource::LED => self.get_led_data(registers::LED2VAL),
193 LEDSource::AMB => self.get_led_data(registers::ALED2VAL),
194 LEDSource::LEDAMB => self.get_led_data(registers::LED2_ALED2VAL),
195 }
196 }
197
198 pub fn set_cancellation_current(&mut self, current: u8) -> Result<(), AfeError<SPI>> {
199 if current > 0b1010 {
200 Err(Error::InvalidSetting)
201 } else {
202 let mask = 0b1111 << 16;
203 let mut tia_settings = self.read_data(registers::TIA_AMB_GAIN)?;
204 tia_settings &= !mask;
205 tia_settings |= (current as u32) << 16;
206 self.write_data(registers::TIA_AMB_GAIN, tia_settings)?;
207 Ok(())
208 }
209 }
210
211 pub fn set_second_stage_gain(&mut self, gain: u8, enabled: bool) -> Result<(), AfeError<SPI>> {
212 if gain > 0b0100 {
213 Err(Error::InvalidSetting)
214 } else {
215 let mask = (0b01 << 14) & (0b0111 << 8);
216 let mut tia_settings = self.read_data(registers::TIA_AMB_GAIN)?;
217 tia_settings &= !mask;
218 tia_settings |= (gain as u32) << 8;
219 tia_settings |= if enabled { 0b01 << 14 } else { 0b00 << 14 };
220 self.write_data(registers::TIA_AMB_GAIN, tia_settings)?;
221 Ok(())
222 }
223 }
224
225 pub fn set_first_stage_cap(&mut self, cap_value: u8) -> Result<(), AfeError<SPI>> {
226 if cap_value > 0b11111 {
227 Err(Error::InvalidSetting)
228 } else {
229 let mask = 0b011111 << 3;
230 let mut tia_settings = self.read_data(registers::TIA_AMB_GAIN)?;
231 tia_settings &= !mask;
232 tia_settings |= (cap_value as u32) << 3;
233 self.write_data(registers::TIA_AMB_GAIN, tia_settings)?;
234 Ok(())
235 }
236 }
237
238 pub fn set_first_stage_gain(&mut self, rf_value: u8) -> Result<(), AfeError<SPI>> {
239 if rf_value > 0b111 {
240 Err(Error::InvalidSetting)
241 } else {
242 let mask = 0b0111;
243 let mut tia_settings = self.read_data(registers::TIA_AMB_GAIN)?;
244 tia_settings &= !mask;
245 tia_settings |= rf_value as u32;
246 self.write_data(registers::TIA_AMB_GAIN, tia_settings)?;
247 Ok(())
248 }
249 }
250
251 pub fn set_led_current(&mut self, value: u8) -> Result<u32, AfeError<SPI>> {
264 let both_leds = ((value as u32) << 8) + value as u32;
265 self.write_data(registers::LEDCNTRL, both_leds)?;
266 self.read_data(registers::LEDCNTRL)
267 }
268
269 pub fn get_led_current(&mut self) -> Result<u8, AfeError<SPI>> {
270 Ok((self.read_data(registers::LEDCNTRL)? & 0x00FF) as u8)
271 }
272
273 pub fn default_pulse_timings(&mut self) -> Result<(), AfeError<SPI>> {
275 self.write_data(registers::CONTROL0, 0x000000)?;
276 self.write_data(registers::CONTROL1, 0x0102)?; self.write_data(registers::CONTROL2, 0x000100)?;
278 self.write_data(registers::LED2STC, 6050)?;
279 self.write_data(registers::LED2ENDC, 7998)?;
280 self.write_data(registers::LED2LEDSTC, 6000)?;
281 self.write_data(registers::LED2LEDENDC, 7999)?;
282 self.write_data(registers::ALED2STC, 50)?;
283 self.write_data(registers::ALED2ENDC, 1998)?;
284 self.write_data(registers::LED1STC, 2050)?;
285 self.write_data(registers::LED1ENDC, 3998)?;
286 self.write_data(registers::LED1LEDSTC, 2000)?;
287 self.write_data(registers::LED1LEDENDC, 3999)?;
288 self.write_data(registers::ALED1STC, 4050)?;
289 self.write_data(registers::ALED1ENDC, 5998)?;
290 self.write_data(registers::LED2CONVST, 4)?;
291 self.write_data(registers::LED2CONVEND, 1999)?;
292 self.write_data(registers::ALED2CONVST, 2004)?;
293 self.write_data(registers::ALED2CONVEND, 3999)?;
294 self.write_data(registers::LED1CONVST, 4004)?;
295 self.write_data(registers::LED1CONVEND, 5999)?;
296 self.write_data(registers::ALED1CONVST, 6004)?;
297 self.write_data(registers::ALED1CONVEND, 7999)?;
298 self.write_data(registers::ADCRSTSTCT0, 0)?;
299 self.write_data(registers::ADCRSTENDCT0, 3)?;
300 self.write_data(registers::ADCRSTSTCT1, 2000)?;
301 self.write_data(registers::ADCRSTENDCT1, 2003)?;
302 self.write_data(registers::ADCRSTSTCT2, 4000)?;
303 self.write_data(registers::ADCRSTENDCT2, 4003)?;
304 self.write_data(registers::ADCRSTSTCT3, 6000)?;
305 self.write_data(registers::ADCRSTENDCT3, 6003)?;
306 self.write_data(registers::PRPCOUNT, 7999)?;
307 Ok(())
310 }
311
312 pub fn self_check(&mut self) -> Result<(), AfeError<SPI>> {
316 let original_value = self.read_data(registers::CONTROL1)?;
317 for _ in 0..5 {
318 if self.read_data(registers::CONTROL1)? != original_value {
319 return Err(Error::SelfCheckFail);
320 }
321 }
322 if self.read_data(registers::CONTROL1)? != 0 {
323 Ok(())
324 } else {
325 Err(Error::SelfCheckFail)
326 }
327 }
328
329}