Browse Source

more refactoring; adds dynamic key coloring

develop
Harald Albrecht 5 years ago
parent
commit
9756bacaea
  1. 23
      sdcard/layouts/shift.lua
  2. 65
      sdcard/snippets/mb/leds.lua
  3. 44
      sdcard/snippets/multibow.lua
  4. 2
      spec/layouts/kdenlive_spec.lua
  5. 19
      spec/layouts/shift_spec.lua
  6. 35
      spec/snippets/leds_spec.lua

23
sdcard/layouts/shift.lua

@ -55,12 +55,17 @@ shift.KEY_SHIFT = shift.KEY_SHIFT or 11
shift.KEY_LAYOUT = shift.KEY_LAYOUT or 8
shift.KEY_BRIGHTNESS = shift.KEY_BRIGHTNESS or 5
shift.BRIGHTNESS_LEVELS = shift.BRIGHTNESS_LEVELS or { 70, 100, 40 }
-- Internal flag for detecting SHIFT press-release sequences without any SHIFTed
-- function.
local shift_only = false
local grabbed_key_count = 0
-- Activates the first brightness level...
shift.brightnesses = table.pack(table.unpack(shift.BRIGHTNESS_LEVELS))
mb.cycle_brightness(shift.brightnesses)
-- Switches to the next SHIFT layer within the currently active keyboard layout.
-- SHIFT layer(s) are wired up as a circular list of keymaps, linked using their
@ -72,7 +77,6 @@ function shift.shift_secondary_keymap()
end
end
-- Remember how many grabbed keys are pressed, so we won't ungrab later until
-- all keys have been released.
function shift.any_press(keyno)
@ -94,7 +98,6 @@ function shift.any_release(keyno)
end
end
-- SHIFT press: switches into grabbed SHIFT mode, activating the in-SHIFT keys
-- for brightness change, keymap cycling, et cetera.
function shift.shift(key)
@ -106,23 +109,27 @@ function shift.shift(key)
mb.grab(shift.keymap_shifted.name)
end
-- Cycles to the next primary keyboard layout (keymap)
function shift.cycle(key)
shift_only = false
mb.cycle_primary_keymaps()
end
-- Changes the Keybow LED brightness, by cycling through different brightness
-- levels
function shift.brightness(key)
shift_only = false
local b = mb.brightness + 0.3
if b > 1 then; b = 0.4; end
mb.set_brightness(b)
mb.cycle_brightness(shift.brightnesses)
mb.led(key, shift.next_brightness_color())
end
-- Returns the color for the BRIGHTNESS key LED: this is the next brightness
-- level in the sequence of brightness levels as a color of gray/white.
function shift.next_brightness_color()
local br = shift.brightnesses[1]
br = br > 1.0 and br / 100 or br
return { r=br, g=br, b=br }
end
-- define and register our keymaps: the permanent SHIFT key-only keymap, as well
-- as a temporary grabbing keymap while the SHIFT key is being pressed and held.
@ -138,7 +145,7 @@ shift.keymap_shifted = {
[shift.KEY_SHIFT] = {c={r=1, g=1, b=1}},
[shift.KEY_LAYOUT] = {c={r=0, g=1, b=1}, press=shift.cycle, release=shift.release_other},
[shift.KEY_BRIGHTNESS] = {c={r=0.5, g=0.5, b=0.5}, press=shift.brightness, release=shift.release_other}
[shift.KEY_BRIGHTNESS] = {c=shift.next_brightness_color, press=shift.brightness, release=shift.release_other}
}
mb.register_keymap(shift.keymap)
mb.register_keymap(shift.keymap_shifted)

65
sdcard/snippets/mb/leds.lua

@ -23,13 +23,74 @@ SOFTWARE.
]]--
mb.MIN_BRIGHTNESS = mb.MIN_BRIGHTNESS or 0.1
-- Default LED brightness in the [0.1..1] range.
mb.brightness = 1
-- Sets the Keybow key LEDs maximum brightness, in the range [0.1..1].
-- Sets the Keybow key LEDs maximum brightness, in the range [0.1..1] or
-- [10..100] (percent). The minim brightness is clamped on purpose to avoid
-- unlit LEDs. The lower clamp defaults to mb.MIN_BRIGHTNESS.
function mb.set_brightness(brightness)
if brightness < 0.1 then brightness = 0.1 end
brightness = brightness > 1.0 and brightness / 100 or brightness
if brightness < mb.MIN_BRIGHTNESS then brightness = mb.MIN_BRIGHTNESS end
if brightness > 1 then brightness = 1 end
mb.brightness = brightness
mb.activate_leds()
end
-- Cycles through a list of brightness values, always taking the first
-- value and modifying the list by cycling it. Brightness values can be
-- either [0..1] or [0..100] (that is, percent)
function mb.cycle_brightness(brightnesses)
local brightness = table.remove(brightnesses, 1)
table.insert(brightnesses, brightness)
mb.set_brightness(brightness)
return brightnesses
end
-- Sets key LED to specific color, taking brightness into consideration.
-- The color is a triple (table) with the elements r, g, and b. Each color
-- component is in the range [0..1].
function mb.led(keyno, color)
if color then
local b = mb.brightness * 255
keybow.set_pixel(keyno, color.r * b, color.g * b, color.b * b)
else
keybow.set_pixel(keyno, 0, 0, 0)
end
end
-- Restores Keybow LEDs according to current keymap and the permanent keymaps.
function mb.activate_leds()
keybow.clear_lights()
-- if a grab is in place then it takes absolute priority
if mb.grab_keymap then
mb.activate_keymap_leds(mb.grab_keymap)
else
-- first update LEDs for the current keymap...
if mb.current_keymap ~= nil then
mb.activate_keymap_leds(mb.current_keymap)
end
-- ...then update LEDs from permanent keymap(s), as this ensures that
-- the permanent keymaps take precedence.
for name, keymap in pairs(mb.keymaps) do
if keymap.permanent then
mb.activate_keymap_leds(keymap)
end
end
end
end
-- Helper function that iterates over all keymap elements but skipping non-key
-- bindings.
function mb.activate_keymap_leds(keymap)
for keyno, keydef in pairs(keymap) do
-- Only iterates over keys, skipping any other keymap definitions.
if type(keyno) == "number" and keydef.c then
local color = type(keydef.c) == "function" and keydef.c() or keydef.c
mb.led(keyno, color)
end
end
end

