1use super::{Modules, Reg};
2use crate::{devices::SeesawDevice, Driver, DriverExt, SeesawError};
3
4#[allow(dead_code)]
8const SET_OUTPUT: &Reg = &[Modules::Gpio.into_u8(), 0x02];
9
10const SET_INPUT: &Reg = &[Modules::Gpio.into_u8(), 0x03];
14
15const GPIO: &Reg = &[Modules::Gpio.into_u8(), 0x04];
21
22const SET_HIGH: &Reg = &[Modules::Gpio.into_u8(), 0x05];
26
27const SET_LOW: &Reg = &[Modules::Gpio.into_u8(), 0x06];
31
32#[allow(dead_code)]
36const TOGGLE: &Reg = &[Modules::Gpio.into_u8(), 0x07];
37
38#[allow(dead_code)]
43const INT_ENABLE: &Reg = &[Modules::Gpio.into_u8(), 0x08];
44
45#[allow(dead_code)]
49const INT_DISABLE: &Reg = &[Modules::Gpio.into_u8(), 0x09];
50
51#[allow(dead_code)]
56const INT_FLAG: &Reg = &[Modules::Gpio.into_u8(), 0x0A];
57
58const PULL_ENABLE: &Reg = &[Modules::Gpio.into_u8(), 0x0B];
65
66#[allow(dead_code)]
70const PULL_DISABLE: &Reg = &[Modules::Gpio.into_u8(), 0x0C];
71
72pub trait GpioModule<D: Driver>: SeesawDevice<Driver = D> {
84 fn digital_read(&mut self, pin: u8) -> Result<bool, SeesawError<D::Error>> {
85 self.digital_read_bulk()
86 .map(|pins| !matches!((pins >> pin) & 0x1, 1))
87 }
88
89 fn digital_read_bulk(&mut self) -> Result<u32, SeesawError<D::Error>> {
90 let addr = self.addr();
91 self.driver().read_u32(addr, GPIO).map_err(SeesawError::I2c)
92 }
93
94 fn digital_write(&mut self, pin: u8, output: PinOutput) -> Result<(), SeesawError<D::Error>> {
95 self.digital_write_bulk(1 << pin, output)
96 }
97
98 fn digital_write_bulk(
99 &mut self,
100 pins: u32,
101 output: PinOutput,
102 ) -> Result<(), SeesawError<D::Error>> {
103 let addr = self.addr();
104 let bus = self.driver();
105
106 match output {
107 PinOutput::High => bus.write_u32(addr, SET_HIGH, pins),
108 PinOutput::Low => bus.write_u32(addr, SET_LOW, pins),
109 PinOutput::Set => bus.write_u32(addr, GPIO, pins),
110 PinOutput::Toggle => bus.write_u32(addr, TOGGLE, pins),
111 }
112 .map_err(SeesawError::I2c)
113 }
114
115 fn set_pin_mode(&mut self, pin: u8, mode: PinMode) -> Result<(), SeesawError<D::Error>> {
116 self.set_pin_mode_bulk(1 << pin, mode)
117 }
118
119 fn set_pin_mode_bulk(&mut self, pins: u32, mode: PinMode) -> Result<(), SeesawError<D::Error>> {
120 let addr = self.addr();
121 let bus = self.driver();
122
123 match mode {
124 PinMode::Output => bus.write_u32(addr, SET_OUTPUT, pins),
125 PinMode::Input => bus.write_u32(addr, SET_INPUT, pins),
126 PinMode::InputPullup => bus
127 .write_u32(addr, SET_INPUT, pins)
128 .and_then(|_| bus.write_u32(addr, PULL_ENABLE, pins))
129 .and_then(|_| bus.write_u32(addr, SET_HIGH, pins)),
130 PinMode::InputPulldown => bus
131 .write_u32(addr, SET_INPUT, pins)
132 .and_then(|_| bus.write_u32(addr, PULL_ENABLE, pins))
133 .and_then(|_| bus.write_u32(addr, SET_LOW, pins)),
134 _ => unimplemented!("Other pins modes are not supported."),
135 }
136 .map_err(SeesawError::I2c)
137 }
138}
139
140#[derive(Clone, Copy, Debug)]
141#[cfg_attr(feature = "defmt", derive(defmt::Format))]
142#[repr(u8)]
143pub enum PinOutput {
144 High,
145 Low,
146 Set,
147 Toggle,
148}
149
150#[derive(Clone, Copy, Debug)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152#[repr(u8)]
153pub enum PinMode {
154 Input = 0x01,
155 Output = 0x02,
156 Pullup = 0x04,
157 InputPullup = 0x05,
158 Pulldown = 0x08,
159 InputPulldown = 0x09,
160 OpenDrain = 0x10,
161 OutputOpenDrain = 0x12,
162 Special = 0xF0,
163 Function1 = 0x00,
164 Function2 = 0x20,
165 Function3 = 0x40,
166 Function4 = 0x60,
167 Function5 = 0x80,
168 Function6 = 0xA0,
169 Analog = 0xC0,
170}
171
172impl From<PinMode> for u8 {
173 fn from(value: PinMode) -> Self {
174 value as u8
175 }
176}
177
178#[derive(Clone, Copy, Debug)]
179#[cfg_attr(feature = "defmt", derive(defmt::Format))]
180#[repr(u8)]
181pub enum InterruptMode {
182 Disabled = 0x00,
183 Rising = 0x01,
184 Falling = 0x02,
185 Change = 0x03,
186 Onlow = 0x04,
187 Onhigh = 0x05,
188 OnlowWe = 0x0C,
189 OnhighWe = 0x0D,
190}
191
192impl From<InterruptMode> for u8 {
193 fn from(value: InterruptMode) -> Self {
194 value as u8
195 }
196}