pimoroni / keybow-firmware

Keybow Firmware for the Raspberry Pi Zero
Other
180 stars 66 forks source link

Adaptive layouts #82

Open hardillb opened 2 years ago

hardillb commented 2 years ago

I've been trying to use the serial support added at v0.0.4 to change the key mapping with something like the following:

require "keybow"

-- Keybow MINI volume/zoom controls --

function setup()
    keybow.use_mini()
    keybow.auto_lights(false)
    keybow.clear_lights()
    keybow.set_pixel(0, 0, 255, 255)
    keybow.set_pixel(1, 255, 0, 255)
    keybow.set_pixel(2, 0, 255, 255)
end

-- Key mappings --

state = 'zoom'

function handle_minikey_02(pressed)
    if state == 'zoom' then
    if pressed then
            keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
            keybow.tap_key("v")
            keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
        end
    elseif state == 'media' then
        keybow.set_media_key(keybow.MEDIA_VOL_UP, pressed)
    end
end

function handle_minikey_01(pressed)
    if state == 'zoom' then
    if pressed then
            keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
            keybow.tap_key("a")
            keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
        end
    elseif state == 'media' then
        keybow.set_media_key(keybow.MEDIA_MUTE, pressed)
    end
end

function handle_minikey_00(pressed)
    if state == 'zoom' then
    if pressed then
             keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_DOWN)
             keybow.tap_key("n")
             keybow.set_modifier(keybow.LEFT_ALT, keybow.KEY_UP)
        end
    elseif state == 'media' then
        keybow.set_media_key(keybow.MEDIA_VOL_DOWN, pressed)
    end
end

local function isempty(s)
  return s == nil or s == ''
end

function tick()
    local line
    line = keybow_serial_read()
    if not isempty(line) then 
        -- keybow_serial_write( line .. "\n" )
        if line == 'zoom' then
            keybow.clear_lights()
            keybow.set_pixel(0, 0, 255, 255)
            keybow.set_pixel(1, 255, 0, 255)
            keybow.set_pixel(2, 0, 255, 255)
            state = 'zoom'
        elseif line == 'media' then
            keybow.clear_lights()
            keybow.set_pixel(0, 255, 0, 255)
            keybow.set_pixel(1, 0, 255, 255)
            keybow.set_pixel(2, 255, 0, 255)
            state = 'media'
        end
    end

end

It's really laggy which I think is down to:

https://github.com/pimoroni/keybow-firmware/blob/ec9bc9989935b196806e54065ca3ea8c67c738a6/keybow/serial.c#L37

Which sets a 1 second read timeout on the serial connection.

I tried reducing that to 1 decasecond but when I built the keybow binary (on a different pi zero) from the head of the repo it doesn't look to setup the USB gadget properly (at least it never shows up on the host machine).

Any suggestions?

Or suggestions on how to debug, I attached a screen, but it just drops me at a login prompt and there is no way to add a keyboard as the USB port is in device mode to talk to the host. (When Pi Zero W's become available again I will try and grab one so I can ssh in and have a look).

P.s. I understand the world has probably mainly moved on to the 2040 based kit, but this is still useful and being able to switch profiles would be huge upgrade.

hardillb commented 2 years ago

OK, the rebuilt keybow with the VTIME set to 1 does work (it was a dodgy USB-C hub that needed resetting). There was still a 10th of a second latency which is not great but just about workable.

I tried it with the VTIME set to 0 and it's lighting fast, I'm shift between layouts with echo zoom > /dev/ttyACM0 and echo media > /dev/ttyACM0 It doesn't appear to work with picocom, but that's fine. I should be able to script this with xprop or xdotool.

hardillb commented 2 years ago

If there is ever a new release, making the serial_read act more like a callback than an explicit read (or at least having it configurable) would be great and mean the lua would only see the input when there had been a new line char.

I guess this might need a background thread to handle the serial read.

Gadgetoid commented 2 years ago

@hardillb agreed- it would be nice to have it structured as a callback, and that's relatively straight-forward to do. A non-blocking, buffer-filling, short read on the main loop that triggers the callback on \n or something might work well.

Gadgetoid commented 2 years ago

@hardillb while you're here, and since you can build/run keybow from source... would you mind trying out the refactored code here?: https://github.com/pimoroni/keybow-firmware/pull/79

This is what any changes to the serial handling would be based upon, so getting it merged would be a great start.

Cheers!

hardillb commented 2 years ago

Might have to wait for the weekend, but will do.

Gadgetoid commented 2 years ago

Thanks- it's been sitting in PR purgatory for months, so there's no hurry.