1use core::convert::Infallible;
3use core::marker::PhantomData;
4use embedded_hal::digital::{ErrorType, InputPin, OutputPin};
5
6use mik32_pac::Peripherals;
7
8pub struct Floating;
10
11pub struct PullDown;
13
14pub struct PullUp;
16
17pub struct Output;
19
20pub 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 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
199impl<const P: u8, const N: u8> OutputPin for Pin<P, N, Output> {
201 #[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 #[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 pub type Pin05 = Pin<0, 5>;
290 impl OutputPermitted for Pin<0, 5> {}
291 impl SerialPermitted for Pin<0, 5> {}
292
293 pub type Pin06 = Pin<0, 6>;
296 impl OutputPermitted for Pin<0, 6> {}
297 impl SerialPermitted for Pin<0, 6> {}
298
299 pub type Pin07 = Pin<0, 7>;
302 impl OutputPermitted for Pin<0, 7> {}
303 impl SerialPermitted for Pin<0, 7> {}
304
305 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 pub type Pin08 = Pin<1, 8>;
363 impl OutputPermitted for Pin<1, 8> {}
364 impl SerialPermitted for Pin<1, 8> {}
365
366 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}