max11300/
lib.rs

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 bus error
23    Spi(S),
24    /// CS pin error
25    Pin(P),
26    /// Connection error (device not found)
27    Conn,
28    /// Address error (invalid or out of bounds)
29    Address,
30    /// Port error (invalid or out of bounds)
31    Port,
32    /// Mode error (wrong port mode for method)
33    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
44/// Max11300 driver
45pub 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    /// Create a new Max11300 instance
58    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    /// Return the current DeviceConfig
78    pub fn config(&self) -> DeviceConfig {
79        self.config
80    }
81
82    /// Configure the input threshold for a ConfigMode1 Port
83    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    /// Configure the digital output level for a ConfigMode3 Port
96    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    /// Set a digital output high on a ConfigMode3 Port
104    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    /// Set a digital output low on a ConfigMode3 Port
112    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    /// Toggle digital output on a ConfigMode3 Port
120    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    /// Set a DAC value for a ConfigMode5 Port
128    pub async fn dac_set_value(&mut self, port: Port, data: u16) -> Result<(), Error<S, P>> {
129        // Setting the DAC register values should be allowed in any mode as it is required
130        // for some mode transitions (e.g. -> Mode3)
131        self._dac_set_value(port, data).await
132    }
133
134    /// Read an ADC value from a ConfigMode7 Port
135    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    /// Read the Interrupts from the Interrupt register
143    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    /// Read the raw Interrupts from the Interrupt register
149    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    /// Read the GPI Status Interrupts from the GPIST register
155    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    /// Get the Mode for a Port
162    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        // Max 1 command byte + 2x20 data bytes
189        let mut buf: Vec<u8, 41> = Vec::new();
190        // The read buffer must be long enough for the junk byte that is read
191        // while the address is being written, PLUS the actual data bytes.
192        buf.resize(1 + data.len() * 2, 0).ok();
193        // Read values into buf
194        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        // Copy to data buffer, skipping the first junk byte.
201        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        // 1 address byte, 2x20 data bytes maximum
229        let mut buf: Vec<u8, 41> = Vec::new();
230        // Actual size of u16 data buffer times two plus address byte
231        buf.resize(data.len() * 2 + 1, 0).ok();
232        // Write instruction
233        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        // Set IRQ mode for port
259        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        // Set threshold for port
266        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    /// Read the Interrupts from the Interrupt register
349    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    /// Read the raw Interrupts from the Interrupt register
355    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    /// Read the GPI Status Interrupts from the GPIST register
361    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            // connection check
429            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
430            // write default configuration
431            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            // connection check
458            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
459            // write default configuration
460            SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
461            // configure port
462            SpiTransaction::write_vec(vec![0x25 << 1, 16, 0]),
463            // reconfigure port
464            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        // Configure port 5 for the first time
476        let port5 = ports.port5.into_configured_port(ConfigMode1).await.unwrap();
477        // Reconfigure port 5
478        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            // connection check
506            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
507            // write default configuration
508            SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
509            // configure port
510            SpiTransaction::write_vec(vec![0x25 << 1, 81, 0]),
511            // set value on port
512            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            // connection check
549            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
550            // write default configuration
551            SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
552            // configure port
553            SpiTransaction::write_vec(vec![0x25 << 1, 113, 192]),
554            // read value on port
555            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            // connection check
597            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
598            // write default configuration
599            SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
600            // configure port
601            SpiTransaction::write_vec(vec![0x25 << 1, 113, 192]),
602            // read value on port
603            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            // connection check
644            SpiTransaction::transfer(vec![1], vec![0x0, 0x04, 0x24]),
645            // write default configuration
646            SpiTransaction::write_vec(vec![0x10 << 1, 0, 0]),
647            // configure ports
648            SpiTransaction::write_vec(vec![0x25 << 1, 81, 0]),
649            SpiTransaction::write_vec(vec![0x26 << 1, 81, 0]),
650            // set value on port
651            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}