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

Implement Keyboard Host via PIO #287

Merged
merged 12 commits into from
Jun 21, 2023

Conversation

deeebug
Copy link
Contributor

@deeebug deeebug commented May 27, 2023

The following changes integrates Pico-PIO-USB to implement a keyboard host interface. With this, a keyboard can be connected via GPIO pins to have its inputs translated via GP2040-CE.

image

Care must be taken when wiring as incorrectly mapping the GND could cause the keyboard to be borked (happened to one).
Currently, D+ and D- pins are set to GPIO0 and GPIO1 pins. RGB LED also seems to be incompatible with this addon.

This is only one implementation and needs to be expanded to support NKRO, which will be done soon. In the future, several other USB devices could be supported. I think the Pico-PIO-USB integration can be very useful for many use-cases, for instance, it could also be used as an adapter that reserves player slot, given that host support for other controllers are implemented.

Please review the changes and merge if all is good,
Thanks!

@deeebug deeebug requested review from Fortinbra, mthiesen, arntsonl, FeralAI and TheTrainGoes and removed request for Fortinbra May 27, 2023 10:47

#include "pio_usb.h"

GamepadState _keyboard_host_state;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the global variables should be static (all the _keyboard_host_xxx variables). in C++ static globals have "internal linkage", meaning they are only visible in the .cpp they are declared in.

Otherwise the program will fail to link if there are name clashes in the global scope. Admittedly highly unlikely in this case but this is the idiomatic thing to do in C++.

tuh_configure(1, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &pio_cfg);
tuh_init(BOARD_TUH_RHPORT);

_keyboard_host_mapDpadUp = new KeyboardButtonMapping(keyboardMapping.keyDpadUp , GAMEPAD_MASK_UP);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any reason to work with dynamic allocations here. Just put the structs in the global scope, not pointers. There is no need for this additional indirection.

}

void KeyboardHostAddon::setup() {
KeyboardMapping& keyboardMapping = Storage::getInstance().getAddonOptions().keyboardHostOptions.mapping;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a const reference. You are not modifying the struct behind the reference.

uint8_t keycode = (i < 6) ? report->keycode[i] : getKeycodeFromModifier(report->modifier);
if ( keycode )
{
GamepadOptions& gamepadOptions = Storage::getInstance().getGamepadOptions();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a const reference. You are not modifying the struct behind the reference.

@deeebug
Copy link
Contributor Author

deeebug commented May 27, 2023

@mthiesen thank you very much for the review!
I'll get these changes added now.

mthiesen
mthiesen previously approved these changes May 27, 2023
@ez2torta
Copy link

ez2torta commented Jun 4, 2023

This PR looks so awesome! I don't have access to a rpi pico until one more month but I'm sure I will test this ASAP 💕💕

Copy link
Contributor

@arntsonl arntsonl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only other change is adding D+/D- to our Web Config (if we can, if not lets me just add this) and we're ready to merge!

@@ -175,7 +174,7 @@ app.get("/api/getPinMappings", (req, res) => {
});

app.get("/api/getKeyMappings", (req, res) =>
res.send(mapValues(keyboardMapping))
res.send(mapValues(DEFAULT_KEYBOARD_MAPPING))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this right? we only send default keyboard mapping?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just the default data sent to the dev server, so it's good.

setValidated(true);
};

// const handleSubmit = async (e) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can delete any big comment blocks :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make another PR tomorrow.

Copy link
Contributor

@arntsonl arntsonl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great

@arntsonl arntsonl merged commit a0c2d5d into OpenStickCommunity:main Jun 21, 2023
38 checks passed
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

Successfully merging this pull request may close these issues.

None yet

4 participants