TransparentPins: offer iterator interface
This commit is contained in:
parent
70526c44eb
commit
6dabe79aa5
@ -45,9 +45,9 @@ struct Connection {
|
||||
#[embassy_executor::task]
|
||||
async fn scanner_task(mut pin_driver: pins::TransparentPins) {
|
||||
log::info!("scanner_task: setting pins as input");
|
||||
for i in 0..pin_driver.n_usable_pins() {
|
||||
unwrap(pin_driver.set_input(i as u8)).await;
|
||||
unwrap(pin_driver.set_pull(i as u8, gpio::Pull::Up)).await;
|
||||
for i in pin_driver.pins {
|
||||
unwrap(pin_driver.set_input(i)).await;
|
||||
unwrap(pin_driver.set_pull(i, gpio::Pull::Up)).await;
|
||||
}
|
||||
|
||||
loop {
|
||||
@ -61,16 +61,14 @@ async fn scanner_task(mut pin_driver: pins::TransparentPins) {
|
||||
log::info!("");
|
||||
log::info!("---");
|
||||
log::info!("STARTING SCAN...");
|
||||
for gnd_pin in 0..pin_driver.n_usable_pins() {
|
||||
let gnd_pin = gnd_pin as u8;
|
||||
for gnd_pin in pin_driver.pins {
|
||||
unwrap(pin_driver.set_output(gnd_pin)).await;
|
||||
let input = unwrap(pin_driver.read_all()).await;
|
||||
unwrap(pin_driver.set_input(gnd_pin)).await;
|
||||
|
||||
// this represents the pins that are different from expected
|
||||
let mask = input ^ (((1 << pin_driver.n_usable_pins()) - 1) ^ (1 << gnd_pin));
|
||||
for input_pin in 0..pin_driver.n_usable_pins() {
|
||||
let input_pin = input_pin as u8;
|
||||
for input_pin in pin_driver.pins {
|
||||
if ((1 << input_pin) & mask) != 0 && n_connections < MAX_CONNECTIONS {
|
||||
connections[n_connections] = Some(Connection { gnd_pin, input_pin });
|
||||
n_connections += 1;
|
||||
|
@ -60,9 +60,9 @@ async fn main(_spawner: Spawner) {
|
||||
.await;
|
||||
|
||||
log::info!("main: setting pins as input");
|
||||
for i in 0..pin_driver.n_usable_pins() {
|
||||
unwrap(pin_driver.set_input(i as u8)).await;
|
||||
unwrap(pin_driver.set_pull(i as u8, gpio::Pull::Up)).await;
|
||||
for i in pin_driver.pins {
|
||||
unwrap(pin_driver.set_input(i)).await;
|
||||
unwrap(pin_driver.set_pull(i, gpio::Pull::Up)).await;
|
||||
}
|
||||
log::debug!("main: setting pin 0 as output, active low");
|
||||
unwrap(pin_driver.set_output(0)).await;
|
||||
|
43
src/pins.rs
43
src/pins.rs
@ -79,6 +79,21 @@ impl<E> From<mcp23017::Error<E>> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// Range of pins that can be iterated over
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct PinCollection {
|
||||
/// Number of total usable pins.
|
||||
n_usable: usize,
|
||||
}
|
||||
|
||||
impl IntoIterator for PinCollection {
|
||||
type Item = u8;
|
||||
type IntoIter = core::ops::Range<u8>;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
0..(self.n_usable as u8)
|
||||
}
|
||||
}
|
||||
|
||||
/// "Transparent pins" to consistently interface with a GPIO extender + onboard GPIO ports.
|
||||
///
|
||||
/// This interface uses a single addressing scheme for all the pins it manages. Extender A is 0-15,
|
||||
@ -92,13 +107,13 @@ impl<E> From<mcp23017::Error<E>> for Error {
|
||||
/// pins addressing scheme.
|
||||
pub struct TransparentPins {
|
||||
addrs: [u8; N_PIN_EXTENDERS],
|
||||
pins: [Flex<'static, AnyPin>; N_REGULAR_PINS],
|
||||
onboard_pins: [Flex<'static, AnyPin>; N_REGULAR_PINS],
|
||||
i2c_bus: I2cBus,
|
||||
disable_unsafe_pins: bool,
|
||||
/// Number of total usable pins.
|
||||
n_total_pins: usize,
|
||||
/// Usable pins per extender. Depends on `disable_unsafe_pins`.
|
||||
usable_pins_per_extender: usize,
|
||||
/// Iterable over all usable pins
|
||||
pub pins: PinCollection,
|
||||
/// Usable pin count on all extenders. Depends on `disable_unsafe_pins`.
|
||||
usable_extended_pins: usize,
|
||||
}
|
||||
@ -124,7 +139,7 @@ macro_rules! extender {
|
||||
impl TransparentPins {
|
||||
/// Get amount of usable pins. Transparent pins all have an address from `0..n_usable_pins()`.
|
||||
pub fn n_usable_pins(&self) -> usize {
|
||||
self.n_total_pins
|
||||
self.pins.n_usable
|
||||
}
|
||||
|
||||
/// Transform addresses into a transparent pin number, taking into account pins that aren't being used.
|
||||
@ -176,12 +191,14 @@ impl TransparentPins {
|
||||
) -> Result<Self, Error> {
|
||||
let mut ret = TransparentPins {
|
||||
addrs,
|
||||
pins: pins.map(Flex::new),
|
||||
onboard_pins: pins.map(Flex::new),
|
||||
i2c_bus: shared_bus::BusManagerSimple::new(i2c),
|
||||
disable_unsafe_pins: false,
|
||||
usable_pins_per_extender: PINS_PER_EXTENDER,
|
||||
usable_extended_pins: N_EXTENDED_PINS,
|
||||
n_total_pins: N_EXTENDED_PINS + N_REGULAR_PINS,
|
||||
pins: PinCollection {
|
||||
n_usable: N_EXTENDED_PINS + N_REGULAR_PINS,
|
||||
},
|
||||
};
|
||||
if disable_unsafe_pins {
|
||||
for i in 0..N_PIN_EXTENDERS {
|
||||
@ -189,10 +206,10 @@ impl TransparentPins {
|
||||
ret.set_output((i as u8) * (PINS_PER_EXTENDER as u8) + PORT_B + 7)?;
|
||||
ret.usable_pins_per_extender = PINS_PER_EXTENDER - UNSAFE_PER_EXTENDER;
|
||||
ret.usable_extended_pins = N_PIN_EXTENDERS * ret.usable_pins_per_extender;
|
||||
ret.n_total_pins = ret.usable_extended_pins + N_REGULAR_PINS;
|
||||
ret.pins.n_usable = ret.usable_extended_pins + N_REGULAR_PINS;
|
||||
}
|
||||
ret.disable_unsafe_pins = true;
|
||||
log::debug!("TransparentPins: {} usable pins", ret.n_total_pins)
|
||||
log::debug!("TransparentPins: {} usable pins", ret.pins.n_usable)
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
@ -230,7 +247,7 @@ impl TransparentPins {
|
||||
extender!(self, i)?.write_gpioab(self.usable_to_raw(ext_val as u16))?;
|
||||
}
|
||||
for pin in 0..N_REGULAR_PINS {
|
||||
self.pins[pin].set_level(match (val >> self.usable_extended_pins >> pin) & 1 {
|
||||
self.onboard_pins[pin].set_level(match (val >> self.usable_extended_pins >> pin) & 1 {
|
||||
0 => embassy_rp::gpio::Level::Low,
|
||||
1 => embassy_rp::gpio::Level::High,
|
||||
_ => panic!("Invalid level"),
|
||||
@ -250,7 +267,7 @@ impl TransparentPins {
|
||||
ret |= (self.raw_to_usable(read_val) as u64) << (i * self.usable_pins_per_extender);
|
||||
}
|
||||
for pin in 0..N_REGULAR_PINS {
|
||||
ret |= (self.pins[pin].is_high() as u64) << (self.usable_extended_pins + pin);
|
||||
ret |= (self.onboard_pins[pin].is_high() as u64) << (self.usable_extended_pins + pin);
|
||||
}
|
||||
|
||||
Ok(ret)
|
||||
@ -264,7 +281,7 @@ impl TransparentPins {
|
||||
let pin = self.get_pin(pin_n)?;
|
||||
match pin {
|
||||
TransparentPin::Onboard(p) => {
|
||||
self.pins[p].set_pull(pull);
|
||||
self.onboard_pins[p].set_pull(pull);
|
||||
}
|
||||
TransparentPin::Extended(p) => {
|
||||
let pull_on: bool = match pull {
|
||||
@ -284,7 +301,7 @@ impl TransparentPins {
|
||||
let pin_n = self.addr_to_pin(addr);
|
||||
let pin = self.get_pin(pin_n)?;
|
||||
match pin {
|
||||
TransparentPin::Onboard(p) => self.pins[p].set_as_input(),
|
||||
TransparentPin::Onboard(p) => self.onboard_pins[p].set_as_input(),
|
||||
TransparentPin::Extended(p) => {
|
||||
extender!(self, p.ext_id)?.pin_mode(p.loc_pin, mcp23017::PinMode::INPUT)?
|
||||
}
|
||||
@ -297,7 +314,7 @@ impl TransparentPins {
|
||||
let pin_n = self.addr_to_pin(addr);
|
||||
let pin = self.get_pin(pin_n)?;
|
||||
match pin {
|
||||
TransparentPin::Onboard(p) => self.pins[p].set_as_output(),
|
||||
TransparentPin::Onboard(p) => self.onboard_pins[p].set_as_output(),
|
||||
TransparentPin::Extended(p) => {
|
||||
extender!(self, p.ext_id)?.pin_mode(p.loc_pin, mcp23017::PinMode::OUTPUT)?
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user