summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorDrashna Jael're <drashna@live.com>2021-06-29 12:23:03 -0700
committerDrashna Jael're <drashna@live.com>2021-06-29 12:24:07 -0700
commitacf2c323e2927f6007b17ded577cf49fd86fec6c (patch)
tree8334dc5c71e6ab9bf33c76143eac7bb0e60159b0 /util
parentec7a7beeed3046e9144d4c4ce0ef3b2c4f9e4341 (diff)
parentf55e39e8a2246f6f96fd5d4a84a866e2615cde7b (diff)
Merge upstream QMK Firmware at '0.12.52~1'
Diffstat (limited to 'util')
-rwxr-xr-xutil/atmega32a_program.py105
-rwxr-xr-xutil/audio_generate_dac_lut.py67
-rwxr-xr-xutil/chibios_conf_updater.sh184
-rwxr-xr-xutil/docker_build.sh42
-rw-r--r--util/drivers.txt3
-rwxr-xr-xutil/install/debian.sh2
-rwxr-xr-xutil/install/fedora.sh2
-rwxr-xr-xutil/install/freebsd.sh2
-rwxr-xr-xutil/install/gentoo.sh2
-rwxr-xr-xutil/install/msys2.sh2
-rwxr-xr-xutil/install/void.sh2
-rwxr-xr-xutil/linux_install.sh245
-rwxr-xr-xutil/list_keyboards.sh12
-rwxr-xr-xutil/macos_install.sh30
-rwxr-xr-xutil/new_keyboard.sh13
-rwxr-xr-xutil/new_project.sh70
-rwxr-xr-xutil/qmk_install.sh15
-rw-r--r--util/qmk_tab_complete.sh2
-rwxr-xr-xutil/rules_cleaner.sh40
-rwxr-xr-xutil/sample_parser.py39
-rwxr-xr-xutil/travis_utils.sh25
-rw-r--r--util/udev/50-qmk.rules2
-rwxr-xr-xutil/wavetable_parser.py40
23 files changed, 469 insertions, 477 deletions
diff --git a/util/atmega32a_program.py b/util/atmega32a_program.py
deleted file mode 100755
index b777b91106..0000000000
--- a/util/atmega32a_program.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017 Luiz Ribeiro <luizribeiro@gmail.com>, Sebastian Kaim <sebb@sebb767.de>
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import print_function
-
-import os
-import sys
-import time
-import usb
-
-
-def checkForKeyboardInNormalMode():
- """Returns a device if a ps2avrGB device in normal made (that is in keyboard mode) or None if it is not found."""
- return usb.core.find(idVendor=0x20A0, idProduct=0x422D)
-
-def checkForKeyboardInBootloaderMode():
- """Returns True if a ps2avrGB device in bootloader (flashable) mode is found and False otherwise."""
- return (usb.core.find(idVendor=0x16c0, idProduct=0x05df) is not None)
-
-def flashKeyboard(firmware_file):
- """Calls bootloadHID to flash the given file to the device."""
- print('Flashing firmware to device ...')
- if os.system('bootloadHID -r "%s"' % firmware_file) == 0:
- print('\nDone!')
- else:
- print('\nbootloadHID returned an error.')
-
-def printDeviceInfo(dev):
- """Prints all infos for a given USB device"""
- print('Device Information:')
- print(' idVendor: %d (0x%04x)' % (dev.idVendor, dev.idVendor))
- print(' idProduct: %d (0x%04x)' % (dev.idProduct, dev.idProduct))
- print('Manufacturer: %s' % (dev.iManufacturer))
- print('Serial: %s' % (dev.iSerialNumber))
- print('Product: %s' % (dev.iProduct), end='\n\n')
-
-def sendDeviceToBootloaderMode(dev):
- """Tries to send a given ps2avrGB keyboard to bootloader mode to allow flashing."""
- try:
- dev.set_configuration()
-
- request_type = usb.util.build_request_type(
- usb.util.CTRL_OUT,
- usb.util.CTRL_TYPE_CLASS,
- usb.util.CTRL_RECIPIENT_DEVICE)
-
- USBRQ_HID_SET_REPORT = 0x09
- HID_REPORT_OPTION = 0x0301
-
- dev.ctrl_transfer(request_type, USBRQ_HID_SET_REPORT, HID_REPORT_OPTION, 0, [0, 0, 0xFF] + [0] * 5)
- except usb.core.USBError:
- # for some reason I keep getting USBError, but it works!
- pass
-
-
-if len(sys.argv) < 2:
- print('Usage: %s <firmware.hex>' % sys.argv[0])
- sys.exit(1)
-
-kb = checkForKeyboardInNormalMode()
-
-if kb is not None:
- print('Found a keyboard in normal mode. Attempting to send it to bootloader mode ...', end='')
- sendDeviceToBootloaderMode(kb)
- print(' done.')
- print("Hint: If your keyboard can't be set to bootloader mode automatically, plug it in while pressing the bootloader key to do so manually.")
- print(" You can find more infos about this here: https://github.com/qmk/qmk_firmware/tree/master/keyboards/ps2avrGB#setting-the-board-to-bootloader-mode")
-
-attempts = 12 # 60 seconds
-found = False
-for attempt in range(1, attempts + 1):
- print("Searching for keyboard in bootloader mode (%i/%i) ... " % (attempt, attempts), end='')
-
- if checkForKeyboardInBootloaderMode():
- print('Found', end='\n\n')
- flashKeyboard(sys.argv[1])
- found = True
- break
- else:
- print('Nothing.', end='')
-
- if attempt != attempts: # no need to wait on the last attempt
- print(' Sleeping 5 seconds.', end='')
- time.sleep(5)
-
- # print a newline
- print()
-
-if not found:
- print("Couldn't find a flashable keyboard. Aborting.")
- sys.exit(2)
-
diff --git a/util/audio_generate_dac_lut.py b/util/audio_generate_dac_lut.py
new file mode 100755
index 0000000000..c31ba3d7ee
--- /dev/null
+++ b/util/audio_generate_dac_lut.py
@@ -0,0 +1,67 @@
+#!/usr/bin/env python3
+#
+# Copyright 2020 JohSchneider
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+AUDIO_DAC_BUFFER_SIZE=256
+AUDIO_DAC_SAMPLE_MAX=4095
+
+def plot(values):
+ for v in values:
+ print('0'* int(v * 80/AUDIO_DAC_SAMPLE_MAX))
+
+def to_lut(values):
+ for v in values:
+ print(hex(int(v)), end=", ")
+
+
+from math import sin, tau, pi
+
+samples=[]
+
+def sampleSine():
+ for s in range(AUDIO_DAC_BUFFER_SIZE):
+ samples.append((sin((s/AUDIO_DAC_BUFFER_SIZE)*tau - pi/2) + 1 )/2* AUDIO_DAC_SAMPLE_MAX)
+
+def sampleTriangle():
+ for s in range(AUDIO_DAC_BUFFER_SIZE):
+ if s < AUDIO_DAC_BUFFER_SIZE/2:
+ samples.append(s/(AUDIO_DAC_BUFFER_SIZE/2) * AUDIO_DAC_SAMPLE_MAX)
+ else:
+ samples.append(AUDIO_DAC_SAMPLE_MAX - (s-AUDIO_DAC_BUFFER_SIZE/2)/(AUDIO_DAC_BUFFER_SIZE/2) * AUDIO_DAC_SAMPLE_MAX)
+
+#compromise between square and triangle wave,
+def sampleTrapezoidal():
+ for i in range(AUDIO_DAC_BUFFER_SIZE):
+ a=3 #slope/inclination
+ if (i < AUDIO_DAC_BUFFER_SIZE/2):
+ s = a * (i * AUDIO_DAC_SAMPLE_MAX/(AUDIO_DAC_BUFFER_SIZE/2)) + (1-a)*AUDIO_DAC_SAMPLE_MAX/2
+ else:
+ i = i - AUDIO_DAC_BUFFER_SIZE/2
+ s = AUDIO_DAC_SAMPLE_MAX - a * (i * AUDIO_DAC_SAMPLE_MAX/(AUDIO_DAC_BUFFER_SIZE/2)) - (1-a)*AUDIO_DAC_SAMPLE_MAX/2
+
+ if s < 0:
+ s=0
+ if s> AUDIO_DAC_SAMPLE_MAX:
+ s=AUDIO_DAC_SAMPLE_MAX
+ samples.append(s)
+
+
+#sampleSine()
+sampleTrapezoidal()
+#print(samples)
+plot(samples)
+to_lut(samples)
diff --git a/util/chibios_conf_updater.sh b/util/chibios_conf_updater.sh
new file mode 100755
index 0000000000..70bd80da1e
--- /dev/null
+++ b/util/chibios_conf_updater.sh
@@ -0,0 +1,184 @@
+#!/bin/bash
+
+set -eEuo pipefail
+umask 022
+
+sinfo() { echo "$@" >&2 ; }
+shead() { sinfo "" ; sinfo "---------------------------------" ; sinfo "-- $@" ; sinfo "---------------------------------" ; }
+havecmd() { command command type "${1}" >/dev/null 2>&1 || return 1 ; }
+
+this_script="$(realpath "${BASH_SOURCE[0]}")"
+script_dir="$(realpath "$(dirname "$this_script")")"
+qmk_firmware_dir="$(realpath "$script_dir/../")"
+
+declare -A file_hashes
+
+export PATH="$PATH:$script_dir/fmpp/bin"
+
+build_fmpp() {
+ [ -f "$script_dir/fmpp.tar.gz" ] \
+ || wget -O"$script_dir/fmpp.tar.gz" https://github.com/freemarker/fmpp/archive/v0.9.16.tar.gz
+ [ -d "$script_dir/fmpp" ] \
+ || { mkdir "$script_dir/fmpp" && tar xf "$script_dir/fmpp.tar.gz" -C "$script_dir/fmpp" --strip-components=1 ; }
+ pushd "$script_dir/fmpp" >/dev/null 2>&1
+ sed -e "s#bootclasspath.path=.*#bootclasspath.path=$(find /usr/lib/jvm -name 'rt.jar' | sort | tail -n1)#g" \
+ -e "s#ant.jar.path=.*#ant.jar.path=$(find /usr/share/java -name 'ant-1*.jar' | sort | tail -n1)#g" \
+ build.properties.sample > build.properties
+ sed -e 's#source="1.5"#source="1.8"#g' \
+ -e 's#target="1.5"#target="1.8"#g' \
+ build.xml > build.xml.new
+ mv build.xml.new build.xml
+ ant clean
+ ant
+ chmod +x "$script_dir/fmpp/bin/fmpp"
+ popd >/dev/null 2>&1
+}
+
+find_chibi_files() {
+ local search_path="$1"
+ shift
+ local conditions=( "$@" )
+ for file in $(find -L "$search_path" -not -path '*/lib/chibios*' -and -not -path '*/lib/ugfx*' -and -not -path '*/util/*' -and \( "${conditions[@]}" \) | sort) ; do
+ if [ -z "$(grep 'include_next' "$file")" ] ; then
+ echo $file
+ fi
+ done
+}
+
+revert_chibi_files() {
+ local search_path="$1"
+ shead "Reverting ChibiOS config/board files..."
+ for file in $(find_chibi_files "$search_path" -name chconf.h -or -name halconf.h -or -name mcuconf.h -or -name board.c -or -name board.h -or -name board.mk -or -name board.chcfg) ; do
+ pushd "$search_path" >/dev/null 2>&1
+ local relpath=$(realpath --relative-to="$search_path" "$file")
+ git checkout upstream/develop -- "$relpath" || git checkout origin/develop -- "$relpath" || true
+ popd >/dev/null 2>&1
+ done
+}
+
+populate_file_hashes() {
+ local search_path="$1"
+ shead "Determining duplicate config/board files..."
+ for file in $(find_chibi_files "$search_path" -name chconf.h -or -name halconf.h -or -name mcuconf.h -or -name board.c -or -name board.h) ; do
+ local key="file_$(clang-format "$file" | sha1sum | cut -d' ' -f1)"
+ local relpath=$(realpath --relative-to="$search_path" "$file")
+ file_hashes[$key]="${file_hashes[$key]:-} $relpath"
+ done
+ for file in $(find_chibi_files "$search_path" -name board.mk -or -name board.chcfg) ; do
+ local key="file_$(cat "$file" | sha1sum | cut -d' ' -f1)"
+ local relpath=$(realpath --relative-to="$search_path" "$file")
+ file_hashes[$key]="${file_hashes[$key]:-} $relpath"
+ done
+}
+
+determine_equivalent_files() {
+ local search_file="$1"
+ for K in "${!file_hashes[@]}"; do
+ for V in ${file_hashes[$K]}; do
+ if [[ "$V" == "$search_file" ]] ; then
+ for V in ${file_hashes[$K]}; do
+ echo "$V"
+ done
+ return 0
+ fi
+ done
+ done
+ return 1
+}
+
+deploy_staged_files() {
+ shead "Deploying staged files..."
+ for file in $(find "$qmk_firmware_dir/util/chibios-upgrade-staging" -type f) ; do
+ local relpath=$(realpath --relative-to="$qmk_firmware_dir/util/chibios-upgrade-staging" "$file")
+ sinfo "Deploying staged file: $relpath"
+ for other in $(determine_equivalent_files "$relpath") ; do
+ sinfo " => $other"
+ cp "$qmk_firmware_dir/util/chibios-upgrade-staging/$relpath" "$qmk_firmware_dir/$other"
+ done
+ done
+}
+
+swap_mcuconf_f3xx_f303() {
+ shead "Swapping STM32F3xx_MCUCONF -> STM32F303_MCUCONF..."
+ for file in $(find_chibi_files "$qmk_firmware_dir" -name mcuconf.h) ; do
+ sed -i 's#STM32F3xx_MCUCONF#STM32F303_MCUCONF#g' "$file"
+ dos2unix "$file" >/dev/null 2>&1
+ done
+}
+
+upgrade_conf_files_generic() {
+ local search_filename="$1"
+ local update_script="$2"
+ shead "Updating $search_filename files ($update_script)..."
+ pushd "$qmk_firmware_dir/lib/chibios/tools/updater" >/dev/null 2>&1
+ for file in $(find_chibi_files "$qmk_firmware_dir" -name "$search_filename") ; do
+ cp -f "$file" "$file.orig"
+ clang-format --style='{IndentPPDirectives: None}' -i "$file"
+ cp -f "$file" "$file.formatted"
+ bash "$update_script" "$file"
+ if ! diff "$file" "$file.formatted" >/dev/null 2>&1 ; then
+ dos2unix "$file" >/dev/null 2>&1
+ else
+ cp -f "$file.orig" "$file"
+ fi
+ rm -f "$file.orig" "$file.formatted"
+ done
+ popd >/dev/null 2>&1
+}
+
+upgrade_chconf_files() {
+ upgrade_conf_files_generic chconf.h update_chconf_rt.sh
+}
+
+upgrade_halconf_files() {
+ upgrade_conf_files_generic halconf.h update_halconf.sh
+
+ OIFS=$IFS
+ IFS=$'\n'
+ for file in $(find_chibi_files "$qmk_firmware_dir" -name halconf.h) ; do
+ echo $file
+ sed -i 's@#include "mcuconf.h"@#include <mcuconf.h>@g' "$file"
+ done
+ IFS=$OIFS
+}
+
+upgrade_mcuconf_files() {
+ pushd "$qmk_firmware_dir/lib/chibios/tools/updater" >/dev/null 2>&1
+ for f in $(find . -name 'update_mcuconf*') ; do
+ upgrade_conf_files_generic mcuconf.h $f
+ done
+ popd >/dev/null 2>&1
+}
+
+update_staged_files() {
+ shead "Updating staged files with ChibiOS upgraded versions..."
+ for file in $(find "$qmk_firmware_dir/util/chibios-upgrade-staging" -type f) ; do
+ local relpath=$(realpath --relative-to="$qmk_firmware_dir/util/chibios-upgrade-staging" "$file")
+ sinfo "Updating staged file: $relpath"
+ cp "$qmk_firmware_dir/$relpath" "$qmk_firmware_dir/util/chibios-upgrade-staging/$relpath"
+ done
+}
+
+havecmd fmpp || build_fmpp
+revert_chibi_files "$qmk_firmware_dir"
+populate_file_hashes "$qmk_firmware_dir"
+
+shead "Showing duplicate ChibiOS files..."
+for K in "${!file_hashes[@]}"; do
+ sinfo ${K#file_}:
+ for V in ${file_hashes[$K]}; do
+ sinfo " $V"
+ done
+done
+
+if [ "${1:-}" == "-r" ] ; then
+ exit 0
+fi
+
+swap_mcuconf_f3xx_f303
+
+deploy_staged_files
+upgrade_mcuconf_files
+upgrade_chconf_files
+upgrade_halconf_files
+update_staged_files
diff --git a/util/docker_build.sh b/util/docker_build.sh
index 7106344690..2c2a26e776 100755
--- a/util/docker_build.sh
+++ b/util/docker_build.sh
@@ -17,12 +17,27 @@ done
if [ $# -gt 1 ]; then
errcho "$USAGE"
exit 1
-elif ! command -v docker >/dev/null 2>&1; then
- errcho "Error: docker not found"
- errcho "See https://docs.docker.com/install/#supported-platforms for installation instructions"
- exit 2
fi
+# Allow $RUNTIME to be overriden by the user as an environment variable
+# Else check if either docker or podman exit and set them as runtime
+# if none are found error out
+if [ -z "$RUNTIME" ]; then
+ if command -v docker >/dev/null 2>&1; then
+ RUNTIME="docker"
+ elif command -v podman >/dev/null 2>&1; then
+ RUNTIME="podman"
+ else
+ errcho "Error: no compatible container runtime found."
+ errcho "Either podman or docker are required."
+ errcho "See https://podman.io/getting-started/installation"
+ errcho "or https://docs.docker.com/install/#supported-platforms"
+ errcho "for installation instructions."
+ exit 2
+ fi
+fi
+
+
# Determine arguments
if [ $# -eq 0 ]; then
printf "keyboard=" && read -r keyboard
@@ -37,21 +52,30 @@ else
exit 1
fi
fi
+if [ -z "$keyboard" ]; then
+ keyboard=all
+fi
if [ -n "$target" ]; then
- if [ "$(uname)" = "Linux" ] || docker-machine active >/dev/null 2>&1; then
- usb_args="--privileged -v /dev/bus/usb:/dev/bus/usb"
- else
+ # IF we are using docker on non Linux and docker-machine isn't working print an error
+ # ELSE set usb_args
+ if [ ! "$(uname)" = "Linux" ] && [ "$RUNTIME" = "docker" ] && ! docker-machine active >/dev/null 2>&1; then
errcho "Error: target requires docker-machine to work on your platform"
errcho "See http://gw.tnode.com/docker/docker-machine-with-usb-support-on-windows-macos"
errcho "Consider flashing with QMK Toolbox (https://github.com/qmk/qmk_toolbox) instead"
exit 3
+ else
+ usb_args="--privileged -v /dev:/dev"
fi
fi
dir=$(pwd -W 2>/dev/null) || dir=$PWD # Use Windows path if on Windows
+if [ "$RUNTIME" = "docker" ]; then
+ uid_arg="--user $(id -u):$(id -g)"
+fi
+
# Run container and build firmware
-docker run --rm -it $usb_args \
- --user $(id -u):$(id -g) \
+"$RUNTIME" run --rm -it $usb_args \
+ $uid_arg \
-w /qmk_firmware \
-v "$dir":/qmk_firmware \
-e ALT_GET_KEYBOARDS=true \
diff --git a/util/drivers.txt b/util/drivers.txt
index c3c5e286b1..1f6c67c4c5 100644
--- a/util/drivers.txt
+++ b/util/drivers.txt
@@ -4,6 +4,8 @@
# Driver can be one of winusb,libusb,libusbk
# Use Windows Powershell and type [guid]::NewGuid() to generate guids
winusb,STM32 Bootloader,0483,DF11,6d98a87f-4ecf-464d-89ed-8c684d857a75
+winusb,APM32 Bootloader,314B,0106,9ff3cc31-6772-4a3f-a492-a80d91f7a853
+winusb,STM32duino Bootloader,1EAF,0003,746915ec-99d8-4a90-a722-3c85ba31e4fe
libusbk,USBaspLoader,16C0,05DC,e69affdc-0ef0-427c-aefb-4e593c9d2724
winusb,Kiibohd DFU Bootloader,1C11,B007,aa5a3f86-b81e-4416-89ad-0c1ea1ed63af
libusb,ATmega16U2,03EB,2FEF,007274da-b75f-492e-a288-8fc0aff8339f
@@ -11,4 +13,5 @@ libusb,ATmega32U2,03EB,2FF0,ddc2c572-cb6e-4f61-a6cc-1a5de941f063
libusb,ATmega16U4,03EB,2FF3,3180d426-bf93-4578-a693-2efbc337da8e
libusb,ATmega32U4,03EB,2FF4,5f9726fd-f9de-487a-9fbd-8b3524a7a56a
libusb,AT90USB64,03EB,2FF9,c6a708ad-e97d-43cd-b04a-3180d737a71b
+libusb,AT90USB162,03EB,2FFA,ef8546f0-ef09-4e7c-8fc2-ffbae1dcd84a
libusb,AT90USB128,03EB,2FFB,fd217df3-59d0-440a-a8f3-4c0c8c84daa3
diff --git a/util/install/debian.sh b/util/install/debian.sh
index 0ae9764a33..885df723d9 100755
--- a/util/install/debian.sh
+++ b/util/install/debian.sh
@@ -5,7 +5,7 @@ DEBCONF_NONINTERACTIVE_SEEN=true
export DEBIAN_FRONTEND DEBCONF_NONINTERACTIVE_SEEN
_qmk_install_prepare() {
- sudo apt-get update
+ sudo apt-get update $SKIP_PROMPT
}
_qmk_install() {
diff --git a/util/install/fedora.sh b/util/install/fedora.sh
index 44b71b98bf..d9452f68d5 100755
--- a/util/install/fedora.sh
+++ b/util/install/fedora.sh
@@ -4,7 +4,7 @@ _qmk_install() {
echo "Installing dependencies"
# TODO: Check whether devel/headers packages are really needed
- sudo dnf -y install \
+ sudo dnf $SKIP_PROMPT install \
clang diffutils git gcc glibc-headers kernel-devel kernel-headers make unzip wget zip \
python3 \
avr-binutils avr-gcc avr-libc \
diff --git a/util/install/freebsd.sh b/util/install/freebsd.sh
index 353c52d647..d9399a5de9 100755
--- a/util/install/freebsd.sh
+++ b/util/install/freebsd.sh
@@ -1,7 +1,7 @@
#!/bin/bash
_qmk_install_prepare() {
- sudo pkg update
+ sudo pkg update $SKIP_PROMPT
}
_qmk_install() {
diff --git a/util/install/gentoo.sh b/util/install/gentoo.sh
index d4284e9a93..97eb5df07f 100755
--- a/util/install/gentoo.sh
+++ b/util/install/gentoo.sh
@@ -23,7 +23,7 @@ _qmk_install() {
sudo emerge -auN sys-devel/gcc
sudo emerge -au --noreplace \
app-arch/unzip app-arch/zip net-misc/wget sys-devel/clang sys-devel/crossdev \
- \>=dev-lang/python-3.6 \
+ \>=dev-lang/python-3.7 \
dev-embedded/avrdude dev-embedded/dfu-programmer app-mobilephone/dfu-util
sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr
diff --git a/util/install/msys2.sh b/util/install/msys2.sh
index c8598a60fa..b1300a34d2 100755
--- a/util/install/msys2.sh
+++ b/util/install/msys2.sh
@@ -1,7 +1,7 @@
#!/bin/bash
_qmk_install_prepare() {
- pacman -Syu
+ pacman -Syu $MSYS2_CONFIRM
}
_qmk_install() {
diff --git a/util/install/void.sh b/util/install/void.sh
index 9ec7019e5c..c49c3ef63f 100755
--- a/util/install/void.sh
+++ b/util/install/void.sh
@@ -3,7 +3,7 @@
_qmk_install() {
echo "Installing dependencies"
- sudo xbps-install \
+ sudo xbps-install $SKIP_PROMPT \
gcc git make wget unzip zip \
python3-pip \
avr-binutils avr-gcc avr-libc \
diff --git a/util/linux_install.sh b/util/linux_install.sh
deleted file mode 100755
index 01518a29d7..0000000000
--- a/util/linux_install.sh
+++ /dev/null
@@ -1,245 +0,0 @@
-#!/bin/sh
-
-# Note: This file uses tabs to indent. Please don't mix tabs and spaces.
-
-GENTOO_WARNING="This script will make a USE change in order to ensure that that QMK works on your system. All changes will be sent to the the file /etc/portage/package.use/qmk_firmware -- please review it, and read Portage's output carefully before installing any packages on your system. You will also need to ensure that your kernel is compiled with support for the keyboard chip that you are using (e.g. enable Arduino for the Pro Micro). Further information can be found on the Gentoo wiki."
-
-SLACKWARE_WARNING="You will need the following packages from slackbuilds.org:\n\tarm-binutils\n\tarm-gcc\n\tavr-binutils\n\tavr-gcc\n\tavr-libc\n\tavrdude\n\tdfu-programmer\n\tdfu-util\n\tnewlib\nThese packages will be installed with sudo and sboinstall, so ensure that your user is added to sudoers and that sboinstall is configured."
-
-SOLUS_INFO="Your tools are now installed. To start using them, open new terminal or source these scripts:\n\t/usr/share/defaults/etc/profile.d/50-arm-toolchain-path.sh\n\t/usr/share/defaults/etc/profile.d/50-avr-toolchain-path.sh"
-
-util_dir=$(dirname "$0")
-
-# For those distros that do not package bootloadHID
-install_bootloadhid() {
- if ! command -v bootloadHID >/dev/null; then
- wget https://www.obdev.at/downloads/vusb/bootloadHID.2012-12-08.tar.gz -O - | tar -xz -C /tmp
- cd /tmp/bootloadHID.2012-12-08/commandline/
- if make; then
- sudo cp bootloadHID /usr/local/bin
- fi
- cd -
- fi
-}
-
-if grep ID /etc/os-release | grep -qE "fedora"; then
- sudo dnf install \
- arm-none-eabi-binutils-cs \
- arm-none-eabi-gcc-cs \
- arm-none-eabi-newlib \
- avr-binutils \
- avr-gcc \
- avr-libc \
- binutils-avr32-linux-gnu \
- clang \
- dfu-util \
- dfu-programmer \
- diffutils \
- git \
- gcc \
- glibc-headers \
- kernel-devel \
- kernel-headers \
- libusb-devel \
- make \
- perl \
- python3 \
- unzip \
- wget \
- zip
-
-elif grep ID /etc/os-release | grep -qE 'debian|ubuntu'; then
- DEBIAN_FRONTEND=noninteractive
- DEBCONF_NONINTERACTIVE_SEEN=true
- export DEBIAN_FRONTEND DEBCONF_NONINTERACTIVE_SEEN
- sudo apt-get update
- sudo apt-get install \
- build-essential \
- avr-libc \
- binutils-arm-none-eabi \
- binutils-avr \
- clang-format \
- dfu-programmer \
- dfu-util \
- diffutils \
- gcc \
- gcc-arm-none-eabi \
- gcc-avr \
- git \
- libnewlib-arm-none-eabi \
- libusb-dev \
- python3 \
- python3-pip \
- unzip \
- wget \
- zip
-
-elif grep ID /etc/os-release | grep -q 'arch\|manjaro'; then
- sudo pacman --needed -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz
- sudo pacman -S --needed \
- arm-none-eabi-binutils \
- arm-none-eabi-gcc \
- arm-none-eabi-newlib \
- avr-binutils \
- avr-libc \
- base-devel \
- clang \
- dfu-programmer \
- dfu-util \
- diffutils \
- gcc \
- git \
- libusb-compat \
- python \
- python-pip \
- unzip \
- wget \
- zip
-
-elif grep ID /etc/os-release | grep -q gentoo; then
- echo "$GENTOO_WARNING" | fmt
- printf "\nProceed (y/N)? "
- read -r answer
- if echo "$answer" | grep -iq "^y"; then
- sudo touch /etc/portage/package.use/qmkfirmware
- # tee is used here since sudo doesn't apply to >>
- echo "sys-devel/gcc multilib" | sudo tee --append /etc/portage/package.use/qmkfirmware >/dev/null
- sudo emerge -auN sys-devel/gcc
- sudo emerge -au --noreplace \
- app-arch/unzip \
- app-arch/zip \
- app-mobilephone/dfu-util \
- dev-embedded/avrdude \
- net-misc/wget \
- sys-devel/clang \
- sys-devel/crossdev
- sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr
- sudo crossdev -s4 --stable --g \<9 --portage --verbose --target arm-none-eabi
- echo "Done!"
- else
- echo "Quitting..."
- fi
-
-elif grep ID /etc/os-release | grep -q sabayon; then
- sudo equo install \
- app-arch/unzip \
- app-arch/zip \
- app-mobilephone/dfu-util \
- dev-embedded/avrdude \
- dev-lang/python \
- net-misc/wget \
- sys-devel/clang \
- sys-devel/gcc \
- sys-devel/crossdev
- sudo crossdev -s4 --stable --g \<9 --portage --verbose --target avr
- sudo crossdev -s4 --stable --g \<9 --portage --verbose --target arm-none-eabi
- echo "Done!"
-
-elif grep ID /etc/os-release | grep -qE "opensuse|tumbleweed"; then
- CROSS_AVR_GCC=cross-avr-gcc8
- CROSS_ARM_GCC=cross-arm-none-gcc8
- if grep ID /etc/os-release | grep -q "15."; then
- CROSS_AVR_GCC=cross-avr-gcc7
- CROSS_ARM_GCC=cross-arm-none-gcc7
- fi
- sudo zypper install \
- avr-libc \
- clang \
- $CROSS_AVR_GCC \
- $CROSS_ARM_GCC \
- cross-avr-binutils \
- cross-arm-none-newlib-devel \
- cross-arm-binutils cross-arm-none-newlib-devel \
- dfu-tool \
- dfu-programmer \
- gcc \
- libusb-devel \
- python3 \
- unzip \
- wget \
- zip
-
-elif grep ID /etc/os-release | grep -q slackware; then
- printf "$SLACKWARE_WARNING\n"
- printf "\nProceed (y/N)? "
- read -r answer
- if echo "$answer" | grep -iq "^y" ;then
- sudo sboinstall \
- avr-binutils \
- avr-gcc \
- avr-libc \
- avrdude \
- dfu-programmer \
- dfu-util \
- arm-binutils \
- arm-gcc \
- newlib \
- python3
- echo "Done!"
- else
- echo "Quitting..."
- fi
-
-elif grep ID /etc/os-release | grep -q solus; then
- sudo eopkg ur
- sudo eopkg it \
- -c system.devel \
- arm-none-eabi-gcc \
- arm-none-eabi-binutils \
- arm-none-eabi-newlib \
- avr-libc \
- avr-binutils \
- avr-gcc \
- avrdude \
- dfu-util \
- dfu-programmer \
- libusb-devel \
- python3 \
- git \
- wget \
- zip \
- unzip
- printf "\n$SOLUS_INFO\n"
-
-elif grep ID /etc/os-release | grep -q void; then
- sudo xbps-install \
- avr-binutils \
- avr-gcc \
- avr-libc \
- cross-arm-none-eabi-binutils \
- cross-arm-none-eabi-gcc \
- cross-arm-none-eabi-newlib \
- avrdude \
- dfu-programmer \
- dfu-util \
- gcc \
- git \
- libusb-compat-devel \
- make \
- wget \
- unzip \
- zip
-
-else
- echo "Sorry, we don't recognize your OS. Help us by contributing support!"
- echo
- echo "https://docs.qmk.fm/#/contributing"
-fi
-
-# Global install tasks
-install_bootloadhid
-pip3 install --user -r ${util_dir}/../requirements.txt
-
-if uname -a | grep -qi microsoft; then
- echo "********************************************************************************"
- echo "* Detected Windows Subsystem for Linux. *"
- echo "* Currently, WSL has no access to USB devices and so flashing from within the *"
- echo "* WSL terminal will not work. *"
- echo "* *"
- echo "* Please install the QMK Toolbox instead: *"
- echo "* https://github.com/qmk/qmk_toolbox/releases *"
- echo "* Then, map your WSL filesystem as a network drive: *"
- echo "* \\\\\\\\wsl$\\<distro> *"
- echo "********************************************************************************"
- echo
-fi
diff --git a/util/list_keyboards.sh b/util/list_keyboards.sh
index 1c103e0f11..aa6ed1c6af 100755
--- a/util/list_keyboards.sh
+++ b/util/list_keyboards.sh
@@ -4,5 +4,15 @@
# This allows us to exclude keyboards by including a .noci file.
find -L keyboards -type f -name rules.mk | grep -v keymaps | sed 's!keyboards/\(.*\)/rules.mk!\1!' | while read keyboard; do
- [ "$1" = "noci" -a -e "keyboards/${keyboard}/.noci" ] || echo "$keyboard"
+ if [ "$1" = "noci" ]; then
+ case "$keyboard" in
+ handwired/*)
+ ;;
+ *)
+ test -e "keyboards/${keyboard}/.noci" || echo "$keyboard"
+ ;;
+ esac
+ else
+ echo "$keyboard"
+ fi
done
diff --git a/util/macos_install.sh b/util/macos_install.sh
deleted file mode 100755
index 810f234ab3..0000000000
--- a/util/macos_install.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-util_dir=$(dirname "$0")
-
-if ! brew --version 2>&1 > /dev/null; then
- echo "Error! Homebrew not installed or broken!"
- echo -n "Would you like to install homebrew now? [y/n] "
- while read ANSWER; do
- case $ANSWER in
- y|Y)
- /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- break
- ;;
- n|N)
- exit 1
- ;;
- *)
- echo -n "Would you like to install homebrew now? [y/n] "
- ;;
- esac
- done
-fi
-
-# All macOS dependencies are managed in the homebrew package:
-# https://github.com/qmk/homebrew-qmk
-brew update
-brew install qmk/qmk/qmk
-brew link --force avr-gcc@8
-
-pip3 install -r "${util_dir}/../requirements.txt"
diff --git a/util/new_keyboard.sh b/util/new_keyboard.sh
index 01458b4f19..cf3339f9a7 100755
--- a/util/new_keyboard.sh
+++ b/util/new_keyboard.sh
@@ -32,8 +32,10 @@ set_git_username() {
# Copy the template files to the new keyboard directory.
copy_templates() {
+ mkdir -p "$keyboard_dir"
+
echo -n "Copying base template files..."
- cp -r "quantum/template/base" "${keyboard_dir}"
+ cp -r "quantum/template/base/." "${keyboard_dir}"
echo " done"
echo -n "Copying $keyboard_type template files..."
@@ -41,8 +43,8 @@ copy_templates() {
echo " done"
echo -n "Renaming keyboard files..."
- mv "${keyboard_dir}/template.c" "${keyboard_dir}/${keyboard_name}.c"
- mv "${keyboard_dir}/template.h" "${keyboard_dir}/${keyboard_name}.h"
+ mv "${keyboard_dir}/keyboard.c" "${keyboard_dir}/${keyboard_base_name}.c"
+ mv "${keyboard_dir}/keyboard.h" "${keyboard_dir}/${keyboard_base_name}.h"
echo " done"
}
@@ -87,10 +89,10 @@ replace_keyboard_placeholders() {
"${keyboard_dir}/config.h"
"${keyboard_dir}/info.json"
"${keyboard_dir}/readme.md"
- "${keyboard_dir}/${keyboard_name}.c"
+ "${keyboard_dir}/${keyboard_base_name}.c"
"${keyboard_dir}/keymaps/default/readme.md"
)
- replace_placeholders "%KEYBOARD%" "$keyboard_name" "${replace_keyboard_filenames[@]}"
+ replace_placeholders "%KEYBOARD%" "$keyboard_base_name" "${replace_keyboard_filenames[@]}"
}
# Replace %YOUR_NAME% with the username.
@@ -134,6 +136,7 @@ echo
while [ -z "$keyboard_name" ]; do
prompt "Keyboard Name" ""
keyboard_name=$prompt_return
+ keyboard_base_name=$(basename $keyboard_name)
done
keyboard_dir="keyboards/$keyboard_name"
diff --git a/util/new_project.sh b/util/new_project.sh
deleted file mode 100755
index 9dec714b02..0000000000
--- a/util/new_project.sh
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-# Script to make a new quantum project
-# Jack Humbert 2015
-
-KEYBOARD=$1
-KEYBOARD_TYPE=$2
-
-if [ -z "$KEYBOARD" ]; then
- echo "Usage: $0 <keyboard_name> <keyboard_type>"
- echo "Example: $0 gh60 avr"
- echo "Example: $0 bfake ps2avrgb"
- exit 1
-elif [ -z "$KEYBOARD_TYPE" ]; then
- KEYBOARD_TYPE=avr
-fi
-
-if [ "$KEYBOARD_TYPE" != "avr" ] && [ "$KEYBOARD_TYPE" != "ps2avrgb" ]; then
- echo "Invalid keyboard type target"
- exit 1
-fi
-
-if [ -e "keyboards/$1" ]; then
- echo "Error! keyboards/$1 already exists!"
- exit 1
-fi
-
-cd "$(dirname "$0")/.." || exit
-
-KEYBOARD_NAME=$(basename "$1")
-KEYBOARD_NAME_UPPERCASE=$(echo "$KEYBOARD_NAME" | awk '{print toupper($0)}')
-NEW_KBD=keyboards/${KEYBOARD}
-
-
-cp -r quantum/template/base "$NEW_KBD"
-cp -r "quantum/template/$KEYBOARD_TYPE/." "$NEW_KBD"
-
-mv "${NEW_KBD}/template.c" "${NEW_KBD}/${KEYBOARD_NAME}.c"
-mv "${NEW_KBD}/template.h" "${NEW_KBD}/${KEYBOARD_NAME}.h"
-find "${NEW_KBD}" -type f -exec sed -i '' -e "s;%KEYBOARD%;${KEYBOARD_NAME};g" {} \;
-find "${NEW_KBD}" -type f -exec sed -i '' -e "s;%KEYBOARD_UPPERCASE%;${KEYBOARD_NAME_UPPERCASE};g" {} \;
-
-GIT=$(whereis git)
-if [ "$GIT" != "" ]; then
- IS_GIT_REPO=$($GIT log >>/dev/null 2>&1; echo $?)
- if [ "$IS_GIT_REPO" -eq 0 ]; then
- ID="$($GIT config --get user.name)"
- read -rp "What is your name? [$ID] " YOUR_NAME
- if [ -n "$YOUR_NAME" ]; then
- ID=$YOUR_NAME
- fi
- echo "Using $ID as user name"
-
- for i in "$NEW_KBD/config.h" \
- "$NEW_KBD/$KEYBOARD_NAME.c" \
- "$NEW_KBD/$KEYBOARD_NAME.h" \
- "$NEW_KBD/keymaps/default/config.h" \
- "$NEW_KBD/keymaps/default/keymap.c"
- do
- awk -v id="$ID" '{sub(/%YOUR_NAME%/,id); print}' < "$i" > "$i.$$"
- mv "$i.$$" "$i"
- done
- fi
-fi
-
-cat <<-EOF
-######################################################
-# $NEW_KBD project created. To start
-# working on things, cd into $NEW_KBD
-######################################################
-EOF
diff --git a/util/qmk_install.sh b/util/qmk_install.sh
index 5076e980a2..943069453a 100755
--- a/util/qmk_install.sh
+++ b/util/qmk_install.sh
@@ -2,6 +2,13 @@
QMK_FIRMWARE_DIR=$(cd -P -- "$(dirname -- "$0")/.." && pwd -P)
QMK_FIRMWARE_UTIL_DIR=$QMK_FIRMWARE_DIR/util
+if [ "$1" = "-y" ]; then
+ SKIP_PROMPT='-y'
+ MSYS2_CONFIRM='--noconfirm'
+else
+ SKIP_PROMPT=''
+ MSYS2_CONFIRM=''
+fi
case $(uname -a) in
*Darwin*)
@@ -25,10 +32,6 @@ case $(uname -a) in
. "$QMK_FIRMWARE_UTIL_DIR/install/fedora.sh";;
*gentoo*)
. "$QMK_FIRMWARE_UTIL_DIR/install/gentoo.sh";;
- *opensuse*|*tumbleweed*)
- . "$QMK_FIRMWARE_UTIL_DIR/install/opensuse.sh";;
- *sabayon*)
- . "$QMK_FIRMWARE_UTIL_DIR/install/sabayon.sh";;
*slackware*)
. "$QMK_FIRMWARE_UTIL_DIR/install/slackware.sh";;
*solus*)
@@ -36,9 +39,9 @@ case $(uname -a) in
*void*)
. "$QMK_FIRMWARE_UTIL_DIR/install/void.sh";;
*)
- echo "Sorry, we don't recognize your distribution. Help us by contributing support!"
+ echo "Sorry, we don't recognize your distribution. Try using the docker image instead:"
echo
- echo "https://docs.qmk.fm/#/contributing"
+ echo "https://docs.qmk.fm/#/getting_started_docker"
exit 1;;
esac
diff --git a/util/qmk_tab_complete.sh b/util/qmk_tab_complete.sh
new file mode 100644
index 0000000000..ebcb5536ac
--- /dev/null
+++ b/util/qmk_tab_complete.sh
@@ -0,0 +1,2 @@
+# Register qmk with tab completion
+eval "$(register-python-argcomplete --no-defaults qmk)"
diff --git a/util/rules_cleaner.sh b/util/rules_cleaner.sh
new file mode 100755
index 0000000000..ac27c2b09b
--- /dev/null
+++ b/util/rules_cleaner.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+
+# This script finds all rules.mk files in keyboards/ subdirectories,
+# and deletes the build option filesize impacts from them.
+
+# Print an error message with the word "ERROR" in red.
+echo_error() {
+ echo -e "[\033[0;91mERROR\033[m]: $1"
+}
+
+# If we've been started from util/, we want to be in qmk_firmware/
+[[ "$PWD" == *util ]] && cd ..
+
+# The root qmk_firmware/ directory should have a subdirectory called quantum/
+if [ ! -d "quantum" ]; then
+ echo_error "Could not detect the QMK firmware directory!"
+ echo_error "Are you sure you're in the right place?"
+ exit 1
+fi
+
+# Set the inplace editing parameter for sed.
+# macOS/BSD sed expects a file extension immediately following -i.
+set_sed_i() {
+ sed_i=(-i)
+
+ case $(uname -a) in
+ *Darwin*) sed_i=(-i "")
+ esac
+}
+set_sed_i
+
+# Exclude keyamps/ directories
+files=$(find keyboards -type f -name 'rules.mk' -not \( -path '*/keymaps*' -prune \))
+
+# Edit rules.mk files
+for file in $files; do
+ sed "${sed_i[@]}" -e "s/(+[0-9].*)$//g" "$file"
+done
+
+echo "Cleaned up rules.mk files."
diff --git a/util/sample_parser.py b/util/sample_parser.py
new file mode 100755
index 0000000000..70e193aee7
--- /dev/null
+++ b/util/sample_parser.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 Jack Humbert
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import wave, struct, sys
+
+waveFile = wave.open(sys.argv[1], 'r')
+# print(str(waveFile.getparams()))
+# sys.exit()
+
+if (waveFile.getsampwidth() != 2):
+ raise(Exception("This script currently only works with 16bit audio files"))
+
+length = waveFile.getnframes()
+out = "#define DAC_SAMPLE_CUSTOM_LENGTH " + str(length) + "\n\n"
+out += "static const dacsample_t dac_sample_custom[" + str(length) + "] = {"
+for i in range(0,length):
+ if (i % 8 == 0):
+ out += "\n "
+ waveData = waveFile.readframes(1)
+ data = struct.unpack("<h", waveData)
+ out += str(int((int(data[0]) + 0x8000) / 16)) + ", "
+out = out[:-2]
+out += "\n};"
+print(out)
diff --git a/util/travis_utils.sh b/util/travis_utils.sh
new file mode 100755
index 0000000000..e949946e22
--- /dev/null
+++ b/util/travis_utils.sh
@@ -0,0 +1,25 @@
+# Use this by sourcing it in your script.
+
+# Provide sane defaults for travis environment
+TRAVIS_BRANCH="${TRAVIS_BRANCH:master}"
+TRAVIS_PULL_REQUEST="${TRAVIS_PULL_REQUEST:false}"
+TRAVIS_COMMIT_MESSAGE="${TRAVIS_COMMIT_MESSAGE:-none}"
+TRAVIS_COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-HEAD~1..HEAD}"
+
+# test force push
+#TRAVIS_COMMIT_RANGE="c287f1bfc5c8...81f62atc4c1d"
+
+# Extra variables
+LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+QMK_CHANGES=$(git diff --name-only -n 1 ${TRAVIS_COMMIT_RANGE})
+NUM_CORE_CHANGES=$(echo "$QMK_CHANGES" | grep -Ec -e '^Makefile' -e '^[^/]*.mk' -e '^drivers/' -e '^lib/atsam' -e '^lib/lib8tion/' -e '^platforms' -e '^quantum' -e '^tests' -e '^tmk_core')
+
+# if docker is installed - patch calls to within the qmk docker image
+if command -v docker >/dev/null; then
+ function make() {
+ docker run --rm -e MAKEFLAGS="$MAKEFLAGS" -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container make "$@"
+ }
+ function qmk() {
+ docker run --rm -w /qmk_firmware/ -v "$PWD":/qmk_firmware --user $(id -u):$(id -g) qmkfm/base_container bin/qmk "$@"
+ }
+fi
diff --git a/util/udev/50-qmk.rules b/util/udev/50-qmk.rules
index 70bd7e6e3e..acaa7dcc58 100644
--- a/util/udev/50-qmk.rules
+++ b/util/udev/50-qmk.rules
@@ -9,6 +9,8 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff3", TAG+="uacc
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff4", TAG+="uaccess"
### AT90USB64
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ff9", TAG+="uaccess"
+### AT90USB162
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffa", TAG+="uaccess"
### AT90USB128
SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2ffb", TAG+="uaccess"
diff --git a/util/wavetable_parser.py b/util/wavetable_parser.py
new file mode 100755
index 0000000000..be0f01f7b4
--- /dev/null
+++ b/util/wavetable_parser.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019 Jack Humbert
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import wave, struct, sys
+
+waveFile = wave.open(sys.argv[1], 'r')
+
+length = waveFile.getnframes()
+out = "#define DAC_WAVETABLE_CUSTOM_LENGTH " + str(int(length / 256)) + "\n\n"
+out += "static const dacsample_t dac_wavetable_custom[" + str(int(length / 256)) + "][256] = {"
+for i in range(0,length):
+ if (i % 8 == 0):
+ out += "\n "
+ if (i % 256 == 0):
+ out = out[:-2]
+ out += "{\n "
+ waveData = waveFile.readframes(1)
+ data = struct.unpack("<h", waveData)
+ out += str(int((int(data[0]) + 0x8000) / 16)) + ", "
+ if (i % 256 == 255):
+ out = out[:-2]
+ out += "\n },"
+out = out[:-1]
+out += "\n};"
+print(out)