1use crate::{
2 drivers::pins::Pin,
3 traits::Gint,
4 typestates::pin::{self, PinId},
5};
6
7pub trait Mode {}
8pub trait NotAnd {}
9pub trait NotOr {}
10pub trait Set {}
11pub struct NotSet;
12impl Mode for NotSet {}
13impl NotAnd for NotSet {}
14impl NotOr for NotSet {}
15pub struct And;
16impl Mode for And {}
17impl NotOr for And {}
18impl Set for And {}
19pub struct Or;
20impl Mode for Or {}
21impl NotAnd for Or {}
22impl Set for Or {}
23
24pub enum Active {
30 High,
31 Low,
32}
33
34pub enum Trigger {
35 Edge,
36 Level,
37}
38
39pub struct GroupInterrupt<GINT, MODE = NotSet>
43where
44 GINT: Gint,
45 MODE: Mode,
46{
47 gint: GINT,
48 #[allow(dead_code)]
49 mode: MODE,
50 trigger: Trigger,
51}
52
53impl<GINT> GroupInterrupt<GINT>
54where
55 GINT: Gint,
56{
57 pub fn new_edge_triggered(gint: GINT) -> GroupInterrupt<GINT, NotSet> {
58 GroupInterrupt::new(gint, Trigger::Edge)
59 }
60
61 pub fn new_level_triggered(gint: GINT) -> GroupInterrupt<GINT, NotSet> {
62 GroupInterrupt::new(gint, Trigger::Level)
63 }
64
65 pub fn new(gint: GINT, trigger: Trigger) -> GroupInterrupt<GINT, NotSet> {
66 match trigger {
67 Trigger::Edge => {
68 gint.ctrl.modify(|_, w| w.trig().edge_triggered());
69 }
70 Trigger::Level => {
71 gint.ctrl.modify(|_, w| w.trig().level_triggered());
72 }
73 };
74
75 Self {
76 gint,
77 mode: NotSet,
78 trigger,
79 }
80 }
81}
82
83impl<GINT, MODE> GroupInterrupt<GINT, MODE>
84where
85 GINT: Gint,
86 MODE: Mode,
87 MODE: NotAnd,
88{
89 pub fn or(self) -> GroupInterrupt<GINT, Or> {
90 self.gint.ctrl.modify(|_, w| w.comb().or());
91
92 GroupInterrupt {
93 gint: self.gint,
94 mode: Or,
95 trigger: self.trigger,
96 }
97 }
98}
99
100impl<GINT, MODE> GroupInterrupt<GINT, MODE>
101where
102 GINT: Gint,
103 MODE: Mode,
104 MODE: NotOr,
105{
106 pub fn and(self) -> GroupInterrupt<GINT, And> {
107 self.gint.ctrl.modify(|_, w| w.comb().and());
108
109 GroupInterrupt {
110 gint: self.gint,
111 mode: And,
112 trigger: self.trigger,
113 }
114 }
115}
116
117impl<GINT, MODE> GroupInterrupt<GINT, MODE>
118where
119 GINT: Gint,
120 MODE: Mode,
121 MODE: Set,
122{
123 pub fn on<PIO: PinId>(
124 self,
125 _pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
126 active: Active,
127 ) -> GroupInterrupt<GINT, MODE> {
128 match active {
129 Active::Low => {
130 self.gint.port_pol[PIO::PORT]
131 .modify(|r, w| unsafe { w.pol().bits(r.pol().bits() & !PIO::MASK) });
132 }
133 Active::High => {
134 self.gint.port_pol[PIO::PORT]
135 .modify(|r, w| unsafe { w.pol().bits(r.pol().bits() | PIO::MASK) });
136 }
137 };
138
139 self.gint.port_ena[PIO::PORT]
140 .modify(|r, w| unsafe { w.ena().bits(r.ena().bits() | PIO::MASK) });
141
142 GroupInterrupt {
143 gint: self.gint,
144 mode: self.mode,
145 trigger: self.trigger,
146 }
147 }
148
149 pub fn on_high<PIO: PinId>(
150 self,
151 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
152 ) -> GroupInterrupt<GINT, MODE> {
153 self.on(pin, Active::High)
154 }
155
156 pub fn on_low<PIO: PinId>(
157 self,
158 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
159 ) -> GroupInterrupt<GINT, MODE> {
160 self.on(pin, Active::Low)
161 }
162
163 pub fn clear_interrupt(&self) {
164 self.gint.ctrl.modify(|_, w| w.int().set_bit());
165 }
166}
167
168impl<GINT, MODE> GroupInterrupt<GINT, MODE>
169where
170 GINT: Gint,
171 MODE: Mode,
172 MODE: NotAnd,
173{
174 pub fn or_on<PIO: PinId>(
175 self,
176 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
177 active: Active,
178 ) -> GroupInterrupt<GINT, Or> {
179 self.or().on(pin, active)
180 }
181
182 pub fn or_on_high<PIO: PinId>(
183 self,
184 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
185 ) -> GroupInterrupt<GINT, Or> {
186 self.or_on(pin, Active::High)
187 }
188
189 pub fn or_on_low<PIO: PinId>(
190 self,
191 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
192 ) -> GroupInterrupt<GINT, Or> {
193 self.or_on(pin, Active::Low)
194 }
195}
196
197impl<GINT, MODE> GroupInterrupt<GINT, MODE>
198where
199 GINT: Gint,
200 MODE: Mode,
201 MODE: NotOr,
202{
203 pub fn and_on<PIO: PinId>(
204 self,
205 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
206 active: Active,
207 ) -> GroupInterrupt<GINT, And> {
208 self.and().on(pin, active)
209 }
210
211 pub fn and_on_high<PIO: PinId>(
212 self,
213 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
214 ) -> GroupInterrupt<GINT, And> {
215 self.and_on(pin, Active::High)
216 }
217
218 pub fn and_on_low<PIO: PinId>(
219 self,
220 pin: &Pin<PIO, pin::state::Gpio<pin::gpio::direction::Input>>,
221 ) -> GroupInterrupt<GINT, And> {
222 self.and_on(pin, Active::Low)
223 }
224}