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

[WIP] Attempt hold-tap implementation of Magic key #2

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 77 additions & 35 deletions app/boards/arm/glove80/glove80.keymap
Original file line number Diff line number Diff line change
Expand Up @@ -8,50 +8,92 @@
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
#include <dt-bindings/zmk/ext_power.h>
#include <dt-bindings/zmk/outputs.h>
#include <dt-bindings/zmk/outputs.h>
#include <dt-bindings/zmk/rgb.h>

#define HYPER LC(LS(LG(LALT)))

// layers
#define DEFAULT 0
#define LOWER 1
#define MAGIC 2
#define FACTORY_TEST 3

/ {
behaviors {
// For the "layer" key, it'd nice to be able to use it as either a shift or a toggle.
// Configure it as a tap dance, so the first tap (or hold) is a &mo and the second is a &to
layer_td: tap_dance_0 {
compatible = "zmk,behavior-tap-dance";
label = "LAYER_TAP_DANCE";
#binding-cells = <0>;
tapping-term-ms = <200>;
bindings = <&mo LOWER>, <&to LOWER>;
};

mht: magic_layer_indicator {
compatible = "zmk,behavior-hold-tap";
label = "MAGIC_HOLD_TAP";
#binding-cells = <3>;
flavor = "tap-preferred";
tapping-term-ms = <200>;
bindings = <&mo>, <&rgb_ug>;
};
};

keymap {
compatible = "zmk,keymap";

default_layer {
// ---------------------------------------------------------------------------------------------------------------------------------
// | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
// | ESC | A | S | D | F | G | | H | J | K | L | ; | ' |
// | ` | Z | X | C | V | B | LSHFT | LCTRL | LOWER | | LGUI | RCTRL | RSHFT | N | M | , | . | / | PGUP |
// | MAGIC | HOME| END | LEFT | RIGHT| | BSPC | DEL | LALT | | RALT | RET | SPACE | | UP | DOWN | [ | ] | PGDN |


// MAGIC is currently bound to the same as LAYER - these will be fixed later
bindings = <
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10
&kp EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
&kp ESC &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
&kp GRAVE &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LCTRL &mo LOWER &kp LGUI &kp RCTRL &kp RSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp PG_UP
&mo LOWER &kp HOME &kp END &kp LEFT &kp RIGHT &kp BSPC &kp DEL &kp LALT &kp RALT &kp RET &kp SPACE &kp UP &kp DOWN &kp LBKT &kp RBKT &kp PG_DN
>;
};

lower_layer {
bindings = <
&bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &none &none &none &kp F11 &kp F12
&bt BT_CLR &bt BT_CLR &out OUT_USB &out OUT_BLE &out OUT_TOG &none &none &none &none &none &none &none
&bootloader &rgb_ug RGB_TOG &rgb_ug RGB_EFF &rgb_ug RGB_BRI &rgb_ug RGB_BRD &kp K_VOL_UP &none &none &none &none &none &bootloader
&reset &none &none &none &none &kp K_VOL_DN &none &none &none &none &none &reset
&ext_power EP_ON &ext_power EP_OFF &none &none &none &kp K_MUTE &none &kp HYPER &none &none &none &none &none &none &none &none &none &none
&none &kp CAPS &kp INS &none &none &none &none &none &none &none &none &none &none &none &none &none
>;
};
compatible = "zmk,keymap";

default_layer {
// ---------------------------------------------------------------------------------------------------------------------------------
// | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 |
// | = | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | - |
// | TAB | Q | W | E | R | T | | Y | U | I | O | P | \ |
// | ESC | A | S | D | F | G | | H | J | K | L | ; | ' |
// | ` | Z | X | C | V | B | LSHFT | LCTRL | LOWER | | LGUI | RCTRL | RSHFT | N | M | , | . | / | PGUP |
// | MAGIC | HOME| END | LEFT | RIGHT| | BSPC | DEL | LALT | | RALT | RET | SPACE | | UP | DOWN | [ | ] | PGDN |

bindings = <
&kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10
&kp EQUAL &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp MINUS
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
&kp ESC &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
&kp GRAVE &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LCTRL &layer_td &kp LGUI &kp RCTRL &kp RSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp PG_UP
&mht MAGIC RGB_STATUS &kp HOME &kp END &kp LEFT &kp RIGHT &kp BSPC &kp DEL &kp LALT &kp RALT &kp RET &kp SPACE &kp UP &kp DOWN &kp LBKT &kp RBKT &kp PG_DN
>;
};

lower_layer {
bindings = <
&kp C_BRI_DN &kp C_BRI_UP &kp C_PREV &kp C_NEXT &kp C_PP &kp C_MUTE &kp C_VOL_DN &kp C_VOL_UP &none &kp PAUSE_BREAK
&trans &none &none &kp F11 &kp F12 &kp HOME &kp LPAR &kp KP_NUM &kp KP_EQUAL &kp KP_DIVIDE &kp KP_MULTIPLY &kp PSCRN
&trans &none &none &kp UP &none &kp END &kp RPAR &kp KP_N7 &kp KP_N8 &kp KP_N9 &kp KP_MINUS &kp SLCK
&trans &none &kp LEFT &kp DOWN &kp RIGHT &kp PGUP &kp PRCNT &kp KP_N4 &kp KP_N5 &kp KP_N6 &kp KP_PLUS &none
&trans &kp K_CMENU &none &none &none &kp PGDN &trans &trans &to DEFAULT &trans &trans &trans &kp COMMA &kp KP_N1 &kp KP_N2 &kp KP_N3 &kp KP_ENTER &trans
&trans &kp CAPS &kp INS &kp F11 &kp F12 &trans &trans &trans &trans &trans &trans &kp KP_N0 &kp KP_N0 &kp KP_DOT &kp KP_ENTER &trans
>;
};

magic_layer {
bindings = <
&bt BT_CLR &none &none &none &none &none &none &none &none &none &bt BT_CLR_ALL
&none &none &none &none &none &none &none &none &none &none &none &none
&none &rgb_ug RGB_SPI &rgb_ug RGB_SAI &rgb_ug RGB_HUI &rgb_ug RGB_BRI &rgb_ug RGB_TOG &none &none &none &none &none &none
&bootloader &rgb_ug RGB_SPD &rgb_ug RGB_SAD &rgb_ug RGB_HUD &rgb_ug RGB_BRD &rgb_ug RGB_EFF &none &none &none &none &none &bootloader
&reset &none &none &none &none &none &bt BT_SEL 3 &bt BT_SEL 4 &none &none &none &none &none &none &none &none &none &reset
&none &out OUT_TOG &out OUT_BLE &out OUT_USB &none &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &none &none &none &none &none &none &none &to FACTORY_TEST
>;
};

factory_test_layer {
bindings = <
&kp N0 &kp N6 &kp N2 &kp N8 &kp N4 &kp N4 &kp N8 &kp N2 &kp N6 &kp N0
&kp N1 &kp N7 &kp N3 &kp N9 &kp N5 &kp N0 &kp N0 &kp N5 &kp N9 &kp N3 &kp N7 &kp N1
&kp N2 &kp N8 &kp N4 &kp N0 &kp N6 &kp N1 &kp N1 &kp N6 &kp N0 &kp N4 &kp N8 &kp N2
&kp N3 &kp N9 &kp N5 &kp N1 &kp N7 &kp N2 &kp N2 &kp N7 &kp N1 &kp N5 &kp N9 &kp N3
&kp N4 &kp N0 &kp N6 &kp N2 &kp N8 &kp N3 &kp N4 &kp N5 &kp N6 &kp N6 &kp N5 &kp N4 &kp N3 &kp N8 &kp N2 &kp N6 &kp N0 &kp N4
&kp N5 &kp N1 &kp N7 &kp N3 &kp N9 &kp N7 &kp N8 &kp N9 &kp N9 &kp N8 &kp N7 &kp N9 &kp N3 &kp N7 &kp N1 &kp N5
>;
};
};
};

