#!/usr/bin/env bash set -e ###### ###### Build and output configuration ###### build_version () { GIT_VERSION="$(cd "$(find_sketch)"; git describe --abbrev=4 --dirty --always)" LIB_VERSION="$(cd "$(find_sketch)"; (grep version= ../../library.properties 2>/dev/null || echo version=0.0.0) | cut -d= -f2)-g${GIT_VERSION}" BUILD_PATH="${BUILD_PATH:-"$(mktemp -d 2>/dev/null || mktemp -d -t 'build')"}" OUTPUT_DIR="${OUTPUT_DIR:-output/${LIBRARY}}" OUTPUT_PATH="${OUTPUT_PATH:-${SOURCEDIR}/${OUTPUT_DIR}}" } build_filenames () { OUTPUT_FILE_PREFIX="${SKETCH}-${LIB_VERSION}" HEX_FILE_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.hex" HEX_FILE_WITH_BOOTLOADER_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}-with-bootloader.hex" ELF_FILE_PATH="${OUTPUT_PATH}/${OUTPUT_FILE_PREFIX}.elf" } firmware_size () { if [ "${BOARD}" = "virtual" ]; then echo "[Size not computed for virtual build]" return fi ## This is a terrible hack, please don't hurt me. - algernon MAX_PROG_SIZE=28672 output="$($@ | grep "\\(Program\\|Data\\):" | sed -e 's,^, - ,' && echo)" PROGSIZE="$(echo "${output}" | grep "Program:" | cut -d: -f2 | awk '{print $1}')" PERCENT="$(echo "${PROGSIZE}" "${MAX_PROG_SIZE}" | awk "{ printf \"%02.01f\", \$1 / \$2 * 100 }")" echo "${output}" | sed -e "s/\(Program:.*\)(\([0-9\.]*%\) Full)/\1(${PERCENT}% Full)/" } find_sketch () { SKETCH="${SKETCH:-${DEFAULT_SKETCH}}" LIBRARY="${LIBRARY:-${SKETCH}}" if [ -z "${SKETCH}" ] || [ -z "${LIBRARY}" ] || [ -z "${ROOT}" ] || [ -z "${SOURCEDIR}" ]; then echo "SKETCH, LIBRARY, SOURCEDIR, and ROOT need to be set before including this file!" >&2 exit 1 fi for path in "examples/${LIBRARY}" \ "src" \ "."; do if [ -f "${path}/${SKETCH}.ino" ]; then echo "${path}" return fi done echo "Couldn't find sketch (.ino file)" >&2 exit 1 } prepare_to_flash () { if [ ! -e "${HEX_FILE_PATH}" ]; then compile size fi echo "Press ENTER when ready..." read } flash () { prepare_to_flash reset_device sleep 3s find_bootloader_ports flash_over_usb || flash_over_usb } flash_over_usb () { if [ -z "${DEVICE_PORT_BOOTLOADER}" ]; then echo 'DEVICE_PORT_BOOTLOADER is empty (did you hold "Prog" to enable bootloader mode?)' >&2 return 1 fi sleep 1s ${AVRDUDE} -q -q -C ${AVRDUDE_CONF} -p${MCU} -cavr109 -D -P ${DEVICE_PORT_BOOTLOADER} -b57600 "-Uflash:w:${HEX_FILE_PATH}:i" } flash_from_bootloader() { prepare_to_flash find_bootloader_ports flash_over_usb || flash_over_usb } program() { prepare_to_flash flash_with_programmer } flash_with_programmer() { ${AVRDUDE} -v \ -C ${AVRDUDE_CONF} \ -p${MCU} \ -cusbtiny \ -D \ -B 1 \ "-Uflash:w:${HEX_FILE_PATH}:i" } hex_with_bootloader () { if [ ! -e "${HEX_FILE_PATH}" ]; then compile fi awk '/^:00000001FF/ == 0' "${HEX_FILE_PATH}" > "${HEX_FILE_WITH_BOOTLOADER_PATH}" echo "Using ${BOOTLOADER_PATH}" ${MD5} ${BOOTLOADER_PATH} cat "${BOOTLOADER_PATH}" >> "${HEX_FILE_WITH_BOOTLOADER_PATH}" ln -sf -- "${HEX_FILE_WITH_BOOTLOADER_PATH}" "${OUTPUT_PATH}/${SKETCH}-latest-with-bootloader.hex" cat <<- EOF Combined firmware and bootloader are now at ${HEX_FILE_WITH_BOOTLOADER_PATH} Make sure you have the bootloader version you expect. And TEST THIS ON REAL HARDWARE BEFORE YOU GIVE IT TO ANYONE EOF } build () { compile $@ size $@ } compile () { build_version build_filenames install -d "${OUTPUT_PATH}" echo "Building ${OUTPUT_DIR}/${SKETCH} (${LIB_VERSION}) ..." ${compile_HOOKS} if [ -d "${ARDUINO_LOCAL_LIB_PATH}/libraries" ]; then local_LIBS="-libraries \"${ARDUINO_LOCAL_LIB_PATH}/libraries\"" fi ARDUINO_PACKAGES="" if [ -d ${ARDUINO_PACKAGE_PATH} ]; then ARDUINO_PACKAGES="-hardware \"${ARDUINO_PACKAGE_PATH}\"" fi ${ARDUINO_BUILDER} \ -compile \ ${ARDUINO_PACKAGES} \ -hardware "${ARDUINO_PATH}/hardware" \ -hardware "${BOARD_HARDWARE_PATH}" \ ${ARDUINO_TOOLS_PARAM} \ -tools "${ARDUINO_PATH}/tools-builder" \ -fqbn "${FQBN}" \ -libraries "." \ -libraries "${ROOT}" \ -libraries "${BOARD_HARDWARE_PATH}/.." \ ${local_LIBS} \ ${EXTRA_BUILDER_ARGS} \ -build-path "${BUILD_PATH}" \ -ide-version "${ARDUINO_IDE_VERSION}" \ -prefs "compiler.cpp.extra_flags=-std=c++11 -Woverloaded-virtual -Wno-unused-parameter -Wno-unused-variable -Wno-ignored-qualifiers ${ARDUINO_CFLAGS} ${LOCAL_CFLAGS}" \ -warnings all \ ${ARDUINO_VERBOSE} \ ${ARDUINO_AVR_GCC_PREFIX_PARAM} \ "$(find_sketch)/${SKETCH}.ino" cp "${BUILD_PATH}/${SKETCH}.ino.hex" "${HEX_FILE_PATH}" cp "${BUILD_PATH}/${SKETCH}.ino.elf" "${ELF_FILE_PATH}" ln -sf "${OUTPUT_FILE_PREFIX}.hex" "${OUTPUT_PATH}/${SKETCH}-latest.hex" ln -sf "${OUTPUT_FILE_PREFIX}.elf" "${OUTPUT_PATH}/${SKETCH}-latest.elf" if [ "${ARDUINO_VERBOSE}" = "-verbose" ]; then echo "Build artifacts can be found in ${BUILD_PATH}"; else rm -rf "${BUILD_PATH}" fi } _find_all () { for plugin in ./*.ino \ examples/* \ src/*.ino; do if [ -d "$(dirname ${plugin})" ] || [ -f "${plugin}" ]; then p="$(basename "${plugin}" .ino)" if [ "${p}" != '*' ]; then echo "${p}" fi fi done | sort } build_all () { plugins="$(_find_all)" for plugin in ${plugins}; do export SKETCH="${plugin}" export LIBRARY="${plugin}" $0 ${plugin} build done } size () { if [ ! -e "${HEX_FILE_PATH}" ]; then compile fi echo "- Size: firmware/${LIBRARY}/${OUTPUT_FILE_PREFIX}.elf" firmware_size "${AVR_SIZE}" -C --mcu="${MCU}" "${ELF_FILE_PATH}" echo } size_map () { if [ ! -e "${HEX_FILE_PATH}" ]; then compile fi "${AVR_NM}" --size-sort -C -r -l -t decimal "${ELF_FILE_PATH}" } disassemble () { if [ ! -e "${HEX_FILE_PATH}" ]; then compile fi "${AVR_OBJDUMP}" -C -d "${ELF_FILE_PATH}" } decompile () { disassemble } clean () { rm -rf -- "${OUTPUT_PATH}" } reset_device() { find_device_port check_device_port reset_device_cmd } check_device_port () { if [ -z "$DEVICE_PORT" ]; then cat <&2 Couldn't autodetect the keyboard's serial port. If you see this message and your keyboard is connected to your computer, it probably means that our serial port detection logic is buggy or incomplete. Please report this issue at https://github.com/keyboardio/Kaleidoscope EOF exit 1 elif echo "$DEVICE_PORT" | grep -q '[[:space:]]'; then cat <&2 Unexpected whitespace found in detected serial port: $DEVICE_PORT If you see this message, it means that our serial port detection logic is buggy or incomplete. Please report this issue at https://github.com/keyboardio/Kaleidoscope EOF exit 1 fi if ! [ -w "$DEVICE_PORT" ]; then cat <&2 $DEVICE_PORT is not writable: `ls -l $DEVICE_PORT` You are currently in the following groups: `id -Gn` Please ensure you have followed the instructions on setting up your account to be in the right group: https://github.com/keyboardio/Kaleidoscope/wiki/Install-Arduino-support-on-Linux EOF exit 1 fi } usage () { cat <