summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2021-12-20 20:37:27 +0100
committerHampusM <hampus@hampusmat.com>2021-12-20 20:37:27 +0100
commit72ab3d315269950d59e2f7307ae42db577423d10 (patch)
treef2f7d8b1aa758442c22cd5a584767b526f409928
parent135ecb444644079983de7123a0fdf0c21fa68a14 (diff)
build: add build scripts
-rw-r--r--Makefile10
-rw-r--r--make-scripts/Arduino.mk1358
-rw-r--r--make-scripts/Common.mk138
-rw-r--r--make-scripts/license.txt502
-rw-r--r--tools/reset_leonardo.py109
5 files changed, 2117 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..65fcacf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,10 @@
+ARDUINO_VERSION = 1.8.4
+BOARD_TAG = leonardo
+ARCHITECTURE = avr
+ARDUINO_DIR = $(HOME).arduino15/packages/arduino
+ARDMK_DIR = make-scripts
+AVRDUDE_CONF = /etc/avrdude.conf
+
+ARDUINO_LIBS = Wire GY521
+
+include $(ARDMK_DIR)/Arduino.mk
diff --git a/make-scripts/Arduino.mk b/make-scripts/Arduino.mk
new file mode 100644
index 0000000..908966b
--- /dev/null
+++ b/make-scripts/Arduino.mk
@@ -0,0 +1,1358 @@
+#
+# Makefile for compiling Arduino sketches from command line
+# System part (i.e. project independent)
+#
+# Copyright (C) 2012 Sudar <http://sudarmuthu.com>, based on
+# M J Oldfield work: https://github.com/mjoldfield/Arduino-Makefile
+#
+# Copyright (C) 2010,2011,2012 Martin Oldfield <m@mjo.tc>, based on
+# work that is copyright Nicholas Zambetti, David A. Mellis & Hernando
+# Barragan.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# Adapted from Arduino 0011 Makefile by M J Oldfield
+#
+# Original Arduino adaptation by mellis, eighthave, oli.keller
+#
+# Current version: 1.6.0
+#
+
+arduino_output =
+# When output is not suppressed and we're in the top-level makefile,
+# running for the first time (i.e., not after a restart after
+# regenerating the dependency file), then output the configuration.
+ifndef ARDUINO_QUIET
+ ARDUINO_QUIET = 0
+endif
+ifeq ($(ARDUINO_QUIET),0)
+ ifeq ($(MAKE_RESTARTS),)
+ ifeq ($(MAKELEVEL),0)
+ arduino_output = $(info $(1))
+ endif
+ endif
+endif
+
+include $(ARDMK_DIR)/Common.mk
+
+$(call show_config_variable,ARDMK_DIR,[USER])
+
+ifndef TARGET
+ space :=
+ space +=
+ TARGET = $(notdir $(subst $(space),_,$(CURDIR)))
+endif
+
+$(call show_config_variable,ARDUINO_VERSION,[USER])
+
+ifdef ARDUINO_VERSION
+ ARDUINO_VERSION_SHORT = $(shell sed "s/\.//g" <<< $(ARDUINO_VERSION))
+ $(call show_config_variable,ARDUINO_VERSION_SHORT,[AUTODETECTED])
+endif
+
+$(call show_config_variable,ARCHITECTURE,[USER])
+
+#avoid using shell for known architectures
+ifeq ($(ARCHITECTURE),avr)
+ ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_AVR
+else
+ ARDUINO_ARCH_FLAG = -DARDUINO_ARCH_$(shell echo $(ARCHITECTURE) | tr '[:lower:]' '[:upper:]')
+endif
+
+ARDMK_VENDOR = arduino
+
+$(call show_config_variable,ARDMK_VENDOR,[DEFAULT])
+
+ARDUINO_VAR_PATH = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/variants
+$(call show_config_variable,ARDUINO_VAR_PATH,[COMPUTED],(from ARDUINO_DIR))
+
+BOARDS_TXT = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/boards.txt
+$(call show_config_variable,BOARDS_TXT,[COMPUTED],(from ARDUINO_DIR))
+
+ifeq (,$(wildcard $(BOARDS_TXT)))
+ $(error Currently BOARDS_TXT='$(BOARDS_TXT)', which is not an existing file or an invalid filename.)
+endif
+
+TOOL_PREFIX = avr
+
+CC_NAME := $(TOOL_PREFIX)-gcc
+CXX_NAME := $(TOOL_PREFIX)-g++
+AS_NAME := $(TOOL_PREFIX)-as
+OBJCOPY_NAME := $(TOOL_PREFIX)-objcopy
+OBJDUMP_NAME := $(TOOL_PREFIX)-objdump
+AR_NAME := $(TOOL_PREFIX)-ar
+SIZE_NAME := $(TOOL_PREFIX)-size
+NM_NAME := $(TOOL_PREFIX)-nm
+
+ifndef AVR_TOOLS_DIR
+
+ BUNDLED_AVR_TOOLS_DIR := $(call dir_if_exists,$(ARDUINO_DIR)/hardware/tools/avr)
+
+ ifdef BUNDLED_AVR_TOOLS_DIR
+ AVR_TOOLS_DIR = $(BUNDLED_AVR_TOOLS_DIR)
+ $(call show_config_variable,AVR_TOOLS_DIR,[BUNDLED],(in Arduino distribution))
+
+ # In Linux distribution of Arduino, the path to avrdude and avrdude.conf are different
+ # More details at https://github.com/sudar/Arduino-Makefile/issues/48 and
+ # https://groups.google.com/a/arduino.cc/d/msg/developers/D_m97jGr8Xs/uQTt28KO_8oJ
+ ifeq ($(CURRENT_OS),LINUX)
+
+ ifndef AVRDUDE
+ ifeq ($(shell expr $(ARDUINO_VERSION_SHORT) '>' 157), 1)
+ # 1.5.8 has different location than all prior versions!
+ AVRDUDE = $(AVR_TOOLS_DIR)/bin/avrdude
+ else
+ AVRDUDE = $(AVR_TOOLS_DIR)/../avrdude
+ endif
+ endif
+
+ ifndef AVRDUDE_CONF
+ ifeq ($(shell expr $(ARDUINO_VERSION_SHORT) '>' 157), 1)
+ AVRDUDE_CONF = $(AVR_TOOLS_DIR)/etc/avrdude.conf
+ else
+ AVRDUDE_CONF = $(AVR_TOOLS_DIR)/../avrdude.conf
+ endif
+ endif
+
+ else
+
+ ifndef AVRDUDE_CONF
+ AVRDUDE_CONF = $(AVR_TOOLS_DIR)/etc/avrdude.conf
+ endif
+
+ endif
+
+ else
+
+ SYSTEMPATH_AVR_TOOLS_DIR := $(call dir_if_exists,$(abspath $(dir $(shell which $(CC_NAME)))/..))
+ ifdef SYSTEMPATH_AVR_TOOLS_DIR
+ AVR_TOOLS_DIR = $(SYSTEMPATH_AVR_TOOLS_DIR)
+ $(call show_config_variable,AVR_TOOLS_DIR,[AUTODETECTED],(found in $$PATH))
+ else
+ # One last attempt using $(TOOL_PREFIX)-gcc in case using arm
+ SYSTEMPATH_AVR_TOOLS_DIR := $(call dir_if_exists,$(abspath $(dir $(shell which $($(TOOL_PREFIX)-gcc)))/..))
+ ifdef SYSTEMPATH_AVR_TOOLS_DIR
+ AVR_TOOLS_DIR = $(SYSTEMPATH_AVR_TOOLS_DIR)
+ $(call show_config_variable,AVR_TOOLS_DIR,[AUTODETECTED],(found in $$PATH))
+ else
+ echo $(error No AVR tools directory found)
+ endif
+ endif # SYSTEMPATH_AVR_TOOLS_DIR
+
+ endif # BUNDLED_AVR_TOOLS_DIR
+
+else
+ $(call show_config_variable,AVR_TOOLS_DIR,[USER])
+
+ # ensure we can still find avrdude.conf
+ ifndef AVRDUDE_CONF
+ ifeq ($(shell expr $(ARDUINO_VERSION_SHORT) '>' 157), 1)
+ AVRDUDE_CONF = $(AVR_TOOLS_DIR)/etc/avrdude.conf
+ else
+ AVRDUDE_CONF = $(AVR_TOOLS_DIR)/../avrdude.conf
+ endif
+ endif
+
+endif
+
+TOOLS_PATH = $(ARDUINO_DIR)/tools/avr-gcc/$(shell /bin/ls --color=never -1 $(ARDUINO_DIR)/tools/avr-gcc/ | sort -r | xargs | awk '{print $$1}')/bin
+
+ARDUINO_LIB_PATH = $(ARDUINO_DIR)/libraries
+$(call show_config_variable,ARDUINO_LIB_PATH,[COMPUTED],(from ARDUINO_DIR))
+
+ifeq ($(shell expr $(ARDUINO_VERSION_SHORT) '>' 150), 1)
+ ARDUINO_PLATFORM_LIB_PATH = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/libraries
+ $(call show_config_variable,ARDUINO_PLATFORM_LIB_PATH,[COMPUTED],(from ARDUINO_DIR))
+endif
+
+PROJ_LIBS_PATH = libraries
+$(call show_config_variable,PROJ_LIBS_PATH,[DEFAULT])
+
+PRE_BUILD_HOOK = pre-build-hook.sh
+$(call show_config_variable,PRE_BUILD_HOOK,[DEFAULT])
+
+########################################################################
+# boards.txt parsing
+
+ifdef BOARD_SUB
+ BOARD_SUB := $(strip $(BOARD_SUB))
+ $(call show_config_variable,BOARD_SUB,[USER])
+endif
+
+BOARD_TAG := $(strip $(BOARD_TAG))
+$(call show_config_variable,BOARD_TAG,[USER])
+
+ifdef BOARD_CLOCK
+ BOARD_CLOCK := $(strip $(BOARD_CLOCK))
+ $(call show_config_variable,BOARD_CLOCK,[USER])
+endif
+
+# If NO_CORE is set, then we don't have to parse boards.txt file
+# But the user might have to define MCU, F_CPU etc
+ifeq ($(strip $(NO_CORE)),)
+
+ # Select a core from the 'cores' directory. Two main values: 'arduino' or
+ # 'robot', but can also hold 'tiny', for example, if using
+ # https://code.google.com/p/arduino-tiny alternate core.
+ ifndef CORE
+ CORE = $(call PARSE_BOARD,$(BOARD_TAG),build.core)
+ $(call show_config_variable,CORE,[COMPUTED],(from build.core))
+ else
+ $(call show_config_variable,CORE,[USER])
+ endif
+
+ # Which variant ? This affects the include path
+ ifndef VARIANT
+ VARIANT := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.variant)
+ ifndef VARIANT
+ VARIANT := $(call PARSE_BOARD,$(BOARD_TAG),build.variant)
+ endif
+ $(call show_config_variable,VARIANT,[COMPUTED],(from build.variant))
+ else
+ $(call show_config_variable,VARIANT,[USER])
+ endif
+
+ ifndef BOARD
+ BOARD := $(call PARSE_BOARD,$(BOARD_TAG),build.board)
+ ifndef BOARD
+ BOARD := $(shell echo $(ARCHITECTURE)_$(BOARD_TAG) | tr '[:lower:]' '[:upper:]')
+ endif
+ $(call show_config_variable,BOARD,[COMPUTED],(from build.board))
+ else
+ $(call show_config_variable,BOARD,[USER])
+ endif
+
+ # see if we are a caterina device like leonardo or micro
+ CATERINA := $(findstring caterina,$(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).bootloader.file))
+ ifndef CATERINA
+ # 1.5+ method if not a submenu
+ CATERINA := $(findstring caterina,$(call PARSE_BOARD,$(BOARD_TAG),bootloader.file))
+ endif
+ ifndef CATERINA
+ # 1.0 method uses deprecated bootloader.path
+ CATERINA := $(findstring caterina,$(call PARSE_BOARD,$(BOARD_TAG),bootloader.path))
+ endif
+
+ # processor stuff
+ ifndef MCU
+ MCU := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.mcu)
+ ifndef MCU
+ MCU := $(call PARSE_BOARD,$(BOARD_TAG),build.mcu)
+ endif
+ endif
+
+ ifndef F_CPU
+ ifdef BOARD_CLOCK
+ F_CPU := $(call PARSE_BOARD,$(BOARD_TAG),menu.(speed|clock).$(BOARD_CLOCK).build.f_cpu)
+ endif
+ ifndef F_CPU
+ F_CPU := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.f_cpu)
+ endif
+ ifndef F_CPU
+ F_CPU := $(call PARSE_BOARD,$(BOARD_TAG),build.f_cpu)
+ endif
+ endif
+
+ ifneq ($(CATERINA),)
+ # USB IDs for the caterina devices like leonardo or micro
+ ifndef USB_VID
+ USB_VID = $(call PARSE_BOARD,$(BOARD_TAG),build.vid)
+ endif
+
+ # coping with 2-3 methods sparkfun use for usb.pid
+ ifndef USB_PID
+ USB_PID := $(call PARSE_BOARD,$(BOARD_TAG),build.pid)
+ ifndef USB_PID
+ USB_PID := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).build.pid)
+ endif
+ endif
+
+ ifndef USB_PRODUCT
+ USB_PRODUCT := $(call PARSE_BOARD,$(BOARD_TAG),build.usb_product)
+ ifdef USB_PRODUCT
+ $(call show_config_variable,USB_PRODUCT,[COMPUTED])
+ endif
+ endif
+
+ ifndef USB_MANUFACTURER
+ USB_MANUFACTURER := $(call PARSE_BOARD,$(BOARD_TAG),build.usb_manufacturer)
+ ifndef USB_MANUFACTURER
+ USB_MANUFACTURER = "Unknown"
+ else
+ $(call show_config_variable,USB_MANUFACTURER,[COMPUTED])
+ endif
+ endif
+ endif
+
+ # normal programming info
+ ifndef AVRDUDE_ARD_PROGRAMMER
+ AVRDUDE_ARD_PROGRAMMER := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).upload.protocol)
+ ifndef AVRDUDE_ARD_PROGRAMMER
+ AVRDUDE_ARD_PROGRAMMER := $(call PARSE_BOARD,$(BOARD_TAG),upload.protocol)
+ endif
+ endif
+
+ ifndef AVRDUDE_ARD_BAUDRATE
+ AVRDUDE_ARD_BAUDRATE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).upload.speed)
+ ifndef AVRDUDE_ARD_BAUDRATE
+ AVRDUDE_ARD_BAUDRATE := $(call PARSE_BOARD,$(BOARD_TAG),upload.speed)
+ endif
+ endif
+
+ # fuses if you're using e.g. ISP
+ ifndef ISP_LOCK_FUSE_PRE
+ ISP_LOCK_FUSE_PRE = $(call PARSE_BOARD,$(BOARD_TAG),bootloader.unlock_bits)
+ endif
+
+ ifndef ISP_HIGH_FUSE
+ ifdef BOARD_CLOCK
+ ISP_HIGH_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(speed|clock).$(BOARD_CLOCK).bootloader.high_fuses)
+ endif
+ ifndef ISP_HIGH_FUSE
+ ISP_HIGH_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).bootloader.high_fuses)
+ endif
+ ifndef ISP_HIGH_FUSE
+ ISP_HIGH_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.high_fuses)
+ endif
+ endif
+
+ ifndef ISP_LOW_FUSE
+ ifdef BOARD_CLOCK
+ ISP_LOW_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(speed|clock).$(BOARD_CLOCK).bootloader.low_fuses)
+ endif
+ ifndef ISP_LOW_FUSE
+ ISP_LOW_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).bootloader.low_fuses)
+ endif
+ ifndef ISP_LOW_FUSE
+ ISP_LOW_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.low_fuses)
+ endif
+ endif
+
+ ifndef ISP_EXT_FUSE
+ ifdef BOARD_CLOCK
+ ISP_EXT_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(speed|clock).$(BOARD_CLOCK).bootloader.extended_fuses)
+ endif
+ ifndef ISP_EXT_FUSE
+ ISP_EXT_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).bootloader.extended_fuses)
+ endif
+ ifndef ISP_EXT_FUSE
+ ISP_EXT_FUSE := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.extended_fuses)
+ endif
+ endif
+
+ ifndef BOOTLOADER_PATH
+ BOOTLOADER_PATH = $(call PARSE_BOARD,$(BOARD_TAG),bootloader.path)
+ endif
+
+ ifndef BOOTLOADER_FILE
+ BOOTLOADER_FILE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).bootloader.file)
+ ifndef BOOTLOADER_FILE
+ BOOTLOADER_FILE := $(call PARSE_BOARD,$(BOARD_TAG),bootloader.file)
+ endif
+ endif
+
+ ifndef ISP_LOCK_FUSE_POST
+ ISP_LOCK_FUSE_POST = $(call PARSE_BOARD,$(BOARD_TAG),bootloader.lock_bits)
+ endif
+
+ ifndef HEX_MAXIMUM_SIZE
+ HEX_MAXIMUM_SIZE := $(call PARSE_BOARD,$(BOARD_TAG),menu.(chip|cpu).$(BOARD_SUB).upload.maximum_size)
+ ifndef HEX_MAXIMUM_SIZE
+ HEX_MAXIMUM_SIZE := $(call PARSE_BOARD,$(BOARD_TAG),upload.maximum_size)
+ endif
+ endif
+
+endif
+
+# Everything gets built in here (include BOARD_TAG now)
+ifndef OBJDIR
+ OBJDIR = build
+ $(call show_config_variable,OBJDIR,[COMPUTED],(from BOARD_TAG))
+else
+ $(call show_config_variable,OBJDIR,[USER])
+endif
+
+# Now that we have ARDUINO_DIR, ARDMK_VENDOR, ARCHITECTURE and CORE,
+# we can set ARDUINO_CORE_PATH.
+ifndef ARDUINO_CORE_PATH
+ ifeq ($(strip $(CORE)),)
+ ARDUINO_CORE_PATH = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/cores/arduino
+ $(call show_config_variable,ARDUINO_CORE_PATH,[DEFAULT])
+ else
+ ARDUINO_CORE_PATH = $(ALTERNATE_CORE_PATH)/cores/$(CORE)
+ ifeq ($(wildcard $(ARDUINO_CORE_PATH)),)
+ ARDUINO_CORE_PATH = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/cores/$(CORE)
+ $(call show_config_variable,ARDUINO_CORE_PATH,[COMPUTED],(from ARDUINO_DIR, BOARD_TAG and boards.txt))
+ else
+ $(call show_config_variable,ARDUINO_CORE_PATH,[COMPUTED],(from ALTERNATE_CORE_PATH, BOARD_TAG and boards.txt))
+ endif
+ endif
+else
+ $(call show_config_variable,ARDUINO_CORE_PATH,[USER])
+endif
+
+########################################################################
+# Reset
+
+ifndef RESET_CMD
+ ARD_RESET_ARDUINO_PATH = tools/reset_leonardo.py
+ ARD_RESET_ARDUINO := $(PYTHON_CMD) $(ARD_RESET_ARDUINO_PATH)
+ RESET_CMD = $(ARD_RESET_ARDUINO) $(DEVICE_PATH)
+ $(call show_config_variable,RESET_CMD,[COMPUTED],(from PYTHON_CMD, ARD_RESET_OPTS and MONITOR_PORT))
+else
+ $(call show_config_variable,RESET_CMD,[USER])
+endif
+
+ifneq ($(CATERINA),)
+ ERROR_ON_CATERINA = $(error On $(BOARD_TAG), raw_xxx operation is not supported)
+else
+ ERROR_ON_CATERINA =
+endif
+
+########################################################################
+# Local sources
+
+LOCAL_SRCS ?= $(wildcard src/*.cpp)
+LOCAL_OBJ_FILES = $(LOCAL_SRCS:.cpp=.cpp.o)
+LOCAL_OBJS = $(patsubst %,$(OBJDIR)/%,$(LOCAL_OBJ_FILES))
+
+ifeq ($(words $(LOCAL_SRCS)), 0)
+ $(error At least one source file is needed)
+endif
+
+# core sources
+ifeq ($(strip $(NO_CORE)),)
+ ifdef ARDUINO_CORE_PATH
+ CORE_C_SRCS = $(wildcard $(ARDUINO_CORE_PATH)/*.c)
+ CORE_C_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/$(TOOL_PREFIX)-libc/*.c)
+ CORE_CPP_SRCS = $(wildcard $(ARDUINO_CORE_PATH)/*.cpp)
+ CORE_AS_SRCS = $(wildcard $(ARDUINO_CORE_PATH)/*.S)
+
+ # ArduinoCore-API
+ CORE_C_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/api/*.c)
+ CORE_CPP_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/api/*.cpp)
+
+ # USB Core if samd or sam
+ ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ CORE_C_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/avr/*.c) # avr core emulation files
+ CORE_C_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/USB/*.c)
+ CORE_CPP_SRCS += $(wildcard $(ARDUINO_CORE_PATH)/USB/*.cpp)
+ endif
+
+ ifneq ($(strip $(NO_CORE_MAIN_CPP)),)
+ CORE_CPP_SRCS := $(filter-out %main.cpp, $(CORE_CPP_SRCS))
+ $(call show_config_info,NO_CORE_MAIN_CPP set so core library will not include main.cpp,[MANUAL])
+ endif
+
+ # Add core files for sam devices in CORE_OJBS filtering specific paths
+ ifdef SAM_CORE_PATH
+ SAM_CORE_OBJ_FILES = $(SAM_CORE_C_SRCS:.c=.c.o) $(SAM_CORE_CPP_SRCS:.cpp=.cpp.o) $(SAM_CORE_AS_SRCS:.S=.S.o)
+ # variant core files
+ CORE_OBJS += $(patsubst $(SAM_CORE_PATH)/%, \
+ $(OBJDIR)/core/%, $(filter $(SAM_CORE_PATH)/%, $(SAM_CORE_OBJ_FILES)))
+ # libsam on Due
+ ifdef SAM_LIBSAM_PATH
+ CORE_OBJS += $(patsubst $(SAM_LIBSAM_PATH)/source/%, \
+ $(OBJDIR)/core/%, $(filter $(SAM_LIBSAM_PATH)/source/%, $(SAM_CORE_OBJ_FILES)))
+ endif
+ # chip sources on Due
+ ifdef SAM_SYSTEM_PATH
+ CORE_OBJS += $(patsubst $(SAM_SYSTEM_PATH)/source/%, \
+ $(OBJDIR)/core/%, $(filter $(SAM_SYSTEM_PATH)/source/%, $(SAM_CORE_OBJ_FILES)))
+ endif
+ endif
+
+ CORE_OBJ_FILES = $(CORE_C_SRCS:.c=.c.o) $(CORE_CPP_SRCS:.cpp=.cpp.o) $(CORE_AS_SRCS:.S=.S.o)
+ CORE_OBJS += $(patsubst $(ARDUINO_CORE_PATH)/%, \
+ $(OBJDIR)/core/%,$(CORE_OBJ_FILES))
+ endif
+else
+ $(call show_config_info,NO_CORE set so core library will not be built,[MANUAL])
+endif
+
+
+########################################################################
+# Determine ARDUINO_LIBS automatically
+
+ifndef ARDUINO_LIBS
+ # automatically determine included libraries
+ ARDUINO_LIBS += $(filter $(notdir $(wildcard $(ARDUINO_DIR)/libraries/*)), \
+ $(shell sed -ne 's/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p' $(LOCAL_SRCS)))
+ ARDUINO_LIBS += $(filter $(notdir $(wildcard $(PROJ_LIBS_PATH)/*)), \
+ $(shell sed -ne 's/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p' $(LOCAL_SRCS)))
+ ARDUINO_LIBS += $(filter $(notdir $(wildcard $(ARDUINO_PLATFORM_LIB_PATH)/*)), \
+ $(shell sed -ne 's/^ *\# *include *[<\"]\(.*\)\.h[>\"]/\1/p' $(LOCAL_SRCS)))
+endif
+
+########################################################################
+# Serial monitor (just a screen wrapper)
+
+# Quite how to construct the monitor command seems intimately tied
+# to the command we're using (here screen). So, read the screen docs
+# for more information (search for 'character special device').
+
+ifeq ($(strip $(NO_CORE)),)
+ ifndef MONITOR_BAUDRATE
+ MONITOR_BAUDRATE = 9600
+ $(call show_config_variable,MONITOR_BAUDRATE,[ASSUMED])
+ else
+ $(call show_config_variable,MONITOR_BAUDRATE,[USER])
+ endif
+
+ ifndef MONITOR_CMD
+ MONITOR_CMD = screen
+ endif
+endif
+
+# Include Arduino Header file
+ARDUINO_HEADER=Arduino.h
+
+########################################################################
+# Rules for making stuff
+
+# The name of the main targets
+TARGET_HEX = $(OBJDIR)/$(TARGET).hex
+TARGET_ELF = $(OBJDIR)/$(TARGET).elf
+TARGET_EEP = $(OBJDIR)/$(TARGET).eep
+TARGET_BIN = $(OBJDIR)/$(TARGET).bin
+CORE_LIB = $(OBJDIR)/libcore.a
+
+# Names of executables
+# In the rare case of wanting to override a path and/or excecutable
+# name, the OVERRIDE_EXECUTABLES variable must be defned and _all_
+# the excecutables (CC, CXX, AS, OBJCOPY, OBJDUMP AR, SIZE and NM)
+# _must_ be defined in the calling makefile.
+# We can't use "?=" assignment because these are already implicitly
+# defined by Make (e.g. $(CC) == cc).
+ifndef OVERRIDE_EXECUTABLES
+ CC = $(TOOLS_PATH)/$(CC_NAME)
+ CXX = $(TOOLS_PATH)/$(CXX_NAME)
+ AS = $(TOOLS_PATH)/$(AS_NAME)
+ OBJCOPY = $(TOOLS_PATH)/$(OBJCOPY_NAME)
+ OBJDUMP = $(TOOLS_PATH)/$(OBJDUMP_NAME)
+ AR = $(TOOLS_PATH)/$(AR_NAME)
+ SIZE = $(TOOLS_PATH)/$(SIZE_NAME)
+ NM = $(TOOLS_PATH)/$(NM_NAME)
+endif
+
+REMOVE = rm -rf
+MV = mv -f
+CAT = cat
+ECHO = printf
+MKDIR = mkdir -p
+
+# recursive wildcard function, call with params:
+# - start directory (finished with /) or empty string for current dir
+# - glob pattern
+# (taken from http://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html)
+rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
+
+# functions used to determine various properties of library
+# called with library path. Needed because of differences between library
+# layouts in arduino 1.0.x and 1.5.x.
+# Assuming new 1.5.x layout when there is "src" subdirectory in main directory
+# and library.properties file
+
+# Gets include flags for library
+get_library_includes = $(if $(and $(wildcard $(1)/src), $(wildcard $(1)/library.properties)), \
+ -I$(1)/src, \
+ $(addprefix -I,$(1) $(wildcard $(1)/utility)))
+
+# Gets all sources with given extension (param2) for library (path = param1)
+# for old (1.0.x) layout looks in . and "utility" directories
+# for new (1.5.x) layout looks in src and recursively its subdirectories
+get_library_files = $(if $(and $(wildcard $(1)/src), $(wildcard $(1)/library.properties)), \
+ $(call rwildcard,$(1)/src/,*.$(2)), \
+ $(wildcard $(1)/*.$(2) $(1)/utility/*.$(2)))
+
+# General arguments
+PROJ_LIBS := $(sort $(wildcard $(patsubst %,$(PROJ_LIBS_PATH)/%,$(ARDUINO_LIBS))))
+PROJ_LIB_NAMES := $(patsubst $(PROJ_LIBS_PATH)/%,%,$(PROJ_LIBS))
+
+# Let user libraries override system ones.
+SYS_LIBS := $(sort $(wildcard $(patsubst %,$(ARDUINO_LIB_PATH)/%,$(filter-out $(PROJ_LIB_NAMES),$(ARDUINO_LIBS)))))
+SYS_LIB_NAMES := $(patsubst $(ARDUINO_LIB_PATH)/%,%,$(SYS_LIBS))
+
+ifdef ARDUINO_PLATFORM_LIB_PATH
+ PLATFORM_LIBS := $(sort $(wildcard $(patsubst %,$(ARDUINO_PLATFORM_LIB_PATH)/%,$(filter-out $(PROJ_LIB_NAMES),$(ARDUINO_LIBS)))))
+ PLATFORM_LIB_NAMES := $(patsubst $(ARDUINO_PLATFORM_LIB_PATH)/%,%,$(PLATFORM_LIBS))
+endif
+
+# Error here if any are missing.
+LIBS_NOT_FOUND = $(filter-out $(PROJ_LIB_NAMES) $(SYS_LIB_NAMES) $(PLATFORM_LIB_NAMES),$(ARDUINO_LIBS))
+ifneq (,$(strip $(LIBS_NOT_FOUND)))
+ ifdef ARDUINO_PLATFORM_LIB_PATH
+ $(error The following libraries specified in ARDUINO_LIBS could not be found (searched PROJ_LIBS_PATH, ARDUINO_LIB_PATH and ARDUINO_PLATFORM_LIB_PATH): $(LIBS_NOT_FOUND))
+ else
+ $(error The following libraries specified in ARDUINO_LIBS could not be found (searched PROJ_LIBS_PATH and ARDUINO_LIB_PATH): $(LIBS_NOT_FOUND))
+ endif
+endif
+
+SYS_INCLUDES := $(foreach lib, $(SYS_LIBS), $(call get_library_includes,$(lib)))
+PROJ_INCLUDES := $(foreach lib, $(PROJ_LIBS), $(call get_library_includes,$(lib)))
+LIB_C_SRCS := $(foreach lib, $(SYS_LIBS), $(call get_library_files,$(lib),c))
+LIB_CPP_SRCS := $(foreach lib, $(SYS_LIBS), $(call get_library_files,$(lib),cpp))
+LIB_AS_SRCS := $(foreach lib, $(SYS_LIBS), $(call get_library_files,$(lib),S))
+PROJ_LIB_CPP_SRCS := $(foreach lib, $(PROJ_LIBS), $(call get_library_files,$(lib),cpp))
+PROJ_LIB_C_SRCS := $(foreach lib, $(PROJ_LIBS), $(call get_library_files,$(lib),c))
+PROJ_LIB_AS_SRCS := $(foreach lib, $(PROJ_LIBS), $(call get_library_files,$(lib),S))
+LIB_OBJS = $(patsubst $(ARDUINO_LIB_PATH)/%.c,$(OBJDIR)/libs/%.c.o,$(LIB_C_SRCS)) \
+ $(patsubst $(ARDUINO_LIB_PATH)/%.cpp,$(OBJDIR)/libs/%.cpp.o,$(LIB_CPP_SRCS)) \
+ $(patsubst $(ARDUINO_LIB_PATH)/%.S,$(OBJDIR)/libs/%.S.o,$(LIB_AS_SRCS))
+PROJ_LIB_OJS = $(patsubst $(PROJ_LIBS_PATH)/%.cpp,$(OBJDIR)/projlibs/%.cpp.o,$(PROJ_LIB_CPP_SRCS)) \
+ $(patsubst $(PROJ_LIBS_PATH)/%.c,$(OBJDIR)/projlibs/%.c.o,$(PROJ_LIB_C_SRCS)) \
+ $(patsubst $(PROJ_LIBS_PATH)/%.S,$(OBJDIR)/projlibs/%.S.o,$(PROJ_LIB_AS_SRCS))
+
+ifdef ARDUINO_PLATFORM_LIB_PATH
+ PLATFORM_INCLUDES := $(foreach lib, $(PLATFORM_LIBS), $(call get_library_includes,$(lib)))
+ PLATFORM_LIB_CPP_SRCS := $(foreach lib, $(PLATFORM_LIBS), $(call get_library_files,$(lib),cpp))
+ PLATFORM_LIB_C_SRCS := $(foreach lib, $(PLATFORM_LIBS), $(call get_library_files,$(lib),c))
+ PLATFORM_LIB_AS_SRCS := $(foreach lib, $(PLATFORM_LIBS), $(call get_library_files,$(lib),S))
+ PLATFORM_LIB_OBJS := $(patsubst $(ARDUINO_PLATFORM_LIB_PATH)/%.cpp,$(OBJDIR)/platformlibs/%.cpp.o,$(PLATFORM_LIB_CPP_SRCS)) \
+ $(patsubst $(ARDUINO_PLATFORM_LIB_PATH)/%.c,$(OBJDIR)/platformlibs/%.c.o,$(PLATFORM_LIB_C_SRCS)) \
+ $(patsubst $(ARDUINO_PLATFORM_LIB_PATH)/%.S,$(OBJDIR)/platformlibs/%.S.o,$(PLATFORM_LIB_AS_SRCS))
+
+endif
+
+# Dependency files
+DEPS = $(LOCAL_OBJS:.o=.d) $(LIB_OBJS:.o=.d) $(PLATFORM_OBJS:.o=.d) $(PROJ_LIB_OJS:.o=.d) $(CORE_OBJS:.o=.d)
+
+ifndef OPTIMIZATION_LEVEL
+ OPTIMIZATION_LEVEL=s
+ $(call show_config_variable,OPTIMIZATION_LEVEL,[DEFAULT])
+else
+ $(call show_config_variable,OPTIMIZATION_LEVEL,[USER])
+endif
+
+DEBUG_FLAGS = -O0 -g
+
+# SoftwareSerial requires -Os (some delays are tuned for this optimization level)
+%SoftwareSerial.cpp.o : OPTIMIZATION_FLAGS = -Os
+%Uart.cpp.o : OPTIMIZATION_FLAGS = -Os
+
+ifndef MCU_FLAG_NAME
+ MCU_FLAG_NAME = mmcu
+ $(call show_config_variable,MCU_FLAG_NAME,[DEFAULT])
+else
+ $(call show_config_variable,MCU_FLAG_NAME,[USER])
+endif
+
+CPPFLAGS += -$(MCU_FLAG_NAME)=$(MCU) -DF_CPU=$(F_CPU) -DARDUINO=$(ARDUINO_VERSION_SHORT) -DARDUINO_$(BOARD) $(ARDUINO_ARCH_FLAG) \
+ "-DARDUINO_BOARD=\"$(BOARD)\"" "-DARDUINO_VARIANT=\"$(VARIANT)\"" \
+ -I$(ARDUINO_CORE_PATH) -I$(ARDUINO_CORE_PATH)/api -I$(ARDUINO_VAR_PATH)/$(VARIANT) \
+ $(SYS_INCLUDES) $(PLATFORM_INCLUDES) $(PROJ_INCLUDES) -Wall -ffunction-sections \
+ -fdata-sections
+
+# PROG_TYPES_COMPAT is enabled by default for compatibility with the Arduino IDE.
+# By placing it before the user-provided CPPFLAGS rather than after, we allow the
+# the user to disable it if they like, by adding the negation of the flag
+# (-U__PROG_TYPES_COMPAT__) to the user-provided CPPFLAGS.
+CPPFLAGS := -D__PROG_TYPES_COMPAT__ $(CPPFLAGS)
+
+ifdef DEBUG
+OPTIMIZATION_FLAGS= $(DEBUG_FLAGS)
+else
+OPTIMIZATION_FLAGS = -O$(OPTIMIZATION_LEVEL)
+endif
+
+CPPFLAGS += $(OPTIMIZATION_FLAGS)
+
+# USB IDs for the Caterina devices like leonardo or micro
+ifneq ($(CATERINA),)
+ CPPFLAGS += -DUSB_VID=$(USB_VID) -DUSB_PID=$(USB_PID)
+ ifdef USB_PRODUCT
+ CPPFLAGS += -DUSB_PRODUCT='$(USB_PRODUCT)' -DUSB_MANUFACTURER='$(USB_MANUFACTURER)'
+ endif
+endif
+
+# $(TOOL_PREFIX)-gcc version that we can do maths on
+CC_VERNUM = $(shell $(CC) -dumpversion | sed 's/\.//g')
+
+# moved from above so we can find version-dependant ar
+ifeq ($(TOOL_PREFIX), avr)
+ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ AR_NAME := $(TOOL_PREFIX)-gcc-ar
+ else
+ AR_NAME := $(TOOL_PREFIX)-ar
+ endif
+endif
+
+ifndef CFLAGS_STD
+ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ CFLAGS_STD = -std=gnu11
+ else
+ CFLAGS_STD =
+ endif
+ $(call show_config_variable,CFLAGS_STD,[DEFAULT])
+else
+ $(call show_config_variable,CFLAGS_STD,[USER])
+endif
+
+ifndef CXXFLAGS_STD
+ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ CXXFLAGS_STD = -std=gnu++11
+ else
+ CXXFLAGS_STD =
+ endif
+ $(call show_config_variable,CXXFLAGS_STD,[DEFAULT])
+else
+ $(call show_config_variable,CXXFLAGS_STD,[USER])
+endif
+
+CFLAGS += $(CFLAGS_STD)
+CXXFLAGS += -fpermissive -fno-exceptions $(CXXFLAGS_STD)
+ASFLAGS += -x assembler-with-cpp
+DIAGNOSTICS_COLOR_WHEN ?= always
+
+# Flags for AVR
+ifeq ($(findstring avr, $(strip $(CC_NAME))), avr)
+ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ ASFLAGS += -flto
+ CXXFLAGS += -fno-threadsafe-statics -flto -fno-devirtualize -fdiagnostics-color=$(DIAGNOSTICS_COLOR_WHEN)
+ CFLAGS += -flto -fno-fat-lto-objects -fdiagnostics-color=$(DIAGNOSTICS_COLOR_WHEN)
+ LDFLAGS += -flto -fuse-linker-plugin
+ endif
+# Flags for ARM (most set in Sam.mk)
+else
+ ifeq ($(shell expr $(CC_VERNUM) '>' 490), 1)
+ CXXFLAGS += -fdiagnostics-color=$(DIAGNOSTICS_COLOR_WHEN)
+ CFLAGS += -fdiagnostics-color=$(DIAGNOSTICS_COLOR_WHEN)
+ endif
+endif
+
+LDFLAGS += -$(MCU_FLAG_NAME)=$(MCU) -Wl,--gc-sections -O$(OPTIMIZATION_LEVEL)
+SIZEFLAGS ?= --mcu=$(MCU) -C
+
+# for backwards compatibility, grab ARDUINO_PORT if the user has it set
+# instead of MONITOR_PORT
+MONITOR_PORT ?= $(ARDUINO_PORT)
+
+ifneq ($(strip $(MONITOR_PORT)),)
+ ifeq ($(CURRENT_OS), WINDOWS)
+ # Expect MONITOR_PORT to be '1' or 'com1' for COM1 in Windows. Split it up
+ # into the two styles required: /dev/ttyS* for ard-reset-arduino and com*
+ # for avrdude. This also could work with /dev/com* device names and be more
+ # consistent, but the /dev/com* is not recommended by Cygwin and doesn't
+ # always show up.
+ COM_PORT_ID = $(subst com,,$(MONITOR_PORT))
+ COM_STYLE_MONITOR_PORT = com$(COM_PORT_ID)
+ DEVICE_PATH = /dev/ttyS$(shell awk 'BEGIN{ print $(COM_PORT_ID) - 1 }')
+ else
+ # set DEVICE_PATH based on user-defined MONITOR_PORT or ARDUINO_PORT
+ DEVICE_PATH = $(MONITOR_PORT)
+ endif
+ $(call show_config_variable,DEVICE_PATH,[COMPUTED],(from MONITOR_PORT))
+else
+ # If no port is specified, try to guess it from wildcards.
+ # Will only work if the Arduino is the only/first device matched.
+ DEVICE_PATH = $(firstword $(wildcard \
+ /dev/ttyACM? /dev/ttyUSB? /dev/tty.usbserial* /dev/tty.usbmodem* /dev/tty.wchusbserial*))
+ $(call show_config_variable,DEVICE_PATH,[AUTODETECTED])
+endif
+
+ifndef FORCE_MONITOR_PORT
+ $(call show_config_variable,FORCE_MONITOR_PORT,[DEFAULT])
+else
+ $(call show_config_variable,FORCE_MONITOR_PORT,[USER])
+endif
+
+ifdef FORCE_MONITOR_PORT
+ # Skips the DEVICE_PATH existance check.
+ get_monitor_port = $(DEVICE_PATH)
+else
+ # Returns the Arduino port (first wildcard expansion) if it exists, otherwise it errors.
+ ifeq ($(CURRENT_OS), WINDOWS)
+ get_monitor_port = $(COM_STYLE_MONITOR_PORT)
+ else
+ get_monitor_port = $(if $(wildcard $(DEVICE_PATH)),$(firstword $(wildcard $(DEVICE_PATH))),$(error Arduino port $(DEVICE_PATH) not found!))
+ endif
+endif
+
+# Returns the ISP port (first wildcard expansion) if it exists, otherwise it errors.
+get_isp_port = $(if $(wildcard $(ISP_PORT)),$(firstword $(wildcard $(ISP_PORT))),$(if $(findstring Xusb,X$(ISP_PORT)),$(ISP_PORT),$(error ISP port $(ISP_PORT) not found!)))
+
+# Command for avr_size: do $(call avr_size,elffile,hexfile)
+ifneq (,$(findstring AVR,$(shell $(SIZE) --help)))
+ # We have a patched version of binutils that mentions AVR - pass the MCU
+ # and the elf to get nice output.
+ avr_size = $(SIZE) $(SIZEFLAGS) --format=avr $(1)
+ $(call show_config_info,Size utility: AVR-aware for enhanced output,[AUTODETECTED])
+else
+ ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ avr_size = $(SIZE) $(SIZEFLAGS) $(1)
+ $(call show_config_info,Size utility: ARM,[AUTODETECTED])
+ else
+ # We have a plain-old binutils version - just give it the hex.
+ avr_size = $(SIZE) $(2)
+ $(call show_config_info,Size utility: Basic (not AVR-aware),[AUTODETECTED])
+ endif
+endif
+
+ifneq (,$(strip $(ARDUINO_LIBS)))
+ $(call arduino_output,-)
+ $(call show_config_info,ARDUINO_LIBS =)
+endif
+
+ifneq (,$(strip $(PROJ_LIB_NAMES)))
+ $(foreach lib,$(PROJ_LIB_NAMES),$(call show_config_info, $(lib),[USER]))
+endif
+
+ifneq (,$(strip $(SYS_LIB_NAMES)))
+ $(foreach lib,$(SYS_LIB_NAMES),$(call show_config_info, $(lib),[SYSTEM]))
+endif
+
+ifneq (,$(strip $(PLATFORM_LIB_NAMES)))
+ $(foreach lib,$(PLATFORM_LIB_NAMES),$(call show_config_info, $(lib),[PLATFORM]))
+endif
+
+# either calculate parent dir from arduino dir, or user-defined path
+ifndef BOOTLOADER_PARENT
+ BOOTLOADER_PARENT = $(ARDUINO_DIR)/hardware/$(ARCHITECTURE)/$(ARDUINO_VERSION)/bootloaders
+ $(call show_config_variable,BOOTLOADER_PARENT,[COMPUTED],(from ARDUINO_DIR))
+else
+ $(call show_config_variable,BOOTLOADER_PARENT,[USER])
+endif
+
+########################################################################
+# Tools version info
+ARDMK_VERSION = 1.6
+$(call show_config_variable,ARDMK_VERSION,[COMPUTED])
+
+CC_VERSION := $(shell $(CC) -dumpversion)
+$(call show_config_variable,CC_VERSION,[COMPUTED],($(CC_NAME)))
+
+# end of config output
+$(call show_separator)
+
+# Implicit rules for building everything (needed to get everything in
+# the right directory)
+#
+# Rather than mess around with VPATH there are quasi-duplicate rules
+# here for building e.g. a system C++ file and a local C++
+# file. Besides making things simpler now, this would also make it
+# easy to change the build options in future
+
+# library sources
+$(OBJDIR)/libs/%.c.o: $(ARDUINO_LIB_PATH)/%.c
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/libs/%.cpp.o: $(ARDUINO_LIB_PATH)/%.cpp
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/libs/%.S.o: $(ARDUINO_LIB_PATH)/%.S
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+$(OBJDIR)/platformlibs/%.c.o: $(ARDUINO_PLATFORM_LIB_PATH)/%.c
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/platformlibs/%.cpp.o: $(ARDUINO_PLATFORM_LIB_PATH)/%.cpp
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/platformlibs/%.S.o: $(ARDUINO_PLATFORM_LIB_PATH)/%.S
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+$(OBJDIR)/projlibs/%.cpp.o: $(PROJ_LIBS_PATH)/%.cpp
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/projlibs/%.c.o: $(PROJ_LIBS_PATH)/%.c
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/projlibs/%.S.o: $(PROJ_LIBS_PATH)/%.S
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+ifdef COMMON_DEPS
+ COMMON_DEPS := $(COMMON_DEPS) $(MAKEFILE_LIST)
+else
+ COMMON_DEPS := $(MAKEFILE_LIST)
+endif
+
+# normal local sources
+$(OBJDIR)/%.c.o: %.c $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/%.cc.o: %.cc $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/%.cpp.o: %.cpp $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/%.S.o: %.S $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+$(OBJDIR)/%.s.o: %.s $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+
+# generated assembly
+$(OBJDIR)/%.s: %.pde $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -x c++ -include $(ARDUINO_HEADER) -MMD -S -fverbose-asm $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/%.s: %.ino $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -x c++ -include $(ARDUINO_HEADER) -MMD -S -fverbose-asm $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/%.s: %.cpp $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -x c++ -MMD -S -fverbose-asm $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+# core files
+$(OBJDIR)/core/%.c.o: $(ARDUINO_CORE_PATH)/%.c $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/core/%.cpp.o: $(ARDUINO_CORE_PATH)/%.cpp $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/core/%.S.o: $(ARDUINO_CORE_PATH)/%.S $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+# sam core files
+$(OBJDIR)/core/%.c.o: $(SAM_CORE_PATH)/%.c $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/core/%.cpp.o: $(SAM_CORE_PATH)/%.cpp $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CXX) -MMD -c $(CPPFLAGS) $(CXXFLAGS) $< -o $@
+
+$(OBJDIR)/core/%.S.o: $(SAM_CORE_PATH)/%.S $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(ASFLAGS) $< -o $@
+
+# due specific sources from sam core as doesn't core doesn't have SystemInit startup file
+$(OBJDIR)/core/%.c.o: $(SAM_LIBSAM_PATH)/source/%.c $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+$(OBJDIR)/core/%.c.o: $(SAM_SYSTEM_PATH)/source/%.c $(COMMON_DEPS) | $(OBJDIR)
+ @$(MKDIR) $(dir $@)
+ $(CC) -MMD -c $(CPPFLAGS) $(CFLAGS) $< -o $@
+
+# various object conversions
+$(OBJDIR)/%.bin: $(OBJDIR)/%.elf $(COMMON_DEPS)
+ @$(MKDIR) $(dir $@)
+ -$(OBJCOPY) -O binary $< $@
+
+$(OBJDIR)/%.hex: $(OBJDIR)/%.elf $(COMMON_DEPS)
+ @$(MKDIR) $(dir $@)
+ $(OBJCOPY) -O ihex -R .eeprom $< $@
+ @$(ECHO) '\n'
+ $(call avr_size,$<,$@)
+ifneq ($(strip $(HEX_MAXIMUM_SIZE)),)
+ @if [ `$(SIZE) $@ | awk 'FNR == 2 {print $$2}'` -le $(HEX_MAXIMUM_SIZE) ]; then touch $@.sizeok; fi
+else
+ @$(ECHO) "Maximum flash memory of $(BOARD_TAG) is not specified. Make sure the size of $@ is less than $(BOARD_TAG)\'s flash memory"
+ @touch $@.sizeok
+endif
+
+$(OBJDIR)/%.eep: $(OBJDIR)/%.elf $(COMMON_DEPS)
+ @$(MKDIR) $(dir $@)
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom='alloc,load' \
+ --no-change-warnings --change-section-lma .eeprom=0 -O ihex $< $@
+
+$(OBJDIR)/%.lss: $(OBJDIR)/%.elf $(COMMON_DEPS)
+ @$(MKDIR) $(dir $@)
+ $(OBJDUMP) -h --source --demangle --wide $< > $@
+
+$(OBJDIR)/%.sym: $(OBJDIR)/%.elf $(COMMON_DEPS)
+ @$(MKDIR) $(dir $@)
+ $(NM) --size-sort --demangle --reverse-sort --line-numbers $< > $@
+
+########################################################################
+# Ctags
+
+# Assume ctags is on path unless has been specified
+ifndef CTAGS_EXEC
+ CTAGS_EXEC = ctags
+endif
+
+# Default to 'tags' unless user has specified a tags file
+ifndef TAGS_FILE
+ TAGS_FILE = tags
+endif
+
+# ctags command: append, flags unsort (as will be sorted after) and specify filename
+CTAGS_CMD = $(CTAGS_EXEC) $(CTAGS_OPTS) -auf
+
+########################################################################
+# Avrdude
+
+AVRDUDE = $(ARDUINO_DIR)/tools/avrdude/$(shell /bin/ls --color=never -1 $(ARDUINO_DIR)/tools/avrdude | sort -r | xargs | awk '{print $$1}')/bin/avrdude
+
+AVRDUDE_OPTS = -q -V
+
+AVRDUDE_MCU = $(MCU)
+
+AVRDUDE_COM_OPTS = $(AVRDUDE_OPTS) -p $(AVRDUDE_MCU)
+ifdef AVRDUDE_CONF
+ AVRDUDE_COM_OPTS += -C $(AVRDUDE_CONF)
+endif
+
+# -D - Disable auto erase for flash memory
+# Note: -D is needed for Mega boards.
+# (See https://github.com/sudar/Arduino-Makefile/issues/114#issuecomment-25011005)
+ifeq ($(AVRDUDE_AUTOERASE_FLASH), yes)
+else
+ AVRDUDE_ARD_OPTS = -D
+endif
+AVRDUDE_ARD_OPTS += -c $(AVRDUDE_ARD_PROGRAMMER) -b $(AVRDUDE_ARD_BAUDRATE) -P
+ifeq ($(CURRENT_OS), WINDOWS)
+ # get_monitor_port checks to see if the monitor port exists, assuming it is
+ # a file. In Windows, avrdude needs the port in the format 'com1' which is
+ # not a file, so we have to add the COM-style port directly.
+ AVRDUDE_ARD_OPTS += $(COM_STYLE_MONITOR_PORT)
+else
+ AVRDUDE_ARD_OPTS += $(call get_monitor_port)
+endif
+
+ifndef ISP_PROG
+ ifneq ($(strip $(AVRDUDE_ARD_PROGRAMMER)),)
+ ISP_PROG = $(AVRDUDE_ARD_PROGRAMMER)
+ else
+ ISP_PROG = stk500v1
+ endif
+endif
+
+ifndef AVRDUDE_ISP_BAUDRATE
+ ifneq ($(strip $(AVRDUDE_ARD_BAUDRATE)),)
+ AVRDUDE_ISP_BAUDRATE = $(AVRDUDE_ARD_BAUDRATE)
+ else
+ AVRDUDE_ISP_BAUDRATE = 19200
+ endif
+endif
+
+# Fuse settings copied from Arduino IDE.
+# https://github.com/arduino/Arduino/blob/master/app/src/processing/app/debug/AvrdudeUploader.java#L254
+
+# Pre fuse settings
+ifndef AVRDUDE_ISP_FUSES_PRE
+ ifneq ($(strip $(ISP_LOCK_FUSE_PRE)),)
+ AVRDUDE_ISP_FUSES_PRE += -U lock:w:$(ISP_LOCK_FUSE_PRE):m
+ endif
+
+ ifneq ($(strip $(ISP_EXT_FUSE)),)
+ AVRDUDE_ISP_FUSES_PRE += -U efuse:w:$(ISP_EXT_FUSE):m
+ endif
+
+ ifneq ($(strip $(ISP_HIGH_FUSE)),)
+ AVRDUDE_ISP_FUSES_PRE += -U hfuse:w:$(ISP_HIGH_FUSE):m
+ endif
+
+ ifneq ($(strip $(ISP_LOW_FUSE)),)
+ AVRDUDE_ISP_FUSES_PRE += -U lfuse:w:$(ISP_LOW_FUSE):m
+ endif
+endif
+
+# Bootloader file settings
+ifndef AVRDUDE_ISP_BURN_BOOTLOADER
+ ifneq ($(strip $(BOOTLOADER_FILE)),)
+ AVRDUDE_ISP_BURN_BOOTLOADER += -U flash:w:$(BOOTLOADER_PARENT)/$(BOOTLOADER_PATH)/$(BOOTLOADER_FILE):i
+ endif
+endif
+
+# Post fuse settings
+ifndef AVRDUDE_ISP_FUSES_POST
+ ifneq ($(strip $(ISP_LOCK_FUSE_POST)),)
+ AVRDUDE_ISP_FUSES_POST += -U lock:w:$(ISP_LOCK_FUSE_POST):m
+ endif
+endif
+
+# Note: setting -D to disable flash erase before programming may cause issues
+# with some boards like attiny84a, making the program not "take",
+# so we do not set it by default.
+AVRDUDE_ISP_OPTS = -c $(ISP_PROG) -b $(AVRDUDE_ISP_BAUDRATE)
+
+ifndef ISP_PORT
+ ifneq ($(strip $(ISP_PROG)),$(filter $(ISP_PROG), atmelice_isp usbasp usbtiny gpio linuxgpio avrispmkii dragon_isp dragon_dw))
+ # switch for sam devices as bootloader will be on usb serial if using stk500_v2
+ ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ AVRDUDE_ISP_OPTS += -P $(call get_monitor_port)
+ else
+ AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
+ endif
+ endif
+else
+ ifeq ($(CURRENT_OS), WINDOWS)
+ AVRDUDE_ISP_OPTS += -P $(ISP_PORT)
+ else
+ AVRDUDE_ISP_OPTS += -P $(call get_isp_port)
+ endif
+endif
+
+ifndef ISP_EEPROM
+ ISP_EEPROM = 0
+endif
+
+AVRDUDE_UPLOAD_HEX = -U flash:w:$(TARGET_HEX):i
+AVRDUDE_UPLOAD_EEP = -U eeprom:w:$(TARGET_EEP):i
+AVRDUDE_ISPLOAD_OPTS = $(AVRDUDE_UPLOAD_HEX)
+
+ifneq ($(ISP_EEPROM), 0)
+ AVRDUDE_ISPLOAD_OPTS += $(AVRDUDE_UPLOAD_EEP)
+endif
+
+########################################################################
+# Explicit targets start here
+
+all: $(TARGET_EEP) $(TARGET_BIN) $(TARGET_HEX)
+
+# Rule to create $(OBJDIR) automatically. All rules with recipes that
+# create a file within it, but do not already depend on a file within it
+# should depend on this rule. They should use a "order-only
+# prerequisite" (e.g., put "| $(OBJDIR)" at the end of the prerequisite
+# list) to prevent remaking the target when any file in the directory
+# changes.
+$(OBJDIR): pre-build
+ $(MKDIR) $(OBJDIR)
+
+pre-build:
+ $(call runscript_if_exists,$(PRE_BUILD_HOOK))
+
+# copied from arduino with start-group, end-group
+$(TARGET_ELF): $(LOCAL_OBJS) $(CORE_LIB) $(OTHER_OBJS)
+# sam devices need start and end group, and must be linked using C++ compiler
+ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ $(CXX) $(LINKER_SCRIPTS) -Wl,-Map=$(OBJDIR)/$(TARGET).map -o $@ $(LOCAL_OBJS) $(OTHER_OBJS) $(OTHER_LIBS) $(LDFLAGS) $(CORE_LIB) -Wl,--end-group
+# otherwise traditional
+else
+ $(CC) $(LDFLAGS) -o $@ $(LOCAL_OBJS) $(OTHER_OBJS) $(OTHER_LIBS) $(CORE_LIB) -lc -lm $(LINKER_SCRIPTS)
+endif
+
+$(CORE_LIB): $(CORE_OBJS) $(LIB_OBJS) $(PLATFORM_LIB_OBJS) $(PROJ_LIB_OJS)
+ $(AR) rcs $@ $(CORE_OBJS) $(LIB_OBJS) $(PLATFORM_LIB_OBJS) $(PROJ_LIB_OJS)
+
+error_on_caterina:
+ $(ERROR_ON_CATERINA)
+
+# Use submake so we can guarantee the reset happens
+# before the upload, even with make -j
+upload: $(TARGET_HEX) verify_size
+ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+# do reset toggle at 1200 BAUD to enter bootloader if using avrdude or bossa
+ifeq ($(strip $(UPLOAD_TOOL)), avrdude)
+ $(MAKE) reset
+else ifeq ($(findstring bossac, $(strip $(UPLOAD_TOOL))), bossac)
+ $(MAKE) reset
+endif
+ $(MAKE) do_sam_upload
+else
+ $(MAKE) reset
+ $(MAKE) do_upload
+endif
+
+raw_upload: $(TARGET_HEX) verify_size
+ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ $(MAKE) do_sam_upload
+else
+ $(MAKE) error_on_caterina
+ $(MAKE) do_upload
+endif
+
+do_upload:
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ARD_OPTS) \
+ $(AVRDUDE_UPLOAD_HEX)
+
+do_sam_upload: $(TARGET_BIN) verify_size
+ifeq ($(findstring openocd, $(strip $(UPLOAD_TOOL))), openocd)
+ $(OPENOCD) $(OPENOCD_OPTS) -c "telnet_port disabled; program {{$(TARGET_BIN)}} verify reset $(BOOTLOADER_SIZE); shutdown"
+else ifeq ($(findstring bossac, $(strip $(UPLOAD_TOOL))), bossac)
+ $(BOSSA) $(BOSSA_OPTS) $(TARGET_BIN)
+else ifeq ($(findstring gdb, $(strip $(UPLOAD_TOOL))), gdb)
+ $(GDB) $(GDB_UPLOAD_OPTS)
+else ifeq ($(strip $(UPLOAD_TOOL)), avrdude)
+ $(MAKE) ispload
+else
+ @$(ECHO) "$(BOOTLOADER_UPLOAD_TOOL) not currently supported!\n\n"
+endif
+
+do_eeprom: $(TARGET_EEP) $(TARGET_HEX)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ARD_OPTS) \
+ $(AVRDUDE_UPLOAD_EEP)
+
+eeprom: $(TARGET_HEX) verify_size
+ $(MAKE) reset
+ $(MAKE) do_eeprom
+
+raw_eeprom: $(TARGET_HEX) verify_size
+ $(MAKE) error_on_caterina
+ $(MAKE) do_eeprom
+
+reset:
+ $(call arduino_output,Resetting Arduino...)
+ $(RESET_CMD)
+
+# stty on MacOS likes -F, but on Debian it likes -f redirecting
+# stdin/out appears to work but generates a spurious error on MacOS at
+# least. Perhaps it would be better to just do it in perl ?
+reset_stty:
+ for STTYF in 'stty -F' 'stty --file' 'stty -f' 'stty <' ; \
+ do $$STTYF /dev/tty >/dev/null 2>&1 && break ; \
+ done ; \
+ $$STTYF $(call get_monitor_port) hupcl ; \
+ (sleep 0.1 2>/dev/null || sleep 1) ; \
+ $$STTYF $(call get_monitor_port) -hupcl
+
+ispload: $(TARGET_EEP) $(TARGET_HEX) verify_size
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) -e \
+ $(AVRDUDE_ISPLOAD_OPTS)
+
+burn_bootloader:
+ifeq ($(findstring sam, $(strip $(ARCHITECTURE))), sam)
+ ifeq ($(strip $(BOOTLOADER_UPLOAD_TOOL)), openocd)
+ $(OPENOCD) $(OPENOCD_OPTS) -c "telnet_port disabled; init; halt; $(BOOTLOADER_UNPROTECT); program {{$(BOOTLOADER_PARENT)/$(BOOTLOADER_FILE)}} verify reset; shutdown"
+ else
+ @$(ECHO) "$(BOOTLOADER_UPLOAD_TOOL) not currently supported!\n\n"
+ endif
+else
+ ifneq ($(strip $(AVRDUDE_ISP_FUSES_PRE)),)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) -e $(AVRDUDE_ISP_FUSES_PRE)
+ endif
+ ifneq ($(strip $(AVRDUDE_ISP_BURN_BOOTLOADER)),)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_BURN_BOOTLOADER)
+ endif
+ ifneq ($(strip $(AVRDUDE_ISP_FUSES_POST)),)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_FUSES_POST)
+ endif
+endif
+
+set_fuses:
+ifneq ($(strip $(AVRDUDE_ISP_FUSES_PRE)),)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_FUSES_PRE)
+endif
+ifneq ($(strip $(AVRDUDE_ISP_FUSES_POST)),)
+ $(AVRDUDE) $(AVRDUDE_COM_OPTS) $(AVRDUDE_ISP_OPTS) $(AVRDUDE_ISP_FUSES_POST)
+endif
+
+clean::
+ $(REMOVE) $(OBJDIR)
+
+size: $(TARGET_HEX)
+ $(call avr_size,$(TARGET_ELF),$(TARGET_HEX))
+
+show_boards:
+ @$(CAT) $(BOARDS_TXT) | grep -E '^[a-zA-Z0-9_\-]+.name' | sort -uf | sed 's/.name=/:/' | column -s: -t
+
+show_submenu:
+ @$(CAT) $(BOARDS_TXT) | grep -E '[a-zA-Z0-9_\-]+.menu.(cpu|chip).[a-zA-Z0-9_\-]+=' | sort -uf | sed 's/.menu.\(cpu\|chip\)./:/' | sed 's/=/:/' | column -s: -t
+
+monitor:
+ifeq ($(notdir $(MONITOR_CMD)), putty)
+ifneq ($(strip $(MONITOR_PARAMS)),)
+ $(MONITOR_CMD) -serial -sercfg $(MONITOR_BAUDRATE),$(MONITOR_PARAMS) $(call get_monitor_port)
+else
+ $(MONITOR_CMD) -serial -sercfg $(MONITOR_BAUDRATE) $(call get_monitor_port)
+endif
+else ifeq ($(notdir $(MONITOR_CMD)), picocom)
+ $(MONITOR_CMD) -b $(MONITOR_BAUDRATE) $(MONITOR_PARAMS) $(call get_monitor_port)
+else ifeq ($(notdir $(MONITOR_CMD)), cu)
+ $(MONITOR_CMD) -l $(call get_monitor_port) -s $(MONITOR_BAUDRATE)
+else
+ $(MONITOR_CMD) $(call get_monitor_port) $(MONITOR_BAUDRATE)
+endif
+
+debug_init:
+ $(OPENOCD) $(OPENOCD_OPTS)
+
+debug:
+ $(GDB) $(GDB_OPTS)
+
+disasm: $(OBJDIR)/$(TARGET).lss
+ @$(ECHO) "The compiled ELF file has been disassembled to $(OBJDIR)/$(TARGET).lss\n\n"
+
+symbol_sizes: $(OBJDIR)/$(TARGET).sym
+ @$(ECHO) "A symbol listing sorted by their size have been dumped to $(OBJDIR)/$(TARGET).sym\n\n"
+
+verify_size:
+ifeq ($(strip $(HEX_MAXIMUM_SIZE)),)
+ @$(ECHO) "\nMaximum flash memory of $(BOARD_TAG) is not specified. Make sure the size of $(TARGET_HEX) is less than $(BOARD_TAG)\'s flash memory\n\n"
+endif
+ @if [ ! -f $(TARGET_HEX).sizeok ]; then echo >&2 "\nThe size of the compiled binary file is greater than the $(BOARD_TAG)'s flash memory. \
+See http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it."; false; fi
+
+generate_assembly: $(OBJDIR)/$(TARGET).s
+ @$(ECHO) "Compiler-generated assembly for the main input source has been dumped to $(OBJDIR)/$(TARGET).s\n\n"
+
+generated_assembly: generate_assembly
+ @$(ECHO) "\"generated_assembly\" target is deprecated. Use \"generate_assembly\" target instead\n\n"
+
+tags:
+ifneq ($(words $(wildcard $(TAGS_FILE))), 0)
+ rm -f $(TAGS_FILE)
+endif
+ @$(ECHO) "Generating tags for local sources (INO an PDE files as C++): "
+ $(CTAGS_CMD) $(TAGS_FILE) --langmap=c++:+.ino.pde $(LOCAL_SRCS)
+ifneq ($(words $(ARDUINO_LIBS)), 0)
+ @$(ECHO) "Generating tags for project libraries: "
+ $(CTAGS_CMD) $(TAGS_FILE) $(foreach lib, $(ARDUINO_LIBS),$(PROJ_LIBS_PATH)/$(lib)/*)
+endif
+ @$(ECHO) "Generating tags for Arduino core: "
+ $(CTAGS_CMD) $(TAGS_FILE) $(ARDUINO_CORE_PATH)/*
+ @$(ECHO) "Sorting..\n"
+ @sort $(TAGS_FILE) -o $(TAGS_FILE)
+ @$(ECHO) "Tag file generation complete, output: $(TAGS_FILE)\n"
+
+help_vars:
+ @$(CAT) $(ARDMK_DIR)/arduino-mk-vars.md
+
+help:
+ @$(ECHO) "\nAvailable targets:\n\
+ make - compile the code\n\
+ make upload - upload\n\
+ make ispload - upload using an ISP\n\
+ make raw_upload - upload without first resetting\n\
+ make eeprom - upload the eep file\n\
+ make raw_eeprom - upload the eep file without first resetting\n\
+ make clean - remove all our dependencies\n\
+ make depends - update dependencies\n\
+ make reset - reset the Arduino by tickling DTR or changing baud\n\
+ rate on the serial port.\n\
+ make show_boards - list all the boards defined in boards.txt\n\
+ make show_submenu - list all board submenus defined in boards.txt\n\
+ make monitor - connect to the Arduino's serial port\n\
+ make debug_init - start openocd gdb server\n\
+ make debug - connect to gdb target and begin debugging\n\
+ make size - show the size of the compiled output (relative to\n\
+ resources, if you have a patched $(TOOL_PREFIX)-size).\n\
+ make verify_size - verify that the size of the final file is less than\n\
+ the capacity of the micro controller.\n\
+ make symbol_sizes - generate a .sym file containing symbols and their\n\
+ sizes.\n\
+ make disasm - generate a .lss file that contains disassembly\n\
+ of the compiled file interspersed with your\n\
+ original source code.\n\
+ make generate_assembly - generate a .s file containing the compiler\n\
+ generated assembly of the main sketch.\n\
+ make burn_bootloader - burn bootloader and fuses\n\
+ make set_fuses - set fuses without burning bootloader\n\
+ make tags - generate tags file including project libs and Arduino core\n\
+ make help_vars - print all variables that can be overridden\n\
+ make help - show this help\n\
+"
+ @$(ECHO) "Please refer to $(ARDMK_DIR)/Arduino.mk for more details.\n"
+
+.PHONY: all upload raw_upload raw_eeprom error_on_caterina reset reset_stty ispload \
+ clean depends size show_boards monitor disasm symbol_sizes generated_assembly \
+ generate_assembly verify_size burn_bootloader help pre-build tags debug debug_init
+
+# added - in the beginning, so that we don't get an error if the file is not present
+-include $(DEPS)
diff --git a/make-scripts/Common.mk b/make-scripts/Common.mk
new file mode 100644
index 0000000..fd775e7
--- /dev/null
+++ b/make-scripts/Common.mk
@@ -0,0 +1,138 @@
+COMMON_INCLUDED = TRUE
+# Useful functions
+# Returns the first argument (typically a directory), if the file or directory
+# named by concatenating the first and optionally second argument
+# (directory and optional filename) exists
+dir_if_exists = $(if $(wildcard $(1)$(2)),$(1))
+
+# result = $(call READ_BOARD_TXT, 'boardname', 'parameter')
+PARSE_BOARD = $(shell if [ -f $(BOARDS_TXT) ]; \
+then \
+ $(GREP_CMD) -Ev '^\#' $(BOARDS_TXT) | \
+ $(GREP_CMD) -E "^[ \t]*$(1).$(2)=" | \
+ cut -d = -f 2- | \
+ cut -d : -f 2; \
+fi)
+
+# Run a shell script if it exists. Stops make on error.
+runscript_if_exists = \
+ $(if $(wildcard $(1)), \
+ $(if $(findstring 0, \
+ $(lastword $(shell $(abspath $(wildcard $(1))); echo $$?))), \
+ $(info Info: $(1) success), \
+ $(error ERROR: $(1) failed)))
+
+# For message printing: pad the right side of the first argument with spaces to
+# the number of bytes indicated by the second argument.
+space_pad_to = $(shell echo "$(1) " | head -c$(2))
+
+# Call with some text, and a prefix tag if desired (like [AUTODETECTED]),
+show_config_info = $(call arduino_output,- $(call space_pad_to,$(2),20) $(1))
+
+# Call with the name of the variable, a prefix tag if desired (like [AUTODETECTED]),
+# and an explanation if desired (like (found in $$PATH)
+show_config_variable = $(call show_config_info,$(1) = $($(1)) $(3),$(2))
+
+# Just a nice simple visual separator
+show_separator = $(call arduino_output,-------------------------)
+
+# Master Arduino Makefile include (after user Makefile)
+ardmk_include = $(shell basename $(word 2,$(MAKEFILE_LIST)))
+
+$(call show_separator)
+$(call arduino_output,$(call ardmk_include) Configuration:)
+
+########################################################################
+#
+# Detect OS
+
+ifeq ($(OS),Windows_NT)
+ CURRENT_OS = WINDOWS
+ GREP_CMD = grep
+else
+ UNAME_S := $(shell uname -s)
+ ifeq ($(UNAME_S),Linux)
+ CURRENT_OS = LINUX
+ GREP_CMD = grep
+ endif
+ ifeq ($(UNAME_S),Darwin)
+ CURRENT_OS = MAC
+ ifeq (, $(shell which gggrep))
+ $(info Using macOS BSD grep, please install GNU grep to avoid warnings)
+ GREP_CMD = grep
+ else
+ GREP_CMD = ggrep
+ endif
+ endif
+endif
+$(call show_config_variable,CURRENT_OS,[AUTODETECTED])
+
+########################################################################
+#
+# Travis-CI
+ifneq ($(TEST),)
+ DEPENDENCIES_DIR = /var/tmp/Arduino-Makefile-testing-dependencies
+
+ DEPENDENCIES_MPIDE_DIR := $(shell find $(DEPENDENCIES_DIR) -name 'mpide-0023-*' -type d -exec ls -dt {} + | head -n 1)
+
+ ifeq ($(MPIDE_DIR),)
+ MPIDE_DIR = $(DEPENDENCIES_MPIDE_DIR)
+ endif
+
+ ifndef ARDUINO_IDE_DIR
+ ifeq ($(CURRENT_OS),MAC)
+ ARDUINO_IDE_DIR = Arduino.app/Contents/Resources/Java
+ else
+ ARDUINO_IDE_DIR := $(shell basename $(basename $(basename $(lastword $(wildcard $(DEPENDENCIES_DIR)/arduino*)))))
+ endif
+ endif
+ DEPENDENCIES_ARDUINO_DIR = $(DEPENDENCIES_DIR)/$(ARDUINO_IDE_DIR)
+ ifeq ($(ARDUINO_DIR),)
+ ARDUINO_DIR = $(DEPENDENCIES_ARDUINO_DIR)
+ endif
+endif
+
+########################################################################
+# Arduino Directory
+
+ifndef ARDUINO_DIR
+ AUTO_ARDUINO_DIR := $(firstword \
+ $(call dir_if_exists,/usr/share/arduino) \
+ $(call dir_if_exists,/Applications/Arduino.app/Contents/Resources/Java) \
+ $(call dir_if_exists,/Applications/Arduino.app/Contents/Java) )
+ ifdef AUTO_ARDUINO_DIR
+ ARDUINO_DIR = $(AUTO_ARDUINO_DIR)
+ $(call show_config_variable,ARDUINO_DIR,[AUTODETECTED])
+ else
+ echo $(error "ARDUINO_DIR is not defined")
+ endif
+else
+ $(call show_config_variable,ARDUINO_DIR,[USER])
+endif
+
+ifeq ($(CURRENT_OS),WINDOWS)
+ ifneq ($(shell echo $(ARDUINO_DIR) | egrep '\\|[[:space:]]|cygdrive'),)
+ echo $(error On Windows, ARDUINO_DIR and other defines must use forward slash and not contain spaces, special characters or be cygdrive relative)
+ endif
+endif
+
+########################################################################
+# System Python
+
+ifndef PYTHON_CMD
+ # try for Python 3 first
+ PYTHON_CMD := $(shell which python3 2> /dev/null)
+ ifdef PYTHON_CMD
+ $(call show_config_variable,PYTHON_CMD,[AUTODETECTED])
+ else
+ # fall-back to any Python
+ PYTHON_CMD := $(shell which python 2> /dev/null)
+ ifdef PYTHON_CMD
+ $(call show_config_variable,PYTHON_CMD,[AUTODETECTED])
+ else
+ echo $(error "Unable to find system Python! Utility scipts won't work. Override this error by defining PYTHON_CMD")
+ endif
+ endif
+else
+ $(call show_config_variable,PYTHON_CMD,[USER])
+endif
diff --git a/make-scripts/license.txt b/make-scripts/license.txt
new file mode 100644
index 0000000..4362b49
--- /dev/null
+++ b/make-scripts/license.txt
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/tools/reset_leonardo.py b/tools/reset_leonardo.py
new file mode 100644
index 0000000..be53aa1
--- /dev/null
+++ b/tools/reset_leonardo.py
@@ -0,0 +1,109 @@
+"""Tool used to reset a Arduino Leonardo board."""
+from os import O_NDELAY, O_NOCTTY, O_RDWR, open as os_open, close as os_close
+import sys
+from termios import (
+ B1200,
+ TCSANOW,
+ TIOCM_DTR,
+ TIOCM_RTS,
+ TIOCMBIC,
+ TIOCMBIS,
+ tcgetattr,
+ tcsetattr
+)
+from fcntl import ioctl
+from argparse import ArgumentParser
+from dataclasses import dataclass
+from pathlib import Path
+from struct import pack
+from time import sleep
+
+
+@dataclass
+class ParsedArguments:
+ """Parsed command-line arguments."""
+ serial_port: Path
+
+
+class TTYAttributes:
+ """TTY attributes."""
+
+ def __init__(self, tty_fd: int):
+ """Initializes the TTY attributes."""
+ self.__tty_fd = tty_fd
+ self.__attrs = tcgetattr(tty_fd)
+
+ @property
+ def ispeed(self):
+ """The ispeed."""
+ return self.__attrs[4]
+
+ @ispeed.setter
+ def ispeed(self, ispeed: int):
+ self.__attrs[4] = ispeed
+
+ @property
+ def ospeed(self):
+ """The ospeed."""
+ return self.__attrs[5]
+
+ @ospeed.setter
+ def ospeed(self, ospeed: int):
+ self.__attrs[5] = ospeed
+
+ def set(self):
+ """Sets the TTY attributes."""
+ tcsetattr(self.__tty_fd, TCSANOW, self.__attrs)
+
+
+RESET_BAUD_RATE = B1200
+
+DESCRIPTION = "Tool used to reset a Arduino Leonardo board."
+
+
+def main():
+ """Main."""
+ parser = ArgumentParser(allow_abbrev=False, description=DESCRIPTION)
+
+ parser.add_argument(
+ "serial_port",
+ type=Path,
+ help="The serial port for a Arduino Leonardo board"
+ )
+
+ arguments = parser.parse_args(namespace=ParsedArguments)
+
+ is_serial_port_char_device = arguments.serial_port.is_char_device()
+
+ # Verify that the serial port exists
+ if not arguments.serial_port.is_file() and not is_serial_port_char_device:
+ print("Error: The serial port file doesn't exist")
+ sys.exit(1)
+
+ # Verify that the serial port is a character device
+ if not is_serial_port_char_device:
+ print("Error: The serial port file is not a character device")
+ sys.exit(1)
+
+ serial_port_fd = os_open(
+ str(arguments.serial_port),
+ O_RDWR | O_NOCTTY | O_NDELAY
+ )
+
+ tty_attributes = TTYAttributes(serial_port_fd)
+
+ tty_attributes.ispeed = RESET_BAUD_RATE
+ tty_attributes.ospeed = RESET_BAUD_RATE
+
+ tty_attributes.set()
+
+ ioctl(serial_port_fd, TIOCMBIS, pack("I", TIOCM_RTS))
+ ioctl(serial_port_fd, TIOCMBIC, pack("I", TIOCM_DTR))
+
+ os_close(serial_port_fd)
+
+ sleep(1.98)
+
+
+if __name__ == "__main__":
+ main()