3 changes: 2 additions & 1 deletion app/include/dt-bindings/zmk/bt.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define BT_NXT_CMD 1
#define BT_PRV_CMD 2
#define BT_SEL_CMD 3
// #define BT_FULL_RESET_CMD 4
#define BT_CLR_ALL_CMD 4

/*
Note: Some future commands will include additional parameters, so we
Expand All @@ -19,3 +19,4 @@ defines these aliases up front.
#define BT_NXT BT_NXT_CMD 0
#define BT_PRV BT_PRV_CMD 0
#define BT_SEL BT_SEL_CMD
#define BT_CLR_ALL BT_CLR_ALL_CMD
1 change: 1 addition & 0 deletions app/include/zmk/ble.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ int zmk_ble_clear_bonds();
int zmk_ble_prof_next();
int zmk_ble_prof_prev();
int zmk_ble_prof_select(uint8_t index);
int zmk_ble_clear_all_bonds();

int zmk_ble_active_profile_index();
bt_addr_le_t *zmk_ble_active_profile_addr();
Expand Down
2 changes: 2 additions & 0 deletions app/src/behaviors/behavior_bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
return zmk_ble_prof_prev();
case BT_SEL_CMD:
return zmk_ble_prof_select(binding->param2);
case BT_CLR_ALL_CMD:
return zmk_ble_clear_all_bonds();
default:
LOG_ERR("Unknown BT command: %d", binding->param1);
}
Expand Down
17 changes: 17 additions & 0 deletions app/src/ble.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,23 @@ int zmk_ble_clear_bonds() {
return 0;
};

int zmk_ble_clear_all_bonds() {
LOG_DBG("zmk_ble_clear_all_bonds()");

// Unpair all profiles
for (uint8_t i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) {
if (bt_addr_le_cmp(&profiles[i].peer, BT_ADDR_LE_ANY)) {
bt_unpair(BT_ID_DEFAULT, &profiles[i].peer);
set_profile_address(i, BT_ADDR_LE_ANY);
}
}

// Automatically switch to profile 0
zmk_ble_prof_select(0);

return 0;
};

int zmk_ble_active_profile_index() { return active_profile; }

#if IS_ENABLED(CONFIG_SETTINGS)
Expand Down
2 changes: 2 additions & 0 deletions lambda/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
source 'https://rubygems.org'
gem 'aws_lambda_ric'
13 changes: 13 additions & 0 deletions lambda/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
GEM
remote: https://rubygems.org/
specs:
aws_lambda_ric (2.0.0)

PLATFORMS
ruby

DEPENDENCIES
aws_lambda_ric

BUNDLED WITH
2.1.4
117 changes: 117 additions & 0 deletions lambda/app.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# frozen_string_literal: true

require 'tmpdir'
require 'json'
require 'base64'

module LambdaFunction
class Handler
class << self
# ALB event structure:
# {
# "requestContext": { <snip> },
# "httpMethod": "GET",
# "path": "/",
# "queryStringParameters": {parameters},
# "headers": { <snip> },
# "isBase64Encoded": false,
# "body": "request_body"
# }
#
# Handle the single route: POST /compile
def process(event:, context:)
unless event['path'] == '/compile'
return error_response(404, error: "Unknown route: #{event['path']}")
end

unless event['httpMethod'] == 'POST'
return error_response(404, error: "No route for HTTP method : #{event['httpMethod']}")
end

keymap_data = event['body']

unless keymap_data
return error_response(400, error: 'Missing POST body')
end

if event['isBase64Encoded']
keymap_data = Base64.decode64(keymap_data)
end

compile(keymap_data)
end

private

def compile(keymap_data)
in_build_dir do
File.open('build.keymap', 'w') do |io|
io.write(keymap_data)
end

compile_output = nil

IO.popen(['compileZmk', './build.keymap'], err: [:child, :out]) do |io|
compile_output = io.read
end

compile_output = compile_output.split("\n")

unless $?.success?
status = $?.exitstatus
return error_response(400, error: "Compile failed with exit status #{status}", detail: compile_output)
end

unless File.exist?('zephyr/zmk.uf2')
return error_response(500, error: 'Compile failed to produce result binary', detail: compile_output)
end

file_response(File.read('zephyr/zmk.uf2'), compile_output)
rescue StandardError => e
error_response(500, error: 'Unexpected error', detail: e.message)
end
end

# Lambda is single-process per container, and we get substantial speedups
# from ccache by always building in the same path
BUILD_DIR = '/tmp/build'

def in_build_dir
FileUtils.remove_entry(BUILD_DIR, true)
Dir.mkdir(BUILD_DIR)
Dir.chdir(BUILD_DIR)
yield
ensure
FileUtils.remove_entry(BUILD_DIR, true) rescue nil
end

def file_response(file, compile_output)
file64 = Base64.strict_encode64(file)

headers = {
'Content-Type' => 'application/octet-stream',
}

headers.merge!('X-Debug-Output' => compile_output.to_json) if ENV.include?('DEBUG')

{
'isBase64Encoded' => true,
'statusCode' => 200,
'body' => file64,
'headers' => headers,
}
end

def error_response(code, error:, detail: nil)
{
'isBase64Encoded' => false,
'statusCode' => code,
'body' => { error: error, detail: detail }.to_json,
'headers' => {
'Content-Type' => 'application/json'
}
}
end
end
end
end
26 changes: 26 additions & 0 deletions lambda/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{ pkgs ? import ./nix/pinned-nixpkgs.nix }:

with pkgs;

let
bundleEnv = bundlerEnv {
name = "lambda-bundler-env";
inherit ruby;
gemfile = ./Gemfile;
lockfile = ./Gemfile.lock;
gemset = ./gemset.nix;
};

source = stdenv.mkDerivation {
name = "lambda-builder";
version = "0.0.1";
src = ./.;
installPhase = ''
cp -r ./ $out
'';
};

in
{
inherit bundleEnv source;
}
12 changes: 12 additions & 0 deletions lambda/gemset.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
aws_lambda_ric = {
groups = ["default"];
platforms = [];
source = {
remotes = ["https://rubygems.org"];
sha256 = "19c4xlgnhgwf3n3z57z16nmr76jd2vihhshknm5zqip2g00awhi1";
type = "gem";
};
version = "2.0.0";
};
}
Loading