Compare commits

...

15 Commits

Author SHA1 Message Date
8d870812a3 Add instructions for building locally 2024-06-05 20:18:20 -07:00
6b8cb53402 Remove github actions workflows
These don't seem to work when running on Gitea, so let's just prevent
them from running.
2024-06-05 20:18:20 -07:00
cb75a136dd Initial configuration for the Pseudacris board
Some checks failed
Hardware Metadata Validation / validate-metadata (push) Successful in 8m5s
pre-commit / pre-commit (push) Failing after 43s
2024-06-05 08:02:48 -07:00
6cb4d21879 Add missing and fix some existing keys 2024-06-05 08:02:48 -07:00
febfa887dd Initial shield config and keymap for Chrysemys 2024-06-05 08:02:48 -07:00
308d6bce6e feat(docs): Improve the toolchain setup page (#2272)
Split the toolchain setup into separate docker and native pages
and improve instructions to better refer to Zephyr docs in certain steps.
Also refactor to improve consistency and add virtualenv instructions.

---------

Co-authored-by: KemoNine <mcrosson@kemonine.info>
Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
2024-06-01 21:51:08 -07:00
2d96f469c8 fix(docs): Removing to-to typos (#2310) 2024-05-25 22:16:33 -07:00
2ee76be6fe fix(soft_off): central waits 100ms in split if hold_time enabled 2024-05-13 17:43:35 -04:00
f0b20c1c93 feat(boards): Add nRF52 high voltage DC/DC config
Added a Kconfig option to enable SOC_DCDC_NRF52X_HV for nice_nano_v2
and mikoto. According to Nordic's documentation, the DC/DC regulator is
more efficient than the LDO regulator, so this is enabled by default.

The following boards do not support this mode and were not changed:

- nice_nano
- nice60
- nrfmicro_11, nrfmicro_13
- nrf52840_m2
- bluemicro840

I could not find schematics to confirm whether the following boards
support this mode:

- bt60_v1, bt60_v2
- bt65_v1
- bt75_v1
- corneish_zen_v1, corneish_zen_v2
- pillbug
- puchi_ble_v1
- s40nc
2024-05-13 14:14:50 -07:00
8f5c7bbfd4 chore(deps): bump pre-commit/action from 3.0.0 to 3.0.1
Bumps [pre-commit/action](https://github.com/pre-commit/action) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/pre-commit/action/releases)
- [Commits](https://github.com/pre-commit/action/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: pre-commit/action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 14:07:13 -07:00
7d1f84e3eb chore: fix typos in various places 2024-05-13 16:47:33 -04:00
4dfc45d4ab feat(docs): Document example toggle-mode implementation
---------

Co-authored-by: Cem Aksoylar <caksoylar@users.noreply.github.com>
2024-05-03 14:17:09 -04:00
2423136788 fix(boards): Fix pulls on ZMK uno toggle switch
The devicetree pulls always add on to the extra pulls configured by toggle mode, so these should not have pulls defined in the devicetree. Saved ~200uA avg on another board with a 3t toggle switch
2024-05-03 06:55:43 -07:00
af908826cd fix: Initialize sideband kscan in APPLICATION.
* In order to be sure the rest of the system is fully ready before
  intializing, because init may result in immediate events being
  triggered when used with toggle direct kscan inner devices.
2024-05-01 11:35:54 -07:00
d1ad34761a fix: shortening keymap_soft_off behavior node
* Shorten the soft off node in order for it to work across splits.
2024-04-29 12:22:40 -04:00
70 changed files with 1569 additions and 1265 deletions

View File

@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "npm"
directory: "/docs"
schedule:
interval: "daily"

View File

@ -1,15 +0,0 @@
<!-- If you're adding a board/shield please fill out this check-list, otherwise you can delete it -->
## Board/Shield Check-list
- [ ] This board/shield is tested working on real hardware
- [ ] Definitions follow the general style of other shields/boards upstream ([Reference](https://zmk.dev/docs/development/new-shield))
- [ ] `.zmk.yml` metadata file added
- [ ] Proper Copyright + License headers added to applicable files (Generally, we stick to "The ZMK Contributors" for copyrights to help avoid churn when files get edited)
- [ ] General consistent formatting of DeviceTree files
- [ ] Keymaps do not use deprecated key defines (Check using the [upgrader tool](https://zmk.dev/docs/codes/keymap-upgrader))
- [ ] `&pro_micro` used in favor of `&pro_micro_d/a` if applicable
- [ ] If split, no name added for the right/peripheral half
- [ ] Kconfig.defconfig file correctly wraps _all_ configuration in conditional on the shield symbol
- [ ] `.conf` file has optional extra features commented out
- [ ] Keyboard/PCB is part of a shipped group buy or is generally available in stock to purchase (OSH/personal projects without general availability should create a zmk-config repo instead)

View File

@ -1,78 +0,0 @@
name: BLE Tests
on:
push:
paths:
- ".github/workflows/ble-test.yml"
- "app/tests/ble/**"
- "app/src/**"
- "app/run-ble-test.sh"
pull_request:
paths:
- ".github/workflows/ble-test.yml"
- "app/tests/ble/**"
- "app/src/**"
- "app/run-ble-test.sh"
jobs:
collect-tests:
outputs:
test-dirs: ${{ steps.test-dirs.outputs.test-dirs }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Find test directories
id: test-dirs
run: |
cd app/tests/ble
export TESTS=$(ls -d * | grep -v central | jq -R -s -c 'split("\n")[:-1]')
echo "test-dirs=${TESTS}" > $GITHUB_OUTPUT
run-tests:
needs: collect-tests
strategy:
matrix:
test: ${{ fromJSON(needs.collect-tests.outputs.test-dirs) }}
runs-on: ubuntu-latest
container:
image: docker.io/zmkfirmware/zmk-build-arm:3.5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache west modules
uses: actions/cache@v4
env:
cache-name: cache-zephyr-modules
with:
path: |
modules/
tools/
zephyr/
bootloader/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
timeout-minutes: 2
continue-on-error: true
- name: Initialize workspace (west init)
run: west init -l app
- name: Enable babblesim group filter
run: west config manifest.group-filter -- +babblesim
- name: Update modules (west update)
run: west update
- name: Export Zephyr CMake package (west zephyr-export)
run: west zephyr-export
- name: Build BabbleSim components
working-directory: tools/bsim
run: make everything
- name: Test ${{ matrix.test }}
working-directory: app
run: BSIM_COMPONENTS_PATH="${GITHUB_WORKSPACE}/tools/bsim/components" BSIM_OUT_PATH="${GITHUB_WORKSPACE}/tools/bsim" ./run-ble-test.sh tests/ble/${{ matrix.test }}
- name: Archive artifacts
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.test }}-log-files"
path: app/build/**/*.log

View File

@ -1,182 +0,0 @@
name: Reusable user config build
on:
workflow_call:
inputs:
build_matrix_path:
description: "Path to the build matrix file"
default: "build.yaml"
required: false
type: string
config_path:
description: "Path to the config directory"
default: "config"
required: false
type: string
fallback_binary:
description: "Fallback binary format, if no *.uf2 file was built"
default: "bin"
required: false
type: string
archive_name:
description: "Archive output file name"
default: "firmware"
required: false
type: string
jobs:
matrix:
runs-on: ubuntu-latest
name: Fetch Build Keyboards
outputs:
build_matrix: ${{ env.build_matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install yaml2json
run: python3 -m pip install remarshal
- name: Fetch Build Matrix
run: |
echo "build_matrix=$(yaml2json '${{ inputs.build_matrix_path }}' | jq -c .)" >> $GITHUB_ENV
yaml2json "${{ inputs.build_matrix_path }}" | jq
build:
runs-on: ubuntu-latest
container:
image: zmkfirmware/zmk-build-arm:stable
needs: matrix
name: Build
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.matrix.outputs.build_matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create build directory
run: |
echo "build_dir=$(mktemp -d)" >> $GITHUB_ENV
- name: Prepare variables
shell: sh -x {0}
env:
board: ${{ matrix.board }}
shield: ${{ matrix.shield }}
artifact_name: ${{ matrix.artifact-name }}
snippet: ${{ matrix.snippet }}
run: |
if [ -e zephyr/module.yml ]; then
export zmk_load_arg=" -DZMK_EXTRA_MODULES='${GITHUB_WORKSPACE}'"
new_tmp_dir="${TMPDIR:-/tmp}/zmk-config"
mkdir -p "${new_tmp_dir}"
echo "base_dir=${new_tmp_dir}" >> $GITHUB_ENV
else
echo "base_dir=${GITHUB_WORKSPACE}" >> $GITHUB_ENV
fi
if [ -n "${snippet}" ]; then
extra_west_args="-S \"${snippet}\""
fi
echo "zephyr_version=${ZEPHYR_VERSION}" >> $GITHUB_ENV
echo "extra_west_args=${extra_west_args}" >> $GITHUB_ENV
echo "extra_cmake_args=${shield:+-DSHIELD=\"$shield\"}${zmk_load_arg}" >> $GITHUB_ENV
echo "display_name=${shield:+$shield - }${board}" >> $GITHUB_ENV
echo "artifact_name=${artifact_name:-${shield:+$shield-}${board}-zmk}" >> $GITHUB_ENV
- name: Copy config files to isolated temporary directory
run: |
if [ "${{ env.base_dir }}" != "${GITHUB_WORKSPACE}" ]; then
mkdir "${{ env.base_dir }}/${{ inputs.config_path }}"
cp -R ${{ inputs.config_path }}/* "${{ env.base_dir }}/${{ inputs.config_path }}/"
fi
- name: Cache west modules
uses: actions/cache@v4
continue-on-error: true
env:
cache_name: cache-zephyr-${{ env.zephyr_version }}-modules
with:
path: |
${{ env.base_dir }}/modules/
${{ env.base_dir }}/tools/
${{ env.base_dir }}/zephyr/
${{ env.base_dir }}/bootloader/
${{ env.base_dir }}/zmk/
key: ${{ runner.os }}-build-${{ env.cache_name }}-${{ hashFiles('**/west.yml', '**/build.yaml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache_name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: West Init
working-directory: ${{ env.base_dir }}
run: west init -l "${{ env.base_dir }}/${{ inputs.config_path }}"
- name: West Update
working-directory: ${{ env.base_dir }}
run: west update
- name: West Zephyr export
working-directory: ${{ env.base_dir }}
run: west zephyr-export
- name: West Build (${{ env.display_name }})
working-directory: ${{ env.base_dir }}
shell: sh -x {0}
run: west build -s zmk/app -d "${{ env.build_dir }}" -b "${{ matrix.board }}" ${{ env.extra_west_args }} -- -DZMK_CONFIG=${{ env.base_dir }}/${{ inputs.config_path }} ${{ env.extra_cmake_args }} ${{ matrix.cmake-args }}
- name: ${{ env.display_name }} Kconfig file
run: |
if [ -f "${{ env.build_dir }}/zephyr/.config" ]
then
grep -v -e "^#" -e "^$" "${{ env.build_dir }}/zephyr/.config" | sort
else
echo "No Kconfig output"
fi
if: ${{ !cancelled() }}
- name: ${{ env.display_name }} Devicetree file
run: |
if [ -f "${{ env.build_dir }}/zephyr/zephyr.dts" ]
then
cat "${{ env.build_dir }}/zephyr/zephyr.dts"
elif [ -f "${{ env.build_dir }}/zephyr/zephyr.dts.pre" ]
then
cat -s "${{ env.build_dir }}/zephyr/zephyr.dts.pre"
else
echo "No Devicetree output"
fi
if: ${{ !cancelled() }}
- name: Rename artifacts
shell: sh -x {0}
run: |
mkdir "${{ env.build_dir }}/artifacts"
if [ -f "${{ env.build_dir }}/zephyr/zmk.uf2" ]
then
cp "${{ env.build_dir }}/zephyr/zmk.uf2" "${{ env.build_dir }}/artifacts/${{ env.artifact_name }}.uf2"
elif [ -f "${{ env.build_dir }}/zephyr/zmk.${{ inputs.fallback_binary }}" ]
then
cp "${{ env.build_dir }}/zephyr/zmk.${{ inputs.fallback_binary }}" "${{ env.build_dir }}/artifacts/${{ env.artifact_name }}.${{ inputs.fallback_binary }}"
fi
- name: Archive (${{ env.display_name }})
uses: actions/upload-artifact@v4
with:
name: artifact-${{ env.artifact_name }}
path: ${{ env.build_dir }}/artifacts
merge:
runs-on: ubuntu-latest
needs: build
name: Merge Output Artifacts
steps:
- name: Merge Artifacts
uses: actions/upload-artifact/merge@v4
with:
name: ${{ inputs.archive_name }}
pattern: artifact-*
delete-merged: true

View File

@ -1,438 +0,0 @@
name: Build
on:
push:
paths:
- ".github/workflows/build.yml"
- "app/**"
pull_request:
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:3.5
needs: compile-matrix
strategy:
matrix:
include: ${{ fromJSON(needs.compile-matrix.outputs.include-list) }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache west modules
uses: actions/cache@v4
env:
cache-name: cache-zephyr-modules
with:
path: |
modules/
tools/
zephyr/
bootloader/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
timeout-minutes: 2
continue-on-error: true
- name: Initialize workspace (west init)
run: west init -l app
- name: Update modules (west update)
run: west update
- name: Export Zephyr CMake package (west zephyr-export)
run: west zephyr-export
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "14.x"
- name: Install @actions/artifact
run: npm install @actions/artifact
- name: Build
uses: actions/github-script@v7
id: boards-list
with:
script: |
const fs = require('fs');
const execSync = require('child_process').execSync;
const buildShieldArgs = JSON.parse(`${{ matrix.shieldArgs }}`);
let error = false;
for (const shieldArgs of buildShieldArgs) {
try {
console.log(`::group::${{ matrix.board}} ${shieldArgs.shield} Build`)
const output = execSync(`west build -s app -p -b ${{ matrix.board }} -- ${shieldArgs.shield ? '-DSHIELD="' + shieldArgs.shield + '"' : ''} ${shieldArgs['cmake-args'] || ''}`);
console.log(output.toString());
} catch (e) {
console.error(`::error::Failed to build ${{ 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');
}
- name: Upload artifacts
uses: actions/github-script@v7
continue-on-error: ${{ github.event_name == 'pull_request' }}
id: boards-upload
with:
script: |
const fs = require('fs');
const {default: artifact} = require('@actions/artifact');
const buildShieldArgs = JSON.parse(`${{ matrix.shieldArgs }}`);
let error = false;
for (const shieldArgs of buildShieldArgs) {
try {
console.log(`::group::${{ matrix.board}} ${shieldArgs.shield} Upload`)
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 artifact.uploadArtifact(artifactName, files, rootDirectory, options);
} catch (e) {
console.error(`::error::Failed to 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@v7
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@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "14.x"
- name: Install js-yaml
run: npm install js-yaml
- uses: actions/github-script@v7
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@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "14.x"
- name: Install js-yaml
run: npm install js-yaml
- uses: actions/github-script@v7
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))
);
} else {
console.warn("Unhandled shield without keys");
return [];
}
break;
case "interconnect":
return [];
}
});
}))).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@v7
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@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: "14.x"
- name: Install js-yaml
run: npm install js-yaml
- name: Aggregate Metadata
uses: actions/github-script@v7
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,"\\\\").replace(/`/g,"\\`");
result-encoding: string
- name: Organize Metadata
uses: actions/github-script@v7
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,"\\\\").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_changed_files }}
board-changes: ${{ steps.board-changes.outputs.result }}
core-changes: ${{ steps.core-changes.outputs.result }}
steps:
- uses: tj-actions/changed-files@v42
id: changed-files
with:
json: true
escape_json: false
- uses: actions/github-script@v7
id: board-changes
with:
script: |
const changedFiles = JSON.parse(`${{ steps.changed-files.outputs.all_changed_files }}`);
const boardChanges = changedFiles.filter(f => f.startsWith('app/boards'));
return boardChanges.length ? 'true' : 'false';
result-encoding: string
- uses: actions/github-script@v7
id: core-changes
with:
script: |
const changedFiles = JSON.parse(`${{ steps.changed-files.outputs.all_changed_files }}`);
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

View File

@ -1,36 +0,0 @@
name: Docs Checks
on:
push:
paths:
- ".github/workflows/doc-checks.yml"
- "docs/**"
pull_request:
paths:
- ".github/workflows/doc-checks.yml"
- "docs/**"
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bahmutov/npm-install@v1
with:
working-directory: docs
- name: ESLint
run: npm run lint
working-directory: docs
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bahmutov/npm-install@v1
with:
working-directory: docs
- name: Build
run: npm run build
working-directory: docs
- name: TypeScript check
run: npm run typecheck
working-directory: docs

View File

@ -1,34 +0,0 @@
name: Hardware Metadata Validation
on:
push:
paths:
- ".github/workflows/hardware-metadata-validation.yml"
- "schema/hardware-metadata.schema.json"
- "app/boards/**/*.zmk.yml"
- "app/scripts/west_commands/metadata.py"
pull_request:
paths:
- ".github/workflows/hardware-metadata-validation.yml"
- "schema/hardware-metadata.schema.json"
- "app/boards/**/*.zmk.yml"
- "app/scripts/west_commands/metadata.py"
jobs:
validate-metadata:
runs-on: ubuntu-latest
container:
image: docker.io/zmkfirmware/zmk-dev-arm:3.5
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: pip install -r app/scripts/requirements.txt
- name: West init
run: west init -l app
- name: Update modules (west update)
run: west update
- name: Export Zephyr CMake package (west zephyr-export)
run: west zephyr-export
- name: Validate Hardware Metadata
working-directory: app
run: west metadata check

View File

@ -1,15 +0,0 @@
name: pre-commit
on:
pull_request:
push:
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- uses: pre-commit/action@v3.0.0

View File

@ -1,73 +0,0 @@
name: Tests
on:
push:
paths:
- ".github/workflows/test.yml"
- "app/tests/**"
- "app/src/**"
- "app/include/**"
pull_request:
paths:
- ".github/workflows/test.yml"
- "app/tests/**"
- "app/src/**"
- "app/include/**"
jobs:
collect-tests:
outputs:
test-dirs: ${{ steps.test-dirs.outputs.test-dirs }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Find test directories
id: test-dirs
run: |
cd app/tests/
export TESTS=$(ls -d * | grep -v ble | jq -R -s -c 'split("\n")[:-1]')
echo "test-dirs=${TESTS}" >> $GITHUB_OUTPUT
run-tests:
needs: collect-tests
strategy:
matrix:
test: ${{ fromJSON(needs.collect-tests.outputs.test-dirs) }}
runs-on: ubuntu-latest
container:
image: docker.io/zmkfirmware/zmk-build-arm:3.5
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache west modules
uses: actions/cache@v4
env:
cache-name: cache-zephyr-modules
with:
path: |
modules/
tools/
zephyr/
bootloader/
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('app/west.yml') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
timeout-minutes: 2
continue-on-error: true
- name: Initialize workspace (west init)
run: west init -l app
- name: Update modules (west update)
run: west update
- name: Export Zephyr CMake package (west zephyr-export)
run: west zephyr-export
- name: Test ${{ matrix.test }}
working-directory: app
run: west test tests/${{ matrix.test }}
- name: Archive artifacts
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: "${{ matrix.test }}-log-files"
path: app/build/**/*.log

View File

@ -1,13 +1,41 @@
# Zephyr™ Mechanical Keyboard (ZMK) Firmware
# ZMK
[![Discord](https://img.shields.io/discord/719497620560543766)](https://zmk.dev/community/discord/invite)
[![Build](https://github.com/zmkfirmware/zmk/workflows/Build/badge.svg)](https://github.com/zmkfirmware/zmk/actions)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)
NOTE: Try to keep the repo up to date as much as possible. Pull from the
upstream master and then rebase my branch on top of it.
[ZMK Firmware](https://zmk.dev/) is an open source ([MIT](LICENSE)) keyboard firmware built on the [Zephyr™ Project](https://www.zephyrproject.org/) Real Time Operating System (RTOS). ZMK's goal is to provide a modern, wireless, and powerful firmware free of licensing issues.
## Instructions for building
Check out the website to learn more: https://zmk.dev/.
1. Install devcontainer cli
You can also come join our [ZMK Discord Server](https://zmk.dev/community/discord/invite).
```sh
brew install devcontainer
```
2. Setup the devcontainer
```sh
devcontainer up --workspace-path . --docker-path $(which podman)
```
3. Initialize west (this takes a while)
```sh
devcontainer exec --workspace-path . --docker-path $(which podman)
west init -l app/
west update
```
4. Build the firmware
```sh
cd app
west build --pristine -b nice_nano_v2 -- -DSHIELD=chrysemys
```
5. Copy the uf2 file onto the root of the USB mass storage for the keyboard. The uf2 file can be found at `app/build/zephyr/zmk.uf2`.
## Documentation
- [Docker setup](https://zmk.dev/docs/development/setup/docker)
- [Building](https://zmk.dev/docs/development/build-flash)
To review features, check out the [feature overview](https://zmk.dev/docs/). ZMK is under active development, and new features are listed with the [enhancement label](https://github.com/zmkfirmware/zmk/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) in GitHub. Please feel free to add 👍 to the issue description of any requests to upvote the feature.

View File

@ -157,7 +157,7 @@ config ZMK_BLE_EXPERIMENTAL_CONN
bool "Experimental BLE connection changes"
help
Enables a combination of settings that are planned to be default in future versions of ZMK
to improve connection stability. This includes changes to timing on BLE pairing initation,
to improve connection stability. This includes changes to timing on BLE pairing initiation,
restores use of the updated/new LLCP implementation, and disables 2M PHY support.
config ZMK_BLE_EXPERIMENTAL_SEC
@ -257,7 +257,7 @@ menu "Display/LED Options"
rsource "src/display/Kconfig"
menuconfig ZMK_RGB_UNDERGLOW
bool "RGB Adressable LED Underglow"
bool "RGB Addressable LED Underglow"
select LED_STRIP
select ZMK_LOW_PRIORITY_WORK_QUEUE

View File

@ -88,7 +88,7 @@
fuelgauge: bq274xx@55 {
compatible = "ti,bq274xx";
reg = <0x55>;
design-voltage = <3700>; //Battery Design Volatge in mV
design-voltage = <3700>; //Battery Design Voltage in mV
design-capacity = <180>; //Battery Design Capacity in mAh
taper-current = <2>; //Battery Taper current in mAh
terminate-voltage = <2750>; //Battery Terminate Voltage in mV

View File

@ -96,7 +96,7 @@
fuelgauge: bq274xx@55 {
compatible = "ti,bq274xx";
reg = <0x55>;
design-voltage = <3700>; //Battery Design Volatge in mV
design-voltage = <3700>; //Battery Design Voltage in mV
design-capacity = <180>; //Battery Design Capacity in mAh
taper-current = <2>; //Battery Taper current in mAh 2.1
terminate-voltage = <2750>; //Battery Terminate Voltage in mV

View File

@ -4,6 +4,12 @@ config BOARD_ENABLE_DCDC
default y
depends on (BOARD_MIKOTO_520)
config BOARD_ENABLE_DCDC_HV
bool "High voltage DCDC converter"
select SOC_DCDC_NRF52X_HV
default y
depends on (BOARD_MIKOTO_520)
choice BOARD_MIKOTO_CHARGER_CURRENT
prompt "Charge current to supply to attached batteries"
depends on (BOARD_MIKOTO_520)

View File

@ -5,3 +5,9 @@ config BOARD_ENABLE_DCDC
select SOC_DCDC_NRF52X
default y
depends on (BOARD_NICE_NANO || BOARD_NICE_NANO_V2)
config BOARD_ENABLE_DCDC_HV
bool "High voltage DCDC converter"
select SOC_DCDC_NRF52X_HV
default y
depends on (BOARD_NICE_NANO_V2)

View File

@ -0,0 +1,13 @@
# Copyright (c) 2022 Tony Grosinger
# SPDX-License-Identifier: MIT
config BOARD_ENABLE_DCDC
bool "Enable DCDC mode"
select SOC_DCDC_NRF52X
default y
depends on BOARD_PSEUDACRIS
config BOARD_ENABLE_CHARGER
bool "Enable battery charger"
default y
depends on (BOARD_PSEUDACRIS)

View File

@ -0,0 +1,6 @@
# Copyright (c) 2022 Tony Grosinger
# SPDX-License-Identifier: MIT
config BOARD_PSEUDACRIS
bool "pseudacris"
depends on SOC_NRF52840_QIAA

View File

@ -0,0 +1,31 @@
# Copyright (c) 2022 Tony Grosinger
# SPDX-License-Identifier: MIT
if BOARD_PSEUDACRIS
config ZMK_KEYBOARD_NAME
default "pseudacris"
if USB_DEVICE_STACK
config USB_NRFX
default y
endif # USB_DEVICE_STACK
config BT_CTLR
default BT
config ZMK_BLE
default y
config ZMK_USB
default y
config PINMUX
default y
config BOARD_ENABLE_CHARGER
default y
endif # BOARD_PSEUDACRIS

View File

@ -0,0 +1,15 @@
# Pseudacris
Pseudacris is a hotswap 30% keyboard made by Tony Grosinger.
More details, including the BOM and PCB files can be found at https://git.sr.ht/~tgrosinger/keyboards/tree/main/item/pseudacris
## Building Pseudacris ZMK firmware
```bash
# From in this repo
cd app
west build -p -b pseudacris
# Built firmware output to app/build/zephyr/zmk.uf2
```

View File

@ -0,0 +1,7 @@
# Copyright (c) 2022 Tony Grosinger
# SPDX-License-Identifier: MIT
set(OPENOCD_NRF5_SUBFAMILY nrf52)
board_runner_args(nrfjprog "--nrf-family=NRF52" "--softreset")
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake)

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <kernel.h>
#include <device.h>
#include <init.h>
#include <drivers/gpio.h>
#include <sys/sys_io.h>
#include <devicetree.h>
static int pinmux_pseudacris_init(const struct device *port) {
ARG_UNUSED(port);
const struct device *p0 = device_get_binding("GPIO_0");
#if CONFIG_BOARD_ENABLE_CHARGER
gpio_pin_configure(p0, 5, GPIO_OUTPUT);
gpio_pin_set(p0, 5, 0);
#else
gpio_pin_configure(p0, 5, GPIO_INPUT);
#endif
return 0;
}
SYS_INIT(pinmux_pseudacris_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2022 Tony Grosinger
*
* SPDX-License-Identifier: MIT
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include <dt-bindings/zmk/matrix_transform.h>
/ {
model = "pseudacris";
compatible = "pseudacris";
chosen {
zephyr,code-partition = &code_partition;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,console = &cdc_acm_uart;
zmk,kscan = &kscan0;
zmk,matrix_transform = &default_transform;
};
default_transform: keymap_transform_0 {
compatible = "zmk,matrix-transform";
columns = <10>;
rows = <7>;
map = <
RC(0,0) RC(0,1) RC(0,2) RC(0,3) RC(0,4) RC(3,5) RC(3,6) RC(3,7) RC(3,8) RC(3,9)
RC(1,0) RC(1,1) RC(1,2) RC(1,3) RC(1,4) RC(4,5) RC(4,6) RC(4,7) RC(4,8) RC(4,9)
RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(5,5) RC(5,6) RC(5,7) RC(5,8) RC(5,9)
RC(6,2) RC(6,3) RC(6,4) RC(6,5) RC(6,6) RC(6,7)
>;
};
kscan0: kscan {
compatible = "zmk,kscan-gpio-matrix";
label = "KSCAN";
diode-direction = "row2col";
/*
* P0.13 - Left Matrix Top
* P0.22 - Left Matrix Middle
* P1.06 - Left Matrix Bottom
*
* P0.30 - Right Matrix Top
* P0.31 - Right Matrix Middle
* P1.11 - Right Matrix Bottom
*
* P0.10 - Thumbs
*/
row-gpios
= <&gpio0 13 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio0 22 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio0 30 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio0 31 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio1 11 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
, <&gpio0 10 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
;
/*
* P0.09 - Left Pinky
* P1.04 - Left Ring
* P1.02 - Left Middle
* P1.00 - Left Pointer
* P0.24 - Left Inner
* P0.29 - Right Inner
* P0.02 - Right Pointer
* P1.13 - Right Middle
* P0.28 - Right Ring
* P0.03 - Right Pinky
*/
col-gpios
= <&gpio0 9 GPIO_ACTIVE_HIGH>
, <&gpio1 4 GPIO_ACTIVE_HIGH>
, <&gpio1 2 GPIO_ACTIVE_HIGH>
, <&gpio1 0 GPIO_ACTIVE_HIGH>
, <&gpio0 24 GPIO_ACTIVE_HIGH>
, <&gpio0 29 GPIO_ACTIVE_HIGH>
, <&gpio0 2 GPIO_ACTIVE_HIGH>
, <&gpio1 13 GPIO_ACTIVE_HIGH>
, <&gpio0 28 GPIO_ACTIVE_HIGH>
, <&gpio0 3 GPIO_ACTIVE_HIGH>
;
};
ext-power {
compatible = "zmk,ext-power-generic";
label = "EXT_POWER";
control-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
};
};
&gpiote {
status = "okay";
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&i2c0 {
compatible = "nordic,nrf-twi";
sda-pin = <15>;
scl-pin = <17>;
};
&uart0 {
compatible = "nordic,nrf-uarte";
tx-pin = <6>;
rx-pin = <8>;
};
&usbd {
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
label = "CDC_ACM_0";
};
};
&flash0 {
/*
* For more information, see:
* http://docs.zephyrproject.org/latest/devices/dts/flash_partitions.html
*/
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
sd_partition: partition@0 {
label = "softdevice";
reg = <0x00000000 0x00026000>;
};
code_partition: partition@26000 {
label = "code_partition";
reg = <0x00026000 0x000c6000>;
};
/*
* The flash starting at 0x000ec000 and ending at
* 0x000f3fff is reserved for use by the application.
*/
/*
* Storage partition will be used by FCB/LittleFS/NVS
* if enabled.
*/
storage_partition: partition@ec000 {
label = "storage";
reg = <0x000ec000 0x00008000>;
};
boot_partition: partition@f4000 {
label = "adafruit_boot";
reg = <0x000f4000 0x0000c000>;
};
};
};

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2022 Tony Grosinger
*
* SPDX-License-Identifier: MIT
*/
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#define DEF_L 0
#define NUM_L 1
#define SYM_L 2
#define TMUX_L 3
// Using layer taps on thumbs, having quick tap as well helps w/ repeating space/backspace
&lt { quick_tap_ms = <200>; };
/ {
behaviors {
hm: homerow_mods {
compatible = "zmk,behavior-hold-tap";
label = "homerow mods";
#binding-cells = <2>;
tapping_term_ms = <225>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
};
};
combos {
compatible = "zmk,combos";
combo_backtick {
timeout-ms = <50>;
key-positions = <0 1>;
bindings = <&kp GRAVE>;
};
combo_esc {
timeout-ms = <50>;
key-positions = <1 11>;
bindings = <&kp ESC>;
};
combo_backspace {
timeout-ms = <50>;
key-positions = <11 12>;
bindings = <&kp BSPC>;
};
combo_tab {
timeout-ms = <50>;
key-positions = <12 13>;
bindings = <&kp TAB>;
};
combo_enter {
timeout-ms = <50>;
key-positions = <22 23>;
bindings = <&kp ENTER>;
};
combo_minus {
timeout-ms = <50>;
key-positions = <7 8>;
bindings = <&kp MINUS>;
};
combo_backslash {
timeout-ms = <50>;
key-positions = <8 9>;
bindings = <&kp BACKSLASH>;
};
combo_less_than {
timeout-ms = <50>;
key-positions = <15 16>;
bindings = <&kp LT>;
};
combo_greater_than {
timeout-ms = <50>;
key-positions = <17 18>;
bindings = <&kp GT>;
};
combo_colon {
timeout-ms = <50>;
key-positions = <16 17>;
bindings = <&kp COLON>;
};
combo_quote {
timeout-ms = <50>;
key-positions = <25 26>;
bindings = <&kp APOSTROPHE>;
};
combo_underscore {
timeout-ms = <50>;
key-positions = <26 27>;
bindings = <&kp UNDER>;
};
};
macros {
tmux_new: tmux_new {
label = "ZM_tmux_new";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp C>
;
};
tmux_zoom: tmux_zoom {
label = "ZM_tmux_zoom";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp Z>
;
};
tmux_scroll: tmux_scroll {
label = "ZM_tmux_scroll";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp LEFT_BRACKET>
;
};
tmux_pn_lt: tmux_pn_lt {
label = "ZM_tmux_pn_lt";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp LEFT>
;
};
tmux_pn_dn: tmux_pn_dn {
label = "ZM_tmux_pn_dn";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp DOWN>
;
};
tmux_pn_up: tmux_pn_up {
label = "ZM_tmux_pn_up";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp UP>
;
};
tmux_pn_rt: tmux_pn_rt {
label = "ZM_tmux_pn_rt";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp RIGHT>
;
};
tmux_wn_next: tmux_wn_next {
label = "ZM_tmux_wn_next";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp N>
;
};
tmux_wn_prev: tmux_wn_prev {
label = "ZM_tmux_wn_prev";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp P>
;
};
tmux_sp_v: tmux_sp_v {
label = "ZM_tmux_sp_v";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp PERCENT>
;
};
tmux_sp_h: tmux_sp_h {
label = "ZM_tmux_sp_h";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp DOUBLE_QUOTES>
;
};
vi_clip_cp: vi_clip_cp {
label = "ZM_vi_clip_cp";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp DOUBLE_QUOTES>
, <&macro_tap &kp PLUS>
, <&macro_tap &kp Y>
;
};
vi_clip_pst: vi_clip_pst {
label = "ZM_vi_clip_pst";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp DOUBLE_QUOTES>
, <&macro_tap &kp PLUS>
, <&macro_tap &kp P>
;
};
vi_macro: vi_macro {
label = "ZM_vi_macro";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp AT>
, <&macro_tap &kp Q>
;
};
vi_save: vi_save {
label = "ZM_vi_save";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp ESC>
, <&macro_tap &kp COLON &kp W &kp ENTER>
, <&macro_tap &kp LC(T)>
;
};
term_full: term_full {
label = "ZM_term_full";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(TILDE)>
;
};
desk_left: desk_left {
label = "ZM_desk_left";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(LG(LEFT))>
;
};
desk_right: desk_right {
label = "ZM_desk_right";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(LG(RIGHT))>
;
};
};
keymap {
compatible = "zmk,keymap";
// 0
// 10
// 20
default_layer {
bindings = <
&kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P
&hm LCTL A &kp S &kp D &kp F &kp G &kp H &hm LGUI J &kp K &kp L &hm RCTL SEMI
&hm LALT Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp SLASH
&mo NUM_L &kp LSHIFT &kp ESC &mo TMUX_L &kp SPACE &mo SYM_L
>;
};
num_layer {
label = "Num";
bindings = <
&kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0
&trans &desk_left &kp LG(E) &kp LG(R) &desk_right &trans &kp N4 &kp N5 &kp N6 &kp COLON
&kp F1 &kp F2 &kp F12 &kp F4 &kp F5 &trans &kp N1 &kp N2 &kp N3 &kp DOT
&none &none &none &none &none &kp N0
>;
};
sym_layer {
label = "Sym";
bindings = <
&kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp ASTRK &kp PLUS &kp EQUAL
&kp COLON &none &kp LPAR &kp RPAR &none &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans
&none &kp LBRC &kp LBKT &kp RBKT &kp RBRC &kp HOME &kp PG_DN &kp PG_UP &kp END &trans
&none &none &none &none &none &none
>;
};
tmux_layer {
label = "Tmux";
bindings = <
&vi_macro &vi_save &none &none &tmux_sp_v &vi_clip_cp &none &none &none &vi_clip_pst
&none &tmux_scroll &none &term_full &none &tmux_pn_lt &tmux_pn_dn &tmux_pn_up &tmux_pn_rt &tmux_sp_h
&tmux_zoom &none &tmux_new &none &none &tmux_wn_prev &none &none &tmux_wn_next &none
&none &kp DEL &none &none &none &none
>;
};
};
};

View File

@ -0,0 +1,15 @@
identifier: pseudacris
name: pseudacris
type: mcu
arch: arm
toolchain:
- zephyr
- gnuarmemb
- xtools
supported:
- adc
- usb_device
- ble
- ieee802154
- pwm
- watchdog

View File

@ -0,0 +1,11 @@
file_format: "1"
id: pseudacris
name: pseudacris
type: board
arch: arm
features:
- keys
outputs:
- usb
- ble
url: https://git.sr.ht/~tgrosinger/keyboards/tree/main/item/pseudacris

View File

@ -0,0 +1,24 @@
# Copyright (c) 2022 Tony Grosinger
# SPDX-License-Identifier: MIT
CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52840_QIAA=y
CONFIG_BOARD_PSEUDACRIS=y
# Enable MPU
CONFIG_ARM_MPU=y
# enable GPIO
CONFIG_GPIO=y
CONFIG_USE_DT_CODE_PARTITION=y
CONFIG_BUILD_OUTPUT_UF2=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_NVS=y
CONFIG_SETTINGS_NVS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_CLOCK_CONTROL_NRF=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y

View File

@ -5,7 +5,7 @@ type: interconnect
url: https://wiki.seeedstudio.com/Seeeduino-XIAO/
manufacturer: Seeed
description: |
The Seeed(uino) XIAO is a popular smaller format micro-controller, that has gained popularity as an alterative
The Seeed(uino) XIAO is a popular smaller format micro-controller, that has gained popularity as an alternative
to the SparkFun Pro Micro. Since its creation, several pin compatible controllers, such
as the Seeeduino XIAO BLE, Adafruit QT Py and Adafruit QT Py RP2040, have become available.
node_labels:

View File

@ -0,0 +1,9 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
if SHIELD_CHRYSEMYS
config ZMK_KEYBOARD_NAME
default "Chrysemys"
endif

View File

@ -0,0 +1,5 @@
# Copyright (c) 2022 The ZMK Contributors
# SPDX-License-Identifier: MIT
config SHIELD_CHRYSEMYS
def_bool $(shields_list_contains,chrysemys)

View File

@ -0,0 +1,305 @@
/*
* Copyright (c) 2022 The ZMK Contributors
*
* SPDX-License-Identifier: MIT
*/
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#define DEF_L 0
#define NUM_L 1
#define SYM_L 2
#define TMUX_L 3
// Using layer taps on thumbs, having quick tap as well helps w/ repeating space/backspace
&lt { quick_tap_ms = <200>; };
/ {
behaviors {
hm: homerow_mods {
compatible = "zmk,behavior-hold-tap";
label = "homerow mods";
#binding-cells = <2>;
tapping_term_ms = <225>;
flavor = "tap-preferred";
bindings = <&kp>, <&kp>;
};
};
combos {
compatible = "zmk,combos";
combo_backtick {
timeout-ms = <50>;
key-positions = <0 1>;
bindings = <&kp GRAVE>;
};
combo_esc {
timeout-ms = <50>;
key-positions = <1 11>;
bindings = <&kp ESC>;
};
combo_backspace {
timeout-ms = <50>;
key-positions = <11 12>;
bindings = <&kp BSPC>;
};
combo_tab {
timeout-ms = <50>;
key-positions = <12 13>;
bindings = <&kp TAB>;
};
combo_enter {
timeout-ms = <50>;
key-positions = <22 23>;
bindings = <&kp ENTER>;
};
combo_minus {
timeout-ms = <50>;
key-positions = <7 8>;
bindings = <&kp MINUS>;
};
combo_backslash {
timeout-ms = <50>;
key-positions = <8 9>;
bindings = <&kp BACKSLASH>;
};
combo_less_than {
timeout-ms = <50>;
key-positions = <15 16>;
bindings = <&kp LT>;
};
combo_greater_than {
timeout-ms = <50>;
key-positions = <17 18>;
bindings = <&kp GT>;
};
combo_colon {
timeout-ms = <50>;
key-positions = <16 17>;
bindings = <&kp COLON>;
};
combo_quote {
timeout-ms = <50>;
key-positions = <25 26>;
bindings = <&kp APOSTROPHE>;
};
combo_underscore {
timeout-ms = <50>;
key-positions = <26 27>;
bindings = <&kp UNDER>;
};
};
macros {
tmux_new: tmux_new {
label = "ZM_tmux_new";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp C>
;
};
tmux_zoom: tmux_zoom {
label = "ZM_tmux_zoom";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp Z>
;
};
tmux_scroll: tmux_scroll {
label = "ZM_tmux_scroll";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp LEFT_BRACKET>
;
};
tmux_pn_lt: tmux_pn_lt {
label = "ZM_tmux_pn_lt";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp LEFT>
;
};
tmux_pn_dn: tmux_pn_dn {
label = "ZM_tmux_pn_dn";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp DOWN>
;
};
tmux_pn_up: tmux_pn_up {
label = "ZM_tmux_pn_up";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp UP>
;
};
tmux_pn_rt: tmux_pn_rt {
label = "ZM_tmux_pn_rt";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp RIGHT>
;
};
tmux_wn_next: tmux_wn_next {
label = "ZM_tmux_wn_next";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp N>
;
};
tmux_wn_prev: tmux_wn_prev {
label = "ZM_tmux_wn_prev";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp P>
;
};
tmux_sp_v: tmux_sp_v {
label = "ZM_tmux_sp_v";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp PERCENT>
;
};
tmux_sp_h: tmux_sp_h {
label = "ZM_tmux_sp_h";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(B)>
, <&macro_tap &kp DOUBLE_QUOTES>
;
};
vi_clip_cp: vi_clip_cp {
label = "ZM_vi_clip_cp";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp DOUBLE_QUOTES>
, <&macro_tap &kp PLUS>
, <&macro_tap &kp Y>
;
};
vi_clip_pst: vi_clip_pst {
label = "ZM_vi_clip_pst";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp DOUBLE_QUOTES>
, <&macro_tap &kp PLUS>
, <&macro_tap &kp P>
;
};
vi_macro: vi_macro {
label = "ZM_vi_macro";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp AT>
, <&macro_tap &kp Q>
;
};
vi_save: vi_save {
label = "ZM_vi_save";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp ESC>
, <&macro_tap &kp COLON &kp W &kp ENTER>
, <&macro_tap &kp LC(T)>
;
};
term_full: term_full {
label = "ZM_term_full";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(TILDE)>
;
};
desk_left: desk_left {
label = "ZM_desk_left";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(LG(LEFT))>
;
};
desk_right: desk_right {
label = "ZM_desk_right";
compatible = "zmk,behavior-macro";
#binding-cells = <0>;
bindings
= <&macro_tap &kp LC(LG(RIGHT))>
;
};
};
keymap {
compatible = "zmk,keymap";
// 0
// 10
// 20
default_layer {
bindings = <
&kp Q &kp W &kp E &kp R &kp T &kp Y &kp U &kp I &kp O &kp P
&hm LCTL A &kp S &kp D &kp F &kp G &kp H &hm LGUI J &kp K &kp L &hm RCTL SEMI
&hm LALT Z &kp X &kp C &kp V &kp B &kp N &kp M &kp COMMA &kp DOT &kp SLASH
&mo NUM_L &kp LSHIFT &kp ESC &mo TMUX_L &kp SPACE &mo SYM_L
>;
};
num_layer {
label = "Num";
bindings = <
&kp N1 &kp N2 &kp N3 &kp N4 &kp N5 &kp N6 &kp N7 &kp N8 &kp N9 &kp N0
&trans &desk_left &kp LG(E) &kp LG(R) &desk_right &trans &kp N4 &kp N5 &kp N6 &kp COLON
&kp F1 &kp F2 &kp F12 &kp F4 &kp F5 &trans &kp N1 &kp N2 &kp N3 &kp DOT
&none &none &none &none &none &kp N0
>;
};
sym_layer {
label = "Sym";
bindings = <
&kp EXCL &kp AT &kp HASH &kp DLLR &kp PRCNT &kp CARET &kp AMPS &kp ASTRK &kp PLUS &kp EQUAL
&kp COLON &none &kp LPAR &kp RPAR &none &kp LEFT &kp DOWN &kp UP &kp RIGHT &trans
&none &kp LBRC &kp LBKT &kp RBKT &kp RBRC &kp HOME &kp PG_DN &kp PG_UP &kp END &trans
&none &none &none &none &none &none
>;
};
tmux_layer {
label = "Tmux";
bindings = <
&vi_macro &vi_save &none &none &tmux_sp_v &vi_clip_cp &none &none &none &vi_clip_pst
&none &tmux_scroll &none &term_full &none &tmux_pn_lt &tmux_pn_dn &tmux_pn_up &tmux_pn_rt &tmux_sp_h
&tmux_zoom &none &tmux_new &none &none &tmux_wn_prev &none &none &tmux_wn_next &none
&none &kp DEL &none &none &none &none
>;
};
};
};

View File

@ -0,0 +1,54 @@
/*
* 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 = <10>;
rows = <4>;
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(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(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)
>;
};
kscan0: kscan_0 {
compatible = "zmk,kscan-gpio-matrix";
label = "KSCAN";
diode-direction = "row2col";
col-gpios
= <&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)>
, <&pro_micro 9 (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)>
, <&pro_micro 18 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>
;
row-gpios
= <&pro_micro 1 GPIO_ACTIVE_HIGH>
, <&pro_micro 2 GPIO_ACTIVE_HIGH>
, <&pro_micro 3 GPIO_ACTIVE_HIGH>
, <&pro_micro 4 GPIO_ACTIVE_HIGH>
;
};
};

View File

@ -0,0 +1,8 @@
file_format: "1"
id: chrysemys
name: Chrysemys
type: shield
url: https://git.sr.ht/~tgrosinger/keyboards/tree/main/item/chrysemys
requires: [pro_micro]
features:
- keys

View File

@ -125,9 +125,9 @@ nice_view_spi: &arduino_spi {
toggle-mode;
input-gpios
= <&arduino_header 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
, <&arduino_header 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
, <&arduino_header 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>
= <&arduino_header 4 GPIO_ACTIVE_LOW>
, <&arduino_header 3 GPIO_ACTIVE_LOW>
, <&arduino_header 2 GPIO_ACTIVE_LOW>
;
};

View File

@ -6,7 +6,7 @@
/ {
behaviors {
/omit-if-no-ref/ soft_off: keymap_soft_off {
/omit-if-no-ref/ soft_off: z_so_off {
compatible = "zmk,behavior-soft-off";
#binding-cells = <0>;
split-peripheral-off-on-press;

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
/* This provies a mapping from Arduino Uno to Arduino Pro Micro pins for development */
/* This provides a mapping from Arduino Uno to Arduino Pro Micro pins for development */
/ {
pro_micro_d: connector_d {

View File

@ -23,12 +23,12 @@ int zmk_display_init(void);
*
* @param listener THe ZMK Event manager listener name.
* @param state_type The struct/enum type used to store/transfer state.
* @param cb The callback to invoke in the dispaly queue context to update the UI. Should be `void
* @param cb The callback to invoke in the display queue context to update the UI. Should be `void
* func(state_type)` signature.
* @param state_func The callback function to invoke to fetch the updated state from ZMK core.
* Should be `state type func(const zmk_event_t *eh)` signature.
* @retval listner##_init Generates a function `listener##_init` that should be called by the widget
* once ready to be updated.
* @retval listener##_init Generates a function `listener##_init` that should be called by the
* widget once ready to be updated.
**/
#define ZMK_DISPLAY_WIDGET_LISTENER(listener, state_type, cb, state_func) \
K_MUTEX_DEFINE(listener##_mutex); \

View File

@ -181,7 +181,7 @@ static void release_captured_events() {
//
// Events for different mod-tap instances are separated by a NULL pointer.
//
// The first event popped will never be catched by the next active hold-tap
// The first event popped will never be caught by the next active hold-tap
// because to start capturing a mod-tap-key-down event must first completely
// go through the events queue.
//

View File

@ -57,6 +57,9 @@ static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
uint32_t hold_time = k_uptime_get() - data->press_start;
if (hold_time > config->hold_time_ms) {
if (IS_ENABLED(CONFIG_ZMK_SPLIT) && IS_ENABLED(CONFIG_ZMK_SPLIT_ROLE_CENTRAL)) {
k_sleep(K_MSEC(100));
}
zmk_pm_soft_off();
} else {
LOG_INF("Not triggering soft off: held for %d and hold time is %d", hold_time,

View File

@ -162,7 +162,7 @@ static int setup_candidates_for_first_keypress(int32_t position, int64_t timesta
static int filter_candidates(int32_t position) {
// this code iterates over candidates and the lookup together to filter in O(n)
// assuming they are both sorted on key_position_len, virtal_key_position
// assuming they are both sorted on key_position_len, virtual_key_position
int matches = 0, lookup_idx = 0, candidate_idx = 0;
while (lookup_idx < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY &&
candidate_idx < CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY) {

View File

@ -173,7 +173,7 @@ static int ksbb_pm_action(const struct device *dev, enum pm_device_action action
struct ksbb_data ksbb_data_##n = {}; \
PM_DEVICE_DT_INST_DEFINE(n, ksbb_pm_action); \
DEVICE_DT_INST_DEFINE(n, ksbb_init, PM_DEVICE_DT_INST_GET(n), &ksbb_data_##n, \
&ksbb_config_##n, POST_KERNEL, \
&ksbb_config_##n, APPLICATION, \
CONFIG_ZMK_KSCAN_SIDEBAND_BEHAVIORS_INIT_PRIORITY, &ksbb_api);
DT_INST_FOREACH_STATUS_OKAY(KSBB_INST)

View File

@ -24,7 +24,7 @@ config ZMK_SPLIT_PERIPHERAL_HID_INDICATORS
bool "Peripheral HID Indicators"
depends on ZMK_HID_INDICATORS
help
Enable propogating the HID (LED) Indicator state to the split peripheral(s).
Enable propagating the HID (LED) Indicator state to the split peripheral(s).
#ZMK_SPLIT
endif

View File

@ -585,7 +585,7 @@ static bool split_central_eir_found(const bt_addr_le_t *addr) {
return false;
}
LOG_DBG("Initiating new connnection");
LOG_DBG("Initiating new connection");
struct bt_le_conn_param *param =
BT_LE_CONN_PARAM(CONFIG_ZMK_SPLIT_BLE_PREF_INT, CONFIG_ZMK_SPLIT_BLE_PREF_INT,
CONFIG_ZMK_SPLIT_BLE_PREF_LATENCY, CONFIG_ZMK_SPLIT_BLE_PREF_TIMEOUT);

View File

@ -7,7 +7,7 @@
mod_morph: mod_morph {
compatible = "zmk,behavior-mod-morph";
#binding-cells = <0>;
bindings = <&kp A>, <&kp LS(B)>; // implict mod overwrite
bindings = <&kp A>, <&kp LS(B)>; // implicit mod overwrite
mods = <(MOD_LSFT|MOD_RSFT)>;
};
};

View File

@ -19,7 +19,7 @@ There's been lots of various activity in ZMK land!
- Tons of [documentation](/docs) work.
- Refactoring ([#73](https://github.com/zmkfirmware/zmk/pull/73), [#74](https://github.com/zmkfirmware/zmk/pull/74)) of [keymaps](/docs/features/keymaps) to make them simpler for users.
- Mod-Tap Behavior (docs coming!) is much improved ([#69](https://github.com/zmkfirmware/zmk/pull/69)) and usable now.
- An initial [`setup.sh`](http://localhost:3000/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
- An initial [`setup.sh`](/docs/user-setup#user-config-setup-script) script was created, allowing users to quickly bootstrap a "user config" setup and push it to GitHub, where GitHub Actions will build the firmware for you.
- Corne shield ([#80](https://github.com/zmkfirmware/zmk/pull/80)) shield definition was added.
- Initial [encoder](/docs/features/encoders) support ([#61](https://github.com/zmkfirmware/zmk/pull/61)) was added.

View File

@ -61,7 +61,7 @@ Once the container has rebuilt, VS Code will be running the 2.5 Docker image.
The following steps will get you building ZMK locally against Zephyr 2.5:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View File

@ -62,7 +62,7 @@ Once the container has rebuilt, VS Code will be running the 3.0 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.0:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View File

@ -132,7 +132,7 @@ Another persistent bug that Apple users experienced was related to crashes and p
The long awaited locality enhancement was finally merged by [petejohanson] in [#547](https://github.com/zmkfirmware/zmk/pull/547), allowing more fine grained control of where certain behaviors are invoked. Some key improvements thanks to the changes:
- [RGB Underglow](/docs/features/underglow) behaviors now run globally, so enabling/disabling RGB, changing the color, animation, etc. applies to both sides of a split properly.
- [Reset](/docs/behaviors/reset#reset)/[Bootloader](/docs/behaviors/reset#bootloader) behaviors now run wherever the key was pressed. For example, adding a `&bootloader` reference to the peripheral side of a split will now put that side of the split into the bootloader when pressed.
- [Reset](/docs/behaviors/reset#reset)/[Bootloader](/docs/behaviors/reset#bootloader-reset) behaviors now run wherever the key was pressed. For example, adding a `&bootloader` reference to the peripheral side of a split will now put that side of the split into the bootloader when pressed.
#### Split Connections

View File

@ -57,7 +57,7 @@ and then update it as appropriate to build the right shields/boards for your con
### Upgrade a manual script
If you have a custom GitHub Actions workflow you need to maintain for some reason, you can update the workflow to to use the `stable` Docker image tag for the build:
If you have a custom GitHub Actions workflow you need to maintain for some reason, you can update the workflow to use the `stable` Docker image tag for the build:
- Open `.github/workflows/build.yml` in your editor/IDE
- Change `zmkfirmware/zmk-build-arm:2.5` to `zmkfirmware/zmk-build-arm:stable` wherever it is found
@ -87,7 +87,7 @@ Once the container has rebuilt, VS Code will be running the 3.2 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.2:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Install the latest version of `west` by running `pip3 install --user --update west`.
- pull the latest ZMK `main` with `git pull` for your ZMK checkout
- run `west update` to pull the updated Zephyr version and its dependencies

View File

@ -145,7 +145,7 @@ I should note that, as a native English speaker and typer, I don't use any of th
## Keyboard Latency Testing
The last project I want to mention is a tool for testing keyboard latency. It requires only a Rasbperry Pi, an optocoupler IC, a resistor, and some wire. If you've ever wondered how ZMK's latency compares to other keyboards, you can [check the results here](https://github.com/joelspadin/keyboard-latency-tester/blob/main/results/chart.ipynb)!
The last project I want to mention is a tool for testing keyboard latency. It requires only a Raspberry Pi, an optocoupler IC, a resistor, and some wire. If you've ever wondered how ZMK's latency compares to other keyboards, you can [check the results here](https://github.com/joelspadin/keyboard-latency-tester/blob/main/results/chart.ipynb)!
I don't have a very large collection of keyboards though, so the data is pretty limited so far. If you want to try it on your own keyboard, see the instructions on the [keyboard latency tester README](https://github.com/joelspadin/keyboard-latency-tester), and please send me a PR with your results!

View File

@ -70,7 +70,7 @@ Once the container has rebuilt, VS Code will be running the 3.5 Docker image.
The following steps will get you building ZMK locally against Zephyr 3.5:
- Run the updated [toolchain installation](/docs/development/setup#toolchain-installation) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Run the updated [toolchain installation](/docs/development/setup) steps, and once completed, remove the previously installed SDK version (optional, existing SDK should still work)
- Install the latest version of `west` by running `pip3 install --user --update west`.
- Pull the latest ZMK `main` with `git pull` for your ZMK checkout
- Run `west update` to pull the updated Zephyr version and its dependencies

View File

@ -7,7 +7,7 @@ sidebar_label: Caps Word
The caps word behavior behaves similar to a caps lock, but will automatically deactivate when any key not in a continue list is pressed, or if the caps word key is pressed again. For smaller keyboards using [mod-taps](/docs/behaviors/mod-tap), this can help avoid repeated alternating holds when typing words in all caps.
The modifiers are applied only to to the alphabetic (`A` to `Z`) keycodes, to avoid automatically applying them to numeric values, etc.
The modifiers are applied only to the alphabetic (`A` to `Z`) keycodes, to avoid automatically applying them to numeric values, etc.
### Behavior Binding

View File

@ -46,10 +46,10 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
## Reset behaviors
| Binding | Behavior | Description |
| ------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `&sys_reset` | [Reset](reset.md#reset) | Resets the keyboard and re-runs the firmware flashed to the device |
| `&bootloader` | [Bootloader](reset.md#bootloader) | Resets the keyboard and puts it into bootloader mode, allowing you to flash new firmware |
| Binding | Behavior | Description |
| ------------- | --------------------------------------- | ---------------------------------------------------------------------------------------- |
| `&sys_reset` | [Reset](reset.md#reset) | Resets the keyboard and re-runs the firmware flashed to the device |
| `&bootloader` | [Bootloader](reset.md#bootloader-reset) | Resets the keyboard and puts it into bootloader mode, allowing you to flash new firmware |
## Output selection behaviors

View File

@ -18,7 +18,7 @@ Definition file: [zmk/app/Kconfig](https://github.com/zmkfirmware/zmk/blob/main/
:::note[Default setting]
While `CONFIG_ZMK_BATTERY_REPORTING` is disabled by default it is implied by `CONFIG_ZMK_BLE`, thus any board with BLE enabled will have this automatically enabled unless explicitly overriden.
While `CONFIG_ZMK_BATTERY_REPORTING` is disabled by default it is implied by `CONFIG_ZMK_BLE`, thus any board with BLE enabled will have this automatically enabled unless explicitly overridden.
:::

View File

@ -9,10 +9,10 @@ See [Configuration Overview](index.md) for instructions on how to change these s
## Kconfig
| Option | Type | Description | Default |
| -------------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` | bool | Enables a combination of settings that are planned to be default in future versions of ZMK to improve connection stability. This includes changes to timing on BLE pairing initation, restores use of the updated/new LLCP implementation, and disables 2M PHY support. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC` | bool | Enables a combination of settings that are planned to be officially supported in the future. This includes enabling BT Secure Connection passkey entry, and allows overwrite of keys from previously paired hosts. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES` | bool | Aggregate config that enables both `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` and `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC`. | n |
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts.) | n |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |
| Option | Type | Description | Default |
| -------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` | bool | Enables a combination of settings that are planned to be default in future versions of ZMK to improve connection stability. This includes changes to timing on BLE pairing initiation, restores use of the updated/new LLCP implementation, and disables 2M PHY support. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC` | bool | Enables a combination of settings that are planned to be officially supported in the future. This includes enabling BT Secure Connection passkey entry, and allows overwrite of keys from previously paired hosts. | n |
| `CONFIG_ZMK_BLE_EXPERIMENTAL_FEATURES` | bool | Aggregate config that enables both `CONFIG_ZMK_BLE_EXPERIMENTAL_CONN` and `CONFIG_ZMK_BLE_EXPERIMENTAL_SEC`. | n |
| `CONFIG_ZMK_BLE_PASSKEY_ENTRY` | bool | Enable passkey entry during pairing for enhanced security. (Note: After enabling this, you will need to re-pair all previously paired hosts.) | n |
| `CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION` | bool | Low level setting for GATT subscriptions. Set to `n` to work around an annoying Windows bug with battery notifications. | y |

View File

@ -81,10 +81,6 @@ Definition file: [zmk/app/module/dts/bindings/kscan/zmk,kscan-gpio-direct.yaml](
| `toggle-mode` | bool | Use toggle switch mode. | n |
| `wakeup-source` | bool | Mark this kscan instance as able to wake the keyboard from deep sleep | n |
By default, a switch will drain current through the internal pull up/down resistor whenever it is pressed. This is not ideal for a toggle switch, where the switch may be left in the "pressed" state for a long time. Enabling `toggle-mode` will make the driver flip between pull up and down as the switch is toggled to optimize for power.
`toggle-mode` applies to all switches handled by the instance of the driver. To use a toggle switch with other, non-toggle, direct GPIO switches, create two instances of the direct GPIO driver, one with `toggle-mode` and the other without. Then, use a [composite driver](#composite-driver) to combine them.
Assuming the switches connect each GPIO pin to the ground, the [GPIO flags](https://docs.zephyrproject.org/3.5.0/hardware/peripherals/gpio.html#api-reference) for the elements in `input-gpios` should be `(GPIO_ACTIVE_LOW | GPIO_PULL_UP)`:
```dts
@ -98,6 +94,25 @@ Assuming the switches connect each GPIO pin to the ground, the [GPIO flags](http
};
```
By default, a switch will drain current through the internal pull up/down resistor whenever it is pressed. This is not ideal for a toggle switch, where the switch may be left in the "pressed" state for a long time. Enabling `toggle-mode` will make the driver enable and disable the internal pull up/down resistor as needed when the switch is toggled to minimise power draw. For `toggle-mode` to work correctly each pole of the switch needs a dedicated GPIO pin.
`toggle-mode` applies to all switches handled by the instance of the driver. To use a toggle switch with other, non-toggle, direct GPIO switches, create two instances of the direct GPIO driver, one with `toggle-mode` and the other without. Then, use a [composite driver](#composite-driver) to combine them. The state of the switch is read on power on, so if the switch is moved whilst the board is off this will get correctly interpreted by the driver.
When using `toggle-mode` the pull resistors get automatically set by the driver and should not be set in the devicetree via GPIO flags. Assuming the common pole of the switch is connected to ground with an SP3T switch:
```dts
kscan_sp3t_toggle: kscan_sp3t_toggle {
compatible = "zmk,kscan-gpio-direct";
toggle-mode;
input-gpios
= <&pro_micro 4 GPIO_ACTIVE_LOW>
, <&pro_micro 3 GPIO_ACTIVE_LOW>
, <&pro_micro 2 GPIO_ACTIVE_LOW>
;
};
```
## Matrix Driver
Keyboard scan driver where keys are arranged on a matrix with one GPIO per row and column.

View File

@ -31,7 +31,7 @@ Making changes to any of the settings in this section modifies the HID report de
| Config | Type | Description | Default |
| ------------------------------------- | ---- | -------------------------------------------------------------- | ------- |
| `CONFIG_ZMK_HID_INDICATORS` | bool | Enable reciept of HID/LED indicator state from connected hosts | n |
| `CONFIG_ZMK_HID_INDICATORS` | bool | Enable receipt of HID/LED indicator state from connected hosts | n |
| `CONFIG_ZMK_HID_CONSUMER_REPORT_SIZE` | int | Number of consumer keys simultaneously reportable | 6 |
Exactly zero or one of the following options may be set to `y`. The first is used if none are set.

View File

@ -40,7 +40,7 @@ If you need to, a review of [Learn The Basics Of Git In Under 10 Minutes](https:
:::
:::note
It is also possible to build firmware locally on your computer by following the [toolchain setup](development/setup.mdx) and
It is also possible to build firmware locally on your computer by following the [toolchain setup](development/setup/index.md) and
[building instructions](development/build-flash.mdx), which includes pointers to
[building using your `zmk-config` folder](development/build-flash.mdx#building-from-zmk-config-folder).
:::

View File

@ -554,7 +554,7 @@ Add additional bindings as necessary to match the default number of encoders on
### GitHub Actions
Using GitHub Actions to build your new firmware can save you from doing any local [development setup](./setup.mdx),
Using GitHub Actions to build your new firmware can save you from doing any local [development setup](./setup/index.md),
at the expense of a longer feedback loop if there are issues. To push your changes and trigger a build:
- Add all your pending changes with `git add .`
@ -566,7 +566,7 @@ Once pushed, click on the "Actions" tab of the repo you created in the first ste
### Local Build
:::note
To build locally, be sure you've followed the [development setup](./setup.mdx) guide first.
To build locally, be sure you've followed the [development setup](./setup/index.md) guide first.
:::
Once you've fully created the new keyboard shield definition,

View File

@ -1,322 +0,0 @@
---
title: Toolchain Setup
sidebar_label: Toolchain Setup
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
export const OsTabs = (props) => (
<Tabs
groupId="operating-systems"
defaultValue="debian"
values={[
{ label: "VS Code & Docker", value: "docker" },
{ label: "Debian/Ubuntu", value: "debian" },
{ label: "Windows", value: "win" },
{ label: "macOS", value: "mac" },
{ label: "Raspberry OS", value: "raspberryos" },
{ label: "Fedora", value: "fedora" },
]}
>
{/* eslint-disable-next-line */}
{props.children}
</Tabs>
);
This guide will show you how to set up a development environment for building ZMK locally.
## Install Dependencies
Click the operating system you are using. (The VS Code & Docker option can be used on any OS.)
<OsTabs>
<TabItem value="docker">
This option use the same [Docker image which is used by the GitHub action](https://github.com/zmkfirmware/zmk-docker) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach is also the easiest to set up. No toolchain or dependencies are necessary when using Docker; the container image you'll be using already has the toolchain installed and set up to use.
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for your operating system.
2. Install [Visual Studio Code](https://code.visualstudio.com/)
3. Install the [Remote - Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
:::info
The docker container already includes `west`. Skip past the following section to [Get Source Code](#get-source-code).
:::
</TabItem>
<TabItem value="debian">
Open Zephyr's [Getting Started Guide](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html) and follow the instructions under these sections:
- [Select and Update OS](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#select-and-update-os)
- [Install Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-dependencies)
- [Install Zephyr SDK](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-zephyr-sdk)
Return to this guide once you are finished with each section.
</TabItem>
<TabItem value="win">
Open Zephyr's [Getting Started Guide](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html) and follow the instructions under these sections:
- [Select and Update OS](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#select-and-update-os)
- [Install Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-dependencies)
- [Install Zephyr SDK](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-zephyr-sdk)
Return to this guide once you are finished with each section.
`dfu-util` is required to flash devices that use DFU, but there is currently no maintained package for it on Chocolatey. [QMK Toolbox](https://github.com/qmk/qmk_toolbox) contains a working version of it though.
</TabItem>
<TabItem value="mac">
Open Zephyr's [Getting Started Guide](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html) and follow the instructions under these sections:
- [Select and Update OS](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#select-and-update-os)
- [Install Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-dependencies)
- [Install Zephyr SDK](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-zephyr-sdk)
Return to this guide once you are finished with each section.
</TabItem>
<TabItem value="raspberryos">
#### Install Base Dependencies
Open Zephyr's [Getting Started Guide](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html) and follow the instructions for Ubuntu under these sections:
- [Select and Update OS](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#select-and-update-os)
- [Install Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-dependencies)
Return to this guide once you are finished with each section.
#### Install Cross-Compile Toolchain
Because Raspberry OS runs on the same architecture (but different ABI) as ARM keyboard MCUs, the operating system's installed [cross compilers](https://docs.zephyrproject.org/3.5.0/develop/toolchains/other_x_compilers.html) can be used to target the different ABI. Building for non-ARM MCUs has not been tested.
First, the cross compiler should be installed:
```sh
sudo apt install gcc-arm-none-eabi
```
Next, we'll configure Zephyr with some [environment variables](https://docs.zephyrproject.org/3.5.0/develop/env_vars.html#env-vars) needed to find the cross compiler. Create a file named `~/.zephyrrc` if it doesn't exist, and add these lines to it:
```sh
export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
export CROSS_COMPILE=/usr/bin/arm-none-eabi-
```
</TabItem>
<TabItem value="fedora">
Follow Zephyr's [Install Linux Host Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/installation_linux.html) documentation for Fedora.
</TabItem>
</OsTabs>
### Install West
`west` is the [Zephyr® Project's meta-tool](https://docs.zephyrproject.org/3.5.0/develop/west/index.html) used to configure and build Zephyr OS applications.
West can be installed by using the `pip` python package manager. The [Zephyr™ instructions](https://docs.zephyrproject.org/3.5.0/develop/west/install.html) are summarized here:
<Tabs
defaultValue="linux"
groupId="python-os"
values={[
{label: 'Linux', value: 'linux'},
{label: 'Windows', value: 'win'},
{label: 'macOS', value: 'mac'},
]}>
<TabItem value="linux">
Install west:
```sh
pip3 install --user -U west
```
Verify that west is installed:
```sh
west --version
```
This should print a message like "West version: v0.14.0". If it prints an error instead, make sure `~/.local/bin` is on your `PATH` environment variable. You can add it with these commands:
```sh
echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
source ~/.bashrc
```
</TabItem>
<TabItem value="win">
Install west:
```sh
pip3 install -U west
```
Verify that west is installed:
```sh
west --version
```
This should print a message like "West version: v0.14.0". If it prints an error instead, make sure that the Python scripts directory is on your `PATH` environment variable. You can add it by opening a PowerShell window and running the following commands:
```powershell
$Scripts = python -c "import sysconfig; print(sysconfig.get_path('scripts'))"
$Path = [Environment]::GetEnvironmentVariable('PATH', 'User')
[Environment]::SetEnvironmentVariable('PATH', "$Path;$Scripts", 'User')
$env:PATH += ";$Scripts"
```
</TabItem>
<TabItem value="mac">
Install west:
```sh
pip3 install -U west
```
</TabItem>
</Tabs>
## Get Source Code
Next, you'll need to clone the ZMK source repository if you haven't already. Navigate to the folder you would like to place your `zmk` directory in and run the following command:
```
git clone https://github.com/zmkfirmware/zmk.git
```
## Initialize & Update Zephyr Workspace
Since ZMK is built as a Zephyr™ application, the next step is
to use `west` to initialize and update your workspace. The ZMK
Zephyr™ application is in the `app/` source directory:
### Step into the repository
<OsTabs>
<TabItem value="debian">
```sh
cd zmk
```
</TabItem>
<TabItem value="raspberryos">
```sh
cd zmk
```
</TabItem>
<TabItem value="fedora">
```sh
cd zmk
```
</TabItem>
<TabItem value="mac">
```sh
cd zmk
```
</TabItem>
<TabItem value="win">
```sh
cd zmk
```
</TabItem>
<TabItem value="docker">
Open the `zmk` checkout folder in VS Code. The repository includes a configuration for containerized development, so an alert will pop up:
![VS Code Dev Container Configuration Alert](../assets/dev-setup/vscode_devcontainer.png)
Click `Reopen in Container` in order to reopen the VS Code with the running container.
The first time you do this on your machine, it will pull the docker image down from the registry and build the container. Subsequent launches are much faster!
:::warning
All subsequent steps must be performed from the VS Code terminal _inside_ the container.
:::
</TabItem>
</OsTabs>
### Initialize the Application
```sh
west init -l app/
```
### Update to Fetch Modules
```sh
west update
```
:::tip
This step pulls down quite a bit of tooling. Go grab a cup of coffee, it can take 10-15 minutes even on a good internet connection!
:::
:::info
If you're using Docker, you're done with setup! You must restart the container at this point. The easiest way to do so is to close the VS Code window, verify that the container has stopped in Docker Dashboard, and reopen the container with VS Code.
Once your container is restarted, proceed to [Building and Flashing](development/build-flash.mdx).
:::
### Export Zephyr CMake package
This allows CMake to load the code needed to build ZMK.
```sh
west zephyr-export
```
### Install Zephyr Python Dependencies
Some additional Python dependencies are listed in Zephyr's `scripts/requirements.txt` file.
<Tabs
defaultValue="linux"
groupId="python-os"
values={[
{label: 'Linux', value: 'linux'},
{label: 'Windows', value: 'win'},
{label: 'macOS', value: 'mac'},
]}>
<TabItem value="linux">
```sh
pip3 install --user -r zephyr/scripts/requirements.txt
```
</TabItem>
<TabItem value="win">
```sh
pip3 install -r zephyr/scripts/requirements.txt
```
</TabItem>
<TabItem value="mac">
```sh
pip3 install -r zephyr/scripts/requirements.txt
```
</TabItem>
</Tabs>

View File

@ -0,0 +1,53 @@
---
title: Docker
sidebar_label: Docker
---
:::note
Currently the Docker approach is only documented for [VS Code](https://github.com/microsoft/vscode) (not [Code OSS](https://github.com/microsoft/vscode/wiki/Differences-between-the-repository-and-Visual-Studio-Code)). While it can be replicated using [devcontainers](https://containers.dev/) this is not documented yet - contributions are welcome!
:::
### Source Code
First, you'll need to clone the ZMK source repository if you haven't already. Open a terminal and navigate to the folder you would like to place your `zmk` directory in, then run the following command:
```sh
git clone https://github.com/zmkfirmware/zmk.git
```
### Installing Development Tools
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) for your operating system.
2. Install [VS Code](https://code.visualstudio.com/).
3. Install the [Remote - Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers).
### Initialize & Update Zephyr Workspace
Open the `zmk` checkout folder in VS Code. The repository includes a configuration for containerized development, so an alert will pop up:
![VS Code Dev Container Configuration Alert](../../assets/dev-setup/vscode_devcontainer.png)
Click `Reopen in Container` in order to reopen the VS Code with the running container. If the alert fails to pop up or you accidentally close it, you can perform the same action by pressing `ctrl+shift+p` and selecting `Remote: Show Remote Menu`.
The first time you do this on your machine, it will pull the docker image down from the registry and build the container. Subsequent launches are much faster!
:::caution
The following step and any future [build commands](../build-flash.mdx) must be executed from the VS Code terminal _inside_ the container.
:::
Initialize the application and update to fetch modules, including Zephyr:
```sh
west init -l app/
west update
```
:::tip
This step pulls down quite a bit of tooling, be patient!
:::
:::info
You must restart the container at this point. The easiest way to do so is to close the VS Code window, verify that the container has stopped in Docker Dashboard, and reopen the container with VS Code.
Your setup is complete once your container has restarted.
:::

View File

@ -0,0 +1,20 @@
---
title: Getting Started
sidebar_label: Getting Started
---
:::tip
We recommend reading through the setup process before following it step by step, to ensure that you are happy with installing the required dependencies.
:::
## Environment Setup
There are two ways to set up the ZMK development environment:
- [Docker](/docs/development/setup/docker): \
A self-contained development environment. It uses the same [Docker image which is used by the GitHub action](https://github.com/zmkfirmware/zmk-docker) for local development. Beyond the benefits of [dev/prod parity](https://12factor.net/dev-prod-parity), this approach may be easier to set up for some operating systems. No toolchain or dependencies are necessary when using Docker; the container image has the toolchain installed and set up to use.
- [Native](/docs/development/setup/native):\
This uses your operating system directly. Usually runs slightly faster than the Docker approach, and can be preferable for users who already have the dependencies on their system.
Please see the [Docker](/docs/development/setup/docker) instructions or [native](/docs/development/setup/native) instructions to continue setup.

View File

@ -0,0 +1,353 @@
---
title: Native Setup
sidebar_label: Native
---
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
export const OsTabs = (props) => (
<Tabs
groupId="operating-system"
defaultValue="ubuntu"
values={[
{ label: "Ubuntu", value: "ubuntu" },
{ label: "Windows", value: "win" },
{ label: "Mac OS", value: "mac" }
]}
>
{/* eslint-disable-next-line */}
{props.children}
</Tabs>
);
export const OsNoteTabs = (props) => (
<Tabs
groupId="operating-system"
defaultValue="win"
values={[
{ label: "Windows", value: "win" },
{ label: "Raspberry OS", value: "raspberryos" },
]}
>
{/* eslint-disable-next-line */}
{props.children}
</Tabs>
);
export const EnvTabs = (props) => (
<Tabs
groupId="python-environment"
defaultValue="venv"
values={[
{ label: "Install within Virtual Environment", value: "venv" },
{ label: "Install globally", value: "glob" },
]}
>
{/* eslint-disable-next-line */}
{props.children}
</Tabs>
);
export const WinTermTabs = (props) => (
<Tabs
groupId="windows-terminal-choice"
defaultValue="cmd"
values={[
{ label: "Command Prompt", value: "cmd" },
{ label: "Powershell", value: "ps" },
]}
>
{/* eslint-disable-next-line */}
{props.children}
</Tabs>
);
## 1. Install Zephyr Dependencies
Open Zephyr's [Getting Started Guide](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html) and follow the instructions under these sections:
- [Select and Update OS](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#select-and-update-os)
- [Install Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-dependencies)
:::info
Zephyr's [Install Linux Host Dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/installation_linux.html) page may be of use for users of Linux distributions which are not based on Ubuntu.
:::
## 2. Source Code
Next, you'll need to clone the ZMK source repository if you haven't already. Open a terminal and navigate to the folder you would like to place your `zmk` directory in, then run the following command:
```sh
git clone https://github.com/zmkfirmware/zmk.git
```
Then step into the repository.
```sh
cd zmk
```
## 3. Get Zephyr and install Python dependencies
:::note
These steps are very similar to Zephyr's [Get Zephyr and install Python dependencies](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#get-zephyr-and-install-python-dependencies) instructions, but specialized for ZMK.
:::
<EnvTabs>
<TabItem value="venv">
<Tabs groupId="operating-systems" defaultValue="ubuntu">
<TabItem value="ubuntu" label="Ubuntu">
1. Use `apt` to install Python `venv` package:
```sh
sudo apt install python3-venv
```
2. Create a new virtual environment and activate it:
```sh
python3 -m venv .venv
source .venv/bin/activate
```
</TabItem>
<TabItem value="win" label="Windows">
1. Create a new virtual environment:
```sh
python -m venv .venv
```
2. Activate the virtual environment:
<WinTermTabs>
<TabItem value="cmd">
```sh
.venv\Scripts\activate.bat
```
</TabItem>
<TabItem value="ps">
```powershell
.venv\Scripts\Activate.ps1
```
</TabItem>
</WinTermTabs>
</TabItem>
<TabItem value="mac" label="Mac OS">
1. Create a new virtual environment:
```sh
python3 -m venv .venv
```
2. Activate the virtual environment:
```sh
source .venv/bin/activate
```
</TabItem>
</Tabs>
Once activated your shell will be prefixed with `(.venv)`. The virtual environment can be deactivated at any time by running `deactivate`.
:::note
Remember to activate the virtual environment every time you start working.
:::
4. Install west:
```sh
pip install west
```
5. Initialize the application and update to fetch modules, including Zephyr:
```sh
west init -l app/
west update
```
:::tip
This step pulls down quite a bit of tooling, be patient!
:::
6. Export a [Zephyr CMake package](https://docs.zephyrproject.org/3.5.0/build/zephyr_cmake_package.html#cmake-pkg). This allows CMake to automatically load boilerplate code required for building Zephyr applications.
```sh
west zephyr-export
```
7. Install the additional dependencies found in Zephyr's `requirements-base.txt`:
```sh
pip install -r zephyr/scripts/requirements-base.txt
```
</TabItem>
<TabItem value="glob">
<Tabs groupId="operating-systems" defaultValue="ubuntu">
<TabItem value="ubuntu" label="Ubuntu">
1. Install `west`:
```sh
pip3 install --user -U west
```
:::note
You need `~/.local/bin` to be on your `PATH` environment variable; verify that it is by running
```sh
west --version
```
If this prints an error rather than a `west` version number, then add `~/.local/bin` to your `PATH`:
```sh
echo 'export PATH=~/.local/bin:"$PATH"' >> ~/.bashrc
source ~/.bashrc
```
:::
</TabItem>
<TabItem value="win" label="Windows">
1. Install `west`:
```sh
pip install -U west
```
:::note
You need the Python scripts directory to be on your PATH environment variable; verify that it is by running
```sh
west --version
```
If this prints an error rather than a `west` version number, then add said directory to your `PATH` with PowerShell:
```powershell
$Scripts = python -c "import sysconfig; print(sysconfig.get_path('scripts'))"
$Path = [Environment]::GetEnvironmentVariable('PATH', 'User')
[Environment]::SetEnvironmentVariable('PATH', "$Path;$Scripts", 'User')
$env:PATH += ";$Scripts"
```
:::
</TabItem>
<TabItem value="mac" label="Mac OS">
1. Install `west`:
```sh
pip3 install -U west
```
</TabItem>
</Tabs>
2. Initialize the application and update to fetch modules, including Zephyr:
```sh
west init -l app/
west update
```
:::tip
This step pulls down quite a bit of tooling, be patient!
:::
3. Export a [Zephyr CMake package](https://docs.zephyrproject.org/3.5.0/build/zephyr_cmake_package.html#cmake-pkg). This allows CMake to automatically load boilerplate code required for building Zephyr applications.
```sh
west zephyr-export
```
<Tabs groupId="operating-systems" defaultValue="ubuntu" className="secrettabs">
<TabItem value="ubuntu" label="Ubuntu">
4. Install the additional dependencies found in Zephyr's `requirements-base.txt`:
```sh
pip3 install --user -r zephyr/scripts/requirements-base.txt
```
</TabItem>
<TabItem value="win" label="Windows">
4. Install the additional dependencies found in Zephyr's `requirements-base.txt`:
```sh
pip install -r zephyr/scripts/requirements-base.txt
```
</TabItem>
<TabItem value="mac" label="Mac OS">
4. Install the additional dependencies found in Zephyr's `requirements-base.txt`.
```sh
pip3 install -r zephyr/scripts/requirements-base.txt
```
</TabItem>
</Tabs>
</TabItem>
</EnvTabs>
## 4. Install Zephyr SDK
Return to Zephyr's Getting Started Guide and [Install Zephyr SDK](https://docs.zephyrproject.org/3.5.0/develop/getting_started/index.html#install-zephyr-sdk).
### OS specific notes
<OsNoteTabs>
<TabItem value="win">
`dfu-util` is required to flash devices that use DFU, but there is currently
no maintained package for it on Chocolatey. [QMK
Toolbox](https://github.com/qmk/qmk_toolbox) contains a working version of it
though.
</TabItem>
<TabItem value="raspberryos">
#### Install Cross-Compile Toolchain
Because Raspberry OS runs on the same architecture (but different ABI) as ARM keyboard MCUs, the operating system's installed [cross compilers](https://docs.zephyrproject.org/3.5.0/develop/toolchains/other_x_compilers.html) can be used to target the different ABI. Building for non-ARM MCUs has not been tested.
First, the cross compiler should be installed:
```sh
sudo apt install gcc-arm-none-eabi
```
Next, we'll configure Zephyr with some [environment variables](https://docs.zephyrproject.org/3.5.0/develop/env_vars.html#env-vars) needed to find the cross compiler. Create a file named `~/.zephyrrc` if it doesn't exist, and add these lines to it:
```sh
export ZEPHYR_TOOLCHAIN_VARIANT=cross-compile
export CROSS_COMPILE=/usr/bin/arm-none-eabi-
```
</TabItem>
</OsNoteTabs>
Your setup is now complete.

View File

@ -58,7 +58,7 @@ config LED_PWM
endif # ZMK_BACKLIGHT
```
Create a `<board>-pinctrl.dtsi` file if it does not already exist, and include it at the beginning of the `<board>.dts` file. `CONFIG_PINCTRL=y` must be added to to `<board>_defconfig` if it isn't already enabled.
Create a `<board>-pinctrl.dtsi` file if it does not already exist, and include it at the beginning of the `<board>.dts` file. `CONFIG_PINCTRL=y` must be added to `<board>_defconfig` if it isn't already enabled.
The pinctrl file has a `&pinctrl` node that encompasses all pinctrl settings, including I2C or SPI peripherals (e.g. WS2812 LEDs, Battery fuel gauges):

View File

@ -34,7 +34,7 @@ macOS 14.x (Sonoma) Finder may report an "Error code -36" when copying `<firmwar
### CMake Error
An error along the lines of `CMake Error at (zmk directory)/zephyr/cmake/generic_toolchain.cmake:64 (include): include could not find load file:` during firmware compilation indicates that the Zephyr Environment Variables are not properly defined.
For more information, see [toolchain setup documentation](../docs/development/setup.mdx).
For more information, see [Zephyr's CMake Package](https://docs.zephyrproject.org/3.5.0/build/zephyr_cmake_package.html).
### West Build Errors

View File

@ -31,6 +31,7 @@ module.exports = {
"linker-script",
"log",
"powershell",
"diff",
],
theme,
darkTheme,
@ -79,7 +80,7 @@ module.exports = {
},
{
label: "Development",
to: "docs/development/setup/",
to: "docs/development/setup",
},
],
},

View File

@ -76,7 +76,16 @@ module.exports = {
"development/clean-room",
"development/pre-commit",
"development/documentation",
"development/setup",
{
type: "category",
label: "Setup",
collapsed: true,
items: [
"development/setup/index",
"development/setup/docker",
"development/setup/native",
],
},
"development/build-flash",
"development/boards-shields-keymaps",
"development/posix-board",

View File

@ -46,3 +46,7 @@
width: 100%;
height: 100%;
}
.secrettabs {
display: none;
}

View File

@ -308,6 +308,6 @@ if ($github_repo -ne "") {
if ($github_repo -imatch "https") {
$actions = "$($github_repo.substring(0, $github_repo.length - 4))/actions"
Write-Host "Your firmware should be availalbe from GitHub Actions shortly: $actions"
Write-Host "Your firmware should be available from GitHub Actions shortly: $actions"
}
}

View File

@ -297,7 +297,7 @@ if [ -n "$github_repo" ]; then
exit 1
fi
# TODO: Support determing the actions URL when non-https:// repo URL is used.
# TODO: Support determining the actions URL when non-https:// repo URL is used.
if [ "${github_repo}" != "${github_repo#https://}" ]; then
echo "Your firmware should be available from GitHub Actions shortly: ${github_repo%.git}/actions"
fi