1#![doc = crate::before_snippet!()]
28use core::marker::PhantomData;
55
56use crate::{
57 gpio::{
58 interconnect::{InputSignal, OutputSignal},
59 Level,
60 Pull,
61 },
62 peripheral::{Peripheral, PeripheralRef},
63 peripherals::GPIO_SD,
64 private,
65};
66
67#[non_exhaustive]
69pub struct Channels<'d> {
70 _gpio_sd: PeripheralRef<'d, GPIO_SD>,
71 pub channel0_task: TaskChannel<0>,
73 pub channel0_event: EventChannel<0>,
75 pub channel1_task: TaskChannel<1>,
77 pub channel1_event: EventChannel<1>,
79 pub channel2_task: TaskChannel<2>,
81 pub channel2_event: EventChannel<2>,
83 pub channel3_task: TaskChannel<3>,
85 pub channel3_event: EventChannel<3>,
87 pub channel4_task: TaskChannel<4>,
89 pub channel4_event: EventChannel<4>,
91 pub channel5_task: TaskChannel<5>,
93 pub channel5_event: EventChannel<5>,
95 pub channel6_task: TaskChannel<6>,
97 pub channel6_event: EventChannel<6>,
99 pub channel7_task: TaskChannel<7>,
101 pub channel7_event: EventChannel<7>,
103}
104
105impl<'d> Channels<'d> {
106 pub fn new(peripheral: impl Peripheral<P = GPIO_SD> + 'd) -> Self {
108 crate::into_ref!(peripheral);
109
110 Self {
111 _gpio_sd: peripheral,
112 channel0_task: TaskChannel {},
113 channel0_event: EventChannel {},
114 channel1_task: TaskChannel {},
115 channel1_event: EventChannel {},
116 channel2_task: TaskChannel {},
117 channel2_event: EventChannel {},
118 channel3_task: TaskChannel {},
119 channel3_event: EventChannel {},
120 channel4_task: TaskChannel {},
121 channel4_event: EventChannel {},
122 channel5_task: TaskChannel {},
123 channel5_event: EventChannel {},
124 channel6_task: TaskChannel {},
125 channel6_event: EventChannel {},
126 channel7_task: TaskChannel {},
127 channel7_event: EventChannel {},
128 }
129 }
130}
131
132#[derive(Clone, Copy, Debug)]
134#[cfg_attr(feature = "defmt", derive(defmt::Format))]
135pub struct InputConfig {
136 pub pull: Pull,
138}
139
140impl Default for InputConfig {
141 fn default() -> Self {
142 Self { pull: Pull::None }
143 }
144}
145
146pub struct EventChannel<const C: u8> {}
148
149impl<const C: u8> EventChannel<C> {
150 pub fn rising_edge<'d>(
152 self,
153 pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
154 pin_config: InputConfig,
155 ) -> Event<'d> {
156 self.into_event(pin, pin_config, EventKind::Rising)
157 }
158
159 pub fn falling_edge<'d>(
161 self,
162 pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
163 pin_config: InputConfig,
164 ) -> Event<'d> {
165 self.into_event(pin, pin_config, EventKind::Falling)
166 }
167
168 pub fn any_edge<'d>(
170 self,
171 pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
172 pin_config: InputConfig,
173 ) -> Event<'d> {
174 self.into_event(pin, pin_config, EventKind::Any)
175 }
176
177 fn into_event<'d>(
178 self,
179 pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
180 pin_config: InputConfig,
181 kind: EventKind,
182 ) -> Event<'d> {
183 crate::into_mapped_ref!(pin);
184
185 pin.init_input(pin_config.pull);
186
187 enable_event_channel(C, pin.number());
188 Event {
189 id: kind.id() + C,
190 _pin: PhantomData,
191 }
192 }
193}
194
195#[derive(Clone, Copy, Debug)]
196#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197enum EventKind {
198 Rising,
199 Falling,
200 Any,
201}
202
203impl EventKind {
204 fn id(&self) -> u8 {
205 match self {
206 EventKind::Rising => 1,
207 EventKind::Falling => 9,
208 EventKind::Any => 17,
209 }
210 }
211}
212
213pub struct Event<'d> {
215 _pin: PhantomData<&'d mut ()>,
216 id: u8,
217}
218
219impl private::Sealed for Event<'_> {}
220
221impl crate::etm::EtmEvent for Event<'_> {
222 fn id(&self) -> u8 {
223 self.id
224 }
225}
226
227#[derive(Clone, Copy, Debug)]
229#[cfg_attr(feature = "defmt", derive(defmt::Format))]
230pub struct OutputConfig {
231 pub open_drain: bool,
233 pub pull: Pull,
235 pub initial_state: Level,
237}
238
239impl Default for OutputConfig {
240 fn default() -> Self {
241 Self {
242 open_drain: false,
243 pull: Pull::None,
244 initial_state: Level::Low,
245 }
246 }
247}
248
249pub struct TaskChannel<const C: u8> {}
251
252impl<const C: u8> TaskChannel<C> {
253 pub fn set<'d>(
260 self,
261 pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
262 pin_config: OutputConfig,
263 ) -> Task<'d> {
264 self.into_task(pin, pin_config, TaskKind::Set)
265 }
266
267 pub fn clear<'d>(
269 self,
270 pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
271 pin_config: OutputConfig,
272 ) -> Task<'d> {
273 self.into_task(pin, pin_config, TaskKind::Clear)
274 }
275
276 pub fn toggle<'d>(
278 self,
279 pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
280 pin_config: OutputConfig,
281 ) -> Task<'d> {
282 self.into_task(pin, pin_config, TaskKind::Toggle)
283 }
284
285 fn into_task<'d>(
286 self,
287 pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
288 pin_config: OutputConfig,
289 kind: TaskKind,
290 ) -> Task<'d> {
291 crate::into_mapped_ref!(pin);
292
293 pin.set_output_high(pin_config.initial_state.into());
294 if pin_config.open_drain {
295 pin.pull_direction(pin_config.pull);
296 pin.set_to_open_drain_output();
297 } else {
298 pin.set_to_push_pull_output();
299 }
300
301 enable_task_channel(C, pin.number());
302 Task {
303 id: kind.id() + C,
304 _pin: PhantomData,
305 }
306 }
307}
308
309#[derive(Clone, Copy, Debug)]
310#[cfg_attr(feature = "defmt", derive(defmt::Format))]
311enum TaskKind {
312 Set,
313 Clear,
314 Toggle,
315}
316
317impl TaskKind {
318 fn id(&self) -> u8 {
319 match self {
320 TaskKind::Set => 1,
321 TaskKind::Clear => 9,
322 TaskKind::Toggle => 17,
323 }
324 }
325}
326
327pub struct Task<'d> {
329 _pin: PhantomData<&'d mut ()>,
330 id: u8,
331}
332
333impl private::Sealed for Task<'_> {}
334
335impl crate::etm::EtmTask for Task<'_> {
336 fn id(&self) -> u8 {
337 self.id
338 }
339}
340
341fn enable_task_channel(channel: u8, pin: u8) {
342 let gpio_sd = GPIO_SD::regs();
343 let ptr = unsafe { gpio_sd.etm_task_p0_cfg().as_ptr().add(pin as usize / 4) };
344 let shift = 8 * (pin as usize % 4);
345 unsafe {
347 ptr.write_volatile(
348 ptr.read_volatile() & !(0xf << shift)
349 | (1 << shift)
350 | ((channel as u32) << (shift + 1)),
351 );
352 }
353}
354
355fn enable_event_channel(channel: u8, pin: u8) {
356 let gpio_sd = GPIO_SD::regs();
357 gpio_sd
358 .etm_event_ch_cfg(channel as usize)
359 .modify(|_, w| w.event_en().clear_bit());
360 gpio_sd
361 .etm_event_ch_cfg(channel as usize)
362 .modify(|_, w| unsafe { w.event_sel().bits(pin) });
363 gpio_sd
364 .etm_event_ch_cfg(channel as usize)
365 .modify(|_, w| w.event_en().set_bit());
366}