Skip to main content

hal_mik32/
gpio.rs

1//! GPIO
2use core::convert::Infallible;
3use core::marker::PhantomData;
4use embedded_hal::digital::{ErrorType, InputPin, OutputPin};
5
6use mik32_pac::Peripherals;
7
8/// Floating input (type state)
9pub struct Floating;
10
11/// Pulled down input (type state)
12pub struct PullDown;
13
14/// Pulled up input (type state)
15pub struct PullUp;
16
17/// Output mode (type state)
18pub struct Output;
19
20/// Func2Mode mode (type state)
21pub struct Func2Mode;
22
23pub struct Pin<const P: u8, const N: u8, MODE = Floating> {
24    _mode: PhantomData<MODE>,
25}
26
27impl<const P: u8, const N: u8, MODE> Pin<P, N, MODE> {
28    pub const fn new() -> Self {
29        Self { _mode: PhantomData }
30    }
31}
32
33pub trait OutputPermitted {}
34pub trait SerialPermitted {}
35pub trait InputMode {}
36
37impl InputMode for Floating {}
38impl InputMode for PullDown {}
39impl InputMode for PullUp {}
40
41#[inline(always)]
42fn set_gpio_function<const P: u8, const N: u8>(p: &Peripherals) {
43    let shift = 2 * N;
44    let mask = 0b11u32 << shift;
45
46    match P {
47        0 => p
48            .pad_config
49            .pad0_cfg()
50            .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
51        1 => p
52            .pad_config
53            .pad1_cfg()
54            .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
55        2 => p
56            .pad_config
57            .pad2_cfg()
58            .modify(|r, w| unsafe { w.bits(r.bits() & !mask) }),
59        _ => panic!("Invalid port number {}", P),
60    };
61}
62
63#[inline(always)]
64fn set_pull<const P: u8, const N: u8>(p: &Peripherals, pull: u32) {
65    let shift = 2 * N;
66    let mask = 0b11u32 << shift;
67
68    match P {
69        0 => p
70            .pad_config
71            .pad0_pupd()
72            .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
73        1 => p
74            .pad_config
75            .pad1_pupd()
76            .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
77        2 => p
78            .pad_config
79            .pad2_pupd()
80            .modify(|r, w| unsafe { w.bits((r.bits() & !mask) | (pull << shift)) }),
81        _ => panic!("Invalid port number {}", P),
82    };
83}
84
85#[inline(always)]
86fn set_direction_in<const P: u8, const N: u8>(p: &Peripherals) {
87    match P {
88        0 => p
89            .gpio16_0
90            .direction_in()
91            .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
92        1 => p
93            .gpio16_1
94            .direction_in()
95            .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
96        2 => p
97            .gpio8_2
98            .direction_in()
99            .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) }),
100        _ => panic!("Invalid port number {}", P),
101    };
102}
103
104impl<const P: u8, const N: u8, MODE> Pin<P, N, MODE> {
105    pub fn into_output(self) -> Pin<P, N, Output>
106    where
107        Pin<P, N>: OutputPermitted,
108    {
109        let p = unsafe { Peripherals::steal() };
110        set_gpio_function::<P, N>(&p);
111        set_pull::<P, N>(&p, 0);
112
113        match P {
114            0 => {
115                p.gpio16_0
116                    .direction_out()
117                    .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
118            }
119            1 => {
120                p.gpio16_1
121                    .direction_out()
122                    .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
123            }
124            2 => {
125                p.gpio8_2
126                    .direction_out()
127                    .modify(|r, w| unsafe { w.bits(r.bits() | (1u32 << N)) });
128            }
129            _ => panic!("Invalid port number {}", P),
130        }
131
132        Pin::new()
133    }
134
135    pub fn into_floating_input(self) -> Pin<P, N, Floating> {
136        let p = unsafe { Peripherals::steal() };
137        set_gpio_function::<P, N>(&p);
138        set_pull::<P, N>(&p, 0);
139        set_direction_in::<P, N>(&p);
140
141        Pin::new()
142    }
143
144    pub fn into_pull_up_input(self) -> Pin<P, N, PullUp> {
145        let p = unsafe { Peripherals::steal() };
146        set_gpio_function::<P, N>(&p);
147        set_pull::<P, N>(&p, 1);
148        set_direction_in::<P, N>(&p);
149
150        Pin::new()
151    }
152
153    pub fn into_pull_down_input(self) -> Pin<P, N, PullDown> {
154        let p = unsafe { Peripherals::steal() };
155        set_gpio_function::<P, N>(&p);
156        set_pull::<P, N>(&p, 2);
157        set_direction_in::<P, N>(&p);
158
159        Pin::new()
160    }
161
162    pub fn into_serial_port(self) -> Pin<P, N, Func2Mode>
163    where
164        Pin<P, N>: SerialPermitted,
165    {
166        let p = unsafe { Peripherals::steal() };
167
168        p.pad_config.pad1_cfg().modify(|r, w| unsafe {
169            let shift = 2 * N;
170            let mask = 0b11u32 << shift;
171
172            w.bits((r.bits() & !mask) | (0b01u32 << shift))
173        });
174
175        // // FIXME gpio16_0 – нужно выбирать в зависимости от P
176        // p.gpio16_0.direction_in().write(|w| unsafe { w.bits(1 << N) });
177
178        // let mask = 0b11 << 2 * N;
179        // let value = 0b01 << 2 * N;
180
181        // p.pad_config.pad0_cfg().modify(
182        //     |r, w|
183        //     unsafe { w.bits((r.bits() & !mask) | value) }
184        // );
185
186        // p.gpio16_0.func_sel().modify(
187        //     |r, w|
188        //     unsafe { w.bits(r.bits() | (1 << N)) }
189        // );
190
191        Pin::new()
192    }
193}
194
195impl<const P: u8, const N: u8, MODE> ErrorType for Pin<P, N, MODE> {
196    type Error = Infallible;
197}
198
199/// Single digital push-pull output pin.
200impl<const P: u8, const N: u8> OutputPin for Pin<P, N, Output> {
201    /// Drives the pin high.
202    #[inline(always)]
203    fn set_high(&mut self) -> Result<(), Self::Error> {
204        let p = unsafe { Peripherals::steal() };
205
206        match P {
207            0 => {
208                p.gpio16_0.set().write(|w| unsafe { w.bits(1u32 << N) });
209            }
210            1 => {
211                p.gpio16_1.set().write(|w| unsafe { w.bits(1u32 << N) });
212            }
213            2 => {
214                p.gpio8_2.set().write(|w| unsafe { w.bits(1u32 << N) });
215            }
216            _ => panic!("Invalid port number {}", P),
217        }
218
219        Ok(())
220    }
221
222    /// Drives the pin low.
223    #[inline(always)]
224    fn set_low(&mut self) -> Result<(), Self::Error> {
225        let p = unsafe { Peripherals::steal() };
226
227        match P {
228            0 => {
229                p.gpio16_0.clear().write(|w| unsafe { w.bits(1u32 << N) });
230            }
231            1 => {
232                p.gpio16_1.clear().write(|w| unsafe { w.bits(1u32 << N) });
233            }
234            2 => {
235                p.gpio8_2.clear().write(|w| unsafe { w.bits(1u32 << N) });
236            }
237            _ => panic!("Invalid port number {}", P),
238        }
239
240        Ok(())
241    }
242}
243
244impl<const P: u8, const N: u8, MODE> InputPin for Pin<P, N, MODE>
245where
246    MODE: InputMode,
247{
248    #[inline(always)]
249    fn is_high(&mut self) -> Result<bool, Self::Error> {
250        let p = unsafe { Peripherals::steal() };
251        let mask = 1u32 << N;
252
253        let is_set = match P {
254            0 => p.gpio16_0.state().read().bits() & mask != 0,
255            1 => p.gpio16_1.state().read().bits() & mask != 0,
256            2 => p.gpio8_2.state().read().bits() & mask != 0,
257            _ => panic!("Invalid port number {}", P),
258        };
259
260        Ok(is_set)
261    }
262
263    #[inline(always)]
264    fn is_low(&mut self) -> Result<bool, Self::Error> {
265        self.is_high().map(|is_high| !is_high)
266    }
267}
268
269pub mod port_0 {
270    use super::{OutputPermitted, Pin, SerialPermitted};
271
272    pub type Pin00 = Pin<0, 0>;
273    impl OutputPermitted for Pin<0, 0> {}
274
275    pub type Pin01 = Pin<0, 1>;
276    impl OutputPermitted for Pin<0, 1> {}
277
278    pub type Pin02 = Pin<0, 2>;
279    impl OutputPermitted for Pin<0, 2> {}
280
281    pub type Pin03 = Pin<0, 3>;
282    impl OutputPermitted for Pin<0, 3> {}
283
284    pub type Pin04 = Pin<0, 4>;
285    impl OutputPermitted for Pin<0, 4> {}
286
287    // GPIO
288    // UART 0 RX
289    pub type Pin05 = Pin<0, 5>;
290    impl OutputPermitted for Pin<0, 5> {}
291    impl SerialPermitted for Pin<0, 5> {}
292
293    // GPIO
294    // UART 0 TX
295    pub type Pin06 = Pin<0, 6>;
296    impl OutputPermitted for Pin<0, 6> {}
297    impl SerialPermitted for Pin<0, 6> {}
298
299    // GPIO
300    // UART 0 NCTS
301    pub type Pin07 = Pin<0, 7>;
302    impl OutputPermitted for Pin<0, 7> {}
303    impl SerialPermitted for Pin<0, 7> {}
304
305    // GPIO
306    // UART 0 NRTS
307    pub type Pin08 = Pin<0, 8>;
308    impl OutputPermitted for Pin<0, 8> {}
309    impl SerialPermitted for Pin<0, 8> {}
310
311    pub type Pin09 = Pin<0, 9>;
312    impl OutputPermitted for Pin<0, 9> {}
313
314    pub type Pin10 = Pin<0, 10>;
315    impl OutputPermitted for Pin<0, 10> {}
316
317    pub type Pin11 = Pin<0, 11>;
318    impl OutputPermitted for Pin<0, 11> {}
319
320    pub type Pin12 = Pin<0, 12>;
321    impl OutputPermitted for Pin<0, 12> {}
322
323    pub type Pin13 = Pin<0, 13>;
324    impl OutputPermitted for Pin<0, 13> {}
325
326    pub type Pin14 = Pin<0, 14>;
327    impl OutputPermitted for Pin<0, 14> {}
328
329    pub type Pin15 = Pin<0, 15>;
330    impl OutputPermitted for Pin<0, 15> {}
331}
332
333pub mod port_1 {
334    use super::{OutputPermitted, Pin, SerialPermitted};
335
336    pub type Pin00 = Pin<1, 0>;
337    impl OutputPermitted for Pin<1, 0> {}
338
339    pub type Pin01 = Pin<1, 1>;
340    impl OutputPermitted for Pin<1, 1> {}
341
342    pub type Pin02 = Pin<1, 2>;
343    impl OutputPermitted for Pin<1, 2> {}
344
345    pub type Pin03 = Pin<1, 3>;
346    impl OutputPermitted for Pin<1, 3> {}
347
348    pub type Pin04 = Pin<1, 4>;
349    impl OutputPermitted for Pin<1, 4> {}
350
351    pub type Pin05 = Pin<1, 5>;
352    impl OutputPermitted for Pin<1, 5> {}
353
354    pub type Pin06 = Pin<1, 6>;
355    impl OutputPermitted for Pin<1, 6> {}
356
357    pub type Pin07 = Pin<1, 7>;
358    impl OutputPermitted for Pin<1, 7> {}
359
360    // GPIO
361    // UART 1 RX
362    pub type Pin08 = Pin<1, 8>;
363    impl OutputPermitted for Pin<1, 8> {}
364    impl SerialPermitted for Pin<1, 8> {}
365
366    // GPIO
367    // UART 1 TX
368    pub type Pin09 = Pin<1, 9>;
369    impl OutputPermitted for Pin<1, 9> {}
370    impl SerialPermitted for Pin<1, 9> {}
371
372    pub type Pin10 = Pin<1, 10>;
373    impl OutputPermitted for Pin<1, 10> {}
374
375    pub type Pin11 = Pin<1, 11>;
376    impl OutputPermitted for Pin<1, 11> {}
377
378    pub type Pin12 = Pin<1, 12>;
379    impl OutputPermitted for Pin<1, 12> {}
380
381    pub type Pin13 = Pin<1, 13>;
382    impl OutputPermitted for Pin<1, 13> {}
383
384    pub type Pin14 = Pin<1, 14>;
385    impl OutputPermitted for Pin<1, 14> {}
386
387    pub type Pin15 = Pin<1, 15>;
388    impl OutputPermitted for Pin<1, 15> {}
389}
390
391pub mod port_2 {
392    use super::{OutputPermitted, Pin};
393
394    pub type Pin00 = Pin<2, 0>;
395    impl OutputPermitted for Pin<2, 0> {}
396
397    pub type Pin01 = Pin<2, 1>;
398    impl OutputPermitted for Pin<2, 1> {}
399
400    pub type Pin02 = Pin<2, 2>;
401    impl OutputPermitted for Pin<2, 2> {}
402
403    pub type Pin03 = Pin<2, 3>;
404    impl OutputPermitted for Pin<2, 3> {}
405
406    pub type Pin04 = Pin<2, 4>;
407    impl OutputPermitted for Pin<2, 4> {}
408
409    pub type Pin05 = Pin<2, 5>;
410    impl OutputPermitted for Pin<2, 5> {}
411
412    pub type Pin06 = Pin<2, 6>;
413    impl OutputPermitted for Pin<2, 6> {}
414
415    pub type Pin07 = Pin<2, 7>;
416    impl OutputPermitted for Pin<2, 7> {}
417}