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}