atwinc1500/
lib.rs

1#![doc = include_str!("../README.md")]
2#![no_std]
3#![warn(missing_docs)]
4
5#[macro_use]
6mod macros;
7mod crc;
8pub mod error;
9pub mod gpio;
10mod hif;
11#[doc(hidden)]
12pub mod registers;
13pub mod socket;
14#[doc(hidden)]
15pub mod spi;
16pub mod types;
17pub mod wifi;
18
19use embedded_hal::blocking::{delay::DelayMs, spi::Transfer};
20use embedded_hal::digital::v2::{InputPin, OutputPin};
21use embedded_nal::{SocketAddr, TcpClientStack, TcpFullStack};
22
23use error::Error;
24use gpio::{AtwincGpio, GpioDirection, GpioValue};
25use hif::{commands, group_ids, HifHeader, HostInterface};
26use socket::TcpSocket;
27use spi::SpiBus;
28use types::{FirmwareVersion, MacAddress};
29use wifi::{ConnectionParameters, OldConnection};
30
31/// Atwin1500 driver struct
32pub struct Atwinc1500<SPI, D, O, I>
33where
34    SPI: Transfer<u8>,
35    D: DelayMs<u32>,
36    O: OutputPin,
37    I: InputPin,
38{
39    delay: D,
40    spi_bus: SpiBus<SPI, O>,
41    hif: HostInterface,
42    _irq: I,
43    reset: O,
44    wake: O,
45    crc: bool,
46}
47
48/// Atwinc1500 struct implementation containing non embedded-nal
49/// public methods
50impl<SPI, D, O, I> Atwinc1500<SPI, D, O, I>
51where
52    SPI: Transfer<u8>,
53    D: DelayMs<u32>,
54    O: OutputPin,
55    I: InputPin,
56{
57    /// Returns an Atwin1500 struct
58    ///
59    /// # Arguments
60    ///
61    /// * `spi` - An spi struct implementing traits from embedded-hal
62    ///
63    /// * `delay` - A delay implementing Delay from embedded-hal
64    ///
65    /// * `cs` - An OutputPin for the chip select
66    ///
67    /// * `irq` - An InputPin for interrupt requests
68    ///
69    /// * `reset` - An OutputPin for chip reset
70    ///
71    /// * `wake` - An OutputPin for chip wake
72    ///
73    /// * `crc` - Turn on CRC in transactions
74    ///
75    pub fn new(
76        spi: SPI,
77        delay: D,
78        cs: O,
79        _irq: I,
80        reset: O,
81        wake: O,
82        crc: bool,
83    ) -> Result<Self, Error> {
84        let mut s = Self {
85            delay,
86            spi_bus: SpiBus::new(spi, cs, crc),
87            hif: HostInterface {},
88            _irq,
89            reset,
90            wake,
91            crc,
92        };
93        s.initialize()?;
94        Ok(s)
95    }
96
97    /// Initializes the driver by:
98    /// * Initializing pins between devices
99    /// * Disables crc if needed
100    /// * Waits for efuse ready
101    /// * Waits for boot rom ready
102    /// * Writes driver version and configuration
103    /// * Enables chip interrupt
104    fn initialize(&mut self) -> Result<(), Error> {
105        const FINISH_BOOT_VAL: u32 = 0x10add09e;
106        const DRIVER_VER_INFO: u32 = 0x13521330;
107        const CONF_VAL: u32 = 0x102;
108        const START_FIRMWARE: u32 = 0xef522f61;
109        const FINISH_INIT_VAL: u32 = 0x02532636;
110        self.init_pins()?;
111        self.disable_crc()?;
112        let mut efuse_value: u32 = 0;
113        retry_while!((efuse_value & 0x80000000) == 0, retries = 10, {
114            efuse_value = self.spi_bus.read_register(registers::EFUSE_REG)?;
115            self.delay.delay_ms(1000);
116        });
117        let wait: u32 = self
118            .spi_bus
119            .read_register(registers::M2M_WAIT_FOR_HOST_REG)?;
120        if (wait & 1) == 0 {
121            let mut bootrom: u32 = 0;
122            retry_while!(bootrom != FINISH_BOOT_VAL, retries = 3, {
123                bootrom = self.spi_bus.read_register(registers::BOOTROM_REG)?;
124                self.delay.delay_ms(1000);
125            });
126        }
127        self.spi_bus
128            .write_register(registers::NMI_STATE_REG, DRIVER_VER_INFO)?;
129        self.spi_bus
130            .write_register(registers::rNMI_GP_REG_1, CONF_VAL)?;
131        self.spi_bus
132            .write_register(registers::BOOTROM_REG, START_FIRMWARE)?;
133        let mut state: u32 = 0;
134        retry_while!(state != FINISH_INIT_VAL, retries = 20, {
135            state = self.spi_bus.read_register(registers::NMI_STATE_REG)?;
136            self.delay.delay_ms(1000);
137        });
138        self.spi_bus.write_register(registers::NMI_STATE_REG, 0)?;
139        self.enable_chip_interrupt()?;
140        Ok(())
141    }
142
143    /// Pulls the chip select and wake pins high
144    /// Then pulses (low/high) the reset pin with
145    /// a delay
146    fn init_pins(&mut self) -> Result<(), Error> {
147        self.spi_bus.init_cs()?;
148        if self.wake.set_high().is_err() {
149            return Err(Error::PinStateError);
150        }
151        if self.reset.set_low().is_err() {
152            return Err(Error::PinStateError);
153        }
154        self.delay.delay_ms(1000);
155        if self.reset.set_high().is_err() {
156            return Err(Error::PinStateError);
157        }
158        self.delay.delay_ms(1000);
159        Ok(())
160    }
161
162    /// Disables crc if self.crc is false
163    fn disable_crc(&mut self) -> Result<(), Error> {
164        if !self.crc {
165            self.spi_bus
166                .write_register(registers::NMI_SPI_PROTOCOL_CONFIG, 0x52)?;
167            self.spi_bus.crc_disabled()?;
168        }
169        Ok(())
170    }
171
172    fn enable_chip_interrupt(&mut self) -> Result<(), Error> {
173        let mux: u32 = self.spi_bus.read_register(registers::NMI_PIN_MUX_0)?;
174        self.spi_bus
175            .write_register(registers::NMI_PIN_MUX_0, mux | 0x100)?;
176        let base: u32 = self.spi_bus.read_register(registers::NMI_INTR_REG_BASE)?;
177        self.spi_bus
178            .write_register(registers::NMI_INTR_REG_BASE, base | 0x10000)?;
179        Ok(())
180    }
181
182    /// Gets the version of the firmware on
183    /// the Atwinc1500
184    pub fn get_firmware_version(&mut self) -> Result<FirmwareVersion, Error> {
185        let mut reg_value = self.spi_bus.read_register(registers::NMI_REV_REG)?;
186        if reg_value == registers::M2M_ATE_FW_IS_UP_VALUE {
187            reg_value = self.spi_bus.read_register(registers::NMI_REV_REG_ATE)?;
188        }
189        Ok(FirmwareVersion([
190            ((reg_value >> 8) & 0xff) as u8, // major
191            ((reg_value >> 4) & 0x0f) as u8, // minor
192            (reg_value & 0x0f) as u8,        // patch
193        ]))
194    }
195
196    /// Gets the mac address stored in
197    /// one time programmable memory
198    pub fn get_otp_mac_address(&mut self) -> Result<MacAddress, Error> {
199        todo!()
200    }
201
202    /// Gets the working mac address
203    /// on the Atwinc1500
204    pub fn get_mac_address(&mut self) -> Result<MacAddress, Error> {
205        const MAC_SIZE: usize = 6;
206        const DATA_SIZE: usize = 8;
207        let mut mac: MacAddress = MacAddress([0; MAC_SIZE]);
208        let mut data: [u8; DATA_SIZE] = [0; DATA_SIZE];
209        let mut reg_value = self.spi_bus.read_register(registers::rNMI_GP_REG_2)?;
210        reg_value |= 0x30000;
211        self.spi_bus
212            .read_data(&mut data, reg_value, DATA_SIZE as u32)?;
213        reg_value = combine_bytes_lsb!(data[0..4]);
214        reg_value &= 0x0000ffff;
215        reg_value |= 0x30000;
216        self.spi_bus
217            .read_data(&mut mac.0, reg_value, MAC_SIZE as u32)?;
218        Ok(mac)
219    }
220
221    /// Sets the direction of a gpio pin
222    /// to either Output or Input
223    pub fn set_gpio_direction(
224        &mut self,
225        gpio: AtwincGpio,
226        direction: GpioDirection,
227    ) -> Result<(), Error> {
228        const GPIO_DIR_REG: u32 = 0x20108;
229        let mut value = self.spi_bus.read_register(GPIO_DIR_REG)?;
230        if direction == GpioDirection::Output {
231            value |= 1 << gpio as u8;
232        } else {
233            value &= !(1 << gpio as u8);
234        }
235        self.spi_bus.write_register(GPIO_DIR_REG, value)
236    }
237
238    /// Sets the value of a gpio
239    /// pin as either High or Low
240    pub fn set_gpio_value(&mut self, gpio: AtwincGpio, value: GpioValue) -> Result<(), Error> {
241        const GPIO_VAL_REG: u32 = 0x20100;
242        let mut response = self.spi_bus.read_register(GPIO_VAL_REG)?;
243        if value == GpioValue::Low {
244            response |= 1 << gpio as u8;
245        } else {
246            response &= !(1 << gpio as u8);
247        }
248        self.spi_bus.write_register(GPIO_VAL_REG, response)
249    }
250
251    /// Gets the direction of a gpio pin
252    /// as either Ouput or Input
253    pub fn get_gpio_direction(&mut self, gpio: AtwincGpio) -> Result<GpioDirection, Error> {
254        const GPIO_GET_DIR_REG: u32 = 0x20104;
255        match self.spi_bus.read_register(GPIO_GET_DIR_REG) {
256            Ok(v) => Ok(GpioDirection::from(((v >> gpio as u8) & 0x01) as u8)),
257            Err(e) => Err(e),
258        }
259    }
260
261    /// Connects to a wireless network
262    /// given a ConnectionParameters struct
263    pub fn connect_network(&mut self, connection: ConnectionParameters) -> Result<(), Error> {
264        let mut conn_header: OldConnection = connection.into();
265        let hif_header = HifHeader::new(
266            group_ids::WIFI,
267            commands::wifi::REQ_CONNECT,
268            conn_header.len() as u16,
269        );
270        self.hif
271            .send(&mut self.spi_bus, hif_header, &mut conn_header, &mut [])?;
272        Ok(())
273    }
274
275    /// Disconnects from a wireless network
276    pub fn disconnect_network(&mut self) -> Result<(), Error> {
277        let hif_header = HifHeader::new(group_ids::WIFI, commands::wifi::REQ_DISCONNECT, 0);
278        self.hif
279            .send(&mut self.spi_bus, hif_header, &mut [], &mut [])?;
280        Ok(())
281    }
282
283    /// Connects to the last remembered network
284    pub fn connect_default_network(&mut self) -> Result<(), Error> {
285        let hif_header = HifHeader::new(group_ids::WIFI, commands::wifi::REQ_DEFAULT_CONNECT, 0);
286        self.hif
287            .send(&mut self.spi_bus, hif_header, &mut [], &mut [])?;
288        Ok(())
289    }
290}
291
292impl<SPI, D, O, I> TcpClientStack for Atwinc1500<SPI, D, O, I>
293where
294    SPI: Transfer<u8>,
295    D: DelayMs<u32>,
296    O: OutputPin,
297    I: InputPin,
298{
299    type TcpSocket = TcpSocket;
300    type Error = Error;
301
302    fn socket(&mut self) -> Result<TcpSocket, Error> {
303        todo!()
304    }
305
306    fn connect(
307        &mut self,
308        _socket: &mut TcpSocket,
309        _address: SocketAddr,
310    ) -> Result<(), embedded_nal::nb::Error<Error>> {
311        todo!()
312    }
313
314    fn is_connected(&mut self, _socket: &TcpSocket) -> Result<bool, Error> {
315        todo!()
316    }
317
318    fn send(
319        &mut self,
320        _socket: &mut TcpSocket,
321        _data: &[u8],
322    ) -> Result<usize, embedded_nal::nb::Error<Error>> {
323        todo!()
324    }
325
326    fn receive(
327        &mut self,
328        _socket: &mut TcpSocket,
329        _data: &mut [u8],
330    ) -> Result<usize, embedded_nal::nb::Error<Error>> {
331        todo!()
332    }
333
334    fn close(&mut self, _socket: TcpSocket) -> Result<(), Error> {
335        todo!()
336    }
337}
338
339impl<SPI, D, O, I> TcpFullStack for Atwinc1500<SPI, D, O, I>
340where
341    SPI: Transfer<u8>,
342    D: DelayMs<u32>,
343    O: OutputPin,
344    I: InputPin,
345{
346    fn bind(&mut self, _socket: &mut TcpSocket, _port: u16) -> Result<(), Error> {
347        todo!()
348    }
349
350    fn listen(&mut self, _socket: &mut TcpSocket) -> Result<(), Error> {
351        todo!()
352    }
353
354    fn accept(
355        &mut self,
356        _socket: &mut TcpSocket,
357    ) -> Result<(TcpSocket, SocketAddr), embedded_nal::nb::Error<Error>> {
358        todo!()
359    }
360}