diff --git a/README.rst b/README.rst index 4675f03..34b73b4 100644 --- a/README.rst +++ b/README.rst @@ -18,7 +18,7 @@ Features -------- * Integrates with *Arduino SDK* -* Supports all Arduino boards. +* Supports all Arduino and Teensy boards. * Supports Arduino type libraries * Automatic detection of Arduino libraries. * Generates firmware images. @@ -135,9 +135,10 @@ Contents 6. `Compiler and Linker Flags`_ 7. `Programmers`_ 8. `Pure AVR Development`_ - 9. `Advanced Options`_ - 10. `Miscellaneous Functions`_ - 11. `Bundling Arduino CMake`_ + 9. `Teensy Development`_ + 10. `Advanced Options`_ + 11. `Miscellaneous Functions`_ + 12. `Bundling Arduino CMake`_ 3. `Linux Environment`_ @@ -292,6 +293,7 @@ To create Arduino firmware in CMake you use the ``generate_arduino_firmware`` co [LIBS lib1 lib2 ... libN] [PORT port] [SERIAL serial_cmd] + [LOADER loader_id] [PROGRAMMER programmer_id] [AFLAGS flags] [NO_AUTOLIBS]) @@ -316,6 +318,8 @@ The options are: +--------------------+----------------------------------------------------------------------+------------------------------------+ | **SERIAL** | Serial command for serial target (see `Serial Terminal`_) | | +--------------------+----------------------------------------------------------------------+------------------------------------+ +| **LOADER** | Uploader to transfer sketches to the board (defaults to avrdude) | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ | **PROGRAMMER** | Programmer ID, enables programmer burning (see `Programmers`_). | | +--------------------+----------------------------------------------------------------------+------------------------------------+ | **ARDLIBS** | Manual list of Arduino type libraries, common use case is when the | | @@ -532,6 +536,7 @@ Most Arduino libraries have examples bundled with them. If you would like to gen [BOARD board_id] [PORT port] [SERIAL serial command] + [LOADER loader_id] [PORGRAMMER programmer_id] [AFLAGS avrdude_flags]) @@ -551,6 +556,8 @@ The options are: +--------------------+----------------------------------------------------------------------+------------------------------------+ | **SERIAL** | Serial command for serial target (see `Serial Terminal`_) | | +--------------------+----------------------------------------------------------------------+------------------------------------+ +| **LOADER** | Uploader to transfer sketches to the board (defaults to avrdude) | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ | **PROGRAMMER** | Programmer ID, enables programmer burning (see `Programmers`_). | | +--------------------+----------------------------------------------------------------------+------------------------------------+ | **AFLAGS** | avrdude flags for target | | @@ -662,6 +669,7 @@ The `generate_avr_firmware()` command:: [LIBS lib1 lib2 ... libN] [PORT port] [SERIAL serial_cmd] + [LOADER loader_id] [PROGRAMMER programmer_id] [AFLAGS flags]) @@ -686,6 +694,8 @@ The options: +--------------------+----------------------------------------------------------------------+------------------------------------+ | **SERIAL** | Serial command for serial target (see `Serial Terminal`_) | | +--------------------+----------------------------------------------------------------------+------------------------------------+ +| **LOADER** | Uploader to transfer sketches to the board (defaults to avrdude) | | ++--------------------+----------------------------------------------------------------------+------------------------------------+ | **PROGRAMMER** | Programmer ID, enables programmer burning (see `Programmers`_). | | +--------------------+----------------------------------------------------------------------+------------------------------------+ | **AFLAGS** | avrdude flags for target | | @@ -728,6 +738,44 @@ You can specify the options in two ways, either as the command arguments or as v Where **${TARGET_NAME}** is the name of you target and **${OPTION_NAME}** is the name of the option. +Teensy Development +~~~~~~~~~~~~~~~~~~ + +When using a `PJRC Teensy`_ board instead of an Arduino, CMAKE requires some additional configuration to set all available modes. + +Ensure you have installed the *Teensy SDK*, which is normally install over the top of the Arduino SDK. +If you install to another location, ensure arduino-cmake is configured to use that directory for the Arduino SDK: + ``set(ARDUINO_SDK_PATH /path/to/the/teensy/sdk)`` + +Use the ``print_boards_list()`` command to view all available Teensy boards. +If no Teensy boards are listed, double check your Teensy SDK path settings. + +Use ``print_teensy_modes(board_id)`` to list all modes that can be configured for the board. + +Use ``print_teensy_modes(board_id MODE mode_id)`` to list all mode options available. + +All Teensy board modes must be specified, and can be applied with the following settings: + ++--------------------------+-----------------------------+ +| **Name** | **Description** | ++--------------------------+-----------------------------+ +| **TEENSY_CPU_F_MODE** | CPU Frequency / Speed | ++--------------------------+-----------------------------+ +| **TEENSY_USB_MODE** | USB Mode (Serial, HID, etc) | ++--------------------------+-----------------------------+ +| **TEENSY_KEYBOARD_MODE** | USB Keyboard Emulation | ++--------------------------+-----------------------------+ + +Set these option either before or after the ``project()`` setting like so:: + + set(TEENSY_CPU_F_MODE 16) + set(TEENSY_USB_MODE serial) + set(TEENSY_KEYBOARD_MODE en-us) + +The uploader (teensy_loader_cli) will be automatically used instead of avrdude. +This can be overridden by specifying a LOADER parameter to generate_arduino_firmware: + generate_arduino_firmware(target_name LOADER avrdude) + Advanced Options ~~~~~~~~~~~~~~~~ @@ -774,6 +822,9 @@ When **Arduino CMake** is configured properly, these options are defined: +---------------------------------+-----------------------------------------------------+ | **ARDUINO_SDK_VERSION_PATCH** | Patch version of the **Arduino SDK** (ex: 0) | +---------------------------------+-----------------------------------------------------+ +| **TEENSY_FOUND** | Set to True when the **Teensy SDK** is detected | +| | and configured. | ++---------------------------------+-----------------------------------------------------+ During compilation, you can enable the following environment variables. @@ -1207,12 +1258,12 @@ Here are some resources you might find useful in getting started. 2. Arduino: - * `Getting Started`_ - Introduction to Arduino + * `Arduino Getting Started`_ - Introduction to Arduino * `Playground`_ - User contributed documentation and help * `Arduino Forums`_ - Official forums * `Arduino Reference`_ - Official reference manual -.. _Getting Started: http://www.arduino.cc/en/Guide/HomePage +.. _Arduino Getting Started: http://www.arduino.cc/en/Guide/HomePage .. _Playground: http://www.arduino.cc/playground/ .. _Arduino Reference: http://www.arduino.cc/en/Reference/HomePage .. _Arduino Forums: http://www.arduino.cc/forum/ @@ -1228,4 +1279,4 @@ Here are some resources you might find useful in getting started. .. _CMake: http://www.cmake.org/cmake/resources/software.html .. _CMake Installer: http://www.cmake.org/cmake/resources/software.html .. _Arduino SDK: http://www.arduino.cc/en/Main/Software - +:: _PJRC Teensy: https://www.pjrc.com/teensy/ diff --git a/cmake/Platform/Arduino.cmake b/cmake/Platform/Arduino.cmake index 042a3c1..0a812e5 100644 --- a/cmake/Platform/Arduino.cmake +++ b/cmake/Platform/Arduino.cmake @@ -7,6 +7,7 @@ # [LIBS lib1 lib2 ... libN] # [PORT port] # [SERIAL serial_cmd] +# [LOADER loader_id] # [PROGRAMMER programmer_id] # [AFLAGS flags] # [NO_AUTOLIBS] @@ -27,6 +28,7 @@ # ARDLIBS # Arduino libraries to link (Wire, Servo, SPI, etc) # PORT # Serial port (enables upload support) # SERIAL # Serial command for serial target +# LOADER # Loader id # PROGRAMMER # Programmer id (enables programmer support) # AFLAGS # Avrdude flags for target # NO_AUTOLIBS # Disables Arduino library detection @@ -226,6 +228,16 @@ # Print the detected Arduino board settings. # #=============================================================================# +# print_teensy_modes(BOARD +# [MODE mode]) +#=============================================================================# +# +# BOARD - Board id +# mode - mode key +# +# Print the detected board modes available for the specified teensy board +# +#=============================================================================# # register_hardware_platform(HARDWARE_PLATFORM_PATH) #=============================================================================# # @@ -260,6 +272,7 @@ # ARDUINO_SDK_PATH - Arduino SDK Path # ARDUINO_AVRDUDE_PROGRAM - Full path to avrdude programmer # ARDUINO_AVRDUDE_CONFIG_PATH - Full path to avrdude configuration file +# TEENSY_LOADER_PROGRAM - Full path to teensy loader # # ARDUINO_C_FLAGS - C compiler flags # ARDUINO_CXX_FLAGS - C++ compiler flags @@ -268,11 +281,16 @@ # ARDUINO_DEFAULT_BOARD - Default Arduino Board ID when not specified. # ARDUINO_DEFAULT_PORT - Default Arduino port when not specified. # ARDUINO_DEFAULT_SERIAL - Default Arduino Serial command when not specified. +# ARDUINO_DEFAULT_LOADER - Default Board Loader (eg. avrdude) # ARDUINO_DEFAULT_PROGRAMMER - Default Arduino Programmer ID when not specified. # +# TEENSY_USB_MODE - USB Mode for the Teensy board +# TEENSY_KEYBOARD_MODE - Keyboard Mode for the Teensy board +# TEENSY_CPU_F_MODE - CPU Frequency mode for Teensy board # # ARDUINO_FOUND - Set to True when the Arduino SDK is detected and configured. # ARDUINO_SDK_VERSION - Set to the version of the detected Arduino SDK (ex: 1.0) +# TEENSY_FOUND - Set to True when the Teensy SDK is detected and configured. #=============================================================================# # Author: Tomasz Bogdal (QueezyTheGreat) @@ -455,7 +473,7 @@ function(GENERATE_ARDUINO_FIRMWARE INPUT_NAME) message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT "NO_AUTOLIBS;MANUAL" # Options - "BOARD;PORT;SKETCH;PROGRAMMER" # One Value Keywords + "BOARD;PORT;SKETCH;LOADER;PROGRAMMER" # One Value Keywords "SERIAL;SRCS;HDRS;LIBS;ARDLIBS;AFLAGS" # Multi Value Keywords ${ARGN}) @@ -471,6 +489,9 @@ function(GENERATE_ARDUINO_FIRMWARE INPUT_NAME) if(NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) endif() + if(NOT INPUT_LOADER) + set(INPUT_LOADER "") + endif() if(NOT INPUT_MANUAL) set(INPUT_MANUAL FALSE) endif() @@ -516,7 +537,7 @@ function(GENERATE_ARDUINO_FIRMWARE INPUT_NAME) setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" "${INPUT_MANUAL}") if(INPUT_PORT) - setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") + setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_LOADER}" "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") endif() if(INPUT_SERIAL) @@ -534,7 +555,7 @@ function(GENERATE_AVR_FIRMWARE INPUT_NAME) message(STATUS "Generating ${INPUT_NAME}") parse_generator_arguments(${INPUT_NAME} INPUT "NO_AUTOLIBS;MANUAL" # Options - "BOARD;PORT;PROGRAMMER" # One Value Keywords + "BOARD;PORT;LOADER;PROGRAMMER" # One Value Keywords "SERIAL;SRCS;HDRS;LIBS;AFLAGS" # Multi Value Keywords ${ARGN}) @@ -547,6 +568,9 @@ function(GENERATE_AVR_FIRMWARE INPUT_NAME) if(NOT INPUT_SERIAL) set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) endif() + if(NOT INPUT_LOADER) + set(INPUT_LOADER "") + endif() if(NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) endif() @@ -568,6 +592,7 @@ function(GENERATE_AVR_FIRMWARE INPUT_NAME) MANUAL BOARD ${INPUT_BOARD} PORT ${INPUT_PORT} + LOADER ${INPUT_LOADER} PROGRAMMER ${INPUT_PROGRAMMER} SERIAL ${INPUT_SERIAL} SRCS ${INPUT_SRCS} @@ -584,7 +609,7 @@ endfunction() function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) parse_generator_arguments(${INPUT_NAME} INPUT "" # Options - "LIBRARY;EXAMPLE;BOARD;PORT;PROGRAMMER" # One Value Keywords + "LIBRARY;EXAMPLE;BOARD;PORT;LOADER;PROGRAMMER" # One Value Keywords "SERIAL;AFLAGS" # Multi Value Keywords ${ARGN}) @@ -598,6 +623,9 @@ function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) if(NOT INPUT_SERIAL) set(INPUT_SERIAL ${ARDUINO_DEFAULT_SERIAL}) endif() + if(NOT INPUT_LOADER) + set(INPUT_LOADER "") + endif() if(NOT INPUT_PROGRAMMER) set(INPUT_PROGRAMMER ${ARDUINO_DEFAULT_PROGRAMMER}) endif() @@ -630,7 +658,7 @@ function(GENERATE_ARDUINO_EXAMPLE INPUT_NAME) setup_arduino_target(${INPUT_NAME} ${INPUT_BOARD} "${ALL_SRCS}" "${ALL_LIBS}" "${LIB_DEP_INCLUDES}" "" FALSE) if(INPUT_PORT) - setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") + setup_arduino_upload(${INPUT_BOARD} ${INPUT_NAME} ${INPUT_PORT} ${INPUT_LOADER} "${INPUT_PROGRAMMER}" "${INPUT_AFLAGS}") endif() if(INPUT_SERIAL) @@ -801,7 +829,20 @@ function(get_arduino_flags COMPILE_FLAGS_VAR LINK_FLAGS_VAR BOARD_ID MANUAL) message("Invalid Arduino SDK Version (${ARDUINO_SDK_VERSION})") endif() - # output + # Teensy CPU Speed + if (TEENSY_CPU_F_MODE) + if (NOT ${BOARD_ID}.menu.speed.${TEENSY_CPU_F_MODE}.build.f_cpu) + message(FATAL_ERROR "Teensy CPU Frequency Mode set, but compatible board mode could not be found. [${TEENSY_CPU_F_MODE}]") + endif() + set(${BOARD_ID}.build.f_cpu ${${BOARD_ID}.menu.speed.${TEENSY_CPU_F_MODE}.build.f_cpu}) + endif() + + # Validate CPU Freq is defined + if(NOT ${BOARD_ID}.build.f_cpu) + message(FATAL_ERROR "CPU frequency not defined. Check Arduino SDK config or TEENSY_SPEED_MODE setting.") + endif() + + # Prepare COMPILE_FLAGS set(COMPILE_FLAGS "-DF_CPU=${${BOARD_ID}.build.f_cpu} -DARDUINO=${ARDUINO_VERSION_DEFINE} -mmcu=${${BOARD_ID}.build.mcu}") if(DEFINED ${BOARD_ID}.build.vid) set(COMPILE_FLAGS "${COMPILE_FLAGS} -DUSB_VID=${${BOARD_ID}.build.vid}") @@ -812,6 +853,48 @@ function(get_arduino_flags COMPILE_FLAGS_VAR LINK_FLAGS_VAR BOARD_ID MANUAL) if(NOT MANUAL) set(COMPILE_FLAGS "${COMPILE_FLAGS} -I\"${${BOARD_CORE}.path}\" -I\"${ARDUINO_LIBRARIES_PATH}\"") endif() + + # Teensy USB Mode + if (TEENSY_USB_MODE) + if (NOT ${BOARD_ID}.menu.usb.${TEENSY_USB_MODE}.build.SETTINGS) + message(FATAL_ERROR "Teensy USB Mode set, but compatible board mode could not be found. [${TEENSY_USB_MODE}]") + endif() + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.menu.usb.${TEENSY_USB_MODE}.build.define0}") + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.menu.usb.${TEENSY_USB_MODE}.build.define1}") + endif() + + # Teensy Keyboard Mode + if (TEENSY_KEYBOARD_MODE) + if (NOT ${BOARD_ID}.menu.keys.${TEENSY_KEYBOARD_MODE}.build.SETTINGS) + message(FATAL_ERROR "Teensy Keyboard Mode set, but compatible board mode could not be found. [${TEENSY_KEYBOARD_MODE}]") + endif() + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.menu.keys.${TEENSY_KEYBOARD_MODE}.build.define0}") + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.menu.keys.${TEENSY_KEYBOARD_MODE}.build.define1}") + endif() + + # Additional build params + if(${BOARD_ID}.build.option1) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option1}") + endif() + if(${BOARD_ID}.build.option2) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option2}") + endif() + if(${BOARD_ID}.build.option3) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option3}") + endif() + if(${BOARD_ID}.build.option4) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option4}") + endif() + if(${BOARD_ID}.build.option5) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option5}") + endif() + if(${BOARD_ID}.build.option6) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option6}") + endif() + if(${BOARD_ID}.build.option7) + set(COMPILE_FLAGS "${COMPILE_FLAGS} ${${BOARD_ID}.build.option7}") + endif() + set(LINK_FLAGS "-mmcu=${${BOARD_ID}.build.mcu}") if(ARDUINO_SDK_VERSION VERSION_GREATER 1.0 OR ARDUINO_SDK_VERSION VERSION_EQUAL 1.0) if(NOT MANUAL) @@ -1121,19 +1204,20 @@ endfunction() #=============================================================================# # [PRIVATE/INTERNAL] # -# setup_arduino_upload(BOARD_ID TARGET_NAME PORT) +# setup_arduino_upload(BOARD_ID TARGET_NAME PORT LOADER_ID) # # BOARD_ID - Arduino board id # TARGET_NAME - Target name # PORT - Serial port for upload +# LOADER_ID - Loader ID # PROGRAMMER_ID - Programmer ID # AVRDUDE_FLAGS - avrdude flags # # Create an upload target (${TARGET_NAME}-upload) for the specified Arduino target. # #=============================================================================# -function(setup_arduino_upload BOARD_ID TARGET_NAME PORT PROGRAMMER_ID AVRDUDE_FLAGS) - setup_arduino_bootloader_upload(${TARGET_NAME} ${BOARD_ID} ${PORT} "${AVRDUDE_FLAGS}") +function(setup_arduino_upload BOARD_ID TARGET_NAME PORT LOADER_ID PROGRAMMER_ID AVRDUDE_FLAGS) + setup_arduino_bootloader_upload(${TARGET_NAME} ${BOARD_ID} ${PORT} "${LOADER_ID}" "${AVRDUDE_FLAGS}") # Add programmer support if defined if(PROGRAMMER_ID AND ${PROGRAMMER_ID}.protocol) @@ -1146,11 +1230,12 @@ endfunction() #=============================================================================# # [PRIVATE/INTERNAL] # -# setup_arduino_bootloader_upload(TARGET_NAME BOARD_ID PORT) +# setup_arduino_bootloader_upload(TARGET_NAME BOARD_ID PORT LOADER) # # TARGET_NAME - target name # BOARD_ID - board id # PORT - serial port +# LOADER_ID - loader id # AVRDUDE_FLAGS - avrdude flags (override) # # Set up target for upload firmware via the bootloader. @@ -1158,7 +1243,7 @@ endfunction() # The target for uploading the firmware is ${TARGET_NAME}-upload . # #=============================================================================# -function(setup_arduino_bootloader_upload TARGET_NAME BOARD_ID PORT AVRDUDE_FLAGS) +function(setup_arduino_bootloader_upload TARGET_NAME BOARD_ID PORT LOADER_ID AVRDUDE_FLAGS) set(UPLOAD_TARGET ${TARGET_NAME}-upload) set(AVRDUDE_ARGS) @@ -1174,12 +1259,28 @@ function(setup_arduino_bootloader_upload TARGET_NAME BOARD_ID PORT AVRDUDE_FLAGS endif() set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) - list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex") - list(APPEND AVRDUDE_ARGS "-Ueeprom:w:${TARGET_PATH}.eep:i") - add_custom_target(${UPLOAD_TARGET} - ${ARDUINO_AVRDUDE_PROGRAM} - ${AVRDUDE_ARGS} - DEPENDS ${TARGET_NAME}) + # Automatic loader determination + if (NOT LOADER_ID) + if (${BOARD_ID}.upload.protocol) + set(LOADER_ID ${${BOARD_ID}.upload.protocol}) + endif() + endif() + + # Determine loader from settings + if (LOADER_ID MATCHES "halfkay") + # Teensy halfkay loader + add_custom_target(${UPLOAD_TARGET} + ${TEENSY_LOADER_PROGRAM} -mmcu=${${BOARD_ID}.build.mcu} -w "${TARGET_PATH}.hex" + DEPENDS ${TARGET_NAME}) + else() + # AVRDUDE loader + list(APPEND AVRDUDE_ARGS '-Uflash:w:"${TARGET_PATH}.hex":i') + list(APPEND AVRDUDE_ARGS '-Ueeprom:w:"${TARGET_PATH}.eep":i') + add_custom_target(${UPLOAD_TARGET} + ${ARDUINO_AVRDUDE_PROGRAM} + ${AVRDUDE_ARGS} + DEPENDS ${TARGET_NAME}) + endif() # Global upload target if(NOT TARGET upload) @@ -1222,7 +1323,7 @@ function(setup_arduino_programmer_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRD endif() set(TARGET_PATH ${EXECUTABLE_OUTPUT_PATH}/${TARGET_NAME}) - list(APPEND AVRDUDE_ARGS "-Uflash:w:${TARGET_PATH}.hex") + list(APPEND AVRDUDE_ARGS '-Uflash:w:"${TARGET_PATH}.hex"') add_custom_target(${PROGRAMMER_TARGET} ${ARDUINO_AVRDUDE_PROGRAM} @@ -1284,7 +1385,7 @@ function(setup_arduino_bootloader_burn TARGET_NAME BOARD_ID PROGRAMMER PORT AVRD "-Ulfuse:w:${${BOARD_ID}.bootloader.low_fuses}:m") # Set bootloader image - list(APPEND AVRDUDE_ARGS "-Uflash:w:${${BOARD_ID}.bootloader.file}:i") + list(APPEND AVRDUDE_ARGS '-Uflash:w:"${${BOARD_ID}.bootloader.file}":i') # Set lockbits list(APPEND AVRDUDE_ARGS "-Ulock:w:${${BOARD_ID}.bootloader.lock_bits}:m") @@ -1528,11 +1629,11 @@ endfunction() # set(uno.build.core "arduino") # # set(uno.SETTINGS name upload build) # List of settings for uno -# set(uno.upload.SUBSETTINGS protocol maximum_size) # List of sub-settings for uno.upload -# set(uno.build.SUBSETTINGS mcu core) # List of sub-settings for uno.build +# set(uno.upload.SETTINGS protocol maximum_size) # List of sub-settings for uno.upload +# set(uno.build.SETTINGS mcu core) # List of sub-settings for uno.build # # The ${ENTRY_NAME}.SETTINGS variable lists all settings for the entry, while -# ${ENTRY_NAME}.SUBSETTINGS variables lists all settings for a sub-setting of +# ${ENTRY_NAME}.SETTINGS variables lists all settings for a sub-setting of # a entry setting pair. # # These variables are generated in order to be able to programatically traverse @@ -1542,61 +1643,69 @@ endfunction() function(LOAD_ARDUINO_STYLE_SETTINGS SETTINGS_LIST SETTINGS_PATH) if(NOT ${SETTINGS_LIST} AND EXISTS ${SETTINGS_PATH}) - file(STRINGS ${SETTINGS_PATH} FILE_ENTRIES) # Settings file split into lines - - foreach(FILE_ENTRY ${FILE_ENTRIES}) - if("${FILE_ENTRY}" MATCHES "^[^#]+=.*") - string(REGEX MATCH "^[^=]+" SETTING_NAME ${FILE_ENTRY}) - string(REGEX MATCH "[^=]+$" SETTING_VALUE ${FILE_ENTRY}) - string(REPLACE "." ";" ENTRY_NAME_TOKENS ${SETTING_NAME}) - string(STRIP "${SETTING_VALUE}" SETTING_VALUE) - - list(LENGTH ENTRY_NAME_TOKENS ENTRY_NAME_TOKENS_LEN) - - # Add entry to settings list if it does not exist - list(GET ENTRY_NAME_TOKENS 0 ENTRY_NAME) - list(FIND ${SETTINGS_LIST} ${ENTRY_NAME} ENTRY_NAME_INDEX) - if(ENTRY_NAME_INDEX LESS 0) - # Add entry to main list - list(APPEND ${SETTINGS_LIST} ${ENTRY_NAME}) - endif() + file(STRINGS ${SETTINGS_PATH} FILE_ENTRIES) # Settings file split into lines + + # Parse each line in the file + foreach(FILE_ENTRY ${FILE_ENTRIES}) + + if("${FILE_ENTRY}" MATCHES "^[^#]+=.*") + + # Extract SETTING_NAME=SETTING_VALUE + # Extract SETTING_NAME to ENTRY_NAME_TOKENS + string(REGEX MATCH "^[^=]+" SETTING_NAME ${FILE_ENTRY}) + string(LENGTH ${SETTING_NAME} SETTING_NAME_LENGTH) + math(EXPR SETTING_NAME_LENGTH ${SETTING_NAME_LENGTH}+1) + string(SUBSTRING ${FILE_ENTRY} ${SETTING_NAME_LENGTH} -1 SETTING_VALUE) + string(REPLACE "." ";" ENTRY_NAME_TOKENS ${SETTING_NAME}) + string(STRIP "${SETTING_VALUE}" SETTING_VALUE) + + # Append the defined Board name to the SETTINGS_LIST, if not present + list(LENGTH ENTRY_NAME_TOKENS ENTRY_NAME_TOKENS_LEN) + list(GET ENTRY_NAME_TOKENS 0 ENTRY_NAME) + list(FIND ${SETTINGS_LIST} ${ENTRY_NAME} ENTRY_NAME_INDEX) + if(ENTRY_NAME_INDEX LESS 0) + # Add entry to main list + list(APPEND ${SETTINGS_LIST} ${ENTRY_NAME}) + endif() - # Add entry setting to entry settings list if it does not exist - set(ENTRY_SETTING_LIST ${ENTRY_NAME}.SETTINGS) - list(GET ENTRY_NAME_TOKENS 1 ENTRY_SETTING) - list(FIND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING} ENTRY_SETTING_INDEX) - if(ENTRY_SETTING_INDEX LESS 0) - # Add setting to entry - list(APPEND ${ENTRY_SETTING_LIST} ${ENTRY_SETTING}) - set(${ENTRY_SETTING_LIST} ${${ENTRY_SETTING_LIST}} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board settings list") - endif() + # Add BOARD_ID.PATH.SETTINGS list entries + set(FULL_SETTING_NAME "") + foreach(TOKEN ${ENTRY_NAME_TOKENS}) + + # Add this token to the {LAST_FULL_PATH}.SETTINGS + if (FULL_SETTING_NAME) + + # Add setting to entry, if not present + set(ENTRY_SETTING_LIST ${FULL_SETTING_NAME}.SETTINGS) + list(FIND ${ENTRY_SETTING_LIST} ${TOKEN} ENTRY_SETTING_INDEX) + if(ENTRY_SETTING_INDEX LESS 0) + # Add setting to entry + list(APPEND ${ENTRY_SETTING_LIST} ${TOKEN}) + set(${ENTRY_SETTING_LIST} ${${ENTRY_SETTING_LIST}} + CACHE INTERNAL "Arduino ${FULL_SETTING_NAME} Board settings list") + endif() - set(FULL_SETTING_NAME ${ENTRY_NAME}.${ENTRY_SETTING}) - - # Add entry sub-setting to entry sub-settings list if it does not exists - if(ENTRY_NAME_TOKENS_LEN GREATER 2) - set(ENTRY_SUBSETTING_LIST ${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) - list(GET ENTRY_NAME_TOKENS 2 ENTRY_SUBSETTING) - list(FIND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING} ENTRY_SUBSETTING_INDEX) - if(ENTRY_SUBSETTING_INDEX LESS 0) - list(APPEND ${ENTRY_SUBSETTING_LIST} ${ENTRY_SUBSETTING}) - set(${ENTRY_SUBSETTING_LIST} ${${ENTRY_SUBSETTING_LIST}} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board sub-settings list") - endif() - set(FULL_SETTING_NAME ${FULL_SETTING_NAME}.${ENTRY_SUBSETTING}) - endif() + endif() + + # Append LAST_FULL_PATH + if (FULL_SETTING_NAME) + set(FULL_SETTING_NAME ${FULL_SETTING_NAME}.${TOKEN}) + else() + set(FULL_SETTING_NAME ${TOKEN}) + endif() + endforeach() - # Save setting value - set(${FULL_SETTING_NAME} ${SETTING_VALUE} - CACHE INTERNAL "Arduino ${ENTRY_NAME} Board setting") - + # Set the full setting path key/value + set(${FULL_SETTING_NAME} ${SETTING_VALUE} + CACHE INTERNAL "Arduino ${ENTRY_NAME} Board setting") - endif() - endforeach() - set(${SETTINGS_LIST} ${${SETTINGS_LIST}} - CACHE STRING "List of detected Arduino Board configurations") - mark_as_advanced(${SETTINGS_LIST}) + endif() + endforeach() + + # Update SETTINGS_LIST with any additional boards + set(${SETTINGS_LIST} ${${SETTINGS_LIST}} + CACHE STRING "List of detected Arduino Board configurations") + mark_as_advanced(${SETTINGS_LIST}) endif() endfunction() @@ -1609,21 +1718,61 @@ endfunction() # #=============================================================================# function(PRINT_SETTINGS ENTRY_NAME) - if(${ENTRY_NAME}.SETTINGS) + # Container match + if(${ENTRY_NAME}.SETTINGS) foreach(ENTRY_SETTING ${${ENTRY_NAME}.SETTINGS}) - if(${ENTRY_NAME}.${ENTRY_SETTING}) - message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}}") - endif() - if(${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS) - foreach(ENTRY_SUBSETTING ${${ENTRY_NAME}.${ENTRY_SETTING}.SUBSETTINGS}) - if(${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}) - message(STATUS " ${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}=${${ENTRY_NAME}.${ENTRY_SETTING}.${ENTRY_SUBSETTING}}") - endif() - endforeach() + # Recurse deeper + print_settings(${ENTRY_NAME}.${ENTRY_SETTING}) + endforeach() + endif() + + # Specific entry match + if(${ENTRY_NAME}) + message(STATUS " ${ENTRY_NAME}=${${ENTRY_NAME}}") + endif() +endfunction() + +#=============================================================================# +# [PUBLIC/USER] +# +# print_teensy_modes(BOARD_ID +# [MODE MODE_ID]) +# +# BOARD_ID - Board Id to display modes for +# MODE_ID - Mode Id to display options for +# +# Print modes available for teensy, or specific options for a mode. +#=============================================================================# +function(PRINT_TEENSY_MODES INPUT_BOARD) + cmake_parse_arguments(INPUT "" "MODE" "" ${ARGN}) + + if(NOT ${INPUT_BOARD}.SETTINGS) + message(FATAL_ERROR "Board specified for print_teensy_modes [${INPUT_BOARD}] could not be found.") + elseif (NOT INPUT_MODE) + message(STATUS "Mode sets for board [${INPUT_BOARD}]:") + print_list(${INPUT_BOARD}.menu.SETTINGS) + elseif (NOT ${INPUT_BOARD}.menu.${INPUT_MODE}.SETTINGS) + message(FATAL_ERROR "Mode set [${INPUT_MODE}] for board [${INPUT_BOARD}] could not be found.") + else() + message(STATUS "Mode [${INPUT_MODE}] options for board [${INPUT_BOARD}]:") + set(MAX_LENGTH 0) + foreach(ENTRY_NAME ${${INPUT_BOARD}.menu.${INPUT_MODE}.SETTINGS}) + string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) + if(CURRENT_LENGTH GREATER MAX_LENGTH) + set(MAX_LENGTH ${CURRENT_LENGTH}) endif() - message(STATUS "") endforeach() + foreach(ENTRY_NAME ${${INPUT_BOARD}.menu.${INPUT_MODE}.SETTINGS}) + string(LENGTH "${ENTRY_NAME}" CURRENT_LENGTH) + math(EXPR PADDING_LENGTH "${MAX_LENGTH}-${CURRENT_LENGTH}") + set(PADDING "") + foreach(X RANGE ${PADDING_LENGTH}) + set(PADDING "${PADDING} ") + endforeach() + message(STATUS " ${PADDING}${ENTRY_NAME}: ${${INPUT_BOARD}.menu.${INPUT_MODE}.${ENTRY_NAME}.name}") + endforeach() + message(STATUS "") endif() endfunction() @@ -2177,6 +2326,7 @@ if(NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) set(ARDUINO_DEFAULT_BOARD uno CACHE STRING "Default Arduino Board ID when not specified.") set(ARDUINO_DEFAULT_PORT CACHE STRING "Default Arduino port when not specified.") set(ARDUINO_DEFAULT_SERIAL CACHE STRING "Default Arduino Serial command when not specified.") + set(ARDUINO_DEFAULT_LOADER avrdude CACHE STRING "Default Arduino uploader when not specified.") set(ARDUINO_DEFAULT_PROGRAMMER CACHE STRING "Default Arduino Programmer ID when not specified.") # Ensure that all required paths are found @@ -2230,3 +2380,19 @@ if(NOT ARDUINO_FOUND AND ARDUINO_SDK_PATH) AVRSIZE_PROGRAM) endif() +# Initialise Teensy +if(NOT TEENSY_FOUND) + register_hardware_platform(${ARDUINO_SDK_PATH}/hardware/teensy/) + + find_program(TEENSY_LOADER_PROGRAM + NAMES teensy_loader_cli + PATHS ${ARDUINO_SDK_PATH} + NO_DEFAULT_PATH) + + if(TEENSY_LOADER_PROGRAM) + set(TEENSY_FOUND True CACHE INTERNAL "Teensy Found") + mark_as_advanced( + TEENSY_LOADER_PROGRAM + ) + endif() +endif()