1#![cfg_attr(not(test), no_std)]
2
3pub mod config;
4mod port;
5
6use core::future::Future;
7
8use embassy_sync::blocking_mutex::raw::RawMutex;
9use embassy_sync::mutex::Mutex;
10use embedded_hal::digital::OutputPin;
11use embedded_hal_async::spi::SpiBus;
12use heapless::Vec;
13use seq_macro::seq;
14
15use config::*;
16
17pub use port::{IntoConfiguredPort, IntoMode};
18pub use port::{MaxPort, Mode0Port, Multiport};
19
20#[derive(Debug)]
21pub enum Error<S, P> {
22 Spi(S),
24 Pin(P),
26 Conn,
28 Address,
30 Port,
32 Mode,
34}
35
36pub trait ConfigurePort<CONFIG, S, P> {
37 fn configure_port(
38 &mut self,
39 port: Port,
40 config: CONFIG,
41 ) -> impl Future<Output = Result<(), Error<S, P>>>;
42}
43
44pub struct Max11300<SPI, EN> {
46 channel_config: [Mode; 20],
47 config: DeviceConfig,
48 enable: EN,
49 spi: SPI,
50}
51
52impl<SPI, EN, S, P> Max11300<SPI, EN>
53where
54 SPI: SpiBus<Error = S>,
55 EN: OutputPin<Error = P>,
56{
57 pub async fn try_new(
59 spi: SPI,
60 mut enable: EN,
61 config: DeviceConfig,
62 ) -> Result<Self, Error<S, P>> {
63 enable.set_high().map_err(Error::Pin)?;
64 let mut max = Self {
65 channel_config: [Mode::Mode0(ConfigMode0); 20],
66 config,
67 enable,
68 spi,
69 };
70 if max.read_register(REG_DEVICE_ID).await? != DEVICE_ID {
71 return Err(Error::Conn);
72 }
73 max.write_register(REG_DEVICE_CTRL, config.as_u16()).await?;
74 Ok(max)
75 }
76
77 pub fn config(&self) -> DeviceConfig {
79 self.config
80 }
81
82 pub async fn gpi_configure_threshold(
84 &mut self,
85 port: Port,
86 threshold: u16,
87 mode: GPIMD,
88 ) -> Result<(), Error<S, P>> {
89 let Mode::Mode1(_) = self.get_mode(port) else {
90 return Err(Error::Mode);
91 };
92 self._gpi_configure_threshold(port, threshold, mode).await
93 }
94
95 pub async fn gpo_configure_level(&mut self, port: Port, level: u16) -> Result<(), Error<S, P>> {
97 let Mode::Mode3(_) = self.get_mode(port) else {
98 return Err(Error::Mode);
99 };
100 self._gpo_configure_level(port, level).await
101 }
102
103 pub async fn gpo_set_high(&mut self, port: Port) -> Result<(), Error<S, P>> {
105 let Mode::Mode3(_) = self.get_mode(port) else {
106 return Err(Error::Mode);
107 };
108 self._gpo_set_high(port).await
109 }
110
111 pub async fn gpo_set_low(&mut self, port: Port) -> Result<(), Error<S, P>> {
113 let Mode::Mode3(_) = self.get_mode(port) else {
114 return Err(Error::Mode);
115 };
116 self._gpo_set_low(port).await
117 }
118
119 pub async fn gpo_toggle(&mut self, port: Port) -> Result<(), Error<S, P>> {
121 let Mode::Mode3(_) = self.get_mode(port) else {
122 return Err(Error::Mode);
123 };
124 self._gpo_toggle(port).await
125 }
126
127 pub async fn dac_set_value(&mut self, port: Port, data: u16) -> Result<(), Error<S, P>> {
129 self._dac_set_value(port, data).await
132 }
133
134 pub async fn adc_get_value(&mut self, port: Port) -> Result<u16, Error<S, P>> {
136 let Mode::Mode7(_) = self.get_mode(port) else {
137 return Err(Error::Mode);
138 };
139 self._adc_get_value(port).await
140 }
141
142 pub async fn int_read(&mut self) -> Result<Interrupts, Error<S, P>> {
144 let val = self.read_register(REG_INTERRUPT).await?;
145 Ok(Interrupts::from(val))
146 }
147
148 pub async fn int_read_raw(&mut self) -> Result<u16, Error<S, P>> {
150 let val = self.read_register(REG_INTERRUPT).await?;
151 Ok(val)
152 }
153
154 pub async fn int_read_gpist(&mut self) -> Result<u32, Error<S, P>> {
156 let mut data = [0_u16; 2];
157 self.read_registers(REG_GPI_STATUS, &mut data).await?;
158 Ok(((data[0] as u32) << 16) | data[1] as u32)
159 }
160
161 pub fn get_mode(&self, port: Port) -> Mode {
163 self.channel_config[port.as_usize()]
164 }
165
166 async fn read_register(&mut self, address: u8) -> Result<u16, Error<S, P>> {
167 if address > MAX_ADDRESS {
168 return Err(Error::Address);
169 }
170 let mut buf = [0, 0, 0];
171 self.enable.set_low().map_err(Error::Pin)?;
172 self.spi
173 .transfer(&mut buf, &[(address << 1) | 1])
174 .await
175 .map_err(Error::Spi)?;
176 self.enable.set_high().map_err(Error::Pin)?;
177 Ok(((buf[1] as u16) << 8) | buf[2] as u16)
178 }
179
180 async fn read_registers<'a>(
181 &mut self,
182 start_address: u8,
183 data: &'a mut [u16],
184 ) -> Result<&'a [u16], Error<S, P>> {
185 if data.len() > 20 || start_address + data.len() as u8 - 1 > MAX_ADDRESS {
186 return Err(Error::Address);
187 }
188 let mut buf: Vec<u8, 41> = Vec::new();
190 buf.resize(1 + data.len() * 2, 0).ok();
193 self.enable.set_low().map_err(Error::Pin)?;
195 self.spi
196 .transfer(&mut buf, &[(start_address << 1) | 1])
197 .await
198 .map_err(Error::Spi)?;
199 self.enable.set_high().map_err(Error::Pin)?;
200 for (i, bytes) in buf[1..].chunks_exact(2).enumerate() {
202 data[i] = ((bytes[0] as u16) << 8) | bytes[1] as u16;
203 }
204 Ok(data)
205 }
206
207 async fn write_register(&mut self, address: u8, data: u16) -> Result<(), Error<S, P>> {
208 if address > MAX_ADDRESS {
209 return Err(Error::Address);
210 }
211 self.enable.set_low().map_err(Error::Pin)?;
212 self.spi
213 .write(&[address << 1, (data >> 8) as u8, (data & 0xff) as u8])
214 .await
215 .map_err(Error::Spi)?;
216 self.enable.set_high().map_err(Error::Pin)?;
217 Ok(())
218 }
219
220 async fn write_registers(
221 &mut self,
222 start_address: u8,
223 data: &[u16],
224 ) -> Result<(), Error<S, P>> {
225 if data.len() > 20 || start_address + data.len() as u8 - 1 > MAX_ADDRESS {
226 return Err(Error::Address);
227 }
228 let mut buf: Vec<u8, 41> = Vec::new();
230 buf.resize(data.len() * 2 + 1, 0).ok();
232 buf[0] = start_address << 1;
234
235 let payload = &mut buf[1..];
236 for (bytes, &word) in payload.chunks_exact_mut(2).zip(data.iter()) {
237 let word_bytes = word.to_be_bytes();
238 bytes[0] = word_bytes[0];
239 bytes[1] = word_bytes[1];
240 }
241
242 self.enable.set_low().map_err(Error::Pin)?;
243 self.spi.write(&buf).await.map_err(Error::Spi)?;
244 self.enable.set_high().map_err(Error::Pin)?;
245 Ok(())
246 }
247
248 async fn _configure_port(&mut self, port: Port, config: u16) -> Result<(), Error<S, P>> {
249 self.write_register(port.as_config_addr(), config).await
250 }
251
252 async fn _gpi_configure_threshold(
253 &mut self,
254 port: Port,
255 threshold: u16,
256 mode: GPIMD,
257 ) -> Result<(), Error<S, P>> {
258 let pos = port as usize % 8 * 2;
260 let mut current = self.read_register(REG_IRQ_MODE).await?;
261 let mut next = (mode as u16) << pos;
262 current &= !(0b11 << pos);
263 next |= current;
264 self.write_register(REG_IRQ_MODE, next).await?;
265 self.write_register(REG_DAC_DATA + (port as u8), threshold)
267 .await
268 }
269
270 async fn _gpo_configure_level(&mut self, port: Port, level: u16) -> Result<(), Error<S, P>> {
271 self.write_register(REG_DAC_DATA + (port as u8), level)
272 .await
273 }
274
275 async fn _gpo_set_high(&mut self, port: Port) -> Result<(), Error<S, P>> {
276 let mut buf: [u16; 2] = [0; 2];
277 let regs = self.read_registers(REG_GPO_DATA, &mut buf).await?;
278 let current = (regs[1] as u32) << 16 | (regs[0] as u32);
279 let next = current | (1 << port as usize);
280
281 let next_low = next as u16;
282 let next_high = (next >> 16) as u16;
283 self.write_registers(REG_GPO_DATA, &[next_low, next_high])
284 .await
285 }
286
287 async fn _gpo_set_low(&mut self, port: Port) -> Result<(), Error<S, P>> {
288 let mut buf: [u16; 2] = [0; 2];
289 let regs = self.read_registers(REG_GPO_DATA, &mut buf).await?;
290 let current = (regs[1] as u32) << 16 | (regs[0] as u32);
291 let next = current & !(1 << port as usize);
292
293 let next_low = next as u16;
294 let next_high = (next >> 16) as u16;
295 self.write_registers(REG_GPO_DATA, &[next_low, next_high])
296 .await
297 }
298
299 async fn _gpo_toggle(&mut self, port: Port) -> Result<(), Error<S, P>> {
300 let mut buf: [u16; 2] = [0; 2];
301 let regs = self.read_registers(REG_GPO_DATA, &mut buf).await?;
302 let current = (regs[1] as u32) << 16 | (regs[0] as u32);
303 let next = current ^ (1 << port as usize);
304
305 let next_low = next as u16;
306 let next_high = (next >> 16) as u16;
307 self.write_registers(REG_GPO_DATA, &[next_low, next_high])
308 .await
309 }
310
311 async fn _dac_set_value(&mut self, port: Port, data: u16) -> Result<(), Error<S, P>> {
312 self.write_register(REG_DAC_DATA + (port as u8), data).await
313 }
314
315 async fn _adc_get_value(&mut self, port: Port) -> Result<u16, Error<S, P>> {
316 self.read_register(REG_ADC_DATA + (port as u8)).await
317 }
318}
319
320seq!(N in 0..=12 {
321 impl<SPI, EN, S, P> ConfigurePort<ConfigMode~N, S, P> for Max11300<SPI, EN>
322 where
323 SPI: SpiBus<Error = S>,
324 EN: OutputPin<Error = P>,
325 {
326 async fn configure_port(&mut self, port: Port, config: ConfigMode~N) -> Result<(), Error<S, P>> {
327 self._configure_port(port, config.as_u16()).await?;
328 self.channel_config[port.as_usize()] = Mode::Mode~N(config);
329 Ok(())
330 }
331 }
332});
333
334pub struct ReadInterrupts<SPI: 'static, EN: 'static, M: RawMutex + 'static> {
335 max: &'static Mutex<M, Max11300<SPI, EN>>,
336}
337
338impl<SPI, EN, M, S, P> ReadInterrupts<SPI, EN, M>
339where
340 SPI: SpiBus<Error = S>,
341 EN: OutputPin<Error = P>,
342 M: RawMutex,
343{
344 pub fn new(max: &'static Mutex<M, Max11300<SPI, EN>>) -> Self {
345 Self { max }
346 }
347
348 pub async fn read(&self) -> Result<Interrupts, Error<S, P>> {
350 let mut driver = self.max.lock().await;
351 driver.int_read().await
352 }
353
354 pub async fn read_raw(&self) -> Result<u16, Error<S, P>> {
356 let mut driver = self.max.lock().await;
357 driver.int_read_raw().await
358 }
359
360 pub async fn read_gpist(&self) -> Result<u32, Error<S, P>> {
362 let mut driver = self.max.lock().await;
363 driver.int_read_gpist().await
364 }
365}
366
367seq!(N in 0..20 {
368 pub struct Ports<SPI: 'static, EN: 'static, M: RawMutex + 'static> {
369 pub interrupts: ReadInterrupts<SPI, EN, M>,
370 #(
371 pub port~N: Mode0Port<SPI, EN, M>,
372 )*
373 }
374});
375
376seq!(N in 0..20 {
377 impl<SPI, EN, M> Ports<SPI, EN, M>
378 where
379 SPI: SpiBus,
380 EN: OutputPin,
381 M: RawMutex,
382 {
383 pub fn new(max: &'static Mutex<M, Max11300<SPI, EN>>) -> Self {
384 Self {
385 interrupts: ReadInterrupts::new(max),
386 #(
387 port~N: Mode0Port::new(Port::P~N, max),
388 )*
389 }
390 }
391 }
392});
393
394#[cfg(test)]
395mod tests {
396 use crate::{
397 config::{ConfigMode1, ConfigMode5, ConfigMode7, ADCRANGE, AVR, DACRANGE, NSAMPLES},
398 port::{IntoConfiguredPort, IntoMode},
399 };
400
401 use super::*;
402 use embassy_sync::blocking_mutex::raw::NoopRawMutex;
403 use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction};
404 use embedded_hal_mock::{
405 common::Generic,
406 eh1::digital::{Mock as PinMock, State as PinState, Transaction as PinTransaction},
407 };
408 use static_cell::StaticCell;
409
410 type MockMax = Max11300<Generic<SpiTransaction<u8>>, Generic<PinTransaction>>;
411
412 static MAX0: StaticCell<Mutex<NoopRawMutex, MockMax>> = StaticCell::new();
413 static MAX1: StaticCell<Mutex<NoopRawMutex, MockMax>> = StaticCell::new();
414 static MAX2: StaticCell<Mutex<NoopRawMutex, MockMax>> = StaticCell::new();
415 static MAX3: StaticCell<Mutex<NoopRawMutex, MockMax>> = StaticCell::new();
416
417 #[tokio::test]
418 async fn into_configured() {
419 let config = DeviceConfig::default();
420 let pin_expectations = [
421 PinTransaction::set(PinState::High),
422 PinTransaction::set(PinState::Low),
423 PinTransaction::set(PinState::High),
424 PinTransaction::set(PinState::Low),
425 PinTransaction::set(PinState::High),
426 ];
427 let spi_expectations = [
428 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
430 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
432 ];
433 let mut pin = PinMock::new(&pin_expectations);
434 let mut spi = SpiMock::new(&spi_expectations);
435 let _max = Max11300::try_new(spi.clone(), pin.clone(), config)
436 .await
437 .unwrap();
438 pin.done();
439 spi.done();
440 }
441
442 #[tokio::test]
443 async fn config_modes() {
444 let config = DeviceConfig::default();
445 let pin_expectations = [
446 PinTransaction::set(PinState::High),
447 PinTransaction::set(PinState::Low),
448 PinTransaction::set(PinState::High),
449 PinTransaction::set(PinState::Low),
450 PinTransaction::set(PinState::High),
451 PinTransaction::set(PinState::Low),
452 PinTransaction::set(PinState::High),
453 PinTransaction::set(PinState::Low),
454 PinTransaction::set(PinState::High),
455 ];
456 let spi_expectations = [
457 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
459 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
461 SpiTransaction::write_vec(vec![0x25 << 1, 16, 0]),
463 SpiTransaction::write_vec(vec![0x25 << 1, 113, 192]),
465 ];
466 let mut pin = PinMock::new(&pin_expectations);
467 let mut spi = SpiMock::new(&spi_expectations);
468 let max = Max11300::try_new(spi.clone(), pin.clone(), config)
469 .await
470 .unwrap();
471
472 let max = MAX0.init(Mutex::new(max));
473 let ports = Ports::new(max);
474
475 let port5 = ports.port5.into_configured_port(ConfigMode1).await.unwrap();
477 port5
479 .into_mode(ConfigMode7(
480 AVR::InternalRef,
481 ADCRANGE::Rg0_10v,
482 NSAMPLES::Samples64,
483 ))
484 .await
485 .unwrap();
486 pin.done();
487 spi.done();
488 }
489
490 #[tokio::test]
491 async fn config_mode_5() {
492 let config = DeviceConfig::default();
493 let pin_expectations = [
494 PinTransaction::set(PinState::High),
495 PinTransaction::set(PinState::Low),
496 PinTransaction::set(PinState::High),
497 PinTransaction::set(PinState::Low),
498 PinTransaction::set(PinState::High),
499 PinTransaction::set(PinState::Low),
500 PinTransaction::set(PinState::High),
501 PinTransaction::set(PinState::Low),
502 PinTransaction::set(PinState::High),
503 ];
504 let spi_expectations = [
505 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
507 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
509 SpiTransaction::write_vec(vec![0x25 << 1, 81, 0]),
511 SpiTransaction::write_vec(vec![0x65 << 1, 0, 42]),
513 ];
514 let mut pin = PinMock::new(&pin_expectations);
515 let mut spi = SpiMock::new(&spi_expectations);
516 let max = Max11300::try_new(spi.clone(), pin.clone(), config)
517 .await
518 .unwrap();
519
520 let max = MAX1.init(Mutex::new(max));
521 let ports = Ports::new(max);
522
523 let port5 = ports
524 .port5
525 .into_configured_port(ConfigMode5(DACRANGE::Rg0_10v))
526 .await
527 .unwrap();
528 port5.set_value(42).await.unwrap();
529 pin.done();
530 spi.done();
531 }
532
533 #[tokio::test]
534 async fn config_mode_7() {
535 let config = DeviceConfig::default();
536 let pin_expectations = [
537 PinTransaction::set(PinState::High),
538 PinTransaction::set(PinState::Low),
539 PinTransaction::set(PinState::High),
540 PinTransaction::set(PinState::Low),
541 PinTransaction::set(PinState::High),
542 PinTransaction::set(PinState::Low),
543 PinTransaction::set(PinState::High),
544 PinTransaction::set(PinState::Low),
545 PinTransaction::set(PinState::High),
546 ];
547 let spi_expectations = [
548 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
550 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
552 SpiTransaction::write_vec(vec![0x25 << 1, 113, 192]),
554 SpiTransaction::transfer(vec![(0x45 << 1) | 1], vec![0x0, 0x1, 0x1]),
556 ];
557 let mut pin = PinMock::new(&pin_expectations);
558 let mut spi = SpiMock::new(&spi_expectations);
559 let max = Max11300::try_new(spi.clone(), pin.clone(), config)
560 .await
561 .unwrap();
562
563 let max = MAX2.init(Mutex::new(max));
564 let ports = Ports::new(max);
565
566 let port5 = ports
567 .port5
568 .into_configured_port(ConfigMode7(
569 AVR::InternalRef,
570 ADCRANGE::Rg0_10v,
571 NSAMPLES::Samples64,
572 ))
573 .await
574 .unwrap();
575 let val = port5.get_value().await.unwrap();
576 assert_eq!(val, 257);
577 pin.done();
578 spi.done();
579 }
580
581 #[tokio::test]
582 async fn config_mode_7_direct() {
583 let config = DeviceConfig::default();
584 let pin_expectations = [
585 PinTransaction::set(PinState::High),
586 PinTransaction::set(PinState::Low),
587 PinTransaction::set(PinState::High),
588 PinTransaction::set(PinState::Low),
589 PinTransaction::set(PinState::High),
590 PinTransaction::set(PinState::Low),
591 PinTransaction::set(PinState::High),
592 PinTransaction::set(PinState::Low),
593 PinTransaction::set(PinState::High),
594 ];
595 let spi_expectations = [
596 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
598 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
600 SpiTransaction::write_vec(vec![0x25 << 1, 113, 192]),
602 SpiTransaction::transfer(vec![(0x45 << 1) | 1], vec![0x0, 0x1, 0x1]),
604 ];
605 let mut pin = PinMock::new(&pin_expectations);
606 let mut spi = SpiMock::new(&spi_expectations);
607 let mut max = Max11300::try_new(spi.clone(), pin.clone(), config)
608 .await
609 .unwrap();
610
611 let port = Port::try_from(5).unwrap();
612 max.configure_port(
613 port,
614 ConfigMode7(AVR::InternalRef, ADCRANGE::Rg0_10v, NSAMPLES::Samples64),
615 )
616 .await
617 .unwrap();
618
619 let val = max.adc_get_value(port).await.unwrap();
620
621 assert_eq!(val, 257);
622 pin.done();
623 spi.done();
624 }
625
626 #[tokio::test]
627 async fn multiport() {
628 let config = DeviceConfig::default();
629 let pin_expectations = [
630 PinTransaction::set(PinState::High),
631 PinTransaction::set(PinState::Low),
632 PinTransaction::set(PinState::High),
633 PinTransaction::set(PinState::Low),
634 PinTransaction::set(PinState::High),
635 PinTransaction::set(PinState::Low),
636 PinTransaction::set(PinState::High),
637 PinTransaction::set(PinState::Low),
638 PinTransaction::set(PinState::High),
639 PinTransaction::set(PinState::Low),
640 PinTransaction::set(PinState::High),
641 ];
642 let spi_expectations = [
643 SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
645 SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
647 SpiTransaction::write_vec(vec![0x25 << 1, 81, 0]),
649 SpiTransaction::write_vec(vec![0x26 << 1, 81, 0]),
650 SpiTransaction::write_vec(vec![0x65 << 1, 0, 42, 0, 43]),
652 ];
653 let mut pin = PinMock::new(&pin_expectations);
654 let mut spi = SpiMock::new(&spi_expectations);
655 let max = Max11300::try_new(spi.clone(), pin.clone(), config)
656 .await
657 .unwrap();
658
659 let max = MAX3.init(Mutex::new(max));
660 let ports = Ports::new(max);
661
662 let port5 = ports
663 .port5
664 .into_configured_port(ConfigMode5(DACRANGE::Rg0_10v))
665 .await
666 .unwrap();
667 let port6 = ports
668 .port6
669 .into_configured_port(ConfigMode5(DACRANGE::Rg0_10v))
670 .await
671 .unwrap();
672 let mut mp = Multiport::new([port5, port6]).unwrap();
673 mp.set_values(&[42, 43]).await.unwrap();
674 pin.done();
675 spi.done();
676 }
677}