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