-
Notifications
You must be signed in to change notification settings - Fork 65
Open
Description
I would like to refactor this:
/// General Purpose Input/Output driver
pub struct IO {
_io_mux: IO_MUX,
pub pins: Pins,
}(A reduced version of the `Pins` struct:)
struct Pins {
gpio0: GpioPin<Unknown, 0>,
gpio1: GpioPin<Unknown, 1>,
gpio2: GpioPin<Unknown, 2>,
gpio3: GpioPin<Unknown, 3>,
}
// MODE is a series of ZST structs. `Input<PullDown>`, for example
pub struct GpioPin<MODE, const GPIONUM: u8> {
_mode: PhantomData<MODE>,
}into this:
/// General Purpose Input/Output driver
pub struct IO<???> {
_io_mux: IO_MUX,
pub pins: PinHList<???>,
}I've built macros to create the HList type and to construct an initial pin-list:
type InitialPins = gpiopin_HList!(0, 1, 2);
// ->
type InitialPins = HCons<GpioPin<Unknown, { 0 }>,
HCons<GpioPin<Unknown, { 1 }>,
HCons<GpioPin<Unknown, { 2 }>,
HNil>>>;
let pin_list = gpiopin_hlist!(0, 1, 2);
// ->
let pin_list = frunk::hlist!(
GpioPin::<Unknown>, 0>::new(),
GpioPin::<Unknown>, 1>::new(),
GpioPin::<Unknown>, 2>::new()
);...and go from this:
// blinky example: https://github.com/esp-rs/esp-hal/blob/422eb2118676d4c1c938fa6cb2b8211fb177c232/esp32s3-hal/examples/blinky.rs
// Borrow GPIO4, and set it as an output
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = io.pins.gpio4.into_push_pull_output();
// initialize the gpio4 pin by setting it to high
led.set_high().unwrap();
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
loop {
led.toggle().unwrap();
delay.delay_ms(500u32);
}to something like this:
// Give pin 4 to an initialized, ready to go, blinker implementation.
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let (blinky, io) = Blinker::<4>::init(io);
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
blinky.blink_loop(&mut delay, 500);
unreachable!();And `Blinker` might look something like this:
struct Blinker<const PIN: u8> {
pin: GpioPin<Output<PushPull>, PIN>
}
impl<const PIN: u8> Blinker<PIN>
{
fn initialize<???, ???>(io: IO<???>) -> (Self, IO<???>)
{
let (pin, io) = io.pins.pluck();
let mut pin = pin.pin.into_push_pull_output();
pin.set_high().unwrap();
(Self{pin}, io)
}
fn toggle(&mut self) {
self.pin.toggle().unwrap();
}
fn blink_loop(mut self, delay: &mut Delay, rest_period: u16) -> ! {
loop {
self.toggle();
delay.delay_ms(rest_period);
}
}
}Setting up the IO struct is difficult:
- It seems I need to implement
PluckerforIO? - is it possible to implement
Pluckerin such a way that aconst NUM: u8can be used, and pluck solely based on the GpioNums const? - I'm not sure the kind of approach I'd need: should I just re-implement
HConsfrom the ground up, copy-pasting a lot of the code? Is there a way I'd be able to re-use thefrunkimplementations (e.g. by setting the pins field to beHCons<???, ???>)? - Are there any other projects out there that I've missed, that I could use as an example. Closest I found was
usbd-human-interface-device, but that doesn't take advantage of plucking (which is a core feature I'm after)
Metadata
Metadata
Assignees
Labels
No labels