44
sdcard/snippets/multibow.lua

@ -160,50 +160,6 @@ function mb.ungrab()
end
-- Sets key LED to specific color, taking brightness into consideration.
-- The color is a triple (table) with the elements r, g, and b. Each color
-- component is in the range [0..1].
function mb.led(keyno, color)
if color then
local b = mb.brightness * 255
keybow.set_pixel(keyno, color.r * b, color.g * b, color.b * b)
else
keybow.set_pixel(keyno, 0, 0, 0)
end
end
-- Restores Keybow LEDs according to current keymap and the permanent keymaps.
function mb.activate_leds()
keybow.clear_lights()
-- if a grab is in place then it takes absolute priority
if mb.grab_keymap then
mb.activate_keymap_leds(mb.grab_keymap)
else
-- first update LEDs for the current keymap...
if mb.current_keymap ~= nil then
mb.activate_keymap_leds(mb.current_keymap)
end
-- ...then update LEDs from permanent keymap(s), as this ensures that
-- the permanent keymaps take precedence.
for name, keymap in pairs(mb.keymaps) do
if keymap.permanent then
mb.activate_keymap_leds(keymap)
end
end
end
end
-- Helper function that iterates over all keymap elements but skipping non-key
-- bindings.
function mb.activate_keymap_leds(keymap)
for keyno, keydef in pairs(keymap) do
if type(keyno) == "number" and keydef.c then
-- print((keymap.permanent and "permanent LED" or "LED") .. " " .. keyno)
mb.led(keyno, keydef.c)
end
end
end
-- Disables the automatic Keybow lightshow and sets the key LED colors. This
-- is a well-known (hook) function that gets called by the Keybow firmware
-- after initialization immediately before waiting for key events.

2
spec/layouts/kdenlive_spec.lua

@ -46,7 +46,7 @@ describe("Kdenlive keymap", function()
_G.setup()
end)
it("colors its keys", function()
inslit("colors its keys", function()
for _, keymap in pairs(mb.registered_keymaps()) do
if string.sub(keymap.name, 1, #"kdenlive") == "kdenlive" then
for keyno = 0, 11 do

19
spec/layouts/shift_spec.lua

@ -179,6 +179,25 @@ describe("SHIFT multibow keymap", function()
end)
end)
inslit("cycles brightness", function()
local s = spy.on(mb, "led")
local len = #shift.BRIGHTNESS_LEVELS
for i = 1, len do
assert.equals(mb.brightness * 100, shift.BRIGHTNESS_LEVELS[i])
-- enters SHIFT and check the brightness of brightness key...
s:clear()
hwk.press(shift.KEY_SHIFT)
assert.spy(s).was.called_with(
shift.KEY_BRIGHTNESS,
shift.next_brightness_color())
-- cycles to next brightness
hwk.tap(shift.KEY_BRIGHTNESS)
hwk.release(shift.KEY_SHIFT)
end
assert.equals(mb.brightness * 100, shift.BRIGHTNESS_LEVELS[1])
end)
end)
end)

35
spec/snippets/leds_spec.lua

@ -29,11 +29,42 @@ describe("multibow LEDs", function()
mb.set_brightness(0.5)
assert.equals(0.5, mb.brightness)
mb.set_brightness(1.1)
mb.set_brightness(1.0)
assert.equals(1.0, mb.brightness)
mb.set_brightness(0)
assert.equals(0.1, mb.brightness)
assert.equals(mb.MIN_BRIGHTNESS, mb.brightness)
mb.set_brightness(20)
assert.equals(0.2, mb.brightness)
end)
it("cycles brightness", function()
function f(b, scale)
local copy = table.pack(table.unpack(b))
local len = #b
for i = 1, len do
mb.cycle_brightness(copy)
assert.equals(b[i], mb.brightness * scale)
end
end
f({ 0.7, 1.0, 0.4 }, 1)
f({ 70, 100, 40 }, 100)
end)
inslit("accepts LED color functions in keymaps", function()
local s = spy.on(mb, "led")
local km = {
name="test",
[0]={c={r=0, g=1, b=0}},
[1]={c=function() return {r=1, g=1, b=1} end}
}
mb.activate_keymap_leds(km)
assert.spy(s).was.called(2)
assert.spy(s).was.called_with(0, {r=0, g=1, b=0})
assert.spy(s).was.called_with(1, {r=1, g=1, b=1})
end)
end)

Loading…
Cancel
Save