Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do a crate that is microcontroller agnostic #14

Closed
TeXitoi opened this issue Sep 24, 2019 · 15 comments
Closed

Do a crate that is microcontroller agnostic #14

TeXitoi opened this issue Sep 24, 2019 · 15 comments

Comments

@TeXitoi
Copy link
Owner

TeXitoi commented Sep 24, 2019

The idea is to provide all you need to construct your keyboard. It will provide:

  • the machinery to do the matrix, allowing the user to choose the pins (almost done)
  • the debouncer (it's already generic enough I think)
  • the layout, that takes in parameters the description of the layers provided by the user
  • the hid to be used with usb-device
  • some examples using the crate based on the bluepill and rtfm
@TeXitoi
Copy link
Owner Author

TeXitoi commented Oct 1, 2019

@TheZoq2 relevant issue where we can discuss about a keyboard crate.

@TeXitoi
Copy link
Owner Author

TeXitoi commented Oct 1, 2019

Some person that might be interested: @ah- @hdhoang @TyberiusPrime

@TheZoq2
Copy link

TheZoq2 commented Oct 1, 2019

Very nice. For it to work with my keyboard, it also has to support split keyboards and backlight.

Keebrs deals with the first point really well. Each the boards send coordinates of keys pressed over serial. Whichever board gets a USB connection makes itself master, and you can even chain boards.

It would be kind of nice to see something like embedded-hal but for keyboards.
Perhaps we could have a generic keyboard base that can handle translation from key coordinates to actual key presses, with support for layers and all the fancy stuff like that.

This would interract with implementaions of some traits like

enum EventType {
    Press,
    Release
}
pub struct KeyEvent {
    coords: (u8, u8),
    type: EventType
}
// Could be implemented for matrix checks, data from another keyboard etc.
pub trait KeypressSource {
    fn events(&mut self) -> Iterator<Item=KeyEvent>
}

pub trait BacklightRenderer {
    fn render(<some structure representing>) {}
}

What do you think?

@TeXitoi
Copy link
Owner Author

TeXitoi commented Oct 2, 2019

Yeah, that's exactly the kind of feedbacks that I'm looking for.

A trait with some kind of combinators/modifiers would be great. For example, something to translate the events, or convert a 8x6 to a 4x12 matrix.

I'm not sure I want to manage backlight explicitly, but allowing custom events in the layout would allow to manage other things as lights, sound, screen or anything else.

@TheZoq2
Copy link

TheZoq2 commented Oct 2, 2019

A trait with some kind of combinators/modifiers would be great. For example, something to translate the events, or convert a 8x6 to a 4x12 matrix.

Yea, that's something I'd like as well. I imagine being able to do something like

let local_scanner = Matrix::new();
let slave_scanner = OtherKeyboardOverSerial::new();

let full_scanner = local_scanner
    .merge(slave_scanner.translate(|x, y| x + 6));

let layout = Layout::new();

loop {
    let raw_keys = full_scanner.new_keys();

    let pressed_keys = layout.translate(raw_keys)

    usb.send(pressed_keys)

    backlight.new_events(pressed_keys, raw_keys);
}

There are probably plenty of issues with this API, but something along those lines would suit all my needs I think

@TyberiusPrime
Copy link

  • the machinery to do the matrix, allowing the user to choose the pins (almost done)

I'd love to see this done - I miserably failed even abstracting over the pins of one platform.

For the 'turning presses into USB-input' part (layers etc...) you might want to check out my keytokey crate, which does this in a totally processor agnostic and flexible way: https://github.com/TyberiusPrime/KeyToKey

It's configuration is a departure from the qmk style 'define each key on each layer' approach though.

@ah-
Copy link

ah- commented Oct 7, 2019

Wow, these are both really cool! What are you doing about the USB stack, is there something robust around now?

@TyberiusPrime
Copy link

keytokey abstracts the usb stack into a trait that collects usb-keycodes for sending by the stack.

I have a reference implementation for the bluepill, the stack is borrowed from Keyberon (great work, btw, it's been very robust against my coding mishaps during development).

@TeXitoi
Copy link
Owner Author

TeXitoi commented Oct 8, 2019

@TyberiusPrime For the generic matrix implementation, you can look at https://github.com/TeXitoi/keyberon/blob/master/src/matrix.rs

That's not yet finished as you now need to declare your pin like that:

pub struct Cols(
    pub PB12<Input<PullUp>>,
    pub PB13<Input<PullUp>>,
    pub PB14<Input<PullUp>>,
    pub PB15<Input<PullUp>>,
    pub PA8<Input<PullUp>>,
    pub PA9<Input<PullUp>>,
    pub PA10<Input<PullUp>>,
    pub PB5<Input<PullUp>>,
    pub PB6<Input<PullUp>>,
    pub PB7<Input<PullUp>>,
    pub PB8<Input<PullUp>>,
    pub PB9<Input<PullUp>>,
);
impl_getter! {
    Cols,
    dyn _embedded_hal_digital_InputPin,
    U12,
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
}

pub struct Rows(
    pub PB11<Output<PushPull>>,
    pub PB10<Output<PushPull>>,
    pub PB1<Output<PushPull>>,
    pub PB0<Output<PushPull>>,
    pub PA7<Output<PushPull>>,
);
impl_getter! {
    Rows,
    dyn _embedded_hal_digital_OutputPin,
    U5,
    [0, 1, 2, 3, 4]
}

let mut matrix = matrix::Matrix::new(
    Cols(
        gpiob.pb12.into_pull_up_input(&mut gpiob.crh),
        gpiob.pb13.into_pull_up_input(&mut gpiob.crh),
        gpiob.pb14.into_pull_up_input(&mut gpiob.crh),
        gpiob.pb15.into_pull_up_input(&mut gpiob.crh),
        gpioa.pa8.into_pull_up_input(&mut gpioa.crh),
        gpioa.pa9.into_pull_up_input(&mut gpioa.crh),
        gpioa.pa10.into_pull_up_input(&mut gpioa.crh),
        gpiob.pb5.into_pull_up_input(&mut gpiob.crl),
        gpiob.pb6.into_pull_up_input(&mut gpiob.crl),
        gpiob.pb7.into_pull_up_input(&mut gpiob.crl),
        gpiob.pb8.into_pull_up_input(&mut gpiob.crh),
        gpiob.pb9.into_pull_up_input(&mut gpiob.crh),
    ),
    Rows(
        gpiob.pb11.into_push_pull_output(&mut gpiob.crh),
        gpiob.pb10.into_push_pull_output(&mut gpiob.crh),
        gpiob.pb1.into_push_pull_output(&mut gpiob.crl),
        gpiob.pb0.into_push_pull_output(&mut gpiob.crl),
        gpioa.pa7.into_push_pull_output(&mut gpioa.crl),
   ),
);
matrix.clear();

The need to give the [0, 1, 2, 3, 4] to the macro is quite ugly, and I'm not yet found of the result (I think overly complicated).

@TeXitoi
Copy link
Owner Author

TeXitoi commented Oct 8, 2019

@ah- For the usb stack, I use https://crates.io/crates/stm32-usbd The hid implementation is https://github.com/TeXitoi/keyberon/blob/master/src/hid.rs and only depend on https://crates.io/crates/usb-device

I use it daily without any problem, but I don't have your usecase of pluging and unpluging without a reset of the microcontroller.

@TeXitoi
Copy link
Owner Author

TeXitoi commented Nov 15, 2019

Update: I know have a crate that expose building blocks for constructing a keyboard. I should now be trivial to port keyberon on any MCU supporting UsbDevice, InputPin<Error = Void> and OutputPin<Error = Void>

It doesn't add any feature, so your use case might not be supported yet (Keyberon is not really event driven for the moment, for example).

If you have any feedbacks, feel free to tell!

@BenBergman
Copy link

Your hid.rs file seems really useful outside of this project (most of the other Rust keyboard firmwares seem to use a copy of it). Maybe it is mature enough to be broken out into its own crate similar to usbd-serial?

@btrepp
Copy link

btrepp commented Dec 30, 2019

Your hid.rs file seems really useful outside of this project (most of the other Rust keyboard firmwares seem to use a copy of it). Maybe it is mature enough to be broken out into its own crate similar to usbd-serial?

I think it would be super if you did this. I threw together a simple midi one, before and I was thinking of doing a USB hid one, but then stumbled upon this project.

It would be awesome to split that into it's own crate.

@TheZoq2
Copy link

TheZoq2 commented Jan 3, 2020

I too would like to see hid.rs as its own crate. I recently used it to implement a joystick and it was a very neat process

@TeXitoi
Copy link
Owner Author

TeXitoi commented Sep 14, 2020

With 0.1.0 just published, we can close this.

@TeXitoi TeXitoi closed this as completed Sep 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants