1use ch32v1::ch32v103::{self as pac, AFIO, EXTI};
2use core::convert::Infallible;
3use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, ToggleableOutputPin};
4use riscv::interrupt::free;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum Port {
9 GPIOA = 0x00,
11 GPIOB = 0x01,
13 GPIOC = 0x02,
15 GPIOD = 0x03,
17}
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum PinMode {
23 Input = 0b00,
24 Output,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum OutputType {
29 PushPull,
30 OpenDrain,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum OutputSpeed {
35 LowSpeed = 1,
37 MediumSpeed,
39 HighSpeed,
41}
42
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum Pull {
45 PullUp,
46 PullDown,
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub enum CfgLock {
51 Unlock,
52 Lock,
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq)]
56pub enum IntTrigger {
57 Rising = 0b01,
58 Falling = 0b10,
59 RisingFalling = 0b11,
60}
61
62#[derive(Debug, Clone, Copy, PartialEq, Eq)]
63pub enum PinState {
64 Low,
65 High,
66}
67pub struct Pin {
69 port: Port,
70 pin: u8,
71}
72
73impl Pin {
74 const fn regs(&self) -> *const pac::gpioa::RegisterBlock {
76 _regs(&self.port)
77 }
78
79 pub fn new(port: Port, pin: u8, mode: PinMode) -> Self {
80 free(|| {
82 let rcc = unsafe { &(*pac::RCC::ptr()) };
83
84 match port {
85 Port::GPIOA => {
86 if rcc.apb2pcenr.read().iopaen().bit_is_clear() {
87 rcc.apb2pcenr.modify(|_, w| w.iopaen().set_bit())
88 }
89 }
90 Port::GPIOB => {
91 if rcc.apb2pcenr.read().iopben().bit_is_clear() {
92 rcc.apb2pcenr.modify(|_, w| w.iopben().set_bit())
93 }
94 }
95 Port::GPIOC => {
96 if rcc.apb2pcenr.read().iopcen().bit_is_clear() {
97 rcc.apb2pcenr.modify(|_, w| w.iopcen().set_bit())
98 }
99 }
100 Port::GPIOD => {
101 if rcc.apb2pcenr.read().iopden().bit_is_clear() {
102 rcc.apb2pcenr.modify(|_, w| w.iopden().set_bit())
103 }
104 }
105 }
106 });
107
108 let pin = Self {
109 port: port,
110 pin: pin,
111 };
112
113 pin.mode(mode);
114
115 pin
116 }
117
118 pub fn mode(&self, mode: PinMode) {
119 let reg = unsafe { &(*self.regs()) };
120 free(|| {
121 let offset = 4 * (self.pin & !(0x01 << 3));
122 if self.pin >> 3 == 0 {
123 reg.cfglr.modify(|r, w| {
124 let val = r.bits() & !(0x03 << offset) | ((mode as u32) << offset);
125 unsafe { w.bits(val) }
126 })
127 } else {
128 reg.cfghr.modify(|r, w| {
129 let val = r.bits() & !(0x03 << offset) | ((mode as u32) << offset);
130 unsafe { w.bits(val) }
131 })
132 }
133 })
134 }
135
136 pub fn output_type(&self, val: OutputType) {
137 let reg = unsafe { &(*self.regs()) };
138 free(|| {
139 let offset = 4 * (self.pin & !(0x01 << 3));
140 if self.pin >> 3 == 0 {
141 reg.cfglr.modify(|r, w| {
142 let bits = r.bits() & !(0x0c << offset) | ((val as u32) << (offset + 2));
143 unsafe { w.bits(bits) }
144 })
145 }
146 if self.pin >> 3 == 1 {
147 let offset = 4 * (self.pin - 8);
148 reg.cfghr.modify(|r, w| {
149 let bits = r.bits() & !(0x0c << offset) | ((val as u32) << (offset + 2));
150 unsafe { w.bits(bits) }
151 })
152 }
153 })
154 }
155
156 pub fn output_speed(&self, speed: OutputSpeed) {
157 let reg = unsafe { &(*(self.regs())) };
158
159 free(|| {
160 if self.pin >> 3 == 0 {
161 let offset = 4 * (self.pin & !(0x01 << 3));
162 reg.cfglr.modify(|r, w| {
163 let bits = r.bits() & !(0x03 << offset) | (speed as u32);
164 unsafe { w.bits(bits) }
165 })
166 }
167 if self.pin >> 3 == 1 {
168 let offset = 4 * (self.pin - 8);
169 reg.cfghr.modify(|r, w| {
170 let bits = r.bits() & !(0x03 << offset) | (speed as u32);
171 unsafe { w.bits(bits) }
172 })
173 }
174 })
175 }
176
177 pub fn pull(&self, value: Pull) {
178 let reg = unsafe { &(*(self.regs())) };
179
180 free(|| {
181 let offset = 4 * (self.pin & !(0x01 << 3));
182
183 let mut current_mode = 0x00;
184
185 if self.pin >> 3 == 0 {
186 current_mode = (reg.cfglr.read().bits() & (0x03 << offset)) >> offset;
187 } else if self.pin >> 3 == 1 {
188 current_mode = (reg.cfghr.read().bits() & (0x03 << offset)) >> offset;
189 }
190
191 if current_mode == PinMode::Input as u32 {
192 reg.outdr.modify(|r, w| {
193 let bits = r.bits() & !(0x01 << self.pin) | ((value as u32) << self.pin);
194 unsafe { w.bits(bits) }
195 })
196 }
197 })
198 }
199
200 pub fn cfg_lock(&self, value: CfgLock) {
201 let reg = unsafe { &(*(self.regs())) };
202
203 free(|| {
204 if reg.lckr.read().lckk().is_unlocked() {
205 reg.lckr.modify(|_, w| w.lckk().locked())
206 }
207 todo!()
208 })
209 }
210
211 pub fn enable_int(&self, trigger: IntTrigger) {
212 let afio = unsafe { &(*AFIO::ptr()) };
213 let offset = (self.pin & 0x03) * 4;
214 let exti = unsafe { &(*(EXTI::ptr())) };
215
216 free(|| {
217 if self.pin <= 3 {
219 afio.exticr1
220 .modify(|_, w| unsafe { w.bits((self.port as u32) << offset) })
221 } else if self.pin <= 7 {
222 afio.exticr2
223 .modify(|_, w| unsafe { w.bits((self.port as u32) << offset) })
224 } else if self.pin <= 11 {
225 afio.exticr3
226 .modify(|_, w| unsafe { w.bits((self.port as u32) << offset) })
227 } else if self.pin <= 15 {
228 afio.exticr4
229 .modify(|_, w| unsafe { w.bits((self.port as u32) << offset) })
230 }
231
232 exti.intenr
234 .modify(|_, w| unsafe { w.bits(0x01 << self.pin) });
235 exti.evenr
237 .modify(|_, w| unsafe { w.bits(0x01 << self.pin) });
238 exti.rtenr
240 .modify(|_, w| unsafe { w.bits((trigger as u32 & 0x01) << self.pin) });
241 exti.ftenr
243 .modify(|_, w| unsafe { w.bits((trigger as u32 >> 1) << self.pin) });
244 })
245 }
246
247 pub fn disable_int(&self) {
248 let exti = unsafe { &(*(EXTI::ptr())) };
249
250 free(|| {
251 exti.intenr.modify(|_, w| unsafe { w.bits(0 << self.pin) });
253 exti.evenr.modify(|_, w| unsafe { w.bits(0 << self.pin) });
255 exti.rtenr.modify(|_, w| unsafe { w.bits(0 << self.pin) });
257 exti.ftenr.modify(|_, w| unsafe { w.bits(0 << self.pin) });
259 })
260 }
261
262 pub fn get_state(&self) -> PinState {
263 let reg = unsafe { &(*(self.regs())) };
264 free(|| {
265 let state = (reg.indr.read().bits() & !(0x01 << self.pin)) >> self.pin;
266
267 if state == 1 {
268 PinState::High
269 } else {
270 PinState::Low
271 }
272 })
273 }
274
275 pub fn set_state(&self, value: PinState) {
276 let reg = unsafe { &(*(self.regs())) };
277
278 free(|| match value {
279 PinState::Low => reg.bcr.write(|w| unsafe { w.bits(0x01 << self.pin) }),
280 PinState::High => reg.bshr.write(|w| unsafe { w.bits(0x01 << self.pin) }),
281 })
282 }
283
284 pub fn is_high(&self) -> bool {
285 let reg = unsafe { &(*(self.regs())) };
286 free(|| {
287 let state = (reg.indr.read().bits() & (0x01 << self.pin)) >> self.pin;
288 if state == 0 {
289 false
290 } else {
291 true
292 }
293 })
294 }
295
296 pub fn is_low(&self) -> bool {
297 !self.is_high()
298 }
299
300 pub fn set_high(&self) {
301 self.set_state(PinState::High);
302 }
303
304 pub fn set_low(&self) {
305 self.set_state(PinState::Low);
306 }
307
308 pub fn toggle(&self) {
309 if self.is_high() {
310 self.set_low();
311 } else {
312 self.set_high();
313 }
314 }
315}
316
317impl InputPin for Pin {
318 type Error = Infallible;
319
320 fn is_high(&self) -> Result<bool, Self::Error> {
321 Ok(Pin::is_high(&self))
322 }
323
324 fn is_low(&self) -> Result<bool, Self::Error> {
325 Ok(Pin::is_low(&self))
326 }
327}
328
329impl OutputPin for Pin {
330 type Error = Infallible;
331
332 fn set_high(&mut self) -> Result<(), Self::Error> {
333 Ok(Pin::set_high(&self))
334 }
335
336 fn set_low(&mut self) -> Result<(), Self::Error> {
337 Ok(Pin::set_low(&self))
338 }
339
340 fn set_state(&mut self, state: embedded_hal::digital::v2::PinState) -> Result<(), Self::Error> {
341 match state {
342 embedded_hal::digital::v2::PinState::High => Ok(Pin::set_state(&self, PinState::High)),
343 embedded_hal::digital::v2::PinState::Low => Ok(Pin::set_state(&self, PinState::Low)),
344 }
345 }
346}
347
348impl ToggleableOutputPin for Pin {
349 type Error = Infallible;
350
351 fn toggle(&mut self) -> Result<(), Self::Error> {
352 Ok(Pin::toggle(&self))
353 }
354}
355
356impl StatefulOutputPin for Pin {
357 fn is_set_high(&self) -> Result<bool, Self::Error> {
358 Ok(Pin::is_high(&self))
359 }
360
361 fn is_set_low(&self) -> Result<bool, Self::Error> {
362 Ok(Pin::is_low(&self))
363 }
364}
365const fn _regs(port: &Port) -> *const pac::gpioa::RegisterBlock {
366 match port {
367 Port::GPIOA => pac::GPIOA::ptr(),
368 Port::GPIOB => pac::GPIOB::ptr(),
369 Port::GPIOC => pac::GPIOC::ptr(),
370 Port::GPIOD => pac::GPIOD::ptr(),
371 }
372}