Merge branch 'zmkfirmware:main' into rgb-auto-off
This commit is contained in:
commit
a0b83d546f
144 changed files with 4111 additions and 2749 deletions
447
.github/workflows/build.yml
vendored
447
.github/workflows/build.yml
vendored
|
@ -9,75 +9,19 @@ on:
|
|||
paths:
|
||||
- ".github/workflows/build.yml"
|
||||
- "app/**"
|
||||
schedule:
|
||||
- cron: '22 4 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: docker.io/zmkfirmware/zmk-build-arm:2.5
|
||||
needs: compile-matrix
|
||||
strategy:
|
||||
matrix:
|
||||
board:
|
||||
- bluemicro840_v1
|
||||
- nice_nano
|
||||
- nice_nano_v2
|
||||
- nrfmicro_13
|
||||
- proton_c
|
||||
shield:
|
||||
- bfo9000_left
|
||||
- bfo9000_right
|
||||
- boardsource3x4
|
||||
- corne_left
|
||||
- corne_right
|
||||
- cradio_left
|
||||
- cradio_right
|
||||
- crbn
|
||||
- eek
|
||||
- helix_left
|
||||
- helix_right
|
||||
- iris_left
|
||||
- iris_right
|
||||
- jian_left
|
||||
- jian_right
|
||||
- jorne_left
|
||||
- jorne_right
|
||||
- kyria_left
|
||||
- kyria_right
|
||||
- lily58_left
|
||||
- lily58_right
|
||||
- microdox_left
|
||||
- microdox_right
|
||||
- nibble
|
||||
- qaz
|
||||
- quefrency_left
|
||||
- quefrency_right
|
||||
- reviung41
|
||||
- romac
|
||||
- romac_plus
|
||||
- settings_reset
|
||||
- sofle_left
|
||||
- sofle_right
|
||||
- splitreus62_left
|
||||
- splitreus62_right
|
||||
- tg4x
|
||||
- tidbit
|
||||
cmake-args: [""]
|
||||
include:
|
||||
- board: bdn9_rev2
|
||||
- board: dz60rgb_rev1
|
||||
- board: nrf52840_m2
|
||||
shield: m60
|
||||
- board: planck_rev6
|
||||
- board: proton_c
|
||||
shield: clueboard_california
|
||||
- board: nice_nano_v2
|
||||
shield: kyria_left
|
||||
cmake-args: -DCONFIG_ZMK_DISPLAY=y
|
||||
skip-archive: true
|
||||
- board: nice_nano_v2
|
||||
shield: kyria_right
|
||||
cmake-args: -DCONFIG_ZMK_DISPLAY=y
|
||||
skip-archive: true
|
||||
include: ${{ fromJSON(needs.compile-matrix.outputs.include-list) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -104,29 +48,360 @@ jobs:
|
|||
run: west update
|
||||
- name: Export Zephyr CMake package (west zephyr-export)
|
||||
run: west zephyr-export
|
||||
- name: Prepare variables
|
||||
id: variables
|
||||
run: |
|
||||
SHIELD_ARG=
|
||||
ARTIFACT_NAME="${{ matrix.board }}"
|
||||
|
||||
if [ -n "${{ matrix.shield }}" ]; then
|
||||
SHIELD_ARG="-DSHIELD=${{ matrix.shield }}"
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-${{ matrix.shield }}"
|
||||
fi
|
||||
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-zmk"
|
||||
|
||||
echo ::set-output name=shield-arg::${SHIELD_ARG}
|
||||
echo ::set-output name=artifact-name::${ARTIFACT_NAME}
|
||||
- name: Build (west build)
|
||||
run: west build -s app -b ${{ matrix.board }} -- ${{ steps.variables.outputs.shield-arg }} ${{ matrix.cmake-args }}
|
||||
- name: Archive artifacts
|
||||
if: ${{ !matrix.skip-archive }}
|
||||
uses: actions/upload-artifact@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
name: "${{ steps.variables.outputs.artifact-name }}"
|
||||
path: |
|
||||
build/zephyr/zmk.hex
|
||||
build/zephyr/zmk.uf2
|
||||
continue-on-error: true
|
||||
node-version: '14.x'
|
||||
- name: Install @actions/artifact
|
||||
run: npm install @actions/artifact
|
||||
- name: Build and upload artifacts
|
||||
uses: actions/github-script@v4
|
||||
id: boards-list
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const artifact = require('@actions/artifact');
|
||||
const artifactClient = artifact.create();
|
||||
|
||||
const execSync = require('child_process').execSync;
|
||||
|
||||
const buildShieldArgs = JSON.parse(`${{ matrix.shieldArgs }}`);
|
||||
|
||||
let error = false;
|
||||
|
||||
for (const shieldArgs of buildShieldArgs) {
|
||||
try {
|
||||
const output = execSync(`west build -s app -p -b ${{ matrix.board }} -- ${shieldArgs.shield ? '-DSHIELD=' + shieldArgs.shield : ''} ${shieldArgs['cmake-args'] || ''}`);
|
||||
|
||||
console.log(`::group::${{ matrix.board}} ${shieldArgs.shield} Build`)
|
||||
console.log(output.toString());
|
||||
|
||||
const fileExtensions = ["hex", "uf2"];
|
||||
|
||||
const files = fileExtensions
|
||||
.map(extension => "build/zephyr/zmk." + extension)
|
||||
.filter(path => fs.existsSync(path));
|
||||
|
||||
const rootDirectory = 'build/zephyr';
|
||||
const options = {
|
||||
continueOnError: true
|
||||
}
|
||||
|
||||
const cmakeName = shieldArgs['cmake-args'] ? '-' + (shieldArgs.nickname || shieldArgs['cmake-args'].split(' ').join('')) : '';
|
||||
const artifactName = `${{ matrix.board }}${shieldArgs.shield ? '-' + shieldArgs.shield : ''}${cmakeName}-zmk`;
|
||||
|
||||
await artifactClient.uploadArtifact(artifactName, files, rootDirectory, options);
|
||||
} catch (e) {
|
||||
console.error(`::error::Failed to build or upload ${{ matrix.board }} ${shieldArgs.shield} ${shieldArgs['cmake-args']}`);
|
||||
console.error(e);
|
||||
error = true;
|
||||
} finally {
|
||||
console.log('::endgroup::');
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
throw new Error('Failed to build one or more configurations');
|
||||
}
|
||||
compile-matrix:
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: [core-coverage, board-changes, nightly]
|
||||
outputs:
|
||||
include-list: ${{ steps.compile-list.outputs.result }}
|
||||
steps:
|
||||
- name: Join build lists
|
||||
uses: actions/github-script@v4
|
||||
id: compile-list
|
||||
with:
|
||||
script: |
|
||||
const coreCoverage = `${{ needs.core-coverage.outputs.core-include }}` || "[]";
|
||||
const boardChanges = `${{ needs.board-changes.outputs.boards-include }}` || "[]";
|
||||
const nightly = `${{ needs.nightly.outputs.nightly-include }}` || "[]";
|
||||
|
||||
const combined = [
|
||||
...JSON.parse(coreCoverage),
|
||||
...JSON.parse(boardChanges),
|
||||
...JSON.parse(nightly)
|
||||
];
|
||||
const combinedUnique = [...new Map(combined.map(el => [JSON.stringify(el), el])).values()];
|
||||
|
||||
const perBoard = {};
|
||||
|
||||
for (const configuration of combinedUnique) {
|
||||
if (!perBoard[configuration.board])
|
||||
perBoard[configuration.board] = [];
|
||||
|
||||
perBoard[configuration.board].push({
|
||||
shield: configuration.shield,
|
||||
'cmake-args': configuration['cmake-args'],
|
||||
nickname: configuration.nickname
|
||||
})
|
||||
}
|
||||
|
||||
return Object.entries(perBoard).map(([board, shieldArgs]) => ({
|
||||
board,
|
||||
shieldArgs: JSON.stringify(shieldArgs),
|
||||
}));
|
||||
core-coverage:
|
||||
if: ${{ needs.get-changed-files.outputs.core-changes == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-changed-files
|
||||
outputs:
|
||||
core-include: ${{ steps.core-list.outputs.result }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14.x'
|
||||
- name: Install js-yaml
|
||||
run: npm install js-yaml
|
||||
- uses: actions/github-script@v4
|
||||
id: core-list
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const coreCoverage = yaml.load(fs.readFileSync('app/core-coverage.yml', 'utf8'));
|
||||
|
||||
let include = coreCoverage.board.flatMap(board =>
|
||||
coreCoverage.shield.map(shield => ({ board, shield }))
|
||||
);
|
||||
|
||||
return [...include, ...coreCoverage.include];
|
||||
board-changes:
|
||||
if: ${{ needs.get-changed-files.outputs.board-changes == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-grouped-hardware, get-changed-files]
|
||||
outputs:
|
||||
boards-include: ${{ steps.boards-list.outputs.result }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14.x'
|
||||
- name: Install js-yaml
|
||||
run: npm install js-yaml
|
||||
- uses: actions/github-script@v4
|
||||
id: boards-list
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const changedFiles = JSON.parse(`${{ needs.get-changed-files.outputs.changed-files }}`);
|
||||
const metadata = JSON.parse(`${{ needs.get-grouped-hardware.outputs.organized-metadata }}`);
|
||||
const boardChanges = new Set(changedFiles.filter(f => f.startsWith('app/boards')).map(f => f.split('/').slice(0, 4).join('/')));
|
||||
|
||||
return (await Promise.all([...boardChanges].flatMap(async bc => {
|
||||
const globber = await glob.create(bc + "/*.zmk.yml");
|
||||
const files = await globber.glob();
|
||||
|
||||
const aggregated = files.flatMap((f) =>
|
||||
yaml.loadAll(fs.readFileSync(f, "utf8"))
|
||||
);
|
||||
|
||||
const boardAndShield = (b, s) => {
|
||||
if (s.siblings) {
|
||||
return s.siblings.map(shield => ({
|
||||
board: b.id,
|
||||
shield,
|
||||
}));
|
||||
} else {
|
||||
return {
|
||||
board: b.id,
|
||||
shield: s.id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return aggregated.flatMap(hm => {
|
||||
switch (hm.type) {
|
||||
case "board":
|
||||
if (hm.features && hm.features.includes("keys")) {
|
||||
if (hm.siblings) {
|
||||
return hm.siblings.map(board => ({
|
||||
board,
|
||||
}));
|
||||
} else {
|
||||
return {
|
||||
board: hm.id
|
||||
};
|
||||
}
|
||||
} else if (hm.exposes) {
|
||||
return hm.exposes.flatMap(i =>
|
||||
metadata.interconnects[i].shields.flatMap(s => boardAndShield(hm, s))
|
||||
);
|
||||
} else {
|
||||
console.error("Board without keys or interconnect");
|
||||
}
|
||||
break;
|
||||
case "shield":
|
||||
if (hm.features && hm.features.includes("keys")) {
|
||||
return hm.requires.flatMap(i =>
|
||||
metadata.interconnects[i].boards.flatMap(b => boardAndShield(b, hm))
|
||||
);
|
||||
}
|
||||
break;
|
||||
case "interconnect":
|
||||
break;
|
||||
}
|
||||
});
|
||||
}))).flat();
|
||||
nightly:
|
||||
if: ${{ github.event_name == 'schedule' }}
|
||||
runs-on: ubuntu-latest
|
||||
needs: get-grouped-hardware
|
||||
outputs:
|
||||
nightly-include: ${{ steps.nightly-list.outputs.result }}
|
||||
steps:
|
||||
- name: Create nightly list
|
||||
uses: actions/github-script@v4
|
||||
id: nightly-list
|
||||
with:
|
||||
script: |
|
||||
const metadata = JSON.parse(`${{ needs.get-grouped-hardware.outputs.organized-metadata }}`);
|
||||
|
||||
let includeOnboard = metadata.onboard.flatMap(b => {
|
||||
if (b.siblings) {
|
||||
return b.siblings.map(board => ({
|
||||
board,
|
||||
}));
|
||||
} else {
|
||||
return {
|
||||
board: b.id,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
let includeInterconnect = Object.values(metadata.interconnects).flatMap(i =>
|
||||
i.boards.flatMap(b =>
|
||||
i.shields.flatMap(s => {
|
||||
if (s.siblings) {
|
||||
return s.siblings.map(shield => ({
|
||||
board: b.id,
|
||||
shield,
|
||||
}));
|
||||
} else {
|
||||
return {
|
||||
board: b.id,
|
||||
shield: s.id,
|
||||
};
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return [...includeOnboard, ...includeInterconnect];
|
||||
get-grouped-hardware:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
organized-metadata: ${{ steps.organize-metadata.outputs.result }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14.x'
|
||||
- name: Install js-yaml
|
||||
run: npm install js-yaml
|
||||
- name: Aggregate Metadata
|
||||
uses: actions/github-script@v4
|
||||
id: aggregate-metadata
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const globber = await glob.create("app/boards/**/*.zmk.yml");
|
||||
const files = await globber.glob();
|
||||
|
||||
const aggregated = files.flatMap((f) =>
|
||||
yaml.loadAll(fs.readFileSync(f, "utf8"))
|
||||
);
|
||||
|
||||
return JSON.stringify(aggregated).replace(/\\/g,"\\\\");
|
||||
result-encoding: string
|
||||
|
||||
- name: Organize Metadata
|
||||
uses: actions/github-script@v4
|
||||
id: organize-metadata
|
||||
with:
|
||||
script: |
|
||||
const hardware = JSON.parse(`${{ steps.aggregate-metadata.outputs.result }}`);
|
||||
|
||||
const grouped = hardware.reduce((agg, hm) => {
|
||||
switch (hm.type) {
|
||||
case "board":
|
||||
if (hm.features && hm.features.includes("keys")) {
|
||||
agg.onboard.push(hm);
|
||||
} else if (hm.exposes) {
|
||||
hm.exposes.forEach((element) => {
|
||||
let ic = agg.interconnects[element] || {
|
||||
boards: [],
|
||||
shields: [],
|
||||
};
|
||||
ic.boards.push(hm);
|
||||
agg.interconnects[element] = ic;
|
||||
});
|
||||
} else {
|
||||
console.error("Board without keys or interconnect");
|
||||
}
|
||||
break;
|
||||
case "shield":
|
||||
if (hm.features && hm.features.includes("keys")) {
|
||||
hm.requires.forEach((id) => {
|
||||
let ic = agg.interconnects[id] || { boards: [], shields: [] };
|
||||
ic.shields.push(hm);
|
||||
agg.interconnects[id] = ic;
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "interconnect":
|
||||
let ic = agg.interconnects[hm.id] || { boards: [], shields: [] };
|
||||
ic.interconnect = hm;
|
||||
agg.interconnects[hm.id] = ic;
|
||||
break;
|
||||
}
|
||||
return agg;
|
||||
},
|
||||
{ onboard: [], interconnects: {} });
|
||||
|
||||
return JSON.stringify(grouped).replace(/\\/g,"\\\\");
|
||||
result-encoding: string
|
||||
get-changed-files:
|
||||
if: ${{ github.event_name != 'schedule' }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
changed-files: ${{ steps.changed-files.outputs.all }}
|
||||
board-changes: ${{ steps.board-changes.outputs.result }}
|
||||
core-changes: ${{ steps.core-changes.outputs.result }}
|
||||
steps:
|
||||
- uses: Ana06/get-changed-files@v2.0.0
|
||||
id: changed-files
|
||||
with:
|
||||
format: 'json'
|
||||
- uses: actions/github-script@v4
|
||||
id: board-changes
|
||||
with:
|
||||
script: |
|
||||
const changedFiles = JSON.parse(`${{ steps.changed-files.outputs.all }}`);
|
||||
const boardChanges = changedFiles.filter(f => f.startsWith('app/boards'));
|
||||
return boardChanges.length ? 'true' : 'false';
|
||||
result-encoding: string
|
||||
- uses: actions/github-script@v4
|
||||
id: core-changes
|
||||
with:
|
||||
script: |
|
||||
const changedFiles = JSON.parse(`${{ steps.changed-files.outputs.all }}`);
|
||||
const boardChanges = changedFiles.filter(f => f.startsWith('app/boards'));
|
||||
const appChanges = changedFiles.filter(f => f.startsWith('app'));
|
||||
const ymlChanges = changedFiles.includes('.github/workflows/build.yml');
|
||||
return boardChanges.length < appChanges.length || ymlChanges ? 'true' : 'false';
|
||||
result-encoding: string
|
||||
|
|
|
@ -23,6 +23,7 @@ zephyr_linker_sources(RODATA include/linker/zmk-events.ld)
|
|||
# find_package(Zephyr) which defines the target.
|
||||
target_include_directories(app PRIVATE include)
|
||||
target_sources_ifdef(CONFIG_ZMK_SLEEP app PRIVATE src/power.c)
|
||||
target_sources(app PRIVATE src/stdlib.c)
|
||||
target_sources(app PRIVATE src/activity.c)
|
||||
target_sources(app PRIVATE src/kscan.c)
|
||||
target_sources(app PRIVATE src/matrix_transform.c)
|
||||
|
@ -42,12 +43,14 @@ target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
|||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/ble_active_profile_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/events/battery_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_USB app PRIVATE src/events/usb_conn_state_changed.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sticky_key.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_caps_word.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_repeat.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_momentary_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_mod_morph.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_outputs.c)
|
||||
|
@ -56,12 +59,12 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
|||
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_sensor_rotate_key_press.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext_power.c)
|
||||
target_sources(app PRIVATE src/combo.c)
|
||||
target_sources(app PRIVATE src/conditional_layer.c)
|
||||
target_sources(app PRIVATE src/keymap.c)
|
||||
endif()
|
||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/behaviors/behavior_rgb_underglow.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/behaviors/behavior_backlight.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/behaviors/behavior_bt.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/ble.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/battery.c)
|
||||
|
@ -75,6 +78,7 @@ endif()
|
|||
target_sources_ifdef(CONFIG_USB app PRIVATE src/usb.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BLE app PRIVATE src/hog.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_RGB_UNDERGLOW app PRIVATE src/rgb_underglow.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BACKLIGHT app PRIVATE src/backlight.c)
|
||||
target_sources(app PRIVATE src/endpoints.c)
|
||||
target_sources(app PRIVATE src/hid_listener.c)
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
|
|
41
app/Kconfig
41
app/Kconfig
|
@ -175,6 +175,14 @@ config ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE
|
|||
int "Max number of key position state events to queue when received from peripherals"
|
||||
default 5
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE
|
||||
int "BLE split central write thread stack size"
|
||||
default 512
|
||||
|
||||
config ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE
|
||||
int "Max number of behavior run events to queue to send to the peripheral(s)"
|
||||
default 5
|
||||
|
||||
endif
|
||||
|
||||
if !ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
|
@ -249,7 +257,7 @@ menu "Display/LED Options"
|
|||
|
||||
rsource "src/display/Kconfig"
|
||||
|
||||
config ZMK_RGB_UNDERGLOW
|
||||
menuconfig ZMK_RGB_UNDERGLOW
|
||||
bool "RGB Adressable LED Underglow"
|
||||
select LED_STRIP
|
||||
|
||||
|
@ -327,6 +335,35 @@ config ZMK_RGB_UNDERGLOW_AUTO_OFF_USB
|
|||
#ZMK_RGB_UNDERGLOW
|
||||
endif
|
||||
|
||||
menuconfig ZMK_BACKLIGHT
|
||||
bool "LED backlight"
|
||||
select LED
|
||||
|
||||
if ZMK_BACKLIGHT
|
||||
|
||||
config ZMK_BACKLIGHT_BRT_STEP
|
||||
int "Brightness step in percent"
|
||||
range 1 100
|
||||
default 20
|
||||
|
||||
config ZMK_BACKLIGHT_BRT_START
|
||||
int "Default brightness in percent"
|
||||
range 1 100
|
||||
default 40
|
||||
|
||||
config ZMK_BACKLIGHT_ON_START
|
||||
bool "Default backlight state"
|
||||
default y
|
||||
|
||||
config ZMK_BACKLIGHT_AUTO_OFF_IDLE
|
||||
bool "Turn off backlight when keyboard goes into idle state"
|
||||
|
||||
config ZMK_BACKLIGHT_AUTO_OFF_USB
|
||||
bool "Turn off backlight when USB is disconnected"
|
||||
|
||||
#ZMK_BACKLIGHT
|
||||
endif
|
||||
|
||||
#Display/LED Options
|
||||
endmenu
|
||||
|
||||
|
@ -377,7 +414,7 @@ config ZMK_COMBO_MAX_KEYS_PER_COMBO
|
|||
int "Maximum number of keys per combo"
|
||||
default 4
|
||||
|
||||
#Display/LED Options
|
||||
#Combo options
|
||||
endmenu
|
||||
|
||||
menu "Advanced"
|
||||
|
|
19
app/boards/shields/clog/Kconfig.defconfig
Normal file
19
app/boards/shields/clog/Kconfig.defconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_CLOG_LEFT
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Clog"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
if SHIELD_CLOG_LEFT || SHIELD_CLOG_RIGHT
|
||||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
||||
endif
|
8
app/boards/shields/clog/Kconfig.shield
Normal file
8
app/boards/shields/clog/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_CLOG_LEFT
|
||||
def_bool $(shields_list_contains,clog_left)
|
||||
|
||||
config SHIELD_CLOG_RIGHT
|
||||
def_bool $(shields_list_contains,clog_right)
|
8
app/boards/shields/clog/README.md
Normal file
8
app/boards/shields/clog/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# The Clog
|
||||
|
||||
The Clog is a 34-key choc v1 split board by S'mores. This firmware works for both the [Clog][clog],
|
||||
as well as the [Sephirette][sephirette], the MX version. You can purchase kits for both boards
|
||||
at smoresboards.com.
|
||||
|
||||
[clog]: https://github.com/smores56/clog
|
||||
[sephirette]: https://github.com/smores56/sephirette
|
0
app/boards/shields/clog/clog.conf
Normal file
0
app/boards/shields/clog/clog.conf
Normal file
51
app/boards/shields/clog/clog.dtsi
Normal file
51
app/boards/shields/clog/clog.dtsi
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <34>;
|
||||
rows = <1>;
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,20) RC(0,19) RC(0,18) RC(0,17)
|
||||
RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,26) RC(0,25) RC(0,24) RC(0,23) RC(0,22) RC(0,21)
|
||||
RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,31) RC(0,30) RC(0,29) RC(0,28) RC(0,27)
|
||||
RC(0,15) RC(0,16) RC(0,33) RC(0,32)
|
||||
>;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-direct";
|
||||
label = "KSCAN";
|
||||
|
||||
input-gpios
|
||||
= <&pro_micro 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 10 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 1 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
, <&pro_micro 9 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
|
||||
;
|
||||
};
|
||||
};
|
113
app/boards/shields/clog/clog.keymap
Normal file
113
app/boards/shields/clog/clog.keymap
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
#define MAIN 0
|
||||
#define SYM 1
|
||||
#define NAV 2
|
||||
#define BT 3
|
||||
|
||||
&mt {
|
||||
flavor = "tap-preferred";
|
||||
tapping_term_ms = <140>;
|
||||
};
|
||||
|
||||
/ {
|
||||
combos {
|
||||
compatible = "zmk,combos";
|
||||
|
||||
combo_esc {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <21 22>;
|
||||
bindings = <&kp ESC>;
|
||||
};
|
||||
|
||||
combo_tab {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <22 23>;
|
||||
bindings = <&kp TAB>;
|
||||
};
|
||||
|
||||
combo_minus {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <26 27>;
|
||||
bindings = <&kp MINUS>;
|
||||
};
|
||||
|
||||
combo_underscore {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <26 28>;
|
||||
bindings = <&kp UNDERSCORE>;
|
||||
};
|
||||
|
||||
combo_colon {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <7 8>;
|
||||
bindings = <&kp COLON>;
|
||||
};
|
||||
|
||||
combo_semicolon {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <6 8>;
|
||||
bindings = <&kp SEMICOLON>;
|
||||
};
|
||||
|
||||
combo_backslash {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <27 28>;
|
||||
bindings = <&kp BSLH>;
|
||||
};
|
||||
|
||||
combo_grave {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <8 9>;
|
||||
bindings = <&kp GRAVE>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
MAIN_layer {
|
||||
bindings = <
|
||||
&kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O
|
||||
&kp Q &kp A &kp S &kp D < SYM F &kp G &kp H < SYM J &kp K &kp L &kp SQT &kp P
|
||||
&mt LSHFT Z &mt LALT X &mt LCTRL C &mt LGUI V &kp B &kp N &mt RGUI M &mt RCTRL COMMA &mt RALT DOT &mt RSHFT FSLH
|
||||
< BT ENTER < NAV SPACE &sk RSHFT &kp BSPC
|
||||
>;
|
||||
};
|
||||
|
||||
SYM_layer {
|
||||
bindings = <
|
||||
&kp N7 &kp N8 &kp N9 &kp STAR &kp DLLR &kp LBRC &kp RBRC &kp HASH
|
||||
&kp AMPS &kp EXCL &kp N1 &kp N2 &kp N3 &kp EQUAL &kp LT &kp LPAR &kp RPAR &kp GT &kp PIPE &none
|
||||
&kp CARET &kp N4 &kp N5 &kp N6 &kp PLUS &kp TILDE &kp LBKT &kp RBKT &kp AT &kp PRCNT
|
||||
&kp DOT &kp N0 &trans &none
|
||||
>;
|
||||
};
|
||||
|
||||
NAV_layer {
|
||||
bindings = <
|
||||
&kp C_VOL_DN &kp C_VOL_UP &kp C_NEXT &kp C_PP &none &kp F7 &kp F8 &kp F9
|
||||
&kp C_PREV &kp LEFT &kp DOWN &kp UP &kp RIGHT &kp LC(TAB) &kp PSCRN &kp F1 &kp F2 &kp F3 &kp F10 &kp F12
|
||||
&kp HOME &kp PG_DN &kp PG_UP &kp END &kp LS(LC(TAB)) &kp CAPS &kp F4 &kp F5 &kp F6 &kp F11
|
||||
&none &none &trans &kp DEL
|
||||
>;
|
||||
};
|
||||
|
||||
BT_layer {
|
||||
bindings = <
|
||||
&none &none &none &none &none &none &none &none
|
||||
&none &none &none &none &none &none &none &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &none
|
||||
&none &none &none &none &none &none &bt BT_CLR &none &none &none
|
||||
&none &none &none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
11
app/boards/shields/clog/clog.zmk.yml
Normal file
11
app/boards/shields/clog/clog.zmk.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
file_format: "1"
|
||||
id: clog
|
||||
name: Clog
|
||||
type: shield
|
||||
url: https://github.com/smores56/clog
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
||||
siblings:
|
||||
- clog_left
|
||||
- clog_right
|
7
app/boards/shields/clog/clog_left.overlay
Normal file
7
app/boards/shields/clog/clog_left.overlay
Normal file
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "clog.dtsi"
|
11
app/boards/shields/clog/clog_right.overlay
Normal file
11
app/boards/shields/clog/clog_right.overlay
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "clog.dtsi"
|
||||
|
||||
&default_transform {
|
||||
col-offset = <17>;
|
||||
};
|
9
app/boards/shields/contra/Kconfig.defconfig
Normal file
9
app/boards/shields/contra/Kconfig.defconfig
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_CONTRA
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Contra Keyboard"
|
||||
|
||||
endif
|
5
app/boards/shields/contra/Kconfig.shield
Normal file
5
app/boards/shields/contra/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_CONTRA
|
||||
def_bool $(shields_list_contains,contra)
|
0
app/boards/shields/contra/contra.conf
Normal file
0
app/boards/shields/contra/contra.conf
Normal file
46
app/boards/shields/contra/contra.keymap
Normal file
46
app/boards/shields/contra/contra.keymap
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
#define DEFAULT 0
|
||||
#define NUM_MODS 1
|
||||
#define BT_CTRL 2
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSPC
|
||||
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
|
||||
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp ENTER
|
||||
&kp LCTRL &kp LGUI &kp LALT &kp BSLH &to DEFAULT &kp SPACE &trans &to NUM_MODS &kp LEFT &kp RIGHT &kp UP &kp DOWN
|
||||
>;
|
||||
};
|
||||
|
||||
num_mods {
|
||||
bindings = <
|
||||
&kp GRAVE &kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp DEL
|
||||
&kp TAB &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp MINUS &kp PG_UP &kp LBKT &kp RBKT &kp BSLH
|
||||
&kp LSHFT &kp F7 &kp F8 &kp F9 &kp F10 &kp F11 &kp F12 &kp EQUAL &kp PG_DN &kp HOME &kp END &kp ENTER
|
||||
&kp LCTRL &kp LGUI &kp LALT &reset &to DEFAULT &kp SPACE &trans &mo BT_CTRL &kp LEFT &kp RIGHT &kp UP &kp DOWN
|
||||
>;
|
||||
};
|
||||
|
||||
bt_control {
|
||||
bindings = <
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &trans &trans &trans &trans &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans &bt BT_PRV &bt BT_NXT &trans &trans
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
39
app/boards/shields/contra/contra.overlay
Normal file
39
app/boards/shields/contra/contra.overlay
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan_0 {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
diode-direction = "col2row";
|
||||
|
||||
col-gpios
|
||||
= <&pro_micro 21 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 20 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 9 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 8 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 7 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 6 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 5 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 4 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 3 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 2 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 0 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 1 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
|
||||
row-gpios
|
||||
= <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
};
|
||||
};
|
8
app/boards/shields/contra/contra.zmk.yml
Normal file
8
app/boards/shields/contra/contra.zmk.yml
Normal file
|
@ -0,0 +1,8 @@
|
|||
file_format: "1"
|
||||
id: contra
|
||||
name: Contra
|
||||
type: shield
|
||||
url: https://github.com/ai03-2725/Contra
|
||||
requires: [pro_micro]
|
||||
features:
|
||||
- keys
|
45
app/boards/shields/knob_goblin/Kconfig.defconfig
Normal file
45
app/boards/shields/knob_goblin/Kconfig.defconfig
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_KNOB_GOBLIN
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Knob Goblin"
|
||||
|
||||
if ZMK_DISPLAY
|
||||
|
||||
config I2C
|
||||
default y
|
||||
|
||||
config SSD1306
|
||||
default y
|
||||
|
||||
config SSD1306_REVERSE_MODE
|
||||
default y
|
||||
|
||||
endif # ZMK_DISPLAY
|
||||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
config LVGL_DPI
|
||||
default 148
|
||||
|
||||
config LVGL_BITS_PER_PIXEL
|
||||
default 1
|
||||
|
||||
choice LVGL_COLOR_DEPTH
|
||||
default LVGL_COLOR_DEPTH_1
|
||||
endchoice
|
||||
|
||||
endif # LVGL
|
||||
|
||||
endif # SHIELD_KNOB_GOBLIN
|
5
app/boards/shields/knob_goblin/Kconfig.shield
Normal file
5
app/boards/shields/knob_goblin/Kconfig.shield
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_KNOB_GOBLIN
|
||||
def_bool $(shields_list_contains,knob_goblin)
|
9
app/boards/shields/knob_goblin/knob_goblin.conf
Normal file
9
app/boards/shields/knob_goblin/knob_goblin.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Uncomment to enable Encoders
|
||||
CONFIG_EC11=y
|
||||
CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
||||
|
||||
# Uncomment the following line to enable the Knob Goblin OLED Display
|
||||
CONFIG_ZMK_DISPLAY=y
|
40
app/boards/shields/knob_goblin/knob_goblin.keymap
Normal file
40
app/boards/shields/knob_goblin/knob_goblin.keymap
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
|
||||
bindings = <
|
||||
&trans &kp EQUAL &kp KP_SLASH &kp KP_MULTIPLY &kp KP_MINUS
|
||||
&trans &kp KP_NUMBER_7 &kp KP_NUMBER_8 &kp KP_NUMBER_9 &kp KP_PLUS
|
||||
&trans &kp KP_NUMBER_4 &kp KP_NUMBER_5 &kp KP_NUMBER_6 &kp KP_PLUS
|
||||
&kp C_PLAY_PAUSE &kp KP_NUMBER_1 &kp KP_NUMBER_2 &kp KP_NUMBER_3 &kp KP_ENTER
|
||||
&kp C_MUTE &mo 1 &kp KP_NUMBER_0 &kp KP_DOT &kp KP_ENTER
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>;
|
||||
};
|
||||
|
||||
num_layer {
|
||||
bindings = <
|
||||
&trans &bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2
|
||||
&trans &kp HOME &trans &kp PAGE_UP &trans
|
||||
&trans &kp END &kp UP_ARROW &kp PAGE_DOWN &trans
|
||||
&trans &kp LEFT_ARROW &kp DOWN_ARROW &kp RIGHT_ARROW &kp SPACE
|
||||
&trans &trans &kp BACKSPACE &kp DELETE &trans
|
||||
>;
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
79
app/boards/shields/knob_goblin/knob_goblin.overlay
Normal file
79
app/boards/shields/knob_goblin/knob_goblin.overlay
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
diode-direction = "col2row";
|
||||
|
||||
row-gpios
|
||||
= <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 16 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
|
||||
col-gpios
|
||||
= <&pro_micro 9 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 8 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 7 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 6 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 5 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
};
|
||||
|
||||
top_encoder: encoder_top {
|
||||
compatible = "alps,ec11";
|
||||
label = "TOP_ENCODER";
|
||||
a-gpios = <&pro_micro 19 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 18 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
bottom_encoder: encoder_bottom {
|
||||
compatible = "alps,ec11";
|
||||
label = "BOTTOM_ENCODER";
|
||||
a-gpios = <&pro_micro 20 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 21 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sensors {
|
||||
compatible = "zmk,keymap-sensors";
|
||||
sensors = <&top_encoder &bottom_encoder>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&pro_micro_i2c {
|
||||
status = "okay";
|
||||
|
||||
oled: ssd1306@3c {
|
||||
compatible = "solomon,ssd1306fb";
|
||||
reg = <0x3c>;
|
||||
label = "DISPLAY";
|
||||
width = <128>;
|
||||
height = <32>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <31>;
|
||||
segment-remap;
|
||||
com-invdir;
|
||||
com-sequential;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
};
|
11
app/boards/shields/knob_goblin/knob_goblin.zmk.yml
Normal file
11
app/boards/shields/knob_goblin/knob_goblin.zmk.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
file_format: "1"
|
||||
id: knob_goblin
|
||||
name: Knob Goblin
|
||||
type: shield
|
||||
url: https://knob-goblin.com/
|
||||
requires: [pro_micro]
|
||||
exposes: [i2c_oled]
|
||||
features:
|
||||
- keys
|
||||
- display
|
||||
- encoder
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
if SHIELD_KYRIA_LEFT
|
||||
if SHIELD_KYRIA_LEFT || SHIELD_KYRIA_REV2_LEFT
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Kyria"
|
||||
|
@ -9,7 +9,7 @@ config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
|||
|
||||
endif
|
||||
|
||||
if SHIELD_KYRIA_LEFT || SHIELD_KYRIA_RIGHT
|
||||
if SHIELD_KYRIA
|
||||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
# Copyright (c) 2020 Pete Johanson
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_KYRIA
|
||||
bool
|
||||
|
||||
config SHIELD_KYRIA_LEFT
|
||||
def_bool $(shields_list_contains,kyria_left)
|
||||
select SHIELD_KYRIA
|
||||
|
||||
config SHIELD_KYRIA_RIGHT
|
||||
def_bool $(shields_list_contains,kyria_right)
|
||||
select SHIELD_KYRIA
|
||||
|
||||
config SHIELD_KYRIA_REV2_LEFT
|
||||
def_bool $(shields_list_contains,kyria_rev2_left)
|
||||
select SHIELD_KYRIA
|
||||
|
||||
config SHIELD_KYRIA_REV2_RIGHT
|
||||
def_bool $(shields_list_contains,kyria_rev2_right)
|
||||
select SHIELD_KYRIA
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Pete Johanson
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
#include "kyria_common.dtsi"
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
|
@ -43,60 +42,23 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9)
|
|||
RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
|
||||
diode-direction = "col2row";
|
||||
&kscan0 {
|
||||
row-gpios
|
||||
= <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
left_encoder: encoder_left {
|
||||
compatible = "alps,ec11";
|
||||
label = "LEFT_ENCODER";
|
||||
&left_encoder {
|
||||
a-gpios = <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
||||
right_encoder: encoder_right {
|
||||
compatible = "alps,ec11";
|
||||
label = "RIGHT_ENCODER";
|
||||
&right_encoder {
|
||||
a-gpios = <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 9 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sensors {
|
||||
compatible = "zmk,keymap-sensors";
|
||||
sensors = <&left_encoder &right_encoder>;
|
||||
};
|
||||
|
||||
// TODO: RGB node(s)
|
||||
};
|
||||
|
||||
&pro_micro_i2c {
|
||||
status = "okay";
|
||||
|
||||
ssd1306@3c {
|
||||
compatible = "solomon,ssd1306fb";
|
||||
reg = <0x3c>;
|
||||
label = "DISPLAY";
|
||||
width = <128>;
|
||||
height = <64>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <63>;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
};
|
||||
|
|
59
app/boards/shields/kyria/kyria_common.dtsi
Normal file
59
app/boards/shields/kyria/kyria_common.dtsi
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
|
||||
diode-direction = "col2row";
|
||||
};
|
||||
|
||||
left_encoder: encoder_left {
|
||||
compatible = "alps,ec11";
|
||||
label = "LEFT_ENCODER";
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
right_encoder: encoder_right {
|
||||
compatible = "alps,ec11";
|
||||
label = "RIGHT_ENCODER";
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sensors {
|
||||
compatible = "zmk,keymap-sensors";
|
||||
sensors = <&left_encoder &right_encoder>;
|
||||
};
|
||||
|
||||
// TODO: RGB node(s)
|
||||
};
|
||||
|
||||
&pro_micro_i2c {
|
||||
status = "okay";
|
||||
|
||||
ssd1306@3c {
|
||||
compatible = "solomon,ssd1306fb";
|
||||
reg = <0x3c>;
|
||||
label = "DISPLAY";
|
||||
width = <128>;
|
||||
height = <64>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <63>;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
};
|
10
app/boards/shields/kyria/kyria_rev2.conf
Normal file
10
app/boards/shields/kyria/kyria_rev2.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Uncomment these two line to add support for encoders to your firmware
|
||||
# CONFIG_EC11=y
|
||||
# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
||||
|
||||
# Uncomment the following line to enable the Kyria OLED Display
|
||||
# CONFIG_ZMK_DISPLAY=y
|
||||
|
||||
# Uncomment the following lines to enable RGB underglow
|
||||
# CONFIG_ZMK_RGB_UNDERGLOW=y
|
||||
# CONFIG_WS2812_STRIP=y
|
55
app/boards/shields/kyria/kyria_rev2.dtsi
Normal file
55
app/boards/shields/kyria/kyria_rev2.dtsi
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "kyria_common.dtsi"
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <16>;
|
||||
rows = <4>;
|
||||
// | MX6 | MX5 | MX4 | MX3 | MX2 | MX1 | | MX1 | MX2 | MX3 | MX4 | MX5 | MX6 |
|
||||
// | MX12 | MX11 | MX10 | MX9 | MX8 | MX7 | | MX7 | MX8 | MX9 | MX10 | MX11 | MX12 |
|
||||
// | MX20 | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 | | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 | MX20 |
|
||||
// | MX25 | MX24 | MX23 | MX22 | MX21 | | MX21 | MX22 | MX23 | MX24 | MX25 |
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,10) RC(0,11) RC(0,12) RC(0,13) RC(0,14) RC(0,15)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,10) RC(1,11) RC(1,12) RC(1,13) RC(1,14) RC(1,15)
|
||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13) RC(2,14) RC(2,15)
|
||||
RC(3,2) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11) RC(3,13)
|
||||
>;
|
||||
};
|
||||
|
||||
// | MX5 | MX4 | MX3 | MX2 | MX1 | | MX1 | MX2 | MX3 | MX4 | MX5 |
|
||||
// | MX11 | MX10 | MX9 | MX8 | MX7 | | MX7 | MX8 | MX9 | MX10 | MX11 |
|
||||
// | MX19 | MX18 | MX17 | MX16 | MX15 | MX14 | MX13 | | MX13 | MX14 | MX15 | MX16 | MX17 | MX18 | MX19 |
|
||||
// | MX25 | MX24 | MX23 | MX22 | MX21 | | MX21 | MX22 | MX23 | MX24 | MX25 |
|
||||
five_column_transform: keymap_transform_1 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <14>;
|
||||
rows = <4>;
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,9) RC(0,10) RC(0,11) RC(0,12) RC(0,13)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,9) RC(1,10) RC(1,11) RC(1,12) RC(1,13)
|
||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11) RC(2,12) RC(2,13)
|
||||
RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
|
||||
>;
|
||||
};
|
||||
};
|
||||
|
||||
&left_encoder {
|
||||
a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
};
|
||||
|
||||
&right_encoder {
|
||||
a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
};
|
30
app/boards/shields/kyria/kyria_rev2.keymap
Normal file
30
app/boards/shields/kyria/kyria_rev2.keymap
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
// ---------------------------------------------------------------------------------------------------------------------------------
|
||||
// | ESC | Q | W | E | R | T | | Y | U | I | O | P | \ |
|
||||
// | TAB | A | S | D | F | G | | H | J | K | L | ; | ' |
|
||||
// | SHIFT | Z | X | C | V | B | L SHIFT | L SHIFT | | L SHIFT | L SHIFT | N | M | , | . | / | CTRL |
|
||||
// | GUI | DEL | RET | SPACE | ESC | | RET | SPACE | TAB | BSPC | R-ALT |
|
||||
bindings = <
|
||||
&kp ESC &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp BSLH
|
||||
&kp TAB &kp A &kp S &kp D &kp F &kp G &kp H &kp J &kp K &kp L &kp SEMI &kp SQT
|
||||
&kp LSHFT &kp Z &kp X &kp C &kp V &kp B &kp LSHFT &kp LSHFT &kp LSHFT &kp LSHFT &kp N &kp M &kp COMMA &kp DOT &kp FSLH &kp RCTRL
|
||||
&kp LGUI &kp DEL &kp RET &kp SPACE &kp ESC &kp RET &kp SPACE &kp TAB &kp BSPC &kp RALT
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_kp C_VOL_UP C_VOL_DN &inc_dec_kp PG_UP PG_DN>;
|
||||
};
|
||||
};
|
||||
};
|
15
app/boards/shields/kyria/kyria_rev2.zmk.yml
Normal file
15
app/boards/shields/kyria/kyria_rev2.zmk.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
file_format: "1"
|
||||
id: kyria_rev2
|
||||
name: Kyria Rev2
|
||||
type: shield
|
||||
url: https://splitkb.com/products/kyria-pcb-kit
|
||||
requires: [pro_micro]
|
||||
exposes: [i2c_oled]
|
||||
features:
|
||||
- keys
|
||||
- display
|
||||
- encoder
|
||||
- underglow
|
||||
siblings:
|
||||
- kyria_rev2_left
|
||||
- kyria_rev2_right
|
0
app/boards/shields/kyria/kyria_rev2_left.conf
Normal file
0
app/boards/shields/kyria/kyria_rev2_left.conf
Normal file
30
app/boards/shields/kyria/kyria_rev2_left.overlay
Normal file
30
app/boards/shields/kyria/kyria_rev2_left.overlay
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "kyria_rev2.dtsi"
|
||||
|
||||
&kscan0 {
|
||||
row-gpios
|
||||
= <&pro_micro 19 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 15 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
col-gpios
|
||||
= <&pro_micro 4 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 5 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 6 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 7 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 8 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 9 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 10 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 16 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
};
|
||||
|
||||
&left_encoder {
|
||||
status = "okay";
|
||||
};
|
0
app/boards/shields/kyria/kyria_rev2_right.conf
Normal file
0
app/boards/shields/kyria/kyria_rev2_right.conf
Normal file
34
app/boards/shields/kyria/kyria_rev2_right.overlay
Normal file
34
app/boards/shields/kyria/kyria_rev2_right.overlay
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "kyria_rev2.dtsi"
|
||||
|
||||
&default_transform {
|
||||
col-offset = <8>;
|
||||
};
|
||||
|
||||
&kscan0 {
|
||||
row-gpios
|
||||
= <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
col-gpios
|
||||
= <&pro_micro 8 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 9 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 10 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 16 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 14 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 15 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
};
|
||||
|
||||
&right_encoder {
|
||||
status = "okay";
|
||||
};
|
55
app/boards/shields/lotus58/Kconfig.defconfig
Normal file
55
app/boards/shields/lotus58/Kconfig.defconfig
Normal file
|
@ -0,0 +1,55 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
if SHIELD_LOTUS58_LEFT
|
||||
|
||||
config ZMK_KEYBOARD_NAME
|
||||
default "Lotus58"
|
||||
|
||||
config ZMK_SPLIT_BLE_ROLE_CENTRAL
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
if SHIELD_LOTUS58_LEFT || SHIELD_LOTUS58_RIGHT
|
||||
|
||||
config ZMK_SPLIT
|
||||
default y
|
||||
|
||||
if ZMK_DISPLAY
|
||||
|
||||
config I2C
|
||||
default y
|
||||
|
||||
config SSD1306
|
||||
default y
|
||||
|
||||
config SSD1306_REVERSE_MODE
|
||||
default y
|
||||
|
||||
endif # ZMK_DISPLAY
|
||||
|
||||
if LVGL
|
||||
|
||||
config LVGL_HOR_RES_MAX
|
||||
default 128
|
||||
|
||||
config LVGL_VER_RES_MAX
|
||||
default 32
|
||||
|
||||
config LVGL_VDB_SIZE
|
||||
default 64
|
||||
|
||||
config LVGL_DPI
|
||||
default 148
|
||||
|
||||
config LVGL_BITS_PER_PIXEL
|
||||
default 1
|
||||
|
||||
choice LVGL_COLOR_DEPTH
|
||||
default LVGL_COLOR_DEPTH_1
|
||||
endchoice
|
||||
|
||||
endif # LVGL
|
||||
|
||||
endif
|
8
app/boards/shields/lotus58/Kconfig.shield
Normal file
8
app/boards/shields/lotus58/Kconfig.shield
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config SHIELD_LOTUS58_LEFT
|
||||
def_bool $(shields_list_contains,lotus58_left)
|
||||
|
||||
config SHIELD_LOTUS58_RIGHT
|
||||
def_bool $(shields_list_contains,lotus58_right)
|
9
app/boards/shields/lotus58/lotus58.conf
Normal file
9
app/boards/shields/lotus58/lotus58.conf
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2022 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
# Uncomment the following line to enable the Lotus58 OLED Display
|
||||
# CONFIG_ZMK_DISPLAY=y
|
||||
|
||||
# Uncomment these two lines to add support for encoders
|
||||
# CONFIG_EC11=y
|
||||
# CONFIG_EC11_TRIGGER_GLOBAL_THREAD=y
|
89
app/boards/shields/lotus58/lotus58.dtsi
Normal file
89
app/boards/shields/lotus58/lotus58.dtsi
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/matrix_transform.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,kscan = &kscan0;
|
||||
zmk,matrix_transform = &default_transform;
|
||||
};
|
||||
|
||||
default_transform: keymap_transform_0 {
|
||||
compatible = "zmk,matrix-transform";
|
||||
columns = <16>;
|
||||
rows = <4>;
|
||||
// | SW6 | SW5 | SW4 | SW3 | SW2 | SW1 | | SW1 | SW2 | SW3 | SW4 | SW5 | SW6 |
|
||||
// | SW12 | SW11 | SW10 | SW9 | SW8 | SW7 | | SW7 | SW8 | SW9 | SW10 | SW11 | SW12 |
|
||||
// | SW18 | SW17 | SW16 | SW15 | SW14 | SW13 | SW30 | | SW30 | SW13 | SW14 | SW15 | SW16 | SW17 | SW18 |
|
||||
// | SW24 | SW23 | SW22 | SW21 | SW20 | SW19 | SW25 | | SW25 | SW19 | SW20 | SW21 | SW22 | SW23 | SW24 |
|
||||
// | SW29 | SW28 | SW27 | SW26 | | SW26 | SW27 | SW28 | SW29 |
|
||||
map = <
|
||||
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(0,5) RC(0,6) RC(0,7) RC(0,8) RC(0,9) RC(0,10) RC(0,11)
|
||||
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(1,5) RC(1,6) RC(1,7) RC(1,8) RC(1,9) RC(1,10) RC(1,11)
|
||||
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(4,0) RC(4,11) RC(2,6) RC(2,7) RC(2,8) RC(2,9) RC(2,10) RC(2,11)
|
||||
RC(3,0) RC(3,1) RC(3,2) RC(3,3) RC(3,4) RC(3,5) RC(4,5) RC(4,6) RC(3,6) RC(3,7) RC(3,8) RC(3,9) RC(3,10) RC(3,11)
|
||||
RC(4,1) RC(4,2) RC(4,3) RC(4,4) RC(4,7) RC(4,8) RC(4,9) RC(4,10)
|
||||
>;
|
||||
};
|
||||
|
||||
kscan0: kscan {
|
||||
compatible = "zmk,kscan-gpio-matrix";
|
||||
label = "KSCAN";
|
||||
|
||||
diode-direction = "col2row";
|
||||
row-gpios
|
||||
= <&pro_micro 4 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 5 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 7 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
, <&pro_micro 8 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
|
||||
;
|
||||
};
|
||||
|
||||
left_encoder: encoder_left {
|
||||
compatible = "alps,ec11";
|
||||
label = "LEFT_ENCODER";
|
||||
a-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
right_encoder: encoder_right {
|
||||
compatible = "alps,ec11";
|
||||
label = "RIGHT_ENCODER";
|
||||
a-gpios = <&pro_micro 20 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
b-gpios = <&pro_micro 21 (GPIO_ACTIVE_HIGH | GPIO_PULL_UP)>;
|
||||
resolution = <4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
sensors {
|
||||
compatible = "zmk,keymap-sensors";
|
||||
sensors = <&left_encoder &right_encoder>;
|
||||
};
|
||||
};
|
||||
|
||||
&pro_micro_i2c {
|
||||
status = "okay";
|
||||
|
||||
ssd1306@3c {
|
||||
compatible = "solomon,ssd1306fb";
|
||||
reg = <0x3c>;
|
||||
label = "DISPLAY";
|
||||
width = <128>;
|
||||
height = <32>;
|
||||
segment-offset = <0>;
|
||||
page-offset = <0>;
|
||||
display-offset = <0>;
|
||||
multiplex-ratio = <31>;
|
||||
segment-remap;
|
||||
com-invdir;
|
||||
com-sequential;
|
||||
prechargep = <0x22>;
|
||||
};
|
||||
};
|
104
app/boards/shields/lotus58/lotus58.keymap
Normal file
104
app/boards/shields/lotus58/lotus58.keymap
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/bt.h>
|
||||
#include <dt-bindings/zmk/outputs.h>
|
||||
|
||||
/ {
|
||||
combos {
|
||||
compatible = "zmk,combos";
|
||||
combo_dsklg {
|
||||
timeout-ms = <100>;
|
||||
key-positions = <24 52>;
|
||||
layers = <0>;
|
||||
bindings = <&kp LGUI>;
|
||||
};
|
||||
};
|
||||
|
||||
behaviors {
|
||||
fofunc: four_ffour {
|
||||
compatible = "zmk,behavior-mod-morph";
|
||||
label = "FOUR_FUNCFOUR";
|
||||
#binding-cells = <0>;
|
||||
bindings = <&kp N4>, <&kp F4>;
|
||||
mods = <(MOD_LALT|MOD_RALT)>;
|
||||
};
|
||||
sleft: s_left {
|
||||
compatible = "zmk,behavior-mod-morph";
|
||||
label = "S_LEFT";
|
||||
#binding-cells = <0>;
|
||||
bindings = <&kp S>, <&kp LEFT>;
|
||||
mods = <(MOD_LGUI|MOD_RGUI)>;
|
||||
};
|
||||
fright: f_right {
|
||||
compatible = "zmk,behavior-mod-morph";
|
||||
label = "R_RIGHT";
|
||||
#binding-cells = <0>;
|
||||
bindings = <&kp F>, <&kp RIGHT>;
|
||||
mods = <(MOD_LGUI|MOD_RGUI)>;
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
|
||||
default_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// 0| ESC | 1 | 2 | 3 | 4 | 5 | | 6 | 7 | 8 | 9 | 0 | = | 11
|
||||
// 12| TAB | Q | W | E | R | T | | Y | U | I | O | P | [ | 23
|
||||
// 24| SFT | A | S | D | F | G | RESET | | RESET | H | J | K | L | ; | ' SFT | 37
|
||||
// 38| CTRL | Z | X | C | V | B | MUTE | | PLAY | N | M | , | . | / | \ CTRL| 51
|
||||
// 52 |ENT RS| ALT | SPACE|DELETE LW| |ENTER RS| BSPC | ] LW | RGUI | 59
|
||||
bindings = <
|
||||
&kp ESC &kp N1 &kp N2 &kp N3 &fofunc &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0 &kp EQUAL
|
||||
&kp TAB &kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P &kp LBKT
|
||||
&kp LSHFT &kp A &sleft &kp D &fright &kp G &reset &reset &kp H &kp J &kp K &kp L &kp SEMI &mt RSHFT SQT
|
||||
&kp LCTRL &kp Z &kp X &kp C &kp V &kp B &kp C_MUTE &kp C_PP &kp N &kp M &kp COMMA &kp DOT &kp FSLH &mt RCTRL BSLH
|
||||
< 2 RET &kp LALT &kp SPACE < 1 DEL < 2 RET &kp BSPC < 1 RBKT &kp LGUI
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP &inc_dec_kp PG_UP PG_DN>;
|
||||
};
|
||||
|
||||
lower_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// | ` | F1 | F2 | F3 | F4 | F5 | | F6 | F7 | F8 | F9 | F10 | F11 |
|
||||
// | | ! | HOME| ^ | END | % | | VOL^ | PGUP | INS | ^ | PSCR | - |
|
||||
// | | # | <- | v | -> | $ | | | | VOLv | <- | ^ | -> | ~ | _ |
|
||||
// | | @ | - | ( | ) | & | | | | MUTE | PGDN | v | : | * | | |
|
||||
// | F11 | | | | | | | | F12 |
|
||||
bindings = <
|
||||
&kp GRAVE &kp F1 &kp F2 &kp F3 &kp F4 &kp F5 &kp F6 &kp F7 &kp F8 &kp F9 &kp F10 &kp PLUS
|
||||
&trans &kp EXCL &kp HOME &kp UP &kp END &kp PRCNT &kp C_VOL_UP &kp PG_UP &kp INS &kp CARET &kp PSCRN &kp MINUS
|
||||
&trans &kp HASH &kp LEFT &kp DOWN &kp RIGHT &kp DLLR &trans &trans &kp C_VOL_DN &kp LEFT &kp UP &kp RIGHT &kp TILDE &kp UNDER
|
||||
&trans &kp AT &kp MINUS &kp LBRC &kp RBRC &kp AMPS &trans &trans &kp C_MUTE &kp PG_DN &kp DOWN &kp COLON &kp STAR &kp PIPE
|
||||
&kp F11 &trans &trans &trans &trans &trans &trans &kp F12
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP &inc_dec_kp C_NEXT C_PREV>;
|
||||
};
|
||||
|
||||
raise_layer {
|
||||
// ------------------------------------------------------------------------------------------------------------
|
||||
// |BTCLR| BT1 | BT2 | BT3 | BT4 | BT5 | |OUTTOG|OUTUSB| OUTBT | | RESET | FLASH |
|
||||
// | | INS | PSCR | GUI | RESET | | | PGUP | | ^ | | | |
|
||||
// | | ALT | CTRL | SHIFT | FLASH | CAPS | | | | PGDN | <- | v | -> | DEL | BSPC |
|
||||
// | | UNDO | CUT | COPY | PASTE | | | | | | |> | <|<| | |>|> | | |
|
||||
// | | | | | | | | | |
|
||||
bindings = <
|
||||
&bt BT_CLR &bt BT_SEL 0 &bt BT_SEL 1 &bt BT_SEL 2 &bt BT_SEL 3 &bt BT_SEL 4 &out OUT_TOG &out OUT_USB &out OUT_BLE &trans &reset &bootloader
|
||||
&trans &kp INS &kp PSCRN &kp K_CMENU &reset &trans &kp PG_UP &trans &kp UP &trans &trans &trans
|
||||
&trans &kp LALT &kp LCTRL &kp LSHFT &bootloader &kp CLCK &trans &trans &kp PG_DN &kp LEFT &kp DOWN &kp RIGHT &kp DEL &kp BSPC
|
||||
&trans &kp K_UNDO &kp K_CUT &kp K_COPY &kp K_PASTE &trans &trans &trans &trans &kp C_PP &kp C_PREV &kp C_NEXT &trans &trans
|
||||
&trans &trans &trans &trans &trans &trans &trans &trans
|
||||
>;
|
||||
|
||||
sensor-bindings = <&inc_dec_kp C_VOL_DN C_VOL_UP &inc_dec_kp PG_UP PG_DN>;
|
||||
};
|
||||
};
|
||||
};
|
14
app/boards/shields/lotus58/lotus58.zmk.yml
Normal file
14
app/boards/shields/lotus58/lotus58.zmk.yml
Normal file
|
@ -0,0 +1,14 @@
|
|||
file_format: "1"
|
||||
id: lotus58
|
||||
name: Lotus58
|
||||
type: shield
|
||||
url: https://github.com/TweetyDaBird/Lotus58
|
||||
requires: [pro_micro]
|
||||
exposes: [i2c_oled]
|
||||
features:
|
||||
- keys
|
||||
- display
|
||||
- encoder
|
||||
siblings:
|
||||
- lotus58_left
|
||||
- lotus58_right
|
22
app/boards/shields/lotus58/lotus58_left.overlay
Normal file
22
app/boards/shields/lotus58/lotus58_left.overlay
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "lotus58.dtsi"
|
||||
|
||||
&kscan0 {
|
||||
col-gpios
|
||||
= <&pro_micro 15 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 16 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 14 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 10 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 19 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
};
|
||||
|
||||
&left_encoder {
|
||||
status = "okay";
|
||||
};
|
26
app/boards/shields/lotus58/lotus58_right.overlay
Normal file
26
app/boards/shields/lotus58/lotus58_right.overlay
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "lotus58.dtsi"
|
||||
|
||||
&default_transform {
|
||||
col-offset = <6>;
|
||||
};
|
||||
|
||||
&kscan0 {
|
||||
col-gpios
|
||||
= <&pro_micro 19 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 18 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 10 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 14 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 16 GPIO_ACTIVE_HIGH>
|
||||
, <&pro_micro 15 GPIO_ACTIVE_HIGH>
|
||||
;
|
||||
};
|
||||
|
||||
&right_encoder {
|
||||
status = "okay";
|
||||
};
|
30
app/core-coverage.yml
Normal file
30
app/core-coverage.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
board:
|
||||
- nice_nano_v2
|
||||
- nrfmicro_13
|
||||
- proton_c
|
||||
shield:
|
||||
- corne_left
|
||||
- corne_right
|
||||
- romac
|
||||
- settings_reset
|
||||
- tidbit
|
||||
include:
|
||||
- board: bdn9_rev2
|
||||
- board: nice60
|
||||
- board: nrf52840_m2
|
||||
shield: m60
|
||||
- board: planck_rev6
|
||||
- board: proton_c
|
||||
shield: clueboard_california
|
||||
- board: nice_nano_v2
|
||||
shield: kyria_left
|
||||
cmake-args: "-DCONFIG_ZMK_DISPLAY=y"
|
||||
nickname: "display"
|
||||
- board: nice_nano_v2
|
||||
shield: kyria_right
|
||||
cmake-args: "-DCONFIG_ZMK_DISPLAY=y"
|
||||
nickname: "display"
|
||||
- board: nice_nano
|
||||
shield: romac_plus
|
||||
cmake-args: "-DCONFIG_ZMK_RGB_UNDERGLOW=y -DCONFIG_WS2812_STRIP=y"
|
||||
nickname: "underglow"
|
|
@ -15,3 +15,5 @@
|
|||
#include <behaviors/ext_power.dtsi>
|
||||
#include <behaviors/outputs.dtsi>
|
||||
#include <behaviors/caps_word.dtsi>
|
||||
#include <behaviors/key_repeat.dtsi>
|
||||
#include <behaviors/backlight.dtsi>
|
||||
|
|
15
app/dts/behaviors/backlight.dtsi
Normal file
15
app/dts/behaviors/backlight.dtsi
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ bl: behavior_backlight {
|
||||
compatible = "zmk,behavior-backlight";
|
||||
label = "BCKLGHT";
|
||||
#binding-cells = <2>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ ext_power: behavior_ext_power {
|
||||
ext_power: behavior_ext_power {
|
||||
compatible = "zmk,behavior-ext-power";
|
||||
label = "EXT_POWER_BEHAVIOR";
|
||||
label = "EXTPOWER";
|
||||
#binding-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
|
19
app/dts/behaviors/key_repeat.dtsi
Normal file
19
app/dts/behaviors/key_repeat.dtsi
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ key_repeat: behavior_key_repeat {
|
||||
compatible = "zmk,behavior-key-repeat";
|
||||
label = "KEY_REPEAT";
|
||||
#binding-cells = <0>;
|
||||
usage-pages = <HID_USAGE_KEY>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -8,15 +8,15 @@
|
|||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ reset: behavior_reset {
|
||||
reset: behavior_reset {
|
||||
compatible = "zmk,behavior-reset";
|
||||
label = "RESET";
|
||||
#binding-cells = <0>;
|
||||
};
|
||||
|
||||
/omit-if-no-ref/ bootloader: behavior_reset_dfu {
|
||||
bootloader: behavior_reset_dfu {
|
||||
compatible = "zmk,behavior-reset";
|
||||
label = "BOOTLOADER_RESET";
|
||||
label = "BOOTLOAD";
|
||||
type = <RST_UF2>;
|
||||
#binding-cells = <0>;
|
||||
};
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ rgb_ug: behavior_rgb_underglow {
|
||||
rgb_ug: behavior_rgb_underglow {
|
||||
compatible = "zmk,behavior-rgb-underglow";
|
||||
label = "RGB_UNDERGLOW";
|
||||
label = "RGB_UG";
|
||||
#binding-cells = <2>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#binding-cells = <1>;
|
||||
release-after-ms = <1000>;
|
||||
bindings = <&kp>;
|
||||
ignore-modifiers;
|
||||
};
|
||||
/omit-if-no-ref/ sl: behavior_sticky_layer {
|
||||
compatible = "zmk,behavior-sticky-key";
|
||||
|
|
8
app/dts/bindings/behaviors/zmk,behavior-backlight.yaml
Normal file
8
app/dts/bindings/behaviors/zmk,behavior-backlight.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Backlight behavior
|
||||
|
||||
compatible: "zmk,behavior-backlight"
|
||||
|
||||
include: two_param.yaml
|
13
app/dts/bindings/behaviors/zmk,behavior-key-repeat.yaml
Normal file
13
app/dts/bindings/behaviors/zmk,behavior-key-repeat.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Copyright (c) 2021 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Key repeat behavior
|
||||
|
||||
compatible: "zmk,behavior-key-repeat"
|
||||
|
||||
include: zero_param.yaml
|
||||
|
||||
properties:
|
||||
usage-pages:
|
||||
type: array
|
||||
required: true
|
|
@ -15,3 +15,5 @@ properties:
|
|||
type: int
|
||||
quick-release:
|
||||
type: boolean
|
||||
ignore-modifiers:
|
||||
type: boolean
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/util.h>
|
||||
#include <string.h>
|
||||
#include <device.h>
|
||||
#include <zmk/keys.h>
|
||||
#include <zmk/behavior.h>
|
||||
|
@ -26,7 +28,14 @@ typedef int (*behavior_sensor_keymap_binding_callback_t)(struct zmk_behavior_bin
|
|||
const struct device *sensor,
|
||||
int64_t timestamp);
|
||||
|
||||
enum behavior_locality {
|
||||
BEHAVIOR_LOCALITY_CENTRAL,
|
||||
BEHAVIOR_LOCALITY_EVENT_SOURCE,
|
||||
BEHAVIOR_LOCALITY_GLOBAL
|
||||
};
|
||||
|
||||
__subsystem struct behavior_driver_api {
|
||||
enum behavior_locality locality;
|
||||
behavior_keymap_binding_callback_t binding_convert_central_state_dependent_params;
|
||||
behavior_keymap_binding_callback_t binding_pressed;
|
||||
behavior_keymap_binding_callback_t binding_released;
|
||||
|
@ -60,6 +69,28 @@ static inline int z_impl_behavior_keymap_binding_convert_central_state_dependent
|
|||
return api->binding_convert_central_state_dependent_params(binding, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine where the behavior should be run
|
||||
* @param behavior Pointer to the device structure for the driver instance.
|
||||
*
|
||||
* @retval Zero if successful.
|
||||
* @retval Negative errno code if failure.
|
||||
*/
|
||||
__syscall int behavior_get_locality(const struct device *behavior,
|
||||
enum behavior_locality *locality);
|
||||
|
||||
static inline int z_impl_behavior_get_locality(const struct device *behavior,
|
||||
enum behavior_locality *locality) {
|
||||
if (behavior == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)behavior->api;
|
||||
*locality = api->locality;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the keymap binding being pressed
|
||||
* @param dev Pointer to the device structure for the driver instance.
|
||||
|
@ -75,6 +106,11 @@ __syscall int behavior_keymap_binding_pressed(struct zmk_behavior_binding *bindi
|
|||
static inline int z_impl_behavior_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
|
||||
if (dev == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api;
|
||||
|
||||
if (api->binding_pressed == NULL) {
|
||||
|
@ -98,6 +134,11 @@ __syscall int behavior_keymap_binding_released(struct zmk_behavior_binding *bind
|
|||
static inline int z_impl_behavior_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
|
||||
if (dev == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api;
|
||||
|
||||
if (api->binding_released == NULL) {
|
||||
|
@ -125,6 +166,11 @@ static inline int
|
|||
z_impl_behavior_sensor_keymap_binding_triggered(struct zmk_behavior_binding *binding,
|
||||
const struct device *sensor, int64_t timestamp) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
|
||||
if (dev == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct behavior_driver_api *api = (const struct behavior_driver_api *)dev->api;
|
||||
|
||||
if (api->sensor_binding_triggered == NULL) {
|
||||
|
|
21
app/include/dt-bindings/zmk/backlight.h
Normal file
21
app/include/dt-bindings/zmk/backlight.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define BL_ON_CMD 0
|
||||
#define BL_OFF_CMD 1
|
||||
#define BL_TOG_CMD 2
|
||||
#define BL_INC_CMD 3
|
||||
#define BL_DEC_CMD 4
|
||||
#define BL_CYCLE_CMD 5
|
||||
#define BL_SET_CMD 6
|
||||
|
||||
#define BL_ON BL_ON_CMD 0
|
||||
#define BL_OFF BL_OFF_CMD 0
|
||||
#define BL_TOG BL_TOG_CMD 0
|
||||
#define BL_INC BL_INC_CMD 0
|
||||
#define BL_DEC BL_DEC_CMD 0
|
||||
#define BL_CYCLE BL_CYCLE_CMD 0
|
||||
#define BL_SET BL_SET_CMD
|
|
@ -17,7 +17,8 @@
|
|||
#define RGB_SPD_CMD 10
|
||||
#define RGB_EFF_CMD 11
|
||||
#define RGB_EFR_CMD 12
|
||||
#define RGB_COLOR_HSB_CMD 13
|
||||
#define RGB_EFS_CMD 13
|
||||
#define RGB_COLOR_HSB_CMD 14
|
||||
|
||||
#define RGB_TOG RGB_TOG_CMD 0
|
||||
#define RGB_ON RGB_ON_CMD 0
|
||||
|
|
17
app/include/zmk/backlight.h
Normal file
17
app/include/zmk/backlight.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
int zmk_backlight_on();
|
||||
int zmk_backlight_off();
|
||||
int zmk_backlight_toggle();
|
||||
bool zmk_backlight_is_on();
|
||||
|
||||
int zmk_backlight_set_brt(uint8_t brightness);
|
||||
uint8_t zmk_backlight_get_brt();
|
||||
uint8_t zmk_backlight_calc_brt(int direction);
|
||||
uint8_t zmk_backlight_calc_brt_cycle();
|
|
@ -9,6 +9,17 @@
|
|||
#include <zmk/keys.h>
|
||||
#include <zmk/ble/profile.h>
|
||||
|
||||
#define ZMK_BLE_IS_CENTRAL \
|
||||
(IS_ENABLED(CONFIG_ZMK_SPLIT) && IS_ENABLED(CONFIG_ZMK_BLE) && \
|
||||
IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
#define ZMK_BLE_PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
#define ZMK_BLE_SPLIT_PERIPHERAL_COUNT 1
|
||||
#else
|
||||
#define ZMK_BLE_PROFILE_COUNT CONFIG_BT_MAX_PAIRED
|
||||
#endif
|
||||
|
||||
int zmk_ble_clear_bonds();
|
||||
int zmk_ble_prof_next();
|
||||
int zmk_ble_prof_prev();
|
||||
|
@ -21,7 +32,6 @@ bool zmk_ble_active_profile_is_connected();
|
|||
char *zmk_ble_active_profile_name();
|
||||
|
||||
int zmk_ble_unpair_all();
|
||||
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event);
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
void zmk_ble_set_peripheral_addr(bt_addr_le_t *addr);
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
|
||||
#include <zephyr.h>
|
||||
#include <zmk/event_manager.h>
|
||||
|
||||
#define ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL UINT8_MAX
|
||||
|
||||
struct zmk_position_state_changed {
|
||||
uint8_t source;
|
||||
uint32_t position;
|
||||
bool state;
|
||||
int64_t timestamp;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
|
||||
typedef uint32_t zmk_keymap_layers_state_t;
|
||||
|
||||
uint8_t zmk_keymap_layer_default();
|
||||
|
@ -18,7 +20,8 @@ int zmk_keymap_layer_toggle(uint8_t layer);
|
|||
int zmk_keymap_layer_to(uint8_t layer);
|
||||
const char *zmk_keymap_layer_label(uint8_t layer);
|
||||
|
||||
int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp);
|
||||
int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pressed,
|
||||
int64_t timestamp);
|
||||
|
||||
#define ZMK_KEYMAP_EXTRACT_BINDING(idx, drv_inst) \
|
||||
{ \
|
||||
|
|
|
@ -17,6 +17,8 @@ int zmk_rgb_underglow_get_state(bool *state);
|
|||
int zmk_rgb_underglow_on();
|
||||
int zmk_rgb_underglow_off();
|
||||
int zmk_rgb_underglow_cycle_effect(int direction);
|
||||
int zmk_rgb_underglow_calc_effect(int direction);
|
||||
int zmk_rgb_underglow_select_effect(int effect);
|
||||
struct zmk_led_hsb zmk_rgb_underglow_calc_hue(int direction);
|
||||
struct zmk_led_hsb zmk_rgb_underglow_calc_sat(int direction);
|
||||
struct zmk_led_hsb zmk_rgb_underglow_calc_brt(int direction);
|
||||
|
|
8
app/include/zmk/split/bluetooth/central.h
Normal file
8
app/include/zmk/split/bluetooth/central.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <bluetooth/addr.h>
|
||||
#include <zmk/behavior.h>
|
||||
|
||||
int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event, bool state);
|
|
@ -6,5 +6,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN 9
|
||||
|
||||
struct zmk_split_run_behavior_data {
|
||||
uint8_t position;
|
||||
uint8_t state;
|
||||
uint32_t param1;
|
||||
uint32_t param2;
|
||||
} __packed;
|
||||
|
||||
struct zmk_split_run_behavior_payload {
|
||||
struct zmk_split_run_behavior_data data;
|
||||
char behavior_dev[ZMK_SPLIT_RUN_BEHAVIOR_DEV_LEN];
|
||||
} __packed;
|
||||
|
||||
int zmk_split_bt_position_pressed(uint8_t position);
|
||||
int zmk_split_bt_position_released(uint8_t position);
|
|
@ -15,3 +15,4 @@
|
|||
#define ZMK_BT_SPLIT_UUID(num) BT_UUID_128_ENCODE(num, 0x0096, 0x7107, 0xc967, 0xc5cfb1c2482a)
|
||||
#define ZMK_SPLIT_BT_SERVICE_UUID ZMK_BT_SPLIT_UUID(0x00000000)
|
||||
#define ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID ZMK_BT_SPLIT_UUID(0x00000001)
|
||||
#define ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID ZMK_BT_SPLIT_UUID(0x00000002)
|
||||
|
|
19
app/include/zmk/stdlib.h
Normal file
19
app/include/zmk/stdlib.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h> /* for size_t */
|
||||
|
||||
/*
|
||||
* ANSI C version of strlcpy
|
||||
* Based on the NetBSD strlcpy man page.
|
||||
*
|
||||
* Nathan Myers <ncm-nospam@cantrip.org>, 2003/06/03
|
||||
* Placed in the public domain.
|
||||
*/
|
||||
|
||||
size_t strlcpy(char *dst, const char *src, size_t size);
|
189
app/src/backlight.c
Normal file
189
app/src/backlight.c
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <device.h>
|
||||
#include <devicetree.h>
|
||||
#include <init.h>
|
||||
#include <kernel.h>
|
||||
|
||||
#include <drivers/led.h>
|
||||
#include <logging/log.h>
|
||||
#include <settings/settings.h>
|
||||
|
||||
#include <zmk/activity.h>
|
||||
#include <zmk/backlight.h>
|
||||
#include <zmk/usb.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/activity_state_changed.h>
|
||||
#include <zmk/events/usb_conn_state_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
BUILD_ASSERT(DT_HAS_CHOSEN(zmk_backlight),
|
||||
"CONFIG_ZMK_BACKLIGHT is enabled but no zmk,backlight chosen node found");
|
||||
|
||||
static const struct device *const backlight_dev = DEVICE_DT_GET(DT_CHOSEN(zmk_backlight));
|
||||
|
||||
#define CHILD_COUNT(...) +1
|
||||
#define DT_NUM_CHILD(node_id) (DT_FOREACH_CHILD(node_id, CHILD_COUNT))
|
||||
|
||||
#define BACKLIGHT_NUM_LEDS (DT_NUM_CHILD(DT_CHOSEN(zmk_backlight)))
|
||||
|
||||
#define BRT_MAX 100
|
||||
|
||||
struct backlight_state {
|
||||
uint8_t brightness;
|
||||
bool on;
|
||||
};
|
||||
|
||||
static struct backlight_state state = {.brightness = CONFIG_ZMK_BACKLIGHT_BRT_START,
|
||||
.on = IS_ENABLED(CONFIG_ZMK_BACKLIGHT_ON_START)};
|
||||
|
||||
static int zmk_backlight_update() {
|
||||
uint8_t brt = zmk_backlight_get_brt();
|
||||
LOG_DBG("Update backlight brightness: %d%%", brt);
|
||||
|
||||
for (int i = 0; i < BACKLIGHT_NUM_LEDS; i++) {
|
||||
int rc = led_set_brightness(backlight_dev, i, brt);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to update backlight LED %d: %d", i, rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
static int backlight_settings_load_cb(const char *name, size_t len, settings_read_cb read_cb,
|
||||
void *cb_arg, void *param) {
|
||||
const char *next;
|
||||
if (settings_name_steq(name, "state", &next) && !next) {
|
||||
if (len != sizeof(state)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int rc = read_cb(cb_arg, &state, sizeof(state));
|
||||
return MIN(rc, 0);
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static void backlight_save_work_handler(struct k_work *work) {
|
||||
settings_save_one("backlight/state", &state, sizeof(state));
|
||||
}
|
||||
|
||||
static K_DELAYED_WORK_DEFINE(backlight_save_work, backlight_save_work_handler);
|
||||
#endif
|
||||
|
||||
static int zmk_backlight_init(const struct device *_arg) {
|
||||
if (!device_is_ready(backlight_dev)) {
|
||||
LOG_ERR("Backlight device \"%s\" is not ready", backlight_dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
settings_subsys_init();
|
||||
int rc = settings_load_subtree_direct("backlight", backlight_settings_load_cb, NULL);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to load backlight settings: %d", rc);
|
||||
}
|
||||
#endif
|
||||
|
||||
return zmk_backlight_update();
|
||||
}
|
||||
|
||||
static int zmk_backlight_update_and_save() {
|
||||
int rc = zmk_backlight_update();
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_SETTINGS)
|
||||
k_delayed_work_cancel(&backlight_save_work);
|
||||
return k_delayed_work_submit(&backlight_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int zmk_backlight_on() {
|
||||
state.brightness = MAX(state.brightness, CONFIG_ZMK_BACKLIGHT_BRT_STEP);
|
||||
state.on = true;
|
||||
return zmk_backlight_update_and_save();
|
||||
}
|
||||
|
||||
int zmk_backlight_off() {
|
||||
state.on = false;
|
||||
return zmk_backlight_update_and_save();
|
||||
}
|
||||
|
||||
int zmk_backlight_toggle() { return state.on ? zmk_backlight_off() : zmk_backlight_on(); }
|
||||
|
||||
bool zmk_backlight_is_on() { return state.on; }
|
||||
|
||||
int zmk_backlight_set_brt(uint8_t brightness) {
|
||||
state.brightness = MIN(brightness, BRT_MAX);
|
||||
state.on = (state.brightness > 0);
|
||||
return zmk_backlight_update_and_save();
|
||||
}
|
||||
|
||||
uint8_t zmk_backlight_get_brt() { return state.on ? state.brightness : 0; }
|
||||
|
||||
uint8_t zmk_backlight_calc_brt(int direction) {
|
||||
int brt = state.brightness + (direction * CONFIG_ZMK_BACKLIGHT_BRT_STEP);
|
||||
return CLAMP(brt, 0, BRT_MAX);
|
||||
}
|
||||
|
||||
uint8_t zmk_backlight_calc_brt_cycle() {
|
||||
if (state.brightness == BRT_MAX) {
|
||||
return 0;
|
||||
} else {
|
||||
return zmk_backlight_calc_brt(1);
|
||||
}
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) || IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||
static int backlight_auto_state(bool *prev_state, bool new_state) {
|
||||
if (state.on == new_state) {
|
||||
return 0;
|
||||
}
|
||||
state.on = new_state && *prev_state;
|
||||
*prev_state = !new_state;
|
||||
return zmk_backlight_update();
|
||||
}
|
||||
|
||||
static int backlight_event_listener(const zmk_event_t *eh) {
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||
if (as_zmk_activity_state_changed(eh)) {
|
||||
static bool prev_state = false;
|
||||
return backlight_auto_state(&prev_state, zmk_activity_get_state() == ZMK_ACTIVITY_ACTIVE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||
if (as_zmk_usb_conn_state_changed(eh)) {
|
||||
static bool prev_state = false;
|
||||
return backlight_auto_state(&prev_state, zmk_usb_is_powered());
|
||||
}
|
||||
#endif
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(backlight, backlight_event_listener);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE) ||
|
||||
// IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_IDLE)
|
||||
ZMK_SUBSCRIPTION(backlight, zmk_activity_state_changed);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_BACKLIGHT_AUTO_OFF_USB)
|
||||
ZMK_SUBSCRIPTION(backlight, zmk_usb_conn_state_changed);
|
||||
#endif
|
||||
|
||||
SYS_INIT(zmk_backlight_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
97
app/src/behaviors/behavior_backlight.c
Normal file
97
app/src/behaviors/behavior_backlight.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_backlight
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include <dt-bindings/zmk/backlight.h>
|
||||
#include <zmk/backlight.h>
|
||||
#include <zmk/keymap.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
static int behavior_backlight_init(const struct device *dev) { return 0; }
|
||||
|
||||
static int
|
||||
on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
switch (binding->param1) {
|
||||
case BL_TOG_CMD:
|
||||
binding->param1 = zmk_backlight_is_on() ? BL_OFF_CMD : BL_ON_CMD;
|
||||
break;
|
||||
case BL_INC_CMD:
|
||||
binding->param1 = BL_SET_CMD;
|
||||
binding->param2 = zmk_backlight_calc_brt(1);
|
||||
break;
|
||||
case BL_DEC_CMD:
|
||||
binding->param1 = BL_SET_CMD;
|
||||
binding->param2 = zmk_backlight_calc_brt(-1);
|
||||
break;
|
||||
case BL_CYCLE_CMD:
|
||||
binding->param1 = BL_SET_CMD;
|
||||
binding->param2 = zmk_backlight_calc_brt_cycle();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG_DBG("Backlight relative to absolute (%d/%d)", binding->param1, binding->param2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
switch (binding->param1) {
|
||||
case BL_ON_CMD:
|
||||
return zmk_backlight_on();
|
||||
case BL_OFF_CMD:
|
||||
return zmk_backlight_off();
|
||||
case BL_TOG_CMD:
|
||||
return zmk_backlight_toggle();
|
||||
case BL_INC_CMD: {
|
||||
uint8_t brt = zmk_backlight_calc_brt(1);
|
||||
return zmk_backlight_set_brt(brt);
|
||||
}
|
||||
case BL_DEC_CMD: {
|
||||
uint8_t brt = zmk_backlight_calc_brt(-1);
|
||||
return zmk_backlight_set_brt(brt);
|
||||
}
|
||||
case BL_CYCLE_CMD: {
|
||||
uint8_t brt = zmk_backlight_calc_brt_cycle();
|
||||
return zmk_backlight_set_brt(brt);
|
||||
}
|
||||
case BL_SET_CMD:
|
||||
return zmk_backlight_set_brt(binding->param2);
|
||||
default:
|
||||
LOG_ERR("Unknown backlight command: %d", binding->param1);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_backlight_driver_api = {
|
||||
.binding_convert_central_state_dependent_params =
|
||||
on_keymap_binding_convert_central_state_dependent_params,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, behavior_backlight_init, device_pm_control_nop, NULL, NULL, APPLICATION,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_backlight_driver_api);
|
||||
|
||||
#endif /* DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT) */
|
|
@ -71,6 +71,7 @@ static const struct behavior_driver_api behavior_ext_power_driver_api = {
|
|||
on_keymap_binding_convert_central_state_dependent_params,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, behavior_ext_power_init, device_pm_control_nop, NULL, NULL, APPLICATION,
|
||||
|
|
126
app/src/behaviors/behavior_key_repeat.c
Normal file
126
app/src/behaviors/behavior_key_repeat.c
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_key_repeat
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <logging/log.h>
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/hid.h>
|
||||
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/keycode_state_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
struct behavior_key_repeat_config {
|
||||
uint8_t index;
|
||||
uint8_t usage_pages_count;
|
||||
uint16_t usage_pages[];
|
||||
};
|
||||
|
||||
struct behavior_key_repeat_data {
|
||||
struct zmk_keycode_state_changed last_keycode_pressed;
|
||||
struct zmk_keycode_state_changed current_keycode_pressed;
|
||||
};
|
||||
|
||||
static int on_key_repeat_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
struct behavior_key_repeat_data *data = dev->data;
|
||||
|
||||
if (data->last_keycode_pressed.usage_page == 0) {
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
memcpy(&data->current_keycode_pressed, &data->last_keycode_pressed,
|
||||
sizeof(struct zmk_keycode_state_changed));
|
||||
data->current_keycode_pressed.timestamp = k_uptime_get();
|
||||
|
||||
ZMK_EVENT_RAISE(new_zmk_keycode_state_changed(data->current_keycode_pressed));
|
||||
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static int on_key_repeat_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *dev = device_get_binding(binding->behavior_dev);
|
||||
struct behavior_key_repeat_data *data = dev->data;
|
||||
|
||||
if (data->current_keycode_pressed.usage_page == 0) {
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
data->current_keycode_pressed.timestamp = k_uptime_get();
|
||||
data->current_keycode_pressed.state = false;
|
||||
|
||||
ZMK_EVENT_RAISE(new_zmk_keycode_state_changed(data->current_keycode_pressed));
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_key_repeat_driver_api = {
|
||||
.binding_pressed = on_key_repeat_binding_pressed,
|
||||
.binding_released = on_key_repeat_binding_released,
|
||||
};
|
||||
|
||||
static int key_repeat_keycode_state_changed_listener(const zmk_event_t *eh);
|
||||
|
||||
ZMK_LISTENER(behavior_key_repeat, key_repeat_keycode_state_changed_listener);
|
||||
ZMK_SUBSCRIPTION(behavior_key_repeat, zmk_keycode_state_changed);
|
||||
|
||||
static const struct device *devs[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)];
|
||||
|
||||
static int key_repeat_keycode_state_changed_listener(const zmk_event_t *eh) {
|
||||
struct zmk_keycode_state_changed *ev = as_zmk_keycode_state_changed(eh);
|
||||
if (ev == NULL || !ev->state) {
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT); i++) {
|
||||
const struct device *dev = devs[i];
|
||||
if (dev == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct behavior_key_repeat_data *data = dev->data;
|
||||
const struct behavior_key_repeat_config *config = dev->config;
|
||||
|
||||
for (int u = 0; u < config->usage_pages_count; u++) {
|
||||
if (config->usage_pages[u] == ev->usage_page) {
|
||||
memcpy(&data->last_keycode_pressed, ev, sizeof(struct zmk_keycode_state_changed));
|
||||
data->last_keycode_pressed.implicit_modifiers |= zmk_hid_get_explicit_mods();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
static int behavior_key_repeat_init(const struct device *dev) {
|
||||
const struct behavior_key_repeat_config *config = dev->config;
|
||||
devs[config->index] = dev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define KR_INST(n) \
|
||||
static struct behavior_key_repeat_data behavior_key_repeat_data_##n = {}; \
|
||||
static struct behavior_key_repeat_config behavior_key_repeat_config_##n = { \
|
||||
.index = n, \
|
||||
.usage_pages = DT_INST_PROP(n, usage_pages), \
|
||||
.usage_pages_count = DT_INST_PROP_LEN(n, usage_pages), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, behavior_key_repeat_init, device_pm_control_nop, \
|
||||
&behavior_key_repeat_data_##n, &behavior_key_repeat_config_##n, \
|
||||
APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_key_repeat_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(KR_INST)
|
||||
|
||||
#endif
|
|
@ -36,6 +36,7 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|||
|
||||
static const struct behavior_driver_api behavior_reset_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.locality = BEHAVIOR_LOCALITY_EVENT_SOURCE,
|
||||
};
|
||||
|
||||
#define RST_INST(n) \
|
||||
|
|
|
@ -77,6 +77,16 @@ on_keymap_binding_convert_central_state_dependent_params(struct zmk_behavior_bin
|
|||
binding->param2 = RGB_COLOR_HSB_VAL(color.h, color.s, color.b);
|
||||
break;
|
||||
}
|
||||
case RGB_EFR_CMD: {
|
||||
binding->param1 = RGB_EFS_CMD;
|
||||
binding->param2 = zmk_rgb_underglow_calc_effect(-1);
|
||||
break;
|
||||
}
|
||||
case RGB_EFF_CMD: {
|
||||
binding->param1 = RGB_EFS_CMD;
|
||||
binding->param2 = zmk_rgb_underglow_calc_effect(1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -111,6 +121,8 @@ static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
|||
return zmk_rgb_underglow_change_spd(1);
|
||||
case RGB_SPD_CMD:
|
||||
return zmk_rgb_underglow_change_spd(-1);
|
||||
case RGB_EFS_CMD:
|
||||
return zmk_rgb_underglow_select_effect(binding->param2);
|
||||
case RGB_EFF_CMD:
|
||||
return zmk_rgb_underglow_cycle_effect(1);
|
||||
case RGB_EFR_CMD:
|
||||
|
@ -134,6 +146,7 @@ static const struct behavior_driver_api behavior_rgb_underglow_driver_api = {
|
|||
on_keymap_binding_convert_central_state_dependent_params,
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
.locality = BEHAVIOR_LOCALITY_GLOBAL,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, behavior_rgb_underglow_init, device_pm_control_nop, NULL, NULL,
|
||||
|
|
|
@ -31,6 +31,7 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
struct behavior_sticky_key_config {
|
||||
uint32_t release_after_ms;
|
||||
bool quick_release;
|
||||
bool ignore_modifiers;
|
||||
struct zmk_behavior_binding behavior;
|
||||
};
|
||||
|
||||
|
@ -201,7 +202,7 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// If events were queued, the timer event may be queued late or not at all.
|
||||
// If this event was queued, the timer may be triggered late or not at all.
|
||||
// Release the sticky key if the timer should've run out in the meantime.
|
||||
if (sticky_key->release_at != 0 && ev->timestamp > sticky_key->release_at) {
|
||||
stop_timer(sticky_key);
|
||||
|
@ -210,6 +211,11 @@ static int sticky_key_keycode_state_changed_listener(const zmk_event_t *eh) {
|
|||
}
|
||||
|
||||
if (ev->state) { // key down
|
||||
if (sticky_key->config->ignore_modifiers && is_mod(ev->usage_page, ev->keycode)) {
|
||||
// ignore modifier key press so we can stack sticky keys and combine with other
|
||||
// modifiers
|
||||
continue;
|
||||
}
|
||||
if (sticky_key->modified_key_usage_page != 0 || sticky_key->modified_key_keycode != 0) {
|
||||
// this sticky key is already in use for a keycode
|
||||
continue;
|
||||
|
@ -270,6 +276,7 @@ static struct behavior_sticky_key_data behavior_sticky_key_data;
|
|||
static struct behavior_sticky_key_config behavior_sticky_key_config_##n = { \
|
||||
.behavior = ZMK_KEYMAP_EXTRACT_BINDING(0, DT_DRV_INST(n)), \
|
||||
.release_after_ms = DT_INST_PROP(n, release_after_ms), \
|
||||
.ignore_modifiers = DT_INST_PROP(n, ignore_modifiers), \
|
||||
.quick_release = DT_INST_PROP(n, quick_release), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, behavior_sticky_key_init, device_pm_control_nop, \
|
||||
|
|
111
app/src/ble.c
111
app/src/ble.c
|
@ -36,10 +36,24 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/ble_active_profile_changed.h>
|
||||
|
||||
#define IS_HOST_PERIPHERAL \
|
||||
(!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
#define IS_SPLIT_PERIPHERAL \
|
||||
(IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
|
||||
#define DO_PASSKEY_ENTRY (IS_ENABLED(CONFIG_ZMK_BLE_PASSKEY_ENTRY) && !IS_SPLIT_PERIPHERAL)
|
||||
|
||||
#if DO_PASSKEY_ENTRY
|
||||
#include <zmk/events/keycode_state_changed.h>
|
||||
|
||||
#define PASSKEY_DIGITS 6
|
||||
|
||||
static struct bt_conn *auth_passkey_entry_conn;
|
||||
static uint8_t passkey_entries[6] = {0, 0, 0, 0, 0, 0};
|
||||
static uint8_t passkey_entries[PASSKEY_DIGITS] = {};
|
||||
static uint8_t passkey_digit = 0;
|
||||
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL)
|
||||
#define PROFILE_COUNT (CONFIG_BT_MAX_PAIRED - 1)
|
||||
#else
|
||||
|
@ -58,7 +72,7 @@ enum advertising_type {
|
|||
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
|
||||
static struct zmk_ble_profile profiles[PROFILE_COUNT];
|
||||
static struct zmk_ble_profile profiles[ZMK_BLE_PROFILE_COUNT];
|
||||
static uint8_t active_profile;
|
||||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
|
@ -66,11 +80,6 @@ static uint8_t active_profile;
|
|||
|
||||
BUILD_ASSERT(DEVICE_NAME_LEN <= 16, "ERROR: BLE device name is too long. Max length: 16");
|
||||
|
||||
#define IS_HOST_PERIPHERAL \
|
||||
(!IS_ENABLED(CONFIG_ZMK_SPLIT) || IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
#define IS_SPLIT_PERIPHERAL \
|
||||
(IS_ENABLED(CONFIG_ZMK_SPLIT) && !IS_ENABLED(CONFIG_ZMK_SPLIT_BLE_ROLE_CENTRAL))
|
||||
|
||||
static const struct bt_data zmk_ble_ad[] = {
|
||||
#if IS_HOST_PERIPHERAL
|
||||
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
|
||||
|
@ -251,7 +260,7 @@ static int ble_save_profile() {
|
|||
}
|
||||
|
||||
int zmk_ble_prof_select(uint8_t index) {
|
||||
if (index >= PROFILE_COUNT) {
|
||||
if (index >= ZMK_BLE_PROFILE_COUNT) {
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
|
@ -272,12 +281,13 @@ int zmk_ble_prof_select(uint8_t index) {
|
|||
|
||||
int zmk_ble_prof_next() {
|
||||
LOG_DBG("");
|
||||
return zmk_ble_prof_select((active_profile + 1) % PROFILE_COUNT);
|
||||
return zmk_ble_prof_select((active_profile + 1) % ZMK_BLE_PROFILE_COUNT);
|
||||
};
|
||||
|
||||
int zmk_ble_prof_prev() {
|
||||
LOG_DBG("");
|
||||
return zmk_ble_prof_select((active_profile + PROFILE_COUNT - 1) % PROFILE_COUNT);
|
||||
return zmk_ble_prof_select((active_profile + ZMK_BLE_PROFILE_COUNT - 1) %
|
||||
ZMK_BLE_PROFILE_COUNT);
|
||||
};
|
||||
|
||||
bt_addr_le_t *zmk_ble_active_profile_addr() { return &profiles[active_profile].peer; }
|
||||
|
@ -315,8 +325,9 @@ static int ble_profiles_handle_set(const char *name, size_t len, settings_read_c
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (idx >= PROFILE_COUNT) {
|
||||
LOG_WRN("Profile address for index %d is larger than max of %d", idx, PROFILE_COUNT);
|
||||
if (idx >= ZMK_BLE_PROFILE_COUNT) {
|
||||
LOG_WRN("Profile address for index %d is larger than max of %d", idx,
|
||||
ZMK_BLE_PROFILE_COUNT);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -456,7 +467,7 @@ static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey) {
|
|||
}
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
|
||||
#if DO_PASSKEY_ENTRY
|
||||
|
||||
static void auth_passkey_entry(struct bt_conn *conn) {
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
@ -464,6 +475,7 @@ static void auth_passkey_entry(struct bt_conn *conn) {
|
|||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
LOG_DBG("Passkey entry requested for %s", log_strdup(addr));
|
||||
passkey_digit = 0;
|
||||
auth_passkey_entry_conn = bt_conn_ref(conn);
|
||||
}
|
||||
|
||||
|
@ -474,12 +486,14 @@ static void auth_cancel(struct bt_conn *conn) {
|
|||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
#if DO_PASSKEY_ENTRY
|
||||
if (auth_passkey_entry_conn) {
|
||||
bt_conn_unref(auth_passkey_entry_conn);
|
||||
auth_passkey_entry_conn = NULL;
|
||||
}
|
||||
|
||||
passkey_digit = 0;
|
||||
#endif
|
||||
|
||||
LOG_DBG("Pairing cancelled: %s", log_strdup(addr));
|
||||
}
|
||||
|
@ -532,7 +546,7 @@ static struct bt_conn_auth_cb zmk_ble_auth_cb_display = {
|
|||
.pairing_complete = auth_pairing_complete,
|
||||
// .passkey_display = auth_passkey_display,
|
||||
|
||||
#ifdef CONFIG_ZMK_BLE_PASSKEY_ENTRY
|
||||
#if DO_PASSKEY_ENTRY
|
||||
.passkey_entry = auth_passkey_entry,
|
||||
#endif
|
||||
.cancel = auth_cancel,
|
||||
|
@ -579,7 +593,7 @@ static int zmk_ble_init(const struct device *_arg) {
|
|||
bt_unpair(i, NULL);
|
||||
}
|
||||
|
||||
for (int i = 0; i < PROFILE_COUNT; i++) {
|
||||
for (int i = 0; i < ZMK_BLE_PROFILE_COUNT; i++) {
|
||||
char setting_name[15];
|
||||
sprintf(setting_name, "ble/profiles/%d", i);
|
||||
|
||||
|
@ -612,32 +626,79 @@ int zmk_ble_unpair_all() {
|
|||
return resp;
|
||||
};
|
||||
|
||||
bool zmk_ble_handle_key_user(struct zmk_key_event *key_event) {
|
||||
zmk_key_t key = key_event->key;
|
||||
#if DO_PASSKEY_ENTRY
|
||||
|
||||
static bool zmk_ble_numeric_usage_to_value(const zmk_key_t key, const zmk_key_t one,
|
||||
const zmk_key_t zero, uint32_t *value) {
|
||||
if (key < one || key > zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = (key == zero) ? 0 : (key - one + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int zmk_ble_handle_key_user(struct zmk_keycode_state_changed *event) {
|
||||
zmk_key_t key = event->keycode;
|
||||
|
||||
LOG_DBG("key %d", key);
|
||||
|
||||
if (!auth_passkey_entry_conn) {
|
||||
return true;
|
||||
LOG_DBG("No connection for passkey entry");
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
if (key < NUMBER_1 || key > NUMBER_0) {
|
||||
return true;
|
||||
if (!event->state) {
|
||||
LOG_DBG("Key released, ignoring");
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
uint32_t val = (key == NUMBER_0) ? 0 : (key - NUMBER_1 + 1);
|
||||
if (key == HID_USAGE_KEY_KEYBOARD_ESCAPE) {
|
||||
bt_conn_auth_cancel(auth_passkey_entry_conn);
|
||||
return ZMK_EV_EVENT_HANDLED;
|
||||
}
|
||||
|
||||
uint32_t val;
|
||||
if (!(zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYBOARD_1_AND_EXCLAMATION,
|
||||
HID_USAGE_KEY_KEYBOARD_0_AND_RIGHT_PARENTHESIS, &val) ||
|
||||
zmk_ble_numeric_usage_to_value(key, HID_USAGE_KEY_KEYPAD_1_AND_END,
|
||||
HID_USAGE_KEY_KEYPAD_0_AND_INSERT, &val))) {
|
||||
LOG_DBG("Key not a number, ignoring");
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
passkey_entries[passkey_digit++] = val;
|
||||
LOG_DBG("value entered: %d, digits collected so far: %d", val, passkey_digit);
|
||||
|
||||
if (passkey_digit == 6) {
|
||||
if (passkey_digit == PASSKEY_DIGITS) {
|
||||
uint32_t passkey = 0;
|
||||
for (int i = 5; i >= 0; i--) {
|
||||
passkey = (passkey * 10) + val;
|
||||
for (int i = 0; i < PASSKEY_DIGITS; i++) {
|
||||
passkey = (passkey * 10) + passkey_entries[i];
|
||||
}
|
||||
|
||||
LOG_DBG("Final passkey: %d", passkey);
|
||||
bt_conn_auth_passkey_entry(auth_passkey_entry_conn, passkey);
|
||||
bt_conn_unref(auth_passkey_entry_conn);
|
||||
auth_passkey_entry_conn = NULL;
|
||||
}
|
||||
|
||||
return false;
|
||||
return ZMK_EV_EVENT_HANDLED;
|
||||
}
|
||||
|
||||
static int zmk_ble_listener(const zmk_event_t *eh) {
|
||||
struct zmk_keycode_state_changed *kc_state;
|
||||
|
||||
kc_state = as_zmk_keycode_state_changed(eh);
|
||||
|
||||
if (kc_state != NULL) {
|
||||
return zmk_ble_handle_key_user(kc_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(zmk_ble, zmk_ble_listener);
|
||||
ZMK_SUBSCRIPTION(zmk_ble, zmk_keycode_state_changed);
|
||||
#endif /* DO_PASSKEY_ENTRY */
|
||||
|
||||
SYS_INIT(zmk_ble_init, APPLICATION, CONFIG_ZMK_BLE_INIT_PRIORITY);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/util.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
|
@ -14,6 +15,11 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <drivers/behavior.h>
|
||||
#include <zmk/behavior.h>
|
||||
|
||||
#include <zmk/ble.h>
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
#include <zmk/split/bluetooth/central.h>
|
||||
#endif
|
||||
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
#include <zmk/events/layer_state_changed.h>
|
||||
|
@ -152,7 +158,17 @@ const char *zmk_keymap_layer_label(uint8_t layer) {
|
|||
return zmk_keymap_layer_names[layer];
|
||||
}
|
||||
|
||||
int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed, int64_t timestamp) {
|
||||
int invoke_locally(struct zmk_behavior_binding *binding, struct zmk_behavior_binding_event event,
|
||||
bool pressed) {
|
||||
if (pressed) {
|
||||
return behavior_keymap_binding_pressed(binding, event);
|
||||
} else {
|
||||
return behavior_keymap_binding_released(binding, event);
|
||||
}
|
||||
}
|
||||
|
||||
int zmk_keymap_apply_position_state(uint8_t source, int layer, uint32_t position, bool pressed,
|
||||
int64_t timestamp) {
|
||||
// We want to make a copy of this, since it may be converted from
|
||||
// relative to absolute before being invoked
|
||||
struct zmk_behavior_binding binding = zmk_keymap[layer][position];
|
||||
|
@ -169,7 +185,7 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed,
|
|||
behavior = device_get_binding(binding.behavior_dev);
|
||||
|
||||
if (!behavior) {
|
||||
LOG_DBG("No behavior assigned to %d on layer %d", position, layer);
|
||||
LOG_WRN("No behavior assigned to %d on layer %d", position, layer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -179,20 +195,46 @@ int zmk_keymap_apply_position_state(int layer, uint32_t position, bool pressed,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
return behavior_keymap_binding_pressed(&binding, event);
|
||||
} else {
|
||||
return behavior_keymap_binding_released(&binding, event);
|
||||
enum behavior_locality locality = BEHAVIOR_LOCALITY_CENTRAL;
|
||||
err = behavior_get_locality(behavior, &locality);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to get behavior locality %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
switch (locality) {
|
||||
case BEHAVIOR_LOCALITY_CENTRAL:
|
||||
return invoke_locally(&binding, event, pressed);
|
||||
case BEHAVIOR_LOCALITY_EVENT_SOURCE:
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
if (source == ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL) {
|
||||
return invoke_locally(&binding, event, pressed);
|
||||
} else {
|
||||
return zmk_split_bt_invoke_behavior(source, &binding, event, pressed);
|
||||
}
|
||||
#else
|
||||
return invoke_locally(&binding, event, pressed);
|
||||
#endif
|
||||
case BEHAVIOR_LOCALITY_GLOBAL:
|
||||
#if ZMK_BLE_IS_CENTRAL
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
zmk_split_bt_invoke_behavior(i, &binding, event, pressed);
|
||||
}
|
||||
#endif
|
||||
return invoke_locally(&binding, event, pressed);
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int zmk_keymap_position_state_changed(uint32_t position, bool pressed, int64_t timestamp) {
|
||||
int zmk_keymap_position_state_changed(uint8_t source, uint32_t position, bool pressed,
|
||||
int64_t timestamp) {
|
||||
if (pressed) {
|
||||
zmk_keymap_active_behavior_layer[position] = _zmk_keymap_layer_state;
|
||||
}
|
||||
for (int layer = ZMK_KEYMAP_LAYERS_LEN - 1; layer >= _zmk_keymap_layer_default; layer--) {
|
||||
if (zmk_keymap_layer_active_with_state(layer, zmk_keymap_active_behavior_layer[position])) {
|
||||
int ret = zmk_keymap_apply_position_state(layer, position, pressed, timestamp);
|
||||
int ret = zmk_keymap_apply_position_state(source, layer, position, pressed, timestamp);
|
||||
if (ret > 0) {
|
||||
LOG_DBG("behavior processing to continue to next layer");
|
||||
continue;
|
||||
|
@ -249,7 +291,7 @@ int zmk_keymap_sensor_triggered(uint8_t sensor_number, const struct device *sens
|
|||
int keymap_listener(const zmk_event_t *eh) {
|
||||
const struct zmk_position_state_changed *pos_ev;
|
||||
if ((pos_ev = as_zmk_position_state_changed(eh)) != NULL) {
|
||||
return zmk_keymap_position_state_changed(pos_ev->position, pos_ev->state,
|
||||
return zmk_keymap_position_state_changed(pos_ev->source, pos_ev->position, pos_ev->state,
|
||||
pos_ev->timestamp);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <bluetooth/addr.h>
|
||||
#include <drivers/kscan.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
|
@ -49,8 +50,11 @@ void zmk_kscan_process_msgq(struct k_work *item) {
|
|||
uint32_t position = zmk_matrix_transform_row_column_to_position(ev.row, ev.column);
|
||||
LOG_DBG("Row: %d, col: %d, position: %d, pressed: %s", ev.row, ev.column, position,
|
||||
(pressed ? "true" : "false"));
|
||||
ZMK_EVENT_RAISE(new_zmk_position_state_changed((struct zmk_position_state_changed){
|
||||
.state = pressed, .position = position, .timestamp = k_uptime_get()}));
|
||||
ZMK_EVENT_RAISE(new_zmk_position_state_changed(
|
||||
(struct zmk_position_state_changed){.source = ZMK_POSITION_STATE_CHANGE_SOURCE_LOCAL,
|
||||
.state = pressed,
|
||||
.position = position,
|
||||
.timestamp = k_uptime_get()}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -338,18 +338,28 @@ int zmk_rgb_underglow_off() {
|
|||
return zmk_rgb_underglow_save_state();
|
||||
}
|
||||
|
||||
int zmk_rgb_underglow_cycle_effect(int direction) {
|
||||
int zmk_rgb_underglow_calc_effect(int direction) {
|
||||
return (state.current_effect + UNDERGLOW_EFFECT_NUMBER + direction) % UNDERGLOW_EFFECT_NUMBER;
|
||||
}
|
||||
|
||||
int zmk_rgb_underglow_select_effect(int effect) {
|
||||
if (!led_strip)
|
||||
return -ENODEV;
|
||||
|
||||
state.current_effect += UNDERGLOW_EFFECT_NUMBER + direction;
|
||||
state.current_effect %= UNDERGLOW_EFFECT_NUMBER;
|
||||
if (effect < 0 || effect >= UNDERGLOW_EFFECT_NUMBER) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
state.current_effect = effect;
|
||||
state.animation_step = 0;
|
||||
|
||||
return zmk_rgb_underglow_save_state();
|
||||
}
|
||||
|
||||
int zmk_rgb_underglow_cycle_effect(int direction) {
|
||||
return zmk_rgb_underglow_select_effect(zmk_rgb_underglow_calc_effect(direction));
|
||||
}
|
||||
|
||||
int zmk_rgb_underglow_toggle() {
|
||||
return state.on ? zmk_rgb_underglow_off() : zmk_rgb_underglow_on();
|
||||
}
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/stdlib.h>
|
||||
#include <zmk/ble.h>
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/split/bluetooth/uuid.h>
|
||||
#include <zmk/split/bluetooth/service.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
#include <init.h>
|
||||
|
@ -27,16 +30,112 @@ static int start_scan(void);
|
|||
|
||||
#define POSITION_STATE_DATA_LEN 16
|
||||
|
||||
static struct bt_conn *default_conn;
|
||||
enum peripheral_slot_state {
|
||||
PERIPHERAL_SLOT_STATE_OPEN,
|
||||
PERIPHERAL_SLOT_STATE_CONNECTING,
|
||||
PERIPHERAL_SLOT_STATE_CONNECTED,
|
||||
};
|
||||
|
||||
struct peripheral_slot {
|
||||
enum peripheral_slot_state state;
|
||||
struct bt_conn *conn;
|
||||
struct bt_gatt_discover_params discover_params;
|
||||
struct bt_gatt_subscribe_params subscribe_params;
|
||||
struct bt_gatt_discover_params sub_discover_params;
|
||||
uint16_t run_behavior_handle;
|
||||
uint8_t position_state[POSITION_STATE_DATA_LEN];
|
||||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||
};
|
||||
|
||||
static struct peripheral_slot peripherals[ZMK_BLE_SPLIT_PERIPHERAL_COUNT];
|
||||
|
||||
static const struct bt_uuid_128 split_service_uuid = BT_UUID_INIT_128(ZMK_SPLIT_BT_SERVICE_UUID);
|
||||
static struct bt_gatt_discover_params discover_params;
|
||||
static struct bt_gatt_subscribe_params subscribe_params;
|
||||
static struct bt_gatt_discover_params sub_discover_params;
|
||||
|
||||
K_MSGQ_DEFINE(peripheral_event_msgq, sizeof(struct zmk_position_state_changed),
|
||||
CONFIG_ZMK_SPLIT_BLE_CENTRAL_POSITION_QUEUE_SIZE, 4);
|
||||
|
||||
int peripheral_slot_index_for_conn(struct bt_conn *conn) {
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].conn == conn) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct peripheral_slot *peripheral_slot_for_conn(struct bt_conn *conn) {
|
||||
int idx = peripheral_slot_index_for_conn(conn);
|
||||
if (idx < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &peripherals[idx];
|
||||
}
|
||||
|
||||
int release_peripheral_slot(int index) {
|
||||
if (index < 0 || index >= ZMK_BLE_SPLIT_PERIPHERAL_COUNT) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct peripheral_slot *slot = &peripherals[index];
|
||||
|
||||
if (slot->state == PERIPHERAL_SLOT_STATE_OPEN) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
LOG_DBG("Releasing peripheral slot at %d", index);
|
||||
|
||||
if (slot->conn != NULL) {
|
||||
bt_conn_unref(slot->conn);
|
||||
slot->conn = NULL;
|
||||
}
|
||||
slot->state = PERIPHERAL_SLOT_STATE_OPEN;
|
||||
|
||||
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
|
||||
slot->position_state[i] = 0U;
|
||||
slot->changed_positions[i] = 0U;
|
||||
}
|
||||
|
||||
// Clean up previously discovered handles;
|
||||
slot->subscribe_params.value_handle = 0;
|
||||
slot->run_behavior_handle = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reserve_peripheral_slot() {
|
||||
for (int i = 0; i < ZMK_BLE_SPLIT_PERIPHERAL_COUNT; i++) {
|
||||
if (peripherals[i].state == PERIPHERAL_SLOT_STATE_OPEN) {
|
||||
// Be sure the slot is fully reinitialized.
|
||||
release_peripheral_slot(i);
|
||||
peripherals[i].state = PERIPHERAL_SLOT_STATE_CONNECTING;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int release_peripheral_slot_for_conn(struct bt_conn *conn) {
|
||||
int idx = peripheral_slot_index_for_conn(conn);
|
||||
if (idx < 0) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
return release_peripheral_slot(idx);
|
||||
}
|
||||
|
||||
int confirm_peripheral_slot_conn(struct bt_conn *conn) {
|
||||
int idx = peripheral_slot_index_for_conn(conn);
|
||||
if (idx < 0) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
peripherals[idx].state = PERIPHERAL_SLOT_STATE_CONNECTED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void peripheral_event_work_callback(struct k_work *work) {
|
||||
struct zmk_position_state_changed ev;
|
||||
while (k_msgq_get(&peripheral_event_msgq, &ev, K_NO_WAIT) == 0) {
|
||||
|
@ -50,9 +149,12 @@ K_WORK_DEFINE(peripheral_event_work, peripheral_event_work_callback);
|
|||
static uint8_t split_central_notify_func(struct bt_conn *conn,
|
||||
struct bt_gatt_subscribe_params *params, const void *data,
|
||||
uint16_t length) {
|
||||
static uint8_t position_state[POSITION_STATE_DATA_LEN];
|
||||
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
|
||||
|
||||
uint8_t changed_positions[POSITION_STATE_DATA_LEN];
|
||||
if (slot == NULL) {
|
||||
LOG_ERR("No peripheral state found for connection");
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
LOG_DBG("[UNSUBSCRIBED]");
|
||||
|
@ -63,17 +165,21 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
|
|||
LOG_DBG("[NOTIFICATION] data %p length %u", data, length);
|
||||
|
||||
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
|
||||
changed_positions[i] = ((uint8_t *)data)[i] ^ position_state[i];
|
||||
position_state[i] = ((uint8_t *)data)[i];
|
||||
slot->changed_positions[i] = ((uint8_t *)data)[i] ^ slot->position_state[i];
|
||||
slot->position_state[i] = ((uint8_t *)data)[i];
|
||||
LOG_DBG("data: %d", slot->position_state[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < POSITION_STATE_DATA_LEN; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (changed_positions[i] & BIT(j)) {
|
||||
if (slot->changed_positions[i] & BIT(j)) {
|
||||
uint32_t position = (i * 8) + j;
|
||||
bool pressed = position_state[i] & BIT(j);
|
||||
struct zmk_position_state_changed ev = {
|
||||
.position = position, .state = pressed, .timestamp = k_uptime_get()};
|
||||
bool pressed = slot->position_state[i] & BIT(j);
|
||||
struct zmk_position_state_changed ev = {.source =
|
||||
peripheral_slot_index_for_conn(conn),
|
||||
.position = position,
|
||||
.state = pressed,
|
||||
.timestamp = k_uptime_get()};
|
||||
|
||||
k_msgq_put(&peripheral_event_msgq, &ev, K_NO_WAIT);
|
||||
k_work_submit(&peripheral_event_work);
|
||||
|
@ -85,7 +191,13 @@ static uint8_t split_central_notify_func(struct bt_conn *conn,
|
|||
}
|
||||
|
||||
static void split_central_subscribe(struct bt_conn *conn) {
|
||||
int err = bt_gatt_subscribe(conn, &subscribe_params);
|
||||
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
|
||||
if (slot == NULL) {
|
||||
LOG_ERR("No peripheral state found for connection");
|
||||
return;
|
||||
}
|
||||
|
||||
int err = bt_gatt_subscribe(conn, &slot->subscribe_params);
|
||||
switch (err) {
|
||||
case -EALREADY:
|
||||
LOG_DBG("[ALREADY SUBSCRIBED]");
|
||||
|
@ -112,24 +224,36 @@ static uint8_t split_central_chrc_discovery_func(struct bt_conn *conn,
|
|||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
|
||||
if (slot == NULL) {
|
||||
LOG_ERR("No peripheral state found for connection");
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
|
||||
|
||||
if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_POSITION_STATE_UUID))) {
|
||||
LOG_DBG("Found position state characteristic");
|
||||
discover_params.uuid = NULL;
|
||||
discover_params.start_handle = attr->handle + 2;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
slot->discover_params.uuid = NULL;
|
||||
slot->discover_params.start_handle = attr->handle + 2;
|
||||
slot->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
subscribe_params.disc_params = &sub_discover_params;
|
||||
subscribe_params.end_handle = discover_params.end_handle;
|
||||
subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
subscribe_params.notify = split_central_notify_func;
|
||||
subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||
slot->subscribe_params.disc_params = &slot->sub_discover_params;
|
||||
slot->subscribe_params.end_handle = slot->discover_params.end_handle;
|
||||
slot->subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
slot->subscribe_params.notify = split_central_notify_func;
|
||||
slot->subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||
split_central_subscribe(conn);
|
||||
} else if (!bt_uuid_cmp(((struct bt_gatt_chrc *)attr->user_data)->uuid,
|
||||
BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID))) {
|
||||
LOG_DBG("Found run behavior handle");
|
||||
slot->run_behavior_handle = bt_gatt_attr_value_handle(attr);
|
||||
}
|
||||
|
||||
return subscribe_params.value_handle ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
|
||||
bool subscribed = (slot->run_behavior_handle && slot->subscribe_params.value_handle);
|
||||
|
||||
return subscribed ? BT_GATT_ITER_STOP : BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static uint8_t split_central_service_discovery_func(struct bt_conn *conn,
|
||||
|
@ -143,18 +267,24 @@ static uint8_t split_central_service_discovery_func(struct bt_conn *conn,
|
|||
|
||||
LOG_DBG("[ATTRIBUTE] handle %u", attr->handle);
|
||||
|
||||
if (bt_uuid_cmp(discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
|
||||
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
|
||||
if (slot == NULL) {
|
||||
LOG_ERR("No peripheral state found for connection");
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
if (bt_uuid_cmp(slot->discover_params.uuid, BT_UUID_DECLARE_128(ZMK_SPLIT_BT_SERVICE_UUID))) {
|
||||
LOG_DBG("Found other service");
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
LOG_DBG("Found split service");
|
||||
discover_params.uuid = NULL;
|
||||
discover_params.func = split_central_chrc_discovery_func;
|
||||
discover_params.start_handle = attr->handle + 1;
|
||||
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
slot->discover_params.uuid = NULL;
|
||||
slot->discover_params.func = split_central_chrc_discovery_func;
|
||||
slot->discover_params.start_handle = attr->handle + 1;
|
||||
slot->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
int err = bt_gatt_discover(conn, &discover_params);
|
||||
int err = bt_gatt_discover(conn, &slot->discover_params);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to start discovering split service characteristics (err %d)", err);
|
||||
}
|
||||
|
@ -172,14 +302,20 @@ static void split_central_process_connection(struct bt_conn *conn) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (conn == default_conn && !subscribe_params.value_handle) {
|
||||
discover_params.uuid = &split_service_uuid.uuid;
|
||||
discover_params.func = split_central_service_discovery_func;
|
||||
discover_params.start_handle = 0x0001;
|
||||
discover_params.end_handle = 0xffff;
|
||||
discover_params.type = BT_GATT_DISCOVER_PRIMARY;
|
||||
struct peripheral_slot *slot = peripheral_slot_for_conn(conn);
|
||||
if (slot == NULL) {
|
||||
LOG_ERR("No peripheral state found for connection");
|
||||
return;
|
||||
}
|
||||
|
||||
err = bt_gatt_discover(default_conn, &discover_params);
|
||||
if (!slot->subscribe_params.value_handle) {
|
||||
slot->discover_params.uuid = &split_service_uuid.uuid;
|
||||
slot->discover_params.func = split_central_service_discovery_func;
|
||||
slot->discover_params.start_handle = 0x0001;
|
||||
slot->discover_params.end_handle = 0xffff;
|
||||
slot->discover_params.type = BT_GATT_DISCOVER_PRIMARY;
|
||||
|
||||
err = bt_gatt_discover(slot->conn, &slot->discover_params);
|
||||
if (err) {
|
||||
LOG_ERR("Discover failed(err %d)", err);
|
||||
return;
|
||||
|
@ -240,21 +376,33 @@ static bool split_central_eir_found(struct bt_data *data, void *user_data) {
|
|||
continue;
|
||||
}
|
||||
|
||||
default_conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
|
||||
if (default_conn) {
|
||||
uint8_t slot_idx = reserve_peripheral_slot();
|
||||
if (slot_idx < 0) {
|
||||
LOG_ERR("Faild to reserve peripheral slot (err %d)", slot_idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct peripheral_slot *slot = &peripherals[slot_idx];
|
||||
|
||||
slot->conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, addr);
|
||||
if (slot->conn) {
|
||||
LOG_DBG("Found existing connection");
|
||||
split_central_process_connection(default_conn);
|
||||
split_central_process_connection(slot->conn);
|
||||
err = bt_conn_le_phy_update(slot->conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||
if (err) {
|
||||
LOG_ERR("Update phy conn failed (err %d)", err);
|
||||
}
|
||||
} else {
|
||||
param = BT_LE_CONN_PARAM(0x0006, 0x0006, 30, 400);
|
||||
|
||||
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn);
|
||||
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &slot->conn);
|
||||
if (err) {
|
||||
LOG_ERR("Create conn failed (err %d) (create conn? 0x%04x)", err,
|
||||
BT_HCI_OP_LE_CREATE_CONN);
|
||||
start_scan();
|
||||
}
|
||||
|
||||
err = bt_conn_le_phy_update(default_conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||
err = bt_conn_le_phy_update(slot->conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||
if (err) {
|
||||
LOG_ERR("Update phy conn failed (err %d)", err);
|
||||
start_scan();
|
||||
|
@ -303,8 +451,7 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) {
|
|||
if (conn_err) {
|
||||
LOG_ERR("Failed to connect to %s (%u)", log_strdup(addr), conn_err);
|
||||
|
||||
bt_conn_unref(default_conn);
|
||||
default_conn = NULL;
|
||||
release_peripheral_slot_for_conn(conn);
|
||||
|
||||
start_scan();
|
||||
return;
|
||||
|
@ -312,6 +459,7 @@ static void split_central_connected(struct bt_conn *conn, uint8_t conn_err) {
|
|||
|
||||
LOG_DBG("Connected: %s", log_strdup(addr));
|
||||
|
||||
confirm_peripheral_slot_conn(conn);
|
||||
split_central_process_connection(conn);
|
||||
}
|
||||
|
||||
|
@ -322,15 +470,7 @@ static void split_central_disconnected(struct bt_conn *conn, uint8_t reason) {
|
|||
|
||||
LOG_DBG("Disconnected: %s (reason %d)", log_strdup(addr), reason);
|
||||
|
||||
if (default_conn != conn) {
|
||||
return;
|
||||
}
|
||||
|
||||
bt_conn_unref(default_conn);
|
||||
default_conn = NULL;
|
||||
|
||||
// Clean up previously discovered handles;
|
||||
subscribe_params.value_handle = 0;
|
||||
release_peripheral_slot_for_conn(conn);
|
||||
|
||||
start_scan();
|
||||
}
|
||||
|
@ -340,7 +480,91 @@ static struct bt_conn_cb conn_callbacks = {
|
|||
.disconnected = split_central_disconnected,
|
||||
};
|
||||
|
||||
K_THREAD_STACK_DEFINE(split_central_split_run_q_stack,
|
||||
CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_STACK_SIZE);
|
||||
|
||||
struct k_work_q split_central_split_run_q;
|
||||
|
||||
struct zmk_split_run_behavior_payload_wrapper {
|
||||
uint8_t source;
|
||||
struct zmk_split_run_behavior_payload payload;
|
||||
};
|
||||
|
||||
K_MSGQ_DEFINE(zmk_split_central_split_run_msgq,
|
||||
sizeof(struct zmk_split_run_behavior_payload_wrapper),
|
||||
CONFIG_ZMK_BLE_SPLIT_CENTRAL_SPLIT_RUN_QUEUE_SIZE, 4);
|
||||
|
||||
void split_central_split_run_callback(struct k_work *work) {
|
||||
struct zmk_split_run_behavior_payload_wrapper payload_wrapper;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
while (k_msgq_get(&zmk_split_central_split_run_msgq, &payload_wrapper, K_NO_WAIT) == 0) {
|
||||
if (peripherals[payload_wrapper.source].state != PERIPHERAL_SLOT_STATE_CONNECTED) {
|
||||
LOG_ERR("Source not connected");
|
||||
continue;
|
||||
}
|
||||
|
||||
int err = bt_gatt_write_without_response(
|
||||
peripherals[payload_wrapper.source].conn,
|
||||
peripherals[payload_wrapper.source].run_behavior_handle, &payload_wrapper.payload,
|
||||
sizeof(struct zmk_split_run_behavior_payload), true);
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to write the behavior characteristic (err %d)", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
K_WORK_DEFINE(split_central_split_run_work, split_central_split_run_callback);
|
||||
|
||||
static int
|
||||
split_bt_invoke_behavior_payload(struct zmk_split_run_behavior_payload_wrapper payload_wrapper) {
|
||||
LOG_DBG("");
|
||||
|
||||
int err = k_msgq_put(&zmk_split_central_split_run_msgq, &payload_wrapper, K_MSEC(100));
|
||||
if (err) {
|
||||
switch (err) {
|
||||
case -EAGAIN: {
|
||||
LOG_WRN("Consumer message queue full, popping first message and queueing again");
|
||||
struct zmk_split_run_behavior_payload_wrapper discarded_report;
|
||||
k_msgq_get(&zmk_split_central_split_run_msgq, &discarded_report, K_NO_WAIT);
|
||||
return split_bt_invoke_behavior_payload(payload_wrapper);
|
||||
}
|
||||
default:
|
||||
LOG_WRN("Failed to queue behavior to send (%d)", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
k_work_submit_to_queue(&split_central_split_run_q, &split_central_split_run_work);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
int zmk_split_bt_invoke_behavior(uint8_t source, struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event, bool state) {
|
||||
struct zmk_split_run_behavior_payload payload = {.data = {
|
||||
.param1 = binding->param1,
|
||||
.param2 = binding->param2,
|
||||
.position = event.position,
|
||||
.state = state ? 1 : 0,
|
||||
}};
|
||||
const size_t payload_dev_size = sizeof(payload.behavior_dev);
|
||||
if (strlcpy(payload.behavior_dev, binding->behavior_dev, payload_dev_size) >=
|
||||
payload_dev_size) {
|
||||
LOG_ERR("Truncated behavior label %s to %s before invoking peripheral behavior",
|
||||
log_strdup(binding->behavior_dev), log_strdup(payload.behavior_dev));
|
||||
}
|
||||
|
||||
struct zmk_split_run_behavior_payload_wrapper wrapper = {.source = source, .payload = payload};
|
||||
return split_bt_invoke_behavior_payload(wrapper);
|
||||
}
|
||||
|
||||
int zmk_split_bt_central_init(const struct device *_arg) {
|
||||
k_work_q_start(&split_central_split_run_q, split_central_split_run_q_stack,
|
||||
K_THREAD_STACK_SIZEOF(split_central_split_run_q_stack),
|
||||
CONFIG_ZMK_BLE_THREAD_PRIORITY);
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
|
||||
return start_scan();
|
||||
|
|
|
@ -15,6 +15,8 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
#include <bluetooth/gatt.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
|
||||
#include <drivers/behavior.h>
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/matrix.h>
|
||||
#include <zmk/split/bluetooth/uuid.h>
|
||||
#include <zmk/split/bluetooth/service.h>
|
||||
|
@ -24,12 +26,59 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
static uint8_t num_of_positions = ZMK_KEYMAP_LEN;
|
||||
static uint8_t position_state[POS_STATE_LEN];
|
||||
|
||||
static struct zmk_split_run_behavior_payload behavior_run_payload;
|
||||
|
||||
static ssize_t split_svc_pos_state(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||
void *buf, uint16_t len, uint16_t offset) {
|
||||
return bt_gatt_attr_read(conn, attrs, buf, len, offset, &position_state,
|
||||
sizeof(position_state));
|
||||
}
|
||||
|
||||
static ssize_t split_svc_run_behavior(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||
const void *buf, uint16_t len, uint16_t offset,
|
||||
uint8_t flags) {
|
||||
struct zmk_split_run_behavior_payload *payload = attrs->user_data;
|
||||
uint16_t end_addr = offset + len;
|
||||
|
||||
LOG_DBG("offset %d len %d", offset, len);
|
||||
|
||||
if (end_addr > sizeof(struct zmk_split_run_behavior_payload)) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
}
|
||||
|
||||
memcpy(payload + offset, buf, len);
|
||||
|
||||
// We run if:
|
||||
// 1: We've gotten all the position/state/param data.
|
||||
// 2: We have a null terminated string for the behavior device label.
|
||||
const size_t behavior_dev_offset =
|
||||
offsetof(struct zmk_split_run_behavior_payload, behavior_dev);
|
||||
if ((end_addr > sizeof(struct zmk_split_run_behavior_data)) &&
|
||||
payload->behavior_dev[end_addr - behavior_dev_offset - 1] == '\0') {
|
||||
struct zmk_behavior_binding binding = {
|
||||
.param1 = payload->data.param1,
|
||||
.param2 = payload->data.param2,
|
||||
.behavior_dev = payload->behavior_dev,
|
||||
};
|
||||
LOG_DBG("%s with params %d %d: pressed? %d", log_strdup(binding.behavior_dev),
|
||||
binding.param1, binding.param2, payload->data.state);
|
||||
struct zmk_behavior_binding_event event = {.position = payload->data.position,
|
||||
.timestamp = k_uptime_get()};
|
||||
int err;
|
||||
if (payload->data.state > 0) {
|
||||
err = behavior_keymap_binding_pressed(&binding, event);
|
||||
} else {
|
||||
err = behavior_keymap_binding_released(&binding, event);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Failed to invoke behavior %s: %d", log_strdup(binding.behavior_dev), err);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t split_svc_num_of_positions(struct bt_conn *conn, const struct bt_gatt_attr *attrs,
|
||||
void *buf, uint16_t len, uint16_t offset) {
|
||||
return bt_gatt_attr_read(conn, attrs, buf, len, offset, attrs->user_data, sizeof(uint8_t));
|
||||
|
@ -45,6 +94,9 @@ BT_GATT_SERVICE_DEFINE(
|
|||
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT,
|
||||
split_svc_pos_state, NULL, &position_state),
|
||||
BT_GATT_CCC(split_svc_pos_state_ccc, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_DECLARE_128(ZMK_SPLIT_BT_CHAR_RUN_BEHAVIOR_UUID),
|
||||
BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE_ENCRYPT, NULL,
|
||||
split_svc_run_behavior, &behavior_run_payload),
|
||||
BT_GATT_DESCRIPTOR(BT_UUID_NUM_OF_DIGITALS, BT_GATT_PERM_READ, split_svc_num_of_positions, NULL,
|
||||
&num_of_positions), );
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_split_listener
|
||||
|
||||
#include <device.h>
|
||||
#include <power/reboot.h>
|
||||
#include <logging/log.h>
|
||||
|
|
25
app/src/stdlib.c
Normal file
25
app/src/stdlib.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Copyright (c) 2022 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zmk/stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* ANSI C version of strlcpy
|
||||
* Based on the NetBSD strlcpy man page.
|
||||
*
|
||||
* Nathan Myers <ncm-nospam@cantrip.org>, 2003/06/03
|
||||
* Placed in the public domain.
|
||||
*/
|
||||
|
||||
size_t strlcpy(char *dst, const char *src, size_t size) {
|
||||
const size_t len = strlen(src);
|
||||
if (size != 0) {
|
||||
memcpy(dst, src, (len > size - 1) ? size - 1 : len);
|
||||
dst[size - 1] = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
1
app/tests/backlight/basic/events.patterns
Normal file
1
app/tests/backlight/basic/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_backlight_update: //p
|
9
app/tests/backlight/basic/keycode_events.snapshot
Normal file
9
app/tests/backlight/basic/keycode_events.snapshot
Normal file
|
@ -0,0 +1,9 @@
|
|||
Update backlight brightness: 40%
|
||||
Update backlight brightness: 60%
|
||||
Update backlight brightness: 80%
|
||||
Update backlight brightness: 60%
|
||||
Update backlight brightness: 40%
|
||||
Update backlight brightness: 0%
|
||||
Update backlight brightness: 0%
|
||||
Update backlight brightness: 40%
|
||||
Update backlight brightness: 40%
|
14
app/tests/backlight/basic/native_posix.conf
Normal file
14
app/tests/backlight/basic/native_posix.conf
Normal file
|
@ -0,0 +1,14 @@
|
|||
CONFIG_KSCAN=n
|
||||
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
|
||||
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_GPIO_EMUL=y
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_DEBUG=y
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
30
app/tests/backlight/basic/native_posix.keymap
Normal file
30
app/tests/backlight/basic/native_posix.keymap
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_OFF */
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
/* BL_OFF */
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
/* BL_ON */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
/* BL_ON */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
>;
|
||||
};
|
34
app/tests/backlight/behavior_keymap.dtsi
Normal file
34
app/tests/backlight/behavior_keymap.dtsi
Normal file
|
@ -0,0 +1,34 @@
|
|||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/backlight.h>
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zmk,backlight = &backlight;
|
||||
};
|
||||
|
||||
backlight: leds {
|
||||
compatible = "gpio-leds";
|
||||
led_0 {
|
||||
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||
label = "Backlight LED 0";
|
||||
};
|
||||
led_1 {
|
||||
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
||||
label = "Backlight LED 1";
|
||||
};
|
||||
};
|
||||
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&bl BL_INC &bl BL_DEC
|
||||
&bl BL_ON &bl BL_OFF
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
1
app/tests/backlight/config-brt/events.patterns
Normal file
1
app/tests/backlight/config-brt/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_backlight_update: //p
|
3
app/tests/backlight/config-brt/keycode_events.snapshot
Normal file
3
app/tests/backlight/config-brt/keycode_events.snapshot
Normal file
|
@ -0,0 +1,3 @@
|
|||
Update backlight brightness: 60%
|
||||
Update backlight brightness: 80%
|
||||
Update backlight brightness: 60%
|
15
app/tests/backlight/config-brt/native_posix.conf
Normal file
15
app/tests/backlight/config-brt/native_posix.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
CONFIG_KSCAN=n
|
||||
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
|
||||
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_GPIO_EMUL=y
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_DEBUG=y
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
||||
CONFIG_ZMK_BACKLIGHT_BRT_START=60
|
12
app/tests/backlight/config-brt/native_posix.keymap
Normal file
12
app/tests/backlight/config-brt/native_posix.keymap
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
1
app/tests/backlight/config-on/events.patterns
Normal file
1
app/tests/backlight/config-on/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_backlight_update: //p
|
3
app/tests/backlight/config-on/keycode_events.snapshot
Normal file
3
app/tests/backlight/config-on/keycode_events.snapshot
Normal file
|
@ -0,0 +1,3 @@
|
|||
Update backlight brightness: 0%
|
||||
Update backlight brightness: 40%
|
||||
Update backlight brightness: 0%
|
15
app/tests/backlight/config-on/native_posix.conf
Normal file
15
app/tests/backlight/config-on/native_posix.conf
Normal file
|
@ -0,0 +1,15 @@
|
|||
CONFIG_KSCAN=n
|
||||
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
|
||||
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_GPIO_EMUL=y
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_DEBUG=y
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
||||
CONFIG_ZMK_BACKLIGHT_ON_START=n
|
12
app/tests/backlight/config-on/native_posix.keymap
Normal file
12
app/tests/backlight/config-on/native_posix.keymap
Normal file
|
@ -0,0 +1,12 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* BL_ON */
|
||||
ZMK_MOCK_PRESS(1,0,10)
|
||||
ZMK_MOCK_RELEASE(1,0,10)
|
||||
/* BL_OFF */
|
||||
ZMK_MOCK_PRESS(1,1,10)
|
||||
ZMK_MOCK_RELEASE(1,1,10)
|
||||
>;
|
||||
};
|
1
app/tests/backlight/config-step/events.patterns
Normal file
1
app/tests/backlight/config-step/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_backlight_update: //p
|
11
app/tests/backlight/config-step/keycode_events.snapshot
Normal file
11
app/tests/backlight/config-step/keycode_events.snapshot
Normal file
|
@ -0,0 +1,11 @@
|
|||
Update backlight brightness: 60%
|
||||
Update backlight brightness: 90%
|
||||
Update backlight brightness: 100%
|
||||
Update backlight brightness: 100%
|
||||
Update backlight brightness: 70%
|
||||
Update backlight brightness: 40%
|
||||
Update backlight brightness: 10%
|
||||
Update backlight brightness: 0%
|
||||
Update backlight brightness: 0%
|
||||
Update backlight brightness: 30%
|
||||
Update backlight brightness: 60%
|
16
app/tests/backlight/config-step/native_posix.conf
Normal file
16
app/tests/backlight/config-step/native_posix.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
CONFIG_KSCAN=n
|
||||
CONFIG_ZMK_KSCAN_MOCK_DRIVER=y
|
||||
CONFIG_ZMK_KSCAN_GPIO_DRIVER=n
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_GPIO_EMUL=y
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_DEBUG=y
|
||||
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
|
||||
|
||||
CONFIG_LED_GPIO=y
|
||||
CONFIG_ZMK_BACKLIGHT=y
|
||||
CONFIG_ZMK_BACKLIGHT_BRT_START=60
|
||||
CONFIG_ZMK_BACKLIGHT_BRT_STEP=30
|
36
app/tests/backlight/config-step/native_posix.keymap
Normal file
36
app/tests/backlight/config-step/native_posix.keymap
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "../behavior_keymap.dtsi"
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_DEC */
|
||||
ZMK_MOCK_PRESS(0,1,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
/* BL_INC */
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
>;
|
||||
};
|
1
app/tests/backlight/cycle/events.patterns
Normal file
1
app/tests/backlight/cycle/events.patterns
Normal file
|
@ -0,0 +1 @@
|
|||
s/.*zmk_backlight_update: //p
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue