default: @just --list --unsorted config := absolute_path('config') build := absolute_path('.build') out := absolute_path('firmware') draw := absolute_path('draw') # parse combos.dtsi and adjust settings to not run out of slots _parse_combos: #!/usr/bin/env bash set -euo pipefail cconf="{{ config / 'combos.dtsi' }}" if [[ -f $cconf ]]; then # set MAX_COMBOS_PER_KEY to the most frequent combos count count=$( tail -n +10 $cconf | grep -Eo '[LR][TMBH][0-9]' | sort | uniq -c | sort -nr | awk 'NR==1{print $1}' ) sed -Ei "/CONFIG_ZMK_COMBO_MAX_COMBOS_PER_KEY/s/=.+/=$count/" "{{ config }}"/*.conf echo "Setting MAX_COMBOS_PER_KEY to $count" # set MAX_KEYS_PER_COMBO to the most frequent key count count=$( tail -n +10 $cconf | grep -o -n '[LR][TMBH][0-9]' | cut -d : -f 1 | uniq -c | sort -nr | awk 'NR==1{print $1}' ) sed -Ei "/CONFIG_ZMK_COMBO_MAX_KEYS_PER_COMBO/s/=.+/=$count/" "{{ config }}"/*.conf echo "Setting MAX_KEYS_PER_COMBO to $count" fi # parse build.yaml and filter targets by expression _parse_targets $expr: #!/usr/bin/env bash attrs="[.board, .shield, .snippet]" filter="(($attrs | map(. // [.]) | combinations), ((.include // {})[] | $attrs)) | join(\",\")" echo "$(yq -r "$filter" build.yaml | grep -v "^," | grep -i "${expr/#all/.*}")" # build firmware for single board & shield combination _build_single $board $shield $snippet *west_args: #!/usr/bin/env bash set -euo pipefail artifact="${shield:+${shield// /+}-}${board}" build_dir="{{ build / '$artifact' }}" echo "Building firmware for $artifact..." west build -s zmk/app -d "$build_dir" -b $board {{ west_args }} ${snippet:+-S "$snippet"} -- \ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DZMK_CONFIG="{{ config }}" ${shield:+-DSHIELD="$shield"} if [[ -f "$build_dir/zephyr/zmk.uf2" ]]; then mkdir -p "{{ out }}" && cp "$build_dir/zephyr/zmk.uf2" "{{ out }}/$artifact.uf2" else mkdir -p "{{ out }}" && cp "$build_dir/zephyr/zmk.bin" "{{ out }}/$artifact.bin" fi # build firmware for matching targets build expr *west_args: _parse_combos #!/usr/bin/env bash set -euo pipefail targets=$(just _parse_targets {{ expr }}) [[ -z $targets ]] && echo "No matching targets found. Aborting..." >&2 && exit 1 echo "$targets" | while IFS=, read -r board shield snippet; do just _build_single "$board" "$shield" "$snippet" {{ west_args }} done just draw # clear build cache and artifacts clean: rm -rf {{ build }} {{ out }} # clear all automatically generated files clean-all: clean rm -rf .west zmk # clear nix cache clean-nix: nix-collect-garbage --delete-old # parse & plot keymap draw: #!/usr/bin/env bash set -euo pipefail echo "Parsing keymap..." keymap -c "{{ draw }}/config.yaml" parse -z "{{ config }}/corne.keymap" >"{{ draw }}/base.yaml" echo "Drawing vector graphics..." keymap -c "{{ draw }}/config.yaml" draw "{{ draw }}/base.yaml" >"{{ draw }}/base.svg" # put inkscape command here echo "Converting to png..." inkscape --export-type png --export-filename {{ draw }}/keymap.png --export-dpi 300 --export-background=gray {{ draw }}/base.svg > /dev/null 2>&1 # initialize west init: west init -l config west update west zephyr-export # list build targets list: @just _parse_targets all | sed 's/,$//' | sort | column # update west update: west update # upgrade zephyr-sdk and python dependencies upgrade-sdk: nix flake update --flake . # Flash the firmware hardflash side: #!/usr/bin/env bash if [[ {{side}} == "left" || {{side}} == "right" ]]; then echo "Flashing: {{side}}" file {{out}}/corne_{{side}}+nice_view_adapter+nice_view-nice_nano_v2.uf2 || exit cp {{out}}/corne_{{side}}+nice_view_adapter+nice_view-nice_nano_v2.uf2 /run/media/fic/NICENANO else echo "Provide either 'left' or 'right'!" exit 1 fi flash side="both" gem="gem": #!/usr/bin/env bash timeout=30 elapsed=0 function fl { echo "Flashing: $1" if [[ {{gem}} != "nogem" ]]; then GEM="_gem" echo "Flashing with gem, use flash [side] nogem to disable!" else echo "Flashing without gem!" fi FILE="{{out}}/corne_$1+nice_view_adapter+nice_view$GEM-nice_nano_v2.uf2" # Verify the file exists before proceeding file $FILE || exit 1 echo "Waiting for /run/media/fic/NICENANO to appear..." # Wait for the directory with a timeout using `until` until [[ -d "/run/media/fic/NICENANO" ]] || ((elapsed >= timeout)); do sleep 1 ((elapsed++)) done # Check if the timeout was reached if ((elapsed >= timeout)); then echo "Timeout reached! NICENANO drive not found." exit 1 else echo "NICENANO drive found, flashing now..." fi # Copy the file after the directory is detected cp $FILE /run/media/fic/NICENANO echo "Flashing done." } if [[ {{side}} == "left" || {{side}} == "right" ]]; then fl "{{side}}" elif [[ {{side}} == "both" ]]; then fl "left" echo "Preparing to flash other side, remove keyboard..." timer=5 until ((timer == 0)); do echo "$timer" sleep 1 ((timer--)) done echo "Flashing other side." sleep 1 fl "right" else echo "Provide either 'left' or 'right'!" exit 1 fi