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;
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 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
228impl<const P: u8, const N: u8> OutputPin for Pin<P, N, Output> {
230 #[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 #[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 pub type Pin05 = Pin<0, 5>;
319 impl OutputPermitted for Pin<0, 5> {}
320 impl SerialPermitted for Pin<0, 5> {}
321
322 pub type Pin06 = Pin<0, 6>;
325 impl OutputPermitted for Pin<0, 6> {}
326 impl SerialPermitted for Pin<0, 6> {}
327
328 pub type Pin07 = Pin<0, 7>;
331 impl OutputPermitted for Pin<0, 7> {}
332 impl SerialPermitted for Pin<0, 7> {}
333
334 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 pub type Pin08 = Pin<1, 8>;
394 impl OutputPermitted for Pin<1, 8> {}
395 impl SerialPermitted for Pin<1, 8> {}
396
397 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}