lpc55_hal/drivers/
gint.rs

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
24// pub enum Mode {
25//     And,
26//     Or,
27// }
28
29pub enum Active {
30    High,
31    Low,
32}
33
34pub enum Trigger {
35    Edge,
36    Level,
37}
38
39// This is a kind of build, but on itself.
40// To accommodate the typestate changes, it's a consuming builder.
41
42pub 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}