diff --git a/.gitignore b/.gitignore index e43b0f9..538c8c5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .DS_Store +*~ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0efd7bc --- /dev/null +++ b/.travis.yml @@ -0,0 +1,410 @@ +# This file is used to configure the Travis CI tests for MegaCoreX + +# Although sudo is no longer required by arduino-ci-script since the 1.0.0 release, for some reason setting "sudo: false" causes the Travis CI build time to significantly increase so this setting is left as "sudo: required" +sudo: required + + +env: + global: + # The Arduino IDE will be installed at APPLICATION_FOLDER/arduino + - APPLICATION_FOLDER="${HOME}/arduino-ide" + - SKETCHBOOK_FOLDER="${HOME}/Arduino" + + # Use Arduino IDE version that supports the new AVRs + - IDE_VERSION_LIST_FULL='"1.8.12" "1.8.13"' + + + matrix: + # Compile every example sketch for every library included with MegaCoreX for every MCU, every board option, every installed IDE version + # Each line in the matrix will be run as a separate job in the Travis CI build + + ## ATmega4809 + # pinout=48pin_standard, resetpin=reset, BOD=2v6, clock=internal_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=40pin_standard, resetpin=gpio, BOD=4v3, clock=internal_20MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=40pin_standard,resetpin=gpio,BOD=4v3,clock=internal_20MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=uno_wifi, BOD=4v0, clock=internal_10MHz, bootloader=uart0_alternative + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=uno_wifi,resetpin=reset,BOD=4v0,clock=internal_10MHz,bootloader=uart0_alternative" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=nano_every, BOD=3v7, clock=internal_8MHz, bootloader=uart1_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=nano_every,resetpin=reset,BOD=3v7,clock=internal_8MHz,bootloader=uart1_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # BOD=3v3, clock=internal_5MHz, bootloader=uart1_alternative + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=3v3,clock=internal_5MHz,bootloader=uart1_alternative" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # BOD=2v9, clock=internal_4MHz, bootloader=uart2_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v9,clock=internal_4MHz,bootloader=uart2_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # BOD=2v1, clock=internal_2MHz, bootloader=uart2_alternative + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v1,clock=internal_2MHz,bootloader=uart2_alternative" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # BOD=1v8, clock=internal_1MHz, bootloader=uart3_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=1v8,clock=internal_1MHz,bootloader=uart3_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # BOD=disabled, clock=external_20MHz, bootloader=uart3_alternative + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=disabled,clock=external_20MHz,bootloader=uart3_alternative" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # clock=external_16MHz + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # clock=external_12MHz + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_12MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # clock=external_8MHz + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # clock=external_4MHz + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # clock=external_1MHz + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + + ## ATmega4808 + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_10MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_5MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_2MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:4808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + ## ATmega3209 + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_10MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_5MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_2MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3209:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + ## ATmega3208 + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_10MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_5MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_2MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:3208:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + ## ATmega1609 + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_10MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_5MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_2MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1609:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + ## ATmega1608 + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_10MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_5MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_4MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_2MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_1MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries" BOARD_ID="MegaCoreX:megaavr:1608:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + ## ATmega809 + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=48pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=48pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:809:pinout=48pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + + ## ATmega808 + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Comparator" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/EEPROM" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Event" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Logic" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Servo" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SoftwareSerial" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/SPI" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + # pinout=32pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=32pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=32pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_20MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_8MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=internal_16MHz, bootloader=uart0_default + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=internal_16MHz,bootloader=uart0_default" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + # pinout=28pin_standard, clock=external_16MHz, bootloader=no_bootloader + - SKETCH_PATH="${SKETCHBOOK_FOLDER}/hardware/MegaCoreX/megaavr/libraries/Wire" BOARD_ID="MegaCoreX:megaavr:808:pinout=28pin_standard,resetpin=reset,BOD=2v6,clock=external_16MHz,bootloader=no_bootloader" ALLOW_FAILURE="false" IDE_VERSIONS="$IDE_VERSION_LIST_FULL" + + +before_install: + # Check for tabs (excluding subtrees and keywords.txt files) + - find . -path './.git' -prune -or -path './megaavr/bootloaders/optiboot' -prune -or -path './megaavr/avrdude.conf' -prune -or -path './avr/travis-ci/arduino-ci-script' -prune -or \( -not -name 'keywords.txt' -and -type f \) -exec grep --with-filename --line-number --binary-files=without-match --regexp=$'\t' '{}' \; -exec echo 'Tab found.' \; -exec false '{}' + + + # Check for non-Unix line endings (excluding subtrees) + - find . -path './.git' -prune -or -path './megaavr/bootloaders/optiboot' -prune -or -path './megaavr/avrdude.conf' -prune -or -path './avr/travis-ci/arduino-ci-script' -prune -or -type f -exec grep --files-with-matches --binary-files=without-match --regexp=$'\r$' '{}' \; -exec echo 'Non-Unix EOL detected.' \; -exec false '{}' + + + # Install the script used to simplify use of Travis CI for testing Arduino projects + - source "${TRAVIS_BUILD_DIR}/megaavr/travis-ci/arduino-ci-script/arduino-ci-script.sh" + + # These functions can be used to get verbose output for debugging the script + # set_script_verbosity can be set to values from 0 - 2 (verbosity off - maximum verbosity) + #- set_script_verbosity 1 + # Setting set_verbose_output_during_compilation to true is the same as File > Preferences > Show verbose output during > compilation (check) in the Arduino IDE + #- set_verbose_output_during_compilation "true" + + - set_application_folder "$APPLICATION_FOLDER" + - set_sketchbook_folder "$SKETCHBOOK_FOLDER" + + # Check for board definition errors that don't affect compilation + - set_board_testing "true" + + # Check for library issues that don't affect compilation + - set_library_testing "true" + + # Install a version of Arduino IDE with an outdated bundled arduino:megaavr platform to force installation of latest arduino:avr + - install_ide "1.8.13" + # Install Arduino AVR Boards to get the AVR toolchain + - install_package "arduino:megaavr" + # Install MegaCoreX from the repository + - install_package + + # Install all IDE version required by the job + - install_ide "$IDE_VERSIONS" + + +script: + # Verify every sketch in SKETCH_PATH using the environment variables set in the matrix + - build_sketch "$SKETCH_PATH" "$BOARD_ID" "$ALLOW_FAILURE" "all" + + +after_script: + # Determine user name and repository name from TRAVIS_REPO_SLUG so the configuration will automatically adjust to forks + - USER_NAME="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 1)" + - REPOSITORY_NAME="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 2)" + # Commit a report of the job results to a folder named with the build number in the MegaCoreX branch of the CI-reports repository + - publish_report_to_repository "$REPORT_GITHUB_TOKEN" "https://github.com/${USER_NAME}/CI-reports.git" "$REPOSITORY_NAME" "build_$(printf "%05d\n" "${TRAVIS_BUILD_NUMBER}")" "false" + + # Print a tab separated report of all sketch verification results to the log + - display_report + + +notifications: + email: + on_success: never + on_failure: always diff --git a/Extended-API.md b/Extended-API.md new file mode 100644 index 0000000..b5ea4a7 --- /dev/null +++ b/Extended-API.md @@ -0,0 +1,253 @@ +# Extended Arduino API + +MegaCoreX is Arduino compatible out of the box, but also includes extra functionality that's not available on the official Arduino "megaavr" core. This is functionality that I personally have been missing in the official Arduino API, and have added to MegaCoreX instead. + +My goal isn't to "Arduino wrap" all hardware functionality the megaAVR-0 series brings to the table, but to expose functionality advanced users may benefit from and actually use. If you have a very niche application that utilizes one of the more obscure features the chip has, you're probably better off writing the low-level code yourself. Very spesific needs for ADC readings? Obscure timer needs? Read the approperiate Microchip application note! + + +## Table of contents +* [Analog read resolution](#analog-read-resolution) +* [Fast IO](#fast-io) +* [Peripheral pin swapping](#peripheral-pin-swapping) +* [pinConfigure](#pinConfigure---extended-pin-configuration) +* [Printf support](#printf-support) +* [pwmWrite](#pwmwrite---flexible-pwm-routing) +* [pwmPrescaler](#pwmprescaler---pwm-frequency-setting) +* [pwmSetResolution](#pwmsetresolution) + + +## Analog read resolution +The default analog read resolution for these chips is 10 bit, which gives you values between 0 - 1023. If you need lower resolution you can turn it down to 8 bits instead, which gives you values between 0 - 255. +Simply call `analogReadResolution` like this: +```c +analogReadResolution(8); // Set resolution to 8 bits +analogReadResolution(10); // Set resolution to 10 bits +``` + + +## Fast IO +For timing critical applications the standard `digitalRead()` and `digitalWrite()` functions may be too slow. To solve this, MegaCoreX also includes some improved variants that compiles down to a single instruction. +Call `digitalReadFast(myPin)` or `digitalWriteFast(mypin, state)` to use these.
+**Note that the pin number and pin state has to be known at compile time!** + +### Declaration +```c++ +uint8_t digitalReadFast(uint8_t pinNumber); +void digitalWriteFast(uint8_t pinNumber, uint8_t state); +``` + + +## Peripheral pin swapping +The megaAVR-0 microcontrollers support alternative pin assignments for some of their built-in peripherals. +This is specified by invoking the `swap()` or `pins()` method before `begin()` for the associated peripheral. +They will return `true` if that swap or pin combination is supported. +For `Serial` peripherals the method is `pins(tx,rx)`, for `Wire` it's `pins(sda,scl)` and for `SPI` it's `pins(mosi,miso,sck,ss)`. +(Note that this is the same pin sequence as used for the ESP8266 `pins` method, but the opposite of the one SoftwareSerial uses.) + +Note that `swap()` and `pins()` do the exact same thing, but `swap()` is MUX swap oriented, while `pins()` is pin oriented. + +If you want to use this feature to implement communication with two different external devices connected to different pins using one internal peripheral, +note that the proper way to switch is first to invoke `end()` to cleanly shut down, then `swap()` or `pins()` to switch assigned pins, and finally `begin()` to cleanly start again. + +`swap()` or `pins()` are called like this. **Use either `swap()` or `pins()`, not both!** + +``` c++ +// UART pin swapping +Serial3.swap(1); +Serial3.begin(9600); + +// Wire pin swapping +Wire.swap(1); +Wire.begin(); + +// SPI pin swapping +SPI.swap(1); +SPI.begin(); +``` + +Available pin combinations for the *48 pin standard* pinout are: + +| Peripheral | Default | Alternative 1 | Alternative 2 | +|------------|------------------------------- |------------------------------------|------------------------------------| +| Serial | swap(0) **or** pins(0,1) | swap(1) **or** pins(4,5) | | +| Serial1 | swap(0) **or** pins(14,15) | swap(1) **or** pins(18,19) | | +| Serial2 | swap(0) **or** pins(34,35) | swap(1) **or** pins(38,39) | | +| Serial3 | swap(0) **or** pins(8,9) | swap(1) **or** pins(12,13) | | +| Wire | swap(0) **or** pins(2,3) | swap(1) **or** pins(16,17) | | +| SPI | swap(0) **or** pins(4,5,6,7) | swap(1) **or** pins(14,15,16,17) | swap(2) **or** pins(30,31,32,33) | + +Available pin combinations for the *28 pin* and *32 pin standard* pinouts are: + +| Peripheral | Default | Alternative | +|------------|--------------------------------|----------------------------------| +| Serial | swap(0) **or** pins(0,1) | swap(1) **or** pins(4,5) | +| Serial1 | swap(0) **or** pins(8,9) | | +| Serial2 | swap(0) **or** pins(20,21) | swap(1) **or** pins(24,25) | +| Wire | swap(0) **or** pins(2,3) | swap(1) **or** pins(10,11) | +| SPI | swap(0) **or** pins(4,5,6,7) | swap(1) **or** pins(8,9,10,11) | + +Available pin combinations for the *Uno WiFi* pinout are: + +| Peripheral | Default | Alternative | +|------------|--------------------------------------------------------------|--------------------------------------------------------| +| Serial | swap(0) **or** pins(27,26)
(connected to mEDBG) | swap(1) **or** pins(9,10) | +| Serial1 | swap(0) **or** pins(1,0) | swap(1) **or** pins(32,33) (available on SPI header) | +| Serial2 | swap(0) **or** pins(24,23)
(connected to Wifi module) | swap(1) **or** pins(2,7) | +| Serial3 | swap(0) **or** pins(6,3) | swap(1) **or** pins(37,38) (not broken out) | + +Available pin combinations for the *Nano Every* pinout are: + +| Peripheral | Default | Alternative | +|------------|------------------------------------------------------------------|-----------------------------------------------| +| Serial | swap(0) **or** pins(25,24)
(connected to USB-serial chip) | swap(1) **or** pins(9,10) | +| Serial1 | swap(0) **or** pins(1,0) | swap(1) **or** pins(34,35) (not broken out) | +| Serial2 | swap(0) **or** pins(2,7) | swap(1) **or** pins(28,27) (not broken out) | +| Serial3 | swap(0) **or** pins(6,3) | swap(1) **or** pins(37,38) (not broken out) | + + +## pinConfigure - extended pin configuration +pinConfigure is a template based function that exposes all functions that can be configured on a per-pin basis. The first argument is the Arduino pin number to configure, and the second to nth parameter are the configuration parameters. The order the arguments has does not matter. The function will set the pin functionality regardless if it "makes sense" or not. If you enable interupts on a pin and there's no interrupt handler in your code, the microcontroller will crash. + +### Declaration +```c++ +template +void pinConfigure(const uint8_t digital_pin, const pin_configure_t mode, const MODES&... modes); +``` + +### Example +```c++ +// Set pin PA0 to output and drive the pin high +pinConfigure(PIN_PA0, PIN_DIR_OUTPUT, PIN_OUT_HIGH); +// Disable pin PA1 completely to save power +pinConfigure(PIN_PA1, PIN_INPUT_DISABLE); +``` + +### Table of valid pin modes +The following parameters ca be used to set the pinConfigure modes: +| Functionality | Enable | Disable | Toggle | +|---------------|-------|---------------------|--------------------| +| Direction, pinMode() | `PIN_DIR_OUTPUT`
`PIN_DIR_OUT`
`PIN_DIRSET` | `PIN_DIR_INPUT`
`PIN_DIR_IN`
`PIN_DIRCLR` | `PIN_DIR_TOGGLE`
`PIN_DIRTGL` | +| Pin output, `HIGH` or LOW | `PIN_OUT_HIGH`
`PIN_OUTSET` | `PIN_OUT_LOW`
`PIN_OUTCLR` | `PIN_OUT_TOGGLE`
`PIN_OUTTGL` | +| Internal Pullup | `PIN_PULLUP_ON`
`PIN_PULLUP` | `PIN_PULLUP_OFF`
`PIN_NOPULLUP` | `PIN_PULLUP_TGL` | +| Invert `HIGH` and LOW |`PIN_INVERT_ON` | `PIN_INVERT_OFF` | `PIN_INVERT_TGL` | +| Digital input buffer | `PIN_INPUT_ENABLE` or
`PIN_ISC_ENABLE` | `PIN_ISC_DISABLE` or
`PIN_INPUT_DISABLE` | Not supported | +| Interrupt on change | `PIN_ISC_ENABLE` or
`PIN_INPUT_ENABLE` | `PIN_ISC_ENABLE` or
`PIN_ISC_DISABLE` | Not applicable | +| Interrupt on Rise | `PIN_ISC_RISE` or
`PIN_INT_RISE` | `PIN_ISC_ENABLE` or
`PIN_ISC_DISABLE` | Not applicable | +| Interrupt on Fall | `PIN_ISC_FALL` or
`PIN_INT_FALL` | `PIN_ISC_ENABLE` or
`PIN_ISC_DISABLE` | Not applicable | +| Interrupt on LOW | `PIN_ISC_LEVEL` or
`PIN_INT_LEVEL` | `PIN_ISC_ENABLE` or
`PIN_ISC_DISABLE` | Not applicable | + + +## Printf support +Unlike the official Arduino core, MegaCoreX has printf support out of the box. If you're not familiar with printf you should probably [read this first](https://www.tutorialspoint.com/c_standard_library/c_function_printf.htm). It's added to the Print class and will work with all libraries that inherit Print. Printf is a standard C function that lets you format text much easier than using Arduino's built-in print and println. + +Note that the default printf implementation will NOT print floats or doubles by default. This is a limitation of the avr-libc printf implementation on AVR microcontrollers, but can be enabled by setting a build flag. This can easily be done if you're using [PlatformIO](https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md). + +If you're using a serial port, simply use `Serial.printf("Milliseconds since start: %ld\n", millis());`. Other common libraries that inherit the Print class (and thus supports printf) are SoftwareSerial, the LiquidCrystal LCD library and the u8g2 graphical LCD library. + + +## pwmWrite - flexible PWM routing +The Arduino pinout definition and the `analogWrite` function have the PWM output pins pre-defined, and can't be moved or routed to different pins using the default Arduino API, even though the chip itself supports this. The `pwmWrite` function lets to use every supported PWM output pin, and you can route the PWM signals as you like. Note that the chip limits which timer output can be routed to which pins, and you also need to make sure you don't route the PWM signal to a pins that's used for something else, like UART or SPI. Also keep in mind that the timer used for millis/micros is occupied and can not be used for PWM generation. For the Nano Every 4809 and Uno Wifi Rev2 this means timer TCB2, and for all the other pinouts TCB2. Also note that low-pinout parts does not have timer TCB3 and all the routing pin options due to the lack of physical IO. + +### Declaration +```c++ +void pwmWrite(pwm_timers_t pwmTimer, uint16_t val, timers_route_t timerRoute); +``` + +### Example +```c++ +// Route timer TCB0 PWM output to pin PF4 and set the duty cycle to 50% (128/255) +pwmWrite(TCB_0, 128, ROUTE_TCB0_PF4); +// Set the timer TCB0 duty cycle to 30% but leave the routing as is +pwmWrite(TCB_0, 76); +// Route all TCA0 timer to PORTA, enable the 2nd TCA0 PWM output (PA2 in this case), and set dyty cycle to 50% +pwmWrite(TCA0_2, 128, ROUTE_TCA0_PORTA); +``` + +### Table of valid options + +| Timer enums | Description | +|-------------|----------------------------------| +| `TCA0_0` | Identifier for TCA0 PWM output 0 | +| `TCA0_1` | Identifier for TCA0 PWM output 1 | +| `TCA0_2` | Identifier for TCA0 PWM output 2 | +| `TCA0_3` | Identifier for TCA0 PWM output 3 | +| `TCA0_4` | Identifier for TCA0 PWM output 4 | +| `TCA0_5` | Identifier for TCA0 PWM output 5 | +| `TCB_0` | Identifier for TCB0 PWM output | +| `TCB_1` | Identifier for TCB1 PWM output | +| `TCB_2` | Identifier for TCB2 PWM output | +| `TCB_3` | Identifier for TCB3 PWM output | + +| PWM routing enums | Description | +|--------------------|---------------------------------------------------------------------------------| +| `ROUTE_TCA0_PORTA` | Route all six TCA0 PWM channels to PA0..PA5 | +| `ROUTE_TCA0_PORTB` | Route all six TCA0 PWM channels to PB0..PB5 (not present on low pincount parts) | +| `ROUTE_TCA0_PORTC` | Route all six TCA0 PWM channels to PC0..PC5 | +| `ROUTE_TCA0_PORTD` | Route all six TCA0 PWM channels to PD0..PD5 | +| `ROUTE_TCA0_PORTE` | Route all six TCA0 PWM channels to PE0..PE5 (not present on low pincount parts) | +| `ROUTE_TCA0_PORTF` | Route all six TCA0 PWM channels to PF0..PF5 | +| `ROUTE_TCB0_PA2` | Route the TCB0 PWM output to pin PA2 | +| `ROUTE_TCB0_PF4` | Route the TCB0 PWM output to pin PF4 | +| `ROUTE_TCB1_PA3` | Route the TCB1 PWM output to pin PA3 | +| `ROUTE_TCB1_PF5` | Route the TCB1 PWM output to pin PF5 | +| `ROUTE_TCB2_PC0` | Route the TCB2 PWM output to pin PC0 | +| `ROUTE_TCB2_PB4` | Route the TCB2 PWM output to pin PB4 (not present on low pincount parts) | +| `ROUTE_TCB3_PB5` | Route the TCB3 PWM output to pin PB5 (not present on low pincount parts) | +| `ROUTE_TCB3_PC1` | Route the TCB3 PWM output to pin PC1 (not present on low pincount parts) | + + +## pwmPrescaler - PWM frequency setting +`pwmPrescaler` sets the clock source that drives timer. Timer TCA0 has the most options, while the TCB timers have fewer. +The prescaler direcly affects the PWM frequency, and this is the formula that determines the frequency: +`F_CPU / resolution / prescaler`. For instance, the default TCB PWM prescaler with a system clock of 16 MHz is 1/64, which results in a PWM frequency of just under 1 kHz. + +### Declaration +```c++ +void pwmPrescaler(pwm_timers_t pwmTimer, timers_prescaler_t prescaler); +``` + +### Example +```c++ +// Set the TCA0 timer prescaler to 1/64 of the system clock frequency +pwmPrescaler(TCA0_0, TCA_DIV64); +// Set timer TCB0 to run off the TCA0 clock +pwmPrescaler(TCB_0, TCB_CLKTCA); +// Set timer TCB1 prescaler to 1/2 of the system clock frequency +pwmPrescaler(TCB_1, TCB_DIV2); +``` + +### Table of valid options + +| Prescaler | Timer | Description | Notes | +|---------------|---------|----------------------------------------------------|-------------------------------------------------| +| `TCB_DIV1` | TCB0..3 | Runs TCB at full system clock speed | | +| `TCB_DIV2` | TCB0..3 | Runs TCB at 1/2 of the system clock | | +| `TCB_CLKTCA` | TCB0..3 | Runs TCB at the same clock as TCA0 is running off | Default option for all TCB timers | +| `TCA_DIV1` | TCA0 | Runs TCA0 full system clock speed | | +| `TCA_DIV2` | TCA0 | Runs TCA0 at 1/2 of the system clock | | +| `TCA_DIV4` | TCA0 | Runs TCA0 at 1/4 of the system clock | | +| `TCA_DIV8` | TCA0 | Runs TCA0 at 1/8 of the system clock | | +| `TCA_DIV16` | TCA0 | Runs TCA0 at 1/16 of the system clock | | +| `TCA_DIV64` | TCA0 | Runs TCA0 at 1/64 of the system clock | Default option when using a 16 MHz system clock | +| `TCA_DIV256` | TCA0 | Runs TCA0 at 1/256 of the system clock | | +| `TCA_DIV1024` | TCA0 | Runs TCA0 at 1/1024 the system clock | | + + +## pwmSetResolution +This function lets you change the PWM resolution in favour of increased PWM frequency. The default PWM range is 0-255, but the upper limit can be set to anything between 1 and 254. The resolution also affects the PWM frequency. The frequency can be calculated using this formula: +`F_CPU / resolution / prescaler` + +### Declaration +```c++ +void pwmSetResolution(pwm_timers_t pwmTimer, uint8_t maxValue); +``` + +### Example +```c++ +// Set TCA0 timer max value to 127 +pwmSetResolution(TCA0_0, 127); +// Set TCB0 timer max value to 31 +pwmSetResolution(TCB_0, 31); +// Set TCB1 timer max value to 99 +pwmSetResolution(TCB_1, 99); +``` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8000a6f --- /dev/null +++ b/LICENSE @@ -0,0 +1,504 @@ + 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. + + + Copyright (C) + + 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/PlatformIO.md b/PlatformIO.md new file mode 100644 index 0000000..17fc9fd --- /dev/null +++ b/PlatformIO.md @@ -0,0 +1,479 @@ +# PlatformIO + +[PlatformIO](https://platformio.org) is an open-source ecosystem for embedded development. +It has a built-in library manager and is Arduino-compatible. It supports most operating systems; Windows, MacOS, Linux 32 and 64-bit, ARM, and X86. And best of all, MegaCoreX is supported! + +* [What is PlatformIO?](http://docs.platformio.org/en/latest/what-is-platformio.html) +* [PlatformIO IDE](https://platformio.org/platformio-ide) +* Getting started with [PlatformIO IDE](https://docs.platformio.org/en/latest/integration/ide/visualstudio.html) or [PlatformIO command line interface](https://docs.platformio.org/en/latest/core/index.html) +* [Advanced functionality](https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html) +* [Project Examples](https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html#examples) + + +## MegaCoreX + PlatformIO +MegaCoreX and PlatformIO go great together. You can do serial uploads and upload using a dedicated UPDI programmer, but you can also let PlatformIO calculate the fuses and load the correct bootloader file, just like Arduino IDE does! + +PlatformIO uses the information provided in platformio.ini to calculate what fuse bits and what bootloader file to load. +Simply provide enough information and run the following commands: + +```ini +; Only set fuses +pio run -t fuses -e fuses_bootloader +; Set fuses and burn bootloader +pio run -t bootloader -e fuses_bootloader +; (where "fuses_bootloader" can be replaced with a different environment to match your build configuration) +``` + +You can find a platformio.ini template you can use when creating a project for a MegaCoreX-compatible device below. +The most common functionality is available in this template. As you can see, the templated is divided into multiple environments. + +* The default build environment is defined under *[platformio]*. +* All parameters that are common for all environments are defined under *[env]*. +* Use the *[env:Upload_UPDI]* or *[env:Upload_UART]* to upload to your target. +* Use *[env:fuses_bootloader]* to set the fuses or burn the bootloader. + +More information on what each line means can be found further down on this page. + + +## platformio.ini templates +All these templates are very similar, but I've created a few ones for different programmers to make it easier to get started + +
+ATmega4809, microUPDI / Xplained Mini programmer, optional bootloader + +```ini +; PlatformIO template configuration file for MegaCoreX +; https://github.com/MCUdude/MegaCoreX/ +; +; Build options: build flags, source filter +; Hardware options: oscillator type, BOD, UART number, EEPROM retain +; Upload options: custom upload port, speed, and extra flags +; Library options: dependencies, extra library storage +; Advanced options: extra scripting +; +; Please visit documentation for the other options +; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md +; https://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html + +[platformio] +; Default build target +default_envs = Upload_UPDI + +; Parameters used for all environments +[env] +platform = atmelmegaavr +framework = arduino + +; Chip in use +board = ATmega4809 +; Clock frequency in [Hz] +board_build.f_cpu = 16000000L +; Oscillator type (internal or external) +board_hardware.oscillator = internal +; Arduino pinout variant +board_build.variant = 48pin-standard + +; Unflag build flags +build_unflags = +; Extra build flags +build_flags = + +; Monitor port is auto detected. Override here +;monitor_port = +monitor_speed = 9600 + + +; Run the following command to upload with this environment +; pio run -t upload +[env:Upload_UPDI] +; Upload protocol for UPDI upload +upload_protocol = xplainedmini_updi +upload_flags = + + +; Run the following command to upload with this environment +; pio run -e Upload_UART -t upload +[env:Upload_UART] +; Upload protocol for serial uploads (using Optiboot) +upload_protocol = arduino +upload_port = /dev/cu.usbserial* +upload_flags = + + +; run the following command to set fuses +; pio run -e fuses_bootloader -t fuses +; run the following command to set fuses + burn bootloader +; pio run -e fuses_bootloader -t bootloader +[env:fuses_bootloader] +; Inherit upload settings from the Upload_UPDI environment +extends = env:Upload_UPDI + +; Hardware settings +board_hardware.bod = 2.7v +board_hardware.eesave = yes +board_hardware.uart = no_bootloader +board_hardware.rstpin = reset + +``` + +
+ +
+ATmega4809, SerialUPDI programmer, optional bootloader + +```ini +; PlatformIO template configuration file for MegaCoreX +; https://github.com/MCUdude/MegaCoreX/ +; +; Build options: build flags, source filter +; Hardware options: oscillator type, BOD, UART number, EEPROM retain +; Upload options: custom upload port, speed, and extra flags +; Library options: dependencies, extra library storage +; Advanced options: extra scripting +; +; Please visit documentation for the other options +; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md +; https://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html + +[platformio] +; Default build target +default_envs = Upload_UPDI + +; Parameters used for all environments +[env] +platform = atmelmegaavr +framework = arduino + +; Chip in use +board = ATmega4809 +; Clock frequency in [Hz] +board_build.f_cpu = 16000000L +; Oscillator type (internal or external) +board_hardware.oscillator = internal +; Arduino pinout variant +board_build.variant = 48pin-standard + +; Unflag build flags +build_unflags = +; Extra build flags +build_flags = + +; Monitor port is auto-detected. Override here +;monitor_port = ${env:Upload_UPDI.upload_port} +monitor_speed = 9600 +monitor_dtr = 0 + + +; Run the following command to upload with this environment +; pio run -t upload +[env:Upload_UPDI] +; Upload protocol for UPDI upload +upload_protocol = serialupdi +upload_port = /dev/cu.usbserial* +upload_speed = 115200 +upload_flags = + -xrtsdtr=high + + +; Run the following command to upload with this environment +; pio run -e Upload_UART -t upload +[env:Upload_UART] +; Upload protocol for serial uploads (using Optiboot) +upload_protocol = arduino +upload_port = /dev/cu.usbserial* +upload_flags = + + +; run the following command to set fuses +; pio run -e fuses_bootloader -t fuses +; run the following command to set fuses + burn bootloader +; pio run -e fuses_bootloader -t bootloader +[env:fuses_bootloader] +; Inherit upload settings from the Upload_UPDI environment +extends = env:Upload_UPDI + +; Hardware settings +board_hardware.bod = 2.7v +board_hardware.eesave = yes +board_hardware.uart = no_bootloader +board_hardware.rstpin = reset + +``` + +
+ +
+ATmega4809, JTAG2UPDI programmer, optional bootloader + +```ini +; PlatformIO template configuration file for MegaCoreX +; https://github.com/MCUdude/MegaCoreX/ +; +; Build options: build flags, source filter +; Hardware options: oscillator type, BOD, UART number, EEPROM retain +; Upload options: custom upload port, speed, and extra flags +; Library options: dependencies, extra library storage +; Advanced options: extra scripting +; +; Please visit documentation for the other options +; https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md +; https://docs.platformio.org/page/projectconf.html +; https://docs.platformio.org/en/latest/platforms/atmelmegaavr.html + +[platformio] +; Default build target +default_envs = Upload_UPDI + +; Parameters used for all environments +[env] +platform = atmelmegaavr +framework = arduino + +; Chip in use +board = ATmega4809 +; Clock frequency in [Hz] +board_build.f_cpu = 16000000L +; Oscillator type (internal or external) +board_hardware.oscillator = internal +; Arduino pinout variant +board_build.variant = 48pin-standard + +; Unflag build flags +build_unflags = +; Extra build flags +build_flags = + +; Monitor port is auto-detected. Override here +;monitor_port = ${env:Upload_UPDI.upload_port} +monitor_speed = 9600 +monitor_dtr = 0 + + +; Run the following command to upload with this environment +; pio run -t upload +[env:Upload_UPDI] +; Upload protocol for UPDI upload +upload_protocol = jtag2updi +upload_port = /dev/cu.usbserial* +upload_speed = 115200 +upload_flags = + + +; Run the following command to upload with this environment +; pio run -e Upload_UART -t upload +[env:Upload_UART] +; Upload protocol for serial uploads (using Optiboot) +upload_protocol = arduino +upload_port = /dev/cu.usbserial* +upload_flags = + + +; run the following command to set fuses +; pio run -e fuses_bootloader -t fuses +; run the following command to set fuses + burn bootloader +; pio run -e fuses_bootloader -t bootloader +[env:fuses_bootloader] +; Inherit upload settings from the Upload_UPDI environment +extends = env:Upload_UPDI + +; Hardware settings +board_hardware.bod = 2.7v +board_hardware.eesave = yes +board_hardware.uart = no_bootloader +board_hardware.rstpin = reset + +``` + +
+ +### `board` +PlatformIO requires the `board` parameter to be present. +The table below shows what board name should be used for each target +| Board name | +|---------------| +| `ATmega4809` | +| `ATmega4808` | +| `ATmega3209` | +| `ATmega3208` | +| `ATmega1609` | +| `ATmega1608` | +| `ATmega809` | +| `ATmega808` | + + +### `board_build.f_cpu` +Specifies the clock frequency in [Hz]. +Used to determine what oscillator option to choose. A capital *L* has to be added to the end of the frequency number. +Below is a table with supported clocks for MegaCoreX. Defaults to 16 MHz internal if not specified. + +| Clock speed | Oscillator | board_build.f_cpu | +|-------------|------------|-----------------------| +| 20 MHz | Internal | `20000000L` | +| 16 MHz | Internal | `16000000L` (default) | +| 10 MHz | Internal | `10000000L` | +| 8 MHz | Internal | `8000000L` | +| 5 MHz | Internal | `5000000L` | +| 4 MHz | Internal | `4000000L` | +| 2 MHz | Internal | `2000000L` | +| 1 MHz | Internal | `1000000L` | +| 16 MHz | External | `16000000L` | +| 12 MHz | External | `12000000L` | +| 8 MHz | External | `8000000L` | +| 4 MHz | External | `4000000L` | +| 1 MHz | External | `1000000L` | + + +### `board_hardware.oscillator` +Specifies to use the internal or an external oscillator. + +| Oscillator option | +|----------------------| +| `internal` (default) | +| `external` | + + +### `board_hardware.uart` +Specifies the hardware UART port used for serial upload. Use `no_bootloader` if you’re using a dedicated UPDI programmer, i.e not using a bootloader for serial upload. + +| Upload serial port option | Description | +|---------------------------|------------------------------------------------| +| `no_bootloader` (default) | | +| `uart0` / `uart0_def` | Use UART0 default pins | +| `uart0_alt` | Use UART0 alternative pins | +| `uart1` / `uart1_def` | Use UART1 default pins | +| `uart1_alt` | Use UART1 alternative pins | +| `uart2` / `uart2_def` | Use UART2 default pins | +| `uart2_alt` | Use UART2 alternative pins | +| `uart3` / `uart3_def` | Use UART3 default pins (48-pin parts only) | +| `uart3_alt` | Use UART3 alternative pins (48-pin parts only) | + +### `board_hardware.bod` +Specifies the hardware brown-out detection. Use `disabled` to disable. + +| BOD | +|------------------| +| `4.3v` | +| `2.6v` (default) | +| `1.8v` | +| `disabled` | + + +### `board_hardware.eesave` +Specifies if the EEPROM memory should be retained when uploading using a programmer. Use `no` to disable. + +| EEPROM retain | +|-----------------| +| `yes` (default) | +| `no` | + + +### `board_hardware.rstpin` +Specifies what functionality the reset pin should have. Note that the option `reset` _will_ be selected regardless if you're using a bootloader. + +| Reset pin functionality | +|---------------------------| +| `reset` (default) | +| `gpio` | + + +### `board_build.variant` +Holds the current pinout in use. PlatformIO automatically selects the *default* one if not specified. +See [pinout pics](https://github.com/MCUdude/MegaCoreX#pinout) for more info. + +| Pinouts 48 pin parts | Pinouts 40 pin parts | Pinouts 32 pin parts | Pinouts 28 pin parts | +|----------------------------|------------------------------------|----------------------------|----------------------------| +| `48pin-standard` (default) | `40pin-standard` (must be defined) | `32pin-standard` (default) | `28pin-standard` (default) | +| `nano-every` | | `nano-4808` | | +| `uno-wifi` | | | | + + +### `build_unflags` +This parameter is used to unflag flags automatically set by the PlatformIO build environment. + +**Example:** +``` +build_unflags = + -flto + -fpermissive +``` + + +### `build_flags` +This parameter is used to set compiler flags. This is useful if you want to for instance want to chage the serial RX or TX buffer. Here's a list of the current available core files flags: + +| Flag | Default size | Description | +|-----------------------------|--------------|-----------------------------------------------------------| +| -lprintf_flt | | Lets you print floats with printf (occupies ~1.5 kB) | +| -Wall -Wextra | | Show on all compiler warnings | +| -DSERIAL_RX_BUFFER_SIZE=128 | 64 bytes | Sets the serial RX buffer to 128 bytes | +| -DSERIAL_TX_BUFFER_SIZE=128 | 64 bytes | Sets the serial TX buffer to 128 bytes | +| -DTWI_BUFFER_SIZE=64 | 32 bytes | Sets the TWI (i2c) buffer to 64 bytes | + +**Example:** +``` +build_flags = + -DSERIAL_RX_BUFFER_SIZE=128 + -DSERIAL_TX_BUFFER_SIZE=128 +``` + + +### `upload_port` +Holds the serial port used for uploading. Only needed if you're uploading using a SerialUPDI or JTAG2UPDI programmer or with a USB-to-serial adapter using the Optiboot bootloader. PlatformIO automatically detects the serial port. However, if you want to override this you can uncomment `upload_port`. Use `/dev/[port]` on Unix-compatible systems, and use `COMx` on Windows. + + +### `upload_protocol` +Programmer used for uploading. + +| Supported UPDI programmers in Avrdude | Notes | +|---------------------------------------|------------------------------------------------------------------------------------------------------------------| +| [`serialupdi`](https://www.tindie.com/products/mcudude/serialupdi-programmer/) | Requires upload serial port. Change the baud rate in `upload_speed` to increase or decrease upload speed | +| `xplainedmini_updi` | Xplained Mini and [microUPDI](https://www.tindie.com/products/MCUdude/microupdi-programmer/) programmers | +| `jtag2updi` | Requires serial upload port. Newer JTAG2UPDI firmware versions support baud rates higher than 115200 baud | +| `arduino` | Used when uploading using the Optiboot bootloader. Requires upload port | +| `pkobn_updi` | On-board Curiosity nano programmer | +| `pickit4_updi` | PICkit4 programmer in UPDI mode | +| `snap_updi` | MPLAB SNAP programmer in UPDI mode | +| `atmelice_updi` | Atmel ICE programmer in UPDI mode | +| `xplainedpro_updi` | Xplained Pro in UPDI mode | +| `powerdebugger_updi` | Power Debugger in UPDI mode | + + +### `upload_flags` +Used to pass extra flags to Avrdude when uploading using a programmer. +Typical parameters are `-qq` or `-v`. See the [Avrdude documentation](https://avrdudes.github.io/avrdude/) for more information. +**Note that every flag has to be on its own line, and they have to be indented with two spaces:** +```ini +upload_flags = + -v +``` + + +### `monitor_port` +PlatformIO detects serial ports automatically. However, if you want to override this you can uncomment `monitor_port`. Use `/dev/[port]` on Unix-compatible systems, and use `COMx` on Windows. + + +### `monitor_speed` +Sets the serial monitor baud rate. Defaults to 9600 if not defined. + + +## User-defined fuses +Even though PlatformIO can calculate fuse values depending on the user-specified data in platformio.ini, there may be applications where the fuses have to be set to known values. This can be done like so: +```ini +; run the following command to set fuses +; pio run -e custom_fuses -t fuses +[env:custom_fuses] +; Inherit upload settings from the Upload_UPDI environment +extends = env:Upload_UPDI + +; Fuse settings +board_fuses.wdtcfg = 0x00 +board_fuses.bodcfg = 0x00 +board_fuses.osccfg = 0x01 +board_fuses.tcd0cfg = 0x00 +board_fuses.syscfg0 = 0xC9 +board_fuses.syscfg1 = 0x06 +board_fuses.append = 0x00 +board_fuses.bootend = 0x00 +``` diff --git a/README.md b/README.md index 5e3f1d0..830341e 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,87 @@ # MegaCoreX -An Arduino core for the new megaAVR series! -ATmega3208, ATmega4808, ATmega3209 and ATmega4809. - -**TODO:** -* ~~UART pin swap inegraion~~ **DONE! use Serial.swap()** -* ~~Add printf to print class~~ **DONE! use Serial.printf()** -* Get rid of nasty compiler warning when compiling a blank sketch (or any sketch really..) -* Steal 20 MHz accurate timing from MCUdude_corefiles -* SPI pin swap integration in libraries -* I2C pin swap integration in libraries -* Example (library?) for using the 32.768kHz cystal that can be found on Uno Wifi Rev2 and Curiosity Nano 4809 -* Add ArduinoAPI as subtree for easy maintainance (just need to get some PRs such as printf functionality merged first) -* Readme - - Need some good intro text at the beginning - - Minimal setup schematics -* Proper testing with updated toolchain (I'm experiencing trouble with the 32kB chips) +An Arduino core for ATmega4809, ATmega4808, ATmega3209, ATmega3208, ATmega1609, ATmega1608, ATmega809 and ATmega808. This megaAVR-0 chip family offers lots of features and peripherals at an incredible price point. The largest one, the ATmega4809 can be found in products like the Arduino Uno WiFi Rev2 and the Arduino Nano Every. Some of their key features include multiple serial ports, SPI and i2c interfaces, built-in programmable logic, up to 16 analog input pins, and an analog comparator with a built-in programmable voltage reference and hysteresis and much more! +Compared to older AVR families they also have more advanced and accurate internal oscillators which can provide base frequencies of 16 and 20 MHz. These can then be divided down internally to reduce the processor speed and power consumption. This means in most applications an external clock isn't necessary anymore. You can read more about clocks and clock frequencies in the [Supported clock frequencies](#supported-clock-frequencies) section. + +For programming, these chips use a UPDI programming interface. This is a bi-directional single wire interface and requires a programmer that supports UPDI. If you rather prefer uploading using a USB to serial adapter there is an option to use the Optiboot bootloader. Read more about UPDI and bootloaders in the [Programming](#programming) section below. + +#### UPDI programmers +If you're looking for well-designed, reliable UPDI programmers that also acts as a USB to serial adapters, check out the [microUPDI](https://www.tindie.com/products/MCUdude/microupdi-programmer/) and the [SerialUPDI](https://www.tindie.com/products/mcudude/serialupdi-programmer/) programmers I sell on [Tindie](https://www.tindie.com/stores/mcudude/)! +They're small programmers with excellent software support, and can be used with Arduino IDE or PlatformIO. The SerialUPDI programmer comes fully assembled (except for the 6-pin programming connector), but the microUPDI needs to be soldered to an Arduino Pro Micro board. + +| [microUPDI](https://www.tindie.com/products/MCUdude/microupdi-programmer/) | [SerialUPDI](https://www.tindie.com/products/mcudude/serialupdi-programmer/) | Pinout | +|----------------------------------------------------------------------------|------------------------------------------------------------------------------|----------------------------------------------------------| +| | | | +| | | | # Table of contents * [Supported microcontrollers](#supported-microcontrollers) * [Programming](#programming) + - [Using a UPDI programmer](#using-a-updi-programmer) + - [SerialUPDI](#serialupdi) + - [Using a bootloader](#using-a-bootloader) * [Supported clock frequencies](#supported-clock-frequencies) * [BOD option](#bod-option) +* [EEPROM retain option](#eeprom-option) * [Reset pin](#reset-pin) +* [Printf support](#printf-support) +* [Fast IO](#fast-io) +* [Flexible PWM setup and routing](#flexible-pwm-setup-and-routing) +* [Pin macros](#pin-macros) +* [Write to own flash](#write-to-own-flash) +* [Memory-mapped flash](#memory-mapped-flash) +* [Identifying MegaCoreX](#identifying-megacorex) +* [Timer used for millis and micros](#timer-used-for-millis-and-micros) * [Pinout](#pinout) +* [Hardware features](#hardware-features) + - [PWM output](#pwm-output) + - [Configurable Custom Logic (CCL)](#configurable-custom-logic-ccl) + - [Analog Comparator (AC)](#analog-comparator-ac) + - [Event System (EVSYS)](#event-system-evsys) + - [Peripheral pin swapping](#peripheral-pin-swapping) * [How to install](#how-to-install) - [Boards Manager Installation](#boards-manager-installation) - [Manual Installation](#manual-installation) + - [PlatformIO](#platformio) +* [Minimal setup](#minimal-setup) * [Getting your hardware working](#getting-your-hardware-working) - [Arduino Uno WiFi Rev2](#arduino-uno-wifi-rev2) + - [Arduino Nano Every](#arduino-nano-every) + - [Nano 4808](#nano-4808) - [Curiosity Nano](#curiosity-nano) - [AVR-IOT-WG](#avr-iot-wg) - [4809 Xplained Pro](#atmega4809-xplained-pro) + ## Supported microcontrollers -| | ATmega4809 | ATmega4808 | ATmega3209 | ATmega3208 | -|------------------------|------------------|-----------------------------|------------------|-----------------------------| -| **Flash** | 48 kB | 48 kB | 32 kB | 32 kB | -| **RAM** | 6 kB | 6 kB | 4 kB | 4 kB | -| **EEPROM** | 256 B | 256 B | 256 B | 256 B | -| **Serial ports** | 4 | 3 | 4 | 3 | -| **IO pins** | 40/41* | 26/27*
23†/24†† | 40/41* | 26/27*
23†/24†† | -| **Available packages** | TQFP48
QFN48 | TQFP32
QFN32
SSOP28 | TQFP48
QFN48 | TQFP32
QFN32
SSOP28 | +| | Mega4809 | Mega4808 | Mega3209 | Mega3208 | Mega1609 | Mega1608 | Mega809 | Mega808 | +|------------------|----------------------------|-----------------------------------|-------------------|-----------------------------------|-------------------|-----------------------------------|-------------------|-----------------------------------| +| **Flash** | 48 kiB | 48 kiB | 32 kiB | 32 kiB | 16 kiB | 16 kiB | 8 kiB | 8 kiB | +| **RAM** | 6 kiB | 6 kiB | 4 kiB | 4 kiB | 2 kiB | 2 kiB | 1 kiB | 1 kiB | +| **EEPROM** | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | 256 B +
64 B† | +| **Serial ports** | 4 | 3 | 4 | 3 | 4 | 3 | 4 | 3 | +| **IO pins** | 41
33*** | 27*
24** | 41 | 27*
24** | 41 | 27*
24** | 41 | 27*
24** | +| **Packages** | TQFP48
QFN48
DIP40 | TQFP32
QFN32
SSOP28 | TQFP48
QFN48 | TQFP32
QFN32
SSOP28 | TQFP48
QFN48 | TQFP32
QFN32
SSOP28 | TQFP48
QFN48 | TQFP32
QFN32
SSOP28 | -* Physical reset pin is disabled -† SSOP28 package -†† SSOP28 package and reset disabled +† 64 bytes of USERROW, accessible from address 256 to 319 using the EEPROM.h library
+* TQFP32/QFN32 package
+** SSOP28 package
+*** DIP40 package ## Programming -Programming must be done with a UPDI compatible programmer, such as the JTAGICE 3 or any of the new EDBG chips that can be found on newer AVR explained and curoisity boards. +### Using a UPDI programmer +Programming must be done with a UPDI compatible programmer, such as the [microUPDI](https://github.com/MCUdude/microUPDI), [JTAG2UPDI](https://github.com/ElTangas/jtag2updi) SerialUPDI or an official Atmel/Microchip UPDI compatible programmer. -Unlike the Arduino UNO WiFi Rev2 boards package MegaCoreX does not auto detect the programmer you're using. You'll have to select the correct programmer in the *Programmers*. If you're using an Arduino Uno Wifi Rev2 board, a Curiosity Nano or an Xplained pro board you'll have to choose mEDBG, nEDBG or EDBG. +Unlike the *Arduino megaAVR boards* package, MegaCoreX does not auto-detect the programmer you're using. You'll have to select the correct programmer in the *Programmers* menu. +#### SerialUPDI +SerialUPDI is a programmer that utilize a simple serial connection. It uses a USB serial adapter which can be turned into a UPDI programmer by adding a few passive components. You can read more about the details on how the SerualUPDI works [here](https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md). + +### Using a bootloader +Programming can also be done using the [Optiboot bootloader](https://github.com/optiboot/Optiboot). It is available for all megaAVR-0 chips and can be used with all hardware serial ports including alternative pin positions. Simply select what UART number to use, default/alternative pin position and click "Burn bootloader". The bootloader will flash an LED connected to PA7 (digital pin 7 on most pinouts) twice when a hardware reset occurs. The upload speed is 115200 baud. Note that that the reset pin cannot be used as a GPIO when using a bootloader. It doesn't matter if you have set the reset pin as GPIO in the tools menu or not; the bootloader option will override this setting. ## Supported clock frequencies MegaCoreX lets you choose what clock frequency you want to run your microcontroller at. @@ -63,20 +90,30 @@ MegaCoreX lets you choose what clock frequency you want to run your microcontrol |-----------|---------------------|--------------------------| | 20 MHz | Internal oscillator | | | 16 MHz | Internal oscillator | **Default option** | +| 10 MHz | Internal oscillator | Derived from 20 MHz osc. | | 8 MHz | Internal oscillator | Derived from 16 MHz osc. | +| 5 MHz | Internal oscillator | Derived from 20 MHz osc. | | 4 MHz | Internal oscillator | Derived from 16 MHz osc. | | 2 MHz | Internal oscillator | Derived from 16 MHz osc. | | 1 MHz | Internal oscillator | Derived from 16 MHz osc. | +| 20 MHz | External clock | | +| 16 MHz | External clock | | +| 12 MHz | External clock | | +| 8 MHz | External clock | | +| 1 MHz | External clock | | + +Note that unlike other AVRs **none of these chips can drive an external crystal or resonator**. If you need an external oscillator it has to be one with a driven clock output. +The microcontroller will freeze if the external clock suddenly drops out. If not present on boot, it will automatically choose the 16 MHz internal oscillator instead. -Note that unlike other AVRs none of these chips are able to drive an external crystal or resonator. If you need an external oscillator it has to be one with a driven clock output. +Another thing to watch out for is the lowest possible baudrates when running at 16 or 20 MHz. At 16 MHz the lowest baud rate is 1200 baud. When running at 20 MHz the lowest is 2400 baud. This is caused by the way the internal baud rate generator works. If you need lower baud rates you'll either have to reduce the main clock speed or use the software serial library instead. ## BOD option -Brown out detection, or BOD for short lets the microcontroller sense the input voltage and shut down if the voltage goes below the brown out setting. Below is a table that shows the available BOD options: +Brownout detection or BOD for short lets the microcontroller sense the input voltage and shut down if the voltage goes below the brownout setting. Below is a table that shows the available BOD options: -| | +| BOD threshold | |--------------------------------| -| 4.2 V | +| 4.3 V | | 4.0 V | | 3.7 V | | 3.3 V | @@ -87,55 +124,241 @@ Brown out detection, or BOD for short lets the microcontroller sense the input v | Disabled | +## EEPROM option +If you want the EEPROM to be erased every time you burn the bootloader or upload using a programmer, you can turn off this option. A UPDI programmer is needed to enable or disable EEPROM retain. Note that when uploading using a bootloader, the EEPROM will always be retained. + + ## Reset pin -None of the megaAVR-0 microcontrollers needs the reset line in order to be reprogrammed over the UPDI interface. This means that the reset pin can be used as a GPIO pin instead! There's no need for a high voltage programmer in order to turn that pin into a reset pin again either. If you have a development board you can instead use the reset button as a general purpose button for your project. +None of the megaAVR-0 microcontrollers needs the reset line to be reprogrammed over the UPDI interface. This means that the reset pin can be used as a GPIO pin instead! There's no need for a high voltage programmer to turn that pin into a reset pin again either. If you have a development board you can instead use the reset button as a general-purpose button for your project. Note that the reset pin cannot be usd as a GPIO when using a bootloader. + + +## Printf support +Unlike the official Arduino core, MegaCoreX has printf support out of the box. If you're not familiar with printf you should probably [read this first](https://www.tutorialspoint.com/c_standard_library/c_function_printf.htm). It's added to the Print class and will work with all libraries that inherit Print. Printf is a standard C function that lets you format text much easier than using Arduino's built-in print and println. + +[**See the extended API documentation for more information!**](https://github.com/MCUdude/MegaCoreX/tree/master/Extended-API.md#printf-support) + + +## Fast IO +For timing critical applications the standard `digitalRead()` and `digitalWrite()` functions may be too slow. To solve this, MegaCoreX also incorporates `digitalReadFast(myPin)` and `digitalWriteFast(mypin, state)` which compiles down to a single instruction. + +[**See the extended API documentation for more information!**](https://github.com/MCUdude/MegaCoreX/tree/master/Extended-API.md#fast-io) + + +## Flexible PWM setup and routing + +The various pinout this core provides are optimized to expose as many features on the available IO pins as possible. This is great where you want to have as many options as possible. For instance, I've tried my best to route various peripherals around so they don't share the same pins as other, frequencly used peripherals. +By default, PWM pins can't be moved around using the Arduino framework. And the megaAVR-0 family of chips only allows you to route a PWM output to a few pin options. To overcome this limitation and provide greater flexibility, I've added a few functions that makes PWM setup and routing much easier! Here's an example of how you would re-route the PWM output from timer TCB0 to a different pin: + +```c +// Route timer TCB0 PWM output to pin PF4 and set the duty cycle to 50% (128/255) +pwmWrite(TCB_0, 128, ROUTE_TCB0_PF4); +// Set the timer TCB0 duty cycle to 30% but leave the routing as is +pwmWrite(TCB_0, 76); +``` + +[**See the PWM section in the extended API documentation for more information!**](https://github.com/MCUdude/MegaCoreX/tree/master/Extended-API.md#pwmwrite---flexible-pwm-routing) + + +## Pin macros +Note that you don't have to use the digital pin numbers to refer to the pins. You can also use some predefined macros that map "Arduino pins" to the port and port number. +Note that all my Arduino cores have these macros if you prefer to use these rather than the default Arduino pin number. + +```c++ +// Use PIN_PA0 macro to refer to pin PA0 (Arduino pin 0) +digitalWrite(PIN_PA0, HIGH); + +// Results in the exact same compiled code +digitalWrite(0, HIGH); +``` + + +## Write to own flash +As an alternative for UPDI, MegaCoreX uses Optiboot Flash, a bootloader that supports flash writing within the running application, thanks to the work of [@majekw](https://github.com/majekw). +This means that content from e.g. a sensor can be stored in the flash memory directly without the need of external memory. Flash memory is much faster than EEPROM, and can handle at least 10 000 write cycles before wear becomes an issue. +For more information on how it works and how you can use this in you own application, check out the [Serial_read_write](https://github.com/MCUdude/MegaCoreX/blob/master/megaavr/libraries/Optiboot_flasher/examples/Serial_read_write/Serial_read_write.ino) for a simple proof-of-concept demo, and +[Flash_put_get](https://github.com/MCUdude/MegaCoreX/blob/master/megaavr/libraries/Optiboot_flasher/examples/Flash_put_get/Flash_put_get.ino) + [Flash_iterate](https://github.com/MCUdude/MegaCoreX/blob/master/megaavr/libraries/Optiboot_flasher/examples/Flash_iterate/Flash_iterate.ino) for useful examples on how you can store strings, structs and variables to flash and retrieve then afterwards. + + +## Memory-mapped flash +Unlike classic AVRs, the flash memory on these parts is within the same address space as the main memory. This means that functions like `pgm_read_byte()` and `pgm_read_word()` is not needed to read directly from flash. Because of this, the compiler automatically puts any variable declared const into PROGMEM, and accesses it appropriately - you no longer need to explicitly declare them as PROGMEM! +This also includes quoted strings, which means that the string in `Serial.print("Hello World");` won't consume any RAM. This means that the `F()` macro is not needed when working with MegaCoreX. + +If you explicitly declare a variable PROGMEM, you must still use the `pgm_read_byte()/pgm_read_word()` functions, just like on "classic" AVRs. Do note that declaring things PROGMEM or using the `F()` macro works fine, but it is slower and consumes more flash than simply declaring something `const` or omitting the `F()` macro. + + +# Identifying MegaCoreX +If you're writing code that has MegaCoreX specific code in it, you can identify this core and various pinouts with the list of macros below. + + +| Core specific | Pinout specific | Chip family specific | Chip specific | +|---------------------|----------------------------------|----------------------|----------------------| +| `MEGACOREX` | `MEGACOREX_DEFAULT_48PIN_PINOUT` | `__AVR_ATmegax09__` | `__AVR_ATmega4809__` | +| `MCUDUDE_MEGACOREX` | `MEGACOREX_DEFAULT_40PIN_PINOUT` | `__AVR_ATmegax08__` | `__AVR_ATmega4808__` | +| | `MEGACOREX_DEFAULT_32PIN_PINOUT` | | `__AVR_ATmega3209__` | +| | `MEGACOREX_DEFAULT_28PIN_PINOUT` | | `__AVR_ATmega3208__` | +| | | | `__AVR_ATmega1609__` | +| | | | `__AVR_ATmega1608__` | +| | | | `__AVR_ATmega809__` | +| | | | `__AVR_ATmega808__` | + +Usage: +```c++ +#if defined(MEGACOREX) +// Code +#endif +``` + + +# Timer used for millis and micros +The 28 and 32 pin part have a total of three TCB timers, while the 40 and 48 pin parts have four. In order to create default pinouts with as may PWM output pins as possible, different pinout uses different timers for millis and micros. +The default timer can be changed by adding `-DMILLIS_USE_TIMERBx` to the platformio.ini build flags, where *x* represents the TCB timer number from 0 to 3. Alternativey, the respective *pins_arduino.h* file can be modified if using Arduino IDE. + +| Pinout | Timer used for millis and micros | +|-----------------|----------------------------------| +| 48 pin standard | TCB3 | +| 40 pin standard | TCB2 | +| 32 pin standard | TCB2 | +| 28 pin standard | TCB2 | +| Uno WiFi | TCB3 | +| Nano Every | TCB3 | +| Nano Every 4808 | TCB2 | ## Pinout This core provides several different Arduino pin mappings based on your current hardware -- **Uno WiFi**: This pinout is 100% compatible with the Arduino Uno WiFi Rev2 hardware. If you have code that's written for the Uno WiFi Rev2 it will work without any modifications if you choose this pinout. Note that this pinout does pin swapping on serial interfaces and PWM pins by default, and some peripherals are renamed to match the original 328P Uno hardware better. Note that this pinout is only available on ATmega3209/ATmega4809. -- **48 pin standard**: This pinout is much closer to the actual hardware than the Uno WiFi pinout. It will not be compatible with shields or anything like that, but it's much more clean and elegant from a hardware point of view. The only pin swap done by default is the PWM output pins. This is done to prevent them from "colliding" with other peripherals. Note that this pinout is only available on ATmega3209/ATmega4809. +- **48 pin standard**: This pinout is much closer to the actual hardware than the Uno WiFi pinout. It will not be compatible with shields or anything like that, but it's much cleaner and elegant from a hardware point of view. The only pin swap done by default is the PWM output pins. This is done to prevent them from "colliding" with other peripherals. Note that this pinout is only available on ATmega3209/ATmega4809. +- **40 pin standard**: This pinout is more or less identical to the 48 pin variant, but with a reduced pin number. Note that this pinout is only available on ATmega4809. - **32 pin standard**: This is the pinout for the 32 pin version of the ATmega3208/4808. Again, it will not be compatible with shields or anything like that, but it's clean and elegant from a hardware point of view. The only pin swap done by default is the PWM output pins. This is done to prevent them from "colliding" with other peripherals. -- **28 pin standard**: This is the pinout for the 28 pin version of the ATmega3208/4808. Will not be compatible with shields or anything like that, but it's still clean and elegant from a hardware point of view. Only pin swap done by default is the PWM output pins. This is done to prevent them from "colliding" with other peripherals. +- **28 pin standard**: This is the pinout for the 28 pin version of the ATmega3208/4808. It will not be compatible with shields or anything like that, but it's still clean and elegant from a hardware point of view. Only pin swap done by default is the PWM output pins. This is done to prevent them from "colliding" with other peripherals. +- **Uno WiFi**: This pinout is 100% compatible with the Arduino Uno WiFi Rev2 hardware. If you have code that's written for the Uno WiFi Rev2 it will work without any modifications if you choose this pinout. Note that this pinout does pin swapping on serial interfaces and PWM pins by default, and some peripherals are renamed to match the original 328P Uno hardware better. Note that this pinout is only available on ATmega3209/ATmega4809. +- **Nano Every**: This pinout is 100% compatible with the Arduino Nano Every. If you have code that's written for the Nano Every it will work without any modifications if you choose this pinout. Note that this pinout does pin swapping on serial interfaces and PWM pins by default, and some peripherals are renamed to match the original 328P Uno hardware better. This pinout is only available when ATmega4809 is selected. +- **Nano Every 4808**: This matches the "official" Thinary Nano Every pinout, and is compatible with the Thinary Nano Every Arduino core. Note that this pinout does pin swapping on serial interfaces and PWM pins by default. This pinout is only available when ATmega4808 is selected. Please have a look at the pins_arduino.h files for detailed info.

-Click to enlarge: +Click to enlarge: + +| **MegaCoreX ATmega809/1609/3209/4809 pinout** | **MegaCoreX ATmega808/1608/3208/4808 pinout** | +|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|

|























| + + +## Hardware features +Here's some hardware specific features that differ from the older AVR families. + +### Interrupt pins +Unlike older AVRs the megaAVR-0 microcontrollers have fully featured interrupts on every pin. +Supported states are *RISING*, *FALLING*, *CHANGE*, *HIGH* and *LOW*. This means there's no need to use the `digitalPinToInterrupt` macro. Simply call attachInterrupt like this: + +```c +attachInterrupt(myPin, myInterruptFunction, RISING); +``` + +### PWM output +PWM output, `analogWrite()`, is available for the following pins: + +| Pinout | Number of PWM pins | Available PWM pins | +|-------------------|--------------------|------------------------------------| +| *28 pin standard* | 8 | 2, 3, 12, 13, 14, 15, 16, 17 | +| *32 pin standard* | 8 | 2, 3, 12, 13, 14, 15, 16, 17 | +| *40 pin standard* | 8 | 8, 9, 10, 11, 12, 13, 30, 31 | +| *48 pin standard* | 9 | 13, 14, 15, 16, 17, 18, 19, 38, 39 | +| *Uno WiFi* | 6 | 3, 5, 6, 9, 10, 27 | +| *Nano Every* | 5 | 3, 5, 6, 9, 10 | +| *Nano Every 4808* | 8 | 4, 5, 14, 15, 16, 17, 22, 23 | + +The repeat frequency for the pulses on all PWM outputs can be changed with the new function `analogWriteFrequency(kHz)`, where +`kHz` values of 1 (default), 4, 8, 16, 32 and 64 are supported. Note that these values are very approximate. The best effort within the constraints of the hardware will be made to match the request. + +Note also that tone() will use TCB1, so the corresponding PWM output is not available if it is used. + +### Configurable Custom Logic (CCL) +The megaAVR-0 microcontrollers are equipped with four independent configurable logic blocks that can be used to improve speed and performance. The CCL pins are marked on all pinout diagrams in a dark blue/grey color. The logic blocks can be used independently from each other, connected together or generate an interrupt to the CPU. I've made a [light weight, high-level library](https://github.com/MCUdude/MegaCoreX/tree/master/megaavr/libraries/Logic) for easy integration with the CCL hardware. -| **MegaCoreX ATmega3209/4809 pinout** | **MegaCoreX ATmega3208/4808 pinout** | -|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| -|
|







| +### Analog Comparator (AC) +The megaAVR-0 microcontrollers are equipped with an analog comparator. It compares the voltage levels on two inputs and gives a digital output based on this comparison. The megAVR chip has four positive AC pins and three negative. There's also a configurable internal voltage reference that can be used on the negative comparator pin instead of an external voltage. +Try out the [Comparator library](https://github.com/MCUdude/MegaCoreX/tree/master/megaavr/libraries/Comparator) for more information, library reference and examples. + +### Event System (EVSYS) +The Event System (EVSYS) enables direct peripheral-to-peripheral signaling. It allows a change in one peripheral (the event generator) to trigger actions in other peripherals (the event users) through event channels, without using the CPU. It is designed to provide short and predictable response times between peripherals, allowing for autonomous peripheral control and interaction, and also for synchronized timing of actions in several peripheral modules. It is thus a powerful tool for reducing the complexity, size, and execution time of the software. Give the [Event library](https://github.com/MCUdude/MegaCoreX/tree/master/megaavr/libraries/Event) a try! Here you'll find documentation and useful library examples. + +### Peripheral pin swapping +The megaAVR-0 microcontrollers support alternative pin assignments for some of their built-in peripherals.
+MegaCoreX currently supports pinswapping the SPI, i2c and UART peripheral pins. + +[**See the extended API documentation for more information!**](https://github.com/MCUdude/MegaCoreX/tree/master/Extended-API.md#peripheral-pin-swapping) ## How to install #### Boards Manager Installation -*Not yet implemented* +* Open Arduino IDE. +* Open the **File > Preferences** menu item. +* Enter the following URL in **Additional Boards Manager URLs**: + ``` + https://mcudude.github.io/MegaCoreX/package_MCUdude_MegaCoreX_index.json + ``` +* Separate the URLs using a comma ( **,** ) if you have more than one URL +* Open the **Tools > Board > Boards Manager...** menu item. +* Wait for the platform indexes to finish downloading. +* Scroll down until you see the **MegaCoreX** entry and click on it. +* Click **Install**. +* After installation is complete close the **Boards Manager** window. #### Manual Installation Click on the "Download ZIP" button. Extract the ZIP file, and move the extracted folder to the location "**~/Documents/Arduino/hardware**". Create the "hardware" folder if it doesn't exist. -Open Arduino IDE, and a new category in the boards menu called "MightyCoreX" will show up. +Open Arduino IDE and a new category in the boards menu called "MightyCoreX" will show up. + +#### PlatformIO +[PlatformIO](http://platformio.org) is an open source ecosystem for IoT development and supports MegaCoreX. +**See [PlatformIO.md](https://github.com/MCUdude/MegaCoreX/blob/master/PlatformIO.md) for more information.** + + +## Minimal setup +Here are some simple schematics that show a minimal setup. The straight 6-pin header may in the future be used for serial uploads without having to use a UPDI programmer. As of today, we're still waiting for a stable version of Optiboot. +Click to enlarge:
+ +| 48-pin *ATmega809/1609/3209/4809* | 40-pin *ATmega4809* | 32-pin *ATmega808/1608/3208/4808* | +|-------------------------------------------------------|-------------------------------------------------------|-------------------------------------------------------| +|||| ## Getting your hardware working ### Arduino Uno WiFi Rev2 -[The Arduino Uno WiFi Rev2](https://store.arduino.cc/usa/arduino-uno-wifi-rev2) is the easiest board out of these to get started with, because it's officially supported by Arduino. It uses an ATmega4809, and recommended pinout is *Uno WiFi*. Printing to the serial monitor on your PC is done by initializing `Serial.begin(baud)`. You'll also have to choose **Atmel mEDBG (ATmega32u4)** as your programmer in order to upload code. For more information about this board please see the product page and its schematic. +[The Arduino Uno WiFi Rev2](https://store.arduino.cc/arduino-uno-wifi-rev2) is one of the few megaAVR-0 based boards that's officially supported by Arduino. It uses an ATmega4809 and the recommended pinout is *Uno WiFi*. Printing to the serial monitor on your PC is done by initializing `Serial.begin(baud)`. You'll also have to choose **microUPDI/Uno Wifi** as your programmer to upload code. Uno WiFi Rev2 does not support a bootloader, so select *No bootloader* in the tools menu. For more information about this board please see the product page and its schematic. + +Click to enlarge: -Click to enlarge: - + + +### Arduino Nano Every +[The Arduino Nano Every](https://store.arduino.cc/arduino-nano-every) is one of the few megaAVR-0 based boards that's officially supported by Arduino. It uses an ATmega4809 and the *only* supported pinout is *Nano Every*. Printing to the serial monitor on your PC is done by initializing `Serial.begin(baud)`. The Nano Every does not support a bootloader, so select *No bootloader* in the tools menu. Burning bootloader or upload using programmer will not work either. However, all fuses are set every time you upload our program. For more information about this board please see the product page and its schematic. + +Click to enlarge: + + + +### Nano 4808 +The Nano 4808, also known as the Thinary Nano 4808 a third-party Arduino compatible board with the Nano form factor. It uses an ATmega4808 and the *only* supported pinout is *Nano 4808*. Printing to the serial monitor on your PC is done by initializing `Serial.begin(baud)`. The Nano 4808 does not support a bootloader, so select *No bootloader* in the tools menu. The on-board JTAG2UPDI programmer is known to be difficult to enter programming mode when printing to the serial monitor. If you're having upload issues, connect a dedicated UPDI programmer to the UPDI pin, select it in the programmers menu and upload using the programmer. +Click to enlarge: + + ### Curiosity Nano -[The Curiosity Nano](https://www.microchip.com/developmenttools/ProductDetails/DM320115) uses an ATmega4809 but has a different pinout than the Uno Wifi Rev2. Recommended pinout for this board is *48 pin standard*. Use the `LED_BUILTIN` macro to control the onboard LED. Note that UART3 is connected to the nEDBG chip (often refered to as the debug serial port). This means you'll have to use `Serial3.begin(baud)` in order to print to the serial monitor. You'll also have to choose **Atmel nEDBG (ATSAMD21E18)** as your programmer in order to upload code. For more information about this board please refer to the userguide and its schematic. +[The Curiosity Nano](https://www.microchip.com/developmenttools/ProductDetails/DM320115) uses an ATmega4809 but has a different pinout than the Uno Wifi Rev2. The recommended pinout for this board is *48 pin standard*. The on-board LED is connected t pin PF5 (digital pin 39). Note that UART3 is connected to the nEDBG chip (often referred to as the debug serial port). This means you'll have to use `Serial3.begin(baud)` to print to the serial monitor. You'll also have to choose **Curiosity Nano** as your programmer to upload code. For more information about this board please refer to the user guide and its schematic. + +Click to enlarge: -Click to enlarge: - + ### AVR-IOT WG -[The AVR-IOT WG](https://www.microchip.com/developmenttools/ProductDetails/AC164160) uses the ATmega4808 in a 32 pin package. *32 pin standard* is the correct pinout for this board. Use the `LED_BUILTIN` macro to control the onboard LED marked with *WIFI*. Note that UART2 is connected to the nEDBG chip (often refered to as the debug serial port). This means tou'll have to use `Serial2.begin(baud)` in order to print to the serial monitor. You'll also have to choose **Atmel nEDBG (ATSAMD21E18)** as your programmer in order to upload code. For more information about this board please refer to the userguide and its schematic. +[The AVR-IOT WG](https://www.microchip.com/developmenttools/ProductDetails/AC164160) uses the ATmega4808 in a 32 pin package. *32 pin standard* is the correct pinout for this board. Note that UART2 is connected to the nEDBG chip (often referred to as the debug serial port). This means you'll have to use `Serial2.begin(baud)` to print to the serial monitor. You'll also have to choose **Curiosity Nano** as your programmer to upload code. For more information about this board please refer to the user guide and its schematic. -Click to enlarge: - +Click to enlarge: + + ### ATmega4809 Xplained Pro -[The ATmega4809 Xplained Pro](https://www.microchip.com/developmenttools/ProductDetails/atmega4809-xpro) uses an ATmega4809. Recommended pinout for this board is *48 pin standard*. Note that the UART1 is connected to the EDBG chip (often refered to as the debug serial port). This means you'll have to use `Serial1.begin(baud)` in order to print to the serial monitor. You'll also have to choose **Atmel EDBG (AT32UC3A4256)** as your programmer in order to upload code. For more information about this board please refer to the userguide and its schematic. +[The ATmega4809 Xplained Pro](https://www.microchip.com/developmenttools/ProductDetails/atmega4809-xpro) uses an ATmega4809. The recommended pinout for this board is *48 pin standard*. Note that the UART1 is connected to the EDBG chip (often referred to as the debug serial port). This means you'll have to use `Serial1.begin(baud)` to print to the serial monitor. You'll also have to choose **Xplained Pro** as your programmer to upload code. For more information about this board please refer to the user guide and its schematic. + +Click to enlarge: -Click to enlarge: - + diff --git a/megaavr/avrdude.conf b/megaavr/avrdude.conf deleted file mode 100644 index 1898252..0000000 --- a/megaavr/avrdude.conf +++ /dev/null @@ -1,15880 +0,0 @@ -# $Id$ -*- text -*- -# -# AVRDUDE Configuration File -# -# This file contains configuration data used by AVRDUDE which describes -# the programming hardware pinouts and also provides part definitions. -# AVRDUDE's "-C" command line option specifies the location of the -# configuration file. The "-c" option names the programmer configuration -# which must match one of the entry's "id" parameter. The "-p" option -# identifies which part AVRDUDE is going to be programming and must match -# one of the parts' "id" parameter. -# -# DO NOT MODIFY THIS FILE. Modifications will be overwritten the next -# time a "make install" is run. For user-specific additions, use the -# "-C +filename" commandline option. -# -# Possible entry formats are: -# -# programmer -# parent # optional parent -# id = [, [, ] ...] ; # are quoted strings -# desc = ; # quoted string -# type = ; # programmer type, quoted string -# # supported programmer types can be listed by "-c ?type" -# connection_type = parallel | serial | usb -# baudrate = ; # baudrate for avr910-programmer -# vcc = [, ... ] ; # pin number(s) -# buff = [, ... ] ; # pin number(s) -# reset = ; # pin number -# sck = ; # pin number -# mosi = ; # pin number -# miso = ; # pin number -# errled = ; # pin number -# rdyled = ; # pin number -# pgmled = ; # pin number -# vfyled = ; # pin number -# usbvid = ; # USB VID (Vendor ID) -# usbpid = [, ...] # USB PID (Product ID) (1) -# usbdev = ; # USB interface or other device info -# usbvendor = ; # USB Vendor Name -# usbproduct = ; # USB Product Name -# usbsn = ; # USB Serial Number -# -# To invert a bit, use = ~ , the spaces are important. -# For a pin list all pins must be inverted. -# A single pin can be specified as usual = ~ , for lists -# specify it as follows = ~ ( [, ... ] ) . -# -# (1) Not all programmer types can process a list of PIDs. -# ; -# -# part -# id = ; # quoted string -# desc = ; # quoted string -# has_jtag = ; # part has JTAG i/f -# has_debugwire = ; # part has debugWire i/f -# has_pdi = ; # part has PDI i/f -# has_updi = ; # part has UPDI i/f -# has_tpi = ; # part has TPI i/f -# devicecode = ; # deprecated, use stk500_devcode -# stk500_devcode = ; # numeric -# avr910_devcode = ; # numeric -# signature = ; # signature bytes -# usbpid = ; # DFU USB PID -# chip_erase_delay = ; # micro-seconds -# reset = dedicated | io; -# retry_pulse = reset | sck; -# pgm_enable = ; -# chip_erase = ; -# chip_erase_delay = ; # chip erase delay (us) -# # STK500 parameters (parallel programming IO lines) -# pagel = ; # pin name in hex, i.e., 0xD7 -# bs2 = ; # pin name in hex, i.e., 0xA0 -# serial = ; # can use serial downloading -# parallel = ; # can use par. programming -# # STK500v2 parameters, to be taken from Atmel's XML files -# timeout = ; -# stabdelay = ; -# cmdexedelay = ; -# synchloops = ; -# bytedelay = ; -# pollvalue = ; -# pollindex = ; -# predelay = ; -# postdelay = ; -# pollmethod = ; -# mode = ; -# delay = ; -# blocksize = ; -# readsize = ; -# hvspcmdexedelay = ; -# # STK500v2 HV programming parameters, from XML -# pp_controlstack = , , ...; # PP only -# hvsp_controlstack = , , ...; # HVSP only -# hventerstabdelay = ; -# progmodedelay = ; # PP only -# latchcycles = ; -# togglevtg = ; -# poweroffdelay = ; -# resetdelayms = ; -# resetdelayus = ; -# hvleavestabdelay = ; -# resetdelay = ; -# synchcycles = ; # HVSP only -# chiperasepulsewidth = ; # PP only -# chiperasepolltimeout = ; -# chiperasetime = ; # HVSP only -# programfusepulsewidth = ; # PP only -# programfusepolltimeout = ; -# programlockpulsewidth = ; # PP only -# programlockpolltimeout = ; -# # JTAG ICE mkII parameters, also from XML files -# allowfullpagebitstream = ; -# enablepageprogramming = ; -# idr = ; # IO addr of IDR (OCD) reg. -# rampz = ; # IO addr of RAMPZ reg. -# spmcr = ; # mem addr of SPMC[S]R reg. -# eecr = ; # mem addr of EECR reg. -# # (only when != 0x3c) -# is_at90s1200 = ; # AT90S1200 part -# is_avr32 = ; # AVR32 part -# -# memory -# paged = ; # yes / no -# size = ; # bytes -# page_size = ; # bytes -# num_pages = ; # numeric -# min_write_delay = ; # micro-seconds -# max_write_delay = ; # micro-seconds -# readback_p1 = ; # byte value -# readback_p2 = ; # byte value -# pwroff_after_write = ; # yes / no -# read = ; -# write = ; -# read_lo = ; -# read_hi = ; -# write_lo = ; -# write_hi = ; -# loadpage_lo = ; -# loadpage_hi = ; -# writepage = ; -# ; -# ; -# -# If any of the above parameters are not specified, the default value -# of 0 is used for numerics or the empty string ("") for string -# values. If a required parameter is left empty, AVRDUDE will -# complain. -# -# Parts can also inherit parameters from previously defined parts -# using the following syntax. In this case specified integer and -# string values override parameter values from the parent part. New -# memory definitions are added to the definitions inherited from the -# parent. -# -# part parent # quoted string -# id = ; # quoted string -# -# ; -# -# NOTES: -# * 'devicecode' is the device code used by the STK500 (see codes -# listed below) -# * Not all memory types will implement all instructions. -# * AVR Fuse bits and Lock bits are implemented as a type of memory. -# * Example memory types are: -# "flash", "eeprom", "fuse", "lfuse" (low fuse), "hfuse" (high -# fuse), "signature", "calibration", "lock" -# * The memory type specified on the avrdude command line must match -# one of the memory types defined for the specified chip. -# * The pwroff_after_write flag causes avrdude to attempt to -# power the device off and back on after an unsuccessful write to -# the affected memory area if VCC programmer pins are defined. If -# VCC pins are not defined for the programmer, a message -# indicating that the device needs a power-cycle is printed out. -# This flag was added to work around a problem with the -# at90s4433/2333's; see the at90s4433 errata at: -# -# http://www.atmel.com/dyn/resources/prod_documents/doc1280.pdf -# -# INSTRUCTION FORMATS -# -# Instruction formats are specified as a comma seperated list of -# string values containing information (bit specifiers) about each -# of the 32 bits of the instruction. Bit specifiers may be one of -# the following formats: -# -# '1' = the bit is always set on input as well as output -# -# '0' = the bit is always clear on input as well as output -# -# 'x' = the bit is ignored on input and output -# -# 'a' = the bit is an address bit, the bit-number matches this bit -# specifier's position within the current instruction byte -# -# 'aN' = the bit is the Nth address bit, bit-number = N, i.e., a12 -# is address bit 12 on input, a0 is address bit 0. -# -# 'i' = the bit is an input data bit -# -# 'o' = the bit is an output data bit -# -# Each instruction must be composed of 32 bit specifiers. The -# instruction specification closely follows the instruction data -# provided in Atmel's data sheets for their parts. -# -# See below for some examples. -# -# -# The following are STK500 part device codes to use for the -# "devicecode" field of the part. These came from Atmel's software -# section avr061.zip which accompanies the application note -# AVR061 available from: -# -# http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf -# - -#define ATTINY10 0x10 /* the _old_ one that never existed! */ -#define ATTINY11 0x11 -#define ATTINY12 0x12 -#define ATTINY15 0x13 -#define ATTINY13 0x14 - -#define ATTINY22 0x20 -#define ATTINY26 0x21 -#define ATTINY28 0x22 -#define ATTINY2313 0x23 - -#define AT90S1200 0x33 - -#define AT90S2313 0x40 -#define AT90S2323 0x41 -#define AT90S2333 0x42 -#define AT90S2343 0x43 - -#define AT90S4414 0x50 -#define AT90S4433 0x51 -#define AT90S4434 0x52 -#define ATMEGA48 0x59 - -#define AT90S8515 0x60 -#define AT90S8535 0x61 -#define AT90C8534 0x62 -#define ATMEGA8515 0x63 -#define ATMEGA8535 0x64 - -#define ATMEGA8 0x70 -#define ATMEGA88 0x73 -#define ATMEGA168 0x86 - -#define ATMEGA161 0x80 -#define ATMEGA163 0x81 -#define ATMEGA16 0x82 -#define ATMEGA162 0x83 -#define ATMEGA169 0x84 - -#define ATMEGA323 0x90 -#define ATMEGA32 0x91 - -#define ATMEGA64 0xA0 - -#define ATMEGA103 0xB1 -#define ATMEGA128 0xB2 -#define AT90CAN128 0xB3 -#define AT90CAN64 0xB3 -#define AT90CAN32 0xB3 - -#define AT86RF401 0xD0 - -#define AT89START 0xE0 -#define AT89S51 0xE0 -#define AT89S52 0xE1 - -# The following table lists the devices in the original AVR910 -# appnote: -# |Device |Signature | Code | -# +-------+----------+------+ -# |tiny12 | 1E 90 05 | 0x55 | -# |tiny15 | 1E 90 06 | 0x56 | -# | | | | -# | S1200 | 1E 90 01 | 0x13 | -# | | | | -# | S2313 | 1E 91 01 | 0x20 | -# | S2323 | 1E 91 02 | 0x48 | -# | S2333 | 1E 91 05 | 0x34 | -# | S2343 | 1E 91 03 | 0x4C | -# | | | | -# | S4414 | 1E 92 01 | 0x28 | -# | S4433 | 1E 92 03 | 0x30 | -# | S4434 | 1E 92 02 | 0x6C | -# | | | | -# | S8515 | 1E 93 01 | 0x38 | -# | S8535 | 1E 93 03 | 0x68 | -# | | | | -# |mega32 | 1E 95 01 | 0x72 | -# |mega83 | 1E 93 05 | 0x65 | -# |mega103| 1E 97 01 | 0x41 | -# |mega161| 1E 94 01 | 0x60 | -# |mega163| 1E 94 02 | 0x64 | - -# Appnote AVR109 also has a table of AVR910 device codes, which -# lists: -# dev avr910 signature -# ATmega8 0x77 0x1E 0x93 0x07 -# ATmega8515 0x3B 0x1E 0x93 0x06 -# ATmega8535 0x6A 0x1E 0x93 0x08 -# ATmega16 0x75 0x1E 0x94 0x03 -# ATmega162 0x63 0x1E 0x94 0x04 -# ATmega163 0x66 0x1E 0x94 0x02 -# ATmega169 0x79 0x1E 0x94 0x05 -# ATmega32 0x7F 0x1E 0x95 0x02 -# ATmega323 0x73 0x1E 0x95 0x01 -# ATmega64 0x46 0x1E 0x96 0x02 -# ATmega128 0x44 0x1E 0x97 0x02 -# -# These codes refer to "BOOT" device codes which are apparently -# different than standard device codes, for whatever reasons -# (often one above the standard code). - -# There are several extended versions of AVR910 implementations around -# in the Internet. These add the following codes (only devices that -# actually exist are listed): - -# ATmega8515 0x3A -# ATmega128 0x43 -# ATmega64 0x45 -# ATtiny26 0x5E -# ATmega8535 0x69 -# ATmega32 0x72 -# ATmega16 0x74 -# ATmega8 0x76 -# ATmega169 0x78 - -# -# Overall avrdude defaults; suitable for ~/.avrduderc -# -default_parallel = "unknown"; -default_serial = "unknown"; -# default_bitclock = 2.5; - -# Turn off safemode by default -#default_safemode = no; - - -# -# PROGRAMMER DEFINITIONS -# - -# http://wiring.org.co/ -# Basically STK500v2 protocol, with some glue to trigger the -# bootloader. -programmer - id = "wiring"; - desc = "Wiring"; - type = "wiring"; - connection_type = serial; -; - -programmer - id = "arduino"; - desc = "Arduino"; - type = "arduino"; - connection_type = serial; -; -# this will interface with the chips on these programmers: -# -# http://real.kiev.ua/old/avreal/en/adapters -# http://www.amontec.com/jtagkey.shtml, jtagkey-tiny.shtml -# http://www.olimex.com/dev/arm-usb-ocd.html, arm-usb-tiny.html -# http://www.ethernut.de/en/hardware/turtelizer/index.html -# http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html -# http://dangerousprototypes.com/docs/FT2232_breakout_board -# http://www.ftdichip.com/Products/Modules/DLPModules.htm,DLP-2232*,DLP-USB1232H -# http://flashrom.org/FT2232SPI_Programmer -# -# The drivers will look for a specific device and use the first one found. -# If you have mulitple devices, then look for unique information (like SN) -# And fill that in here. -# -# Note that the pin numbers for the main ISP signals (reset, sck, -# mosi, miso) are fixed and cannot be changed, since they must match -# the way the Multi-Protocol Synchronous Serial Engine (MPSSE) of -# these FTDI ICs has been designed. - -programmer - id = "avrftdi"; - desc = "FT2232D based generic programmer"; - type = "avrftdi"; - connection_type = usb; - usbvid = 0x0403; - usbpid = 0x6010; - usbvendor = ""; - usbproduct = ""; - usbdev = "A"; - usbsn = ""; -#ISP-signals - lower ADBUS-Nibble (default) - reset = 3; - sck = 0; - mosi = 1; - miso = 2; -#LED SIGNALs - higher ADBUS-Nibble -# errled = 4; -# rdyled = 5; -# pgmled = 6; -# vfyled = 7; -#Buffer Signal - ACBUS - Nibble -# buff = 8; -; -# This is an implementation of the above with a buffer IC (74AC244) and -# 4 LEDs directly attached, all active low. -programmer - id = "2232HIO"; - desc = "FT2232H based generic programmer"; - type = "avrftdi"; - connection_type = usb; - usbvid = 0x0403; -# Note: This PID is reserved for generic H devices and -# should be programmed into the EEPROM -# usbpid = 0x8A48; - usbpid = 0x6010; - usbdev = "A"; - usbvendor = ""; - usbproduct = ""; - usbsn = ""; -#ISP-signals - reset = 3; - sck = 0; - mosi = 1; - miso = 2; - buff = ~4; -#LED SIGNALs - errled = ~ 11; - rdyled = ~ 14; - pgmled = ~ 13; - vfyled = ~ 12; -; - -#The FT4232H can be treated as FT2232H, but it has a different USB -#device ID of 0x6011. -programmer parent "avrftdi" - id = "4232h"; - desc = "FT4232H based generic programmer"; - usbpid = 0x6011; -; - -programmer - id = "jtagkey"; - desc = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2"; - type = "avrftdi"; - connection_type = usb; - usbvid = 0x0403; -# Note: This PID is used in all JTAGKey variants - usbpid = 0xCFF8; - usbdev = "A"; - usbvendor = ""; - usbproduct = ""; - usbsn = ""; -#ISP-signals => 20 - Pin connector on JTAGKey - reset = 3; # TMS 7 violet - sck = 0; # TCK 9 white - mosi = 1; # TDI 5 green - miso = 2; # TDO 13 orange - buff = ~4; -# VTG VREF 1 brown with red tip -# GND GND 20 black -# The colors are on the 20 pin breakout cable -# from Amontec -; - -# UM232H module from FTDI and Glyn.com.au. -# See helix.air.net.au for detailed usage information. -# J1: Connect pin 2 and 3 for USB power. -# J2: Connect pin 2 and 3 for USB power. -# J2: Pin 7 is SCK -# : Pin 8 is MOSI -# : Pin 9 is MISO -# : Pin 11 is RST -# : Pin 6 is ground -# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get -# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant. -programmer - id = "UM232H"; - desc = "FT232H based module from FTDI and Glyn.com.au"; - type = "avrftdi"; - usbvid = 0x0403; -# Note: This PID is reserved for generic 232H devices and -# should be programmed into the EEPROM - usbpid = 0x6014; - usbdev = "A"; - usbvendor = ""; - usbproduct = ""; - usbsn = ""; -#ISP-signals - sck = 0; - mosi = 1; - miso = 2; - reset = 3; -; - -# C232HM module from FTDI and Glyn.com.au. -# : Orange is SCK -# : Yellow is MOSI -# : Green is MISO -# : Brown is RST -# : Black is ground -# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get -# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant. -programmer - id = "C232HM"; - desc = "FT232H based module from FTDI and Glyn.com.au"; - type = "avrftdi"; - usbvid = 0x0403; -# Note: This PID is reserved for generic 232H devices and -# should be programmed into the EEPROM - usbpid = 0x6014; - usbdev = "A"; - usbvendor = ""; - usbproduct = ""; - usbsn = ""; -#ISP-signals - sck = 0; - mosi = 1; - miso = 2; - reset = 3; -; - - -# On the adapter you can read "O-Link". On the PCB is printed "OpenJTAG v3.1" -# You can find it as "OpenJTAG ARM JTAG USB" in the internet. -# (But there are also several projects called Open JTAG, eg. -# http://www.openjtag.org, which are completely different.) -# http://www.100ask.net/shop/english.html (website seems to be outdated) -# http://item.taobao.com/item.htm?id=1559277013 -# http://www.micro4you.com/store/openjtag-arm-jtag-usb.html (schematics!) -# some other sources which call it O-Link -# http://www.andahammer.com/olink/ -# http://www.developmentboard.net/31-o-link-debugger.html -# http://armwerks.com/catalog/o-link-debugger-copy/ -# or just have a look at ebay ... -# It is basically the same entry as jtagkey with different usb ids. -programmer parent "jtagkey" - id = "o-link"; - desc = "O-Link, OpenJTAG from www.100ask.net"; - usbvid = 0x1457; - usbpid = 0x5118; - usbvendor = "www.100ask.net"; - usbproduct = "USB<=>JTAG&RS232"; -; - -# http://wiki.openmoko.org/wiki/Debug_Board_v3 -programmer - id = "openmoko"; - desc = "Openmoko debug board (v3)"; - type = "avrftdi"; - usbvid = 0x1457; - usbpid = 0x5118; - usbdev = "A"; - usbvendor = ""; - usbproduct = ""; - usbsn = ""; - reset = 3; # TMS 7 - sck = 0; # TCK 9 - mosi = 1; # TDI 5 - miso = 2; # TDO 13 -; - -# Only Rev. A boards. -# Schematic and user manual: http://www.cs.put.poznan.pl/wswitala/download/pdf/811EVBK.pdf -programmer - id = "lm3s811"; - desc = "Luminary Micro LM3S811 Eval Board (Rev. A)"; - type = "avrftdi"; - connection_type = usb; - usbvid = 0x0403; - usbpid = 0xbcd9; - usbvendor = "LMI"; - usbproduct = "LM3S811 Evaluation Board"; - usbdev = "A"; - usbsn = ""; -#ISP-signals - lower ACBUS-Nibble (default) - reset = 3; - sck = 0; - mosi = 1; - miso = 2; -# Enable correct buffers - buff = 7; -; - -# submitted as bug #46020 -programmer - id = "tumpa"; - desc = "TIAO USB Multi-Protocol Adapter"; - type = "avrftdi"; - connection_type = usb; - usbvid = 0x0403; - usbpid = 0x8A98; - usbdev = "A"; - usbvendor = "TIAO"; - usbproduct = ""; - usbsn = ""; - sck = 0; # TCK 9 - mosi = 1; # TDI 5 - miso = 2; # TDO 13 - reset = 3; # TMS 7 -; - -programmer - id = "avrisp"; - desc = "Atmel AVR ISP"; - type = "stk500"; - connection_type = serial; -; - -programmer - id = "avrispv2"; - desc = "Atmel AVR ISP V2"; - type = "stk500v2"; - connection_type = serial; -; - -programmer - id = "avrispmkII"; - desc = "Atmel AVR ISP mkII"; - type = "stk500v2"; - connection_type = usb; -; - -programmer parent "avrispmkII" - id = "avrisp2"; -; - -programmer - id = "buspirate"; - desc = "The Bus Pirate"; - type = "buspirate"; - connection_type = serial; -; - -programmer - id = "buspirate_bb"; - desc = "The Bus Pirate (bitbang interface, supports TPI)"; - type = "buspirate_bb"; - connection_type = serial; - # pins are bits in bitbang byte (numbers are 87654321) - # 1|POWER|PULLUP|AUX|MOSI|CLK|MISO|CS - reset = 1; - sck = 3; - mosi = 4; - miso = 2; - #vcc = 7; This is internally set independent of this setting. -; - -# This is supposed to be the "default" STK500 entry. -# Attempts to select the correct firmware version -# by probing for it. Better use one of the entries -# below instead. -programmer - id = "stk500"; - desc = "Atmel STK500"; - type = "stk500generic"; - connection_type = serial; -; - -programmer - id = "stk500v1"; - desc = "Atmel STK500 Version 1.x firmware"; - type = "stk500"; - connection_type = serial; -; - -programmer - id = "mib510"; - desc = "Crossbow MIB510 programming board"; - type = "stk500"; - connection_type = serial; -; - -programmer - id = "stk500v2"; - desc = "Atmel STK500 Version 2.x firmware"; - type = "stk500v2"; - connection_type = serial; -; - -programmer - id = "stk500pp"; - desc = "Atmel STK500 V2 in parallel programming mode"; - type = "stk500pp"; - connection_type = serial; -; - -programmer - id = "stk500hvsp"; - desc = "Atmel STK500 V2 in high-voltage serial programming mode"; - type = "stk500hvsp"; - connection_type = serial; -; - -programmer - id = "stk600"; - desc = "Atmel STK600"; - type = "stk600"; - connection_type = usb; -; - -programmer - id = "stk600pp"; - desc = "Atmel STK600 in parallel programming mode"; - type = "stk600pp"; - connection_type = usb; -; - -programmer - id = "stk600hvsp"; - desc = "Atmel STK600 in high-voltage serial programming mode"; - type = "stk600hvsp"; - connection_type = usb; -; - -programmer - id = "avr910"; - desc = "Atmel Low Cost Serial Programmer"; - type = "avr910"; - connection_type = serial; -; - -programmer - id = "ft245r"; - desc = "FT245R Synchronous BitBang"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 1; # D1 - sck = 0; # D0 - mosi = 2; # D2 - reset = 4; # D4 -; - -programmer - id = "ft232r"; - desc = "FT232R Synchronous BitBang"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 1; # RxD - sck = 0; # TxD - mosi = 2; # RTS - reset = 4; # DTR -; - -# see http://www.bitwizard.nl/wiki/index.php/FTDI_ATmega -programmer - id = "bwmega"; - desc = "BitWizard ftdi_atmega builtin programmer"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 5; # DSR - sck = 6; # DCD - mosi = 3; # CTS - reset = 7; # RI -; - -# see http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html -# Note: pins are numbered from 1! -programmer - id = "arduino-ft232r"; - desc = "Arduino: FT232R connected to ISP"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 3; # CTS X3(1) - sck = 5; # DSR X3(2) - mosi = 6; # DCD X3(3) - reset = 7; # RI X3(4) -; - -# website mentioned above uses this id -programmer parent "arduino-ft232r" - id = "diecimila"; - desc = "alias for arduino-ft232r"; -; - -# There is a ATmega328P kit PCB called "uncompatino". -# This board allows ISP via its on-board FT232R. -# This is designed like Arduino Duemilanove but has no standard ICPS header. -# Its 4 pairs of pins are shorted to enable ftdi_syncbb. -# http://akizukidenshi.com/catalog/g/gP-07487/ -# http://akizukidenshi.com/download/ds/akizuki/k6096_manual_20130816.pdf -programmer - id = "uncompatino"; - desc = "uncompatino with all pairs of pins shorted"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 3; # cts - sck = 5; # dsr - mosi = 6; # dcd - reset = 7; # ri -; - -# FTDI USB to serial cable TTL-232R-5V with a custom adapter for ICSP -# http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm -# http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf -# For ICSP pinout see for example http://www.atmel.com/images/doc2562.pdf -# (Figure 1. ISP6PIN header pinout and Table 1. Connections required for ISP ...) -# TTL-232R GND 1 Black -> ICPS GND (pin 6) -# TTL-232R CTS 2 Brown -> ICPS MOSI (pin 4) -# TTL-232R VCC 3 Red -> ICPS VCC (pin 2) -# TTL-232R TXD 4 Orange -> ICPS RESET (pin 5) -# TTL-232R RXD 5 Yellow -> ICPS SCK (pin 3) -# TTL-232R RTS 6 Green -> ICPS MISO (pin 1) -# Except for VCC and GND, you can connect arbitual pairs as long as -# the following table is adjusted. -programmer - id = "ttl232r"; - desc = "FTDI TTL232R-5V with ICSP adapter"; - type = "ftdi_syncbb"; - connection_type = usb; - miso = 2; # rts - sck = 1; # rxd - mosi = 3; # cts - reset = 0; # txd -; - -programmer - id = "usbasp"; - desc = "USBasp, http://www.fischl.de/usbasp/"; - type = "usbasp"; - connection_type = usb; - usbvid = 0x16C0; # VOTI - usbpid = 0x05DC; # Obdev's free shared PID - usbvendor = "www.fischl.de"; - usbproduct = "USBasp"; - - # following variants are autodetected for id "usbasp" - - # original usbasp from fischl.de - # see above "usbasp" - - # old usbasp from fischl.de - #usbvid = 0x03EB; # ATMEL - #usbpid = 0xC7B4; # (unoffical) USBasp - #usbvendor = "www.fischl.de"; - #usbproduct = "USBasp"; - - # NIBObee (only if -P nibobee is given on command line) - # see below "nibobee" -; - -programmer - id = "nibobee"; - desc = "NIBObee"; - type = "usbasp"; - connection_type = usb; - usbvid = 0x16C0; # VOTI - usbpid = 0x092F; # NIBObee PID - usbvendor = "www.nicai-systems.com"; - usbproduct = "NIBObee"; -; - -programmer - id = "usbasp-clone"; - desc = "Any usbasp clone with correct VID/PID"; - type = "usbasp"; - connection_type = usb; - usbvid = 0x16C0; # VOTI - usbpid = 0x05DC; # Obdev's free shared PID - #usbvendor = ""; - #usbproduct = ""; -; - -# USBtiny can also be used for TPI programming. -# In that case, a resistor of 1 kOhm is needed between MISO and MOSI -# pins of the connector, and MISO (pin 1 of the 6-pin connector) -# connects to TPIDATA. -programmer - id = "usbtiny"; - desc = "USBtiny simple USB programmer, https://learn.adafruit.com/usbtinyisp"; - type = "usbtiny"; - connection_type = usb; - usbvid = 0x1781; - usbpid = 0x0c9f; -; - -# commercial version of USBtiny, using a separate VID/PID -programmer - id = "ehajo-isp"; - desc = "avr-isp-programmer from eHaJo, http://www.eHaJo.de"; - type = "usbtiny"; - connection_type = usb; - usbvid = 0x16D0; - usbpid = 0x0BA5; -; - -programmer - id = "arduinoisp"; - desc = "Arduino ISP Programmer"; - type = "usbtiny"; - connection_type = usb; - usbvid = 0x2341; - usbpid = 0x0049; -; - -programmer - id = "arduinoisporg"; - desc = "Arduino ISP Programmer"; - type = "usbtiny"; - connection_type = usb; - usbvid = 0x2A03; - usbpid = 0x0049; -; - -programmer - id = "butterfly"; - desc = "Atmel Butterfly Development Board"; - type = "butterfly"; - connection_type = serial; -; - -programmer - id = "avr109"; - desc = "Atmel AppNote AVR109 Boot Loader"; - type = "butterfly"; - connection_type = serial; -; - -programmer - id = "avr911"; - desc = "Atmel AppNote AVR911 AVROSP"; - type = "butterfly"; - connection_type = serial; -; - -# suggested in http://forum.mikrokopter.de/topic-post48317.html -programmer - id = "mkbutterfly"; - desc = "Mikrokopter.de Butterfly"; - type = "butterfly_mk"; - connection_type = serial; -; - -programmer parent "mkbutterfly" - id = "butterfly_mk"; -; - -programmer - id = "jtagmkI"; - desc = "Atmel JTAG ICE (mkI)"; - baudrate = 115200; # default is 115200 - type = "jtagmki"; - connection_type = serial; -; - -# easier to type -programmer parent "jtagmkI" - id = "jtag1"; -; - -# easier to type -programmer parent "jtag1" - id = "jtag1slow"; - baudrate = 19200; -; - -# The JTAG ICE mkII has both, serial and USB connectivity. As it is -# mostly used through USB these days (AVR Studio 5 only supporting it -# that way), we make connection_type = usb the default. Users are -# still free to use a serial port with the -P option. - -programmer - id = "jtagmkII"; - desc = "Atmel JTAG ICE mkII"; - baudrate = 19200; # default is 19200 - type = "jtagmkii"; - connection_type = usb; -; - -# easier to type -programmer parent "jtagmkII" - id = "jtag2slow"; -; - -# JTAG ICE mkII @ 115200 Bd -programmer parent "jtag2slow" - id = "jtag2fast"; - baudrate = 115200; -; - -# make the fast one the default, people will love that -programmer parent "jtag2fast" - id = "jtag2"; -; - -# JTAG ICE mkII in ISP mode -programmer - id = "jtag2isp"; - desc = "Atmel JTAG ICE mkII in ISP mode"; - baudrate = 115200; - type = "jtagmkii_isp"; - connection_type = usb; -; - -# JTAG ICE mkII in debugWire mode -programmer - id = "jtag2dw"; - desc = "Atmel JTAG ICE mkII in debugWire mode"; - baudrate = 115200; - type = "jtagmkii_dw"; - connection_type = usb; -; - -# JTAG ICE mkII in AVR32 mode -programmer - id = "jtagmkII_avr32"; - desc = "Atmel JTAG ICE mkII im AVR32 mode"; - baudrate = 115200; - type = "jtagmkii_avr32"; - connection_type = usb; -; - -# JTAG ICE mkII in AVR32 mode -programmer - id = "jtag2avr32"; - desc = "Atmel JTAG ICE mkII im AVR32 mode"; - baudrate = 115200; - type = "jtagmkii_avr32"; - connection_type = usb; -; - -# JTAG ICE mkII in PDI mode -programmer - id = "jtag2pdi"; - desc = "Atmel JTAG ICE mkII PDI mode"; - baudrate = 115200; - type = "jtagmkii_pdi"; - connection_type = usb; -; - -# AVR Dragon in JTAG mode -programmer - id = "dragon_jtag"; - desc = "Atmel AVR Dragon in JTAG mode"; - baudrate = 115200; - type = "dragon_jtag"; - connection_type = usb; -; - -# AVR Dragon in ISP mode -programmer - id = "dragon_isp"; - desc = "Atmel AVR Dragon in ISP mode"; - baudrate = 115200; - type = "dragon_isp"; - connection_type = usb; -; - -# AVR Dragon in PP mode -programmer - id = "dragon_pp"; - desc = "Atmel AVR Dragon in PP mode"; - baudrate = 115200; - type = "dragon_pp"; - connection_type = usb; -; - -# AVR Dragon in HVSP mode -programmer - id = "dragon_hvsp"; - desc = "Atmel AVR Dragon in HVSP mode"; - baudrate = 115200; - type = "dragon_hvsp"; - connection_type = usb; -; - -# AVR Dragon in debugWire mode -programmer - id = "dragon_dw"; - desc = "Atmel AVR Dragon in debugWire mode"; - baudrate = 115200; - type = "dragon_dw"; - connection_type = usb; -; - -# AVR Dragon in PDI mode -programmer - id = "dragon_pdi"; - desc = "Atmel AVR Dragon in PDI mode"; - baudrate = 115200; - type = "dragon_pdi"; - connection_type = usb; -; - -programmer - id = "jtag3"; - desc = "Atmel AVR JTAGICE3 in JTAG mode"; - type = "jtagice3"; - connection_type = usb; - usbpid = 0x2110, 0x2140; -; - -programmer - id = "jtag3pdi"; - desc = "Atmel AVR JTAGICE3 in PDI mode"; - type = "jtagice3_pdi"; - connection_type = usb; - usbpid = 0x2110, 0x2140; -; - -programmer - id = "jtag3dw"; - desc = "Atmel AVR JTAGICE3 in debugWIRE mode"; - type = "jtagice3_dw"; - connection_type = usb; - usbpid = 0x2110, 0x2140; -; - -programmer - id = "jtag3isp"; - desc = "Atmel AVR JTAGICE3 in ISP mode"; - type = "jtagice3_isp"; - connection_type = usb; - usbpid = 0x2110, 0x2140; -; - -programmer - id = "xplainedpro"; - desc = "Atmel AVR XplainedPro in JTAG mode"; - type = "jtagice3"; - connection_type = usb; - usbpid = 0x2111; -; - -programmer - id = "xplainedpro_updi"; - desc = "Atmel AVR XplainedPro in UPDI mode"; - type = "jtagice3_updi"; - connection_type = usb; - usbpid = 0x2111; -; - -programmer - id = "xplainedmini"; - desc = "Atmel AVR XplainedMini in ISP mode"; - type = "jtagice3_isp"; - connection_type = usb; - usbpid = 0x2145; -; - -programmer - id = "xplainedmini_dw"; - desc = "Atmel AVR XplainedMini in debugWIRE mode"; - type = "jtagice3_dw"; - connection_type = usb; - usbpid = 0x2145; -; - -programmer - id = "xplainedmini_updi"; - desc = "Atmel AVR XplainedMini in UPDI mode"; - type = "jtagice3_updi"; - connection_type = usb; - usbpid = 0x2145; -; - -programmer - id = "curiosity_updi"; - desc = "Curiosity in UPDI mode"; - type = "jtagice3_updi"; - connection_type = usb; - usbpid = 0x2175; -; - -programmer - id = "atmelice"; - desc = "Atmel-ICE (ARM/AVR) in JTAG mode"; - type = "jtagice3"; - connection_type = usb; - usbpid = 0x2141; -; - -programmer - id = "atmelice_pdi"; - desc = "Atmel-ICE (ARM/AVR) in PDI mode"; - type = "jtagice3_pdi"; - connection_type = usb; - usbpid = 0x2141; -; - -programmer - id = "atmelice_updi"; - desc = "Atmel-ICE (ARM/AVR) in UPDI mode"; - type = "jtagice3_updi"; - connection_type = usb; - usbpid = 0x2141; -; - -programmer - id = "atmelice_dw"; - desc = "Atmel-ICE (ARM/AVR) in debugWIRE mode"; - type = "jtagice3_dw"; - connection_type = usb; - usbpid = 0x2141; -; - -programmer - id = "atmelice_isp"; - desc = "Atmel-ICE (ARM/AVR) in ISP mode"; - type = "jtagice3_isp"; - connection_type = usb; - usbpid = 0x2141; -; - -programmer - id = "powerdebugger"; - desc = "Atmel PowerDebugger (ARM/AVR) in JTAG mode"; - type = "jtagice3"; - connection_type = usb; - usbpid = 0x2144; -; - -programmer - id = "powerdebugger_pdi"; - desc = "Atmel PowerDebugger (ARM/AVR) in PDI mode"; - type = "jtagice3_pdi"; - connection_type = usb; - usbpid = 0x2144; -; - -programmer - id = "powerdebugger_updi"; - desc = "Atmel PowerDebugger (ARM/AVR) in UPDI mode"; - type = "jtagice3_updi"; - connection_type = usb; - usbpid = 0x2144; -; - -programmer - id = "powerdebugger_dw"; - desc = "Atmel PowerDebugger (ARM/AVR) in debugWire mode"; - type = "jtagice3_dw"; - connection_type = usb; - usbpid = 0x2144; -; - -programmer - id = "powerdebugger_isp"; - desc = "Atmel PowerDebugger (ARM/AVR) in ISP mode"; - type = "jtagice3_isp"; - connection_type = usb; - usbpid = 0x2144; -; - -programmer - id = "pavr"; - desc = "Jason Kyle's pAVR Serial Programmer"; - type = "avr910"; - connection_type = serial; -; - -programmer - id = "pickit2"; - desc = "MicroChip's PICkit2 Programmer"; - type = "pickit2"; - connection_type = usb; -; - -programmer - id = "flip1"; - desc = "FLIP USB DFU protocol version 1 (doc7618)"; - type = "flip1"; - connection_type = usb; -; - -programmer - id = "flip2"; - desc = "FLIP USB DFU protocol version 2 (AVR4023)"; - type = "flip2"; - connection_type = usb; -; - - -#This programmer bitbangs GPIO lines using the Linux sysfs GPIO interface -# -#To enable it set the configuration below to match the GPIO lines connected to the -#relevant ISP header pins and uncomment the entry definition. In case you don't -#have the required permissions to edit this system wide config file put the -#entry in a separate .conf file and use it with -C+.conf -#on the command line. -# -#To check if your avrdude build has support for the linuxgpio programmer compiled in, -#use -c?type on the command line and look for linuxgpio in the list. If it's not available -#you need pass the --enable-linuxgpio=yes option to configure and recompile avrdude. -# -#programmer -# id = "linuxgpio"; -# desc = "Use the Linux sysfs interface to bitbang GPIO lines"; -# type = "linuxgpio"; -# reset = ?; -# sck = ?; -# mosi = ?; -# miso = ?; -#; - - -#This programmer uses the built in linux SPI bus devices to program an -#attached AVR. A GPIO accessed through the sysfs GPIO interface needs to -#be specified for a reset pin since the linux SPI userspace functions do -#not allow for control over the slave select/chip select signal. -# -programmer - id = "linuxspi"; - desc = "Use Linux SPI device in /dev/spidev*"; - type = "linuxspi"; - reset = 25; -; - -# some ultra cheap programmers use bitbanging on the -# serialport. -# -# PC - DB9 - Pins for RS232: -# -# GND 5 -- |O -# | O| <- 9 RI -# DTR 4 <- |O | -# | O| <- 8 CTS -# TXD 3 <- |O | -# | O| -> 7 RTS -# RXD 2 -> |O | -# | O| <- 6 DSR -# DCD 1 -> |O -# -# Using RXD is currently not supported. -# Using RI is not supported under Win32 but is supported under Posix. - -# serial ponyprog design (dasa2 in uisp) -# reset=!txd sck=rts mosi=dtr miso=cts - -programmer - id = "ponyser"; - desc = "design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts"; - type = "serbb"; - connection_type = serial; - reset = ~3; - sck = 7; - mosi = 4; - miso = 8; -; - -# Same as above, different name -# reset=!txd sck=rts mosi=dtr miso=cts - -programmer parent "ponyser" - id = "siprog"; - desc = "Lancos SI-Prog "; -; - -# unknown (dasa in uisp) -# reset=rts sck=dtr mosi=txd miso=cts - -programmer - id = "dasa"; - desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts"; - type = "serbb"; - connection_type = serial; - reset = 7; - sck = 4; - mosi = 3; - miso = 8; -; - -# unknown (dasa3 in uisp) -# reset=!dtr sck=rts mosi=txd miso=cts - -programmer - id = "dasa3"; - desc = "serial port banging, reset=!dtr sck=rts mosi=txd miso=cts"; - type = "serbb"; - connection_type = serial; - reset = ~4; - sck = 7; - mosi = 3; - miso = 8; -; - -# C2N232i (jumper configuration "auto") -# reset=dtr sck=!rts mosi=!txd miso=!cts - -programmer - id = "c2n232i"; - desc = "serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts"; - type = "serbb"; - connection_type = serial; - reset = 4; - sck = ~7; - mosi = ~3; - miso = ~8; -; - -# -# PART DEFINITIONS -# - -#------------------------------------------------------------ -# ATtiny11 -#------------------------------------------------------------ - -# This is an HVSP-only device. - -part - id = "t11"; - desc = "ATtiny11"; - stk500_devcode = 0x11; - signature = 0x1e 0x90 0x04; - chip_erase_delay = 20000; - - timeout = 200; - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, - 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, - 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 50; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - memory "eeprom" - size = 64; - blocksize = 64; - readsize = 256; - delay = 5; - ; - - memory "flash" - size = 1024; - blocksize = 128; - readsize = 256; - delay = 3; - ; - - memory "signature" - size = 3; - ; - - memory "lock" - size = 1; - ; - - memory "calibration" - size = 1; - ; - - memory "fuse" - size = 1; - ; -; - -#------------------------------------------------------------ -# ATtiny12 -#------------------------------------------------------------ - -part - id = "t12"; - desc = "ATtiny12"; - stk500_devcode = 0x12; - avr910_devcode = 0x55; - signature = 0x1e 0x90 0x05; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, - 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, - 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 50; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - memory "eeprom" - size = 64; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 8; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - size = 1024; - min_write_delay = 4500; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 5; - blocksize = 128; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "fuse" - size = 1; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; -; - -#------------------------------------------------------------ -# ATtiny13 -#------------------------------------------------------------ - -part - id = "t13"; - desc = "ATtiny13"; - has_debugwire = yes; - flash_instr = 0xB4, 0x0E, 0x1E; - eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; - stk500_devcode = 0x14; - signature = 0x1e 0x90 0x07; - chip_erase_delay = 4000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 90; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 0; - - memory "eeprom" - size = 64; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 5; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 1024; - page_size = 32; - num_pages = 32; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 0 0 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 0 0 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 0 0 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 2; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - ; - -; - - -#------------------------------------------------------------ -# ATtiny15 -#------------------------------------------------------------ - -part - id = "t15"; - desc = "ATtiny15"; - stk500_devcode = 0x13; - avr910_devcode = 0x56; - signature = 0x1e 0x90 0x06; - chip_erase_delay = 8200; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, - 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, - 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - hvspcmdexedelay = 5; - synchcycles = 6; - latchcycles = 16; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 50; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - memory "eeprom" - size = 64; - min_write_delay = 8200; - max_write_delay = 8200; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 10; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - size = 1024; - min_write_delay = 4100; - max_write_delay = 4100; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 5; - blocksize = 128; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "fuse" - size = 1; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x o o o o x x o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", - "x x x x x x x x i i i i 1 1 i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; -; - -#------------------------------------------------------------ -# AT90s1200 -#------------------------------------------------------------ - -part - id = "1200"; - desc = "AT90S1200"; - is_at90s1200 = yes; - stk500_devcode = 0x33; - avr910_devcode = 0x13; - signature = 0x1e 0x90 0x01; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 1; - bytedelay = 0; - pollindex = 0; - pollvalue = 0xFF; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 64; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 20; - blocksize = 32; - readsize = 256; - ; - memory "flash" - size = 1024; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x02; - delay = 15; - blocksize = 128; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - ; - memory "lock" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - ; - ; - -#------------------------------------------------------------ -# AT90s4414 -#------------------------------------------------------------ - -part - id = "4414"; - desc = "AT90S4414"; - stk500_devcode = 0x50; - avr910_devcode = 0x28; - signature = 0x1e 0x92 0x01; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 256; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x80; - readback_p2 = 0x7f; - read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - memory "flash" - size = 4096; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x7f; - readback_p2 = 0x7f; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - ; - -#------------------------------------------------------------ -# AT90s2313 -#------------------------------------------------------------ - -part - id = "2313"; - desc = "AT90S2313"; - stk500_devcode = 0x40; - avr910_devcode = 0x20; - signature = 0x1e 0x91 0x01; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 128; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x80; - readback_p2 = 0x7f; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - memory "flash" - size = 2048; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x7f; - readback_p2 = 0x7f; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x i i x", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - ; - -#------------------------------------------------------------ -# AT90s2333 -#------------------------------------------------------------ - -part - id = "2333"; -##### WARNING: No XML file for device 'AT90S2333'! ##### - desc = "AT90S2333"; - stk500_devcode = 0x42; - avr910_devcode = 0x34; - signature = 0x1e 0x91 0x05; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 128; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - size = 2048; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - pwroff_after_write = yes; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", - "x x x x x x x x x x x x x x x x"; - ; - memory "lock" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - ; - ; - - -#------------------------------------------------------------ -# AT90s2343 (also AT90s2323 and ATtiny22) -#------------------------------------------------------------ - -part - id = "2343"; - desc = "AT90S2343"; - stk500_devcode = 0x43; - avr910_devcode = 0x4c; - signature = 0x1e 0x91 0x03; - chip_erase_delay = 18000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, - 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, - 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 0; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 50; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - memory "eeprom" - size = 128; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - memory "flash" - size = 2048; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 128; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x o o o x x x x o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", - "x x x x x x x x x x x x x x x x"; - ; - memory "lock" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x o o o x x x x o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - ; - ; - - -#------------------------------------------------------------ -# AT90s4433 -#------------------------------------------------------------ - -part - id = "4433"; - desc = "AT90S4433"; - stk500_devcode = 0x51; - avr910_devcode = 0x30; - signature = 0x1e 0x92 0x03; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 256; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "flash" - size = 4096; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - pwroff_after_write = yes; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", - "x x x x x x x x x x x x x x x x"; - ; - memory "lock" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - ; - ; - -#------------------------------------------------------------ -# AT90s4434 -#------------------------------------------------------------ - -part - id = "4434"; -##### WARNING: No XML file for device 'AT90S4434'! ##### - desc = "AT90S4434"; - stk500_devcode = 0x52; - avr910_devcode = 0x6c; - signature = 0x1e 0x92 0x02; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - memory "eeprom" - size = 256; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - ; - memory "flash" - size = 4096; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", - "x x x x x x x x x x x x x x x x"; - ; - memory "lock" - size = 1; - min_write_delay = 9000; - max_write_delay = 20000; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - ; - ; - -#------------------------------------------------------------ -# AT90s8515 -#------------------------------------------------------------ - -part - id = "8515"; - desc = "AT90S8515"; - stk500_devcode = 0x60; - avr910_devcode = 0x38; - signature = 0x1e 0x93 0x01; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 512; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x80; - readback_p2 = 0x7f; - read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "flash" - size = 8192; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x7f; - readback_p2 = 0x7f; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - ; - -#------------------------------------------------------------ -# AT90s8535 -#------------------------------------------------------------ - -part - id = "8535"; - desc = "AT90S8535"; - stk500_devcode = 0x61; - avr910_devcode = 0x68; - signature = 0x1e 0x93 0x03; - chip_erase_delay = 20000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 1; - - memory "eeprom" - size = 512; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0x00; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "flash" - size = 8192; - min_write_delay = 9000; - max_write_delay = 20000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write_lo = " 0 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - write_hi = " 0 1 0 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 128; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "fuse" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x x x o"; - write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x o o x x x x x x"; - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - ; - -#------------------------------------------------------------ -# ATmega103 -#------------------------------------------------------------ - -part - id = "m103"; - desc = "ATmega103"; - stk500_devcode = 0xB1; - avr910_devcode = 0x41; - signature = 0x1e 0x97 0x01; - chip_erase_delay = 112000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x8E, 0x9E, 0x2E, 0x3E, 0xAE, 0xBE, - 0x4E, 0x5E, 0xCE, 0xDE, 0x6E, 0x7E, 0xEE, 0xDE, - 0x66, 0x76, 0xE6, 0xF6, 0x6A, 0x7A, 0xEA, 0x7A, - 0x7F, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 15; - chiperasepolltimeout = 0; - programfusepulsewidth = 2; - programfusepolltimeout = 0; - programlockpulsewidth = 0; - programlockpolltimeout = 10; - - memory "eeprom" - size = 4096; - min_write_delay = 4000; - max_write_delay = 9000; - readback_p1 = 0x80; - readback_p2 = 0x7f; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 22000; - max_write_delay = 56000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x11; - delay = 70; - blocksize = 256; - readsize = 256; - ; - - memory "fuse" - size = 1; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x x x o x o 1 o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 1 i 1 i i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x o o x"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATmega64 -#------------------------------------------------------------ - -part - id = "m64"; - desc = "ATmega64"; - has_jtag = yes; - stk500_devcode = 0xA0; - avr910_devcode = 0x45; - signature = 0x1e 0x96 0x02; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x22; - spmcr = 0x68; - allowfullpagebitstream = yes; - - ocdrev = 2; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 20; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - - - -#------------------------------------------------------------ -# ATmega128 -#------------------------------------------------------------ - -part - id = "m128"; - desc = "ATmega128"; - has_jtag = yes; - stk500_devcode = 0xB2; - avr910_devcode = 0x43; - signature = 0x1e 0x97 0x02; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x22; - spmcr = 0x68; - rampz = 0x3b; - allowfullpagebitstream = yes; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 12; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90CAN128 -#------------------------------------------------------------ - -part - id = "c128"; - desc = "AT90CAN128"; - has_jtag = yes; - stk500_devcode = 0xB3; -# avr910_devcode = 0x43; - signature = 0x1e 0x97 0x81; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - eecr = 0x3f; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - - mode = 0x41; - delay = 20; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90CAN64 -#------------------------------------------------------------ - -part - id = "c64"; - desc = "AT90CAN64"; - has_jtag = yes; - stk500_devcode = 0xB3; -# avr910_devcode = 0x43; - signature = 0x1e 0x96 0x81; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - eecr = 0x3f; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - - mode = 0x41; - delay = 20; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90CAN32 -#------------------------------------------------------------ - -part - id = "c32"; - desc = "AT90CAN32"; - has_jtag = yes; - stk500_devcode = 0xB3; -# avr910_devcode = 0x43; - signature = 0x1e 0x95 0x81; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - eecr = 0x3f; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - - mode = 0x41; - delay = 20; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 256; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATmega16 -#------------------------------------------------------------ - -part - id = "m16"; - desc = "ATmega16"; - has_jtag = yes; - stk500_devcode = 0x82; - avr910_devcode = 0x74; - signature = 0x1e 0x94 0x03; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 100; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = yes; - - ocdrev = 2; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x04; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "calibration" - size = 4; - - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATmega164P -#------------------------------------------------------------ - -# close to ATmega16 - -part parent "m16" - id = "m164p"; - desc = "ATmega164P"; - signature = 0x1e 0x94 0x0a; - - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - allowfullpagebitstream = no; - chip_erase_delay = 55000; - - ocdrev = 3; - ; - - -#------------------------------------------------------------ -# ATmega324P -#------------------------------------------------------------ - -# similar to ATmega164P - -part - id = "m324p"; - desc = "ATmega324P"; - has_jtag = yes; - stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one - avr910_devcode = 0x74; - signature = 0x1e 0x95 0x08; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 55000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATmega324PA -#------------------------------------------------------------ - -# similar to ATmega324P - -part parent "m324p" - id = "m324pa"; - desc = "ATmega324PA"; - signature = 0x1e 0x95 0x11; - - ocdrev = 3; - ; - - -#------------------------------------------------------------ -# ATmega644 -#------------------------------------------------------------ - -# similar to ATmega164 - -part - id = "m644"; - desc = "ATmega644"; - has_jtag = yes; - stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one - avr910_devcode = 0x74; - signature = 0x1e 0x96 0x09; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 55000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega644P -#------------------------------------------------------------ - -# similar to ATmega164p - -part parent "m644" - id = "m644p"; - desc = "ATmega644P"; - signature = 0x1e 0x96 0x0a; - - ocdrev = 3; - ; - - - -#------------------------------------------------------------ -# ATmega1284 -#------------------------------------------------------------ - -# similar to ATmega164 - -part - id = "m1284"; - desc = "ATmega1284"; - has_jtag = yes; - stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one - avr910_devcode = 0x74; - signature = 0x1e 0x97 0x06; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 55000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 256; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - - - -#------------------------------------------------------------ -# ATmega1284P -#------------------------------------------------------------ - -# similar to ATmega164p - -part - id = "m1284p"; - desc = "ATmega1284P"; - has_jtag = yes; - stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one - avr910_devcode = 0x74; - signature = 0x1e 0x97 0x05; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 55000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 256; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - - - -#------------------------------------------------------------ -# ATmega162 -#------------------------------------------------------------ - -part - id = "m162"; - desc = "ATmega162"; - has_jtag = yes; - stk500_devcode = 0x83; - avr910_devcode = 0x63; - signature = 0x1e 0x94 0x04; - chip_erase_delay = 9000; - pagel = 0xd7; - bs2 = 0xa0; - - idr = 0x04; - spmcr = 0x57; - allowfullpagebitstream = yes; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - ocdrev = 2; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - - ; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 16000; - max_write_delay = 16000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 16000; - max_write_delay = 16000; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 16000; - max_write_delay = 16000; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 16000; - max_write_delay = 16000; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - - read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; -; - - - -#------------------------------------------------------------ -# ATmega163 -#------------------------------------------------------------ - -part - id = "m163"; - desc = "ATmega163"; - stk500_devcode = 0x81; - avr910_devcode = 0x64; - signature = 0x1e 0x94 0x02; - chip_erase_delay = 32000; - pagel = 0xd7; - bs2 = 0xa0; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 30; - programfusepulsewidth = 0; - programfusepolltimeout = 2; - programlockpulsewidth = 0; - programlockpolltimeout = 2; - - - memory "eeprom" - size = 512; - min_write_delay = 4000; - max_write_delay = 4000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 16000; - max_write_delay = 16000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x11; - delay = 20; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o x x o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i 1 1 i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x x x x x 1 o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x 1 1 1 1 1 i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x 0 x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega169 -#------------------------------------------------------------ - -part - id = "m169"; - desc = "ATmega169"; - has_jtag = yes; - stk500_devcode = 0x85; - avr910_devcode = 0x78; - signature = 0x1e 0x94 0x05; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - - ocdrev = 2; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega329 -#------------------------------------------------------------ - -part - id = "m329"; - desc = "ATmega329"; - has_jtag = yes; -# stk500_devcode = 0x85; # no STK500 support, only STK500v2 -# avr910_devcode = 0x?; # try the ATmega169 one: - avr910_devcode = 0x75; - signature = 0x1e 0x95 0x03; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega329P -#------------------------------------------------------------ -# Identical to ATmega329 except of the signature - -part parent "m329" - id = "m329p"; - desc = "ATmega329P"; - signature = 0x1e 0x95 0x0b; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega3290 -#------------------------------------------------------------ - -# identical to ATmega329 - -part parent "m329" - id = "m3290"; - desc = "ATmega3290"; - signature = 0x1e 0x95 0x04; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega3290P -#------------------------------------------------------------ - -# identical to ATmega3290 except of the signature - -part parent "m3290" - id = "m3290p"; - desc = "ATmega3290P"; - signature = 0x1e 0x95 0x0c; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega649 -#------------------------------------------------------------ - -part - id = "m649"; - desc = "ATmega649"; - has_jtag = yes; -# stk500_devcode = 0x85; # no STK500 support, only STK500v2 -# avr910_devcode = 0x?; # try the ATmega169 one: - avr910_devcode = 0x75; - signature = 0x1e 0x96 0x03; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega6490 -#------------------------------------------------------------ - -# identical to ATmega649 - -part parent "m649" - id = "m6490"; - desc = "ATmega6490"; - signature = 0x1e 0x96 0x04; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega32 -#------------------------------------------------------------ - -part - id = "m32"; - desc = "ATmega32"; - has_jtag = yes; - stk500_devcode = 0x91; - avr910_devcode = 0x72; - signature = 0x1e 0x95 0x02; - chip_erase_delay = 9000; - pagel = 0xd7; - bs2 = 0xa0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = yes; - - ocdrev = 2; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x04; - delay = 10; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega161 -#------------------------------------------------------------ - -part - id = "m161"; - desc = "ATmega161"; - stk500_devcode = 0x80; - avr910_devcode = 0x60; - signature = 0x1e 0x94 0x01; - chip_erase_delay = 28000; - pagel = 0xd7; - bs2 = 0xa0; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 30; - programfusepulsewidth = 0; - programfusepolltimeout = 2; - programlockpulsewidth = 0; - programlockpolltimeout = 2; - - memory "eeprom" - size = 512; - min_write_delay = 3400; - max_write_delay = 3400; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 5; - blocksize = 128; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 14000; - max_write_delay = 14000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 16; - blocksize = 128; - readsize = 256; - ; - - memory "fuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 x x x x x x x x", - "x x x x x x x x x o x o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", - "x x x x x x x x 1 i 1 i i i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATmega8 -#------------------------------------------------------------ - -part - id = "m8"; - desc = "ATmega8"; - stk500_devcode = 0x70; - avr910_devcode = 0x76; - signature = 0x1e 0x93 0x07; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 10000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 2; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - size = 512; - page_size = 4; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 20; - blocksize = 128; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 10; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - # Required for Arduino IDE - # see: https://github.com/arduino/Arduino/issues/2075 - # https://github.com/arduino/Arduino/issues/2075#issuecomment-238031689 - memory "efuse" - size = 0; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - - -#------------------------------------------------------------ -# ATmega8515 -#------------------------------------------------------------ - -part - id = "m8515"; - desc = "ATmega8515"; - stk500_devcode = 0x63; - avr910_devcode = 0x3A; - signature = 0x1e 0x93 0x06; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - size = 512; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 20; - blocksize = 128; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - - - -#------------------------------------------------------------ -# ATmega8535 -#------------------------------------------------------------ - -part - id = "m8535"; - desc = "ATmega8535"; - stk500_devcode = 0x64; - avr910_devcode = 0x69; - signature = 0x1e 0x93 0x08; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 6; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - size = 512; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - mode = 0x04; - delay = 20; - blocksize = 128; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 0 x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 2000; - max_write_delay = 2000; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - - -#------------------------------------------------------------ -# ATtiny26 -#------------------------------------------------------------ - -part - id = "t26"; - desc = "ATtiny26"; - stk500_devcode = 0x21; - avr910_devcode = 0x5e; - signature = 0x1e 0x91 0x09; - pagel = 0xb3; - bs2 = 0xb2; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, - 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, - 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, - 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 2; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - size = 128; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - mode = 0x04; - delay = 10; - blocksize = 64; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 2048; - page_size = 32; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 16; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x x o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x x x x i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 4; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - -; - - -#------------------------------------------------------------ -# ATtiny261 -#------------------------------------------------------------ -# Close to ATtiny26 - -part - id = "t261"; - desc = "ATtiny261"; - has_debugwire = yes; - flash_instr = 0xB4, 0x00, 0x10; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -# stk500_devcode = 0x21; -# avr910_devcode = 0x5e; - signature = 0x1e 0x91 0x0c; - pagel = 0xb3; - bs2 = 0xb2; - chip_erase_delay = 4000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, - 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, - 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, - 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 2; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - size = 128; - page_size = 4; - num_pages = 32; - min_write_delay = 4000; - max_write_delay = 4000; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read = "1 0 1 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 x x x x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 2048; - page_size = 32; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x x x x a9 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x x o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - -; - - -#------------------------------------------------------------ -# ATtiny461 -#------------------------------------------------------------ -# Close to ATtiny261 - -part - id = "t461"; - desc = "ATtiny461"; - has_debugwire = yes; - flash_instr = 0xB4, 0x00, 0x10; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -# stk500_devcode = 0x21; -# avr910_devcode = 0x5e; - signature = 0x1e 0x92 0x08; - pagel = 0xb3; - bs2 = 0xb2; - chip_erase_delay = 4000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, - 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, - 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, - 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 2; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - size = 256; - page_size = 4; - num_pages = 64; - min_write_delay = 4000; - max_write_delay = 4000; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read = " 1 0 1 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x x o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - -; - - -#------------------------------------------------------------ -# ATtiny861 -#------------------------------------------------------------ -# Close to ATtiny461 - -part - id = "t861"; - desc = "ATtiny861"; - has_debugwire = yes; - flash_instr = 0xB4, 0x00, 0x10; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -# stk500_devcode = 0x21; -# avr910_devcode = 0x5e; - signature = 0x1e 0x93 0x0d; - pagel = 0xb3; - bs2 = 0xb2; - chip_erase_delay = 4000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 0; - - pp_controlstack = - 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, - 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, - 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, - 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 2; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - size = 512; - num_pages = 128; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4000; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read_lo = " 0 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 x x x x x x x x", - "x x x x x x x x x x x x x x o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", - "x x x x x x x x x x x x x x x x"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - -; - - -#------------------------------------------------------------ -# ATtiny28 -#------------------------------------------------------------ - -# This is an HVPP-only device. - -part - id = "t28"; - desc = "ATtiny28"; - stk500_devcode = 0x22; - avr910_devcode = 0x5c; - signature = 0x1e 0x91 0x07; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 0; - poweroffdelay = 0; - resetdelayms = 0; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "flash" - size = 2048; - page_size = 2; - readsize = 256; - delay = 5; - ; - - memory "signature" - size = 3; - ; - - memory "lock" - size = 1; - ; - - memory "calibration" - size = 1; - ; - - memory "fuse" - size = 1; - ; -; - - - -#------------------------------------------------------------ -# ATmega48 -#------------------------------------------------------------ - -part - id = "m48"; - desc = "ATmega48"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x59; -# avr910_devcode = 0x; - signature = 0x1e 0x92 0x05; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 45000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - page_size = 4; - size = 256; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x x x", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega48P -#------------------------------------------------------------ - -part parent "m48" - id = "m48p"; - desc = "ATmega48P"; - signature = 0x1e 0x92 0x0a; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# ATmega48PB -#------------------------------------------------------------ - -part parent "m48" - id = "m48pb"; - desc = "ATmega48PB"; - signature = 0x1e 0x92 0x10; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# ATmega88 -#------------------------------------------------------------ - -part - id = "m88"; - desc = "ATmega88"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x73; -# avr910_devcode = 0x; - signature = 0x1e 0x93 0x0a; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - page_size = 4; - size = 512; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega88P -#------------------------------------------------------------ - -part parent "m88" - id = "m88p"; - desc = "ATmega88P"; - signature = 0x1e 0x93 0x0f; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# ATmega88PB -#------------------------------------------------------------ - -part parent "m88" - id = "m88pb"; - desc = "ATmega88PB"; - signature = 0x1e 0x93 0x16; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# ATmega168 -#------------------------------------------------------------ - -part - id = "m168"; - desc = "ATmega168"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x86; - # avr910_devcode = 0x; - signature = 0x1e 0x94 0x06; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - page_size = 4; - size = 512; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; -; - -#------------------------------------------------------------ -# ATmega168P -#------------------------------------------------------------ - -part parent "m168" - id = "m168p"; - desc = "ATmega168P"; - signature = 0x1e 0x94 0x0b; - - ocdrev = 1; -; - -#------------------------------------------------------------ -# ATmega168PB -#------------------------------------------------------------ - -part parent "m168" - id = "m168pb"; - desc = "ATmega168PB"; - signature = 0x1e 0x94 0x15; - - ocdrev = 1; -; - -#------------------------------------------------------------ -# ATtiny88 -#------------------------------------------------------------ - -part - id = "t88"; - desc = "ATtiny88"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x73; -# avr910_devcode = 0x; - signature = 0x1e 0x93 0x11; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - page_size = 4; - size = 64; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 64; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega328 -#------------------------------------------------------------ - -part - id = "m328"; - desc = "ATmega328"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x86; - # avr910_devcode = 0x; - signature = 0x1e 0x95 0x14; - pagel = 0xd7; - bs2 = 0xc2; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; - page_size = 4; - size = 1024; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; -; - -part parent "m328" - id = "m328p"; - desc = "ATmega328P"; - signature = 0x1e 0x95 0x0F; - - ocdrev = 1; -; - -part parent "m328" - id = "m328pb"; - desc = "ATmega328PB"; - signature = 0x1e 0x95 0x16; - - ocdrev = 1; -; - -#------------------------------------------------------------ -# ATmega32m1 -#------------------------------------------------------------ - -part parent "m328" - id = "m32m1"; - desc = "ATmega32M1"; - # stk500_devcode = 0x; - # avr910_devcode = 0x; - signature = 0x1e 0x95 0x84; - bs2 = 0xe2; - - memory "efuse" - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x i i i i i i"; - ; -; - -#------------------------------------------------------------ -# ATmega64m1 -#------------------------------------------------------------ - -part parent "m328" - id = "m64m1"; - desc = "ATmega64M1"; - # stk500_devcode = 0x; - # avr910_devcode = 0x; - signature = 0x1e 0x96 0x84; - bs2 = 0xe2; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x i i i i i i"; - ; -; - -#------------------------------------------------------------ -# ATtiny2313 -#------------------------------------------------------------ - -part - id = "t2313"; - desc = "ATtiny2313"; - has_debugwire = yes; - flash_instr = 0xB2, 0x0F, 0x1F; - eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; - stk500_devcode = 0x23; -## Use the ATtiny26 devcode: - avr910_devcode = 0x5e; - signature = 0x1e 0x91 0x0a; - pagel = 0xD4; - bs2 = 0xD6; - reset = io; - chip_erase_delay = 9000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, - 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, - 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, - 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 0; - - memory "eeprom" - size = 128; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 2048; - page_size = 32; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - -# The information in the data sheet of April/2004 is wrong, this works: - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - -# The information in the data sheet of April/2004 is wrong, this works: - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - -# The information in the data sheet of April/2004 is wrong, this works: - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny2313 has Signature Bytes: 0x1E 0x91 0x0A. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; -# The Tiny2313 has calibration data for both 4 MHz and 8 MHz. -# The information in the data sheet of April/2004 is wrong, this works: - - memory "calibration" - size = 2; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny4313 -#------------------------------------------------------------ - -part - id = "t4313"; - desc = "ATtiny4313"; - has_debugwire = yes; - flash_instr = 0xB2, 0x0F, 0x1F; - eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; - stk500_devcode = 0x23; -## Use the ATtiny26 devcode: - avr910_devcode = 0x5e; - signature = 0x1e 0x92 0x0d; - pagel = 0xD4; - bs2 = 0xD6; - reset = io; - chip_erase_delay = 9000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, - 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, - 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, - 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 0; - - memory "eeprom" - size = 256; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny4313 has Signature Bytes: 0x1E 0x92 0x0D. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 2; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90PWM2 -#------------------------------------------------------------ - -part - id = "pwm2"; - desc = "AT90PWM2"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x65; -## avr910_devcode = ?; - signature = 0x1e 0x93 0x81; - pagel = 0xD8; - bs2 = 0xE2; - reset = io; - chip_erase_delay = 9000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - size = 512; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 64; - readsize = 256; - ; -# AT90PWM2 has Signature Bytes: 0x1E 0x93 0x81. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90PWM3 -#------------------------------------------------------------ - -# Completely identical to AT90PWM2 (including the signature!) - -part parent "pwm2" - id = "pwm3"; - desc = "AT90PWM3"; - ; - -#------------------------------------------------------------ -# AT90PWM2B -#------------------------------------------------------------ -# Same as AT90PWM2 but different signature. - -part parent "pwm2" - id = "pwm2b"; - desc = "AT90PWM2B"; - signature = 0x1e 0x93 0x83; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# AT90PWM3B -#------------------------------------------------------------ - -# Completely identical to AT90PWM2B (including the signature!) - -part parent "pwm2b" - id = "pwm3b"; - desc = "AT90PWM3B"; - - ocdrev = 1; - ; - -#------------------------------------------------------------ -# AT90PWM316 -#------------------------------------------------------------ - -# Similar to AT90PWM3B, but with 16 kiB flash, 512 B EEPROM, and 1024 B SRAM. - -part parent "pwm3b" - id = "pwm316"; - desc = "AT90PWM316"; - signature = 0x1e 0x94 0x83; - - ocdrev = 1; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x21; - delay = 6; - blocksize = 128; - readsize = 256; - ; - ; - -#------------------------------------------------------------ -# AT90PWM216 -#------------------------------------------------------------ -# Completely identical to AT90PWM316 (including the signature!) - -part parent "pwm316" - id = "pwm216"; - desc = "AT90PWM216"; - ; - -#------------------------------------------------------------ -# ATtiny25 -#------------------------------------------------------------ - -part - id = "t25"; - desc = "ATtiny25"; - has_debugwire = yes; - flash_instr = 0xB4, 0x02, 0x12; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -## no STK500 devcode in XML file, use the ATtiny45 one - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x91 0x08; - reset = io; - chip_erase_delay = 4500; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 128; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 2048; - page_size = 32; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny25 has Signature Bytes: 0x1E 0x91 0x08. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny45 -#------------------------------------------------------------ - -part - id = "t45"; - desc = "ATtiny45"; - has_debugwire = yes; - flash_instr = 0xB4, 0x02, 0x12; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x92 0x06; - reset = io; - chip_erase_delay = 4500; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 256; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny45 has Signature Bytes: 0x1E 0x92 0x08. (Data sheet 2586C-AVR-06/05 (doc2586.pdf) indicates otherwise!) - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny85 -#------------------------------------------------------------ - -part - id = "t85"; - desc = "ATtiny85"; - has_debugwire = yes; - flash_instr = 0xB4, 0x02, 0x12; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -## no STK500 devcode in XML file, use the ATtiny45 one - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x93 0x0b; - reset = io; - chip_erase_delay = 400000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 512; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 12; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 30000; - max_write_delay = 30000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny85 has Signature Bytes: 0x1E 0x93 0x08. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega640 -#------------------------------------------------------------ -# Almost same as ATmega1280, except for different memory sizes - -part - id = "m640"; - desc = "ATmega640"; - signature = 0x1e 0x96 0x08; - has_jtag = yes; -# stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega1280 -#------------------------------------------------------------ - -part - id = "m1280"; - desc = "ATmega1280"; - signature = 0x1e 0x97 0x03; - has_jtag = yes; -# stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega1281 -#------------------------------------------------------------ -# Identical to ATmega1280 - -part parent "m1280" - id = "m1281"; - desc = "ATmega1281"; - signature = 0x1e 0x97 0x04; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega2560 -#------------------------------------------------------------ - -part - id = "m2560"; - desc = "ATmega2560"; - signature = 0x1e 0x98 0x01; - has_jtag = yes; - stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 4; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 262144; - page_size = 256; - num_pages = 1024; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - load_ext_addr = " 0 1 0 0 1 1 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 0 a16", - " 0 0 0 0 0 0 0 0"; - - mode = 0x41; - delay = 10; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega2561 -#------------------------------------------------------------ - -part parent "m2560" - id = "m2561"; - desc = "ATmega2561"; - signature = 0x1e 0x98 0x02; - - ocdrev = 4; - ; - -#------------------------------------------------------------ -# ATmega128RFA1 -#------------------------------------------------------------ -# Identical to ATmega2561 but half the ROM - -part parent "m2561" - id = "m128rfa1"; - desc = "ATmega128RFA1"; - signature = 0x1e 0xa7 0x01; - chip_erase_delay = 55000; - bs2 = 0xE2; - - ocdrev = 3; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 50000; - max_write_delay = 50000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 256; - readsize = 256; - ; - ; - -#------------------------------------------------------------ -# ATmega256RFR2 -#------------------------------------------------------------ - -part parent "m2561" - id = "m256rfr2"; - desc = "ATmega256RFR2"; - signature = 0x1e 0xa8 0x02; - chip_erase_delay = 18500; - bs2 = 0xE2; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 8192; - min_write_delay = 13000; - max_write_delay = 13000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - - ocdrev = 4; - ; - -#------------------------------------------------------------ -# ATmega128RFR2 -#------------------------------------------------------------ - -part parent "m128rfa1" - id = "m128rfr2"; - desc = "ATmega128RFR2"; - signature = 0x1e 0xa7 0x02; - - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega64RFR2 -#------------------------------------------------------------ - -part parent "m128rfa1" - id = "m64rfr2"; - desc = "ATmega64RFR2"; - signature = 0x1e 0xa6 0x02; - - - ocdrev = 3; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 50000; - max_write_delay = 50000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 256; - readsize = 256; - ; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 13000; - max_write_delay = 13000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - - ; - -#------------------------------------------------------------ -# ATmega2564RFR2 -#------------------------------------------------------------ - -part parent "m256rfr2" - id = "m2564rfr2"; - desc = "ATmega2564RFR2"; - signature = 0x1e 0xa8 0x03; - ; - -#------------------------------------------------------------ -# ATmega1284RFR2 -#------------------------------------------------------------ - -part parent "m128rfr2" - id = "m1284rfr2"; - desc = "ATmega1284RFR2"; - signature = 0x1e 0xa7 0x03; - ; - -#------------------------------------------------------------ -# ATmega644RFR2 -#------------------------------------------------------------ - -part parent "m64rfr2" - id = "m644rfr2"; - desc = "ATmega644RFR2"; - signature = 0x1e 0xa6 0x03; - ; - -#------------------------------------------------------------ -# ATtiny24 -#------------------------------------------------------------ - -part - id = "t24"; - desc = "ATtiny24"; - has_debugwire = yes; - flash_instr = 0xB4, 0x07, 0x17; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -## no STK500 devcode in XML file, use the ATtiny45 one - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x91 0x0b; - reset = io; - chip_erase_delay = 4500; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 70; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 128; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 2048; - page_size = 32; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny24 has Signature Bytes: 0x1E 0x91 0x0B. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x x x x x x x i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny44 -#------------------------------------------------------------ - -part - id = "t44"; - desc = "ATtiny44"; - has_debugwire = yes; - flash_instr = 0xB4, 0x07, 0x17; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -## no STK500 devcode in XML file, use the ATtiny45 one - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x92 0x07; - reset = io; - chip_erase_delay = 4500; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 70; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 256; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny44 has Signature Bytes: 0x1E 0x92 0x07. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x x x x x x x i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny84 -#------------------------------------------------------------ - -part - id = "t84"; - desc = "ATtiny84"; - has_debugwire = yes; - flash_instr = 0xB4, 0x07, 0x17; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; -## no STK500 devcode in XML file, use the ATtiny45 one - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x93 0x0c; - reset = io; - chip_erase_delay = 4500; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - hvsp_controlstack = - 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, - 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, - 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, - 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; - hventerstabdelay = 100; - hvspcmdexedelay = 0; - synchcycles = 6; - latchcycles = 1; - togglevtg = 1; - poweroffdelay = 25; - resetdelayms = 0; - resetdelayus = 70; - hvleavestabdelay = 100; - resetdelay = 25; - chiperasepolltimeout = 40; - chiperasetime = 0; - programfusepolltimeout = 25; - programlockpolltimeout = 25; - - ocdrev = 1; - - memory "eeprom" - size = 512; - paged = no; - page_size = 4; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", - "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 8192; - page_size = 64; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 32; - readsize = 256; - ; -# ATtiny84 has Signature Bytes: 0x1E 0x93 0x0C. - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x x x x x x x i i"; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATtiny441 -#------------------------------------------------------------ - -part parent "t44" - id = "t441"; - desc = "ATtiny441"; - signature = 0x1e 0x92 0x15; - - memory "flash" - paged = yes; - size = 4096; - page_size = 16; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x x a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x x a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 16; - readsize = 256; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; -; - -#------------------------------------------------------------ -# ATtiny841 -#------------------------------------------------------------ - -part parent "t84" - id = "t841"; - desc = "ATtiny841"; - signature = 0x1e 0x93 0x15; - - memory "flash" - paged = yes; - size = 8192; - page_size = 16; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x x x a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x x x a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 16; - readsize = 256; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; -; - -#------------------------------------------------------------ -# ATtiny43U -#------------------------------------------------------------ - -part - id = "t43u"; - desc = "ATtiny43u"; - has_debugwire = yes; - flash_instr = 0xB4, 0x07, 0x17; - eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, - 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, - 0x99, 0xE1, 0xBB, 0xAC; - stk500_devcode = 0x14; -## avr910_devcode = ?; -## Try the AT90S2313 devcode: - avr910_devcode = 0x20; - signature = 0x1e 0x92 0x0C; - reset = io; - chip_erase_delay = 1000; - - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, 0x4E, 0x5E, - 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, 0x06, 0x16, 0x46, 0x56, - 0x0A, 0x1A, 0x4A, 0x5A, 0x1E, 0x7C, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - hvspcmdexedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 20; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - memory "eeprom" - size = 64; - paged = yes; - page_size = 4; - num_pages = 16; - min_write_delay = 4000; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", - "0 0 a4 a3 a2 a1 a0 o o o o o o o o"; - - write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", - "0 0 a5 a4 a3 a2 a1 a0 i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " 0 0 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 5; - blocksize = 4; - readsize = 256; - ; - memory "flash" - paged = yes; - size = 4096; - page_size = 64; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x x a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 64; - readsize = 256; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - memory "lock" - size = 1; - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x x x x i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 4500; - max_write_delay = 4500; - ; - - memory "calibration" - size = 2; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 a0 o o o o o o o o"; - ; -; - -#------------------------------------------------------------ -# ATmega32u4 -#------------------------------------------------------------ - -part - id = "m32u4"; - desc = "ATmega32U4"; - signature = 0x1e 0x95 0x87; - usbpid = 0x2ff4; - has_jtag = yes; -# stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90USB646 -#------------------------------------------------------------ - -part - id = "usb646"; - desc = "AT90USB646"; - signature = 0x1e 0x96 0x82; - usbpid = 0x2ff9; - has_jtag = yes; -# stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x x a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90USB647 -#------------------------------------------------------------ -# identical to AT90USB646 - -part parent "usb646" - id = "usb647"; - desc = "AT90USB647"; - signature = 0x1e 0x96 0x82; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# AT90USB1286 -#------------------------------------------------------------ - -part - id = "usb1286"; - desc = "AT90USB1286"; - signature = 0x1e 0x97 0x82; - usbpid = 0x2ffb; - has_jtag = yes; -# stk500_devcode = 0xB2; -# avr910_devcode = 0x43; - chip_erase_delay = 9000; - pagel = 0xD7; - bs2 = 0xA0; - reset = dedicated; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - rampz = 0x3b; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 4096; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " x x x x a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 131072; - page_size = 256; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 x x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 256; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x x i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 x x x x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 x x x x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90USB1287 -#------------------------------------------------------------ -# identical to AT90USB1286 - -part parent "usb1286" - id = "usb1287"; - desc = "AT90USB1287"; - signature = 0x1e 0x97 0x82; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# AT90USB162 -#------------------------------------------------------------ - -part - id = "usb162"; - desc = "AT90USB162"; - has_jtag = no; - has_debugwire = yes; - signature = 0x1e 0x94 0x82; - usbpid = 0x2ffa; - chip_erase_delay = 9000; - reset = io; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - pagel = 0xD7; - bs2 = 0xC6; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - num_pages = 128; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# AT90USB82 -#------------------------------------------------------------ -# Changes against AT90USB162 (beside IDs) -# memory "flash" -# size = 8192; -# num_pages = 64; - -part - id = "usb82"; - desc = "AT90USB82"; - has_jtag = no; - has_debugwire = yes; - signature = 0x1e 0x93 0x82; - usbpid = 0x2ff7; - chip_erase_delay = 9000; - reset = io; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - pagel = 0xD7; - bs2 = 0xC6; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - num_pages = 128; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 8192; - page_size = 128; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega32U2 -#------------------------------------------------------------ -# Changes against AT90USB162 (beside IDs) -# memory "flash" -# size = 32768; -# num_pages = 256; -# memory "eeprom" -# size = 1024; -# num_pages = 256; -part - id = "m32u2"; - desc = "ATmega32U2"; - has_jtag = no; - has_debugwire = yes; - signature = 0x1e 0x95 0x8a; - usbpid = 0x2ff0; - chip_erase_delay = 9000; - reset = io; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - pagel = 0xD7; - bs2 = 0xC6; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - num_pages = 256; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; -#------------------------------------------------------------ -# ATmega16U2 -#------------------------------------------------------------ -# Changes against ATmega32U2 (beside IDs) -# memory "flash" -# size = 16384; -# num_pages = 128; -# memory "eeprom" -# size = 512; -# num_pages = 128; -part - id = "m16u2"; - desc = "ATmega16U2"; - has_jtag = no; - has_debugwire = yes; - signature = 0x1e 0x94 0x89; - usbpid = 0x2fef; - chip_erase_delay = 9000; - reset = io; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - pagel = 0xD7; - bs2 = 0xC6; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - num_pages = 128; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 128; - num_pages = 128; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega8U2 -#------------------------------------------------------------ -# Changes against ATmega16U2 (beside IDs) -# memory "flash" -# size = 8192; -# page_size = 64; -# blocksize = 64; - -part - id = "m8u2"; - desc = "ATmega8U2"; - has_jtag = no; - has_debugwire = yes; - signature = 0x1e 0x93 0x89; - usbpid = 0x2fee; - chip_erase_delay = 9000; - reset = io; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - pagel = 0xD7; - bs2 = 0xC6; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - ocdrev = 1; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 512; - num_pages = 128; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0x00; - readback_p2 = 0x00; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 20; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 8192; - page_size = 128; - num_pages = 64; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0x00; - readback_p2 = 0x00; - read_lo = " 0 0 1 0 0 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " x x x x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - "a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - ; - - memory "lfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x i i i i i i i i"; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; - ; -#------------------------------------------------------------ -# ATmega325 -#------------------------------------------------------------ - -part - id = "m325"; - desc = "ATmega325"; - signature = 0x1e 0x95 0x05; - has_jtag = yes; -# stk500_devcode = 0x??; # No STK500v1 support? -# avr910_devcode = 0x??; # Try the ATmega16 one - avr910_devcode = 0x74; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 4; /* for parallel programming */ - size = 1024; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 0 0 a9 a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 32768; - page_size = 128; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 0 0 0 0 0", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 0 0 0 0 0", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", - "0 0 0 0 0 0 0 0 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "0 0 0 0 0 0 0 0 i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "0 0 0 0 0 0 0 0 i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega645 -#------------------------------------------------------------ - -part - id = "m645"; - desc = "ATmega645"; - signature = 0x1E 0x96 0x05; - has_jtag = yes; -# stk500_devcode = 0x??; # No STK500v1 support? -# avr910_devcode = 0x??; # Try the ATmega16 one - avr910_devcode = 0x74; - pagel = 0xd7; - bs2 = 0xa0; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, - 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, - 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, - 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 5; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - idr = 0x31; - spmcr = 0x57; - allowfullpagebitstream = no; - - ocdrev = 3; - - memory "eeprom" - paged = no; /* leave this "no" */ - page_size = 8; /* for parallel programming */ - size = 2048; - min_write_delay = 9000; - max_write_delay = 9000; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 0 0 0 a10 a9 a8", - " a7 a6 a5 a4 a3 0 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 10; - blocksize = 8; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 65536; - page_size = 256; - num_pages = 256; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 0 0 0 0 0", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 0 0 0 0 0", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " a15 a14 a13 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " 0 0 0 0 0 0 0 0"; - - mode = 0x41; - delay = 10; - blocksize = 128; - readsize = 256; - ; - - memory "lock" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", - "0 0 0 0 0 0 0 0 1 1 i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "lfuse" - size = 1; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "0 0 0 0 0 0 0 0 i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "hfuse" - size = 1; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "0 0 0 0 0 0 0 0 i i i i i i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "efuse" - size = 1; - - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; - min_write_delay = 9000; - max_write_delay = 9000; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 a1 a0 o o o o o o o o"; - ; - - memory "calibration" - size = 1; - - read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - ; - -#------------------------------------------------------------ -# ATmega3250 -#------------------------------------------------------------ - -part parent "m325" - id = "m3250"; - desc = "ATmega3250"; - signature = 0x1E 0x95 0x06; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# ATmega6450 -#------------------------------------------------------------ - -part parent "m645" - id = "m6450"; - desc = "ATmega6450"; - signature = 0x1E 0x96 0x06; - - ocdrev = 3; - ; - -#------------------------------------------------------------ -# AVR XMEGA family common values -#------------------------------------------------------------ - -part - id = ".xmega"; - desc = "AVR XMEGA family common values"; - has_pdi = yes; - nvm_base = 0x01c0; - mcu_base = 0x0090; - - memory "signature" - size = 3; - offset = 0x1000090; - ; - - memory "prodsig" - size = 0x32; - offset = 0x8e0200; - page_size = 0x32; - readsize = 0x32; - ; - - memory "fuse1" - size = 1; - offset = 0x8f0021; - ; - - memory "fuse2" - size = 1; - offset = 0x8f0022; - ; - - memory "fuse4" - size = 1; - offset = 0x8f0024; - ; - - memory "fuse5" - size = 1; - offset = 0x8f0025; - ; - - memory "lock" - size = 1; - offset = 0x8f0027; - ; - - memory "data" - # SRAM, only used to supply the offset - offset = 0x1000000; - ; -; - -#------------------------------------------------------------ -# ATxmega16A4U -#------------------------------------------------------------ - -part parent ".xmega" - id = "x16a4u"; - desc = "ATxmega16A4U"; - signature = 0x1e 0x94 0x41; - usbpid = 0x2fe3; - - memory "eeprom" - size = 0x400; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x4000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x803000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "boot" - size = 0x1000; - offset = 0x804000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "flash" - size = 0x5000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "usersig" - size = 0x100; - offset = 0x8e0400; - page_size = 0x100; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega16C4 -#------------------------------------------------------------ - -part parent "x16a4u" - id = "x16c4"; - desc = "ATxmega16C4"; - signature = 0x1e 0x94 0x43; -; - -#------------------------------------------------------------ -# ATxmega16D4 -#------------------------------------------------------------ - -part parent "x16a4u" - id = "x16d4"; - desc = "ATxmega16D4"; - signature = 0x1e 0x94 0x42; -; - -#------------------------------------------------------------ -# ATxmega16A4 -#------------------------------------------------------------ - -part parent "x16a4u" - id = "x16a4"; - desc = "ATxmega16A4"; - signature = 0x1e 0x94 0x41; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega32A4U -#------------------------------------------------------------ - -part parent ".xmega" - id = "x32a4u"; - desc = "ATxmega32A4U"; - signature = 0x1e 0x95 0x41; - usbpid = 0x2fe4; - - memory "eeprom" - size = 0x400; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x8000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x807000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "boot" - size = 0x1000; - offset = 0x808000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "flash" - size = 0x9000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "usersig" - size = 0x100; - offset = 0x8e0400; - page_size = 0x100; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega32C4 -#------------------------------------------------------------ - -part parent "x32a4u" - id = "x32c4"; - desc = "ATxmega32C4"; - signature = 0x1e 0x95 0x44; -; - -#------------------------------------------------------------ -# ATxmega32D4 -#------------------------------------------------------------ - -part parent "x32a4u" - id = "x32d4"; - desc = "ATxmega32D4"; - signature = 0x1e 0x95 0x42; -; - -#------------------------------------------------------------ -# ATxmega32A4 -#------------------------------------------------------------ - -part parent "x32a4u" - id = "x32a4"; - desc = "ATxmega32A4"; - signature = 0x1e 0x95 0x41; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega64A4U -#------------------------------------------------------------ - -part parent ".xmega" - id = "x64a4u"; - desc = "ATxmega64A4U"; - signature = 0x1e 0x96 0x46; - usbpid = 0x2fe5; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x10000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x80f000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "boot" - size = 0x1000; - offset = 0x810000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "flash" - size = 0x11000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "usersig" - size = 0x100; - offset = 0x8e0400; - page_size = 0x100; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega64C3 -#------------------------------------------------------------ - -part parent "x64a4u" - id = "x64c3"; - desc = "ATxmega64C3"; - signature = 0x1e 0x96 0x49; - usbpid = 0x2fd6; -; - -#------------------------------------------------------------ -# ATxmega64D3 -#------------------------------------------------------------ - -part parent "x64a4u" - id = "x64d3"; - desc = "ATxmega64D3"; - signature = 0x1e 0x96 0x4a; -; - -#------------------------------------------------------------ -# ATxmega64D4 -#------------------------------------------------------------ - -part parent "x64a4u" - id = "x64d4"; - desc = "ATxmega64D4"; - signature = 0x1e 0x96 0x47; -; - -#------------------------------------------------------------ -# ATxmega64A1 -#------------------------------------------------------------ - -part parent "x64a4u" - id = "x64a1"; - desc = "ATxmega64A1"; - signature = 0x1e 0x96 0x4e; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega64A1U -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64a1u"; - desc = "ATxmega64A1U"; - signature = 0x1e 0x96 0x4e; - usbpid = 0x2fe8; -; - -#------------------------------------------------------------ -# ATxmega64A3 -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64a3"; - desc = "ATxmega64A3"; - signature = 0x1e 0x96 0x42; -; - -#------------------------------------------------------------ -# ATxmega64A3U -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64a3u"; - desc = "ATxmega64A3U"; - signature = 0x1e 0x96 0x42; - usbpid = 0x2fe5; -; - -#------------------------------------------------------------ -# ATxmega64A4 -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64a4"; - desc = "ATxmega64A4"; - signature = 0x1e 0x96 0x46; -; - -#------------------------------------------------------------ -# ATxmega64B1 -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64b1"; - desc = "ATxmega64B1"; - signature = 0x1e 0x96 0x52; - usbpid = 0x2fe1; -; - -#------------------------------------------------------------ -# ATxmega64B3 -#------------------------------------------------------------ - -part parent "x64a1" - id = "x64b3"; - desc = "ATxmega64B3"; - signature = 0x1e 0x96 0x51; - usbpid = 0x2fdf; -; - -#------------------------------------------------------------ -# ATxmega128C3 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x128c3"; - desc = "ATxmega128C3"; - signature = 0x1e 0x97 0x52; - usbpid = 0x2fd7; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x20000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "apptable" - size = 0x2000; - offset = 0x81e000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x820000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "flash" - size = 0x22000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "usersig" - size = 0x200; - offset = 0x8e0400; - page_size = 0x200; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega128D3 -#------------------------------------------------------------ - -part parent "x128c3" - id = "x128d3"; - desc = "ATxmega128D3"; - signature = 0x1e 0x97 0x48; -; - -#------------------------------------------------------------ -# ATxmega128D4 -#------------------------------------------------------------ - -part parent "x128c3" - id = "x128d4"; - desc = "ATxmega128D4"; - signature = 0x1e 0x97 0x47; -; - -#------------------------------------------------------------ -# ATxmega128A1 -#------------------------------------------------------------ - -part parent "x128c3" - id = "x128a1"; - desc = "ATxmega128A1"; - signature = 0x1e 0x97 0x4c; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega128A1 revision D -#------------------------------------------------------------ - -part parent "x128a1" - id = "x128a1d"; - desc = "ATxmega128A1revD"; - signature = 0x1e 0x97 0x41; -; - -#------------------------------------------------------------ -# ATxmega128A1U -#------------------------------------------------------------ - -part parent "x128a1" - id = "x128a1u"; - desc = "ATxmega128A1U"; - signature = 0x1e 0x97 0x4c; - usbpid = 0x2fed; -; - -#------------------------------------------------------------ -# ATxmega128A3 -#------------------------------------------------------------ - -part parent "x128a1" - id = "x128a3"; - desc = "ATxmega128A3"; - signature = 0x1e 0x97 0x42; -; - -#------------------------------------------------------------ -# ATxmega128A3U -#------------------------------------------------------------ - -part parent "x128a1" - id = "x128a3u"; - desc = "ATxmega128A3U"; - signature = 0x1e 0x97 0x42; - usbpid = 0x2fe6; -; - -#------------------------------------------------------------ -# ATxmega128A4 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x128a4"; - desc = "ATxmega128A4"; - signature = 0x1e 0x97 0x46; - has_jtag = yes; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x20000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x81f000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x820000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "flash" - size = 0x22000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "usersig" - size = 0x200; - offset = 0x8e0400; - page_size = 0x200; - readsize = 0x100; - ; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega128A4U -#------------------------------------------------------------ - -part parent ".xmega" - id = "x128a4u"; - desc = "ATxmega128A4U"; - signature = 0x1e 0x97 0x46; - usbpid = 0x2fde; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x20000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x81f000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x820000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "flash" - size = 0x22000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "usersig" - size = 0x100; - offset = 0x8e0400; - page_size = 0x100; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega128B1 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x128b1"; - desc = "ATxmega128B1"; - signature = 0x1e 0x97 0x4d; - usbpid = 0x2fea; - has_jtag = yes; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x20000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "apptable" - size = 0x2000; - offset = 0x81e000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x820000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "flash" - size = 0x22000; - offset = 0x800000; - page_size = 0x100; - readsize = 0x100; - ; - - memory "usersig" - size = 0x100; - offset = 0x8e0400; - page_size = 0x100; - readsize = 0x100; - ; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega128B3 -#------------------------------------------------------------ - -part parent "x128b1" - id = "x128b3"; - desc = "ATxmega128B3"; - signature = 0x1e 0x97 0x4b; - usbpid = 0x2fe0; -; - -#------------------------------------------------------------ -# ATxmega192C3 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x192c3"; - desc = "ATxmega192C3"; - signature = 0x1e 0x97 0x51; - # usbpid = 0x2f??; - - memory "eeprom" - size = 0x800; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x30000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "apptable" - size = 0x2000; - offset = 0x82e000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x830000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "flash" - size = 0x32000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "usersig" - size = 0x200; - offset = 0x8e0400; - page_size = 0x200; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega192D3 -#------------------------------------------------------------ - -part parent "x192c3" - id = "x192d3"; - desc = "ATxmega192D3"; - signature = 0x1e 0x97 0x49; -; - -#------------------------------------------------------------ -# ATxmega192A1 -#------------------------------------------------------------ - -part parent "x192c3" - id = "x192a1"; - desc = "ATxmega192A1"; - signature = 0x1e 0x97 0x4e; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega192A3 -#------------------------------------------------------------ - -part parent "x192a1" - id = "x192a3"; - desc = "ATxmega192A3"; - signature = 0x1e 0x97 0x44; -; - -#------------------------------------------------------------ -# ATxmega192A3U -#------------------------------------------------------------ - -part parent "x192a1" - id = "x192a3u"; - desc = "ATxmega192A3U"; - signature = 0x1e 0x97 0x44; - usbpid = 0x2fe7; -; - -#------------------------------------------------------------ -# ATxmega256C3 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x256c3"; - desc = "ATxmega256C3"; - signature = 0x1e 0x98 0x46; - usbpid = 0x2fda; - - memory "eeprom" - size = 0x1000; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x40000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "apptable" - size = 0x2000; - offset = 0x83e000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x840000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "flash" - size = 0x42000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "usersig" - size = 0x200; - offset = 0x8e0400; - page_size = 0x200; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega256D3 -#------------------------------------------------------------ - -part parent "x256c3" - id = "x256d3"; - desc = "ATxmega256D3"; - signature = 0x1e 0x98 0x44; -; - -#------------------------------------------------------------ -# ATxmega256A1 -#------------------------------------------------------------ - -part parent "x256c3" - id = "x256a1"; - desc = "ATxmega256A1"; - signature = 0x1e 0x98 0x46; - has_jtag = yes; - - memory "fuse0" - size = 1; - offset = 0x8f0020; - ; -; - -#------------------------------------------------------------ -# ATxmega256A3 -#------------------------------------------------------------ - -part parent "x256a1" - id = "x256a3"; - desc = "ATxmega256A3"; - signature = 0x1e 0x98 0x42; -; - -#------------------------------------------------------------ -# ATxmega256A3U -#------------------------------------------------------------ - -part parent "x256a1" - id = "x256a3u"; - desc = "ATxmega256A3U"; - signature = 0x1e 0x98 0x42; - usbpid = 0x2fec; -; - -#------------------------------------------------------------ -# ATxmega256A3B -#------------------------------------------------------------ - -part parent "x256a1" - id = "x256a3b"; - desc = "ATxmega256A3B"; - signature = 0x1e 0x98 0x43; -; - -#------------------------------------------------------------ -# ATxmega256A3BU -#------------------------------------------------------------ - -part parent "x256a1" - id = "x256a3bu"; - desc = "ATxmega256A3BU"; - signature = 0x1e 0x98 0x43; - usbpid = 0x2fe2; -; - -#------------------------------------------------------------ -# ATxmega384C3 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x384c3"; - desc = "ATxmega384C3"; - signature = 0x1e 0x98 0x45; - usbpid = 0x2fdb; - - memory "eeprom" - size = 0x1000; - offset = 0x8c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x60000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "apptable" - size = 0x2000; - offset = 0x85e000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "boot" - size = 0x2000; - offset = 0x860000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "flash" - size = 0x62000; - offset = 0x800000; - page_size = 0x200; - readsize = 0x100; - ; - - memory "usersig" - size = 0x200; - offset = 0x8e0400; - page_size = 0x200; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega384D3 -#------------------------------------------------------------ - -part parent "x384c3" - id = "x384d3"; - desc = "ATxmega384D3"; - signature = 0x1e 0x98 0x47; -; - -#------------------------------------------------------------ -# ATxmega8E5 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x8e5"; - desc = "ATxmega8E5"; - signature = 0x1e 0x93 0x41; - - memory "eeprom" - size = 0x0200; - offset = 0x08c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x2000; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "apptable" - size = 0x800; - offset = 0x00801800; - page_size = 0x80; - readsize = 0x100; - ; - - memory "boot" - size = 0x800; - offset = 0x00802000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "flash" - size = 0x2800; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "usersig" - size = 0x80; - offset = 0x8e0400; - page_size = 0x80; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega16E5 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x16e5"; - desc = "ATxmega16E5"; - signature = 0x1e 0x94 0x45; - - memory "eeprom" - size = 0x0200; - offset = 0x08c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x4000; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x00803000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "boot" - size = 0x1000; - offset = 0x00804000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "flash" - size = 0x5000; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "usersig" - size = 0x80; - offset = 0x8e0400; - page_size = 0x80; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATxmega32E5 -#------------------------------------------------------------ - -part parent ".xmega" - id = "x32e5"; - desc = "ATxmega32E5"; - signature = 0x1e 0x95 0x4c; - - memory "eeprom" - size = 0x0400; - offset = 0x08c0000; - page_size = 0x20; - readsize = 0x100; - ; - - memory "application" - size = 0x8000; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "apptable" - size = 0x1000; - offset = 0x00807000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "boot" - size = 0x1000; - offset = 0x00808000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "flash" - size = 0x9000; - offset = 0x0800000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "usersig" - size = 0x80; - offset = 0x8e0400; - page_size = 0x80; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# AVR32UC3A0512 -#------------------------------------------------------------ - -part - id = "uc3a0512"; - desc = "AT32UC3A0512"; - signature = 0xED 0xC0 0x3F; - has_jtag = yes; - is_avr32 = yes; - - memory "flash" - paged = yes; - page_size = 512; # bytes - readsize = 512; # bytes - num_pages = 1024; # could be set dynamicly - size = 0x00080000; # could be set dynamicly - offset = 0x80000000; - ; -; - -part parent "uc3a0512" - id = "ucr2"; - desc = "deprecated, use 'uc3a0512'"; -; - -#------------------------------------------------------------ -# ATtiny1634. -#------------------------------------------------------------ - -part - id = "t1634"; - desc = "ATtiny1634"; - has_debugwire = yes; - flash_instr = 0xB6, 0x01, 0x11; - eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, - 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, - 0x99, 0xF9, 0xBB, 0xAF; - stk500_devcode = 0x86; - # avr910_devcode = 0x; - signature = 0x1e 0x94 0x12; - pagel = 0xB3; - bs2 = 0xB1; - reset = io; - chip_erase_delay = 9000; - pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", - "x x x x x x x x x x x x x x x x"; - - chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", - "x x x x x x x x x x x x x x x x"; - - timeout = 200; - stabdelay = 100; - cmdexedelay = 25; - synchloops = 32; - bytedelay = 0; - pollindex = 3; - pollvalue = 0x53; - predelay = 1; - postdelay = 1; - pollmethod = 1; - - pp_controlstack = - 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, - 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, - 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, - 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - hventerstabdelay = 100; - progmodedelay = 0; - latchcycles = 0; - togglevtg = 1; - poweroffdelay = 15; - resetdelayms = 1; - resetdelayus = 0; - hvleavestabdelay = 15; - resetdelay = 15; - chiperasepulsewidth = 0; - chiperasepolltimeout = 10; - programfusepulsewidth = 0; - programfusepolltimeout = 5; - programlockpulsewidth = 0; - programlockpolltimeout = 5; - - memory "eeprom" - paged = no; - page_size = 4; - size = 256; - min_write_delay = 3600; - max_write_delay = 3600; - readback_p1 = 0xff; - readback_p2 = 0xff; - read = " 1 0 1 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - write = " 1 1 0 0 0 0 0 0", - " 0 0 0 x x x x a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_lo = " 1 1 0 0 0 0 0 1", - " 0 0 0 0 0 0 0 0", - " 0 0 0 0 0 0 a1 a0", - " i i i i i i i i"; - - writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x a8", - " a7 a6 a5 a4 a3 a2 0 0", - " x x x x x x x x"; - - mode = 0x41; - delay = 5; - blocksize = 4; - readsize = 256; - ; - - memory "flash" - paged = yes; - size = 16384; - page_size = 32; - num_pages = 512; - min_write_delay = 4500; - max_write_delay = 4500; - readback_p1 = 0xff; - readback_p2 = 0xff; - read_lo = " 0 0 1 0 0 0 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - read_hi = " 0 0 1 0 1 0 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 a5 a4 a3 a2 a1 a0", - " o o o o o o o o"; - - loadpage_lo = " 0 1 0 0 0 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - loadpage_hi = " 0 1 0 0 1 0 0 0", - " 0 0 0 x x x x x", - " x x a5 a4 a3 a2 a1 a0", - " i i i i i i i i"; - - writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", - " x x x x x x x x"; - - mode = 0x41; - delay = 6; - blocksize = 128; - readsize = 256; - - ; - - memory "lfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "hfuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", - "x x x x x x x x i i i i i i i i"; - ; - - memory "efuse" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", - "x x x x x x x x o o o o o o o o"; - - write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", - "x x x x x x x x x x x i i i i i"; - ; - - memory "lock" - size = 1; - min_write_delay = 4500; - max_write_delay = 4500; - read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", - "x x x x x x x x x x x x x x o o"; - - write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", - "x x x x x x x x 1 1 1 1 1 1 i i"; - ; - - memory "calibration" - size = 1; - read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", - "0 0 0 0 0 0 0 0 o o o o o o o o"; - ; - - memory "signature" - size = 3; - read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", - "x x x x x x a1 a0 o o o o o o o o"; - ; -; - -#------------------------------------------------------------ -# Common values for reduced core tinys (4/5/9/10/20/40) -#------------------------------------------------------------ - -part - id = ".reduced_core_tiny"; - desc = "Common values for reduced core tinys"; - has_tpi = yes; - - memory "signature" - size = 3; - offset = 0x3fc0; - page_size = 16; - ; - - memory "fuse" - size = 1; - offset = 0x3f40; - page_size = 16; - blocksize = 4; - ; - - memory "calibration" - size = 1; - offset = 0x3f80; - page_size = 16; - ; - - memory "lockbits" - size = 1; - offset = 0x3f00; - page_size = 16; - ; -; - -#------------------------------------------------------------ -# ATtiny4 -#------------------------------------------------------------ - -part parent ".reduced_core_tiny" - id = "t4"; - desc = "ATtiny4"; - signature = 0x1e 0x8f 0x0a; - - memory "flash" - size = 512; - offset = 0x4000; - page_size = 16; - blocksize = 128; - ; -; - -#------------------------------------------------------------ -# ATtiny5 -#------------------------------------------------------------ - -part parent "t4" - id = "t5"; - desc = "ATtiny5"; - signature = 0x1e 0x8f 0x09; -; - -#------------------------------------------------------------ -# ATtiny9 -#------------------------------------------------------------ - -part parent ".reduced_core_tiny" - id = "t9"; - desc = "ATtiny9"; - signature = 0x1e 0x90 0x08; - - memory "flash" - size = 1024; - offset = 0x4000; - page_size = 16; - blocksize = 128; - ; -; - -#------------------------------------------------------------ -# ATtiny10 -#------------------------------------------------------------ - -part parent "t9" - id = "t10"; - desc = "ATtiny10"; - signature = 0x1e 0x90 0x03; -; - -#------------------------------------------------------------ -# ATtiny20 -#------------------------------------------------------------ - -part parent ".reduced_core_tiny" - id = "t20"; - desc = "ATtiny20"; - signature = 0x1e 0x91 0x0F; - - memory "flash" - size = 2048; - offset = 0x4000; - page_size = 16; - blocksize = 128; - ; -; - -#------------------------------------------------------------ -# ATtiny40 -#------------------------------------------------------------ - -part parent ".reduced_core_tiny" - id = "t40"; - desc = "ATtiny40"; - signature = 0x1e 0x92 0x0E; - - memory "flash" - size = 4096; - offset = 0x4000; - page_size = 64; - blocksize = 128; - ; -; - -#------------------------------------------------------------ -# ATmega406 -#------------------------------------------------------------ - -part - id = "m406"; - desc = "ATMEGA406"; - has_jtag = yes; - signature = 0x1e 0x95 0x07; - - # STK500 parameters (parallel programming IO lines) - pagel = 0xa7; - bs2 = 0xa0; - serial = no; - parallel = yes; - - # STK500v2 HV programming parameters, from XML - pp_controlstack = 0x0e, 0x1e, 0x0f, 0x1f, 0x2e, 0x3e, 0x2f, 0x3f, - 0x4e, 0x5e, 0x4f, 0x5f, 0x6e, 0x7e, 0x6f, 0x7f, - 0x66, 0x76, 0x67, 0x77, 0x6a, 0x7a, 0x6b, 0x7b, - 0xbe, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; - - # JTAG ICE mkII parameters, also from XML files - allowfullpagebitstream = no; - enablepageprogramming = yes; - idr = 0x51; - rampz = 0x00; - spmcr = 0x57; - eecr = 0x3f; - - memory "eeprom" - paged = no; - size = 512; - page_size = 4; - blocksize = 4; - readsize = 4; - num_pages = 128; - ; - - memory "flash" - paged = yes; - size = 40960; - page_size = 128; - blocksize = 128; - readsize = 128; - num_pages = 320; - ; - - memory "hfuse" - size = 1; - ; - - memory "lfuse" - size = 1; - ; - - memory "lockbits" - size = 1; - ; - - memory "signature" - size = 3; - ; -; - -#------------------------------------------------------------ -# AVR8X family common values -#------------------------------------------------------------ - -part - id = ".avr8x"; - desc = "AVR8X family common values"; - has_updi = yes; - nvm_base = 0x1000; - ocd_base = 0x0F80; - - memory "signature" - size = 3; - offset = 0x1100; - ; - - memory "prodsig" - size = 0x3D; - offset = 0x1103; - page_size = 0x3D; - readsize = 0x3D; - ; - - memory "fuses" - size = 9; - offset = 0x1280; - ; - - memory "fuse0" - size = 1; - offset = 0x1280; - ; - - memory "fuse1" - size = 1; - offset = 0x1281; - ; - - memory "fuse2" - size = 1; - offset = 0x1282; - ; - - memory "fuse4" - size = 1; - offset = 0x1284; - ; - - memory "fuse5" - size = 1; - offset = 0x1285; - ; - - memory "fuse6" - size = 1; - offset = 0x1286; - ; - - memory "fuse7" - size = 1; - offset = 0x1287; - ; - - memory "fuse8" - size = 1; - offset = 0x1288; - ; - - memory "lock" - size = 1; - offset = 0x128a; - ; - - memory "data" - # SRAM, only used to supply the offset - offset = 0x1000000; - ; -; - -#------------------------------------------------------------ -# AVR8X tiny family common values -#------------------------------------------------------------ - -part parent ".avr8x" - id = ".avr8x_tiny"; - desc = "AVR8X tiny family common values"; - family_id = "tinyAVR"; - - memory "usersig" - size = 0x20; - offset = 0x1300; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# AVR8X mega family common values -#------------------------------------------------------------ - -part parent ".avr8x" - id = ".avr8x_mega"; - desc = "AVR8X mega family common values"; - family_id = "megaAVR"; - - memory "usersig" - size = 0x40; - offset = 0x1300; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny202 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t202"; - desc = "ATtiny202"; - signature = 0x1E 0x91 0x23; - - memory "flash" - size = 0x800; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x40; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny204 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t204"; - desc = "ATtiny204"; - signature = 0x1E 0x91 0x22; - - memory "flash" - size = 0x800; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x40; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny402 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t402"; - desc = "ATtiny402"; - signature = 0x1E 0x92 0x23; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny404 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t404"; - desc = "ATtiny404"; - signature = 0x1E 0x92 0x26; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny406 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t406"; - desc = "ATtiny406"; - signature = 0x1E 0x92 0x25; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny804 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t804"; - desc = "ATtiny804"; - signature = 0x1E 0x93 0x25; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny806 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t806"; - desc = "ATtiny806"; - signature = 0x1E 0x93 0x24; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny807 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t807"; - desc = "ATtiny807"; - signature = 0x1E 0x93 0x23; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1604 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1604"; - desc = "ATtiny1604"; - signature = 0x1E 0x94 0x25; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1606 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1606"; - desc = "ATtiny1606"; - signature = 0x1E 0x94 0x24; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1607 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1607"; - desc = "ATtiny1607"; - signature = 0x1E 0x94 0x23; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny212 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t212"; - desc = "ATtiny212"; - signature = 0x1E 0x91 0x21; - - memory "flash" - size = 0x800; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x40; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny214 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t214"; - desc = "ATtiny214"; - signature = 0x1E 0x91 0x20; - - memory "flash" - size = 0x800; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x40; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny412 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t412"; - desc = "ATtiny412"; - signature = 0x1E 0x92 0x23; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - - -#------------------------------------------------------------ -# ATtiny414 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t414"; - desc = "ATtiny414"; - signature = 0x1E 0x92 0x22; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny416 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t416"; - desc = "ATtiny416"; - signature = 0x1E 0x92 0x21; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - - -#------------------------------------------------------------ -# ATtiny417 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t417"; - desc = "ATtiny417"; - signature = 0x1E 0x92 0x20; - - memory "flash" - size = 0x1000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - - -#------------------------------------------------------------ -# ATtiny814 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t814"; - desc = "ATtiny814"; - signature = 0x1E 0x93 0x22; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - - -#------------------------------------------------------------ -# ATtiny816 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t816"; - desc = "ATtiny816"; - signature = 0x1E 0x93 0x21; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny817 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t817"; - desc = "ATtiny817"; - signature = 0x1E 0x93 0x20; - - memory "flash" - size = 0x2000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x80; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1614 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1614"; - desc = "ATtiny1614"; - signature = 0x1E 0x94 0x22; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1616 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1616"; - desc = "ATtiny1616"; - signature = 0x1E 0x94 0x21; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny1617 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t1617"; - desc = "ATtiny1617"; - signature = 0x1E 0x94 0x20; - - memory "flash" - size = 0x4000; - offset = 0x8000; - page_size = 0x40; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x20; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny3214 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t3214"; - desc = "ATtiny3214"; - signature = 0x1E 0x95 0x20; - - memory "flash" - size = 0x8000; - offset = 0x8000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny3216 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t3216"; - desc = "ATtiny3216"; - signature = 0x1E 0x95 0x21; - - memory "flash" - size = 0x8000; - offset = 0x8000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATtiny3217 -#------------------------------------------------------------ - -part parent ".avr8x_tiny" - id = "t3217"; - desc = "ATtiny3217"; - signature = 0x1E 0x95 0x22; - - memory "flash" - size = 0x8000; - offset = 0x8000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATmega3208 -#------------------------------------------------------------ - -part parent ".avr8x_mega" - id = "m3208"; - desc = "ATmega3208"; - signature = 0x1E 0x95 0x30; - - memory "flash" - size = 0x8000; - offset = 0x4000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATmega3209 -#------------------------------------------------------------ - -part parent ".avr8x_mega" - id = "m3209"; - desc = "ATmega3209"; - signature = 0x1E 0x95 0x31; - - memory "flash" - size = 0x8000; - offset = 0x4000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATmega4808 -#------------------------------------------------------------ - -part parent ".avr8x_mega" - id = "m4808"; - desc = "ATmega4808"; - signature = 0x1E 0x96 0x50; - - memory "flash" - size = 0xC000; - offset = 0x4000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; - -#------------------------------------------------------------ -# ATmega4809 -#------------------------------------------------------------ - -part parent ".avr8x_mega" - id = "m4809"; - desc = "ATmega4809"; - signature = 0x1E 0x96 0x51; - - memory "flash" - size = 0xC000; - offset = 0x4000; - page_size = 0x80; - readsize = 0x100; - ; - - memory "eeprom" - size = 0x100; - offset = 0x1400; - page_size = 0x40; - readsize = 0x100; - ; -; diff --git a/megaavr/boards.txt b/megaavr/boards.txt index 1f9ad9f..74e4904 100644 --- a/megaavr/boards.txt +++ b/megaavr/boards.txt @@ -1,7 +1,9 @@ menu.clock=Clock menu.BOD=BOD +menu.eeprom=EEPROM menu.pinout=Pinout menu.resetpin=Reset pin +menu.bootloader=Bootloader #################### @@ -9,42 +11,61 @@ menu.resetpin=Reset pin #################### # General -4809.name=Atmega4809 +4809.name=ATmega4809 4809.upload.tool=avrdude -4809.upload.maximum_size=49152 4809.upload.maximum_data_size=6144 4809.upload.speed=115200 4809.bootloader.tool=avrdude 4809.build.core=coreX-corefiles 4809.build.board=AVR_ATmega4809 4809.build.mcu=atmega4809 +4809.build.extra_flags={build.oscillator} {build.compat} # Fuses we don't need to modify in the tools menu 4809.bootloader.WDTCFG=0x00 4809.bootloader.TCD0CFG=0x00 4809.bootloader.SYSCFG1=0x06 4809.bootloader.APPEND=0x00 -4809.bootloader.BOOTEND=0x00 4809.bootloader.LOCKBIT=0xC5 # Pinouts -4809.menu.pinout.uno_wifi=Uno WiFi -4809.menu.pinout.uno_wifi.build.variant=uno-wifi -4809.menu.pinout.uno_wifi.build.extra_flags=-DUNO_WIFI_REV2_328MODE 4809.menu.pinout.48pin_standard=48 pin standard 4809.menu.pinout.48pin_standard.build.variant=48pin-standard +4809.menu.pinout.48pin_standard.build.compat= + +4809.menu.pinout.40pin_standard=40 pin standard +4809.menu.pinout.40pin_standard.build.variant=40pin-standard +4809.menu.pinout.40pin_standard.build.compat= + +4809.menu.pinout.uno_wifi=Uno WiFi +4809.menu.pinout.uno_wifi.build.variant=uno-wifi +4809.menu.pinout.uno_wifi.build.compat= + +4809.menu.pinout.nano_every=Nano Every +4809.menu.pinout.nano_every.build.variant=nano-every +4809.menu.pinout.nano_every.upload.tool=avrdude_nanoevery +4809.menu.pinout.nano_every.upload.use_1200bps_touch=true +4809.menu.pinout.nano_every.upload.protocol=jtag2updi +4809.menu.pinout.nano_every.program.extra_params=-P{serial.port} -e +4809.menu.pinout.nano_every.build.compat= + +# EEPROM +4809.menu.eeprom.keep=EEPROM retained +4809.menu.eeprom.keep.bootloader.eesave_bit=1 +4809.menu.eeprom.erase=EEPROM not retained +4809.menu.eeprom.erase.bootloader.eesave_bit=0 # Reset pin 4809.menu.resetpin.reset=Reset -4809.menu.resetpin.reset.bootloader.SYSCFG0=0xC9 +4809.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} 4809.menu.resetpin.gpio=GPIO -4809.menu.resetpin.gpio.bootloader.SYSCFG0=0xC1 +4809.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} # Brown out detection 4809.menu.BOD.2v6=BOD 2.6V 4809.menu.BOD.2v6.bootloader.BODCFG=0x54 -4809.menu.BOD.4v2=BOD 4.2V -4809.menu.BOD.4v2.bootloader.BODCFG=0xF4 +4809.menu.BOD.4v3=BOD 4.3V +4809.menu.BOD.4v3.bootloader.BODCFG=0xF4 4809.menu.BOD.4v0=BOD 4.0V 4809.menu.BOD.4v0.bootloader.BODCFG=0xD4 4809.menu.BOD.3v7=BOD 3.7V @@ -61,41 +82,186 @@ menu.resetpin=Reset pin 4809.menu.BOD.disabled.bootloader.BODCFG=0x00 # Clock -4809.menu.clock.16MHz=16 MHz -4809.menu.clock.16MHz.upload.speed=115200 -4809.menu.clock.16MHz.bootloader.OSCCFG=0x01 -4809.menu.clock.16MHz.build.f_cpu=16000000L +4809.menu.clock.internal_16MHz=Internal 16 MHz +4809.menu.clock.internal_16MHz.upload.speed=115200 +4809.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.internal_16MHz.build.oscillator= +4809.menu.clock.internal_16MHz.build.f_cpu=16000000L + +4809.menu.clock.internal_20MHz=Internal 20 MHz +4809.menu.clock.internal_20MHz.upload.speed=115200 +4809.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +4809.menu.clock.internal_20MHz.build.oscillator= +4809.menu.clock.internal_20MHz.build.f_cpu=20000000L + +4809.menu.clock.internal_10MHz=Internal 10 MHz +4809.menu.clock.internal_10MHz.upload.speed=115200 +4809.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +4809.menu.clock.internal_10MHz.build.oscillator= +4809.menu.clock.internal_10MHz.build.f_cpu=10000000L + +4809.menu.clock.internal_8MHz=Internal 8 MHz +4809.menu.clock.internal_8MHz.upload.speed=115200 +4809.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.internal_8MHz.build.oscillator= +4809.menu.clock.internal_8MHz.build.f_cpu=8000000L + +4809.menu.clock.internal_5MHz=Internal 5 MHz +4809.menu.clock.internal_5MHz.upload.speed=115200 +4809.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +4809.menu.clock.internal_5MHz.build.oscillator= +4809.menu.clock.internal_5MHz.build.f_cpu=5000000L + +4809.menu.clock.internal_4MHz=Internal 4 MHz +4809.menu.clock.internal_4MHz.upload.speed=115200 +4809.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.internal_4MHz.build.oscillator= +4809.menu.clock.internal_4MHz.build.f_cpu=4000000L + +4809.menu.clock.internal_2MHz=Internal 2 MHz +4809.menu.clock.internal_2MHz.upload.speed=115200 +4809.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.internal_2MHz.build.oscillator= +4809.menu.clock.internal_2MHz.build.f_cpu=2000000L -4809.menu.clock.20MHz=20 MHz -4809.menu.clock.20MHz.upload.speed=115200 -4809.menu.clock.20MHz.bootloader.OSCCFG=0x02 -4809.menu.clock.20MHz.build.f_cpu=20000000L +4809.menu.clock.internal_1MHz=Internal 1 MHz +4809.menu.clock.internal_1MHz.upload.speed=115200 +4809.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.internal_1MHz.build.oscillator= +4809.menu.clock.internal_1MHz.build.f_cpu=1000000L -4809.menu.clock.8MHz_div=8 MHz (divided) -4809.menu.clock.8MHz_div.upload.speed=115200 -4809.menu.clock.8MHz_div.bootloader.OSCCFG=0x01 -4809.menu.clock.8MHz_div.build.f_cpu=8000000L +4809.menu.clock.external_20MHz=External 20 MHz +4809.menu.clock.external_20MHz.upload.speed=115200 +4809.menu.clock.external_20MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_20MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_20MHz.build.f_cpu=20000000L -4809.menu.clock.4MHz_div=4 MHz (divided) -4809.menu.clock.4MHz_div.upload.speed=115200 -4809.menu.clock.4MHz_div.bootloader.OSCCFG=0x01 -4809.menu.clock.4MHz_div.build.f_cpu=4000000L +4809.menu.clock.external_16MHz=External 16 MHz +4809.menu.clock.external_16MHz.upload.speed=115200 +4809.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_16MHz.build.f_cpu=16000000L -4809.menu.clock.2MHz_div=2 MHz (divided) -4809.menu.clock.2MHz_div.upload.speed=115200 -4809.menu.clock.2MHz_div.bootloader.OSCCFG=0x01 -4809.menu.clock.2MHz_div.build.f_cpu=2000000L +4809.menu.clock.external_12MHz=External 12 MHz +4809.menu.clock.external_12MHz.upload.speed=115200 +4809.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_12MHz.build.f_cpu=12000000L -4809.menu.clock.1MHz_div=1 MHz (divided) -4809.menu.clock.1MHz_div.upload.speed=115200 -4809.menu.clock.1MHz_div.bootloader.OSCCFG=0x01 -4809.menu.clock.1MHz_div.build.f_cpu=1000000L +4809.menu.clock.external_8MHz=External 8 MHz +4809.menu.clock.external_8MHz.upload.speed=115200 +4809.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_8MHz.build.f_cpu=8000000L -# ATmega328 emulation -#4809.menu.emulation.false=No -#4809.menu.emulation.true=Yes -#4809.menu.emulation.true.build.extra_flags=-DUNO_WIFI_REV2_328MODE +4809.menu.clock.external_4MHz=External 4 MHz +4809.menu.clock.external_4MHz.upload.speed=115200 +4809.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_4MHz.build.f_cpu=4000000L +4809.menu.clock.external_1MHz=External 1 MHz +4809.menu.clock.external_1MHz.upload.speed=115200 +4809.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +4809.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4809.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +4809.menu.bootloader.no_bootloader=No bootloader +4809.menu.bootloader.no_bootloader.upload.maximum_size=49152 +4809.menu.bootloader.no_bootloader.upload.extra_params= +4809.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +4809.menu.bootloader.no_bootloader.build.export_merged_output=false +4809.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +4809.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +4809.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +4809.menu.bootloader.uart0_default.upload.maximum_size=48640 +4809.menu.bootloader.uart0_default.upload.protocol=arduino +4809.menu.bootloader.uart0_default.upload.port=UART0_DEF +4809.menu.bootloader.uart0_default.upload.extra_params= +4809.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart0_default.build.export_merged_output=true +4809.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +4809.menu.bootloader.uart0_alternative.upload.maximum_size=48640 +4809.menu.bootloader.uart0_alternative.upload.protocol=arduino +4809.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +4809.menu.bootloader.uart0_alternative.upload.extra_params= +4809.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart0_alternative.build.export_merged_output=true +4809.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +4809.menu.bootloader.uart1_default.upload.maximum_size=48640 +4809.menu.bootloader.uart1_default.upload.protocol=arduino +4809.menu.bootloader.uart1_default.upload.port=UART1_DEF +4809.menu.bootloader.uart1_default.upload.extra_params= +4809.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart1_default.build.export_merged_output=true +4809.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +4809.menu.bootloader.uart1_alternative.upload.maximum_size=48640 +4809.menu.bootloader.uart1_alternative.upload.protocol=arduino +4809.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +4809.menu.bootloader.uart1_alternative.upload.extra_params= +4809.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart1_alternative.build.export_merged_output=true +4809.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +4809.menu.bootloader.uart2_default.upload.maximum_size=48640 +4809.menu.bootloader.uart2_default.upload.protocol=arduino +4809.menu.bootloader.uart2_default.upload.port=UART2_DEF +4809.menu.bootloader.uart2_default.upload.extra_params= +4809.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart2_default.build.export_merged_output=true +4809.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +4809.menu.bootloader.uart2_alternative.upload.maximum_size=48640 +4809.menu.bootloader.uart2_alternative.upload.protocol=arduino +4809.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +4809.menu.bootloader.uart2_alternative.upload.extra_params= +4809.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart2_alternative.build.export_merged_output=true +4809.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart3_default=Optiboot (UART3 default pins) +4809.menu.bootloader.uart3_default.upload.maximum_size=48640 +4809.menu.bootloader.uart3_default.upload.protocol=arduino +4809.menu.bootloader.uart3_default.upload.port=UART3_DEF +4809.menu.bootloader.uart3_default.upload.extra_params= +4809.menu.bootloader.uart3_default.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart3_default.build.export_merged_output=true +4809.menu.bootloader.uart3_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart3_default.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart3_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4809.menu.bootloader.uart3_alternative=Optiboot (UART3 alternative pins) +4809.menu.bootloader.uart3_alternative.upload.maximum_size=48640 +4809.menu.bootloader.uart3_alternative.upload.protocol=arduino +4809.menu.bootloader.uart3_alternative.upload.port=UART3_ALT +4809.menu.bootloader.uart3_alternative.upload.extra_params= +4809.menu.bootloader.uart3_alternative.build.text_section_start=.text=0x200 +4809.menu.bootloader.uart3_alternative.build.export_merged_output=true +4809.menu.bootloader.uart3_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4809.menu.bootloader.uart3_alternative.bootloader.BOOTEND=0x02 +4809.menu.bootloader.uart3_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} #################### @@ -103,41 +269,54 @@ menu.resetpin=Reset pin #################### # General -4808.name=Atmega4808 +4808.name=ATmega4808 4808.upload.tool=avrdude -4808.upload.maximum_size=49152 4808.upload.maximum_data_size=6144 4808.upload.speed=115200 4808.bootloader.tool=avrdude 4808.build.core=coreX-corefiles 4808.build.board=AVR_ATmega4808 4808.build.mcu=atmega4808 +4808.build.extra_flags={build.oscillator} # Fuses we don't need to modify in the tools menu 4808.bootloader.WDTCFG=0x00 4808.bootloader.TCD0CFG=0x00 4808.bootloader.SYSCFG1=0x06 4808.bootloader.APPEND=0x00 -4808.bootloader.BOOTEND=0x00 4808.bootloader.LOCKBIT=0xC5 # Pinouts 4808.menu.pinout.32pin_standard=32 pin standard 4808.menu.pinout.32pin_standard.build.variant=32pin-standard + 4808.menu.pinout.28pin_standard=28 pin standard 4808.menu.pinout.28pin_standard.build.variant=28pin-standard +4808.menu.pinout.nano_4808=Nano 4808 +4808.menu.pinout.nano_4808.build.variant=nano-4808 +4808.menu.pinout.nano_4808.upload.tool=avrdude_nanoevery +4808.menu.pinout.nano_4808.upload.use_1200bps_touch=true +4808.menu.pinout.nano_4808.upload.protocol=jtag2updi +4808.menu.pinout.nano_4808.program.extra_params=-P{serial.port} -e + +# EEPROM +4808.menu.eeprom.keep=EEPROM retained +4808.menu.eeprom.keep.bootloader.eesave_bit=1 +4808.menu.eeprom.erase=EEPROM not retained +4808.menu.eeprom.erase.bootloader.eesave_bit=0 + # Reset pin 4808.menu.resetpin.reset=Reset -4808.menu.resetpin.reset.bootloader.SYSCFG0=0xC9 +4808.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} 4808.menu.resetpin.gpio=GPIO -4808.menu.resetpin.gpio.bootloader.SYSCFG0=0xC1 +4808.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} # Brown out detection 4808.menu.BOD.2v6=BOD 2.6V 4808.menu.BOD.2v6.bootloader.BODCFG=0x54 -4808.menu.BOD.4v2=BOD 4.2V -4808.menu.BOD.4v2.bootloader.BODCFG=0xF4 +4808.menu.BOD.4v3=BOD 4.3V +4808.menu.BOD.4v3.bootloader.BODCFG=0xF4 4808.menu.BOD.4v0=BOD 4.0V 4808.menu.BOD.4v0.bootloader.BODCFG=0xD4 4808.menu.BOD.3v7=BOD 3.7V @@ -154,35 +333,158 @@ menu.resetpin=Reset pin 4808.menu.BOD.disabled.bootloader.BODCFG=0x00 # Clock -4808.menu.clock.16MHz=16 MHz -4808.menu.clock.16MHz.upload.speed=115200 -4808.menu.clock.16MHz.bootloader.OSCCFG=0x01 -4808.menu.clock.16MHz.build.f_cpu=16000000L +4808.menu.clock.internal_16MHz=Internal 16 MHz +4808.menu.clock.internal_16MHz.upload.speed=115200 +4808.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.internal_16MHz.build.oscillator= +4808.menu.clock.internal_16MHz.build.f_cpu=16000000L + +4808.menu.clock.internal_20MHz=Internal 20 MHz +4808.menu.clock.internal_20MHz.upload.speed=115200 +4808.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +4808.menu.clock.internal_20MHz.build.oscillator= +4808.menu.clock.internal_20MHz.build.f_cpu=20000000L + +4808.menu.clock.internal_10MHz=Internal 10 MHz +4808.menu.clock.internal_10MHz.upload.speed=115200 +4808.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +4808.menu.clock.internal_10MHz.build.oscillator= +4808.menu.clock.internal_10MHz.build.f_cpu=10000000L -4808.menu.clock.20MHz=20 MHz -4808.menu.clock.20MHz.upload.speed=115200 -4808.menu.clock.20MHz.bootloader.OSCCFG=0x02 -4808.menu.clock.20MHz.build.f_cpu=20000000L +4808.menu.clock.internal_8MHz=Internal 8 MHz +4808.menu.clock.internal_8MHz.upload.speed=115200 +4808.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.internal_8MHz.build.oscillator= +4808.menu.clock.internal_8MHz.build.f_cpu=8000000L -4808.menu.clock.8MHz_div=8 MHz (divided) -4808.menu.clock.8MHz_div.upload.speed=115200 -4808.menu.clock.8MHz_div.bootloader.OSCCFG=0x01 -4808.menu.clock.8MHz_div.build.f_cpu=8000000L +4808.menu.clock.internal_5MHz=Internal 5 MHz +4808.menu.clock.internal_5MHz.upload.speed=115200 +4808.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +4808.menu.clock.internal_5MHz.build.oscillator= +4808.menu.clock.internal_5MHz.build.f_cpu=5000000L -4808.menu.clock.4MHz_div=4 MHz (divided) -4808.menu.clock.4MHz_div.upload.speed=115200 -4808.menu.clock.4MHz_div.bootloader.OSCCFG=0x01 -4808.menu.clock.4MHz_div.build.f_cpu=4000000L +4808.menu.clock.internal_4MHz=Internal 4 MHz +4808.menu.clock.internal_4MHz.upload.speed=115200 +4808.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.internal_4MHz.build.oscillator= +4808.menu.clock.internal_4MHz.build.f_cpu=4000000L -4808.menu.clock.2MHz_div=2 MHz (divided) -4808.menu.clock.2MHz_div.upload.speed=115200 -4808.menu.clock.2MHz_div.bootloader.OSCCFG=0x01 -4808.menu.clock.2MHz_div.build.f_cpu=2000000L +4808.menu.clock.internal_2MHz=Internal 2 MHz +4808.menu.clock.internal_2MHz.upload.speed=115200 +4808.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.internal_2MHz.build.oscillator= +4808.menu.clock.internal_2MHz.build.f_cpu=2000000L -4808.menu.clock.1MHz_div=1 MHz (divided) -4808.menu.clock.1MHz_div.upload.speed=115200 -4808.menu.clock.1MHz_div.bootloader.OSCCFG=0x01 -4808.menu.clock.1MHz_div.build.f_cpu=1000000L +4808.menu.clock.internal_1MHz=Internal 1 MHz +4808.menu.clock.internal_1MHz.upload.speed=115200 +4808.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.internal_1MHz.build.oscillator= +4808.menu.clock.internal_1MHz.build.f_cpu=1000000L + +4808.menu.clock.external_16MHz=External 16 MHz +4808.menu.clock.external_16MHz.upload.speed=115200 +4808.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4808.menu.clock.external_16MHz.build.f_cpu=16000000L + +4808.menu.clock.external_12MHz=External 12 MHz +4808.menu.clock.external_12MHz.upload.speed=115200 +4808.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4808.menu.clock.external_12MHz.build.f_cpu=12000000L + +4808.menu.clock.external_8MHz=External 8 MHz +4808.menu.clock.external_8MHz.upload.speed=115200 +4808.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4808.menu.clock.external_8MHz.build.f_cpu=8000000L + +4808.menu.clock.external_4MHz=External 4 MHz +4808.menu.clock.external_4MHz.upload.speed=115200 +4808.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4808.menu.clock.external_4MHz.build.f_cpu=4000000L + +4808.menu.clock.external_1MHz=External 1 MHz +4808.menu.clock.external_1MHz.upload.speed=115200 +4808.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +4808.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +4808.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +4808.menu.bootloader.no_bootloader=No bootloader +4808.menu.bootloader.no_bootloader.upload.maximum_size=49152 +4808.menu.bootloader.no_bootloader.upload.extra_params= +4808.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +4808.menu.bootloader.no_bootloader.build.export_merged_output=false +4808.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +4808.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +4808.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +4808.menu.bootloader.uart0_default.upload.maximum_size=48640 +4808.menu.bootloader.uart0_default.upload.protocol=arduino +4808.menu.bootloader.uart0_default.upload.port=UART0_DEF +4808.menu.bootloader.uart0_default.upload.extra_params= +4808.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart0_default.build.export_merged_output=true +4808.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4808.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +4808.menu.bootloader.uart0_alternative.upload.maximum_size=48640 +4808.menu.bootloader.uart0_alternative.upload.protocol=arduino +4808.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +4808.menu.bootloader.uart0_alternative.upload.extra_params= +4808.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart0_alternative.build.export_merged_output=true +4808.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4808.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +4808.menu.bootloader.uart1_default.upload.maximum_size=48640 +4808.menu.bootloader.uart1_default.upload.protocol=arduino +4808.menu.bootloader.uart1_default.upload.port=UART1_DEF +4808.menu.bootloader.uart1_default.upload.extra_params= +4808.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart1_default.build.export_merged_output=true +4808.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4808.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +4808.menu.bootloader.uart1_alternative.upload.maximum_size=48640 +4808.menu.bootloader.uart1_alternative.upload.protocol=arduino +4808.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +4808.menu.bootloader.uart1_alternative.upload.extra_params= +4808.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart1_alternative.build.export_merged_output=true +4808.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4808.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +4808.menu.bootloader.uart2_default.upload.maximum_size=48640 +4808.menu.bootloader.uart2_default.upload.protocol=arduino +4808.menu.bootloader.uart2_default.upload.port=UART2_DEF +4808.menu.bootloader.uart2_default.upload.extra_params= +4808.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart2_default.build.export_merged_output=true +4808.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +4808.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +4808.menu.bootloader.uart2_alternative.upload.maximum_size=48640 +4808.menu.bootloader.uart2_alternative.upload.protocol=arduino +4808.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +4808.menu.bootloader.uart2_alternative.upload.extra_params= +4808.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +4808.menu.bootloader.uart2_alternative.build.export_merged_output=true +4808.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +4808.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +4808.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} @@ -191,42 +493,48 @@ menu.resetpin=Reset pin ##################### # General -3209.name=Atmega3209 +3209.name=ATmega3209 3209.upload.tool=avrdude -3209.upload.maximum_size=32768 3209.upload.maximum_data_size=4096 3209.upload.speed=115200 3209.bootloader.tool=avrdude 3209.build.core=coreX-corefiles 3209.build.board=AVR_ATmega3209 3209.build.mcu=atmega3209 +3209.build.extra_flags={build.oscillator} {build.compat} # Fuses we don't need to modify in the tools menu 3209.bootloader.WDTCFG=0x00 3209.bootloader.TCD0CFG=0x00 3209.bootloader.SYSCFG1=0x06 3209.bootloader.APPEND=0x00 -3209.bootloader.BOOTEND=0x00 3209.bootloader.LOCKBIT=0xC5 # Pinouts -3209.menu.pinout.uno_wifi=Uno WiFi -3209.menu.pinout.uno_wifi.build.variant=uno-wifi -3209.menu.pinout.uno_wifi.build.extra_flags=-DUNO_WIFI_REV2_328MODE 3209.menu.pinout.48pin_standard=48 pin standard 3209.menu.pinout.48pin_standard.build.variant=48pin-standard +3209.menu.pinout.48pin_standard.build.compat= +3209.menu.pinout.uno_wifi=Uno WiFi +3209.menu.pinout.uno_wifi.build.variant=uno-wifi +3209.menu.pinout.uno_wifi.build.compat= + +# EEPROM +3209.menu.eeprom.keep=EEPROM retained +3209.menu.eeprom.keep.bootloader.eesave_bit=1 +3209.menu.eeprom.erase=EEPROM not retained +3209.menu.eeprom.erase.bootloader.eesave_bit=0 # Reset pin 3209.menu.resetpin.reset=Reset -3209.menu.resetpin.reset.bootloader.SYSCFG0=0xC9 +3209.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} 3209.menu.resetpin.gpio=GPIO -3209.menu.resetpin.gpio.bootloader.SYSCFG0=0xC1 +3209.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} # Brown out detection 3209.menu.BOD.2v6=BOD 2.6V 3209.menu.BOD.2v6.bootloader.BODCFG=0x54 -3209.menu.BOD.4v2=BOD 4.2V -3209.menu.BOD.4v2.bootloader.BODCFG=0xF4 +3209.menu.BOD.4v3=BOD 4.3V +3209.menu.BOD.4v3.bootloader.BODCFG=0xF4 3209.menu.BOD.4v0=BOD 4.0V 3209.menu.BOD.4v0.bootloader.BODCFG=0xD4 3209.menu.BOD.3v7=BOD 3.7V @@ -243,41 +551,180 @@ menu.resetpin=Reset pin 3209.menu.BOD.disabled.bootloader.BODCFG=0x00 # Clock -3209.menu.clock.16MHz=16 MHz -3209.menu.clock.16MHz.upload.speed=115200 -3209.menu.clock.16MHz.bootloader.OSCCFG=0x01 -3209.menu.clock.16MHz.build.f_cpu=16000000L +3209.menu.clock.internal_16MHz=Internal 16 MHz +3209.menu.clock.internal_16MHz.upload.speed=115200 +3209.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.internal_16MHz.build.oscillator= +3209.menu.clock.internal_16MHz.build.f_cpu=16000000L + +3209.menu.clock.internal_20MHz=Internal 20 MHz +3209.menu.clock.internal_20MHz.upload.speed=115200 +3209.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +3209.menu.clock.internal_20MHz.build.oscillator= +3209.menu.clock.internal_20MHz.build.f_cpu=20000000L + +3209.menu.clock.internal_10MHz=Internal 10 MHz +3209.menu.clock.internal_10MHz.upload.speed=115200 +3209.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +3209.menu.clock.internal_10MHz.build.oscillator= +3209.menu.clock.internal_10MHz.build.f_cpu=10000000L + +3209.menu.clock.internal_8MHz=Internal 8 MHz +3209.menu.clock.internal_8MHz.upload.speed=115200 +3209.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.internal_8MHz.build.oscillator= +3209.menu.clock.internal_8MHz.build.f_cpu=8000000L + +3209.menu.clock.internal_5MHz=Internal 5 MHz +3209.menu.clock.internal_5MHz.upload.speed=115200 +3209.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +3209.menu.clock.internal_5MHz.build.oscillator= +3209.menu.clock.internal_5MHz.build.f_cpu=5000000L + +3209.menu.clock.internal_4MHz=Internal 4 MHz +3209.menu.clock.internal_4MHz.upload.speed=115200 +3209.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.internal_4MHz.build.oscillator= +3209.menu.clock.internal_4MHz.build.f_cpu=4000000L + +3209.menu.clock.internal_2MHz=Internal 2 MHz +3209.menu.clock.internal_2MHz.upload.speed=115200 +3209.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.internal_2MHz.build.oscillator= +3209.menu.clock.internal_2MHz.build.f_cpu=2000000L + +3209.menu.clock.internal_1MHz=Internal 1 MHz +3209.menu.clock.internal_1MHz.upload.speed=115200 +3209.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.internal_1MHz.build.oscillator= +3209.menu.clock.internal_1MHz.build.f_cpu=1000000L + +3209.menu.clock.external_16MHz=External 16 MHz +3209.menu.clock.external_16MHz.upload.speed=115200 +3209.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3209.menu.clock.external_16MHz.build.f_cpu=16000000L + +3209.menu.clock.external_12MHz=External 12 MHz +3209.menu.clock.external_12MHz.upload.speed=115200 +3209.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3209.menu.clock.external_12MHz.build.f_cpu=12000000L + +3209.menu.clock.external_8MHz=External 8 MHz +3209.menu.clock.external_8MHz.upload.speed=115200 +3209.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3209.menu.clock.external_8MHz.build.f_cpu=8000000L + +3209.menu.clock.external_4MHz=External 4 MHz +3209.menu.clock.external_4MHz.upload.speed=115200 +3209.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3209.menu.clock.external_4MHz.build.f_cpu=4000000L -3209.menu.clock.20MHz=20 MHz -3209.menu.clock.20MHz.upload.speed=115200 -3209.menu.clock.20MHz.bootloader.OSCCFG=0x02 -3209.menu.clock.20MHz.build.f_cpu=20000000L +3209.menu.clock.external_1MHz=External 1 MHz +3209.menu.clock.external_1MHz.upload.speed=115200 +3209.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +3209.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3209.menu.clock.external_1MHz.build.f_cpu=1000000L -3209.menu.clock.8MHz_div=8 MHz (divided) -3209.menu.clock.8MHz_div.upload.speed=115200 -3209.menu.clock.8MHz_div.bootloader.OSCCFG=0x01 -3209.menu.clock.8MHz_div.build.f_cpu=8000000L +# Bootloader +3209.menu.bootloader.no_bootloader=No bootloader +3209.menu.bootloader.no_bootloader.upload.maximum_size=32768 +3209.menu.bootloader.no_bootloader.upload.extra_params= +3209.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +3209.menu.bootloader.no_bootloader.build.export_merged_output=false +3209.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +3209.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 -3209.menu.clock.4MHz_div=4 MHz (divided) -3209.menu.clock.4MHz_div.upload.speed=115200 -3209.menu.clock.4MHz_div.bootloader.OSCCFG=0x01 -3209.menu.clock.4MHz_div.build.f_cpu=4000000L +3209.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +3209.menu.bootloader.uart0_default.upload.maximum_size=32256 +3209.menu.bootloader.uart0_default.upload.protocol=arduino +3209.menu.bootloader.uart0_default.upload.port=UART0_DEF +3209.menu.bootloader.uart0_default.upload.extra_params= +3209.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart0_default.build.export_merged_output=true +3209.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} -3209.menu.clock.2MHz_div=2 MHz (divided) -3209.menu.clock.2MHz_div.upload.speed=115200 -3209.menu.clock.2MHz_div.bootloader.OSCCFG=0x01 -3209.menu.clock.2MHz_div.build.f_cpu=2000000L +3209.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +3209.menu.bootloader.uart0_alternative.upload.maximum_size=32256 +3209.menu.bootloader.uart0_alternative.upload.protocol=arduino +3209.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +3209.menu.bootloader.uart0_alternative.upload.extra_params= +3209.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart0_alternative.build.export_merged_output=true +3209.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} -3209.menu.clock.1MHz_div=1 MHz (divided) -3209.menu.clock.1MHz_div.upload.speed=115200 -3209.menu.clock.1MHz_div.bootloader.OSCCFG=0x01 -3209.menu.clock.1MHz_div.build.f_cpu=1000000L +3209.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +3209.menu.bootloader.uart1_default.upload.maximum_size=32256 +3209.menu.bootloader.uart1_default.upload.protocol=arduino +3209.menu.bootloader.uart1_default.upload.port=UART1_DEF +3209.menu.bootloader.uart1_default.upload.extra_params= +3209.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart1_default.build.export_merged_output=true +3209.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} -# ATmega328 emulation -3209.menu.emulation.false=No -3209.menu.emulation.true=Yes -3209.menu.emulation.true.build.extra_flags=-DUNO_WIFI_REV2_328MODE +3209.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +3209.menu.bootloader.uart1_alternative.upload.maximum_size=32256 +3209.menu.bootloader.uart1_alternative.upload.protocol=arduino +3209.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +3209.menu.bootloader.uart1_alternative.upload.extra_params= +3209.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart1_alternative.build.export_merged_output=true +3209.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +3209.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +3209.menu.bootloader.uart2_default.upload.maximum_size=32256 +3209.menu.bootloader.uart2_default.upload.protocol=arduino +3209.menu.bootloader.uart2_default.upload.port=UART2_DEF +3209.menu.bootloader.uart2_default.upload.extra_params= +3209.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart2_default.build.export_merged_output=true +3209.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3209.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +3209.menu.bootloader.uart2_alternative.upload.maximum_size=32256 +3209.menu.bootloader.uart2_alternative.upload.protocol=arduino +3209.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +3209.menu.bootloader.uart2_alternative.upload.extra_params= +3209.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart2_alternative.build.export_merged_output=true +3209.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3209.menu.bootloader.uart3_default=Optiboot (UART3 default pins) +3209.menu.bootloader.uart3_default.upload.maximum_size=32256 +3209.menu.bootloader.uart3_default.upload.protocol=arduino +3209.menu.bootloader.uart3_default.upload.port=UART3_DEF +3209.menu.bootloader.uart3_default.upload.extra_params= +3209.menu.bootloader.uart3_default.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart3_default.build.export_merged_output=true +3209.menu.bootloader.uart3_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart3_default.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart3_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3209.menu.bootloader.uart3_alternative=Optiboot (UART3 alternative pins) +3209.menu.bootloader.uart3_alternative.upload.maximum_size=32256 +3209.menu.bootloader.uart3_alternative.upload.protocol=arduino +3209.menu.bootloader.uart3_alternative.upload.port=UART3_ALT +3209.menu.bootloader.uart3_alternative.upload.extra_params= +3209.menu.bootloader.uart3_alternative.build.text_section_start=.text=0x200 +3209.menu.bootloader.uart3_alternative.build.export_merged_output=true +3209.menu.bootloader.uart3_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3209.menu.bootloader.uart3_alternative.bootloader.BOOTEND=0x02 +3209.menu.bootloader.uart3_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} #################### @@ -285,22 +732,21 @@ menu.resetpin=Reset pin #################### # General -3208.name=Atmega3208 +3208.name=ATmega3208 3208.upload.tool=avrdude -3208.upload.maximum_size=32768 3208.upload.maximum_data_size=4096 3208.upload.speed=115200 3208.bootloader.tool=avrdude 3208.build.core=coreX-corefiles 3208.build.board=AVR_ATmega3208 3208.build.mcu=atmega3208 +3208.build.extra_flags={build.oscillator} # Fuses we don't need to modify in the tools menu 3208.bootloader.WDTCFG=0x00 3208.bootloader.TCD0CFG=0x00 3208.bootloader.SYSCFG1=0x06 3208.bootloader.APPEND=0x00 -3208.bootloader.BOOTEND=0x00 3208.bootloader.LOCKBIT=0xC5 # Pinouts @@ -309,17 +755,23 @@ menu.resetpin=Reset pin 3208.menu.pinout.28pin_standard=28 pin standard 3208.menu.pinout.28pin_standard.build.variant=28pin-standard +# EEPROM +3208.menu.eeprom.keep=EEPROM retained +3208.menu.eeprom.keep.bootloader.eesave_bit=1 +3208.menu.eeprom.erase=EEPROM not retained +3208.menu.eeprom.erase.bootloader.eesave_bit=0 + # Reset pin 3208.menu.resetpin.reset=Reset -3208.menu.resetpin.reset.bootloader.SYSCFG0=0xC9 +3208.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} 3208.menu.resetpin.gpio=GPIO -3208.menu.resetpin.gpio.bootloader.SYSCFG0=0xC1 +3208.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} # Brown out detection 3208.menu.BOD.2v6=BOD 2.6V 3208.menu.BOD.2v6.bootloader.BODCFG=0x54 -3208.menu.BOD.4v2=BOD 4.2V -3208.menu.BOD.4v2.bootloader.BODCFG=0xF4 +3208.menu.BOD.4v3=BOD 4.3V +3208.menu.BOD.4v3.bootloader.BODCFG=0xF4 3208.menu.BOD.4v0=BOD 4.0V 3208.menu.BOD.4v0.bootloader.BODCFG=0xD4 3208.menu.BOD.3v7=BOD 3.7V @@ -336,33 +788,1063 @@ menu.resetpin=Reset pin 3208.menu.BOD.disabled.bootloader.BODCFG=0x00 # Clock -3208.menu.clock.16MHz=16 MHz -3208.menu.clock.16MHz.upload.speed=115200 -3208.menu.clock.16MHz.bootloader.OSCCFG=0x01 -3208.menu.clock.16MHz.build.f_cpu=16000000L - -3208.menu.clock.20MHz=20 MHz -3208.menu.clock.20MHz.upload.speed=115200 -3208.menu.clock.20MHz.bootloader.OSCCFG=0x02 -3208.menu.clock.20MHz.build.f_cpu=20000000L - -3208.menu.clock.8MHz_div=8 MHz (divided) -3208.menu.clock.8MHz_div.upload.speed=115200 -3208.menu.clock.8MHz_div.bootloader.OSCCFG=0x01 -3208.menu.clock.8MHz_div.build.f_cpu=8000000L - -3208.menu.clock.4MHz_div=4 MHz (divided) -3208.menu.clock.4MHz_div.upload.speed=115200 -3208.menu.clock.4MHz_div.bootloader.OSCCFG=0x01 -3208.menu.clock.4MHz_div.build.f_cpu=4000000L - -3208.menu.clock.2MHz_div=2 MHz (divided) -3208.menu.clock.2MHz_div.upload.speed=115200 -3208.menu.clock.2MHz_div.bootloader.OSCCFG=0x01 -3208.menu.clock.2MHz_div.build.f_cpu=2000000L - -3208.menu.clock.1MHz_div=1 MHz (divided) -3208.menu.clock.1MHz_div.upload.speed=115200 -3208.menu.clock.1MHz_div.bootloader.OSCCFG=0x01 -3208.menu.clock.1MHz_div.build.f_cpu=1000000L +3208.menu.clock.internal_16MHz=Internal 16 MHz +3208.menu.clock.internal_16MHz.upload.speed=115200 +3208.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.internal_16MHz.build.oscillator= +3208.menu.clock.internal_16MHz.build.f_cpu=16000000L + +3208.menu.clock.internal_20MHz=Internal 20 MHz +3208.menu.clock.internal_20MHz.upload.speed=115200 +3208.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +3208.menu.clock.internal_20MHz.build.oscillator= +3208.menu.clock.internal_20MHz.build.f_cpu=20000000L + +3208.menu.clock.internal_10MHz=Internal 10 MHz +3208.menu.clock.internal_10MHz.upload.speed=115200 +3208.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +3208.menu.clock.internal_10MHz.build.oscillator= +3208.menu.clock.internal_10MHz.build.f_cpu=10000000L + +3208.menu.clock.internal_8MHz=Internal 8 MHz +3208.menu.clock.internal_8MHz.upload.speed=115200 +3208.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.internal_8MHz.build.oscillator= +3208.menu.clock.internal_8MHz.build.f_cpu=8000000L + +3208.menu.clock.internal_5MHz=Internal 5 MHz +3208.menu.clock.internal_5MHz.upload.speed=115200 +3208.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +3208.menu.clock.internal_5MHz.build.oscillator= +3208.menu.clock.internal_5MHz.build.f_cpu=5000000L + +3208.menu.clock.internal_4MHz=Internal 4 MHz +3208.menu.clock.internal_4MHz.upload.speed=115200 +3208.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.internal_4MHz.build.oscillator= +3208.menu.clock.internal_4MHz.build.f_cpu=4000000L + +3208.menu.clock.internal_2MHz=Internal 2 MHz +3208.menu.clock.internal_2MHz.upload.speed=115200 +3208.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.internal_2MHz.build.oscillator= +3208.menu.clock.internal_2MHz.build.f_cpu=2000000L + +3208.menu.clock.internal_1MHz=Internal 1 MHz +3208.menu.clock.internal_1MHz.upload.speed=115200 +3208.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.internal_1MHz.build.oscillator= +3208.menu.clock.internal_1MHz.build.f_cpu=1000000L + +3208.menu.clock.external_16MHz=External 16 MHz +3208.menu.clock.external_16MHz.upload.speed=115200 +3208.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3208.menu.clock.external_16MHz.build.f_cpu=16000000L + +3208.menu.clock.external_12MHz=External 12 MHz +3208.menu.clock.external_12MHz.upload.speed=115200 +3208.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3208.menu.clock.external_12MHz.build.f_cpu=12000000L + +3208.menu.clock.external_8MHz=External 8 MHz +3208.menu.clock.external_8MHz.upload.speed=115200 +3208.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3208.menu.clock.external_8MHz.build.f_cpu=8000000L + +3208.menu.clock.external_4MHz=External 4 MHz +3208.menu.clock.external_4MHz.upload.speed=115200 +3208.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3208.menu.clock.external_4MHz.build.f_cpu=4000000L + +3208.menu.clock.external_1MHz=External 1 MHz +3208.menu.clock.external_1MHz.upload.speed=115200 +3208.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +3208.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +3208.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +3208.menu.bootloader.no_bootloader=No bootloader +3208.menu.bootloader.no_bootloader.upload.maximum_size=32768 +3208.menu.bootloader.no_bootloader.upload.extra_params= +3208.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +3208.menu.bootloader.no_bootloader.build.export_merged_output=false +3208.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +3208.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +3208.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +3208.menu.bootloader.uart0_default.upload.maximum_size=32256 +3208.menu.bootloader.uart0_default.upload.protocol=arduino +3208.menu.bootloader.uart0_default.upload.port=UART0_DEF +3208.menu.bootloader.uart0_default.upload.extra_params= +3208.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart0_default.build.export_merged_output=true +3208.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3208.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +3208.menu.bootloader.uart0_alternative.upload.maximum_size=32256 +3208.menu.bootloader.uart0_alternative.upload.protocol=arduino +3208.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +3208.menu.bootloader.uart0_alternative.upload.extra_params= +3208.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart0_alternative.build.export_merged_output=true +3208.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3208.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +3208.menu.bootloader.uart1_default.upload.maximum_size=32256 +3208.menu.bootloader.uart1_default.upload.protocol=arduino +3208.menu.bootloader.uart1_default.upload.port=UART1_DEF +3208.menu.bootloader.uart1_default.upload.extra_params= +3208.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart1_default.build.export_merged_output=true +3208.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3208.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +3208.menu.bootloader.uart1_alternative.upload.maximum_size=32256 +3208.menu.bootloader.uart1_alternative.upload.protocol=arduino +3208.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +3208.menu.bootloader.uart1_alternative.upload.extra_params= +3208.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart1_alternative.build.export_merged_output=true +3208.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3208.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +3208.menu.bootloader.uart2_default.upload.maximum_size=32256 +3208.menu.bootloader.uart2_default.upload.protocol=arduino +3208.menu.bootloader.uart2_default.upload.port=UART2_DEF +3208.menu.bootloader.uart2_default.upload.extra_params= +3208.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart2_default.build.export_merged_output=true +3208.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +3208.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +3208.menu.bootloader.uart2_alternative.upload.maximum_size=32256 +3208.menu.bootloader.uart2_alternative.upload.protocol=arduino +3208.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +3208.menu.bootloader.uart2_alternative.upload.extra_params= +3208.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +3208.menu.bootloader.uart2_alternative.build.export_merged_output=true +3208.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +3208.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +3208.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + + +##################### +#### ATmega1609 #### +##################### + +# General +1609.name=ATmega1609 +1609.upload.tool=avrdude +1609.upload.maximum_data_size=2048 +1609.upload.speed=115200 +1609.bootloader.tool=avrdude +1609.build.core=coreX-corefiles +1609.build.board=AVR_ATmega1609 +1609.build.mcu=atmega1609 +1609.build.extra_flags={build.oscillator} {build.compat} + +# Fuses we don't need to modify in the tools menu +1609.bootloader.WDTCFG=0x00 +1609.bootloader.TCD0CFG=0x00 +1609.bootloader.SYSCFG1=0x06 +1609.bootloader.APPEND=0x00 +1609.bootloader.LOCKBIT=0xC5 + +# Pinouts +1609.menu.pinout.48pin_standard=48 pin standard +1609.menu.pinout.48pin_standard.build.variant=48pin-standard +1609.menu.pinout.48pin_standard.build.compat= +1609.menu.pinout.uno_wifi=Uno WiFi +1609.menu.pinout.uno_wifi.build.variant=uno-wifi +1609.menu.pinout.uno_wifi.build.compat= + +# EEPROM +1609.menu.eeprom.keep=EEPROM retained +1609.menu.eeprom.keep.bootloader.eesave_bit=1 +1609.menu.eeprom.erase=EEPROM not retained +1609.menu.eeprom.erase.bootloader.eesave_bit=0 + +# Reset pin +1609.menu.resetpin.reset=Reset +1609.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +1609.menu.resetpin.gpio=GPIO +1609.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} + +# Brown out detection +1609.menu.BOD.2v6=BOD 2.6V +1609.menu.BOD.2v6.bootloader.BODCFG=0x54 +1609.menu.BOD.4v3=BOD 4.3V +1609.menu.BOD.4v3.bootloader.BODCFG=0xF4 +1609.menu.BOD.4v0=BOD 4.0V +1609.menu.BOD.4v0.bootloader.BODCFG=0xD4 +1609.menu.BOD.3v7=BOD 3.7V +1609.menu.BOD.3v7.bootloader.BODCFG=0xB4 +1609.menu.BOD.3v3=BOD 3.3V +1609.menu.BOD.3v3.bootloader.BODCFG=0x94 +1609.menu.BOD.2v9=BOD 2.9V +1609.menu.BOD.2v9.bootloader.BODCFG=0x74 +1609.menu.BOD.2v1=BOD 2.1V +1609.menu.BOD.2v1.bootloader.BODCFG=0x34 +1609.menu.BOD.1v8=BOD 1.8V +1609.menu.BOD.1v8.bootloader.BODCFG=0x14 +1609.menu.BOD.disabled=BOD disabled +1609.menu.BOD.disabled.bootloader.BODCFG=0x00 + +# Clock +1609.menu.clock.internal_16MHz=Internal 16 MHz +1609.menu.clock.internal_16MHz.upload.speed=115200 +1609.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.internal_16MHz.build.oscillator= +1609.menu.clock.internal_16MHz.build.f_cpu=16000000L + +1609.menu.clock.internal_20MHz=Internal 20 MHz +1609.menu.clock.internal_20MHz.upload.speed=115200 +1609.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +1609.menu.clock.internal_20MHz.build.oscillator= +1609.menu.clock.internal_20MHz.build.f_cpu=20000000L + +1609.menu.clock.internal_10MHz=Internal 10 MHz +1609.menu.clock.internal_10MHz.upload.speed=115200 +1609.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +1609.menu.clock.internal_10MHz.build.oscillator= +1609.menu.clock.internal_10MHz.build.f_cpu=10000000L + +1609.menu.clock.internal_8MHz=Internal 8 MHz +1609.menu.clock.internal_8MHz.upload.speed=115200 +1609.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.internal_8MHz.build.oscillator= +1609.menu.clock.internal_8MHz.build.f_cpu=8000000L + +1609.menu.clock.internal_5MHz=Internal 5 MHz +1609.menu.clock.internal_5MHz.upload.speed=115200 +1609.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +1609.menu.clock.internal_5MHz.build.oscillator= +1609.menu.clock.internal_5MHz.build.f_cpu=5000000L + +1609.menu.clock.internal_4MHz=Internal 4 MHz +1609.menu.clock.internal_4MHz.upload.speed=115200 +1609.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.internal_4MHz.build.oscillator= +1609.menu.clock.internal_4MHz.build.f_cpu=4000000L + +1609.menu.clock.internal_2MHz=Internal 2 MHz +1609.menu.clock.internal_2MHz.upload.speed=115200 +1609.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.internal_2MHz.build.oscillator= +1609.menu.clock.internal_2MHz.build.f_cpu=2000000L + +1609.menu.clock.internal_1MHz=Internal 1 MHz +1609.menu.clock.internal_1MHz.upload.speed=115200 +1609.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.internal_1MHz.build.oscillator= +1609.menu.clock.internal_1MHz.build.f_cpu=1000000L + +1609.menu.clock.external_16MHz=External 16 MHz +1609.menu.clock.external_16MHz.upload.speed=115200 +1609.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1609.menu.clock.external_16MHz.build.f_cpu=16000000L + +1609.menu.clock.external_12MHz=External 12 MHz +1609.menu.clock.external_12MHz.upload.speed=115200 +1609.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1609.menu.clock.external_12MHz.build.f_cpu=12000000L + +1609.menu.clock.external_8MHz=External 8 MHz +1609.menu.clock.external_8MHz.upload.speed=115200 +1609.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1609.menu.clock.external_8MHz.build.f_cpu=8000000L + +1609.menu.clock.external_4MHz=External 4 MHz +1609.menu.clock.external_4MHz.upload.speed=115200 +1609.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1609.menu.clock.external_4MHz.build.f_cpu=4000000L + +1609.menu.clock.external_1MHz=External 1 MHz +1609.menu.clock.external_1MHz.upload.speed=115200 +1609.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +1609.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1609.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +1609.menu.bootloader.no_bootloader=No bootloader +1609.menu.bootloader.no_bootloader.upload.maximum_size=16384 +1609.menu.bootloader.no_bootloader.upload.extra_params= +1609.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +1609.menu.bootloader.no_bootloader.build.export_merged_output=false +1609.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +1609.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +1609.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +1609.menu.bootloader.uart0_default.upload.maximum_size=15872 +1609.menu.bootloader.uart0_default.upload.protocol=arduino +1609.menu.bootloader.uart0_default.upload.port=UART0_DEF +1609.menu.bootloader.uart0_default.upload.extra_params= +1609.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart0_default.build.export_merged_output=true +1609.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +1609.menu.bootloader.uart0_alternative.upload.maximum_size=15872 +1609.menu.bootloader.uart0_alternative.upload.protocol=arduino +1609.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +1609.menu.bootloader.uart0_alternative.upload.extra_params= +1609.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart0_alternative.build.export_merged_output=true +1609.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +1609.menu.bootloader.uart1_default.upload.maximum_size=15872 +1609.menu.bootloader.uart1_default.upload.protocol=arduino +1609.menu.bootloader.uart1_default.upload.port=UART1_DEF +1609.menu.bootloader.uart1_default.upload.extra_params= +1609.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart1_default.build.export_merged_output=true +1609.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +1609.menu.bootloader.uart1_alternative.upload.maximum_size=15872 +1609.menu.bootloader.uart1_alternative.upload.protocol=arduino +1609.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +1609.menu.bootloader.uart1_alternative.upload.extra_params= +1609.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart1_alternative.build.export_merged_output=true +1609.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +1609.menu.bootloader.uart2_default.upload.maximum_size=15872 +1609.menu.bootloader.uart2_default.upload.protocol=arduino +1609.menu.bootloader.uart2_default.upload.port=UART2_DEF +1609.menu.bootloader.uart2_default.upload.extra_params= +1609.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart2_default.build.export_merged_output=true +1609.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +1609.menu.bootloader.uart2_alternative.upload.maximum_size=15872 +1609.menu.bootloader.uart2_alternative.upload.protocol=arduino +1609.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +1609.menu.bootloader.uart2_alternative.upload.extra_params= +1609.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart2_alternative.build.export_merged_output=true +1609.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart3_default=Optiboot (UART3 default pins) +1609.menu.bootloader.uart3_default.upload.maximum_size=15872 +1609.menu.bootloader.uart3_default.upload.protocol=arduino +1609.menu.bootloader.uart3_default.upload.port=UART3_DEF +1609.menu.bootloader.uart3_default.upload.extra_params= +1609.menu.bootloader.uart3_default.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart3_default.build.export_merged_output=true +1609.menu.bootloader.uart3_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart3_default.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart3_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1609.menu.bootloader.uart3_alternative=Optiboot (UART3 alternative pins) +1609.menu.bootloader.uart3_alternative.upload.maximum_size=15872 +1609.menu.bootloader.uart3_alternative.upload.protocol=arduino +1609.menu.bootloader.uart3_alternative.upload.port=UART3_ALT +1609.menu.bootloader.uart3_alternative.upload.extra_params= +1609.menu.bootloader.uart3_alternative.build.text_section_start=.text=0x200 +1609.menu.bootloader.uart3_alternative.build.export_merged_output=true +1609.menu.bootloader.uart3_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1609.menu.bootloader.uart3_alternative.bootloader.BOOTEND=0x02 +1609.menu.bootloader.uart3_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + + +#################### +#### ATmega1608 #### +#################### + +# General +1608.name=ATmega1608 +1608.upload.tool=avrdude +1608.upload.maximum_data_size=2048 +1608.upload.speed=115200 +1608.bootloader.tool=avrdude +1608.build.core=coreX-corefiles +1608.build.board=AVR_ATmega1608 +1608.build.mcu=atmega1608 +1608.build.extra_flags={build.oscillator} + +# Fuses we don't need to modify in the tools menu +1608.bootloader.WDTCFG=0x00 +1608.bootloader.TCD0CFG=0x00 +1608.bootloader.SYSCFG1=0x06 +1608.bootloader.APPEND=0x00 +1608.bootloader.LOCKBIT=0xC5 + +# Pinouts +1608.menu.pinout.32pin_standard=32 pin standard +1608.menu.pinout.32pin_standard.build.variant=32pin-standard +1608.menu.pinout.28pin_standard=28 pin standard +1608.menu.pinout.28pin_standard.build.variant=28pin-standard + +# EEPROM +1608.menu.eeprom.keep=EEPROM retained +1608.menu.eeprom.keep.bootloader.eesave_bit=1 +1608.menu.eeprom.erase=EEPROM not retained +1608.menu.eeprom.erase.bootloader.eesave_bit=0 + +# Reset pin +1608.menu.resetpin.reset=Reset +1608.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +1608.menu.resetpin.gpio=GPIO +1608.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} + +# Brown out detection +1608.menu.BOD.2v6=BOD 2.6V +1608.menu.BOD.2v6.bootloader.BODCFG=0x54 +1608.menu.BOD.4v3=BOD 4.3V +1608.menu.BOD.4v3.bootloader.BODCFG=0xF4 +1608.menu.BOD.4v0=BOD 4.0V +1608.menu.BOD.4v0.bootloader.BODCFG=0xD4 +1608.menu.BOD.3v7=BOD 3.7V +1608.menu.BOD.3v7.bootloader.BODCFG=0xB4 +1608.menu.BOD.3v3=BOD 3.3V +1608.menu.BOD.3v3.bootloader.BODCFG=0x94 +1608.menu.BOD.2v9=BOD 2.9V +1608.menu.BOD.2v9.bootloader.BODCFG=0x74 +1608.menu.BOD.2v1=BOD 2.1V +1608.menu.BOD.2v1.bootloader.BODCFG=0x34 +1608.menu.BOD.1v8=BOD 1.8V +1608.menu.BOD.1v8.bootloader.BODCFG=0x14 +1608.menu.BOD.disabled=BOD disabled +1608.menu.BOD.disabled.bootloader.BODCFG=0x00 + +# Clock +1608.menu.clock.internal_16MHz=Internal 16 MHz +1608.menu.clock.internal_16MHz.upload.speed=115200 +1608.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.internal_16MHz.build.oscillator= +1608.menu.clock.internal_16MHz.build.f_cpu=16000000L + +1608.menu.clock.internal_20MHz=Internal 20 MHz +1608.menu.clock.internal_20MHz.upload.speed=115200 +1608.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +1608.menu.clock.internal_20MHz.build.oscillator= +1608.menu.clock.internal_20MHz.build.f_cpu=20000000L + +1608.menu.clock.internal_10MHz=Internal 10 MHz +1608.menu.clock.internal_10MHz.upload.speed=115200 +1608.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +1608.menu.clock.internal_10MHz.build.oscillator= +1608.menu.clock.internal_10MHz.build.f_cpu=10000000L + +1608.menu.clock.internal_8MHz=Internal 8 MHz +1608.menu.clock.internal_8MHz.upload.speed=115200 +1608.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.internal_8MHz.build.oscillator= +1608.menu.clock.internal_8MHz.build.f_cpu=8000000L + +1608.menu.clock.internal_5MHz=Internal 5 MHz +1608.menu.clock.internal_5MHz.upload.speed=115200 +1608.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +1608.menu.clock.internal_5MHz.build.oscillator= +1608.menu.clock.internal_5MHz.build.f_cpu=5000000L + +1608.menu.clock.internal_4MHz=Internal 4 MHz +1608.menu.clock.internal_4MHz.upload.speed=115200 +1608.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.internal_4MHz.build.oscillator= +1608.menu.clock.internal_4MHz.build.f_cpu=4000000L + +1608.menu.clock.internal_2MHz=Internal 2 MHz +1608.menu.clock.internal_2MHz.upload.speed=115200 +1608.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.internal_2MHz.build.oscillator= +1608.menu.clock.internal_2MHz.build.f_cpu=2000000L + +1608.menu.clock.internal_1MHz=Internal 1 MHz +1608.menu.clock.internal_1MHz.upload.speed=115200 +1608.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.internal_1MHz.build.oscillator= +1608.menu.clock.internal_1MHz.build.f_cpu=1000000L + +1608.menu.clock.external_16MHz=External 16 MHz +1608.menu.clock.external_16MHz.upload.speed=115200 +1608.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1608.menu.clock.external_16MHz.build.f_cpu=16000000L + +1608.menu.clock.external_12MHz=External 12 MHz +1608.menu.clock.external_12MHz.upload.speed=115200 +1608.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1608.menu.clock.external_12MHz.build.f_cpu=12000000L + +1608.menu.clock.external_8MHz=External 8 MHz +1608.menu.clock.external_8MHz.upload.speed=115200 +1608.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1608.menu.clock.external_8MHz.build.f_cpu=8000000L + +1608.menu.clock.external_4MHz=External 4 MHz +1608.menu.clock.external_4MHz.upload.speed=115200 +1608.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1608.menu.clock.external_4MHz.build.f_cpu=4000000L + +1608.menu.clock.external_1MHz=External 1 MHz +1608.menu.clock.external_1MHz.upload.speed=115200 +1608.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +1608.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +1608.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +1608.menu.bootloader.no_bootloader=No bootloader +1608.menu.bootloader.no_bootloader.upload.maximum_size=16384 +1608.menu.bootloader.no_bootloader.upload.extra_params= +1608.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +1608.menu.bootloader.no_bootloader.build.export_merged_output=false +1608.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +1608.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +1608.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +1608.menu.bootloader.uart0_default.upload.maximum_size=15872 +1608.menu.bootloader.uart0_default.upload.protocol=arduino +1608.menu.bootloader.uart0_default.upload.port=UART0_DEF +1608.menu.bootloader.uart0_default.upload.extra_params= +1608.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart0_default.build.export_merged_output=true +1608.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1608.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +1608.menu.bootloader.uart0_alternative.upload.maximum_size=15872 +1608.menu.bootloader.uart0_alternative.upload.protocol=arduino +1608.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +1608.menu.bootloader.uart0_alternative.upload.extra_params= +1608.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart0_alternative.build.export_merged_output=true +1608.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1608.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +1608.menu.bootloader.uart1_default.upload.maximum_size=15872 +1608.menu.bootloader.uart1_default.upload.protocol=arduino +1608.menu.bootloader.uart1_default.upload.port=UART1_DEF +1608.menu.bootloader.uart1_default.upload.extra_params= +1608.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart1_default.build.export_merged_output=true +1608.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1608.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +1608.menu.bootloader.uart1_alternative.upload.maximum_size=15872 +1608.menu.bootloader.uart1_alternative.upload.protocol=arduino +1608.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +1608.menu.bootloader.uart1_alternative.upload.extra_params= +1608.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart1_alternative.build.export_merged_output=true +1608.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1608.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +1608.menu.bootloader.uart2_default.upload.maximum_size=15872 +1608.menu.bootloader.uart2_default.upload.protocol=arduino +1608.menu.bootloader.uart2_default.upload.port=UART2_DEF +1608.menu.bootloader.uart2_default.upload.extra_params= +1608.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart2_default.build.export_merged_output=true +1608.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +1608.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +1608.menu.bootloader.uart2_alternative.upload.maximum_size=15872 +1608.menu.bootloader.uart2_alternative.upload.protocol=arduino +1608.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +1608.menu.bootloader.uart2_alternative.upload.extra_params= +1608.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +1608.menu.bootloader.uart2_alternative.build.export_merged_output=true +1608.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +1608.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +1608.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + + +################### +#### ATmega809 #### +################### + +# General +809.name=ATmega809 +809.upload.tool=avrdude +809.upload.maximum_data_size=1024 +809.upload.speed=115200 +809.bootloader.tool=avrdude +809.build.core=coreX-corefiles +809.build.board=AVR_ATmega809 +809.build.mcu=atmega809 +809.build.extra_flags={build.oscillator} {build.compat} + +# Fuses we don't need to modify in the tools menu +809.bootloader.WDTCFG=0x00 +809.bootloader.TCD0CFG=0x00 +809.bootloader.SYSCFG1=0x06 +809.bootloader.APPEND=0x00 +809.bootloader.LOCKBIT=0xC5 + +# Pinouts +809.menu.pinout.48pin_standard=48 pin standard +809.menu.pinout.48pin_standard.build.variant=48pin-standard +809.menu.pinout.48pin_standard.build.compat= +809.menu.pinout.uno_wifi=Uno WiFi +809.menu.pinout.uno_wifi.build.variant=uno-wifi +809.menu.pinout.uno_wifi.build.compat= + +# EEPROM +809.menu.eeprom.keep=EEPROM retained +809.menu.eeprom.keep.bootloader.eesave_bit=1 +809.menu.eeprom.erase=EEPROM not retained +809.menu.eeprom.erase.bootloader.eesave_bit=0 + +# Reset pin +809.menu.resetpin.reset=Reset +809.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +809.menu.resetpin.gpio=GPIO +809.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} + +# Brown out detection +809.menu.BOD.2v6=BOD 2.6V +809.menu.BOD.2v6.bootloader.BODCFG=0x54 +809.menu.BOD.4v3=BOD 4.3V +809.menu.BOD.4v3.bootloader.BODCFG=0xF4 +809.menu.BOD.4v0=BOD 4.0V +809.menu.BOD.4v0.bootloader.BODCFG=0xD4 +809.menu.BOD.3v7=BOD 3.7V +809.menu.BOD.3v7.bootloader.BODCFG=0xB4 +809.menu.BOD.3v3=BOD 3.3V +809.menu.BOD.3v3.bootloader.BODCFG=0x94 +809.menu.BOD.2v9=BOD 2.9V +809.menu.BOD.2v9.bootloader.BODCFG=0x74 +809.menu.BOD.2v1=BOD 2.1V +809.menu.BOD.2v1.bootloader.BODCFG=0x34 +809.menu.BOD.1v8=BOD 1.8V +809.menu.BOD.1v8.bootloader.BODCFG=0x14 +809.menu.BOD.disabled=BOD disabled +809.menu.BOD.disabled.bootloader.BODCFG=0x00 + +# Clock +809.menu.clock.internal_16MHz=Internal 16 MHz +809.menu.clock.internal_16MHz.upload.speed=115200 +809.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +809.menu.clock.internal_16MHz.build.oscillator= +809.menu.clock.internal_16MHz.build.f_cpu=16000000L + +809.menu.clock.internal_20MHz=Internal 20 MHz +809.menu.clock.internal_20MHz.upload.speed=115200 +809.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +809.menu.clock.internal_20MHz.build.oscillator= +809.menu.clock.internal_20MHz.build.f_cpu=20000000L + +809.menu.clock.internal_10MHz=Internal 10 MHz +809.menu.clock.internal_10MHz.upload.speed=115200 +809.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +809.menu.clock.internal_10MHz.build.oscillator= +809.menu.clock.internal_10MHz.build.f_cpu=10000000L + +809.menu.clock.internal_8MHz=Internal 8 MHz +809.menu.clock.internal_8MHz.upload.speed=115200 +809.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +809.menu.clock.internal_8MHz.build.oscillator= +809.menu.clock.internal_8MHz.build.f_cpu=8000000L + +809.menu.clock.internal_5MHz=Internal 5 MHz +809.menu.clock.internal_5MHz.upload.speed=115200 +809.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +809.menu.clock.internal_5MHz.build.oscillator= +809.menu.clock.internal_5MHz.build.f_cpu=5000000L + +809.menu.clock.internal_4MHz=Internal 4 MHz +809.menu.clock.internal_4MHz.upload.speed=115200 +809.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +809.menu.clock.internal_4MHz.build.oscillator= +809.menu.clock.internal_4MHz.build.f_cpu=4000000L + +809.menu.clock.internal_2MHz=Internal 2 MHz +809.menu.clock.internal_2MHz.upload.speed=115200 +809.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +809.menu.clock.internal_2MHz.build.oscillator= +809.menu.clock.internal_2MHz.build.f_cpu=2000000L + +809.menu.clock.internal_1MHz=Internal 1 MHz +809.menu.clock.internal_1MHz.upload.speed=115200 +809.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +809.menu.clock.internal_1MHz.build.oscillator= +809.menu.clock.internal_1MHz.build.f_cpu=1000000L + +809.menu.clock.external_16MHz=External 16 MHz +809.menu.clock.external_16MHz.upload.speed=115200 +809.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +809.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +809.menu.clock.external_16MHz.build.f_cpu=16000000L + +809.menu.clock.external_12MHz=External 12 MHz +809.menu.clock.external_12MHz.upload.speed=115200 +809.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +809.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +809.menu.clock.external_12MHz.build.f_cpu=12000000L + +809.menu.clock.external_8MHz=External 8 MHz +809.menu.clock.external_8MHz.upload.speed=115200 +809.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +809.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +809.menu.clock.external_8MHz.build.f_cpu=8000000L + +809.menu.clock.external_4MHz=External 4 MHz +809.menu.clock.external_4MHz.upload.speed=115200 +809.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +809.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +809.menu.clock.external_4MHz.build.f_cpu=4000000L + +809.menu.clock.external_1MHz=External 1 MHz +809.menu.clock.external_1MHz.upload.speed=115200 +809.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +809.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +809.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +809.menu.bootloader.no_bootloader=No bootloader +809.menu.bootloader.no_bootloader.upload.maximum_size=8192 +809.menu.bootloader.no_bootloader.upload.extra_params= +809.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +809.menu.bootloader.no_bootloader.build.export_merged_output=false +809.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +809.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +809.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +809.menu.bootloader.uart0_default.upload.maximum_size=7680 +809.menu.bootloader.uart0_default.upload.protocol=arduino +809.menu.bootloader.uart0_default.upload.port=UART0_DEF +809.menu.bootloader.uart0_default.upload.extra_params= +809.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +809.menu.bootloader.uart0_default.build.export_merged_output=true +809.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +809.menu.bootloader.uart0_alternative.upload.maximum_size=7680 +809.menu.bootloader.uart0_alternative.upload.protocol=arduino +809.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +809.menu.bootloader.uart0_alternative.upload.extra_params= +809.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +809.menu.bootloader.uart0_alternative.build.export_merged_output=true +809.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +809.menu.bootloader.uart1_default.upload.maximum_size=7680 +809.menu.bootloader.uart1_default.upload.protocol=arduino +809.menu.bootloader.uart1_default.upload.port=UART1_DEF +809.menu.bootloader.uart1_default.upload.extra_params= +809.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +809.menu.bootloader.uart1_default.build.export_merged_output=true +809.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +809.menu.bootloader.uart1_alternative.upload.maximum_size=7680 +809.menu.bootloader.uart1_alternative.upload.protocol=arduino +809.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +809.menu.bootloader.uart1_alternative.upload.extra_params= +809.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +809.menu.bootloader.uart1_alternative.build.export_merged_output=true +809.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +809.menu.bootloader.uart2_default.upload.maximum_size=7680 +809.menu.bootloader.uart2_default.upload.protocol=arduino +809.menu.bootloader.uart2_default.upload.port=UART2_DEF +809.menu.bootloader.uart2_default.upload.extra_params= +809.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +809.menu.bootloader.uart2_default.build.export_merged_output=true +809.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +809.menu.bootloader.uart2_alternative.upload.maximum_size=7680 +809.menu.bootloader.uart2_alternative.upload.protocol=arduino +809.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +809.menu.bootloader.uart2_alternative.upload.extra_params= +809.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +809.menu.bootloader.uart2_alternative.build.export_merged_output=true +809.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart3_default=Optiboot (UART3 default pins) +809.menu.bootloader.uart3_default.upload.maximum_size=7680 +809.menu.bootloader.uart3_default.upload.protocol=arduino +809.menu.bootloader.uart3_default.upload.port=UART3_DEF +809.menu.bootloader.uart3_default.upload.extra_params= +809.menu.bootloader.uart3_default.build.text_section_start=.text=0x200 +809.menu.bootloader.uart3_default.build.export_merged_output=true +809.menu.bootloader.uart3_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart3_default.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart3_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +809.menu.bootloader.uart3_alternative=Optiboot (UART3 alternative pins) +809.menu.bootloader.uart3_alternative.upload.maximum_size=7680 +809.menu.bootloader.uart3_alternative.upload.protocol=arduino +809.menu.bootloader.uart3_alternative.upload.port=UART3_ALT +809.menu.bootloader.uart3_alternative.upload.extra_params= +809.menu.bootloader.uart3_alternative.build.text_section_start=.text=0x200 +809.menu.bootloader.uart3_alternative.build.export_merged_output=true +809.menu.bootloader.uart3_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +809.menu.bootloader.uart3_alternative.bootloader.BOOTEND=0x02 +809.menu.bootloader.uart3_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + + +################### +#### ATmega808 #### +################### + +# General +808.name=ATmega808 +808.upload.tool=avrdude +808.upload.maximum_data_size=1024 +808.upload.speed=115200 +808.bootloader.tool=avrdude +808.build.core=coreX-corefiles +808.build.board=AVR_ATmega808 +808.build.mcu=atmega808 +808.build.extra_flags={build.oscillator} + +# Fuses we don't need to modify in the tools menu +808.bootloader.WDTCFG=0x00 +808.bootloader.TCD0CFG=0x00 +808.bootloader.SYSCFG1=0x06 +808.bootloader.APPEND=0x00 +808.bootloader.LOCKBIT=0xC5 + +# Pinouts +808.menu.pinout.32pin_standard=32 pin standard +808.menu.pinout.32pin_standard.build.variant=32pin-standard +808.menu.pinout.28pin_standard=28 pin standard +808.menu.pinout.28pin_standard.build.variant=28pin-standard + +# EEPROM +808.menu.eeprom.keep=EEPROM retained +808.menu.eeprom.keep.bootloader.eesave_bit=1 +808.menu.eeprom.erase=EEPROM not retained +808.menu.eeprom.erase.bootloader.eesave_bit=0 + +# Reset pin +808.menu.resetpin.reset=Reset +808.menu.resetpin.reset.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +808.menu.resetpin.gpio=GPIO +808.menu.resetpin.gpio.bootloader.SYSCFG0=0b1100000{bootloader.eesave_bit} + +# Brown out detection +808.menu.BOD.2v6=BOD 2.6V +808.menu.BOD.2v6.bootloader.BODCFG=0x54 +808.menu.BOD.4v3=BOD 4.3V +808.menu.BOD.4v3.bootloader.BODCFG=0xF4 +808.menu.BOD.4v0=BOD 4.0V +808.menu.BOD.4v0.bootloader.BODCFG=0xD4 +808.menu.BOD.3v7=BOD 3.7V +808.menu.BOD.3v7.bootloader.BODCFG=0xB4 +808.menu.BOD.3v3=BOD 3.3V +808.menu.BOD.3v3.bootloader.BODCFG=0x94 +808.menu.BOD.2v9=BOD 2.9V +808.menu.BOD.2v9.bootloader.BODCFG=0x74 +808.menu.BOD.2v1=BOD 2.1V +808.menu.BOD.2v1.bootloader.BODCFG=0x34 +808.menu.BOD.1v8=BOD 1.8V +808.menu.BOD.1v8.bootloader.BODCFG=0x14 +808.menu.BOD.disabled=BOD disabled +808.menu.BOD.disabled.bootloader.BODCFG=0x00 + +# Clock +808.menu.clock.internal_16MHz=Internal 16 MHz +808.menu.clock.internal_16MHz.upload.speed=115200 +808.menu.clock.internal_16MHz.bootloader.OSCCFG=0x01 +808.menu.clock.internal_16MHz.build.oscillator= +808.menu.clock.internal_16MHz.build.f_cpu=16000000L + +808.menu.clock.internal_20MHz=Internal 20 MHz +808.menu.clock.internal_20MHz.upload.speed=115200 +808.menu.clock.internal_20MHz.bootloader.OSCCFG=0x02 +808.menu.clock.internal_20MHz.build.oscillator= +808.menu.clock.internal_20MHz.build.f_cpu=20000000L + +808.menu.clock.internal_10MHz=Internal 10 MHz +808.menu.clock.internal_10MHz.upload.speed=115200 +808.menu.clock.internal_10MHz.bootloader.OSCCFG=0x02 +808.menu.clock.internal_10MHz.build.oscillator= +808.menu.clock.internal_10MHz.build.f_cpu=10000000L + +808.menu.clock.internal_8MHz=Internal 8 MHz +808.menu.clock.internal_8MHz.upload.speed=115200 +808.menu.clock.internal_8MHz.bootloader.OSCCFG=0x01 +808.menu.clock.internal_8MHz.build.oscillator= +808.menu.clock.internal_8MHz.build.f_cpu=8000000L + +808.menu.clock.internal_5MHz=Internal 5 MHz +808.menu.clock.internal_5MHz.upload.speed=115200 +808.menu.clock.internal_5MHz.bootloader.OSCCFG=0x02 +808.menu.clock.internal_5MHz.build.oscillator= +808.menu.clock.internal_5MHz.build.f_cpu=5000000L + +808.menu.clock.internal_4MHz=Internal 4 MHz +808.menu.clock.internal_4MHz.upload.speed=115200 +808.menu.clock.internal_4MHz.bootloader.OSCCFG=0x01 +808.menu.clock.internal_4MHz.build.oscillator= +808.menu.clock.internal_4MHz.build.f_cpu=4000000L + +808.menu.clock.internal_2MHz=Internal 2 MHz +808.menu.clock.internal_2MHz.upload.speed=115200 +808.menu.clock.internal_2MHz.bootloader.OSCCFG=0x01 +808.menu.clock.internal_2MHz.build.oscillator= +808.menu.clock.internal_2MHz.build.f_cpu=2000000L + +808.menu.clock.internal_1MHz=Internal 1 MHz +808.menu.clock.internal_1MHz.upload.speed=115200 +808.menu.clock.internal_1MHz.bootloader.OSCCFG=0x01 +808.menu.clock.internal_1MHz.build.oscillator= +808.menu.clock.internal_1MHz.build.f_cpu=1000000L + +808.menu.clock.external_16MHz=External 16 MHz +808.menu.clock.external_16MHz.upload.speed=115200 +808.menu.clock.external_16MHz.bootloader.OSCCFG=0x01 +808.menu.clock.external_16MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +808.menu.clock.external_16MHz.build.f_cpu=16000000L + +808.menu.clock.external_12MHz=External 12 MHz +808.menu.clock.external_12MHz.upload.speed=115200 +808.menu.clock.external_12MHz.bootloader.OSCCFG=0x01 +808.menu.clock.external_12MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +808.menu.clock.external_12MHz.build.f_cpu=12000000L + +808.menu.clock.external_8MHz=External 8 MHz +808.menu.clock.external_8MHz.upload.speed=115200 +808.menu.clock.external_8MHz.bootloader.OSCCFG=0x01 +808.menu.clock.external_8MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +808.menu.clock.external_8MHz.build.f_cpu=8000000L + +808.menu.clock.external_4MHz=External 4 MHz +808.menu.clock.external_4MHz.upload.speed=115200 +808.menu.clock.external_4MHz.bootloader.OSCCFG=0x01 +808.menu.clock.external_4MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +808.menu.clock.external_4MHz.build.f_cpu=4000000L + +808.menu.clock.external_1MHz=External 1 MHz +808.menu.clock.external_1MHz.upload.speed=115200 +808.menu.clock.external_1MHz.bootloader.OSCCFG=0x01 +808.menu.clock.external_1MHz.build.oscillator=-DUSE_EXTERNAL_OSCILLATOR +808.menu.clock.external_1MHz.build.f_cpu=1000000L + +# Bootloader +808.menu.bootloader.no_bootloader=No bootloader +808.menu.bootloader.no_bootloader.upload.maximum_size=8192 +808.menu.bootloader.no_bootloader.upload.extra_params= +808.menu.bootloader.no_bootloader.build.text_section_start=.text=0x0 +808.menu.bootloader.no_bootloader.build.export_merged_output=false +808.menu.bootloader.no_bootloader.bootloader.file=empty/empty.hex +808.menu.bootloader.no_bootloader.bootloader.BOOTEND=0x00 + +808.menu.bootloader.uart0_default=Optiboot (UART0 default pins) +808.menu.bootloader.uart0_default.upload.maximum_size=7680 +808.menu.bootloader.uart0_default.upload.protocol=arduino +808.menu.bootloader.uart0_default.upload.port=UART0_DEF +808.menu.bootloader.uart0_default.upload.extra_params= +808.menu.bootloader.uart0_default.build.text_section_start=.text=0x200 +808.menu.bootloader.uart0_default.build.export_merged_output=true +808.menu.bootloader.uart0_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart0_default.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart0_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +808.menu.bootloader.uart0_alternative=Optiboot (UART0 alternative pins) +808.menu.bootloader.uart0_alternative.upload.maximum_size=7680 +808.menu.bootloader.uart0_alternative.upload.protocol=arduino +808.menu.bootloader.uart0_alternative.upload.port=UART0_ALT +808.menu.bootloader.uart0_alternative.upload.extra_params= +808.menu.bootloader.uart0_alternative.build.text_section_start=.text=0x200 +808.menu.bootloader.uart0_alternative.build.export_merged_output=true +808.menu.bootloader.uart0_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart0_alternative.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart0_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +808.menu.bootloader.uart1_default=Optiboot (UART1 default pins) +808.menu.bootloader.uart1_default.upload.maximum_size=7680 +808.menu.bootloader.uart1_default.upload.protocol=arduino +808.menu.bootloader.uart1_default.upload.port=UART1_DEF +808.menu.bootloader.uart1_default.upload.extra_params= +808.menu.bootloader.uart1_default.build.text_section_start=.text=0x200 +808.menu.bootloader.uart1_default.build.export_merged_output=true +808.menu.bootloader.uart1_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart1_default.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart1_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +808.menu.bootloader.uart1_alternative=Optiboot (UART1 alternative pins) +808.menu.bootloader.uart1_alternative.upload.maximum_size=7680 +808.menu.bootloader.uart1_alternative.upload.protocol=arduino +808.menu.bootloader.uart1_alternative.upload.port=UART1_ALT +808.menu.bootloader.uart1_alternative.upload.extra_params= +808.menu.bootloader.uart1_alternative.build.text_section_start=.text=0x200 +808.menu.bootloader.uart1_alternative.build.export_merged_output=true +808.menu.bootloader.uart1_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart1_alternative.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart1_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} + +808.menu.bootloader.uart2_default=Optiboot (UART2 default pins) +808.menu.bootloader.uart2_default.upload.maximum_size=7680 +808.menu.bootloader.uart2_default.upload.protocol=arduino +808.menu.bootloader.uart2_default.upload.port=UART2_DEF +808.menu.bootloader.uart2_default.upload.extra_params= +808.menu.bootloader.uart2_default.build.text_section_start=.text=0x200 +808.menu.bootloader.uart2_default.build.export_merged_output=true +808.menu.bootloader.uart2_default.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart2_default.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart2_default.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} +808.menu.bootloader.uart2_alternative=Optiboot (UART2 alternative pins) +808.menu.bootloader.uart2_alternative.upload.maximum_size=7680 +808.menu.bootloader.uart2_alternative.upload.protocol=arduino +808.menu.bootloader.uart2_alternative.upload.port=UART2_ALT +808.menu.bootloader.uart2_alternative.upload.extra_params= +808.menu.bootloader.uart2_alternative.build.text_section_start=.text=0x200 +808.menu.bootloader.uart2_alternative.build.export_merged_output=true +808.menu.bootloader.uart2_alternative.bootloader.file=optiboot/bootloaders/mega0/{upload.speed}/Optiboot_mega0_{upload.port}_{upload.speed}_A7.hex +808.menu.bootloader.uart2_alternative.bootloader.BOOTEND=0x02 +808.menu.bootloader.uart2_alternative.bootloader.SYSCFG0=0b1100100{bootloader.eesave_bit} diff --git a/megaavr/bootloaders/empty/empty.hex b/megaavr/bootloaders/empty/empty.hex new file mode 100644 index 0000000..7ef5593 --- /dev/null +++ b/megaavr/bootloaders/empty/empty.hex @@ -0,0 +1 @@ +:00000001FF \ No newline at end of file diff --git a/megaavr/bootloaders/optiboot/Makefile b/megaavr/bootloaders/optiboot/Makefile new file mode 100755 index 0000000..f6620a3 --- /dev/null +++ b/megaavr/bootloaders/optiboot/Makefile @@ -0,0 +1,174 @@ +# Makefile for AVR Mega-0 (4809), Tiny-0, and Tiny-1 version of Optiboot +# Bill Westfield, 2019 +# $Id$ +# +# Edit History +# Sep-2019 refactor from the normal AVR Makefile. +# * Copyright 2013-2019 by Bill Westfield. Part of Optiboot. +# * This software is licensed under version 2 of the Gnu Public Licence. +# * See optiboot.c for details. + +HELPTEXT = "\n" +#---------------------------------------------------------------------- +# +# program name should not be changed... +PROGRAM = optiboot_x +MF:= $(MAKEFILE_LIST) + +# export symbols to recursive makes (for ISP) +export + +LDSECTIONS = -Wl,-section-start=.text=0 \ + -Wl,--section-start=.application=0x200 \ + -Wl,--section-start=.version=0x1fe + +BAUD_RATE=115200 + +# Place your avr-gcc tool root here +GCCROOT =/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/ + +# +# End of build environment code. + + +CC = $(GCCROOT)avr-gcc +RCC = $(abspath $(CC)) +#$(info wildcard ("$(wildcard $(CC))","")) +ifndef PRODUCTION +$(info Using Compiler at: ${RCC}) +endif + + + + +OPTIMIZE = -Os -fno-split-wide-types -mrelax + +# Override is only needed by avr-lib build system. + +override CFLAGS = -g -Wall $(OPTIMIZE) +override LDFLAGS = $(LDSECTIONS) -Wl,--relax -nostartfiles -nostdlib + +OBJCOPY = $(GCCROOT)avr-objcopy +OBJDUMP = $(GCCROOT)avr-objdump +SIZE = $(GCCROOT)avr-size + +include parse_options.mk + +.PRECIOUS: optiboot_%.elf + +ifndef PRODUCTION +LISTING= $(OBJDUMP) -S +else +LISTING= @true +endif + +ifeq ($(SKIP_BOOTLOADER_ON_POR), 0) +START_APP_ON_POR=0 +else +START_APP_ON_POR=1 +endif + +ifeq ($(UARTTX), A0) +UART=0 +UARTMUX=DEF +endif +ifeq ($(UARTTX), B0) +UART=3 +UARTMUX=DEF +endif +ifeq ($(UARTTX), C0) +UART=1 +UARTMUX=DEF +endif +ifeq ($(UARTTX), F0) +UART=2 +UARTMUX=DEF +endif +ifeq ($(UARTTX), A4) +UART=0 +UARTMUX=ALT +endif +ifeq ($(UARTTX), B4) +UART=3 +UARTMUX=ALT +endif +ifeq ($(UARTTX), C4) +UART=1 +UARTMUX=ALT +endif +ifeq ($(UARTTX), F4) +UART=2 +UARTMUX=ALT +endif + + +#--------------------------------------------------------------------------- +# "Chip-level Platform" targets. +# A "Chip-level Platform" compiles for a particular chip, but probably does +# not have "standard" values for things like clock speed, LED pin, etc. +# Makes for chip-level platforms should usually explicitly define their +# options like: "make atmega4809 UARTTX=A4 LED=D0" +#--------------------------------------------------------------------------- +# +# Mega0, tiny0, tiny1 don't really have any chip-specific requirements. +# +# Note about fuses: +# The fuses are defined in the source code. There are 9! +# Be sure to use a programmer that will program the fuses from the object file. +# +#--------------------------------------------------------------------------- +# + + + +optiboot_%.hex: optiboot_%.elf + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@ + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@ + +%.elf: optiboot_x.c FORCE + $(CC) $(CFLAGS) $(CPU_OPTIONS) $(LED_OPTIONS) $(UART_OPTIONS) $(COMMON_OPTIONS) $(POR) $(LDFLAGS) $(PACK_OPT) -mmcu=$(TARGET) -o $@ $< + $(SIZE) $@ + + +#--------------------------------------------------------------------------- +# "Board-level Platform" targets. +# A "Board-level Platform" implies a manufactured platform with a particular +# AVR_FREQ, LED, and so on. Parameters are not particularly changable from +# the "make" command line. +# Most of the board-level platform builds should envoke make recursively +# appropriate specific options +#--------------------------------------------------------------------------- + + +mega0: TARGET=atmega4809 +mega0: bootloaders/mega0/$(BAUD_RATE)/Optiboot_mega0_UART$(UART)_$(UARTMUX)_$(BAUD_RATE)_$(LED).hex + + +#--------------------------------------------------------------------------- +# +# Generic build instructions +# + +FORCE: + +#windows "rm" is dumb and objects to wildcards that don't exist +clean: + @touch __temp_.o __temp_.elf __temp_.lst __temp_.map + @touch __temp_.sym __temp_.lss __temp_.eep __temp_.srec + @touch __temp_.bin __temp_.hex __temp_.tmp.sh + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.tmp.sh + +clean_asm: + rm -rf *.lst + +%.lst: %.elf FORCE + $(OBJDUMP) -h -S $< > $@ + +%.srec: %.elf FORCE + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@ + +%.bin: %.elf FORCE + $(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@ + diff --git a/megaavr/bootloaders/optiboot/README.TXT b/megaavr/bootloaders/optiboot/README.TXT new file mode 100755 index 0000000..b4db4c9 --- /dev/null +++ b/megaavr/bootloaders/optiboot/README.TXT @@ -0,0 +1,99 @@ +This directory contains the Optiboot small bootloader for AVR +microcontrollers, somewhat modified specifically for the Arduino +environment. + +Optiboot is more fully described here: http://github.com/Optiboot/optiboot +and is the work of Peter Knight (aka Cathedrow), building on work of Jason P +Kyle, Spiff, and Ladyada. More recent maintenance and modifications are by +Bill Westfield (aka WestfW) + +Arduino-specific issues are tracked as part of the Arduino project +at http://github.com/arduino/Arduino + + +Most of the information in this file is superceeded by the wiki content at +https://github.com/Optiboot/optiboot/wiki + +It's till here "just in case." + +------------------------------------------------------------ + +Building optiboot for Arduino. + +Production builds of optiboot for Arduino are done on a Mac in "unix mode" +using CrossPack-AVR-20100115. CrossPack tracks WINAVR (for windows), which +is just a package of avr-gcc and related utilities, so similar builds should +work on Windows or Linux systems. + +One of the Arduino-specific changes is modifications to the makefile to +allow building optiboot using only the tools installed as part of the +Arduino environment, or the Arduino source development tree. All three +build procedures should yield identical binaries (.hex files) (although +this may change if compiler versions drift apart between CrossPack and +the Arduino IDE.) + + +Building Optiboot in the Arduino IDE Install. + +Work in the .../hardware/arduino/bootloaders/optiboot/ and use the +"omake " command, which just generates a command that uses +the arduino-included "make" utility with a command like: + make OS=windows ENV=arduino +or make OS=macosx ENV=arduino +On windows, this assumes you're using the windows command shell. If +you're using a cygwin or mingw shell, or have one of those in your +path, the build will probably break due to slash vs backslash issues. +On a Mac, if you have the developer tools installed, you can use the +Apple-supplied version of make. +The makefile uses relative paths ("../../../tools/" and such) to find +the programs it needs, so you need to work in the existing optiboot +directory (or something created at the same "level") for it to work. + + +Building Optiboot in the Arduino Source Development Install. + +In this case, there is no special shell script, and you're assumed to +have "make" installed somewhere in your path. +Build the Arduino source ("ant build") to unpack the tools into the +expected directory. +Work in Arduino/hardware/arduino/bootloaders/optiboot and use + make OS=windows ENV=arduinodev +or make OS=macosx ENV=arduinodev + + +Programming Chips Using the _isp Targets + +The CPU targets have corresponding ISP targets that will actuall +program the bootloader into a chip. "atmega328_isp" for the atmega328, +for example. These will set the fuses and lock bits as appropriate as +well as uploading the bootloader code. + +ISP Targets in Version 5.0 and later: + +The isp targets are now built using a separate "Makefile.isp" makefile, +which should make modification easier and more obvious. This also fixes +the atmega8_isp target problem mentioned below. The default +configuration assumes an ArduinoISP setup, but you will probably need to +update at least the serial port, since those are different for each +Arduino board and/or system/ + + +ISP Targets in Version 4.6 and earlier: + +The older makefiles default to using a USB programmer, but you can use a +serial programmer like ArduinoISP by changing the appropriate variables +when you invoke make: + + make ISPTOOL=stk500v1 ISPPORT=/dev/tty.usbserial-A20e1eAN \ + ISPSPEED=-b19200 atmega328_isp + +The "atmega8_isp" target does not currently work, because the mega8 +doesn't have the "extended" fuse that the generic ISP target wants to +pass on to avrdude. You'll need to run avrdude manually. + + +Standard Targets + +I've reduced the pre-built and source-version-controlled targets +(.hex and .lst files included in the git repository) to just the +three basic 16MHz targets: atmega8, atmega16, atmega328. diff --git a/megaavr/bootloaders/optiboot/boot_opt.h b/megaavr/bootloaders/optiboot/boot_opt.h new file mode 100755 index 0000000..d0285a6 --- /dev/null +++ b/megaavr/bootloaders/optiboot/boot_opt.h @@ -0,0 +1,101 @@ +// Get all the "standard" definitions from the official boot.h +#include + + +/* + * Implement some optimized versions that will use OUT instead + * of STS to write SPMCSR. + * (However, omit the *_extended_short, since by the time you + * need _extended_, the extra byte shouldn't be relevant any more) + * + * The C preprocessor can not determin at compile time whether SPMCSR is + * "out of range" of the OUT instruction, but we CAN do that in the + * assembler. We can even make it pretty with a macro. + * With this modification, the _short functions should work on cpus + * (like ATmega128) where STS is required. + */ + +asm(".macro __wr_spmcsr p, v \n\t" + ".if \\p > 0x57 \n\t" + "sts \\p, \\v \n\t" + ".else \n\t" + "out \\p-0x20, \\v \n\t" + ".endif \n\t" + ".endm \n"); + + +#if defined(__SPM_REG) + +#define __boot_page_fill_short(address, data) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "movw r0, %3\n\t" \ + "__wr_spmcsr %0, %1\n\t" \ + "spm\n\t" \ + "clr r1\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_FILL), \ + "z" ((uint16_t)address), \ + "r" ((uint16_t)data) \ + : "r0" \ + ); \ +})) + +#define __boot_page_erase_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "__wr_spmcsr %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_ERASE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_page_write_short(address) \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "__wr_spmcsr %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_PAGE_WRITE), \ + "z" ((uint16_t)address) \ + ); \ +})) + +#define __boot_rww_enable_short() \ +(__extension__({ \ + __asm__ __volatile__ \ + ( \ + "__wr_spmcsr %0, %1\n\t" \ + "spm\n\t" \ + : \ + : "i" (_SFR_MEM_ADDR(__SPM_REG)), \ + "r" ((uint8_t)__BOOT_RWW_ENABLE) \ + ); \ +})) + +#endif // __SPM_REG + +#ifndef __boot_page_erase_short + +/* + * if __SPM_REG didn't get defined by now, but we didn't exit it means + * we have some sort of new-fangled chip that post-dates the version + * of boot.h that we know about. In this case, it's possible that the + * standard boot.h still has workable functions, so we'll alias those. + */ + +#define __boot_page_fill_short(address, data) boot_page_fill(address, data) +#define __boot_page_erase_short(address) boot_page_erase(address) +#define __boot_page_write_short(address) boot_page_write(address) +#define __boot_rww_enable_short() boot_rww_enable() + +#endif + diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_ALT_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_ALT_115200_A7.hex new file mode 100644 index 0000000..5ea5b82 --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_ALT_115200_A7.hex @@ -0,0 +1,32 @@ +:1000000001C0D9C0112480914000882369F0282FB5 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0B0D0ECC0A895049A0C9A81E01B +:100030008093E205809182128370813029F58CE5EE +:1000400090E0809308089093090881E080930B0862 +:1000500083E0809307081092050880EC80930608DF +:1000600088E091D0079A87E0815089F4A8950DE93E +:1000700083E0D82E7CD08134F1F479D0182F8CD045 +:10008000123889F480E013C083E790E0DACF179A42 +:100090002EEC36E5A8959091040897FDE8CF215005 +:1000A0003109C1F7E1CF89E0113809F083E058D078 +:1000B00080E156D0DFCF823419F484E175D0F8CFD7 +:1000C000853411F485E0FACF853531F450D0C82F4E +:1000D0004ED0D82F61D0ECCF863519F484E064D0AF +:1000E000D1CF8436B9F443D042D0182F40D08634D3 +:1000F00079F4D05C3CD0888321961150D9F74CD04C +:1001000004BFD0920010809102108370E1F7D0CF2D +:10011000DC5EF0CF843791F42AD029D0182F27D075 +:10012000F82E3AD086E4F81207C0D05C8881219678 +:1001300017D01150D9F7BCCFDC5EF8CF853751F41A +:100140002BD0809100110CD08091011109D08091A9 +:100150000211ADCF813509F0BDCF81E014D0BACF07 +:100160009091040895FFFCCF809302080895809138 +:10017000040887FFFCCF909101088091000892FD50 +:1001800001C0A89508959091010190FDFCCF98EDD4 +:1001900094BF809300010895EADF803219F081E076 +:1001A000F2DFFFCF84E1DCCFCF93C82FE0DFC15077 +:1001B000E9F7CF91F1CF683048F48DE984BF6093BF +:1001C0000010809102108370E1F70895FC014083D4 +:0201D000089590 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_DEF_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_DEF_115200_A7.hex new file mode 100644 index 0000000..516ec1f --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART0_DEF_115200_A7.hex @@ -0,0 +1,31 @@ +:1000000001C0D8C0112480914000882369F0282FB6 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0AFD0ECC0A895009A089A1092E3 +:10003000E205809182128370813029F58CE590E091 +:10004000809308089093090881E080930B0883E06F +:10005000809307081092050880EC8093060888E0DA +:1000600091D0079A87E0815089F4A8950DE983E043 +:10007000D82E7CD08134F1F479D0182F8CD012385E +:1000800089F480E013C083E790E0DACF179A2EEC72 +:1000900036E5A8959091040897FDE8CF21503109E5 +:1000A000C1F7E1CF89E0113809F083E058D080E151 +:1000B00056D0DFCF823419F484E175D0F8CF85347F +:1000C00011F485E0FACF853531F450D0C82F4ED0E9 +:1000D000D82F61D0ECCF863519F484E064D0D1CF2D +:1000E0008436B9F443D042D0182F40D0863479F406 +:1000F000D05C3CD0888321961150D9F74CD004BFF6 +:10010000D0920010809102108370E1F7D0CFDC5EB6 +:10011000F0CF843791F42AD029D0182F27D0F82E89 +:100120003AD086E4F81207C0D05C8881219617D0B7 +:100130001150D9F7BCCFDC5EF8CF853751F42BD006 +:10014000809100110CD08091011109D08091021191 +:10015000ADCF813509F0BDCF81E014D0BACF9091F9 +:10016000040895FFFCCF809302080895809104084D +:1001700087FFFCCF909101088091000892FD01C09B +:10018000A89508959091010190FDFCCF98ED94BF42 +:10019000809300010895EADF803219F081E0F2DFF8 +:1001A000FFCF84E1DCCFCF93C82FE0DFC150E9F768 +:1001B000CF91F1CF683048F48DE984BF609300108F +:1001C000809102108370E1F70895FC014083089547 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_ALT_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_ALT_115200_A7.hex new file mode 100644 index 0000000..e54179a --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_ALT_115200_A7.hex @@ -0,0 +1,32 @@ +:1000000001C0D9C0112480914000882369F0282FB5 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0B0D0ECC0A895449A4C9A84E098 +:100030008093E205809182128370813029F58CE5EE +:1000400090E0809328089093290881E080932B0802 +:1000500083E0809327081092250880EC809326087F +:1000600088E091D0079A87E0815089F4A8950DE93E +:1000700083E0D82E7CD08134F1F479D0182F8CD045 +:10008000123889F480E013C083E790E0DACF179A42 +:100090002EEC36E5A8959091240897FDE8CF2150E5 +:1000A0003109C1F7E1CF89E0113809F083E058D078 +:1000B00080E156D0DFCF823419F484E175D0F8CFD7 +:1000C000853411F485E0FACF853531F450D0C82F4E +:1000D0004ED0D82F61D0ECCF863519F484E064D0AF +:1000E000D1CF8436B9F443D042D0182F40D08634D3 +:1000F00079F4D05C3CD0888321961150D9F74CD04C +:1001000004BFD0920010809102108370E1F7D0CF2D +:10011000DC5EF0CF843791F42AD029D0182F27D075 +:10012000F82E3AD086E4F81207C0D05C8881219678 +:1001300017D01150D9F7BCCFDC5EF8CF853751F41A +:100140002BD0809100110CD08091011109D08091A9 +:100150000211ADCF813509F0BDCF81E014D0BACF07 +:100160009091240895FFFCCF8093220808958091F8 +:10017000240887FFFCCF909121088091200892FDF0 +:1001800001C0A89508959091010190FDFCCF98EDD4 +:1001900094BF809300010895EADF803219F081E076 +:1001A000F2DFFFCF84E1DCCFCF93C82FE0DFC15077 +:1001B000E9F7CF91F1CF683048F48DE984BF6093BF +:1001C0000010809102108370E1F70895FC014083D4 +:0201D000089590 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_DEF_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_DEF_115200_A7.hex new file mode 100644 index 0000000..e91e29a --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART1_DEF_115200_A7.hex @@ -0,0 +1,31 @@ +:1000000001C0D8C0112480914000882369F0282FB6 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0AFD0ECC0A895409A489A109263 +:10003000E205809182128370813029F58CE590E091 +:10004000809328089093290881E080932B0883E00F +:10005000809327081092250880EC8093260888E07A +:1000600091D0079A87E0815089F4A8950DE983E043 +:10007000D82E7CD08134F1F479D0182F8CD012385E +:1000800089F480E013C083E790E0DACF179A2EEC72 +:1000900036E5A8959091240897FDE8CF21503109C5 +:1000A000C1F7E1CF89E0113809F083E058D080E151 +:1000B00056D0DFCF823419F484E175D0F8CF85347F +:1000C00011F485E0FACF853531F450D0C82F4ED0E9 +:1000D000D82F61D0ECCF863519F484E064D0D1CF2D +:1000E0008436B9F443D042D0182F40D0863479F406 +:1000F000D05C3CD0888321961150D9F74CD004BFF6 +:10010000D0920010809102108370E1F7D0CFDC5EB6 +:10011000F0CF843791F42AD029D0182F27D0F82E89 +:100120003AD086E4F81207C0D05C8881219617D0B7 +:100130001150D9F7BCCFDC5EF8CF853751F42BD006 +:10014000809100110CD08091011109D08091021191 +:10015000ADCF813509F0BDCF81E014D0BACF9091F9 +:10016000240895FFFCCF80932208089580912408ED +:1001700087FFFCCF909121088091200892FD01C05B +:10018000A89508959091010190FDFCCF98ED94BF42 +:10019000809300010895EADF803219F081E0F2DFF8 +:1001A000FFCF84E1DCCFCF93C82FE0DFC150E9F768 +:1001B000CF91F1CF683048F48DE984BF609300108F +:1001C000809102108370E1F70895FC014083089547 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_ALT_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_ALT_115200_A7.hex new file mode 100644 index 0000000..0442ebf --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_ALT_115200_A7.hex @@ -0,0 +1,32 @@ +:1000000001C0D9C0112480914000882369F0282FB5 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0B0D0ECC0A895A49AAC9A80E1DB +:100030008093E205809182128370813029F58CE5EE +:1000400090E0809348089093490881E080934B08A2 +:1000500083E0809347081092450880EC809346081F +:1000600088E091D0079A87E0815089F4A8950DE93E +:1000700083E0D82E7CD08134F1F479D0182F8CD045 +:10008000123889F480E013C083E790E0DACF179A42 +:100090002EEC36E5A8959091440897FDE8CF2150C5 +:1000A0003109C1F7E1CF89E0113809F083E058D078 +:1000B00080E156D0DFCF823419F484E175D0F8CFD7 +:1000C000853411F485E0FACF853531F450D0C82F4E +:1000D0004ED0D82F61D0ECCF863519F484E064D0AF +:1000E000D1CF8436B9F443D042D0182F40D08634D3 +:1000F00079F4D05C3CD0888321961150D9F74CD04C +:1001000004BFD0920010809102108370E1F7D0CF2D +:10011000DC5EF0CF843791F42AD029D0182F27D075 +:10012000F82E3AD086E4F81207C0D05C8881219678 +:1001300017D01150D9F7BCCFDC5EF8CF853751F41A +:100140002BD0809100110CD08091011109D08091A9 +:100150000211ADCF813509F0BDCF81E014D0BACF07 +:100160009091440895FFFCCF8093420808958091B8 +:10017000440887FFFCCF909141088091400892FD90 +:1001800001C0A89508959091010190FDFCCF98EDD4 +:1001900094BF809300010895EADF803219F081E076 +:1001A000F2DFFFCF84E1DCCFCF93C82FE0DFC15077 +:1001B000E9F7CF91F1CF683048F48DE984BF6093BF +:1001C0000010809102108370E1F70895FC014083D4 +:0201D000089590 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_DEF_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_DEF_115200_A7.hex new file mode 100644 index 0000000..ac3719b --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART2_DEF_115200_A7.hex @@ -0,0 +1,31 @@ +:1000000001C0D8C0112480914000882369F0282FB6 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0AFD0ECC0A895A09AA89A1092A3 +:10003000E205809182128370813029F58CE590E091 +:10004000809348089093490881E080934B0883E0AF +:10005000809347081092450880EC8093460888E01A +:1000600091D0079A87E0815089F4A8950DE983E043 +:10007000D82E7CD08134F1F479D0182F8CD012385E +:1000800089F480E013C083E790E0DACF179A2EEC72 +:1000900036E5A8959091440897FDE8CF21503109A5 +:1000A000C1F7E1CF89E0113809F083E058D080E151 +:1000B00056D0DFCF823419F484E175D0F8CF85347F +:1000C00011F485E0FACF853531F450D0C82F4ED0E9 +:1000D000D82F61D0ECCF863519F484E064D0D1CF2D +:1000E0008436B9F443D042D0182F40D0863479F406 +:1000F000D05C3CD0888321961150D9F74CD004BFF6 +:10010000D0920010809102108370E1F7D0CFDC5EB6 +:10011000F0CF843791F42AD029D0182F27D0F82E89 +:100120003AD086E4F81207C0D05C8881219617D0B7 +:100130001150D9F7BCCFDC5EF8CF853751F42BD006 +:10014000809100110CD08091011109D08091021191 +:10015000ADCF813509F0BDCF81E014D0BACF9091F9 +:10016000440895FFFCCF809342080895809144088D +:1001700087FFFCCF909141088091400892FD01C01B +:10018000A89508959091010190FDFCCF98ED94BF42 +:10019000809300010895EADF803219F081E0F2DFF8 +:1001A000FFCF84E1DCCFCF93C82FE0DFC150E9F768 +:1001B000CF91F1CF683048F48DE984BF609300108F +:1001C000809102108370E1F70895FC014083089547 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_ALT_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_ALT_115200_A7.hex new file mode 100644 index 0000000..3d026f0 --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_ALT_115200_A7.hex @@ -0,0 +1,32 @@ +:1000000001C0D9C0112480914000882369F0282FB5 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0B0D0ECC0A895249A2C9A80E4D8 +:100030008093E205809182128370813029F58CE5EE +:1000400090E0809368089093690881E080936B0842 +:1000500083E0809367081092650880EC80936608BF +:1000600088E091D0079A87E0815089F4A8950DE93E +:1000700083E0D82E7CD08134F1F479D0182F8CD045 +:10008000123889F480E013C083E790E0DACF179A42 +:100090002EEC36E5A8959091640897FDE8CF2150A5 +:1000A0003109C1F7E1CF89E0113809F083E058D078 +:1000B00080E156D0DFCF823419F484E175D0F8CFD7 +:1000C000853411F485E0FACF853531F450D0C82F4E +:1000D0004ED0D82F61D0ECCF863519F484E064D0AF +:1000E000D1CF8436B9F443D042D0182F40D08634D3 +:1000F00079F4D05C3CD0888321961150D9F74CD04C +:1001000004BFD0920010809102108370E1F7D0CF2D +:10011000DC5EF0CF843791F42AD029D0182F27D075 +:10012000F82E3AD086E4F81207C0D05C8881219678 +:1001300017D01150D9F7BCCFDC5EF8CF853751F41A +:100140002BD0809100110CD08091011109D08091A9 +:100150000211ADCF813509F0BDCF81E014D0BACF07 +:100160009091640895FFFCCF809362080895809178 +:10017000640887FFFCCF909161088091600892FD30 +:1001800001C0A89508959091010190FDFCCF98EDD4 +:1001900094BF809300010895EADF803219F081E076 +:1001A000F2DFFFCF84E1DCCFCF93C82FE0DFC15077 +:1001B000E9F7CF91F1CF683048F48DE984BF6093BF +:1001C0000010809102108370E1F70895FC014083D4 +:0201D000089590 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_DEF_115200_A7.hex b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_DEF_115200_A7.hex new file mode 100644 index 0000000..f654a0c --- /dev/null +++ b/megaavr/bootloaders/optiboot/bootloaders/mega0/115200/Optiboot_mega0_UART3_DEF_115200_A7.hex @@ -0,0 +1,31 @@ +:1000000001C0D8C0112480914000882369F0282FB6 +:1000100030E083FD03C02C7F232B31F4809340001C +:100020008CBB80E0AFD0ECC0A895209A289A1092A3 +:10003000E205809182128370813029F58CE590E091 +:10004000809368089093690881E080936B0883E04F +:10005000809367081092650880EC8093660888E0BA +:1000600091D0079A87E0815089F4A8950DE983E043 +:10007000D82E7CD08134F1F479D0182F8CD012385E +:1000800089F480E013C083E790E0DACF179A2EEC72 +:1000900036E5A8959091640897FDE8CF2150310985 +:1000A000C1F7E1CF89E0113809F083E058D080E151 +:1000B00056D0DFCF823419F484E175D0F8CF85347F +:1000C00011F485E0FACF853531F450D0C82F4ED0E9 +:1000D000D82F61D0ECCF863519F484E064D0D1CF2D +:1000E0008436B9F443D042D0182F40D0863479F406 +:1000F000D05C3CD0888321961150D9F74CD004BFF6 +:10010000D0920010809102108370E1F7D0CFDC5EB6 +:10011000F0CF843791F42AD029D0182F27D0F82E89 +:100120003AD086E4F81207C0D05C8881219617D0B7 +:100130001150D9F7BCCFDC5EF8CF853751F42BD006 +:10014000809100110CD08091011109D08091021191 +:10015000ADCF813509F0BDCF81E014D0BACF9091F9 +:10016000640895FFFCCF809362080895809164082D +:1001700087FFFCCF909161088091600892FD01C0DB +:10018000A89508959091010190FDFCCF98ED94BF42 +:10019000809300010895EADF803219F081E0F2DFF8 +:1001A000FFCF84E1DCCFCF93C82FE0DFC150E9F768 +:1001B000CF91F1CF683048F48DE984BF609300108F +:1001C000809102108370E1F70895FC014083089547 +:0201FE000009F6 +:00000001FF diff --git a/megaavr/bootloaders/optiboot/makeall b/megaavr/bootloaders/optiboot/makeall new file mode 100755 index 0000000..95c1b1c --- /dev/null +++ b/megaavr/bootloaders/optiboot/makeall @@ -0,0 +1,9 @@ +# Build for 115200 baud +make mega0 UARTTX=A0 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=A4 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=B0 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=B4 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=C0 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=C4 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=F0 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 +make mega0 UARTTX=F4 TIMEOUT=1 LED=A7 BAUD_RATE=115200 SKIP_BOOTLOADER_ON_POR=1 diff --git a/megaavr/bootloaders/optiboot/omake b/megaavr/bootloaders/optiboot/omake new file mode 100755 index 0000000..59d23d9 --- /dev/null +++ b/megaavr/bootloaders/optiboot/omake @@ -0,0 +1,9 @@ +#%/bin/bash +if [ -d ../../../tools ]; then + mypath=../../../tools/avr/bin +else + mypath=../../../../tools/avr/bin +fi + +echo $mypath/make OS=macosx ENV=arduino $* +$mypath/make OS=macosx ENV=arduino $* diff --git a/megaavr/bootloaders/optiboot/omake.bat b/megaavr/bootloaders/optiboot/omake.bat new file mode 100755 index 0000000..83538ca --- /dev/null +++ b/megaavr/bootloaders/optiboot/omake.bat @@ -0,0 +1,2 @@ +call .\install-avr-tools.bat +make %* diff --git a/megaavr/bootloaders/optiboot/optiboot_x.c b/megaavr/bootloaders/optiboot/optiboot_x.c new file mode 100755 index 0000000..607d682 --- /dev/null +++ b/megaavr/bootloaders/optiboot/optiboot_x.c @@ -0,0 +1,734 @@ +/************************************************************/ +/* Optiboot bootloader for Mega0, Tiny0, Tiny1 */ +/* */ +/* https://github.com/optiboot/optiboot */ +/* */ +/* Heavily optimised bootloader that is fast and small */ +/* (512 bytes, 115200bps */ +/* */ +/* Written almost entirely in C */ +/* Customisable timeout with accurate timeconstant */ +/* */ +/* */ +/* Copyright 2013-2020 by Bill Westfield. */ +/* Copyright 2010 by Peter Knight. */ +/* */ +/* This program is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU General */ +/* Public License as published by the Free Software */ +/* Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without even the */ +/* implied warranty of MERCHANTABILITY or FITNESS FOR A */ +/* PARTICULAR PURPOSE. See the GNU General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU General */ +/* Public License along with this program; if not, write */ +/* to the Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* Licence can be viewed at */ +/* https://github.com/Optiboot/optiboot/blob/master/LICENSE */ +/* */ +/************************************************************/ + + +/************************************************************/ +/* */ +/* Optional defines: */ +/* */ +/************************************************************/ +/* */ +/* BIGBOOT: */ +/* Build a 1k bootloader, not 512 bytes. This turns on */ +/* extra functionality. */ +/* */ +/* BAUD_RATE: */ +/* Set bootloader baud rate. */ +/* */ +/* LED_START_FLASHES: */ +/* Number of LED flashes on bootup. */ +/* */ +/* LED_DATA_FLASH: */ +/* Flash LED when transferring data. For boards without */ +/* TX or RX LEDs, or for people who like blinky lights. */ +/* */ +/* TIMEOUT_MS: */ +/* Bootloader timeout period, in milliseconds. */ +/* 500,1000,2000,4000,8000 supported. */ +/* */ +/* UARTTX: */ +/* UART TX pin (B0, etc) for devices with more than */ +/* one hardware uart, or alternative pins */ +/* */ +/************************************************************/ + +/************************************************************/ +/* Version Numbers! */ +/* */ +/* Optiboot now includes a Version number in the source */ +/* and object code, and returns this value via STK500 */ +/* */ +/* The iniital Mega0/Xtiny support is version 9. */ +/* This is very different from normal AVR because of */ +/* changed peripherals and unified address space. */ +/* */ +/* It would be good if versions implemented outside the */ +/* official repository used an out-of-seqeunce version */ +/* number (like 104.6 if based on based on 4.5) to */ +/* prevent collisions. The CUSTOM_VERSION=n option */ +/* adds n to the high version to facilitate this. */ +/* */ +/************************************************************/ + +/************************************************************/ +/* Edit History: */ +/* */ +/* Aug 2019 */ +/* 9.0 Refactored for Mega0/Xtiny from optiboot.c */ +/* : */ +/* 4.1 WestfW: put version number in binary. */ +/************************************************************/ + +#define OPTIBOOT_MAJVER 9 +#define OPTIBOOT_MINVER 0 + +/* + * OPTIBOOT_CUSTOMVER should be defined (by the makefile) for custom edits + * of optiboot. That way you don't wind up with very different code that + * matches the version number of a "released" optiboot. + */ + +#if !defined(OPTIBOOT_CUSTOMVER) +# define OPTIBOOT_CUSTOMVER 0 +#endif + +unsigned const int __attribute__((section(".version"))) __attribute__((used)) +optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER; + + +#include +#include + +#if (!defined(__AVR_XMEGA__)) || (__AVR_ARCH__ != 103) +#error CPU not supported by this version of Optiboot. +#include // include a non-existent file to stop compilation +#endif + +/* + * Fuses. + * This is an example of what they'd be like, but some should not + * necessarilly be under control of the bootloader. You'll need a + * a programmer that processes the .fuses section to actually get + * these programmed into the chip. + * The fuses actually REQUIRED by Optiboot are: + * BOOTEND=2, SYSCFG0=(CRC off, RSTPIN as appropriate) + * On some chips, the "reset" pin can be either RESET or GPIO. + * Other also have the UPDI option. If RESET is not enabled we won't be + * able to auto-reset. But if the UPDI pin is set to cause RESET, we + * won't be able to reprogram the chip without HV UPDI (which is uncommon.) + * The settings show will set chips (ie m4809) with RESET/GPIO to use RESET, + * and chips with RESET/GPIO/UPDI to leave it in UPDI mode - the bootloader + * can still be started by a power-on RESET. + */ +FUSES = { + .WDTCFG = 0, /* Watchdog Configuration */ + .BODCFG = FUSE_BODCFG_DEFAULT, /* BOD Configuration */ + .OSCCFG = FREQSEL_20MHZ_gc, /* 20MHz */ +#ifdef FUSE_TCD0CFG_DEFAULT + .TCD0CFG = FUSE_TCD0CFG_DEFAULT, /* TCD0 Configuration */ +#endif +#ifdef RSTPIN + .SYSCFG0 = CRCSRC_NOCRC_gc | RSTPINCFG_RST_gc, /* RESET is enabled */ +#else +# ifdef FUSE_RSTPINCFG_gm // group mask will be defined for triple-func pins + .SYSCFG0 = CRCSRC_NOCRC_gc | RSTPINCFG_UPDI_gc, /* RESET is not yet */ +# else + .SYSCFG0 = CRCSRC_NOCRC_gc, /* RESET is not yet */ +# endif +#endif + .SYSCFG1 = 0x06, /* startup 32ms */ + .APPEND = 0, /* Application Code Section End */ + .BOOTEND = 2 /* Boot Section End */ +}; + + +/* + * optiboot uses several "address" variables that are sometimes byte pointers, + * sometimes word pointers. sometimes 16bit quantities, and sometimes built + * up from 8bit input characters. avr-gcc is not great at optimizing the + * assembly of larger words from bytes, but we can use the usual union to + * do this manually. Expanding it a little, we can also get rid of casts. + */ +typedef union { + uint8_t *bptr; + uint16_t *wptr; + uint16_t word; + uint8_t bytes[2]; +} addr16_t; + + +/* + * pin_defs.h + * This contains most of the rather ugly defines that implement our + * ability to use UART=n and LED=D3, and some avr family bit name differences. + */ +#include "pin_defs_x.h" + +/* + * stk500.h contains the constant definitions for the stk500v1 comm protocol + */ +#include "stk500.h" + +#ifndef LED_START_FLASHES +# define LED_START_FLASHES 0 +#endif + +/* + * The mega-0, tiny-0, and tiny-1 chips all reset to running on the + * internal oscillator, with a prescaler of 6. The internal oscillator + * is either 20MHz or 16MHz, depending on a fuse setting - we can read + * the fuse to figure our which. + * The BRG divisor is also fractional, permitting (afaik) any reasonable + * bit rate between about 1000bps and 1Mbps. + * This makes the BRG generation a bit different than for prior processors. + */ +/* set the UART baud rate defaults */ +#ifndef BAUD_RATE +# define BAUD_RATE 115200L // Highest rate Avrdude win32 will support +#endif +#ifdef F_CPU +# warning F_CPU is ignored for this chip (run from internal osc.) +#endif +#ifdef SINGLESPEED +# warning SINGLESPEED ignored for this chip. (Fractional BRG) +#endif +#ifdef UART +# warning UART is ignored for this chip (use UARTTX=PortPin instead) +#endif + +#define BAUD_SETTING_16 (((16000000/6)*64) / (16L*BAUD_RATE)) +#define BAUD_ACTUAL_16 ((64L*(16000000/6)) / (16L*BAUD_SETTING)) +#define BAUD_SETTING_20 (((20000000/6)*64) / (16L*BAUD_RATE)) +#define BAUD_ACTUAL_20 ((64L*(20000000/6)) / (16L*BAUD_SETTING)) + +#if BAUD_SETTING_16 < 64 // divisor must be > 1. Low bits are fraction. +# error Unachievable baud rate (too fast) BAUD_RATE +#endif + +#if BAUD_SETTING > 65635 +# error Unachievable baud rate (too slow) BAUD_RATE +#endif // baud rate slow check + +/* + * Watchdog timeout translations from human readable to config vals + */ +#ifndef WDTTIME +# define WDTPERIOD WDT_PERIOD_1KCLK_gc // 1 second +#elif WDTTIME == 1 +# define WDTPERIOD WDT_PERIOD_1KCLK_gc // 1 second +#elif WDTTIME == 2 +# define WDTPERIOD WDT_PERIOD_2KCLK_gc // 2 seconds +#elif WDTTIME == 4 +# define WDTPERIOD WDT_PERIOD_4KCLK_gc // 4 seconds +#elif WDTTIME == 8 +# define WDTPERIOD WDT_PERIOD_8KCLK_gc // 8 seconds +#else +#endif + +/* + * We can never load flash with more than 1 page at a time, so we can save + * some code space on parts with smaller pagesize by using a smaller int. + */ +#if MAPPED_PROGMEM_PAGE_SIZE > 255 +typedef uint16_t pagelen_t; +# define GETLENGTH(len) len = getch()<<8; len |= getch() +#else +typedef uint8_t pagelen_t; +# define GETLENGTH(len) (void) getch() /* skip high byte */; len = getch() +#endif + + +/* Function Prototypes + * The main() function is in init9, which removes the interrupt vector table + * we don't need. It is also 'OS_main', which means the compiler does not + * generate any entry or exit code itself (but unlike 'naked', it doesn't + * supress some compile-time options we want.) + */ + +void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8"))); +int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used)); + +void __attribute__((noinline)) __attribute__((leaf)) putch(char); +uint8_t __attribute__((noinline)) __attribute__((leaf)) getch(void) ; +void __attribute__((noinline)) verifySpace(); +void __attribute__((noinline)) watchdogConfig(uint8_t x); + +static void getNch(uint8_t); + +#if LED_START_FLASHES > 0 +static inline void flash_led(uint8_t); +#endif + +#define watchdogReset() __asm__ __volatile__ ("wdr\n") + +/* + * RAMSTART should be self-explanatory. It's bigger on parts with a + * lot of peripheral registers. + * Note that RAMSTART (for optiboot) need not be exactly at the start of RAM. + */ +#if !defined(RAMSTART) // newer versions of gcc avr-libc define RAMSTART +#error RAMSTART not defined. +#endif + +/* everything that needs to run VERY early */ +void pre_main (void) { + // Allow convenient way of calling do_spm function - jump table, + // so entry to this function will always be here, indepedent + // of compilation, features, etc + __asm__ __volatile__ ( + " rjmp 1f\n" +#ifndef APP_NOSPM + " rjmp do_nvmctrl\n" +#else + " ret\n" // if do_spm isn't include, return without doing anything +#endif + "1:\n" + ); +} + +/* main program starts here */ +int main (void) { + uint8_t ch; + + /* + * Making these local and in registers prevents the need for initializing + * them, and also saves space because code no longer stores to memory. + * (initializing address keeps the compiler happy, but isn't really + * necessary, and uses 4 bytes of flash.) + */ + register addr16_t address; + register pagelen_t length; + + // This is the first code to run. + // + // Optiboot C code makes the following assumptions: + // No interrupts will execute + // SP points to RAMEND + + __asm__ __volatile__ ("clr __zero_reg__"); // known-zero required by avr-libc +#define RESET_EXTERNAL (RSTCTRL_EXTRF_bm|RSTCTRL_UPDIRF_bm|RSTCTRL_SWRF_bm) +#ifndef FANCY_RESET_LOGIC + ch = RSTCTRL.RSTFR; // get reset cause +#ifdef START_APP_ON_POR + /* + * If WDRF is set OR nothing except BORF and PORF are set, that's + * not bootloader entry condition so jump to app - this is for when + * UPDI pin is used as reset, so we go straight to app on start. + * 11/14: NASTY bug - we also need to check for no reset flags being + * set (ie, direct entry) and run bootloader in that case, otherwise + * bootloader won't run, among other things, after fresh bootloading! + */ + + if (ch && (ch & RSTCTRL_WDRF_bm || + (!(ch & (~(RSTCTRL_BORF_bm | RSTCTRL_PORF_bm)))))) { +#else + /* + * If WDRF is set OR nothing except BORF is set, that's not + * bootloader entry condition so jump to app - let's see if this + * works okay or not... + */ + if (ch && (ch & RSTCTRL_WDRF_bm || (!(ch & (~RSTCTRL_BORF_bm))))) { +#endif + /* Start the app. + * Dont bother trying to stuff it in r2, which requires heroic + * effort to fish out we'll put it in GPIOR0 where it won't get + * stomped on. + */ + // __asm__ __volatile__ (" mov r2, %0\n" :: "r" (ch)); + RSTCTRL.RSTFR = ch; //clear the reset causes before jumping to app... + GPIOR0 = ch; // but, stash the reset cause in GPIOR0 for use by app... + watchdogConfig(WDT_PERIOD_OFF_gc); + __asm__ __volatile__( + " jmp app\n" + ); + } +#else + /* + * Protect as much Reset Cause as possible for application + * and still skip bootloader if not necessary + */ + ch = RSTCTRL.RSTFR; + if (ch != 0) { + /* + * We want to run the bootloader when an external reset has occurred. + * On these mega0/XTiny chips, there are three types of ext reset: + * reset pin (may not exist), UPDI reset, and SW-request reset. + * One of these reset causes, together with watchdog reset, should + * mean that Optiboot timed out, and it's time to run the app. + * Other reset causes (notably poweron) should run the app directly. + * If a user app wants to utilize and detect watchdog resets, it + * must make sure that the other reset causes are cleared. + */ + if (ch & RSTCTRL_WDRF_bm) { + if (ch & RESET_EXTERNAL) { + /* + * Clear WDRF because it was most probably set by wdr in + * bootloader. It's also needed to avoid loop by broken + * application which could prevent entering bootloader. + */ + RSTCTRL.RSTFR = RSTCTRL_WDRF_bm; + } + } + if (!(ch & RESET_EXTERNAL)) { + /* + * save the reset flags in the designated register. + * This can be saved in a main program by putting code in + * .init0 (which executes before normal c init code) to save R2 + * to a global variable. + */ + __asm__ __volatile__(" mov r2, %0\n" :: "r"(ch)); + + // switch off watchdog + watchdogConfig(WDT_PERIOD_OFF_gc); + __asm__ __volatile__( + " jmp app\n" + ); + } + } +#endif // Fancy reset cause stuff + + watchdogReset(); +// _PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, 0); // full speed clock + + MYUART_TXPORT.DIR |= MYUART_TXPIN; // set TX pin to output + MYUART_TXPORT.OUT |= MYUART_TXPIN; // and "1" as per datasheet +#if defined (MYUART_PMUX_VAL) + MYPMUX_REG = MYUART_PMUX_VAL; // alternate pinout to use +#endif + if ((FUSE_OSCCFG & FUSE_FREQSEL_gm) == FREQSEL_16MHZ_gc) { + MYUART.BAUD = BAUD_SETTING_16; + } else { + MYUART.BAUD = BAUD_SETTING_20; + } + MYUART.DBGCTRL = 1; // run during debug + MYUART.CTRLC = (USART_CHSIZE_gm & USART_CHSIZE_8BIT_gc); // Async, Parity Disabled, 1 StopBit + MYUART.CTRLA = 0; // Interrupts: all off + MYUART.CTRLB = USART_RXEN_bm | USART_TXEN_bm; + + // Set up watchdog to trigger after a bit + // (nominally:, 1s for autoreset, longer for manual) + watchdogConfig(WDTPERIOD); + +#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) + /* Set LED pin as output */ + LED_PORT.DIR |= LED; +#endif + +#if LED_START_FLASHES > 0 + /* Flash onboard LED to signal entering of bootloader */ +# ifdef LED_INVERT + flash_led(LED_START_FLASHES * 2+1); +# else + flash_led(LED_START_FLASHES * 2); +# endif +#else +#if defined(LED_START_ON) +# ifndef LED_INVERT + /* Turn on LED to indicate starting bootloader (less code!) */ + LED_PORT.OUT |= LED; +# endif +#endif +#endif + + /* Forever loop: exits by causing WDT reset */ + for (;;) { + /* get character from UART */ + ch = getch(); + + if(ch == STK_GET_PARAMETER) { + unsigned char which = getch(); + verifySpace(); + /* + * Send optiboot version as "SW version" + * Note that the references to memory are optimized away. + */ + if (which == STK_SW_MINOR) { + putch(optiboot_version & 0xFF); + } else if (which == STK_SW_MAJOR) { + putch(optiboot_version >> 8); + } else { + /* + * GET PARAMETER returns a generic 0x03 reply for + * other parameters - enough to keep Avrdude happy + */ + putch(0x03); + } + } + else if(ch == STK_SET_DEVICE) { + // SET DEVICE is ignored + getNch(20); + } + else if(ch == STK_SET_DEVICE_EXT) { + // SET DEVICE EXT is ignored + getNch(5); + } + else if(ch == STK_LOAD_ADDRESS) { + // LOAD ADDRESS + address.bytes[0] = getch(); + address.bytes[1] = getch(); + // ToDo: will there be mega-0 chips with >128k of RAM? +/* UPDI chips apparently have byte-addressable FLASH ? + address.word *= 2; // Convert from word address to byte address +*/ + verifySpace(); + } + else if(ch == STK_UNIVERSAL) { +#ifndef RAMPZ + // UNIVERSAL command is ignored + getNch(4); + putch(0x00); +#endif + } + /* Write memory, length is big endian and is in bytes */ + else if(ch == STK_PROG_PAGE) { + // PROGRAM PAGE - any kind of page! + uint8_t desttype; + + GETLENGTH(length); + desttype = getch(); + + if (desttype == 'F') { + address.word += MAPPED_PROGMEM_START; + } else { + address.word += MAPPED_EEPROM_START; + } + // TODO: user row? + + do { + *(address.bptr++) = getch(); + } while (--length); + + // Read command terminator, start reply + verifySpace(); + /* + * Actually Write the buffer to flash (and wait for it to finish.) + */ + _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc); + while (NVMCTRL.STATUS & (NVMCTRL_FBUSY_bm|NVMCTRL_EEBUSY_bm)) + ; // wait for flash and EEPROM not busy, just in case. + } + /* Read memory block mode, length is big endian. */ + else if(ch == STK_READ_PAGE) { + uint8_t desttype; + GETLENGTH(length); + + desttype = getch(); + + verifySpace(); + if (desttype == 'F') { + address.word += MAPPED_PROGMEM_START; + } else { + address.word += MAPPED_EEPROM_START; + } + // TODO: user row? + + do { + putch(*(address.bptr++)); + } while (--length); + } + + /* Get device signature bytes */ + else if(ch == STK_READ_SIGN) { + // READ SIGN - return actual device signature from SIGROW + // This enables the same binary to be ued on multiple chips. + verifySpace(); + putch(SIGROW_DEVICEID0); + putch(SIGROW_DEVICEID1); + putch(SIGROW_DEVICEID2); + } + else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ + // Adaboot no-wait mod + watchdogConfig(WDT_PERIOD_8CLK_gc); + verifySpace(); + } + else { + // This covers the response to commands like STK_ENTER_PROGMODE + verifySpace(); + } + putch(STK_OK); + } +} + +void putch (char ch) { + while (0 == (MYUART.STATUS & USART_DREIF_bm)) + ; + MYUART.TXDATAL = ch; +} + +uint8_t getch (void) { + uint8_t ch, flags; + while (!(MYUART.STATUS & USART_RXCIF_bm)) + ; + flags = MYUART.RXDATAH; + ch = MYUART.RXDATAL; + if ((flags & USART_FERR_bm) == 0) + watchdogReset(); +#ifdef LED_DATA_FLASH + LED_PORT.IN |= LED; +#endif + + return ch; +} + +void getNch (uint8_t count) { + do getch(); while (--count); + verifySpace(); +} + +void verifySpace () { + if (getch() != CRC_EOP) { + watchdogConfig(WDT_PERIOD_8CLK_gc); // shorten WD timeout + while (1) // and busy-loop so that WD causes + ; // a reset and app start. + } + putch(STK_INSYNC); +} + +#if LED_START_FLASHES > 0 +void flash_led (uint8_t count) { + uint16_t delay; // at 20MHz/6, a 16bit delay counter is enough + while (count--) { + LED_PORT.IN |= LED; + // delay assuming 20Mhz OSC. It's only to "look about right", anyway. + for (delay = ((20E6/6)/150); delay; delay--) { + watchdogReset(); + if (MYUART.STATUS & USART_RXCIF_bm) + return; + } + } + watchdogReset(); // for breakpointing +} +#endif + + +/* + * Change the watchdog configuration. + * Could be a new timeout, could be off... + */ +void watchdogConfig (uint8_t x) { + while(WDT.STATUS & WDT_SYNCBUSY_bm) + ; // Busy wait for sycnhronization is required! + _PROTECTED_WRITE(WDT.CTRLA, x); +} + + +#ifndef APP_NOSPM + +/* + * Separate function for doing nvmctrl stuff. + * It's needed for application to do manipulate flash, since only the + * bootloader can write or erase flash, or write to the flash alias areas. + * Note that this is significantly different in the details than the + * do_spm() function provided on older AVRs. Same "vector", though. + * + * How it works: + * - if the "command" is legal, write it to NVMCTRL.CTRLA + * - if the command is not legal, store data to *address + * - wait for NVM to complete + * + * For example, to write a flash page: + * + */ +static void do_nvmctrl(uint16_t address, uint8_t command, uint8_t data) __attribute__ ((used)); +static void do_nvmctrl (uint16_t address, uint8_t command, uint8_t data) { + if (command <= NVMCTRL_CMD_gm) { + _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, command); + while (NVMCTRL.STATUS & (NVMCTRL_FBUSY_bm|NVMCTRL_EEBUSY_bm)) + ; // wait for flash and EEPROM not busy, just in case. + } else { + *(uint8_t *)address = data; + } +} +#endif + + +#ifdef BIGBOOT +/* + * Optiboot is designed to fit in 512 bytes, with a minimum feature set. + * Some chips have a minimum bootloader size of 1024 bytes, and sometimes + * it is desirable to add extra features even though 512bytes is exceedded. + * In that case, the BIGBOOT can be used. + * Our extra features so far don't come close to filling 1k, so we can + * add extra "frivolous" data to the image. In particular, we can add + * information about how Optiboot was built (which options were selected, + * what version, all in human-readable form (and extractable from the + * binary with avr-strings.) + * + * This can always be removed or trimmed if more actual program space + * is needed in the future. Currently the data occupies about 160 bytes, + */ +#define xstr(s) str(s) +#define str(s) #s +#define OPTFLASHSECT __attribute__((section(".fini8"))) +#define OPT2FLASH(o) OPTFLASHSECT const char f##o[] = #o "=" xstr(o) + + +#ifdef LED_START_FLASHES +OPT2FLASH(LED_START_FLASHES); +#endif +#ifdef LED_DATA_FLASH +OPT2FLASH(LED_DATA_FLASH); +#endif +#ifdef LED_START_ON +OPT2FLASH(LED_START_ON); +#endif +#ifdef LED_NAME +OPTFLASHSECT const char f_LED[] = "LED=" LED_NAME; +#endif + +#ifdef SUPPORT_EEPROM +OPT2FLASH(SUPPORT_EEPROM); +#endif + +#ifdef BAUD_RATE +OPT2FLASH(BAUD_RATE); +#endif +#ifdef UARTTX +OPTFLASHSECT const char f_uart[] = "UARTTX=" UART_NAME; +#endif + +OPTFLASHSECT const char f_date[] = "Built:" __DATE__ ":" __TIME__; +#ifdef BIGBOOT +OPT2FLASH(BIGBOOT); +#endif +OPTFLASHSECT const char f_device[] = "Device=" xstr(__AVR_DEVICE_NAME__); +#ifdef OPTIBOOT_CUSTOMVER +# if OPTIBOOT_CUSTOMVER != 0 +OPT2FLASH(OPTIBOOT_CUSTOMVER); +# endif +#endif +OPTFLASHSECT const char f_version[] = "Version=" xstr(OPTIBOOT_MAJVER) "." xstr(OPTIBOOT_MINVER); + +#endif + +// Dummy application that will loop back into the bootloader if not overwritten +// This gives the bootloader somewhere to jump, and by referencing otherwise +// unused variables/functions in the bootloader, it prevents them from being +// omitted by the linker, with fewer mysterious link options. +void __attribute__((section( ".application"))) + __attribute__((naked)) app(); +void app() +{ + uint8_t ch; + + ch = RSTCTRL.RSTFR; + RSTCTRL.RSTFR = ch; // reset causes + *(volatile uint16_t *)(&optiboot_version); // reference the version + do_nvmctrl(0, NVMCTRL_CMD_PAGEBUFCLR_gc, 0); // reference this function! + __asm__ __volatile__ ("jmp 0"); // similar to running off end of memory +// _PROTECTED_WRITE(RSTCTRL.SWRR, 1); // cause new reset +} diff --git a/megaavr/bootloaders/optiboot/parse_options.mk b/megaavr/bootloaders/optiboot/parse_options.mk new file mode 100755 index 0000000..3905200 --- /dev/null +++ b/megaavr/bootloaders/optiboot/parse_options.mk @@ -0,0 +1,142 @@ +# Make command-line Options for Optiboot, Optiboot-Mega0 +# Permit commands like "make atmega4809 LED_START_FLASHES=10" to pass the +# appropriate parameters ("-DLED_START_FLASHES=10") to gcc +# + +ifdef PRODUCTION +ifneq ($(PRODUCTION),0) +VERSION_CMD = -DPRODUCTION=1 +endif +dummy = FORCE +endif + + +# Build Options + +ifdef CUSTOM_VERSION +ifneq ($(CUSTOM_VERSION), 0) +VERSION_CMD = -DOPTIBOOT_CUSTOMVER=$(CUSTOM_VERSION) +else +VERSION_CMD = -DPRODUCTION=1 +endif +dummy = FORCE +endif + +# BIGBOOT: Include extra features, up to 1K. +ifdef BIGBOOT +ifneq ($(BIGBOOT), 0) +BIGBOOT_CMD = -DBIGBOOT=1 +dummy = FORCE +endif +endif + +ifdef SUPPORT_EEPROM +ifneq ($(SUPPORT_EEPROM), 0) +SUPPORT_EEPROM_CMD = -DSUPPORT_EEPROM +dummy = FORCE +endif +endif + +ifdef NO_APP_SPM +ifneq ($(NO_APP_SPM),0) +APPSPM_CMD = -DAPP_NOSPM=1 +endif +endif + + +# LED options + +ifdef LED +LED_CMD = -DLED=$(LED) +dummy = FORCE +endif + +ifdef LED_START_FLASHES +LED_START_FLASHES_CMD = -DLED_START_FLASHES=$(LED_START_FLASHES) +dummy = FORCE +else +LED_START_FLASHES_CMD = -DLED_START_FLASHES=3 +endif + +ifdef LED_DATA_FLASH +ifneq ($(LED_DATA_FLASH), 0) +LED_DATA_FLASH_CMD = -DLED_DATA_FLASH=1 +dummy = FORCE +endif +endif + +ifdef LED_START_ON +ifneq ($(LED_START_ON), 0) +LED_START_ON_CMD = -DLED_START_ON=1 +endif +dummy = FORCE +endif + +ifdef LED_INVERT +ifneq ($(LED_INVERT), 0) +LEDINV_CMD = -DLED_INVERT=1 +endif +dummy = FORCE +endif + + +# UART options + +ifdef BAUD_RATE +BAUD_RATE_CMD = -DBAUD_RATE=$(BAUD_RATE) +dummy = FORCE +else +BAUD_RATE_CMD = -DBAUD_RATE=115200 +endif + +ifdef SOFT_UART +ifneq ($(SOFT_UART), 0) +SOFT_UART_CMD = -DSOFT_UART=1 +dummy = FORCE +endif +endif + +ifdef SINGLESPEED +ifneq ($(SINGLESPEED), 0) +SS_CMD = -DSINGLESPEED=1 +endif +endif + + +#CPU Options + +ifdef TIMEOUT +TIMEOUT_CMD = -DWDTTIME=$(TIMEOUT) +dummy = FORCE +endif + +ifdef RESETPIN +RESETPIN_CMD = -DRSTPIN=$(RESETPIN) +dummy = FORCE +endif + +ifdef AVR_FREQ +FCPU_CMD = -DF_CPU=$(AVR_FREQ) +dummy = FORCE +endif + + + +LED_OPTIONS = $(LED_START_FLASHES_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(LED_START_ON_CMD) $(LEDINV_CMD) +CPU_OPTIONS = $(RESETPIN_CMD) $(TIMEOUT_CMD) $(FCPU_CMD) +COMMON_OPTIONS = $(BIGBOOT_CMD) $(APPSPM_CMD) $(VERSION_CMD) +COMMON_OPTIONS += $(SUPPORT_EEPROM_CMD) + +#UART is handled separately and only passed for devices with more than one. +ifdef UART +UART_CMD = -DUART=$(UART) +endif +ifdef UARTTX +UART_CMD = -DUARTTX=$(UARTTX) +endif + +UART_OPTIONS = $(UART_CMD) $(BAUD_RATE_CMD) $(SOFT_UART_CMD) $(SS_CMD) + +ifneq ($(SKIP_BOOTLOADER_ON_POR),0) +POR = -DSTART_APP_ON_POR +endif diff --git a/megaavr/bootloaders/optiboot/pin_defs_x.h b/megaavr/bootloaders/optiboot/pin_defs_x.h new file mode 100755 index 0000000..a51c0f0 --- /dev/null +++ b/megaavr/bootloaders/optiboot/pin_defs_x.h @@ -0,0 +1,815 @@ +/* + * pin_defs.h + * optiboot helper defining the default pin assignments (LED, SOFT_UART) + * for the various chips that are supported. This also has some ugly macros + * for selecting among various UARTs and LED possibilities using command-line + * defines like "UART=2 LED=B5" + * + * Copyright 2013-2015 by Bill Westfield. + * Copyright 2010 by Peter Knight. + * This software is licensed under version 2 of the Gnu Public Licence. + * See optiboot.c for details. + */ + + +/* + * ------------------------------------------------------------------------ + * A bunch of macros to enable the LED to be specifed as "B5" for bit 5 + * of port B, and similar. + * We define symbols for all the legal combination of port/bit on a chip, + * and do pre-processor tests to see if there's a match. This ends up + * being very verbose, but it is pretty easy to generate semi-automatically. + * (We wouldn't need this if the preprocessor could do string compares.) + */ + +// Symbols for each PortA bit. +#define A0 0x100 +#define A1 0x101 +#define A2 0x102 +#define A3 0x103 +#define A4 0x104 +#define A5 0x105 +#define A6 0x106 +#define A7 0x107 +// If there is no PORTA on this chip, don't allow these to be used +// (and indicate the error by redefining LED) +#if !defined(PORTA) +#if LED >= A0 && LED <= A7 +#undef LED +#define LED -1 +#endif +#endif + +#define B0 0x200 +#define B1 0x201 +#define B2 0x202 +#define B3 0x203 +#define B4 0x204 +#define B5 0x205 +#define B6 0x206 +#define B7 0x207 +#if !defined(PORTB) +#if LED >= B0 && LED <= B7 +#undef LED +#define LED -1 +#endif +#endif + +#define C0 0x300 +#define C1 0x301 +#define C2 0x302 +#define C3 0x303 +#define C4 0x304 +#define C5 0x305 +#define C6 0x306 +#define C7 0x307 +#if !(defined(PORTC)) +#if LED >= C0 && LED <= C7 +#undef LED +#define LED -1 +#endif +#endif + +#define D0 0x400 +#define D1 0x401 +#define D2 0x402 +#define D3 0x403 +#define D4 0x404 +#define D5 0x405 +#define D6 0x406 +#define D7 0x407 +#if !(defined(PORTD)) +#if LED >= D0 && LED <= D7 +#undef LED +#define LED -1 +#endif +#endif + +#define E0 0x500 +#define E1 0x501 +#define E2 0x502 +#define E3 0x503 +#define E4 0x504 +#define E5 0x505 +#define E6 0x506 +#define E7 0x507 +#if !(defined(PORTE)) +#if LED >= E0 && LED <= E7 +#undef LED +#define LED -1 +#endif +#endif + +#define F0 0x600 +#define F1 0x601 +#define F2 0x602 +#define F3 0x603 +#define F4 0x604 +#define F5 0x605 +#define F6 0x606 +#define F7 0x607 +#if !(defined(PORTF)) +#if LED >= F0 && LED <= F7 +#undef LED +#define LED -1 +#endif +#endif + +#define G0 0x700 +#define G1 0x701 +#define G2 0x702 +#define G3 0x703 +#define G4 0x704 +#define G5 0x705 +#define G6 0x706 +#define G7 0x707 +#if !defined(PORTG) +#if LED >= G0 && LED <= G7 +#undef LED +#define LED -1 +#endif +#endif + +#define H0 0x800 +#define H1 0x801 +#define H2 0x802 +#define H3 0x803 +#define H4 0x804 +#define H5 0x805 +#define H6 0x806 +#define H7 0x807 +#if !(defined(PORTH)) +#if LED >= H0 && LED <= H7 +#undef LED +#define LED -1 +#endif +#endif + +#define J0 0xA00 +#define J1 0xA01 +#define J2 0xA02 +#define J3 0xA03 +#define J4 0xA04 +#define J5 0xA05 +#define J6 0xA06 +#define J7 0xA07 +#if !(defined(PORTJ)) +#if LED >= J0 && LED <= J7 +#undef LED +#define LED -1 +#endif +#endif + +#define K0 0xB00 +#define K1 0xB01 +#define K2 0xB02 +#define K3 0xB03 +#define K4 0xB04 +#define K5 0xB05 +#define K6 0xB06 +#define K7 0xB07 +#if !(defined(PORTK)) +#if LED >= K0 && LED <= K7 +#undef LED +#define LED -1 +#endif +#endif + +#define L0 0xC00 +#define L1 0xC01 +#define L2 0xC02 +#define L3 0xC03 +#define L4 0xC04 +#define L5 0xC05 +#define L6 0xC06 +#define L7 0xC07 +#if !(defined(PORTL)) +#if LED >= L0 && LED <= L7 +#undef LED +#define LED -1 +#endif +#endif + + +/* + * A statement like "#if LED == B0" will evaluation (in the preprocessor) + * to #if C0 == B0, and then to #if 0x301 == 0x201 + */ +#if LED == B0 +#define LED_NAME "B0" +#undef LED +#define LED_PORT VPORTB +#define LED (1< #include + #ifdef __cplusplus extern "C"{ #endif -/* Analog reference options */ - -/* Change in mega4809: two places to define analog reference - - VREF peripheral defines internal reference - - analog peripherals define internal/Vdd/external -*/ - - // internal from VREF - - /* Values shifted to avoid clashing with ADC REFSEL defines - Will shift back in analog_reference function - */ -#define INTERNAL0V55 (VREF_ADC0REFSEL_0V55_gc >> VREF_ADC0REFSEL_gp) -#define INTERNAL1V1 (VREF_ADC0REFSEL_1V1_gc >> VREF_ADC0REFSEL_gp) -#define INTERNAL2V5 (VREF_ADC0REFSEL_2V5_gc >> VREF_ADC0REFSEL_gp) -#define INTERNAL4V3 (VREF_ADC0REFSEL_4V34_gc >> VREF_ADC0REFSEL_gp) -#define INTERNAL1V5 (VREF_ADC0REFSEL_1V5_gc >> VREF_ADC0REFSEL_gp) - -#define DEFAULT INTERNAL0V55 -#define INTERNAL ADC_REFSEL_INTREF_gc -#define VDD ADC_REFSEL_VDDREF_gc -#define EXTERNAL ADC_REFSEL_VREFA_gc +// Analog reference options +#define INTERNAL0V55 (VREF_ADC0REFSEL_0V55_gc >> VREF_ADC0REFSEL_gp) +#define INTERNAL1V1 (VREF_ADC0REFSEL_1V1_gc >> VREF_ADC0REFSEL_gp) +#define INTERNAL1V5 (VREF_ADC0REFSEL_1V5_gc >> VREF_ADC0REFSEL_gp) +#define INTERNAL2V5 (VREF_ADC0REFSEL_2V5_gc >> VREF_ADC0REFSEL_gp) +#define INTERNAL4V3 (VREF_ADC0REFSEL_4V34_gc >> VREF_ADC0REFSEL_gp) +#define INTERNAL4V34 INTERNAL4V3 +#define DEFAULT ADC_REFSEL_VDDREF_gc +#define INTERNAL ADC_REFSEL_INTREF_gc +#define VDD ADC_REFSEL_VDDREF_gc +#define EXTERNAL ADC_REFSEL_VREFA_gc +#define ADC_TEMPERATURE ADC_MUXPOS_TEMPSENSE_gc +#define VCC_5V0 2 +#define VCC_3V3 1 +#define VCC_1V8 0 -#define VCC_5V0 2 -#define VCC_3V3 1 -#define VCC_1V8 0 - -#define interrupts() sei() -#define noInterrupts() cli() +#define interrupts() sei() +#define noInterrupts() cli() // avr-libc defines _NOP() since 1.6.2 #ifndef _NOP -#define _NOP() do { __asm__ volatile ("nop"); } while (0) + #define _NOP() do { __asm__ volatile ("nop"); } while (0) #endif -/* Allows performing a correction on the CPU value using the signature row - values indicating oscillator error provided from the device manufacturer */ +/* Allows performing a correction on the CPU value using the signature row + values indicating oscillator error provided from the device manufacturer */ #define PERFORM_SIGROW_CORRECTION_F_CPU 0 /* Variable containing corrected F_CPU value, after checks for safe operating - frequency vs supply voltage, oscillator fuse setting and MCLK divider. - Also includes the correction from signature row values if above #define - PERFORM_SIGROW_CORRECTION_F_CPU = 1 */ + frequency vs supply voltage, oscillator fuse setting and MCLK divider. + Also includes the correction from signature row values if above #define + PERFORM_SIGROW_CORRECTION_F_CPU = 1 */ extern uint32_t F_CPU_CORRECTED; uint16_t clockCyclesPerMicrosecondComp(uint32_t clk); @@ -83,10 +73,10 @@ unsigned long microsecondsToClockCycles(unsigned long microseconds); // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. -extern const uint8_t PROGMEM digital_pin_to_port[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask[]; -extern const uint8_t PROGMEM digital_pin_to_bit_position[]; -extern const uint8_t PROGMEM digital_pin_to_timer[]; +extern const uint8_t digital_pin_to_port[]; +extern const uint8_t digital_pin_to_bit_mask[]; +extern const uint8_t digital_pin_to_bit_position[]; +extern const uint8_t digital_pin_to_timer[]; // Get the bit location within the hardware port of the given virtual pin. // This comes from the pins_*.c file for the active board configuration. @@ -113,19 +103,18 @@ extern const uint8_t PROGMEM digital_pin_to_timer[]; #define TIMERB3 5 void setup_timers(); -bool isDoubleBondedActive(uint8_t pin); -#define digitalPinToPort(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_port + pin) : NOT_A_PIN ) -#define digitalPinToBitPosition(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_bit_position + pin) : NOT_A_PIN ) -#define analogPinToBitPosition(pin) ( (pin < NUM_ANALOG_INPUTS) ? pgm_read_byte(digital_pin_to_bit_position + pin + ANALOG_INPUT_OFFSET) : NOT_A_PIN ) -#define digitalPinToBitMask(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_bit_mask + pin) : NOT_A_PIN ) -#define analogPinToBitMask(pin) ( (pin < NUM_ANALOG_INPUTS) ? pgm_read_byte(digital_pin_to_bit_mask + pin + ANALOG_INPUT_OFFSET) : NOT_A_PIN ) -#define digitalPinToTimer(pin) ( (pin < NUM_TOTAL_PINS) ? pgm_read_byte(digital_pin_to_timer + pin) : NOT_ON_TIMER ) +#define digitalPinToPort(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_port[pin] : NOT_A_PIN ) +#define digitalPinToBitPosition(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_bit_position[pin] : NOT_A_PIN ) +#define digitalPinToBitMask(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_bit_mask[pin] : NOT_A_PIN ) +#define digitalPinToTimer(pin) ( (pin < NUM_TOTAL_PINS) ? digital_pin_to_timer[pin] : NOT_ON_TIMER ) +#define analogPinToBitPosition(pin) ( (digitalOrAnalogPinToDigital(pin) != NOT_A_PIN) ? digital_pin_to_bit_position[digitalOrAnalogPinToDigital(pin)] : NOT_A_PIN ) +#define analogPinToBitMask(pin) ( (digitalOrAnalogPinToDigital(pin) != NOT_A_PIN) ? digital_pin_to_bit_mask[digitalOrAnalogPinToDigital(pin)] : NOT_A_PIN ) #define portToPortStruct(port) ( (port < NUM_TOTAL_PORTS) ? ((PORT_t *)&PORTA + port) : NULL) #define digitalPinToPortStruct(pin) ( (pin < NUM_TOTAL_PINS) ? ((PORT_t *)&PORTA + digitalPinToPort(pin)) : NULL) #define getPINnCTRLregister(port, bit_pos) ( ((port != NULL) && (bit_pos < NOT_A_PIN)) ? ((volatile uint8_t *)&(port->PIN0CTRL) + bit_pos) : NULL ) -#define digitalPinToInterrupt(p) (P) +#define digitalPinToInterrupt(P) (P) #define portOutputRegister(P) ( (volatile uint8_t *)( &portToPortStruct(P)->OUT ) ) #define portInputRegister(P) ( (volatile uint8_t *)( &portToPortStruct(P)->IN ) ) @@ -147,6 +136,207 @@ bool isDoubleBondedActive(uint8_t pin); #error "Targets with both UART0 and CDC serial not supported" #endif +enum timers_prescaler_t : uint8_t { + TCA_DIV1 = 0x00, + TCA_DIV2 = 0x02, + TCA_DIV4 = 0x04, + TCA_DIV8 = 0x06, + TCA_DIV16 = 0x08, + TCA_DIV64 = 0x0A, + TCA_DIV256 = 0x0C, + TCA_DIV1024 = 0x0E, + TCB_DIV1 = 0x00, + TCB_DIV2 = 0x20, + TCB_CLKTCA = 0x40, +}; + +void pwmWrite(pwm_timers_t pwmTimer, uint16_t value, timers_route_t timerRoute = ROUTE_UNTOUCHED); +void pwmPrescaler(pwm_timers_t pwmTimer, timers_prescaler_t prescaler); +void pwmSetResolution(pwm_timers_t pwmTimer, uint8_t maxValue); + +// These are used as the second to N argument to pinConfigure(pin, ...) +// Directives are handled in the order they show up on this list, by pin function: +// PIN_DIR Direction +// PIN_OUT Output value +// PIN_ISC Enable and interrupt mode. If interrupts are turned on w/out the ISR, it will trigger dirty reset. +// PIN_PULLUP Pullups +// PIN_INLVL Input levels (MVIO parts only - everything else is schmitt trigger only, except on I2C pins acting as I2C with SMBus levels enabled. ) +// PIN_INVERT Invert pin +// +// Systematically named constants can be made by combining those names with the postfixes here +// except for PIN_ISC which is not a non-binary option. Valid values are listed below. +// _SET, _CLR, and _TGL can be used as a postfix on all binary options. +// _TOGGLE and _TGL are interchangeable as well. +// Additional names are defined where they might be easier to remember. +typedef enum : uint16_t +{ + // OUTPUT + PIN_DIR_SET = 0x0001, + PIN_DIRSET = 0x0001, + PIN_DIR_OUTPUT = 0x0001, + PIN_DIR_OUT = 0x0001, + // INPUT + PIN_DIR_CLR = 0x0002, + PIN_DIRCLR = 0x0002, + PIN_DIR_INPUT = 0x0002, + PIN_DIR_IN = 0x0002, + // TOGGLE INPUT/OUTPUT + PIN_DIR_TGL = 0x0003, + PIN_DIRTGL = 0x0003, + PIN_DIR_TOGGLE = 0x0003, + // HIGH + PIN_OUT_SET = 0x0004, + PIN_OUTSET = 0x0004, + PIN_OUT_HIGH = 0x0004, + // LOW + PIN_OUT_CLR = 0x0008, + PIN_OUTCLR = 0x0008, + PIN_OUT_LOW = 0x0008, +// CHANGE/TOGGLE + PIN_OUT_TGL = 0x000C, + PIN_OUTTGL = 0x000C, + PIN_OUT_TOGGLE = 0x000C, +//Interrupt disabled but input buffer enabled + PIN_ISC_ENABLE = 0x0080, + PIN_INPUT_ENABLE = 0x0080, + // Interrupt on change + PIN_ISC_CHANGE = 0x0090, + PIN_INT_CHANGE = 0x0090, +// Interrupt on rising edge + PIN_ISC_RISE = 0x00A0, + PIN_INT_RISE = 0x00A0, +// Interrupt on falling edge + PIN_ISC_FALL = 0x00B0, + PIN_INT_FALL = 0x00B0, +// Interrupt and input buffer disabled + PIN_ISC_DISABLE = 0x00C0, + PIN_INPUT_DISABLE = 0x00C0, +// Interrupt enabled with sense on low level + PIN_ISC_LEVEL = 0x00D0, + PIN_INT_LEVEL = 0x00D0, +// PULLUP ON + PIN_PULLUP_ON = 0x0100, + PIN_PULLUP = 0x0100, + PIN_PULLUP_SET = 0x0100, +// PULLUP OFF + PIN_PULLUP_OFF = 0x0200, + PIN_PULLUP_CLR = 0x0200, + PIN_NOPULLUP = 0x0200, +// PULLUP TOGGLE + PIN_PULLUP_TGL = 0x0300, + PIN_PULLUP_TOGGLE = 0x0300, +// PIN INVERT ON + PIN_INVERT_ON = 0x4000, + PIN_INVERT_SET = 0x4000, +// PIN INVERT OFF + PIN_INVERT_OFF = 0x8000, + PIN_INVERT_CLR = 0x8000, +// PIN_INVERT_TOGGLE + PIN_INVERT_TGL = 0xC000, + PIN_INVERT_TOGGLE = 0xC000, +} pin_configure_t; + +/** + * @brief Helper functions to catch the last argument in the pincfg recursion loop + * + * @param mode Mode parameter + * @return pin_configure_t + */ + +inline pin_configure_t pincfg(const pin_configure_t mode) +{ + return mode; +} + +/** + * @brief Helper functions to catch the nth in the pincfg recursion loop + * + * @param digital_pin Arduino pin + * @param mode First "mode" parameter + * @param modes Nth "mode" parameter + * @return uint16_t pin configuration or'ed together + */ +template +uint16_t pincfg(const pin_configure_t mode, const MODES&... modes) +{ + return mode | pincfg(modes...); +} + + +/** + * @brief Variadic template function for configuring a pin + * + * @param digital_pin Arduino pin number + * @param mode First "mode" parameter + * @param modes Nth "mode" parameter + */ +template +void pinConfigure(const uint8_t digital_pin, const pin_configure_t mode, const MODES&... modes) +{ + // Or-ing together the arguments using recursion + uint16_t pin_config = pincfg(mode, modes...); + + uint8_t bit_mask = digitalPinToBitMask(digital_pin); + if(bit_mask == NOT_A_PIN || !pin_config) // Return if digital pin is invalid or the other parameters or out to zero + return; + + uint8_t bit_pos = digitalPinToBitPosition(digital_pin); + volatile uint8_t *portbase = (volatile uint8_t*) digitalPinToPortStruct(digital_pin); + + // Write to selected pin direction register + uint8_t setting = pin_config & 0x03; // Mask out direction bits (DIR, DIRSET, DIRCLR, DIRTGL) + if(setting) + *(portbase + setting) = bit_mask; + + // Write to selected output register + pin_config >>= 2; + setting = pin_config & 0x03; + if(setting) + *(portbase + 4 + setting) = bit_mask; + + // Return if there is nothing more to configure + if(!(pin_config & 0x3FFC)) + return; + + uint8_t oldSREG = SREG; // Store SREG + cli(); // Disable interrupts + + // PINnCTRL register + pin_config >>= 2; + uint8_t pinncfg = *(portbase + 0x10 + bit_pos); + // Input sense configuration (ISC) + if(pin_config & 0x08) + pinncfg = (pinncfg & 0xF8) | (pin_config & PORT_ISC_gm); + // Pullup resistor + uint8_t temp = pin_config & 0x30; + if(temp) + { + if(temp == 0x30) + pinncfg ^= PORT_PULLUPEN_bm; // Toggle pullup + else if(temp == 0x20) + pinncfg &= ~(PORT_PULLUPEN_bm); // Clear pullup + else + pinncfg |= PORT_PULLUPEN_bm; // Set pullup + } + // Invert pin + pin_config >>= 8; + temp = pin_config & 0x0C; + if(temp) + { + if(temp == 0x0C) + pinncfg ^= PORT_INVEN_bm; // Toggle invert + else if(temp == 0x08) + pinncfg &= ~(PORT_INVEN_bm); // Clear + else + pinncfg |= PORT_INVEN_bm; // Set + } + // Write to PINnCTRL register + *(portbase + 0x10 + bit_pos) = pinncfg; + + // Restore SREG + SREG = oldSREG; +} + #endif #include "pins_arduino.h" diff --git a/megaavr/cores/coreX-corefiles/CDC.cpp b/megaavr/cores/coreX-corefiles/CDC.cpp index 9c2b947..7c5cc04 100644 --- a/megaavr/cores/coreX-corefiles/CDC.cpp +++ b/megaavr/cores/coreX-corefiles/CDC.cpp @@ -28,11 +28,11 @@ typedef struct { - uint32_t dwDTERate; - uint8_t bCharFormat; - uint8_t bParityType; - uint8_t bDataBits; - uint8_t lineState; + uint32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; + uint8_t lineState; } LineInfo; static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; @@ -45,137 +45,140 @@ static uint8_t wdtcsr_save; extern const CDCDescriptor _cdcInterface PROGMEM; const CDCDescriptor _cdcInterface = { - D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), - - // CDC communication interface - D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), - D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) - D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) - D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported - D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), - - // CDC data interface - D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0), - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) + D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + + // CDC communication interface + D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), + D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd) + D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (not) + D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported + D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0 + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), + + // CDC data interface + D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), + D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0), + D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0) }; bool isLUFAbootloader() { - return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE; + return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE; } int CDC_GetInterface(uint8_t* interfaceNum) { - interfaceNum[0] += 2; // uses 2 - return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); + interfaceNum[0] += 2; // Uses 2 + return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); } -bool CDC_Setup(USBSetup& setup) +bool CDC_Setup(USBSetup &setup) { - uint8_t r = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) - { - if (CDC_GET_LINE_CODING == r) - { - USB_SendControl(0,(void*)&_usbLineInfo,7); - return true; - } - } - - if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) - { - if (CDC_SEND_BREAK == r) - { - breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; - } - - if (CDC_SET_LINE_CODING == r) - { - USB_RecvControl((void*)&_usbLineInfo,7); - } - - if (CDC_SET_CONTROL_LINE_STATE == r) - { - _usbLineInfo.lineState = setup.wValueL; - - // auto-reset into the bootloader is triggered when the port, already - // open at 1200 bps, is closed. this is the signal to start the watchdog - // with a relatively long period so it can finish housekeeping tasks - // like servicing endpoints before the sketch ends - - uint16_t magic_key_pos = MAGIC_KEY_POS; + uint8_t r = setup.bRequest; + uint8_t requestType = setup.bmRequestType; + + if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) + { + if (CDC_GET_LINE_CODING == r) + { + USB_SendControl(0, (void *)&_usbLineInfo, 7); + return true; + } + } + + if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) + { + if (CDC_SEND_BREAK == r) + { + breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; + } + + if (CDC_SET_LINE_CODING == r) + { + USB_RecvControl((void *)&_usbLineInfo, 7); + } + + if (CDC_SET_CONTROL_LINE_STATE == r) + { + _usbLineInfo.lineState = setup.wValueL; + + // auto-reset into the bootloader is triggered when the port, already + // open at 1200 bps, is closed. this is the signal to start the watchdog + // with a relatively long period so it can finish housekeeping tasks + // like servicing endpoints before the sketch ends + + uint16_t magic_key_pos = MAGIC_KEY_POS; // If we don't use the new RAMEND directly, check manually if we have a newer bootloader. // This is used to keep compatible with the old leonardo bootloaders. // You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check. -#if MAGIC_KEY_POS != (RAMEND-1) - // For future boards save the key in the inproblematic RAMEND - // Which is reserved for the main() return value (which will never return) - if (isLUFAbootloader()) { - // horray, we got a new bootloader! - magic_key_pos = (RAMEND-1); - } +#if MAGIC_KEY_POS != (RAMEND - 1) + // For future boards save the key in the inproblematic RAMEND + // Which is reserved for the main() return value (which will never return) + if (isLUFAbootloader()) + { + // horray, we got a new bootloader! + magic_key_pos = (RAMEND - 1); + } #endif - // We check DTR state to determine if host port is open (bit 0 of lineState). - if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) - { -#if MAGIC_KEY_POS != (RAMEND-1) - // Backup ram value if its not a newer bootloader and it hasn't already been saved. - // This should avoid memory corruption at least a bit, not fully - if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) { - *(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos; - } + // We check DTR state to determine if host port is open (bit 0 of lineState). + if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0) + { +#if MAGIC_KEY_POS != (RAMEND - 1) + // Backup ram value if its not a newer bootloader and it hasn't already been saved. + // This should avoid memory corruption at least a bit, not fully + if (magic_key_pos != (RAMEND - 1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) + { + *(uint16_t *)(RAMEND - 1) = *(uint16_t *)magic_key_pos; + } #endif - // Store boot key - *(uint16_t *)magic_key_pos = MAGIC_KEY; - // Save the watchdog state in case the reset is aborted. - wdtcsr_save = WDTCSR; - wdt_enable(WDTO_120MS); - } - else if (*(uint16_t *)magic_key_pos == MAGIC_KEY) - { - // Most OSs do some intermediate steps when configuring ports and DTR can - // twiggle more than once before stabilizing. - // To avoid spurious resets we set the watchdog to 120ms and eventually - // cancel if DTR goes back high. - // Cancellation is only done if an auto-reset was started, which is - // indicated by the magic key having been set. - - wdt_reset(); - // Restore the watchdog state in case the sketch was using it. - WDTCSR |= (1<= 0) { - return 1 + USB_Available(CDC_RX); - } - return USB_Available(CDC_RX); + if (peek_buffer >= 0) + return 1 + USB_Available(CDC_RX); + return USB_Available(CDC_RX); } int Serial_::peek(void) { - if (peek_buffer < 0) - peek_buffer = USB_Recv(CDC_RX); - return peek_buffer; + if (peek_buffer < 0) + peek_buffer = USB_Recv(CDC_RX); + return peek_buffer; } int Serial_::read(void) { - if (peek_buffer >= 0) { - int c = peek_buffer; - peek_buffer = -1; - return c; - } - return USB_Recv(CDC_RX); + if (peek_buffer >= 0) + { + int c = peek_buffer; + peek_buffer = -1; + return c; + } + return USB_Recv(CDC_RX); } int Serial_::availableForWrite(void) { - return USB_SendSpace(CDC_TX); + return USB_SendSpace(CDC_TX); } void Serial_::flush(void) { - USB_Flush(CDC_TX); + USB_Flush(CDC_TX); } size_t Serial_::write(uint8_t c) { - return write(&c, 1); + return write(&c, 1); } size_t Serial_::write(const uint8_t *buffer, size_t size) { - /* only try to send bytes if the high-level CDC connection itself - is open (not just the pipe) - the OS should set lineState when the port - is opened and clear lineState when the port is closed. - bytes sent before the user opens the connection or after - the connection is closed are lost - just like with a UART. */ - - // TODO - ZE - check behavior on different OSes and test what happens if an - // open connection isn't broken cleanly (cable is yanked out, host dies - // or locks up, or host virtual serial port hangs) - if (_usbLineInfo.lineState > 0) { - int r = USB_Send(CDC_TX,buffer,size); - if (r > 0) { - return r; - } else { - setWriteError(); - return 0; - } - } - setWriteError(); - return 0; + /* only try to send bytes if the high-level CDC connection itself + is open (not just the pipe) - the OS should set lineState when the port + is opened and clear lineState when the port is closed. + bytes sent before the user opens the connection or after + the connection is closed are lost - just like with a UART. */ + + // TODO - ZE - check behavior on different OSes and test what happens if an + // open connection isn't broken cleanly (cable is yanked out, host dies + // or locks up, or host virtual serial port hangs) + if (_usbLineInfo.lineState > 0) + { + int r = USB_Send(CDC_TX, buffer, size); + if (r > 0) + { + return r; + } + else + { + setWriteError(); + return 0; + } + } + setWriteError(); + return 0; } // This operator is a convenient way for a sketch to check whether the // port has actually been configured and opened by the host (as opposed -// to just being connected to the host). It can be used, for example, in +// to just being connected to the host). It can be used, for example, in // setup() before printing to ensure that an application on the host is // actually ready to receive and display the data. // We add a short delay before returning to fix a bug observed by Federico // where the port is configured (lineState != 0) but not quite opened. -Serial_::operator bool() { - bool result = false; - if (_usbLineInfo.lineState > 0) - result = true; - delay(10); - return result; +Serial_::operator bool() +{ + bool result = false; + if (_usbLineInfo.lineState > 0) + result = true; + delay(10); + return result; } -unsigned long Serial_::baud() { - // Disable interrupts while reading a multi-byte value - uint32_t baudrate; - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - baudrate = _usbLineInfo.dwDTERate; - } - return baudrate; +unsigned long Serial_::baud() +{ + // Disable interrupts while reading a multi-byte value + uint32_t baudrate; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + baudrate = _usbLineInfo.dwDTERate; + } + return baudrate; } -uint8_t Serial_::stopbits() { - return _usbLineInfo.bCharFormat; +uint8_t Serial_::stopbits() +{ + return _usbLineInfo.bCharFormat; } -uint8_t Serial_::paritytype() { - return _usbLineInfo.bParityType; +uint8_t Serial_::paritytype() +{ + return _usbLineInfo.bParityType; } -uint8_t Serial_::numbits() { - return _usbLineInfo.bDataBits; +uint8_t Serial_::numbits() +{ + return _usbLineInfo.bDataBits; } -bool Serial_::dtr() { - return _usbLineInfo.lineState & 0x1; +bool Serial_::dtr() +{ + return _usbLineInfo.lineState & 0x1; } -bool Serial_::rts() { - return _usbLineInfo.lineState & 0x2; +bool Serial_::rts() +{ + return _usbLineInfo.lineState & 0x2; } -int32_t Serial_::readBreak() { - int32_t ret; - // Disable IRQs while reading and clearing breakValue to make - // sure we don't overwrite a value just set by the ISR. - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - ret = breakValue; - breakValue = -1; - } - return ret; +int32_t Serial_::readBreak() +{ + int32_t ret; + // Disable IRQs while reading and clearing breakValue to make + // sure we don't overwrite a value just set by the ISR. + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + ret = breakValue; + breakValue = -1; + } + return ret; } Serial_ Serial; diff --git a/megaavr/cores/coreX-corefiles/CDC.h b/megaavr/cores/coreX-corefiles/CDC.h index 43b382e..4df6459 100644 --- a/megaavr/cores/coreX-corefiles/CDC.h +++ b/megaavr/cores/coreX-corefiles/CDC.h @@ -4,11 +4,11 @@ #include "api/Stream.h" #include "api/USBAPI.h" -#if defined (USBCON) +#if defined(USBCON) //================================================================================ //================================================================================ -// Serial over CDC (Serial1 is the physical port) +// Serial over CDC (Serial1 is the physical port) #define RINGBUFFER_FORCE_SMALL_SIZE #include "api/RingBuffer.h" @@ -26,65 +26,67 @@ class Serial_ : public Stream { -private: - int peek_buffer; -public: - Serial_() { peek_buffer = -1; }; - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(void); - - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual int availableForWrite(void); - virtual void flush(void); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t*, size_t); - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); - - //RingBuffer _rx_buffer(SERIAL_BUFFER_SIZE); - - // This method allows processing "SEND_BREAK" requests sent by - // the USB host. Those requests indicate that the host wants to - // send a BREAK signal and are accompanied by a single uint16_t - // value, specifying the duration of the break. The value 0 - // means to end any current break, while the value 0xffff means - // to start an indefinite break. - // readBreak() will return the value of the most recent break - // request, but will return it at most once, returning -1 when - // readBreak() is called again (until another break request is - // received, which is again returned once). - // This also mean that if two break requests are received - // without readBreak() being called in between, the value of the - // first request is lost. - // Note that the value returned is a long, so it can return - // 0-0xffff as well as -1. - int32_t readBreak(); - - // These return the settings specified by the USB host for the - // serial port. These aren't really used, but are offered here - // in case a sketch wants to act on these settings. - uint32_t baud(); - uint8_t stopbits(); - uint8_t paritytype(); - uint8_t numbits(); - bool dtr(); - bool rts(); - enum { - ONE_STOP_BIT = 0, - ONE_AND_HALF_STOP_BIT = 1, - TWO_STOP_BITS = 2, - }; - enum { - NO_PARITY = 0, - ODD_PARITY = 1, - EVEN_PARITY = 2, - MARK_PARITY = 3, - SPACE_PARITY = 4, - }; - + private: + int peek_buffer; + + public: + Serial_() { peek_buffer = -1; }; + void begin(unsigned long); + void begin(unsigned long, uint8_t); + void end(void); + + virtual int available(void); + virtual int peek(void); + virtual int read(void); + virtual int availableForWrite(void); + virtual void flush(void); + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t*, size_t); + using Print::write; // pull in write(str) and write(buf, size) from Print + operator bool(); + + //RingBuffer _rx_buffer(SERIAL_BUFFER_SIZE); + + // This method allows processing "SEND_BREAK" requests sent by + // the USB host. Those requests indicate that the host wants to + // send a BREAK signal and are accompanied by a single uint16_t + // value, specifying the duration of the break. The value 0 + // means to end any current break, while the value 0xffff means + // to start an indefinite break. + // readBreak() will return the value of the most recent break + // request, but will return it at most once, returning -1 when + // readBreak() is called again (until another break request is + // received, which is again returned once). + // This also mean that if two break requests are received + // without readBreak() being called in between, the value of the + // first request is lost. + // Note that the value returned is a long, so it can return + // 0-0xffff as well as -1. + int32_t readBreak(); + + // These return the settings specified by the USB host for the + // serial port. These aren't really used, but are offered here + // in case a sketch wants to act on these settings. + uint32_t baud(); + uint8_t stopbits(); + uint8_t paritytype(); + uint8_t numbits(); + bool dtr(); + bool rts(); + enum + { + ONE_STOP_BIT = 0, + ONE_AND_HALF_STOP_BIT = 1, + TWO_STOP_BITS = 2, + }; + enum + { + NO_PARITY = 0, + ODD_PARITY = 1, + EVEN_PARITY = 2, + MARK_PARITY = 3, + SPACE_PARITY = 4, + }; }; extern Serial_ Serial; @@ -92,11 +94,11 @@ extern Serial_ Serial; //================================================================================ //================================================================================ -// CSC 'Driver' +// CSC 'Driver' -int CDC_GetInterface(uint8_t* interfaceNum); -int CDC_GetDescriptor(int i); -bool CDC_Setup(USBSetup& setup); +int CDC_GetInterface(uint8_t* interfaceNum); +int CDC_GetDescriptor(int i); +bool CDC_Setup(USBSetup& setup); #endif diff --git a/megaavr/cores/coreX-corefiles/MSC.h b/megaavr/cores/coreX-corefiles/MSC.h index 96028e1..3705587 100644 --- a/megaavr/cores/coreX-corefiles/MSC.h +++ b/megaavr/cores/coreX-corefiles/MSC.h @@ -1,4 +1,4 @@ -#if defined (USBCON) +#if defined(USBCON) #ifndef __MSC_H__ #define __MSC_H__ @@ -7,12 +7,12 @@ //================================================================================ //================================================================================ -// MSC 'Driver' +// MSC 'Driver' -int MSC_GetInterface(uint8_t* interfaceNum); -int MSC_GetDescriptor(int i); -bool MSC_Setup(USBSetup& setup); -bool MSC_Data(uint8_t rx,uint8_t tx); +int MSC_GetInterface(uint8_t* interfaceNum); +int MSC_GetDescriptor(int i); +bool MSC_Setup(USBSetup& setup); +bool MSC_Data(uint8_t rx, uint8_t tx); #endif diff --git a/megaavr/cores/coreX-corefiles/Tone.cpp b/megaavr/cores/coreX-corefiles/Tone.cpp index 1102462..791154f 100644 --- a/megaavr/cores/coreX-corefiles/Tone.cpp +++ b/megaavr/cores/coreX-corefiles/Tone.cpp @@ -36,29 +36,30 @@ #include #include + #include "Arduino.h" #include "pins_arduino.h" /* For more than one tone, change AVAILABLE_TONE_PINS and uncomment the correct number of timers */ -#define AVAILABLE_TONE_PINS 1 +#define AVAILABLE_TONE_PINS 1 -#define USE_TIMERB1 // interferes with PWM on pin 3 +#define USE_TIMERB1 // interferes with TCB1 PWM /* -#define USE_TIMERB2 // interferes with PWM on pin 11 -#define USE_TIMERB0 // interferes with PWM on pin 6 +#define USE_TIMERB2 // interferes with TCB2 PWM, and timer in many configurations +#define USE_TIMERB0 // interferes with TCB0 PWM */ -#if !defined(USE_TIMERB1) && !defined(USE_TIMERB2) && !defined(USE_TIMERB0) - # error "No timers allowed for tone()" - /* Please uncomment a timer above and rebuild */ +#if !defined(USE_TIMERB0) && !defined(USE_TIMERB1) && !defined(USE_TIMERB2) && !defined(USE_TIMERB3) +#error "No timers allowed for tone()" +/* Please uncomment a timer above and rebuild */ #endif -// Can't use TIMERB3 -- used for application time tracking +// Can't use timer assigned for application time tracking (usually TIMERB2 or TIMERB3) // Using TIMERA0 NOT RECOMMENDED -- all other timers use its clock! -static volatile TCB_t* _timer = +static volatile TCB_t *_timer = #if defined(USE_TIMERB0) -&TCB0; + &TCB0; #endif #if defined(USE_TIMERB1) &TCB1; @@ -66,6 +67,9 @@ static volatile TCB_t* _timer = #if defined(USE_TIMERB2) &TCB2; #endif +#if defined(USE_TIMERB3) +&TCB3; +#endif static int _pin = NOT_A_PIN; @@ -80,89 +84,124 @@ volatile uint8_t timer_bit_mask; // helper functions static void disableTimer(); +static byte timerPrescaler(); // frequency (in hertz) and duration (in milliseconds). void tone(uint8_t pin, unsigned int frequency, unsigned long duration) { - long toggle_count = 0; - uint32_t compare_val = 0; - - if (_pin != pin) { - pinMode(pin, OUTPUT); - _pin = pin; - } - - // Get pin related stuff - PORT_t *port = digitalPinToPortStruct(_pin); - uint8_t *port_outtgl = (uint8_t *)&(port->OUTTGL); - uint8_t bit_mask = digitalPinToBitMask(_pin); - - if (frequency == 0) { - bit_mask = 0; - frequency = 1; - } - - // Calculate compare value - compare_val = F_CPU_CORRECTED / frequency / 2 - 1; - // If compare larger than 16bits, need to prescale (will be DIV64) - uint8_t prescaler_needed = 0; - if (compare_val > 0xFFFF){ - // recalculate with new prescaler - compare_val = F_CPU_CORRECTED / frequency / 2 / 64 - 1; - prescaler_needed = 1; - } - - // Calculate the toggle count - if (duration > 0){ // Duration defined - toggle_count = 2 * frequency * duration / 1000; - } else { // Duration not defined -- tone until noTone() call - toggle_count = -1; - } - - // Timer settings -- will be type B - uint8_t status = SREG; - cli(); - - // Disable for now, set clk according to 'prescaler_needed' - // (Prescaled clock will come from TCA -- - // by default it should have a prescaler of 64 (250kHz clock) - // TCA default initialization is in wiring.c -- init() ) - if(prescaler_needed){ - _timer->CTRLA = TCB_CLKSEL_CLKTCA_gc; - } else { - _timer->CTRLA = TCB_CLKSEL_CLKDIV1_gc; - } - - // Timer to Periodic interrupt mode - // This write will also disable any active PWM outputs - _timer->CTRLB = TCB_CNTMODE_INT_gc; - - // Write compare register - _timer->CCMP = compare_val; - - // Enable interrupt - _timer->INTCTRL = TCB_CAPTEI_bm; - - timer_outtgl_reg = port_outtgl; - timer_bit_mask = bit_mask; - timer_toggle_count = toggle_count; - - // Enable timer - _timer->CTRLA |= TCB_ENABLE_bm; - - SREG = status; + long toggle_count = 0; + uint32_t compare_val = 0; + + if (_pin != pin) + { + pinMode(pin, OUTPUT); + _pin = pin; + } + + // Get pin related stuff + PORT_t *port = digitalPinToPortStruct(_pin); + uint8_t *port_outtgl = (uint8_t *)&(port->OUTTGL); + uint8_t bit_mask = digitalPinToBitMask(_pin); + + if (frequency == 0) + { + bit_mask = 0; + frequency = 1; + } + + // Calculate compare value, assuming F_CPU/2 used as clock + compare_val = F_CPU / frequency / 4 - 1; + // If compare larger than 16bits, need to prescale (will be DIV64) + uint8_t prescaler = 0; + if (compare_val > 0xFFFF) + { + // recalculate with new prescaler + prescaler = timerPrescaler(); + compare_val = F_CPU / frequency / 2 / prescaler - 1; + if (compare_val > 0xFFFF) compare_val = 0xFFFF; // request lower frequency than supported + } + + // Calculate the toggle count + if (duration > 0) + { // Duration defined + toggle_count = 2 * frequency * duration / 1000; + } + else + { // Duration not defined -- tone until noTone() call + toggle_count = -1; + } + + // Timer settings -- will be type B + uint8_t status = SREG; + cli(); + + // Disable for now, set clk according to whether 'prescaler' is zero + // (Prescaled clock will come from TCA -- + // by default it should have a prescaler of 64 (250kHz clock) + // but this may have changed with analogWriteFrequency() + // TCA default initialization is in wiring.c -- init() ) + if (prescaler != 0) + { + _timer->CTRLA = TCB_CLKSEL_CLKTCA_gc; + } + else + { + _timer->CTRLA = TCB_CLKSEL_CLKDIV2_gc; + } + + // Timer to Periodic interrupt mode + // This write will also disable any active PWM outputs + _timer->CTRLB = TCB_CNTMODE_INT_gc; + + // Write compare register + _timer->CCMP = compare_val; + + // Enable interrupt + _timer->INTCTRL = TCB_CAPTEI_bm; + + timer_outtgl_reg = port_outtgl; + timer_bit_mask = bit_mask; + timer_toggle_count = toggle_count; + + // Enable timer + _timer->CTRLA |= TCB_ENABLE_bm; + + SREG = status; } // pin which currently is being used for a tone void noTone(uint8_t pin) { - if (pin == _pin) { - timer_toggle_count = 0; - //disableTimer(); - // Keep pin low after disabling of timer - digitalWrite(_pin, LOW); - _pin = NOT_A_PIN; - } + if (pin == _pin) + { + timer_toggle_count = 0; + //disableTimer(); + // Keep pin low after disabling of timer + digitalWrite(_pin, LOW); + _pin = NOT_A_PIN; + } +} + +// helper function for noTone() +// find which timer prescaler is currently used +static byte timerPrescaler() +{ + byte clksel = (TCA0.SPLIT.CTRLA & TCA_SPLIT_CLKSEL_gm) >> TCA_SPLIT_CLKSEL_gp; + + // the next five lines may have been a #if, + // but alas the C preprocessor does not understand enums + // they should produce no real code, though + if ((TCA_SPLIT_CLKSEL_DIV1_gc >> TCA_SPLIT_CLKSEL_gp) == 0 + && (TCA_SPLIT_CLKSEL_DIV2_gc >> TCA_SPLIT_CLKSEL_gp) == 1 + && (TCA_SPLIT_CLKSEL_DIV4_gc >> TCA_SPLIT_CLKSEL_gp) == 2 + && (TCA_SPLIT_CLKSEL_DIV8_gc >> TCA_SPLIT_CLKSEL_gp) == 3 + && (TCA_SPLIT_CLKSEL_DIV16_gc >> TCA_SPLIT_CLKSEL_gp) == 4 + && clksel <= (TCA_SPLIT_CLKSEL_DIV16_gc >> TCA_SPLIT_CLKSEL_gp)) + { + // non-standard TCA clock selection is used + return 1 << clksel; + } + return 64; } // helper function for noTone() @@ -170,11 +209,11 @@ void noTone(uint8_t pin) configuration it had to output PWM for analogWrite() */ static void disableTimer() { - // Reinit back to producing PWM -- timer will be type B - // Disable interrupt - _timer->INTCTRL = 0; - // Disable timer - _timer->CTRLA = 0; + // Reinit back to producing PWM -- timer will be type B + // Disable interrupt + _timer->INTCTRL = 0; + // Disable timer + _timer->CTRLA = 0; #if 0 // RESTORE PWM FUNCTIONALITY: @@ -190,7 +229,6 @@ static void disableTimer() #endif } - #if defined USE_TIMERB0 ISR(TCB0_INT_vect) #elif defined USE_TIMERB1 @@ -199,23 +237,25 @@ ISR(TCB1_INT_vect) ISR(TCB2_INT_vect) #endif { - if (timer_toggle_count != 0){ - - // toggle the pin - *timer_outtgl_reg = timer_bit_mask; - - // If duration was defined, decrement - if (timer_toggle_count > 0){ - timer_toggle_count--; - } - - // If no duration (toggle count negative), go on until noTone() call + if (timer_toggle_count != 0) + { + // toggle the pin + *timer_outtgl_reg = timer_bit_mask; + + // If duration was defined, decrement + if (timer_toggle_count > 0) + { + timer_toggle_count--; + } - } else if (timer_toggle_count == 0) { // If toggle count = 0, stop + // If no duration (toggle count negative), go on until noTone() call + } + else if (timer_toggle_count == 0) + { // If toggle count = 0, stop - disableTimer(); - } + disableTimer(); + } - /* Clear flag */ - _timer->INTFLAGS = TCB_CAPT_bm; + /* Clear flag */ + _timer->INTFLAGS = TCB_CAPT_bm; } diff --git a/megaavr/cores/coreX-corefiles/UART.cpp b/megaavr/cores/coreX-corefiles/UART.cpp index 3f4234c..1ce409d 100644 --- a/megaavr/cores/coreX-corefiles/UART.cpp +++ b/megaavr/cores/coreX-corefiles/UART.cpp @@ -63,16 +63,16 @@ bool Serial3_available() __attribute__((weak)); void serialEventRun(void) { #if defined(HAVE_HWSERIAL0) - if (Serial0_available && serialEvent && Serial0_available()) serialEvent(); + if (Serial0_available && serialEvent && Serial0_available()) serialEvent(); #endif #if defined(HAVE_HWSERIAL1) - if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1(); + if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1(); #endif #if defined(HAVE_HWSERIAL2) - if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2(); + if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2(); #endif #if defined(HAVE_HWSERIAL3) - if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3(); + if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3(); #endif } @@ -87,271 +87,299 @@ void serialEventRun(void) void UartClass::_tx_data_empty_irq(void) { - // Check if tx buffer already empty. - // This interrupt-handler can be called "manually" from flush(); - if (_tx_buffer_head == _tx_buffer_tail) { - // Buffer empty, so disable "data register empty" interrupt - (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); - return; - } - - // There must be more data in the output - // buffer. Send the next byte - unsigned char c = _tx_buffer[_tx_buffer_tail]; - _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; + // Check if tx buffer already empty. + if (_tx_buffer_head == _tx_buffer_tail) + { + // Buffer empty, so disable "data register empty" interrupt + (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); + return; + } - // clear the TXCIF flag -- "can be cleared by writing a one to its bit - // location". This makes sure flush() won't return until the bytes - // actually got written - (*_hwserial_module).STATUS = USART_TXCIF_bm; + // There must be more data in the output + // buffer. Send the next byte + unsigned char c = _tx_buffer[_tx_buffer_tail]; + _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; - (*_hwserial_module).TXDATAL = c; + // clear the TXCIF flag -- "can be cleared by writing a one to its bit + // location". This makes sure flush() won't return until the bytes + // actually got written + (*_hwserial_module).STATUS = USART_TXCIF_bm; - while(!((*_hwserial_module).STATUS & USART_DREIF_bm)); + (*_hwserial_module).TXDATAL = c; - if (_tx_buffer_head == _tx_buffer_tail) { - // Buffer empty, so disable "data register empty" interrupt - (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); + if (_tx_buffer_head == _tx_buffer_tail) + { + // Buffer empty, so disable "data register empty" interrupt + (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); + + //Take the DRE interrupt back no normal priority level if it has been elevated + if (_hwserial_dre_interrupt_elevated) + { + CPUINT.LVL1VEC = _prev_lvl1_interrupt_vect; + _hwserial_dre_interrupt_elevated = 0; + } + } +} - //Take the DRE interrupt back no normal priority level if it has been elevated - if(_hwserial_dre_interrupt_elevated) { - CPUINT.LVL1VEC = _prev_lvl1_interrupt_vect; - _hwserial_dre_interrupt_elevated = 0; - } +// To invoke data empty "interrupt" via a call, use this method +void UartClass::_poll_tx_data_empty(void) +{ + if ((!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm))) + { + // Interrupts are disabled either globally or for data register empty, + // so we'll have to poll the "data register empty" flag ourselves. + // If it is set, pretend an interrupt has happened and call the handler + // to free up space for us. + + // Invoke interrupt handler only if conditions data register is empty + if ((*_hwserial_module).STATUS & USART_DREIF_bm) + { + _tx_data_empty_irq(); } + } + // In case interrupts are enabled, the interrupt routine will be invoked by itself } // Public Methods ////////////////////////////////////////////////////////////// -void UartClass::begin(unsigned long baud, uint16_t config) +// Invoke this function before 'begin' to define the pins used +bool UartClass::pins(uint8_t tx, uint8_t rx) { - // Make sure no transmissions are ongoing and USART is disabled in case begin() is called by accident - // without first calling end() - if(_written) { - this->end(); + for (_pin_set = 0; _pin_set < SERIAL_PIN_SETS; ++_pin_set) + { + if (tx == _hw_set[_pin_set].tx_pin && rx == _hw_set[_pin_set].rx_pin) + { + // We are good, this set of pins is supported + return true; } + } + _pin_set = 0; // Default to standard + return false; +} - // Setup default port mux - PORTMUX.USARTROUTEA |= _uart_mux; +bool UartClass::swap(uint8_t state) +{ + if (state == 1) // Use alternative pin position + { + _pin_set = state; + return true; + } + else if (state == 0) // Use default pin position + { + _pin_set = 0; + return true; + } + else // Invalid swap value. Use default position + { + _pin_set = 0; + return false; + } +} - int32_t baud_setting = 0; +void UartClass::begin(unsigned long baud, uint16_t config) +{ + // Make sure no transmissions are ongoing and USART is disabled in case begin() is called by accident + // without first calling end() + if (_written) + { + this->end(); + } - //Make sure global interrupts are disabled during initialization - uint8_t oldSREG = SREG; - cli(); + struct UartPinSet *set = &_hw_set[_pin_set]; - baud_setting = (((8 * F_CPU_CORRECTED) / baud) + 1) / 2; - // Disable CLK2X - (*_hwserial_module).CTRLB &= (~USART_RXMODE_CLK2X_gc); - (*_hwserial_module).CTRLB |= USART_RXMODE_NORMAL_gc; + int32_t baud_setting = 0; - _written = false; + //Make sure global interrupts are disabled during initialization + uint8_t oldSREG = SREG; + cli(); - //Set up the rx pin - pinMode(_hwserial_rx_pin, INPUT_PULLUP); + baud_setting = (((8 * F_CPU) / baud) + 1) / 2; + // Disable CLK2X + (*_hwserial_module).CTRLB &= (~USART_RXMODE_CLK2X_gc); + (*_hwserial_module).CTRLB |= USART_RXMODE_NORMAL_gc; - //Set up the tx pin - digitalWrite(_hwserial_tx_pin, HIGH); - pinMode(_hwserial_tx_pin, OUTPUT); + _written = false; - int8_t sigrow_val = SIGROW.OSC16ERR5V; - baud_setting *= (1024 + sigrow_val); - baud_setting /= (1024 - abs(sigrow_val)); + int8_t sigrow_val = 0; - // assign the baud_setting, a.k.a. BAUD (USART Baud Rate Register) - (*_hwserial_module).BAUD = (int16_t) baud_setting; +// Use error compensation if internal oscillator is used +#if !defined(USE_EXTERNAL_OSCILLATOR) +#if F_CPU == 20000000L + sigrow_val = SIGROW.OSC20ERR5V; +#else + sigrow_val = SIGROW.OSC16ERR5V; +#endif +#endif - // Set USART mode of operation - (*_hwserial_module).CTRLC = config; + baud_setting += (baud_setting * sigrow_val) / 1024; - // Enable transmitter and receiver - (*_hwserial_module).CTRLB |= (USART_RXEN_bm | USART_TXEN_bm); + // assign the baud_setting, a.k.a. BAUD (USART Baud Rate Register) + (*_hwserial_module).BAUD = (uint16_t)baud_setting; - (*_hwserial_module).CTRLA |= USART_RXCIE_bm; + // Set USART mode of operation + (*_hwserial_module).CTRLC = config; - // Restore SREG content - SREG = oldSREG; -} + // Enable transmitter and receiver + (*_hwserial_module).CTRLB |= (USART_RXEN_bm | USART_TXEN_bm); -void UartClass::swap(uint8_t shouldSwap) -{ - if(shouldSwap == true) - { - // Let PORTMUX pont to alternative UART pins - if(_uart_mux_swap > 0) - PORTMUX.USARTROUTEA |= _uart_mux; - else - PORTMUX.USARTROUTEA &= ~_uart_mux; - - // Set pin state for alternative UART pins - pinMode(_hwserial_rx_pin_swap, INPUT_PULLUP); - digitalWrite(_hwserial_tx_pin_swap, HIGH); - pinMode(_hwserial_tx_pin_swap, OUTPUT); - - // Set previous pins to high Z - pinMode(_hwserial_rx_pin, INPUT); - pinMode(_hwserial_tx_pin, INPUT); - } - else //if(shouldSwap == false) - { - if(_uart_mux > 0) - PORTMUX.USARTROUTEA |= _uart_mux; - else - PORTMUX.USARTROUTEA &= ~_uart_mux; - - // Set pin state for default UART pins - pinMode(_hwserial_rx_pin, INPUT_PULLUP); - digitalWrite(_hwserial_tx_pin, HIGH); - pinMode(_hwserial_tx_pin, OUTPUT); - - // Set previous pins to high Z - pinMode(_hwserial_rx_pin_swap, INPUT); - pinMode(_hwserial_tx_pin_swap, INPUT); - } + (*_hwserial_module).CTRLA |= USART_RXCIE_bm; + + // Let PORTMUX point to alternative UART pins as requested + PORTMUX.USARTROUTEA = set->mux | (PORTMUX.USARTROUTEA & ~_hw_set[1].mux); + + // Set pin state for swapped UART pins + pinMode(set->rx_pin, INPUT_PULLUP); + digitalWrite(set->tx_pin, HIGH); + pinMode(set->tx_pin, OUTPUT); + + // Restore SREG content + SREG = oldSREG; } void UartClass::end() { - // wait for transmission of outgoing data - flush(); + // wait for transmission of outgoing data + flush(); - // Disable receiver and transmitter as well as the RX complete and - // data register empty interrupts. - (*_hwserial_module).CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm); - (*_hwserial_module).CTRLA &= ~(USART_RXCIE_bm | USART_DREIE_bm); + // Disable receiver and transmitter as well as the RX complete and + // data register empty interrupts. + (*_hwserial_module).CTRLB &= ~(USART_RXEN_bm | USART_TXEN_bm); + (*_hwserial_module).CTRLA &= ~(USART_RXCIE_bm | USART_DREIE_bm); - // clear any received data - _rx_buffer_head = _rx_buffer_tail; + // clear any received data + _rx_buffer_head = _rx_buffer_tail; - _written = false; + // Note: Does not change output pins + _written = false; } int UartClass::available(void) { - return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; + return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; } int UartClass::peek(void) { - if (_rx_buffer_head == _rx_buffer_tail) { - return -1; - } else { - return _rx_buffer[_rx_buffer_tail]; - } + if (_rx_buffer_head == _rx_buffer_tail) + { + return -1; + } + else + { + return _rx_buffer[_rx_buffer_tail]; + } } int UartClass::read(void) { - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer_head == _rx_buffer_tail) { - return -1; - } else { - unsigned char c = _rx_buffer[_rx_buffer_tail]; - _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; - return c; - } + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer_head == _rx_buffer_tail) + { + return -1; + } + else + { + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; + return c; + } } int UartClass::availableForWrite(void) { - tx_buffer_index_t head; - tx_buffer_index_t tail; + tx_buffer_index_t head; + tx_buffer_index_t tail; - TX_BUFFER_ATOMIC { - head = _tx_buffer_head; - tail = _tx_buffer_tail; - } - if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; - return tail - head - 1; + TX_BUFFER_ATOMIC + { + head = _tx_buffer_head; + tail = _tx_buffer_tail; + } + if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; + return tail - head - 1; } void UartClass::flush() { - // If we have never written a byte, no need to flush. This special - // case is needed since there is no way to force the TXCIF (transmit - // complete) bit to 1 during initialization - if (!_written) { - return; - } - - //Check if we are inside an ISR already (e.g. connected to a different peripheral then UART), in which case the UART ISRs will not be called. - //Temporarily elevate the DRE interrupt to allow it to run. - if(CPUINT.STATUS & CPUINT_LVL0EX_bm) { - //Elevate the priority level of the Data Register Empty Interrupt vector - //and copy whatever vector number that might be in the register already. - _prev_lvl1_interrupt_vect = CPUINT.LVL1VEC; - CPUINT.LVL1VEC = _hwserial_dre_interrupt_vect_num; + // If we have never written a byte, no need to flush. This special + // case is needed since there is no way to force the TXCIF (transmit + // complete) bit to 1 during initialization + if (!_written) + { + return; + } - _hwserial_dre_interrupt_elevated = 1; - } + //Check if we are inside an ISR already (e.g. connected to a different peripheral then UART), in which case the UART ISRs will not be called. + //Temporarily elevate the DRE interrupt to allow it to run. + if (CPUINT.STATUS & CPUINT_LVL0EX_bm) + { + //Elevate the priority level of the Data Register Empty Interrupt vector + //and copy whatever vector number that might be in the register already. + _prev_lvl1_interrupt_vect = CPUINT.LVL1VEC; + CPUINT.LVL1VEC = _hwserial_dre_interrupt_vect_num; - // Spin until the data-register-empty-interrupt is disabled and TX complete interrupt flag is raised - while ( ((*_hwserial_module).CTRLA & USART_DREIE_bm) || (!((*_hwserial_module).STATUS & USART_TXCIF_bm)) ) { + _hwserial_dre_interrupt_elevated = 1; + } - // If interrupts are globally disabled or the and DR empty interrupt is disabled, - // poll the "data register empty" interrupt flag to prevent deadlock - if ( (!(SREG & CPU_I_bm)) || (!((*_hwserial_module).CTRLA & USART_DREIE_bm)) ) { - _tx_data_empty_irq(); - } - } - // If we get here, nothing is queued anymore (DREIE is disabled) and - // the hardware finished transmission (TXCIF is set). + // Spin until the data-register-empty-interrupt is disabled and TX complete interrupt flag is raised + while (((*_hwserial_module).CTRLA & USART_DREIE_bm) || (!((*_hwserial_module).STATUS & USART_TXCIF_bm))) + { + // If interrupts are globally disabled or the and DR empty interrupt is disabled, + // poll the "data register empty" interrupt flag to prevent deadlock + _poll_tx_data_empty(); + } + // If we get here, nothing is queued anymore (DREIE is disabled) and + // the hardware finished transmission (TXCIF is set). } size_t UartClass::write(uint8_t c) { - _written = true; + _written = true; - // If the buffer and the data register is empty, just write the byte - // to the data register and be done. This shortcut helps - // significantly improve the effective data rate at high (> - // 500kbit/s) bit rates, where interrupt overhead becomes a slowdown. - if ( (_tx_buffer_head == _tx_buffer_tail) && ((*_hwserial_module).STATUS & USART_DREIF_bm) ) { - (*_hwserial_module).TXDATAL = c; - (*_hwserial_module).STATUS = USART_TXCIF_bm; + // If the buffer and the data register is empty, just write the byte + // to the data register and be done. This shortcut helps + // significantly improve the effective data rate at high (> + // 500kbit/s) bit rates, where interrupt overhead becomes a slowdown. + if ((_tx_buffer_head == _tx_buffer_tail) && ((*_hwserial_module).STATUS & USART_DREIF_bm)) + { + (*_hwserial_module).TXDATAL = c; + (*_hwserial_module).STATUS = USART_TXCIF_bm; - // Make sure data register empty interrupt is disabled to avoid - // that the interrupt handler is called in this situation - (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); + // Make sure data register empty interrupt is disabled to avoid + // that the interrupt handler is called in this situation + (*_hwserial_module).CTRLA &= (~USART_DREIE_bm); - return 1; - } + return 1; + } - //Check if we are inside an ISR already (could be from by a source other than UART), - // in which case the UART ISRs will be blocked. - if(CPUINT.STATUS & CPUINT_LVL0EX_bm) { - //Elevate the priority level of the Data Register Empty Interrupt vector - //and copy whatever vector number that might be in the register already. - _prev_lvl1_interrupt_vect = CPUINT.LVL1VEC; - CPUINT.LVL1VEC = _hwserial_dre_interrupt_vect_num; + //Check if we are inside an ISR already (could be from by a source other than UART), + // in which case the UART ISRs will be blocked. + if (CPUINT.STATUS & CPUINT_LVL0EX_bm) + { + //Elevate the priority level of the Data Register Empty Interrupt vector + //and copy whatever vector number that might be in the register already. + _prev_lvl1_interrupt_vect = CPUINT.LVL1VEC; + CPUINT.LVL1VEC = _hwserial_dre_interrupt_vect_num; - _hwserial_dre_interrupt_elevated = 1; - } + _hwserial_dre_interrupt_elevated = 1; + } - tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; - - //If the output buffer is full, there's nothing for it other than to - //wait for the interrupt handler to empty it a bit - while (i == _tx_buffer_tail) { - if ( ( !(SREG & CPU_I_bm) ) || ( !((*_hwserial_module).CTRLA & USART_DREIE_bm) ) ) { - // Interrupts are disabled either globally or for data register empty, - // so we'll have to poll the "data register empty" flag ourselves. - // If it is set, pretend an interrupt has happened and call the handler - //to free up space for us. - - _tx_data_empty_irq(); - } else { - // nop, the interrupt handler will free up space for us - } - } + tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; - _tx_buffer[_tx_buffer_head] = c; - _tx_buffer_head = i; + //If the output buffer is full, there's nothing for it other than to + //wait for the interrupt handler to empty it a bit (or emulate interrupts) + while (i == _tx_buffer_tail) + { + _poll_tx_data_empty(); + } - // Enable data "register empty interrupt" - (*_hwserial_module).CTRLA |= USART_DREIE_bm; + _tx_buffer[_tx_buffer_head] = c; + _tx_buffer_head = i; - return 1; + // Enable data "register empty interrupt" + (*_hwserial_module).CTRLA |= USART_DREIE_bm; + + return 1; } #endif // whole file diff --git a/megaavr/cores/coreX-corefiles/UART.h b/megaavr/cores/coreX-corefiles/UART.h index 4ae9c06..896a8db 100644 --- a/megaavr/cores/coreX-corefiles/UART.h +++ b/megaavr/cores/coreX-corefiles/UART.h @@ -120,18 +120,20 @@ typedef uint8_t rx_buffer_index_t; #define SERIAL_7O2 (USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_7BIT_gc | USART_PMODE_ODD_gc | USART_SBMODE_2BIT_gc) #define SERIAL_8O2 (USART_CMODE_ASYNCHRONOUS_gc | USART_CHSIZE_8BIT_gc | USART_PMODE_ODD_gc | USART_SBMODE_2BIT_gc) +#define SERIAL_PIN_SETS 2 + class UartClass : public HardwareSerial { protected: volatile USART_t * const _hwserial_module; - volatile uint8_t const _hwserial_rx_pin; - volatile uint8_t const _hwserial_tx_pin; - volatile uint8_t const _hwserial_rx_pin_swap; - volatile uint8_t const _hwserial_tx_pin_swap; + struct UartPinSet { + uint8_t const rx_pin; + uint8_t const tx_pin; + uint8_t const mux; + } _hw_set[SERIAL_PIN_SETS]; - volatile uint8_t const _uart_mux; - volatile uint8_t const _uart_mux_swap; + uint8_t _pin_set; // Has any byte been written to the UART since begin() bool _written; @@ -148,14 +150,15 @@ class UartClass : public HardwareSerial // Don't put any members after these buffers, since only the first // 32 bytes of this struct can be accessed quickly using the ldd // instruction. - unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; - unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; + volatile unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; + volatile unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; public: inline UartClass(volatile USART_t *hwserial_module, uint8_t hwserial_rx_pin, uint8_t hwserial_tx_pin, uint8_t hwserial_rx_pin_swap, uint8_t hwserial_tx_pin_swap, uint8_t dre_vect_num, uint8_t uart_mux, uint8_t uart_mux_swap); + bool pins(uint8_t tx, uint8_t rx); + bool swap(uint8_t state = 1); void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } void begin(unsigned long, uint16_t); - void swap(uint8_t shouldSwap = true); void end(); virtual int available(void); virtual int peek(void); @@ -168,11 +171,14 @@ class UartClass : public HardwareSerial inline size_t write(unsigned int n) { return write((uint8_t)n); } inline size_t write(int n) { return write((uint8_t)n); } using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool() { return true; } + explicit operator bool() { return true; } // Interrupt handlers - Not intended to be called externally inline void _rx_complete_irq(void); void _tx_data_empty_irq(void); + + private: + void _poll_tx_data_empty(void); }; #if defined(HWSERIAL0) diff --git a/megaavr/cores/coreX-corefiles/UART0.cpp b/megaavr/cores/coreX-corefiles/UART0.cpp index 50b2264..9f8686a 100644 --- a/megaavr/cores/coreX-corefiles/UART0.cpp +++ b/megaavr/cores/coreX-corefiles/UART0.cpp @@ -51,16 +51,17 @@ ISR(HWSERIAL0_DRE_VECTOR) Serial._tx_data_empty_irq(); } #else -#error "Don't know what the Data Received interrupt vector is called for Serial" +#error "Don't know what the Data Register Empty interrupt vector is called for Serial" #endif #if defined(HWSERIAL0) - UartClass Serial(HWSERIAL0, PIN_WIRE_HWSERIAL0_RX, PIN_WIRE_HWSERIAL0_TX, PIN_WIRE_HWSERIAL0_RX_PINSWAP_1, PIN_WIRE_HWSERIAL0_TX_PINSWAP_1, HWSERIAL0_DRE_VECTOR_NUM, HWSERIAL0_MUX, HWSERIAL0_MUX_PINSWAP_1); +UartClass Serial(HWSERIAL0, PIN_HWSERIAL0_RX, PIN_HWSERIAL0_TX, PIN_HWSERIAL0_RX_PINSWAP_1, PIN_HWSERIAL0_TX_PINSWAP_1, HWSERIAL0_DRE_VECTOR_NUM, HWSERIAL0_MUX, HWSERIAL0_MUX_PINSWAP_1); #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. -bool Serial0_available() { +bool Serial0_available() +{ return Serial.available(); } diff --git a/megaavr/cores/coreX-corefiles/UART1.cpp b/megaavr/cores/coreX-corefiles/UART1.cpp index c15332e..99cc22e 100644 --- a/megaavr/cores/coreX-corefiles/UART1.cpp +++ b/megaavr/cores/coreX-corefiles/UART1.cpp @@ -55,12 +55,13 @@ ISR(HWSERIAL1_DRE_VECTOR) #endif #if defined(HWSERIAL1) - UartClass Serial1(HWSERIAL1, PIN_WIRE_HWSERIAL1_RX, PIN_WIRE_HWSERIAL1_TX, PIN_WIRE_HWSERIAL1_RX_PINSWAP_1, PIN_WIRE_HWSERIAL1_TX_PINSWAP_1, HWSERIAL1_DRE_VECTOR_NUM, HWSERIAL1_MUX, HWSERIAL1_MUX_PINSWAP_1); +UartClass Serial1(HWSERIAL1, PIN_HWSERIAL1_RX, PIN_HWSERIAL1_TX, PIN_HWSERIAL1_RX_PINSWAP_1, PIN_HWSERIAL1_TX_PINSWAP_1, HWSERIAL1_DRE_VECTOR_NUM, HWSERIAL1_MUX, HWSERIAL1_MUX_PINSWAP_1); #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. -bool Serial1_available() { +bool Serial1_available() +{ return Serial1.available(); } diff --git a/megaavr/cores/coreX-corefiles/UART2.cpp b/megaavr/cores/coreX-corefiles/UART2.cpp index 4fc9940..203f0a3 100644 --- a/megaavr/cores/coreX-corefiles/UART2.cpp +++ b/megaavr/cores/coreX-corefiles/UART2.cpp @@ -55,12 +55,13 @@ ISR(HWSERIAL2_DRE_VECTOR) #endif #if defined(HWSERIAL2) - UartClass Serial2(HWSERIAL2, PIN_WIRE_HWSERIAL2_RX, PIN_WIRE_HWSERIAL2_TX, PIN_WIRE_HWSERIAL2_RX_PINSWAP_1, PIN_WIRE_HWSERIAL2_TX_PINSWAP_1, HWSERIAL2_DRE_VECTOR_NUM, HWSERIAL2_MUX, HWSERIAL2_MUX_PINSWAP_1); +UartClass Serial2(HWSERIAL2, PIN_HWSERIAL2_RX, PIN_HWSERIAL2_TX, PIN_HWSERIAL2_RX_PINSWAP_1, PIN_HWSERIAL2_TX_PINSWAP_1, HWSERIAL2_DRE_VECTOR_NUM, HWSERIAL2_MUX, HWSERIAL2_MUX_PINSWAP_1); #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. -bool Serial2_available() { +bool Serial2_available() +{ return Serial2.available(); } diff --git a/megaavr/cores/coreX-corefiles/UART3.cpp b/megaavr/cores/coreX-corefiles/UART3.cpp index d6d60b8..6a12e55 100644 --- a/megaavr/cores/coreX-corefiles/UART3.cpp +++ b/megaavr/cores/coreX-corefiles/UART3.cpp @@ -55,12 +55,13 @@ ISR(HWSERIAL3_DRE_VECTOR) #endif #if defined(HWSERIAL3) - UartClass Serial3(HWSERIAL3, PIN_WIRE_HWSERIAL3_RX, PIN_WIRE_HWSERIAL3_TX, PIN_WIRE_HWSERIAL3_RX_PINSWAP_1, PIN_WIRE_HWSERIAL3_TX_PINSWAP_1, HWSERIAL3_DRE_VECTOR_NUM, HWSERIAL3_MUX, HWSERIAL3_MUX_PINSWAP_1); +UartClass Serial3(HWSERIAL3, PIN_HWSERIAL3_RX, PIN_HWSERIAL3_TX, PIN_HWSERIAL3_RX_PINSWAP_1, PIN_HWSERIAL3_TX_PINSWAP_1, HWSERIAL3_DRE_VECTOR_NUM, HWSERIAL3_MUX, HWSERIAL3_MUX_PINSWAP_1); #endif // Function that can be weakly referenced by serialEventRun to prevent // pulling in this file if it's not otherwise used. -bool Serial3_available() { +bool Serial3_available() +{ return Serial3.available(); } diff --git a/megaavr/cores/coreX-corefiles/UART_private.h b/megaavr/cores/coreX-corefiles/UART_private.h index a7b6664..72845eb 100644 --- a/megaavr/cores/coreX-corefiles/UART_private.h +++ b/megaavr/cores/coreX-corefiles/UART_private.h @@ -39,12 +39,10 @@ UartClass::UartClass( volatile uint8_t uart_mux, volatile uint8_t uart_mux_swap) : _hwserial_module(hwserial_module), - _hwserial_rx_pin(hwserial_rx_pin), - _hwserial_tx_pin(hwserial_tx_pin), - _hwserial_rx_pin_swap(hwserial_rx_pin_swap), - _hwserial_tx_pin_swap(hwserial_tx_pin_swap), - _uart_mux(uart_mux), - _uart_mux_swap(uart_mux_swap), + _hw_set { { hwserial_rx_pin, hwserial_tx_pin, uart_mux }, + { hwserial_rx_pin_swap, hwserial_tx_pin_swap, uart_mux_swap } }, + _pin_set(0), + _written(false), _rx_buffer_head(0), _rx_buffer_tail(0), _tx_buffer_head(0), _tx_buffer_tail(0), _hwserial_dre_interrupt_vect_num(hwserial_dre_interrupt_vect_num), @@ -68,11 +66,14 @@ void UartClass::_rx_complete_irq(void) // just before the tail (meaning that the head would advance to the // current location of the tail), we're about to overflow the buffer // and so we don't write the character or advance the head. - if (i != _rx_buffer_tail) { + if (i != _rx_buffer_tail) + { _rx_buffer[_rx_buffer_head] = c; _rx_buffer_head = i; } - } else { + } + else + { // Parity error, read byte but discard it (*_hwserial_module).RXDATAL; } diff --git a/megaavr/cores/coreX-corefiles/UNO_compat.h b/megaavr/cores/coreX-corefiles/UNO_compat.h index 1aad58d..42f43c4 100644 --- a/megaavr/cores/coreX-corefiles/UNO_compat.h +++ b/megaavr/cores/coreX-corefiles/UNO_compat.h @@ -40,241 +40,296 @@ A5 PC5 PD5 */ -#define PORTA_ARDUINO (*(PORT_t *) 0x0400) /* I/O Ports */ -#define PORTB_ARDUINO (*(PORT_t *) 0x0420) /* I/O Ports */ -#define PORTC_ARDUINO (*(PORT_t *) 0x0440) /* I/O Ports */ -#define PORTD_ARDUINO (*(PORT_t *) 0x0460) /* I/O Ports */ -#define PORTE_ARDUINO (*(PORT_t *) 0x0480) /* I/O Ports */ -#define PORTF_ARDUINO (*(PORT_t *) 0x04A0) /* I/O Ports */ +#define PORTA_ARDUINO (*(PORT_t*)0x0400) /* I/O Ports */ +#define PORTB_ARDUINO (*(PORT_t*)0x0420) /* I/O Ports */ +#define PORTC_ARDUINO (*(PORT_t*)0x0440) /* I/O Ports */ +#define PORTD_ARDUINO (*(PORT_t*)0x0460) /* I/O Ports */ +#define PORTE_ARDUINO (*(PORT_t*)0x0480) /* I/O Ports */ +#define PORTF_ARDUINO (*(PORT_t*)0x04A0) /* I/O Ports */ #undef PORTB #undef PORTC #undef PORTD -#define SET_PORT_REGISTER(inPosition, port, position) if ((1 << inPosition) & (uint8_t)value) { port.OUTSET = (1 << position);} -#define CLEAR_PORT_REGISTER(inPosition, port, position) if ((uint8_t)~(1 << inPosition) == (uint8_t)value) { port.OUTCLR = (1 << position);} -#define SET_OR_CLEAR_PORT_REGISTER(inPosition, port, position) if ((uint8_t)~(1 << inPosition) & (uint8_t)value) { port.OUTSET = (1 << position); } else {port.OUTCLR = (1 << position); } - -#define SET_DIR_REGISTER(inPosition, port, position) if ((1 << inPosition) & (uint8_t)value) { port.DIRSET = (1 << position);} -#define CLEAR_DIR_REGISTER(inPosition, port, position) if ((uint8_t)~(1 << inPosition) == (uint8_t)value) { port.DIRCLR = (1 << position);} -#define SET_OR_CLEAR_DIR_REGISTER(inPosition, port, position) if ((uint8_t)~(1 << inPosition) & (uint8_t)value) { port.DIRSET = (1 << position); } else {port.DIRCLR = (1 << position); } +#define SET_PORT_REGISTER(inPosition, port, position) \ + if ((1 << inPosition) & (uint8_t)value) \ + { \ + port.OUTSET = (1 << position); \ + } +#define CLEAR_PORT_REGISTER(inPosition, port, position) \ + if ((uint8_t) ~(1 << inPosition) == (uint8_t)value) \ + { \ + port.OUTCLR = (1 << position); \ + } +#define SET_OR_CLEAR_PORT_REGISTER(inPosition, port, position) \ + if ((uint8_t) ~(1 << inPosition) & (uint8_t)value) \ + { \ + port.OUTSET = (1 << position); \ + } \ + else \ + { \ + port.OUTCLR = (1 << position); \ + } +#define SET_DIR_REGISTER(inPosition, port, position) \ + if ((1 << inPosition) & (uint8_t)value) \ + { \ + port.DIRSET = (1 << position); \ + } +#define CLEAR_DIR_REGISTER(inPosition, port, position) \ + if ((uint8_t) ~(1 << inPosition) == (uint8_t)value) \ + { \ + port.DIRCLR = (1 << position); \ + } +#define SET_OR_CLEAR_DIR_REGISTER(inPosition, port, position) \ + if ((uint8_t) ~(1 << inPosition) & (uint8_t)value) \ + { \ + port.DIRSET = (1 << position); \ + } \ + else \ + { \ + port.DIRCLR = (1 << position); \ + } /** DDR Classes**/ -class DDRBClass { - public: - DDRBClass() {} - DDRBClass& operator=(uint8_t value) { - SET_OR_CLEAR_DIR_REGISTER(0, PORTE_ARDUINO, 3); - SET_OR_CLEAR_DIR_REGISTER(1, PORTB_ARDUINO, 0); - SET_OR_CLEAR_DIR_REGISTER(2, PORTB_ARDUINO, 1); - SET_OR_CLEAR_DIR_REGISTER(3, PORTE_ARDUINO, 0); - SET_OR_CLEAR_DIR_REGISTER(4, PORTE_ARDUINO, 1); - SET_OR_CLEAR_DIR_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } +class DDRBClass +{ + public: + DDRBClass() {} + DDRBClass& operator=(uint8_t value) + { + SET_OR_CLEAR_DIR_REGISTER(0, PORTE_ARDUINO, 3); + SET_OR_CLEAR_DIR_REGISTER(1, PORTB_ARDUINO, 0); + SET_OR_CLEAR_DIR_REGISTER(2, PORTB_ARDUINO, 1); + SET_OR_CLEAR_DIR_REGISTER(3, PORTE_ARDUINO, 0); + SET_OR_CLEAR_DIR_REGISTER(4, PORTE_ARDUINO, 1); + SET_OR_CLEAR_DIR_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } - DDRBClass& operator&=(uint8_t value) { - CLEAR_DIR_REGISTER(0, PORTE_ARDUINO, 3); - CLEAR_DIR_REGISTER(1, PORTB_ARDUINO, 0); - CLEAR_DIR_REGISTER(2, PORTB_ARDUINO, 1); - CLEAR_DIR_REGISTER(3, PORTE_ARDUINO, 0); - CLEAR_DIR_REGISTER(4, PORTE_ARDUINO, 1); - CLEAR_DIR_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } + DDRBClass& operator&=(uint8_t value) + { + CLEAR_DIR_REGISTER(0, PORTE_ARDUINO, 3); + CLEAR_DIR_REGISTER(1, PORTB_ARDUINO, 0); + CLEAR_DIR_REGISTER(2, PORTB_ARDUINO, 1); + CLEAR_DIR_REGISTER(3, PORTE_ARDUINO, 0); + CLEAR_DIR_REGISTER(4, PORTE_ARDUINO, 1); + CLEAR_DIR_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } - DDRBClass& operator|=(uint8_t value) { - SET_DIR_REGISTER(0, PORTE_ARDUINO, 3); - SET_DIR_REGISTER(1, PORTB_ARDUINO, 0); - SET_DIR_REGISTER(2, PORTB_ARDUINO, 1); - SET_DIR_REGISTER(3, PORTE_ARDUINO, 0); - SET_DIR_REGISTER(4, PORTE_ARDUINO, 1); - SET_DIR_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } + DDRBClass& operator|=(uint8_t value) + { + SET_DIR_REGISTER(0, PORTE_ARDUINO, 3); + SET_DIR_REGISTER(1, PORTB_ARDUINO, 0); + SET_DIR_REGISTER(2, PORTB_ARDUINO, 1); + SET_DIR_REGISTER(3, PORTE_ARDUINO, 0); + SET_DIR_REGISTER(4, PORTE_ARDUINO, 1); + SET_DIR_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } }; -class DDRCClass { - public: - DDRCClass() {} - DDRCClass& operator=(uint8_t value) { - SET_OR_CLEAR_DIR_REGISTER(0, PORTD_ARDUINO, 0); - SET_OR_CLEAR_DIR_REGISTER(1, PORTD_ARDUINO, 1); - SET_OR_CLEAR_DIR_REGISTER(2, PORTD_ARDUINO, 2); - SET_OR_CLEAR_DIR_REGISTER(3, PORTD_ARDUINO, 3); - SET_OR_CLEAR_DIR_REGISTER(4, PORTD_ARDUINO, 4); - SET_OR_CLEAR_DIR_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } +class DDRCClass +{ + public: + DDRCClass() {} + DDRCClass& operator=(uint8_t value) + { + SET_OR_CLEAR_DIR_REGISTER(0, PORTD_ARDUINO, 0); + SET_OR_CLEAR_DIR_REGISTER(1, PORTD_ARDUINO, 1); + SET_OR_CLEAR_DIR_REGISTER(2, PORTD_ARDUINO, 2); + SET_OR_CLEAR_DIR_REGISTER(3, PORTD_ARDUINO, 3); + SET_OR_CLEAR_DIR_REGISTER(4, PORTD_ARDUINO, 4); + SET_OR_CLEAR_DIR_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } - DDRCClass& operator&=(uint8_t value) { - CLEAR_DIR_REGISTER(0, PORTD_ARDUINO, 0); - CLEAR_DIR_REGISTER(1, PORTD_ARDUINO, 1); - CLEAR_DIR_REGISTER(2, PORTD_ARDUINO, 2); - CLEAR_DIR_REGISTER(3, PORTD_ARDUINO, 3); - CLEAR_DIR_REGISTER(4, PORTD_ARDUINO, 4); - CLEAR_DIR_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } + DDRCClass& operator&=(uint8_t value) + { + CLEAR_DIR_REGISTER(0, PORTD_ARDUINO, 0); + CLEAR_DIR_REGISTER(1, PORTD_ARDUINO, 1); + CLEAR_DIR_REGISTER(2, PORTD_ARDUINO, 2); + CLEAR_DIR_REGISTER(3, PORTD_ARDUINO, 3); + CLEAR_DIR_REGISTER(4, PORTD_ARDUINO, 4); + CLEAR_DIR_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } - DDRCClass& operator|=(uint8_t value) { - SET_DIR_REGISTER(0, PORTD_ARDUINO, 0); - SET_DIR_REGISTER(1, PORTD_ARDUINO, 1); - SET_DIR_REGISTER(2, PORTD_ARDUINO, 2); - SET_DIR_REGISTER(3, PORTD_ARDUINO, 3); - SET_DIR_REGISTER(4, PORTD_ARDUINO, 4); - SET_DIR_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } + DDRCClass& operator|=(uint8_t value) + { + SET_DIR_REGISTER(0, PORTD_ARDUINO, 0); + SET_DIR_REGISTER(1, PORTD_ARDUINO, 1); + SET_DIR_REGISTER(2, PORTD_ARDUINO, 2); + SET_DIR_REGISTER(3, PORTD_ARDUINO, 3); + SET_DIR_REGISTER(4, PORTD_ARDUINO, 4); + SET_DIR_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } }; -class DDRDClass { - public: - DDRDClass() {} - DDRDClass& operator=(uint8_t value) { - SET_OR_CLEAR_DIR_REGISTER(0, PORTC_ARDUINO, 5); - SET_OR_CLEAR_DIR_REGISTER(1, PORTC_ARDUINO, 4); - SET_OR_CLEAR_DIR_REGISTER(2, PORTA_ARDUINO, 0); - SET_OR_CLEAR_DIR_REGISTER(3, PORTF_ARDUINO, 5); - SET_OR_CLEAR_DIR_REGISTER(4, PORTC_ARDUINO, 6); - SET_OR_CLEAR_DIR_REGISTER(5, PORTB_ARDUINO, 2); - SET_OR_CLEAR_DIR_REGISTER(6, PORTF_ARDUINO, 4); - SET_OR_CLEAR_DIR_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } +class DDRDClass +{ + public: + DDRDClass() {} + DDRDClass& operator=(uint8_t value) + { + SET_OR_CLEAR_DIR_REGISTER(0, PORTC_ARDUINO, 5); + SET_OR_CLEAR_DIR_REGISTER(1, PORTC_ARDUINO, 4); + SET_OR_CLEAR_DIR_REGISTER(2, PORTA_ARDUINO, 0); + SET_OR_CLEAR_DIR_REGISTER(3, PORTF_ARDUINO, 5); + SET_OR_CLEAR_DIR_REGISTER(4, PORTC_ARDUINO, 6); + SET_OR_CLEAR_DIR_REGISTER(5, PORTB_ARDUINO, 2); + SET_OR_CLEAR_DIR_REGISTER(6, PORTF_ARDUINO, 4); + SET_OR_CLEAR_DIR_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } - DDRDClass& operator&=(uint8_t value) { - CLEAR_DIR_REGISTER(0, PORTC_ARDUINO, 5); - CLEAR_DIR_REGISTER(1, PORTC_ARDUINO, 4); - CLEAR_DIR_REGISTER(2, PORTA_ARDUINO, 0); - CLEAR_DIR_REGISTER(3, PORTF_ARDUINO, 5); - CLEAR_DIR_REGISTER(4, PORTC_ARDUINO, 6); - CLEAR_DIR_REGISTER(5, PORTB_ARDUINO, 2); - CLEAR_DIR_REGISTER(6, PORTF_ARDUINO, 4); - CLEAR_DIR_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } + DDRDClass& operator&=(uint8_t value) + { + CLEAR_DIR_REGISTER(0, PORTC_ARDUINO, 5); + CLEAR_DIR_REGISTER(1, PORTC_ARDUINO, 4); + CLEAR_DIR_REGISTER(2, PORTA_ARDUINO, 0); + CLEAR_DIR_REGISTER(3, PORTF_ARDUINO, 5); + CLEAR_DIR_REGISTER(4, PORTC_ARDUINO, 6); + CLEAR_DIR_REGISTER(5, PORTB_ARDUINO, 2); + CLEAR_DIR_REGISTER(6, PORTF_ARDUINO, 4); + CLEAR_DIR_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } - DDRDClass& operator|=(uint8_t value) { - SET_DIR_REGISTER(0, PORTC_ARDUINO, 5); - SET_DIR_REGISTER(1, PORTC_ARDUINO, 4); - SET_DIR_REGISTER(2, PORTA_ARDUINO, 0); - SET_DIR_REGISTER(3, PORTF_ARDUINO, 5); - SET_DIR_REGISTER(4, PORTC_ARDUINO, 6); - SET_DIR_REGISTER(5, PORTB_ARDUINO, 2); - SET_DIR_REGISTER(6, PORTF_ARDUINO, 4); - SET_DIR_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } + DDRDClass& operator|=(uint8_t value) + { + SET_DIR_REGISTER(0, PORTC_ARDUINO, 5); + SET_DIR_REGISTER(1, PORTC_ARDUINO, 4); + SET_DIR_REGISTER(2, PORTA_ARDUINO, 0); + SET_DIR_REGISTER(3, PORTF_ARDUINO, 5); + SET_DIR_REGISTER(4, PORTC_ARDUINO, 6); + SET_DIR_REGISTER(5, PORTB_ARDUINO, 2); + SET_DIR_REGISTER(6, PORTF_ARDUINO, 4); + SET_DIR_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } }; /** PORT Classes**/ -class PORTBClass { - public: - PORTBClass() {} - PORTBClass& operator=(uint8_t value) { - SET_OR_CLEAR_PORT_REGISTER(0, PORTE_ARDUINO, 3); - SET_OR_CLEAR_PORT_REGISTER(1, PORTB_ARDUINO, 0); - SET_OR_CLEAR_PORT_REGISTER(2, PORTB_ARDUINO, 1); - SET_OR_CLEAR_PORT_REGISTER(3, PORTE_ARDUINO, 0); - SET_OR_CLEAR_PORT_REGISTER(4, PORTE_ARDUINO, 1); - SET_OR_CLEAR_PORT_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } +class PORTBClass +{ + public: + PORTBClass() {} + PORTBClass& operator=(uint8_t value) + { + SET_OR_CLEAR_PORT_REGISTER(0, PORTE_ARDUINO, 3); + SET_OR_CLEAR_PORT_REGISTER(1, PORTB_ARDUINO, 0); + SET_OR_CLEAR_PORT_REGISTER(2, PORTB_ARDUINO, 1); + SET_OR_CLEAR_PORT_REGISTER(3, PORTE_ARDUINO, 0); + SET_OR_CLEAR_PORT_REGISTER(4, PORTE_ARDUINO, 1); + SET_OR_CLEAR_PORT_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } - PORTBClass& operator&=(uint8_t value) { - CLEAR_PORT_REGISTER(0, PORTE_ARDUINO, 3); - CLEAR_PORT_REGISTER(1, PORTB_ARDUINO, 0); - CLEAR_PORT_REGISTER(2, PORTB_ARDUINO, 1); - CLEAR_PORT_REGISTER(3, PORTE_ARDUINO, 0); - CLEAR_PORT_REGISTER(4, PORTE_ARDUINO, 1); - CLEAR_PORT_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } + PORTBClass& operator&=(uint8_t value) + { + CLEAR_PORT_REGISTER(0, PORTE_ARDUINO, 3); + CLEAR_PORT_REGISTER(1, PORTB_ARDUINO, 0); + CLEAR_PORT_REGISTER(2, PORTB_ARDUINO, 1); + CLEAR_PORT_REGISTER(3, PORTE_ARDUINO, 0); + CLEAR_PORT_REGISTER(4, PORTE_ARDUINO, 1); + CLEAR_PORT_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } - PORTBClass& operator|=(uint8_t value) { - SET_PORT_REGISTER(0, PORTE_ARDUINO, 3); - SET_PORT_REGISTER(1, PORTB_ARDUINO, 0); - SET_PORT_REGISTER(2, PORTB_ARDUINO, 1); - SET_PORT_REGISTER(3, PORTE_ARDUINO, 0); - SET_PORT_REGISTER(4, PORTE_ARDUINO, 1); - SET_PORT_REGISTER(5, PORTE_ARDUINO, 2); - return *this; - } + PORTBClass& operator|=(uint8_t value) + { + SET_PORT_REGISTER(0, PORTE_ARDUINO, 3); + SET_PORT_REGISTER(1, PORTB_ARDUINO, 0); + SET_PORT_REGISTER(2, PORTB_ARDUINO, 1); + SET_PORT_REGISTER(3, PORTE_ARDUINO, 0); + SET_PORT_REGISTER(4, PORTE_ARDUINO, 1); + SET_PORT_REGISTER(5, PORTE_ARDUINO, 2); + return *this; + } }; -class PORTCClass { - public: - PORTCClass() {} - PORTCClass& operator=(uint8_t value) { - SET_OR_CLEAR_PORT_REGISTER(0, PORTD_ARDUINO, 0); - SET_OR_CLEAR_PORT_REGISTER(1, PORTD_ARDUINO, 1); - SET_OR_CLEAR_PORT_REGISTER(2, PORTD_ARDUINO, 2); - SET_OR_CLEAR_PORT_REGISTER(3, PORTD_ARDUINO, 3); - SET_OR_CLEAR_PORT_REGISTER(4, PORTD_ARDUINO, 4); - SET_OR_CLEAR_PORT_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } +class PORTCClass +{ + public: + PORTCClass() {} + PORTCClass& operator=(uint8_t value) + { + SET_OR_CLEAR_PORT_REGISTER(0, PORTD_ARDUINO, 0); + SET_OR_CLEAR_PORT_REGISTER(1, PORTD_ARDUINO, 1); + SET_OR_CLEAR_PORT_REGISTER(2, PORTD_ARDUINO, 2); + SET_OR_CLEAR_PORT_REGISTER(3, PORTD_ARDUINO, 3); + SET_OR_CLEAR_PORT_REGISTER(4, PORTD_ARDUINO, 4); + SET_OR_CLEAR_PORT_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } - PORTCClass& operator&=(uint8_t value) { - CLEAR_PORT_REGISTER(0, PORTD_ARDUINO, 0); - CLEAR_PORT_REGISTER(1, PORTD_ARDUINO, 1); - CLEAR_PORT_REGISTER(2, PORTD_ARDUINO, 2); - CLEAR_PORT_REGISTER(3, PORTD_ARDUINO, 3); - CLEAR_PORT_REGISTER(4, PORTD_ARDUINO, 4); - CLEAR_PORT_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } + PORTCClass& operator&=(uint8_t value) + { + CLEAR_PORT_REGISTER(0, PORTD_ARDUINO, 0); + CLEAR_PORT_REGISTER(1, PORTD_ARDUINO, 1); + CLEAR_PORT_REGISTER(2, PORTD_ARDUINO, 2); + CLEAR_PORT_REGISTER(3, PORTD_ARDUINO, 3); + CLEAR_PORT_REGISTER(4, PORTD_ARDUINO, 4); + CLEAR_PORT_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } - PORTCClass& operator|=(uint8_t value) { - SET_PORT_REGISTER(0, PORTD_ARDUINO, 0); - SET_PORT_REGISTER(1, PORTD_ARDUINO, 1); - SET_PORT_REGISTER(2, PORTD_ARDUINO, 2); - SET_PORT_REGISTER(3, PORTD_ARDUINO, 3); - SET_PORT_REGISTER(4, PORTD_ARDUINO, 4); - SET_PORT_REGISTER(5, PORTD_ARDUINO, 5); - return *this; - } + PORTCClass& operator|=(uint8_t value) + { + SET_PORT_REGISTER(0, PORTD_ARDUINO, 0); + SET_PORT_REGISTER(1, PORTD_ARDUINO, 1); + SET_PORT_REGISTER(2, PORTD_ARDUINO, 2); + SET_PORT_REGISTER(3, PORTD_ARDUINO, 3); + SET_PORT_REGISTER(4, PORTD_ARDUINO, 4); + SET_PORT_REGISTER(5, PORTD_ARDUINO, 5); + return *this; + } }; -class PORTDClass { - public: - PORTDClass() {} - PORTDClass& operator=(uint8_t value) { - SET_OR_CLEAR_PORT_REGISTER(0, PORTC_ARDUINO, 5); - SET_OR_CLEAR_PORT_REGISTER(1, PORTC_ARDUINO, 4); - SET_OR_CLEAR_PORT_REGISTER(2, PORTA_ARDUINO, 0); - SET_OR_CLEAR_PORT_REGISTER(3, PORTF_ARDUINO, 5); - SET_OR_CLEAR_PORT_REGISTER(4, PORTC_ARDUINO, 6); - SET_OR_CLEAR_PORT_REGISTER(5, PORTB_ARDUINO, 2); - SET_OR_CLEAR_PORT_REGISTER(6, PORTF_ARDUINO, 4); - SET_OR_CLEAR_PORT_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } +class PORTDClass +{ + public: + PORTDClass() {} + PORTDClass& operator=(uint8_t value) + { + SET_OR_CLEAR_PORT_REGISTER(0, PORTC_ARDUINO, 5); + SET_OR_CLEAR_PORT_REGISTER(1, PORTC_ARDUINO, 4); + SET_OR_CLEAR_PORT_REGISTER(2, PORTA_ARDUINO, 0); + SET_OR_CLEAR_PORT_REGISTER(3, PORTF_ARDUINO, 5); + SET_OR_CLEAR_PORT_REGISTER(4, PORTC_ARDUINO, 6); + SET_OR_CLEAR_PORT_REGISTER(5, PORTB_ARDUINO, 2); + SET_OR_CLEAR_PORT_REGISTER(6, PORTF_ARDUINO, 4); + SET_OR_CLEAR_PORT_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } - PORTDClass& operator&=(uint8_t value) { - CLEAR_PORT_REGISTER(0, PORTC_ARDUINO, 5); - CLEAR_PORT_REGISTER(1, PORTC_ARDUINO, 4); - CLEAR_PORT_REGISTER(2, PORTA_ARDUINO, 0); - CLEAR_PORT_REGISTER(3, PORTF_ARDUINO, 5); - CLEAR_PORT_REGISTER(4, PORTC_ARDUINO, 6); - CLEAR_PORT_REGISTER(5, PORTB_ARDUINO, 2); - CLEAR_PORT_REGISTER(6, PORTF_ARDUINO, 4); - CLEAR_PORT_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } + PORTDClass& operator&=(uint8_t value) + { + CLEAR_PORT_REGISTER(0, PORTC_ARDUINO, 5); + CLEAR_PORT_REGISTER(1, PORTC_ARDUINO, 4); + CLEAR_PORT_REGISTER(2, PORTA_ARDUINO, 0); + CLEAR_PORT_REGISTER(3, PORTF_ARDUINO, 5); + CLEAR_PORT_REGISTER(4, PORTC_ARDUINO, 6); + CLEAR_PORT_REGISTER(5, PORTB_ARDUINO, 2); + CLEAR_PORT_REGISTER(6, PORTF_ARDUINO, 4); + CLEAR_PORT_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } - PORTDClass& operator|=(uint8_t value) { - SET_PORT_REGISTER(0, PORTC_ARDUINO, 5); - SET_PORT_REGISTER(1, PORTC_ARDUINO, 4); - SET_PORT_REGISTER(2, PORTA_ARDUINO, 0); - SET_PORT_REGISTER(3, PORTF_ARDUINO, 5); - SET_PORT_REGISTER(4, PORTC_ARDUINO, 6); - SET_PORT_REGISTER(5, PORTB_ARDUINO, 2); - SET_PORT_REGISTER(6, PORTF_ARDUINO, 4); - SET_PORT_REGISTER(7, PORTA_ARDUINO, 1); - return *this; - } + PORTDClass& operator|=(uint8_t value) + { + SET_PORT_REGISTER(0, PORTC_ARDUINO, 5); + SET_PORT_REGISTER(1, PORTC_ARDUINO, 4); + SET_PORT_REGISTER(2, PORTA_ARDUINO, 0); + SET_PORT_REGISTER(3, PORTF_ARDUINO, 5); + SET_PORT_REGISTER(4, PORTC_ARDUINO, 6); + SET_PORT_REGISTER(5, PORTB_ARDUINO, 2); + SET_PORT_REGISTER(6, PORTF_ARDUINO, 4); + SET_PORT_REGISTER(7, PORTA_ARDUINO, 1); + return *this; + } }; extern PORTBClass PORTB; diff --git a/megaavr/cores/coreX-corefiles/USBCore.cpp b/megaavr/cores/coreX-corefiles/USBCore.cpp index e6ee84a..a20ce0a 100644 --- a/megaavr/cores/coreX-corefiles/USBCore.cpp +++ b/megaavr/cores/coreX-corefiles/USBCore.cpp @@ -17,12 +17,14 @@ ** SOFTWARE. */ +#include "USBCore.h" + +#include + #include "Arduino.h" -#include "api/USBAPI.h" #include "api/PluggableUSB.h" -#include "USBCore.h" +#include "api/USBAPI.h" #include "pins_arduino.h" -#include #if defined(USBCON) @@ -40,152 +42,151 @@ extern const uint8_t STRING_MANUFACTURER[] PROGMEM; extern const DeviceDescriptor USB_DeviceDescriptorIAD PROGMEM; const uint16_t STRING_LANGUAGE[2] = { - (3<<8) | (2+2), - 0x0409 // English + (3 << 8) | (2 + 2), + 0x0409 // English }; #ifndef USB_PRODUCT // If no product is provided, use USB IO Board -#define USB_PRODUCT "USB IO Board" +#define USB_PRODUCT "USB IO Board" #endif const uint8_t STRING_PRODUCT[] PROGMEM = USB_PRODUCT; #if USB_VID == 0x2341 -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "Arduino LLC" +#if defined(USB_MANUFACTURER) +#undef USB_MANUFACTURER +#endif +#define USB_MANUFACTURER "Arduino LLC" #elif USB_VID == 0x1b4f -# if defined(USB_MANUFACTURER) -# undef USB_MANUFACTURER -# endif -# define USB_MANUFACTURER "SparkFun" +#if defined(USB_MANUFACTURER) +#undef USB_MANUFACTURER +#endif +#define USB_MANUFACTURER "SparkFun" #elif !defined(USB_MANUFACTURER) // Fall through to unknown if no manufacturer name was provided in a macro -# define USB_MANUFACTURER "Unknown" +#define USB_MANUFACTURER "Unknown" #endif const uint8_t STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER; - #define DEVICE_CLASS 0x02 -// DEVICE DESCRIPTOR +// DEVICE DESCRIPTOR const DeviceDescriptor USB_DeviceDescriptorIAD = - D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1); + D_DEVICE(0xEF, 0x02, 0x01, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, ISERIAL, 1); //================================================================== //================================================================== volatile uint8_t _usbConfiguration = 0; volatile uint8_t _usbCurrentStatus = 0; // meaning of bits see usb_20.pdf, Figure 9-4. Information Returned by a GetStatus() Request to a Device -volatile uint8_t _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits +volatile uint8_t _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits static inline void WaitIN(void) { - while (!(UEINTX & (1< len) { - n = len; - } - - { - LockEP lock(ep); - // Frame may have been released by the SOF interrupt handler - if (!ReadWriteAllowed()) - continue; - - len -= n; - if (ep & TRANSFER_ZERO) - { - while (n--) - Send8(0); - } - else if (ep & TRANSFER_PGM) - { - while (n--) - Send8(pgm_read_byte(data++)); - } - else - { - while (n--) - Send8(*data++); - } - - if (sendZlp) { - ReleaseTX(); - sendZlp = false; - } else if (!ReadWriteAllowed()) { // ...release if buffer is full... - ReleaseTX(); - if (len == 0) sendZlp = true; - } else if ((len == 0) && (ep & TRANSFER_RELEASE)) { // ...or if forced with TRANSFER_RELEASE - // XXX: TRANSFER_RELEASE is never used can be removed? - ReleaseTX(); - } - } - } - TXLED1; // light the TX LED - TxLEDPulse = TX_RX_LED_PULSE_MS; - return r; + if (!_usbConfiguration) + return -1; + + if (_usbSuspendState & (1 << SUSPI)) + { + //send a remote wakeup + UDCON |= (1 << RMWKUP); + } + + int r = len; + const uint8_t* data = (const uint8_t*)d; + uint8_t timeout = 250; // 250ms timeout on send? TODO + bool sendZlp = false; + + while (len || sendZlp) + { + uint8_t n = USB_SendSpace(ep); + if (n == 0) + { + if (!(--timeout)) + return -1; + delay(1); + continue; + } + + if (n > len) + { + n = len; + } + + { + LockEP lock(ep); + // Frame may have been released by the SOF interrupt handler + if (!ReadWriteAllowed()) + continue; + + len -= n; + if (ep & TRANSFER_ZERO) + { + while (n--) + Send8(0); + } + else if (ep & TRANSFER_PGM) + { + while (n--) + Send8(pgm_read_byte(data++)); + } + else + { + while (n--) + Send8(*data++); + } + + if (sendZlp) + { + ReleaseTX(); + sendZlp = false; + } + else if (!ReadWriteAllowed()) + { // ...release if buffer is full... + ReleaseTX(); + if (len == 0) sendZlp = true; + } + else if ((len == 0) && (ep & TRANSFER_RELEASE)) + { // ...or if forced with TRANSFER_RELEASE + // XXX: TRANSFER_RELEASE is never used can be removed? + ReleaseTX(); + } + } + } + TXLED1; // light the TX LED + TxLEDPulse = TX_RX_LED_PULSE_MS; + return r; } uint16_t _initEndpoints[USB_ENDPOINTS] = -{ - 0, // Control Endpoint - - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM - EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT - EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN + { + 0, // Control Endpoint + + EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM + EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT + EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN - // Following endpoints are automatically initialized to 0 + // Following endpoints are automatically initialized to 0 }; -#define EP_SINGLE_64 0x32 // EP0 -#define EP_DOUBLE_64 0x36 // Other endpoints +#define EP_SINGLE_64 0x32 // EP0 +#define EP_DOUBLE_64 0x36 // Other endpoints #define EP_SINGLE_16 0x12 -void* epBuffer(unsigned int lastEp) { - return &(_initEndpoints[lastEp]); +void* epBuffer(unsigned int lastEp) +{ + return &(_initEndpoints[lastEp]); } -static -void InitEP(uint8_t index, uint8_t type, uint8_t size) +static void InitEP(uint8_t index, uint8_t type, uint8_t size) { - UENUM = index; - UECONX = (1< 64){ - recvLength = 64; - } - - // Write data to fit to the end (not the beginning) of the array - WaitOUT(); - Recv((uint8_t*)d + len - length, recvLength); - ClearOUT(); - length -= recvLength; - } - return len; + auto length = len; + while (length) + { + // Dont receive more than the USB Control EP has to offer + // Use fixed 64 because control EP always have 64 bytes even on 16u2. + auto recvLength = length; + if (recvLength > 64) + { + recvLength = 64; + } + + // Write data to fit to the end (not the beginning) of the array + WaitOUT(); + Recv((uint8_t*)d + len - length, recvLength); + ClearOUT(); + length -= recvLength; + } + return len; } static uint8_t SendInterfaces() { - uint8_t interfaces = 0; + uint8_t interfaces = 0; - CDC_GetInterface(&interfaces); + CDC_GetInterface(&interfaces); #ifdef PLUGGABLE_USB_ENABLED - PluggableUSB().getInterface(&interfaces); + PluggableUSB().getInterface(&interfaces); #endif - return interfaces; + return interfaces; } -// Construct a dynamic configuration descriptor -// This really needs dynamic endpoint allocation etc -// TODO -static -bool SendConfiguration(int maxlen) +// Construct a dynamic configuration descriptor +// This really needs dynamic endpoint allocation etc +// TODO +static bool SendConfiguration(int maxlen) { - // Count and measure interfaces - InitControl(0); - uint8_t interfaces = SendInterfaces(); - ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); + // Count and measure interfaces + InitControl(0); + uint8_t interfaces = SendInterfaces(); + ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor), interfaces); - // Now send them - InitControl(maxlen); - USB_SendControl(0,&config,sizeof(ConfigDescriptor)); - SendInterfaces(); - return true; + // Now send them + InitControl(maxlen); + USB_SendControl(0, &config, sizeof(ConfigDescriptor)); + SendInterfaces(); + return true; } -static -bool SendDescriptor(USBSetup& setup) +static bool SendDescriptor(USBSetup& setup) { - int ret; - uint8_t t = setup.wValueH; - if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) - return SendConfiguration(setup.wLength); + int ret; + uint8_t t = setup.wValueH; + if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) + return SendConfiguration(setup.wLength); - InitControl(setup.wLength); + InitControl(setup.wLength); #ifdef PLUGGABLE_USB_ENABLED - ret = PluggableUSB().getDescriptor(setup); - if (ret != 0) { - return (ret > 0 ? true : false); - } + ret = PluggableUSB().getDescriptor(setup); + if (ret != 0) + { + return (ret > 0 ? true : false); + } #endif - const uint8_t* desc_addr = 0; - if (USB_DEVICE_DESCRIPTOR_TYPE == t) - { - desc_addr = (const uint8_t*)&USB_DeviceDescriptorIAD; - } - else if (USB_STRING_DESCRIPTOR_TYPE == t) - { - if (setup.wValueL == 0) { - desc_addr = (const uint8_t*)&STRING_LANGUAGE; - } - else if (setup.wValueL == IPRODUCT) { - return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM); - } - else if (setup.wValueL == IMANUFACTURER) { - return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM); - } - else if (setup.wValueL == ISERIAL) { + const uint8_t* desc_addr = 0; + if (USB_DEVICE_DESCRIPTOR_TYPE == t) + { + desc_addr = (const uint8_t*)&USB_DeviceDescriptorIAD; + } + else if (USB_STRING_DESCRIPTOR_TYPE == t) + { + if (setup.wValueL == 0) + { + desc_addr = (const uint8_t*)&STRING_LANGUAGE; + } + else if (setup.wValueL == IPRODUCT) + { + return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM); + } + else if (setup.wValueL == IMANUFACTURER) + { + return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM); + } + else if (setup.wValueL == ISERIAL) + { #ifdef PLUGGABLE_USB_ENABLED - char name[ISERIAL_MAX_LEN]; - PluggableUSB().getShortName(name); - return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0); + char name[ISERIAL_MAX_LEN]; + PluggableUSB().getShortName(name); + return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0); #endif - } - else - return false; - } + } + else + return false; + } - if (desc_addr == 0) - return false; - uint8_t desc_length = pgm_read_byte(desc_addr); + if (desc_addr == 0) + return false; + uint8_t desc_length = pgm_read_byte(desc_addr); - USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); - return true; + USB_SendControl(TRANSFER_PGM, desc_addr, desc_length); + return true; } -// Endpoint 0 interrupt +// Endpoint 0 interrupt ISR(USB_COM_vect) { - SetEP(0); - if (!ReceivedSetupInt()) - return; - - USBSetup setup; - Recv((uint8_t*)&setup,8); - ClearSetupInt(); - - uint8_t requestType = setup.bmRequestType; - if (requestType & REQUEST_DEVICETOHOST) - WaitIN(); - else - ClearIN(); - - bool ok = true; - if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) - { - // Standard Requests - uint8_t r = setup.bRequest; - uint16_t wValue = setup.wValueL | (setup.wValueH << 8); - if (GET_STATUS == r) - { - if (requestType == (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_DEVICE)) - { - Send8(_usbCurrentStatus); - Send8(0); - } - else - { - // TODO: handle the HALT state of an endpoint here - // see "Figure 9-6. Information Returned by a GetStatus() Request to an Endpoint" in usb_20.pdf for more information - Send8(0); - Send8(0); - } - } - else if (CLEAR_FEATURE == r) - { - if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) - && (wValue == DEVICE_REMOTE_WAKEUP)) - { - _usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED; - } - } - else if (SET_FEATURE == r) - { - if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE)) - && (wValue == DEVICE_REMOTE_WAKEUP)) - { - _usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; - } - } - else if (SET_ADDRESS == r) - { - WaitIN(); - UDADDR = setup.wValueL | (1< #include #include +#include class USBDevice_ { -public: - USBDevice_(); - bool configured(); - - void attach(); - void detach(); // Serial port goes down too... - void poll(); - bool wakeupHost(); // returns false, when wakeup cannot be processed + public: + USBDevice_(); + bool configured(); + + void attach(); + void detach(); // Serial port goes down too... + void poll(); + bool wakeupHost(); // returns false, when wakeup cannot be processed }; extern USBDevice_ USBDevice; -// Standard requests -#define GET_STATUS 0 -#define CLEAR_FEATURE 1 -#define SET_FEATURE 3 -#define SET_ADDRESS 5 -#define GET_DESCRIPTOR 6 -#define SET_DESCRIPTOR 7 -#define GET_CONFIGURATION 8 -#define SET_CONFIGURATION 9 -#define GET_INTERFACE 10 -#define SET_INTERFACE 11 +// Standard requests +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 +#define GET_INTERFACE 10 +#define SET_INTERFACE 11 // bmRequestType -#define REQUEST_HOSTTODEVICE 0x00 -#define REQUEST_DEVICETOHOST 0x80 -#define REQUEST_DIRECTION 0x80 - -#define REQUEST_STANDARD 0x00 -#define REQUEST_CLASS 0x20 -#define REQUEST_VENDOR 0x40 -#define REQUEST_TYPE 0x60 - -#define REQUEST_DEVICE 0x00 -#define REQUEST_INTERFACE 0x01 -#define REQUEST_ENDPOINT 0x02 -#define REQUEST_OTHER 0x03 -#define REQUEST_RECIPIENT 0x03 - -#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) -#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE 0x00 +#define REQUEST_DEVICETOHOST 0x80 +#define REQUEST_DIRECTION 0x80 + +#define REQUEST_STANDARD 0x00 +#define REQUEST_CLASS 0x20 +#define REQUEST_VENDOR 0x40 +#define REQUEST_TYPE 0x60 + +#define REQUEST_DEVICE 0x00 +#define REQUEST_INTERFACE 0x01 +#define REQUEST_ENDPOINT 0x02 +#define REQUEST_OTHER 0x03 +#define REQUEST_RECIPIENT 0x03 + +#define REQUEST_DEVICETOHOST_CLASS_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) #define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE) -// Class requests +// Class requests -#define CDC_SET_LINE_CODING 0x20 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 -#define CDC_SEND_BREAK 0x23 +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#define CDC_SEND_BREAK 0x23 -#define MSC_RESET 0xFF -#define MSC_GET_MAX_LUN 0xFE +#define MSC_RESET 0xFF +#define MSC_GET_MAX_LUN 0xFE -// Descriptors +// Descriptors #define USB_DEVICE_DESC_SIZE 18 #define USB_CONFIGUARTION_DESC_SIZE 9 #define USB_INTERFACE_DESC_SIZE 9 #define USB_ENDPOINT_DESC_SIZE 7 -#define USB_DEVICE_DESCRIPTOR_TYPE 1 -#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 -#define USB_STRING_DESCRIPTOR_TYPE 3 -#define USB_INTERFACE_DESCRIPTOR_TYPE 4 -#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 +#define USB_DEVICE_DESCRIPTOR_TYPE 1 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2 +#define USB_STRING_DESCRIPTOR_TYPE 3 +#define USB_INTERFACE_DESCRIPTOR_TYPE 4 +#define USB_ENDPOINT_DESCRIPTOR_TYPE 5 // usb_20.pdf Table 9.6 Standard Feature Selectors -#define DEVICE_REMOTE_WAKEUP 1 -#define ENDPOINT_HALT 2 -#define TEST_MODE 3 +#define DEVICE_REMOTE_WAKEUP 1 +#define ENDPOINT_HALT 2 +#define TEST_MODE 3 // usb_20.pdf Figure 9-4. Information Returned by a GetStatus() Request to a Device -#define FEATURE_SELFPOWERED_ENABLED (1 << 0) -#define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1) +#define FEATURE_SELFPOWERED_ENABLED (1 << 0) +#define FEATURE_REMOTE_WAKEUP_ENABLED (1 << 1) -#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 -#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 -#define USB_DEVICE_CLASS_STORAGE 0x08 -#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF +#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03 +#define USB_DEVICE_CLASS_STORAGE 0x08 +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF -#define USB_CONFIG_POWERED_MASK 0x40 -#define USB_CONFIG_BUS_POWERED 0x80 -#define USB_CONFIG_SELF_POWERED 0xC0 -#define USB_CONFIG_REMOTE_WAKEUP 0x20 +#define USB_CONFIG_POWERED_MASK 0x40 +#define USB_CONFIG_BUS_POWERED 0x80 +#define USB_CONFIG_SELF_POWERED 0xC0 +#define USB_CONFIG_REMOTE_WAKEUP 0x20 // bMaxPower in Configuration Descriptor -#define USB_CONFIG_POWER_MA(mA) ((mA)/2) +#define USB_CONFIG_POWER_MA(mA) ((mA) / 2) // bEndpointAddress in Endpoint Descriptor -#define USB_ENDPOINT_DIRECTION_MASK 0x80 -#define USB_ENDPOINT_OUT(addr) (lowByte((addr) | 0x00)) -#define USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) +#define USB_ENDPOINT_DIRECTION_MASK 0x80 +#define USB_ENDPOINT_OUT(addr) (lowByte((addr) | 0x00)) +#define USB_ENDPOINT_IN(addr) (lowByte((addr) | 0x80)) -#define USB_ENDPOINT_TYPE_MASK 0x03 -#define USB_ENDPOINT_TYPE_CONTROL 0x00 -#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 -#define USB_ENDPOINT_TYPE_BULK 0x02 -#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 +#define USB_ENDPOINT_TYPE_MASK 0x03 +#define USB_ENDPOINT_TYPE_CONTROL 0x00 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_TYPE_BULK 0x02 +#define USB_ENDPOINT_TYPE_INTERRUPT 0x03 -#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) +#define TOBYTES(x) ((x)&0xFF), (((x) >> 8) & 0xFF) -#define CDC_V1_10 0x0110 -#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 +#define CDC_V1_10 0x0110 +#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02 -#define CDC_CALL_MANAGEMENT 0x01 -#define CDC_ABSTRACT_CONTROL_MODEL 0x02 -#define CDC_HEADER 0x00 -#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 -#define CDC_UNION 0x06 -#define CDC_CS_INTERFACE 0x24 -#define CDC_CS_ENDPOINT 0x25 -#define CDC_DATA_INTERFACE_CLASS 0x0A +#define CDC_CALL_MANAGEMENT 0x01 +#define CDC_ABSTRACT_CONTROL_MODEL 0x02 +#define CDC_HEADER 0x00 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02 +#define CDC_UNION 0x06 +#define CDC_CS_INTERFACE 0x24 +#define CDC_CS_ENDPOINT 0x25 +#define CDC_DATA_INTERFACE_CLASS 0x0A -#define MSC_SUBCLASS_SCSI 0x06 -#define MSC_PROTOCOL_BULK_ONLY 0x50 +#define MSC_SUBCLASS_SCSI 0x06 +#define MSC_PROTOCOL_BULK_ONLY 0x50 #ifndef USB_VERSION #define USB_VERSION 0x200 #endif -#define TRANSFER_PGM 0x80 -#define TRANSFER_RELEASE 0x40 -#define TRANSFER_ZERO 0x20 - -// Device -typedef struct { - uint8_t len; // 18 - uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE - uint16_t usbVersion; // 0x200 or 0x210 - uint8_t deviceClass; - uint8_t deviceSubClass; - uint8_t deviceProtocol; - uint8_t packetSize0; // Packet 0 - uint16_t idVendor; - uint16_t idProduct; - uint16_t deviceVersion; // 0x100 - uint8_t iManufacturer; - uint8_t iProduct; - uint8_t iSerialNumber; - uint8_t bNumConfigurations; +#define TRANSFER_PGM 0x80 +#define TRANSFER_RELEASE 0x40 +#define TRANSFER_ZERO 0x20 + +// Device +typedef struct +{ + uint8_t len; // 18 + uint8_t dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE + uint16_t usbVersion; // 0x200 or 0x210 + uint8_t deviceClass; + uint8_t deviceSubClass; + uint8_t deviceProtocol; + uint8_t packetSize0; // Packet 0 + uint16_t idVendor; + uint16_t idProduct; + uint16_t deviceVersion; // 0x100 + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; } DeviceDescriptor; -// Config -typedef struct { - uint8_t len; // 9 - uint8_t dtype; // 2 - uint16_t clen; // total length - uint8_t numInterfaces; - uint8_t config; - uint8_t iconfig; - uint8_t attributes; - uint8_t maxPower; +// Config +typedef struct +{ + uint8_t len; // 9 + uint8_t dtype; // 2 + uint16_t clen; // total length + uint8_t numInterfaces; + uint8_t config; + uint8_t iconfig; + uint8_t attributes; + uint8_t maxPower; } ConfigDescriptor; -// String +// String -// Interface +// Interface typedef struct { - uint8_t len; // 9 - uint8_t dtype; // 4 - uint8_t number; - uint8_t alternate; - uint8_t numEndpoints; - uint8_t interfaceClass; - uint8_t interfaceSubClass; - uint8_t protocol; - uint8_t iInterface; + uint8_t len; // 9 + uint8_t dtype; // 4 + uint8_t number; + uint8_t alternate; + uint8_t numEndpoints; + uint8_t interfaceClass; + uint8_t interfaceSubClass; + uint8_t protocol; + uint8_t iInterface; } InterfaceDescriptor; -// Endpoint +// Endpoint typedef struct { - uint8_t len; // 7 - uint8_t dtype; // 5 - uint8_t addr; - uint8_t attr; - uint16_t packetSize; - uint8_t interval; + uint8_t len; // 7 + uint8_t dtype; // 5 + uint8_t addr; + uint8_t attr; + uint16_t packetSize; + uint8_t interval; } EndpointDescriptor; // Interface Association Descriptor // Used to bind 2 interfaces together in CDC compostite device typedef struct { - uint8_t len; // 8 - uint8_t dtype; // 11 - uint8_t firstInterface; - uint8_t interfaceCount; - uint8_t functionClass; - uint8_t funtionSubClass; - uint8_t functionProtocol; - uint8_t iInterface; + uint8_t len; // 8 + uint8_t dtype; // 11 + uint8_t firstInterface; + uint8_t interfaceCount; + uint8_t functionClass; + uint8_t funtionSubClass; + uint8_t functionProtocol; + uint8_t iInterface; } IADDescriptor; -// CDC CS interface descriptor +// CDC CS interface descriptor typedef struct { - uint8_t len; // 5 - uint8_t dtype; // 0x24 - uint8_t subtype; - uint8_t d0; - uint8_t d1; + uint8_t len; // 5 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; + uint8_t d1; } CDCCSInterfaceDescriptor; typedef struct { - uint8_t len; // 4 - uint8_t dtype; // 0x24 - uint8_t subtype; - uint8_t d0; + uint8_t len; // 4 + uint8_t dtype; // 0x24 + uint8_t subtype; + uint8_t d0; } CDCCSInterfaceDescriptor4; -typedef struct +typedef struct { - uint8_t len; - uint8_t dtype; // 0x24 - uint8_t subtype; // 1 - uint8_t bmCapabilities; - uint8_t bDataInterface; + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; + uint8_t bDataInterface; } CMFunctionalDescriptor; - -typedef struct + +typedef struct { - uint8_t len; - uint8_t dtype; // 0x24 - uint8_t subtype; // 1 - uint8_t bmCapabilities; + uint8_t len; + uint8_t dtype; // 0x24 + uint8_t subtype; // 1 + uint8_t bmCapabilities; } ACMFunctionalDescriptor; -typedef struct +typedef struct { - // IAD - IADDescriptor iad; // Only needed on compound device - - // Control - InterfaceDescriptor cif; // - CDCCSInterfaceDescriptor header; - CMFunctionalDescriptor callManagement; // Call Management - ACMFunctionalDescriptor controlManagement; // ACM - CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION - EndpointDescriptor cifin; - - // Data - InterfaceDescriptor dif; - EndpointDescriptor in; - EndpointDescriptor out; + // IAD + IADDescriptor iad; // Only needed on compound device + + // Control + InterfaceDescriptor cif; // + CDCCSInterfaceDescriptor header; + CMFunctionalDescriptor callManagement; // Call Management + ACMFunctionalDescriptor controlManagement; // ACM + CDCCSInterfaceDescriptor functionalDescriptor; // CDC_UNION + EndpointDescriptor cifin; + + // Data + InterfaceDescriptor dif; + EndpointDescriptor in; + EndpointDescriptor out; } CDCDescriptor; -typedef struct +typedef struct { - InterfaceDescriptor msc; - EndpointDescriptor in; - EndpointDescriptor out; + InterfaceDescriptor msc; + EndpointDescriptor in; + EndpointDescriptor out; } MSCDescriptor; +#define D_DEVICE(_class, _subClass, _proto, _packetSize0, _vid, _pid, _version, _im, _ip, _is, _configs) \ + { \ + 18, 1, USB_VERSION, _class, _subClass, _proto, _packetSize0, _vid, _pid, _version, _im, _ip, _is, _configs \ + } -#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ - { 18, 1, USB_VERSION, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } - -#define D_CONFIG(_totalLength,_interfaces) \ - { 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) } +#define D_CONFIG(_totalLength, _interfaces) \ + { \ + 9, 2, _totalLength, _interfaces, 1, 0, USB_CONFIG_BUS_POWERED | USB_CONFIG_REMOTE_WAKEUP, USB_CONFIG_POWER_MA(500) \ + } -#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ - { 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } +#define D_INTERFACE(_n, _numEndpoints, _class, _subClass, _protocol) \ + { \ + 9, 4, _n, 0, _numEndpoints, _class, _subClass, _protocol, 0 \ + } -#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ - { 7, 5, _addr,_attr,_packetSize, _interval } +#define D_ENDPOINT(_addr, _attr, _packetSize, _interval) \ + { \ + 7, 5, _addr, _attr, _packetSize, _interval \ + } #define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ - { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } - -#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } -#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } + { \ + 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 \ + } + +#define D_CDCCS(_subtype, _d0, _d1) \ + { \ + 5, 0x24, _subtype, _d0, _d1 \ + } +#define D_CDCCS4(_subtype, _d0) \ + { \ + 4, 0x24, _subtype, _d0 \ + } // Bootloader related fields // Old Caterina bootloader places the MAGIC key into unsafe RAM locations (it can be rewritten @@ -327,13 +344,13 @@ typedef struct #define USB_ENDPOINTS 5 // AtMegaxxU2 #endif -#define EP_TYPE_CONTROL (0x00) -#define EP_TYPE_BULK_IN ((1< -#include #include +#include #include +#include #include #include "wiring_private.h" static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; -void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { - +void attachInterrupt(uint8_t pin, void (*userFunc)(void), uint8_t mode) +{ /* Get bit position and check pin validity */ uint8_t bit_pos = digitalPinToBitPosition(pin); - if(bit_pos == NOT_A_PIN) return; + if (bit_pos == NOT_A_PIN) return; /* Get interrupt number from pin */ uint8_t interruptNum = (digitalPinToPort(pin) * 8) + bit_pos; /* Check interrupt number and apply function pointer to correct array index */ - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { + if (interruptNum < EXTERNAL_NUM_INTERRUPTS) + { intFunc[interruptNum] = userFunc; // Configure the interrupt mode (trigger on low input, any change, rising @@ -52,7 +51,8 @@ void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { // to the configuration bits in the hardware register, so we simply apply // the setting in the pin control register - switch (mode) { + switch (mode) + { case CHANGE: mode = PORT_ISC_BOTHEDGES_gc; break; @@ -74,7 +74,7 @@ void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { /* Get pointer to correct pin control register */ PORT_t *port = digitalPinToPortStruct(pin); - volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); + volatile uint8_t *pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); /* Clear any previous setting */ *pin_ctrl_reg &= ~(PORT_ISC_gm); @@ -84,20 +84,22 @@ void attachInterrupt(uint8_t pin, void (*userFunc)(void), PinStatus mode) { } } -void detachInterrupt(uint8_t pin) { +void detachInterrupt(uint8_t pin) +{ /* Get bit position and check pin validity */ uint8_t bit_pos = digitalPinToBitPosition(pin); - if(bit_pos == NOT_A_PIN) return; + if (bit_pos == NOT_A_PIN) return; /* Get interrupt number from pin */ uint8_t interruptNum = (digitalPinToPort(pin) * 8) + bit_pos; - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { + if (interruptNum < EXTERNAL_NUM_INTERRUPTS) + { // Disable the interrupt. /* Get pointer to correct pin control register */ PORT_t *port = digitalPinToPortStruct(pin); - volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); + volatile uint8_t *pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); /* Clear ISC setting */ *pin_ctrl_reg &= ~(PORT_ISC_gm); @@ -106,8 +108,8 @@ void detachInterrupt(uint8_t pin) { } } -static void port_interrupt_handler(uint8_t port) { - +static void port_interrupt_handler(uint8_t port) +{ PORT_t *portStruct = portToPortStruct(port); /* Copy flags */ uint8_t int_flags = portStruct->INTFLAGS; @@ -115,23 +117,23 @@ static void port_interrupt_handler(uint8_t port) { uint8_t bit_pos = PIN0_bp, bit_mask = PIN0_bm; /* Iterate through flags */ - while(bit_pos <= PIN7_bp){ - + while (bit_pos <= PIN7_bp) + { /* Check if flag raised */ - if(int_flags & bit_mask){ - - /* Get interrupt */ - uint8_t interrupt_num = port*8 + bit_pos; + if (int_flags & bit_mask) + { + /* Get interrupt */ + uint8_t interrupt_num = port * 8 + bit_pos; /* Check if function defined */ - if(intFunc[interrupt_num] != 0){ - + if (intFunc[interrupt_num] != 0) + { /* Call function */ intFunc[interrupt_num](); } } bit_pos++; - bit_mask = (bit_mask << 1); + bit_mask = (bit_mask << 1); } /* Clear flags that have been handled */ @@ -139,9 +141,10 @@ static void port_interrupt_handler(uint8_t port) { } #define IMPLEMENT_ISR(vect, port) \ -ISR(vect) { \ - port_interrupt_handler(port);\ -} \ + ISR(vect) \ + { \ + port_interrupt_handler(port); \ + } IMPLEMENT_ISR(PORTA_PORT_vect, PA) IMPLEMENT_ISR(PORTB_PORT_vect, PB) diff --git a/megaavr/cores/coreX-corefiles/WMath.cpp b/megaavr/cores/coreX-corefiles/WMath.cpp index f4ce2b7..9a5af7d 100644 --- a/megaavr/cores/coreX-corefiles/WMath.cpp +++ b/megaavr/cores/coreX-corefiles/WMath.cpp @@ -1,5 +1,3 @@ -/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - /* Part of the Wiring project - http://wiring.org.co Copyright (c) 2004-06 Hernando Barragan @@ -21,20 +19,23 @@ Boston, MA 02111-1307 USA */ -extern "C" { +extern "C" +{ #include "stdlib.h" } void randomSeed(unsigned long seed) { - if (seed != 0) { + if (seed != 0) + { srandom(seed); } } long random(long howbig) { - if (howbig == 0) { + if (howbig == 0) + { return 0; } return random() % howbig; @@ -42,7 +43,8 @@ long random(long howbig) long random(long howsmall, long howbig) { - if (howsmall >= howbig) { + if (howsmall >= howbig) + { return howsmall; } long diff = howbig - howsmall; diff --git a/megaavr/cores/coreX-corefiles/api/ArduinoAPI.h b/megaavr/cores/coreX-corefiles/api/ArduinoAPI.h index b737af9..1535fe9 100644 --- a/megaavr/cores/coreX-corefiles/api/ArduinoAPI.h +++ b/megaavr/cores/coreX-corefiles/api/ArduinoAPI.h @@ -30,23 +30,23 @@ #include "HardwareI2C.h" #include "HardwareSerial.h" #include "IPAddress.h" +#include "PluggableUSB.h" #include "Print.h" #include "Printable.h" -#include "PluggableUSB.h" #include "Server.h" -#include "String.h" #include "Stream.h" -#include "Udp.h" +#include "String.h" #include "USBAPI.h" +#include "Udp.h" #include "WCharacter.h" #endif /* Standard C library includes */ -#include -#include +#include #include +#include +#include #include -#include // Misc Arduino core functions #include "Common.h" diff --git a/megaavr/cores/coreX-corefiles/api/Client.h b/megaavr/cores/coreX-corefiles/api/Client.h index c8ebc9f..e42a66a 100644 --- a/megaavr/cores/coreX-corefiles/api/Client.h +++ b/megaavr/cores/coreX-corefiles/api/Client.h @@ -19,16 +19,16 @@ #pragma once -#include "Stream.h" #include "IPAddress.h" - -class Client : public Stream { - -public: - virtual int connect(IPAddress ip, uint16_t port) =0; - virtual int connect(const char *host, uint16_t port) =0; - virtual size_t write(uint8_t) =0; - virtual size_t write(const uint8_t *buf, size_t size) =0; +#include "Stream.h" +namespace arduino { +class Client : public Stream +{ + public: + virtual int connect(IPAddress ip, uint16_t port) = 0; + virtual int connect(const char *host, uint16_t port) = 0; + virtual size_t write(uint8_t) = 0; + virtual size_t write(const uint8_t *buf, size_t size) = 0; virtual int available() = 0; virtual int read() = 0; virtual int read(uint8_t *buf, size_t size) = 0; @@ -37,7 +37,10 @@ class Client : public Stream { virtual void stop() = 0; virtual uint8_t connected() = 0; virtual operator bool() = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; + + protected: + uint8_t *rawIPAddress(IPAddress &addr) { return addr.raw_address(); }; }; +} +using arduino::Client; diff --git a/megaavr/cores/coreX-corefiles/api/Common.cpp b/megaavr/cores/coreX-corefiles/api/Common.cpp index d1f822c..bd7a5e2 100644 --- a/megaavr/cores/coreX-corefiles/api/Common.cpp +++ b/megaavr/cores/coreX-corefiles/api/Common.cpp @@ -7,4 +7,4 @@ long map(long x, long in_min, long in_max, long out_min, long out_max) } uint16_t makeWord(uint16_t w) { return w; } -uint16_t makeWord(uint8_t h, uint8_t l) { return (h << 8) | l; } \ No newline at end of file +uint16_t makeWord(uint8_t h, uint8_t l) { return (h << 8) | l; } diff --git a/megaavr/cores/coreX-corefiles/api/Common.h b/megaavr/cores/coreX-corefiles/api/Common.h index 302be4c..2864970 100644 --- a/megaavr/cores/coreX-corefiles/api/Common.h +++ b/megaavr/cores/coreX-corefiles/api/Common.h @@ -6,65 +6,30 @@ extern "C"{ void yield(void); -typedef enum { - LOW = 0, - HIGH = 1, - CHANGE = 2, - FALLING = 3, - RISING = 4, -} PinStatus; - -typedef enum { - INPUT = 0x0, - OUTPUT = 0x1, - INPUT_PULLUP = 0x2, - INPUT_PULLDOWN = 0x3, -} PinMode; - -typedef enum { - LSBFIRST = 0, - MSBFIRST = 1, -} BitOrder; - -#define PI 3.1415926535897932384626433832795 -#define HALF_PI 1.5707963267948966192313216916398 -#define TWO_PI 6.283185307179586476925286766559 -#define DEG_TO_RAD 0.017453292519943295769236907684886 -#define RAD_TO_DEG 57.295779513082320876798154814105 -#define EULER 2.718281828459045235360287471352 - -#define SERIAL 0x0 -#define DISPLAY 0x1 +#define LOW 0 +#define HIGH 1 -#ifndef min -#define min(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a < _b ? _a : _b; }) -#endif +#define FALLING 2 +#define RISING 3 +#define CHANGE 4 -#ifndef max -#define max(a,b) \ - ({ __typeof__ (a) _a = (a); \ - __typeof__ (b) _b = (b); \ - _a > _b ? _a : _b; }) -#endif +#define INPUT 0 +#define OUTPUT 1 +#define INPUT_PULLUP 2 +//#define INPUT_PULLDOWN 3 -#ifndef constrain -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#endif - -#ifndef radians -#define radians(deg) ((deg)*DEG_TO_RAD) -#endif +#define LSBFIRST 0 +#define MSBFIRST 1 -#ifndef degrees -#define degrees(rad) ((rad)*RAD_TO_DEG) -#endif +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 +#define EULER 2.718281828459045235360287471352 -#ifndef sq -#define sq(x) ((x)*(x)) -#endif +#define SERIAL 0 +#define DISPLAY 1 typedef void (*voidFuncPtr)(void); @@ -100,12 +65,16 @@ typedef uint32_t pin_size_t; typedef uint8_t pin_size_t; #endif -void pinMode(pin_size_t pinNumber, PinMode pinMode); -void digitalWrite(pin_size_t pinNumber, PinStatus status); -PinStatus digitalRead(pin_size_t pinNumber); +void pinMode(pin_size_t pinNumber, uint8_t pinMode); +void digitalWrite(pin_size_t pinNumber, uint8_t status); +void digitalWriteFast(pin_size_t pinNumber, uint8_t status); +uint8_t digitalRead(pin_size_t pinNumber); +uint8_t digitalReadFast(pin_size_t pinNumber); int analogRead(pin_size_t pinNumber); +uint8_t analogReadResolution(uint8_t res); void analogReference(uint8_t mode); void analogWrite(pin_size_t pinNumber, int value); +void analogWriteFrequency(uint8_t kHz); unsigned long millis(void); unsigned long micros(void); @@ -114,19 +83,101 @@ void delayMicroseconds(unsigned int us); unsigned long pulseIn(pin_size_t pin, uint8_t state, unsigned long timeout); unsigned long pulseInLong(pin_size_t pin, uint8_t state, unsigned long timeout); -void shiftOut(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder, uint8_t val); -pin_size_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, BitOrder bitOrder); +void shiftOut(pin_size_t dataPin, pin_size_t clockPin, uint8_t bitOrder, uint8_t val); +pin_size_t shiftIn(pin_size_t dataPin, pin_size_t clockPin, uint8_t bitOrder); -void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode); +void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, uint8_t mode); void detachInterrupt(pin_size_t interruptNumber); void setup(void); void loop(void); +// Constant checks error handler +void badArg(const char*) __attribute__((error(""))); +inline __attribute__((always_inline)) void check_constant_pin(pin_size_t pin) +{ + if(!__builtin_constant_p(pin)) + badArg("Digital pin must be a constant"); +} + #ifdef __cplusplus } // extern "C" #endif +#ifdef __cplusplus +#ifndef min + template + auto min(const T& a, const L& b) -> decltype((b < a) ? b : a) { + return (b < a) ? b : a; + } +#endif + +#ifndef max + template + auto max(const T& a, const L& b) -> decltype((a < b) ? b : a) { + return (a < b) ? b : a; + } +#endif + +#ifndef round + template + long round(const T& x) { + return (long)(x >= 0 ? (x + 0.5) : (x - 0.5)); + } +#endif + +#ifndef max + template + auto sq(const T& x) -> decltype(x * x) { + return x * x; + } +#endif + +#ifndef radians + template + auto radians(const T& deg) -> decltype(deg * DEG_TO_RAD) { + return deg * DEG_TO_RAD; + } +#endif + +#ifndef degrees + template + auto degrees(const T& rad) -> decltype(rad * RAD_TO_DEG) { + return rad * RAD_TO_DEG; + } +#endif +#ifndef constrain + template + auto constrain(const T& x, const L& l, const H& h) -> decltype((x < l) ? l : (x > h) ? h : x) { + return (x < l) ? l : (x > h) ? h : x; + } +#endif + +#else + #ifndef min + #define min(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a < _b ? _a : _b; }) + #endif + #ifndef max + #define max(a,b) ({ typeof (a) _a = (a); typeof (b) _b = (b); _a > _b ? _a : _b; }) + #endif + #ifndef sq + #define sq(x) ({ typeof (x) _x = (x); _x * _x; }) + #endif + #ifndef radians + #define radians(deg) ((deg) * DEG_TO_RAD) + #endif + #ifndef degrees + #define degrees(rad) ((rad) * RAD_TO_DEG) + #endif + #ifndef constrain + #define constrain(x,low,high) ({ \ + typeof (x) _x = (x); \ + typeof (low) _l = (low); \ + typeof (high) _h = (high); \ + _x < _l ? _l : _x > _h ? _h : _x; }) + #endif +#endif // __cplusplus + #ifdef __cplusplus /* C++ prototypes */ @@ -147,4 +198,4 @@ long random(long, long); void randomSeed(unsigned long); long map(long, long, long, long, long); -#endif // __cplusplus \ No newline at end of file +#endif // __cplusplus diff --git a/megaavr/cores/coreX-corefiles/api/HardwareI2C.h b/megaavr/cores/coreX-corefiles/api/HardwareI2C.h index 25bf40e..5e37368 100644 --- a/megaavr/cores/coreX-corefiles/api/HardwareI2C.h +++ b/megaavr/cores/coreX-corefiles/api/HardwareI2C.h @@ -19,25 +19,25 @@ #pragma once #include + #include "Stream.h" class HardwareI2C : public Stream { - public: - virtual void begin() = 0; - virtual void begin(uint8_t address) = 0; - virtual void end() = 0; - - virtual void setClock(uint32_t freq) = 0; - - virtual void beginTransmission(uint8_t address) = 0; - virtual uint8_t endTransmission(bool stopBit) = 0; - virtual uint8_t endTransmission(void) = 0; - - virtual uint8_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0; - virtual uint8_t requestFrom(uint8_t address, size_t len) = 0; - - virtual void onReceive(void(*)(int)) = 0; - virtual void onRequest(void(*)(void)) = 0; -}; + public: + virtual void begin() = 0; + virtual void begin(uint8_t address) = 0; + virtual void end() = 0; + + virtual void setClock(uint32_t freq) = 0; + virtual void beginTransmission(uint8_t address) = 0; + virtual uint8_t endTransmission(bool stopBit) = 0; + virtual uint8_t endTransmission(void) = 0; + + virtual uint8_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0; + virtual uint8_t requestFrom(uint8_t address, size_t len) = 0; + + virtual void onReceive(void (*)(int)) = 0; + virtual void onRequest(void (*)(void)) = 0; +}; diff --git a/megaavr/cores/coreX-corefiles/api/HardwareSerial.h b/megaavr/cores/coreX-corefiles/api/HardwareSerial.h index e3b0b27..94207ea 100644 --- a/megaavr/cores/coreX-corefiles/api/HardwareSerial.h +++ b/megaavr/cores/coreX-corefiles/api/HardwareSerial.h @@ -19,84 +19,86 @@ #pragma once #include + #include "Stream.h" // XXX: Those constants should be defined as const int / enums? // XXX: shall we use namespaces too? -#define SERIAL_PARITY_EVEN (0x1ul) -#define SERIAL_PARITY_ODD (0x2ul) -#define SERIAL_PARITY_NONE (0x3ul) -#define SERIAL_PARITY_MARK (0x4ul) -#define SERIAL_PARITY_SPACE (0x5ul) -#define SERIAL_PARITY_MASK (0xFul) +#define SERIAL_PARITY_EVEN (0x1ul) +#define SERIAL_PARITY_ODD (0x2ul) +#define SERIAL_PARITY_NONE (0x3ul) +#define SERIAL_PARITY_MARK (0x4ul) +#define SERIAL_PARITY_SPACE (0x5ul) +#define SERIAL_PARITY_MASK (0xFul) -#define SERIAL_STOP_BIT_1 (0x10ul) -#define SERIAL_STOP_BIT_1_5 (0x20ul) -#define SERIAL_STOP_BIT_2 (0x30ul) +#define SERIAL_STOP_BIT_1 (0x10ul) +#define SERIAL_STOP_BIT_1_5 (0x20ul) +#define SERIAL_STOP_BIT_2 (0x30ul) #define SERIAL_STOP_BIT_MASK (0xF0ul) -#define SERIAL_DATA_5 (0x100ul) -#define SERIAL_DATA_6 (0x200ul) -#define SERIAL_DATA_7 (0x300ul) -#define SERIAL_DATA_8 (0x400ul) -#define SERIAL_DATA_MASK (0xF00ul) +#define SERIAL_DATA_5 (0x100ul) +#define SERIAL_DATA_6 (0x200ul) +#define SERIAL_DATA_7 (0x300ul) +#define SERIAL_DATA_8 (0x400ul) +#define SERIAL_DATA_MASK (0xF00ul) -#define SERIAL_5N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5) -#define SERIAL_6N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6) -#define SERIAL_7N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7) -#define SERIAL_8N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8) -#define SERIAL_5N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5) -#define SERIAL_6N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6) -#define SERIAL_7N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7) -#define SERIAL_8N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8) -#define SERIAL_5E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) -#define SERIAL_6E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) -#define SERIAL_7E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) -#define SERIAL_8E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) -#define SERIAL_5E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) -#define SERIAL_6E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) -#define SERIAL_7E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) -#define SERIAL_8E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) -#define SERIAL_5O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5) -#define SERIAL_6O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6) -#define SERIAL_7O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7) -#define SERIAL_8O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8) -#define SERIAL_5O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5) -#define SERIAL_6O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6) -#define SERIAL_7O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7) -#define SERIAL_8O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8) -#define SERIAL_5M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5) -#define SERIAL_6M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6) -#define SERIAL_7M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7) -#define SERIAL_8M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8) -#define SERIAL_5M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5) -#define SERIAL_6M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6) -#define SERIAL_7M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7) -#define SERIAL_8M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8) -#define SERIAL_5S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) -#define SERIAL_6S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) -#define SERIAL_7S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) -#define SERIAL_8S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) -#define SERIAL_5S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) -#define SERIAL_6S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) -#define SERIAL_7S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) -#define SERIAL_8S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) +#define SERIAL_5N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_5) +#define SERIAL_6N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_6) +#define SERIAL_7N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_7) +#define SERIAL_8N1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_NONE | SERIAL_DATA_8) +#define SERIAL_5N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_5) +#define SERIAL_6N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_6) +#define SERIAL_7N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_7) +#define SERIAL_8N2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_NONE | SERIAL_DATA_8) +#define SERIAL_5E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) +#define SERIAL_6E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) +#define SERIAL_7E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) +#define SERIAL_8E1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) +#define SERIAL_5E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_5) +#define SERIAL_6E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_6) +#define SERIAL_7E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_7) +#define SERIAL_8E2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_EVEN | SERIAL_DATA_8) +#define SERIAL_5O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_5) +#define SERIAL_6O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_6) +#define SERIAL_7O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_7) +#define SERIAL_8O1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_ODD | SERIAL_DATA_8) +#define SERIAL_5O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_5) +#define SERIAL_6O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_6) +#define SERIAL_7O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_7) +#define SERIAL_8O2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_ODD | SERIAL_DATA_8) +#define SERIAL_5M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_5) +#define SERIAL_6M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_6) +#define SERIAL_7M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_7) +#define SERIAL_8M1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_MARK | SERIAL_DATA_8) +#define SERIAL_5M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_5) +#define SERIAL_6M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_6) +#define SERIAL_7M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_7) +#define SERIAL_8M2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_MARK | SERIAL_DATA_8) +#define SERIAL_5S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) +#define SERIAL_6S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) +#define SERIAL_7S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) +#define SERIAL_8S1 (SERIAL_STOP_BIT_1 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) +#define SERIAL_5S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_5) +#define SERIAL_6S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_6) +#define SERIAL_7S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_7) +#define SERIAL_8S2 (SERIAL_STOP_BIT_2 | SERIAL_PARITY_SPACE | SERIAL_DATA_8) class HardwareSerial : public Stream { - public: - virtual void begin(unsigned long) = 0; - virtual void begin(unsigned long baudrate, uint16_t config) = 0; - virtual void end() = 0; - virtual int available(void) = 0; - virtual int peek(void) = 0; - virtual int read(void) = 0; - virtual void flush(void) = 0; - virtual size_t write(uint8_t) = 0; - using Print::write; // pull in write(str) and write(buf, size) from Print - virtual operator bool() = 0; + public: + virtual bool pins(uint8_t tx, uint8_t rx) = 0; + virtual bool swap(uint8_t state) = 0; + virtual void begin(unsigned long) = 0; + virtual void begin(unsigned long baudrate, uint16_t config) = 0; + virtual void end() = 0; + virtual int available(void) = 0; + virtual int peek(void) = 0; + virtual int read(void) = 0; + virtual void flush(void) = 0; + virtual size_t write(uint8_t) = 0; + using Print::write; // pull in write(str) and write(buf, size) from Print + virtual operator bool() = 0; }; // XXX: Are we keeping the serialEvent API? extern void serialEventRun(void) __attribute__((weak)); - diff --git a/megaavr/cores/coreX-corefiles/api/IPAddress.cpp b/megaavr/cores/coreX-corefiles/api/IPAddress.cpp index 62244d6..8f70061 100644 --- a/megaavr/cores/coreX-corefiles/api/IPAddress.cpp +++ b/megaavr/cores/coreX-corefiles/api/IPAddress.cpp @@ -18,100 +18,104 @@ */ #include "IPAddress.h" + #include "Print.h" IPAddress::IPAddress() { - _address.dword = 0; + _address.dword = 0; } IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) { - _address.bytes[0] = first_octet; - _address.bytes[1] = second_octet; - _address.bytes[2] = third_octet; - _address.bytes[3] = fourth_octet; + _address.bytes[0] = first_octet; + _address.bytes[1] = second_octet; + _address.bytes[2] = third_octet; + _address.bytes[3] = fourth_octet; } IPAddress::IPAddress(uint32_t address) { - _address.dword = address; + _address.dword = address; } -IPAddress::IPAddress(const uint8_t *address) +IPAddress::IPAddress(const uint8_t* address) { - memcpy(_address.bytes, address, sizeof(_address.bytes)); + memcpy(_address.bytes, address, sizeof(_address.bytes)); } -bool IPAddress::fromString(const char *address) +bool IPAddress::fromString(const char* address) { - // TODO: add support for "a", "a.b", "a.b.c" formats + // TODO: add support for "a", "a.b", "a.b.c" formats - uint16_t acc = 0; // Accumulator - uint8_t dots = 0; + uint16_t acc = 0; // Accumulator + uint8_t dots = 0; - while (*address) + while (*address) + { + char c = *address++; + if (c >= '0' && c <= '9') { - char c = *address++; - if (c >= '0' && c <= '9') - { - acc = acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return false; - } - } - else if (c == '.') - { - if (dots == 3) { - // Too much dots (there must be 3 dots) - return false; - } - _address.bytes[dots++] = acc; - acc = 0; - } - else - { - // Invalid char - return false; - } + acc = acc * 10 + (c - '0'); + if (acc > 255) + { + // Value out of [0..255] range + return false; + } } - - if (dots != 3) { - // Too few dots (there must be 3 dots) + else if (c == '.') + { + if (dots == 3) + { + // Too much dots (there must be 3 dots) return false; + } + _address.bytes[dots++] = acc; + acc = 0; } - _address.bytes[3] = acc; - return true; + else + { + // Invalid char + return false; + } + } + + if (dots != 3) + { + // Too few dots (there must be 3 dots) + return false; + } + _address.bytes[3] = acc; + return true; } -IPAddress& IPAddress::operator=(const uint8_t *address) +IPAddress& IPAddress::operator=(const uint8_t* address) { - memcpy(_address.bytes, address, sizeof(_address.bytes)); - return *this; + memcpy(_address.bytes, address, sizeof(_address.bytes)); + return *this; } IPAddress& IPAddress::operator=(uint32_t address) { - _address.dword = address; - return *this; + _address.dword = address; + return *this; } bool IPAddress::operator==(const uint8_t* addr) const { - return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; + return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0; } size_t IPAddress::printTo(Print& p) const { - size_t n = 0; - for (int i =0; i < 3; i++) - { - n += p.print(_address.bytes[i], DEC); - n += p.print('.'); - } - n += p.print(_address.bytes[3], DEC); - return n; + size_t n = 0; + for (int i = 0; i < 3; i++) + { + n += p.print(_address.bytes[i], DEC); + n += p.print('.'); + } + n += p.print(_address.bytes[3], DEC); + return n; } -const IPAddress INADDR_NONE(0,0,0,0); +const IPAddress INADDR_NONE(0, 0, 0, 0); diff --git a/megaavr/cores/coreX-corefiles/api/IPAddress.h b/megaavr/cores/coreX-corefiles/api/IPAddress.h index af33cf8..cb3bf27 100644 --- a/megaavr/cores/coreX-corefiles/api/IPAddress.h +++ b/megaavr/cores/coreX-corefiles/api/IPAddress.h @@ -20,57 +20,67 @@ #pragma once #include + #include "Printable.h" #include "String.h" +class EthernetClass; +class DhcpClass; +class DNSClient; + +namespace arduino { // A class to make it easier to handle and pass around IP addresses -class IPAddress : public Printable { -private: - union { - uint8_t bytes[4]; // IPv4 address - uint32_t dword; - } _address; - - // Access the raw byte array containing the address. Because this returns a pointer - // to the internal structure rather than a copy of the address this function should only - // be used when you know that the usage of the returned uint8_t* will be transient and not - // stored. - uint8_t* raw_address() { return _address.bytes; }; - -public: - // Constructors - IPAddress(); - IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); - IPAddress(uint32_t address); - IPAddress(const uint8_t *address); - - bool fromString(const char *address); - bool fromString(const String &address) { return fromString(address.c_str()); } - - // Overloaded cast operator to allow IPAddress objects to be used where a pointer - // to a four-byte uint8_t array is expected - operator uint32_t() const { return _address.dword; }; - bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; - bool operator==(const uint8_t* addr) const; - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { return _address.bytes[index]; }; - uint8_t& operator[](int index) { return _address.bytes[index]; }; - - // Overloaded copy operators to allow initialisation of IPAddress objects from other types - IPAddress& operator=(const uint8_t *address); - IPAddress& operator=(uint32_t address); - - virtual size_t printTo(Print& p) const; - - friend class EthernetClass; - friend class UDP; - friend class Client; - friend class Server; - friend class DhcpClass; - friend class DNSClient; +class IPAddress : public Printable +{ + private: + union { + uint8_t bytes[4]; // IPv4 address + uint32_t dword; + } _address; + + // Access the raw byte array containing the address. Because this returns a pointer + // to the internal structure rather than a copy of the address this function should only + // be used when you know that the usage of the returned uint8_t* will be transient and not + // stored. + uint8_t* raw_address() { return _address.bytes; }; + + public: + // Constructors + IPAddress(); + IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet); + IPAddress(uint32_t address); + IPAddress(const uint8_t* address); + + bool fromString(const char* address); + bool fromString(const String& address) { return fromString(address.c_str()); } + + // Overloaded cast operator to allow IPAddress objects to be used where a pointer + // to a four-byte uint8_t array is expected + operator uint32_t() const { return _address.dword; }; + bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; }; + bool operator==(const uint8_t* addr) const; + + // Overloaded index operator to allow getting and setting individual octets of the address + uint8_t operator[](int index) const { return _address.bytes[index]; }; + uint8_t& operator[](int index) { return _address.bytes[index]; }; + + // Overloaded copy operators to allow initialisation of IPAddress objects from other types + IPAddress& operator=(const uint8_t* address); + IPAddress& operator=(uint32_t address); + + virtual size_t printTo(Print& p) const; + + friend class UDP; + friend class Client; + friend class Server; + + friend ::EthernetClass; + friend ::DhcpClass; + friend ::DNSClient; }; -extern const IPAddress INADDR_NONE; +} +using arduino::IPAddress; +extern const IPAddress INADDR_NONE; diff --git a/megaavr/cores/coreX-corefiles/api/PluggableUSB.cpp b/megaavr/cores/coreX-corefiles/api/PluggableUSB.cpp index f0c45f0..0ef7364 100644 --- a/megaavr/cores/coreX-corefiles/api/PluggableUSB.cpp +++ b/megaavr/cores/coreX-corefiles/api/PluggableUSB.cpp @@ -17,83 +17,95 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "USBAPI.h" #include "PluggableUSB.h" +#include "USBAPI.h" + int PluggableUSB_::getInterface(uint8_t* interfaceCount) { - int sent = 0; - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - int res = node->getInterface(interfaceCount); - if (res < 0) - return -1; - sent += res; - } - return sent; + int sent = 0; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) + { + int res = node->getInterface(interfaceCount); + if (res < 0) + return -1; + sent += res; + } + return sent; } int PluggableUSB_::getDescriptor(USBSetup& setup) { - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - int ret = node->getDescriptor(setup); - // ret!=0 -> request has been processed - if (ret) - return ret; - } - return 0; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) + { + int ret = node->getDescriptor(setup); + // ret!=0 -> request has been processed + if (ret) + return ret; + } + return 0; } -void PluggableUSB_::getShortName(char *iSerialNum) +void PluggableUSB_::getShortName(char* iSerialNum) { - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - iSerialNum += node->getShortName(iSerialNum); - } - *iSerialNum = 0; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) + { + iSerialNum += node->getShortName(iSerialNum); + } + *iSerialNum = 0; } bool PluggableUSB_::setup(USBSetup& setup) { - PluggableUSBModule* node; - for (node = rootNode; node; node = node->next) { - if (node->setup(setup)) { - return true; - } - } - return false; + PluggableUSBModule* node; + for (node = rootNode; node; node = node->next) + { + if (node->setup(setup)) + { + return true; + } + } + return false; } -bool PluggableUSB_::plug(PluggableUSBModule *node) +bool PluggableUSB_::plug(PluggableUSBModule* node) { - if ((lastEp + node->numEndpoints) > totalEP) { - return false; - } + if ((lastEp + node->numEndpoints) > totalEP) + { + return false; + } - if (!rootNode) { - rootNode = node; - } else { - PluggableUSBModule *current = rootNode; - while (current->next) { - current = current->next; - } - current->next = node; - } + if (!rootNode) + { + rootNode = node; + } + else + { + PluggableUSBModule* current = rootNode; + while (current->next) + { + current = current->next; + } + current->next = node; + } - node->pluggedInterface = lastIf; - node->pluggedEndpoint = lastEp; - lastIf += node->numInterfaces; - for (uint8_t i = 0; i < node->numEndpoints; i++) { - *(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i]; - lastEp++; - } - return true; - // restart USB layer??? + node->pluggedInterface = lastIf; + node->pluggedEndpoint = lastEp; + lastIf += node->numInterfaces; + for (uint8_t i = 0; i < node->numEndpoints; i++) + { + *(unsigned int*)(epBuffer(lastEp)) = node->endpointType[i]; + lastEp++; + } + return true; + // restart USB layer??? } PluggableUSB_& PluggableUSB() { - static PluggableUSB_ obj; - return obj; -} \ No newline at end of file + static PluggableUSB_ obj; + return obj; +} diff --git a/megaavr/cores/coreX-corefiles/api/PluggableUSB.h b/megaavr/cores/coreX-corefiles/api/PluggableUSB.h index 09b5fed..1d8b760 100644 --- a/megaavr/cores/coreX-corefiles/api/PluggableUSB.h +++ b/megaavr/cores/coreX-corefiles/api/PluggableUSB.h @@ -20,47 +20,54 @@ #ifndef PUSB_h #define PUSB_h -#include "USBAPI.h" -#include #include +#include + +#include "USBAPI.h" // core need to define void* epBuffer(unsigned int n); // -> returns a poointer to the Nth element of the EP buffer structure -class PluggableUSBModule { -public: - PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int *epType) : - numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) - { } +class PluggableUSBModule +{ + public: + PluggableUSBModule(uint8_t numEps, uint8_t numIfs, unsigned int* epType) : numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) + { + } -protected: + protected: virtual bool setup(USBSetup& setup) = 0; virtual int getInterface(uint8_t* interfaceCount) = 0; virtual int getDescriptor(USBSetup& setup) = 0; - virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; } + virtual uint8_t getShortName(char* name) + { + name[0] = 'A' + pluggedInterface; + return 1; + } uint8_t pluggedInterface; uint8_t pluggedEndpoint; const uint8_t numEndpoints; const uint8_t numInterfaces; - const unsigned int *endpointType; + const unsigned int* endpointType; - PluggableUSBModule *next = NULL; + PluggableUSBModule* next = NULL; friend class PluggableUSB_; }; -class PluggableUSB_ { -public: +class PluggableUSB_ +{ + public: PluggableUSB_(); - bool plug(PluggableUSBModule *node); + bool plug(PluggableUSBModule* node); int getInterface(uint8_t* interfaceCount); int getDescriptor(USBSetup& setup); bool setup(USBSetup& setup); - void getShortName(char *iSerialNum); + void getShortName(char* iSerialNum); -private: + private: uint8_t lastIf; uint8_t lastEp; PluggableUSBModule* rootNode; @@ -72,4 +79,4 @@ class PluggableUSB_ { // https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use PluggableUSB_& PluggableUSB(); -#endif \ No newline at end of file +#endif diff --git a/megaavr/cores/coreX-corefiles/api/Print.cpp b/megaavr/cores/coreX-corefiles/api/Print.cpp index f23b5f2..feec47c 100644 --- a/megaavr/cores/coreX-corefiles/api/Print.cpp +++ b/megaavr/cores/coreX-corefiles/api/Print.cpp @@ -16,10 +16,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +#include #include +#include #include -#include #include "Print.h" @@ -29,9 +29,12 @@ size_t Print::write(const uint8_t *buffer, size_t size) { size_t n = 0; - while (size--) { - if (write(*buffer++)) n++; - else break; + while (size--) + { + if (write(*buffer++)) + n++; + else + break; } return n; } @@ -41,11 +44,14 @@ size_t Print::print(const __FlashStringHelper *ifsh) #if defined(__AVR__) PGM_P p = reinterpret_cast(ifsh); size_t n = 0; - while (1) { + while (1) + { unsigned char c = pgm_read_byte(p++); if (c == 0) break; - if (write(c)) n++; - else break; + if (write(c)) + n++; + else + break; } return n; #else @@ -70,39 +76,47 @@ size_t Print::print(char c) size_t Print::print(unsigned char b, int base) { - return print((unsigned long) b, base); + return print((unsigned long)b, base); } size_t Print::print(int n, int base) { - return print((long) n, base); + return print((long)n, base); } size_t Print::print(unsigned int n, int base) { - return print((unsigned long) n, base); + return print((unsigned long)n, base); } size_t Print::print(long n, int base) { - if (base == 0) { + if (base == 0) + { return write(n); - } else if (base == 10) { - if (n < 0) { + } + else if (base == 10) + { + if (n < 0) + { int t = print('-'); n = -n; return printNumber(n, 10) + t; } return printNumber(n, 10); - } else { + } + else + { return printNumber(n, base); } } size_t Print::print(unsigned long n, int base) { - if (base == 0) return write(n); - else return printNumber(n, base); + if (base == 0) + return write(n); + else + return printNumber(n, base); } size_t Print::print(double n, int digits) @@ -117,7 +131,7 @@ size_t Print::println(const __FlashStringHelper *ifsh) return n; } -size_t Print::print(const Printable& x) +size_t Print::print(const Printable &x) { return x.printTo(*this); } @@ -190,7 +204,7 @@ size_t Print::println(double num, int digits) return n; } -size_t Print::println(const Printable& x) +size_t Print::println(const Printable &x) { size_t n = print(x); n += println(); @@ -238,12 +252,13 @@ size_t Print::printNumber(unsigned long n, uint8_t base) // prevent crash if called with base == 1 if (base < 2) base = 10; - do { + do + { char c = n % base; n /= base; *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); + } while (n); return write(str); } @@ -254,19 +269,19 @@ size_t Print::printFloat(double number, uint8_t digits) if (isnan(number)) return print("nan"); if (isinf(number)) return print("inf"); - if (number > 4294967040.0) return print ("ovf"); // constant determined empirically - if (number <-4294967040.0) return print ("ovf"); // constant determined empirically + if (number > 4294967040.0) return print("ovf"); // constant determined empirically + if (number < -4294967040.0) return print("ovf"); // constant determined empirically // Handle negative numbers if (number < 0.0) { - n += print('-'); - number = -number; + n += print('-'); + number = -number; } // Round correctly so that print(1.999, 2) prints as "2.00" double rounding = 0.5; - for (uint8_t i=0; i 0) { + if (digits > 0) + { n += print("."); } diff --git a/megaavr/cores/coreX-corefiles/api/Print.h b/megaavr/cores/coreX-corefiles/api/Print.h index 9001cfb..f1498ef 100644 --- a/megaavr/cores/coreX-corefiles/api/Print.h +++ b/megaavr/cores/coreX-corefiles/api/Print.h @@ -53,6 +53,10 @@ class Print return write((const uint8_t *)buffer, size); } + // default to zero, meaning "a single write may block" + // should be overriden by subclasses with buffering + virtual int availableForWrite() { return 0; } + size_t print(const __FlashStringHelper *); size_t print(const String &); size_t print(const char[]); @@ -77,8 +81,9 @@ class Print size_t println(double, int = 2); size_t println(const Printable&); size_t println(void); - - int16_t printf(const char *format, ...); + + int16_t printf(const char *format, ...) __attribute__ ((format (printf, 2, 3))); int16_t printf(const __FlashStringHelper *format, ...); -}; + virtual void flush() { /* Empty implementation for backward compatibility */ } +}; diff --git a/megaavr/cores/coreX-corefiles/api/Printable.h b/megaavr/cores/coreX-corefiles/api/Printable.h index de45907..63f93d4 100644 --- a/megaavr/cores/coreX-corefiles/api/Printable.h +++ b/megaavr/cores/coreX-corefiles/api/Printable.h @@ -33,4 +33,3 @@ class Printable public: virtual size_t printTo(Print& p) const = 0; }; - diff --git a/megaavr/cores/coreX-corefiles/api/RingBuffer.cpp b/megaavr/cores/coreX-corefiles/api/RingBuffer.cpp index 90cfcbd..ed16b2c 100644 --- a/megaavr/cores/coreX-corefiles/api/RingBuffer.cpp +++ b/megaavr/cores/coreX-corefiles/api/RingBuffer.cpp @@ -17,66 +17,73 @@ */ #include "RingBuffer.h" -#include + #include #include +#include RingBuffer::RingBuffer(rb_index_type size) : size(size) { - _aucBuffer = (uint8_t*)malloc(size); - memset( _aucBuffer, 0, size ) ; - clear(); + _aucBuffer = (uint8_t*)malloc(size); + memset(_aucBuffer, 0, size); + clear(); } -void RingBuffer::store_char( uint8_t c ) +void RingBuffer::store_char(uint8_t c) { - rb_index_type i = nextIndex(_iHead); - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if ( i != _iTail ) + rb_index_type i = nextIndex(_iHead); + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + if (i != _iTail) + { + if (_iHead < size) { - if (_iHead < size) { - _aucBuffer[_iHead] = c ; - } else { - additionalBuffer[_iHead - size] = c; - } - _iHead = i ; + _aucBuffer[_iHead] = c; } + else + { + additionalBuffer[_iHead - size] = c; + } + _iHead = i; + } } void RingBuffer::clear() { - _iHead = 0; - _iTail = 0; + _iHead = 0; + _iTail = 0; } int RingBuffer::read_char() { - if(_iTail == _iHead) - return -1; - - uint8_t value; - if (_iTail < size) { - value = _aucBuffer[_iTail]; - } else { - value = additionalBuffer[_iTail - size]; - } - _iTail = nextIndex(_iTail); + if (_iTail == _iHead) + return -1; + + uint8_t value; + if (_iTail < size) + { + value = _aucBuffer[_iTail]; + } + else + { + value = additionalBuffer[_iTail - size]; + } + _iTail = nextIndex(_iTail); - return value; + return value; } int RingBuffer::available() { - int delta = _iHead - _iTail; + int delta = _iHead - _iTail; - if(delta < 0) - return size + additionalSize + delta; - else - return delta; + if (delta < 0) + return size + additionalSize + delta; + else + return delta; } int RingBuffer::availableForStore() @@ -88,25 +95,27 @@ int RingBuffer::availableForStore() return -delta - 1; } - int RingBuffer::peek() { - if(_iTail == _iHead) - return -1; + if (_iTail == _iHead) + return -1; - if (_iTail < size) { - return _aucBuffer[_iTail]; - } else { - return additionalBuffer[_iTail - size]; - } + if (_iTail < size) + { + return _aucBuffer[_iTail]; + } + else + { + return additionalBuffer[_iTail - size]; + } } rb_index_type RingBuffer::nextIndex(rb_index_type index) { - return (rb_index_type)(index + 1) % (size + additionalSize); + return (rb_index_type)(index + 1) % (size + additionalSize); } bool RingBuffer::isFull() { - return (nextIndex(_iHead) == _iTail); + return (nextIndex(_iHead) == _iTail); } diff --git a/megaavr/cores/coreX-corefiles/api/RingBuffer.h b/megaavr/cores/coreX-corefiles/api/RingBuffer.h index f7fc4a0..95c1baf 100644 --- a/megaavr/cores/coreX-corefiles/api/RingBuffer.h +++ b/megaavr/cores/coreX-corefiles/api/RingBuffer.h @@ -36,28 +36,29 @@ typedef unsigned int rb_index_type; class RingBuffer { - public: - RingBuffer( rb_index_type size = 64 ) ; - void store_char( uint8_t c ) ; - void clear(); - int read_char(); - int available(); - int availableForStore(); - int peek(); - bool isFull(); - void addStorage(uint8_t* _buffer, rb_index_type _size) { - additionalSize = _size; - additionalBuffer = _buffer; - }; - - private: - rb_index_type nextIndex(rb_index_type index); - uint8_t* additionalBuffer; - int additionalSize = 0; - rb_index_type size; - uint8_t* _aucBuffer; - volatile rb_index_type _iHead ; - volatile rb_index_type _iTail ; + public: + RingBuffer(rb_index_type size = 64); + void store_char(uint8_t c); + void clear(); + int read_char(); + int available(); + int availableForStore(); + int peek(); + bool isFull(); + void addStorage(uint8_t* _buffer, rb_index_type _size) + { + additionalSize = _size; + additionalBuffer = _buffer; + }; + + private: + rb_index_type nextIndex(rb_index_type index); + uint8_t* additionalBuffer; + int additionalSize = 0; + rb_index_type size; + uint8_t* _aucBuffer; + volatile rb_index_type _iHead; + volatile rb_index_type _iTail; }; #endif /* _RING_BUFFER_ */ diff --git a/megaavr/cores/coreX-corefiles/api/Server.h b/megaavr/cores/coreX-corefiles/api/Server.h index 8675682..fa4593c 100644 --- a/megaavr/cores/coreX-corefiles/api/Server.h +++ b/megaavr/cores/coreX-corefiles/api/Server.h @@ -21,8 +21,8 @@ #include "Print.h" -class Server : public Print { - public: - virtual void begin() = 0; +class Server : public Print +{ + public: + virtual void begin() = 0; }; - diff --git a/megaavr/cores/coreX-corefiles/api/Stream.cpp b/megaavr/cores/coreX-corefiles/api/Stream.cpp index c16d60f..287165e 100644 --- a/megaavr/cores/coreX-corefiles/api/Stream.cpp +++ b/megaavr/cores/coreX-corefiles/api/Stream.cpp @@ -25,18 +25,19 @@ #include "Common.h" #include "Stream.h" -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait +#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait // private method to read stream with timeout int Stream::timedRead() { int c; _startMillis = millis(); - do { + do + { c = read(); if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + } while (millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // private method to peek stream with timeout @@ -44,11 +45,12 @@ int Stream::timedPeek() { int c; _startMillis = millis(); - do { + do + { c = peek(); if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout + } while (millis() - _startMillis < _timeout); + return -1; // -1 indicates timeout } // returns peek of the next digit in the stream or -1 if timeout @@ -56,41 +58,47 @@ int Stream::timedPeek() int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal) { int c; - while (1) { + while (1) + { c = timedPeek(); - if( c < 0 || + if (c < 0 || c == '-' || (c >= '0' && c <= '9') || (detectDecimal && c == '.')) return c; - switch( lookahead ){ - case SKIP_NONE: return -1; // Fail code. - case SKIP_WHITESPACE: - switch( c ){ - case ' ': - case '\t': - case '\r': - case '\n': break; - default: return -1; // Fail code. - } - case SKIP_ALL: + switch (lookahead) + { + case SKIP_NONE: + return -1; // Fail code. + case SKIP_WHITESPACE: + switch (c) + { + case ' ': + case '\t': + case '\r': + case '\n': break; + default: + return -1; // Fail code. + } + case SKIP_ALL: + break; } - read(); // discard non-numeric + read(); // discard non-numeric } } // Public Methods ////////////////////////////////////////////////////////////// -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait +void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait { _timeout = timeout; } - // find returns true if the target string is found -bool Stream::find(char *target) +// find returns true if the target string is found +bool Stream::find(char *target) { return findUntil(target, strlen(target), NULL, 0); } @@ -103,7 +111,7 @@ bool Stream::find(char *target, size_t length) } // as find but search ends if the terminator string is found -bool Stream::findUntil(char *target, char *terminator) +bool Stream::findUntil(char *target, char *terminator) { return findUntil(target, strlen(target), terminator, strlen(terminator)); } @@ -113,10 +121,13 @@ bool Stream::findUntil(char *target, char *terminator) // returns true if target string is found, false if terminated or timed out bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) { - if (terminator == NULL) { + if (terminator == NULL) + { MultiTarget t[1] = {{target, targetLen, 0}}; return findMulti(t, 1) == 0 ? true : false; - } else { + } + else + { MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; return findMulti(t, 2) == 0 ? true : false; } @@ -135,22 +146,22 @@ long Stream::parseInt(LookaheadMode lookahead, char ignore) c = peekNextDigit(lookahead, false); // ignore non numeric leading characters - if(c < 0) + if (c < 0) return 0; // zero returned if timeout - do{ - if(c == ignore) + do + { + if (c == ignore) ; // ignore this character - else if(c == '-') + else if (c == '-') isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? + else if (c >= '0' && c <= '9') // is c a digit? value = value * 10 + c - '0'; - read(); // consume the character we got with peek + read(); // consume the character we got with peek c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == ignore ); + } while ((c >= '0' && c <= '9') || c == ignore); - if(isNegative) + if (isNegative) value = -value; return value; } @@ -165,30 +176,31 @@ float Stream::parseFloat(LookaheadMode lookahead, char ignore) float fraction = 1.0; c = peekNextDigit(lookahead, true); - // ignore non numeric leading characters - if(c < 0) + // ignore non numeric leading characters + if (c < 0) return 0; // zero returned if timeout - do{ - if(c == ignore) + do + { + if (c == ignore) ; // ignore - else if(c == '-') + else if (c == '-') isNegative = true; else if (c == '.') isFraction = true; - else if(c >= '0' && c <= '9') { // is c a digit? + else if (c >= '0' && c <= '9') + { // is c a digit? value = value * 10 + c - '0'; - if(isFraction) - fraction *= 0.1; + if (isFraction) + fraction *= 0.1; } - read(); // consume the character we got with peek + read(); // consume the character we got with peek c = timedPeek(); - } - while( (c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore ); + } while ((c >= '0' && c <= '9') || (c == '.' && !isFraction) || c == ignore); - if(isNegative) + if (isNegative) value = -value; - if(isFraction) + if (isFraction) return value * fraction; else return value; @@ -202,7 +214,8 @@ float Stream::parseFloat(LookaheadMode lookahead, char ignore) size_t Stream::readBytes(char *buffer, size_t length) { size_t count = 0; - while (count < length) { + while (count < length) + { int c = timedRead(); if (c < 0) break; *buffer++ = (char)c; @@ -211,7 +224,6 @@ size_t Stream::readBytes(char *buffer, size_t length) return count; } - // as readBytes with terminator character // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) @@ -220,7 +232,8 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) { if (length < 1) return 0; size_t index = 0; - while (index < length) { + while (index < length) + { int c = timedRead(); if (c < 0 || c == terminator) break; *buffer++ = (char)c; @@ -253,22 +266,27 @@ String Stream::readStringUntil(char terminator) return ret; } -int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { +int Stream::findMulti(struct Stream::MultiTarget *targets, int tCount) +{ // any zero length target string automatically matches and would make // a mess of the rest of the algorithm. - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + for (struct MultiTarget *t = targets; t < targets + tCount; ++t) + { if (t->len <= 0) return t - targets; } - while (1) { + while (1) + { int c = timedRead(); if (c < 0) return -1; - for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + for (struct MultiTarget *t = targets; t < targets + tCount; ++t) + { // the simple case is if we match, deal with that first. - if (c == t->str[t->index]) { + if (c == t->str[t->index]) + { if (++t->index == t->len) return t - targets; else @@ -283,14 +301,16 @@ int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { continue; int origIndex = t->index; - do { + do + { --t->index; // first check if current char works against the new current index if (c != t->str[t->index]) continue; // if it's the only char then we're good, nothing more to check - if (t->index == 0) { + if (t->index == 0) + { t->index++; break; } @@ -298,14 +318,16 @@ int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { // otherwise we need to check the rest of the found string int diff = origIndex - t->index; size_t i; - for (i = 0; i < t->index; ++i) { + for (i = 0; i < t->index; ++i) + { if (t->str[i] != t->str[i + diff]) break; } // if we successfully got through the previous loop then our current // index is good. - if (i == t->index) { + if (i == t->index) + { t->index++; break; } diff --git a/megaavr/cores/coreX-corefiles/api/Stream.h b/megaavr/cores/coreX-corefiles/api/Stream.h index 7dbe2fd..dd0645e 100644 --- a/megaavr/cores/coreX-corefiles/api/Stream.h +++ b/megaavr/cores/coreX-corefiles/api/Stream.h @@ -22,6 +22,7 @@ #pragma once #include + #include "Print.h" // compatability macros for testing @@ -37,51 +38,51 @@ readBytesBetween( pre_string, terminator, buffer, length) // This enumeration provides the lookahead options for parseInt(), parseFloat() // The rules set out here are used until either the first valid character is found // or a time out occurs due to lack of input. -enum LookaheadMode{ - SKIP_ALL, // All invalid characters are ignored. - SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. - SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +enum LookaheadMode +{ + SKIP_ALL, // All invalid characters are ignored. + SKIP_NONE, // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. + SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. }; -#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field +#define NO_IGNORE_CHAR '\x01' // a char not found in a valid ASCII numeric field class Stream : public Print { - protected: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout + protected: + unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read + unsigned long _startMillis; // used for timeout measurement + int timedRead(); // private method to read stream with timeout + int timedPeek(); // private method to peek stream with timeout + int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - virtual void flush() = 0; + public: + virtual int available() = 0; + virtual int read() = 0; + virtual int peek() = 0; - Stream() {_timeout=1000;} + Stream() { _timeout = 1000; } -// parsing methods + // parsing methods - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second + void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second unsigned long getTimeout(void) { return _timeout; } - - bool find(char *target); // reads data from the stream until the target string is found - bool find(uint8_t *target) { return find ((char *)target); } + + bool find(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find((char *)target); } // returns true if target string is found, false if timed out (see setTimeout) - bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found - bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find((char *)target, length); } // returns true if target string is found, false if timed out - bool find(char target) { return find (&target, 1); } + bool find(char target) { return find(&target, 1); } - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) { return findUntil((char *)target, targetLen, terminate, termLen); } long parseInt(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // returns the first valid (long) integer value from the current position. @@ -93,13 +94,13 @@ class Stream : public Print float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); // float version of parseInt - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } + size_t readBytes(char *buffer, size_t length); // read chars from stream into buffer + size_t readBytes(uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); } // terminates if length characters have been read or timeout (see setTimeout) // returns the number of characters placed in the buffer (0 means no valid data found) - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } + size_t readBytesUntil(char terminator, char *buffer, size_t length); // as readBytes with terminator character + size_t readBytesUntil(char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); } // terminates if length characters have been read, timeout, or if the terminator character detected // returns the number of characters placed in the buffer (0 means no valid data found) @@ -107,17 +108,18 @@ class Stream : public Print String readString(); String readStringUntil(char terminator); - protected: + protected: long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } // These overload exists for compatibility with any class that has derived // Stream and used parseFloat/Int with a custom ignore character. To keep // the public API simple, these overload remains protected. - struct MultiTarget { - const char *str; // string you're searching for - size_t len; // length of string you're searching for - size_t index; // index used by the search routine. + struct MultiTarget + { + const char *str; // string you're searching for + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. }; // This allows you to search for an arbitrary number of strings. diff --git a/megaavr/cores/coreX-corefiles/api/String.cpp b/megaavr/cores/coreX-corefiles/api/String.cpp index 5a5d710..6efc5f0 100644 --- a/megaavr/cores/coreX-corefiles/api/String.cpp +++ b/megaavr/cores/coreX-corefiles/api/String.cpp @@ -29,101 +29,101 @@ String::String(const char *cstr) { - init(); - if (cstr) copy(cstr, strlen(cstr)); + init(); + if (cstr) copy(cstr, strlen(cstr)); } String::String(const String &value) { - init(); - *this = value; + init(); + *this = value; } String::String(const __FlashStringHelper *pstr) { - init(); - *this = pstr; + init(); + *this = pstr; } #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) String::String(String &&rval) { - init(); - move(rval); + init(); + move(rval); } String::String(StringSumHelper &&rval) { - init(); - move(rval); + init(); + move(rval); } #endif String::String(char c) { - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; + init(); + char buf[2]; + buf[0] = c; + buf[1] = 0; + *this = buf; } String::String(unsigned char value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned char)]; - utoa(value, buf, base); - *this = buf; + init(); + char buf[1 + 8 * sizeof(unsigned char)]; + utoa(value, buf, base); + *this = buf; } String::String(int value, unsigned char base) { - init(); - char buf[2 + 8 * sizeof(int)]; - itoa(value, buf, base); - *this = buf; + init(); + char buf[2 + 8 * sizeof(int)]; + itoa(value, buf, base); + *this = buf; } String::String(unsigned int value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned int)]; - utoa(value, buf, base); - *this = buf; + init(); + char buf[1 + 8 * sizeof(unsigned int)]; + utoa(value, buf, base); + *this = buf; } String::String(long value, unsigned char base) { - init(); - char buf[2 + 8 * sizeof(long)]; - ltoa(value, buf, base); - *this = buf; + init(); + char buf[2 + 8 * sizeof(long)]; + ltoa(value, buf, base); + *this = buf; } String::String(unsigned long value, unsigned char base) { - init(); - char buf[1 + 8 * sizeof(unsigned long)]; - ultoa(value, buf, base); - *this = buf; + init(); + char buf[1 + 8 * sizeof(unsigned long)]; + ultoa(value, buf, base); + *this = buf; } String::String(float value, unsigned char decimalPlaces) { - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } String::String(double value, unsigned char decimalPlaces) { - init(); - char buf[33]; - *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); + init(); + char buf[33]; + *this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf); } String::~String() { - free(buffer); + free(buffer); } /*********************************************/ @@ -132,125 +132,139 @@ String::~String() inline void String::init(void) { - buffer = NULL; - capacity = 0; - len = 0; + buffer = NULL; + capacity = 0; + len = 0; } void String::invalidate(void) { - if (buffer) free(buffer); - buffer = NULL; - capacity = len = 0; + if (buffer) free(buffer); + buffer = NULL; + capacity = len = 0; } unsigned char String::reserve(unsigned int size) { - if (buffer && capacity >= size) return 1; - if (changeBuffer(size)) { - if (len == 0) buffer[0] = 0; - return 1; - } - return 0; + if (buffer && capacity >= size) return 1; + if (changeBuffer(size)) + { + if (len == 0) buffer[0] = 0; + return 1; + } + return 0; } unsigned char String::changeBuffer(unsigned int maxStrLen) { - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); - if (newbuffer) { - buffer = newbuffer; - capacity = maxStrLen; - return 1; - } - return 0; + char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); + if (newbuffer) + { + buffer = newbuffer; + capacity = maxStrLen; + return 1; + } + return 0; } /*********************************************/ /* Copy and Move */ /*********************************************/ -String & String::copy(const char *cstr, unsigned int length) +String &String::copy(const char *cstr, unsigned int length) { - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; + if (!reserve(length)) + { + invalidate(); + return *this; + } + len = length; + strcpy(buffer, cstr); + return *this; } -String & String::copy(const __FlashStringHelper *pstr, unsigned int length) +String &String::copy(const __FlashStringHelper *pstr, unsigned int length) { - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy_P(buffer, (PGM_P)pstr); - return *this; + if (!reserve(length)) + { + invalidate(); + return *this; + } + len = length; + strcpy_P(buffer, (PGM_P)pstr); + return *this; } #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) void String::move(String &rhs) { - if (buffer) { - if (rhs && capacity >= rhs.len) { - strcpy(buffer, rhs.buffer); - len = rhs.len; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; + if (buffer) + { + if (rhs && capacity >= rhs.len) + { + strcpy(buffer, rhs.buffer); + len = rhs.len; + rhs.len = 0; + return; + } + else + { + free(buffer); + } + } + buffer = rhs.buffer; + capacity = rhs.capacity; + len = rhs.len; + rhs.buffer = NULL; + rhs.capacity = 0; + rhs.len = 0; } #endif -String & String::operator = (const String &rhs) +String &String::operator=(const String &rhs) { - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; + if (this == &rhs) return *this; + + if (rhs.buffer) + copy(rhs.buffer, rhs.len); + else + invalidate(); + + return *this; } #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -String & String::operator = (String &&rval) +String &String::operator=(String &&rval) { - if (this != &rval) move(rval); - return *this; + if (this != &rval) move(rval); + return *this; } -String & String::operator = (StringSumHelper &&rval) +String &String::operator=(StringSumHelper &&rval) { - if (this != &rval) move(rval); - return *this; + if (this != &rval) move(rval); + return *this; } #endif -String & String::operator = (const char *cstr) +String &String::operator=(const char *cstr) { - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; + if (cstr) + copy(cstr, strlen(cstr)); + else + invalidate(); + + return *this; } -String & String::operator = (const __FlashStringHelper *pstr) +String &String::operator=(const __FlashStringHelper *pstr) { - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - else invalidate(); + if (pstr) + copy(pstr, strlen_P((PGM_P)pstr)); + else + invalidate(); - return *this; + return *this; } /*********************************************/ @@ -259,174 +273,174 @@ String & String::operator = (const __FlashStringHelper *pstr) unsigned char String::concat(const String &s) { - return concat(s.buffer, s.len); + return concat(s.buffer, s.len); } unsigned char String::concat(const char *cstr, unsigned int length) { - unsigned int newlen = len + length; - if (!cstr) return 0; - if (length == 0) return 1; - if (!reserve(newlen)) return 0; - strcpy(buffer + len, cstr); - len = newlen; - return 1; + unsigned int newlen = len + length; + if (!cstr) return 0; + if (length == 0) return 1; + if (!reserve(newlen)) return 0; + strcpy(buffer + len, cstr); + len = newlen; + return 1; } unsigned char String::concat(const char *cstr) { - if (!cstr) return 0; - return concat(cstr, strlen(cstr)); + if (!cstr) return 0; + return concat(cstr, strlen(cstr)); } unsigned char String::concat(char c) { - char buf[2]; - buf[0] = c; - buf[1] = 0; - return concat(buf, 1); + char buf[2]; + buf[0] = c; + buf[1] = 0; + return concat(buf, 1); } unsigned char String::concat(unsigned char num) { - char buf[1 + 3 * sizeof(unsigned char)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); + char buf[1 + 3 * sizeof(unsigned char)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); } unsigned char String::concat(int num) { - char buf[2 + 3 * sizeof(int)]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); + char buf[2 + 3 * sizeof(int)]; + itoa(num, buf, 10); + return concat(buf, strlen(buf)); } unsigned char String::concat(unsigned int num) { - char buf[1 + 3 * sizeof(unsigned int)]; - utoa(num, buf, 10); - return concat(buf, strlen(buf)); + char buf[1 + 3 * sizeof(unsigned int)]; + utoa(num, buf, 10); + return concat(buf, strlen(buf)); } unsigned char String::concat(long num) { - char buf[2 + 3 * sizeof(long)]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); + char buf[2 + 3 * sizeof(long)]; + ltoa(num, buf, 10); + return concat(buf, strlen(buf)); } unsigned char String::concat(unsigned long num) { - char buf[1 + 3 * sizeof(unsigned long)]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); + char buf[1 + 3 * sizeof(unsigned long)]; + ultoa(num, buf, 10); + return concat(buf, strlen(buf)); } unsigned char String::concat(float num) { - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); + char buf[20]; + char *string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); } unsigned char String::concat(double num) { - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); + char buf[20]; + char *string = dtostrf(num, 4, 2, buf); + return concat(string, strlen(string)); } -unsigned char String::concat(const __FlashStringHelper * str) +unsigned char String::concat(const __FlashStringHelper *str) { - if (!str) return 0; - int length = strlen_P((const char *) str); - if (length == 0) return 1; - unsigned int newlen = len + length; - if (!reserve(newlen)) return 0; - strcpy_P(buffer + len, (const char *) str); - len = newlen; - return 1; + if (!str) return 0; + int length = strlen_P((const char *)str); + if (length == 0) return 1; + unsigned int newlen = len + length; + if (!reserve(newlen)) return 0; + strcpy_P(buffer + len, (const char *)str); + len = newlen; + return 1; } /*********************************************/ /* Concatenate */ /*********************************************/ -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) +StringSumHelper &operator+(const StringSumHelper &lhs, const String &rhs) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) +StringSumHelper &operator+(const StringSumHelper &lhs, const char *cstr) { - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, char c) +StringSumHelper &operator+(const StringSumHelper &lhs, char c) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(c)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) +StringSumHelper &operator+(const StringSumHelper &lhs, unsigned char num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, int num) +StringSumHelper &operator+(const StringSumHelper &lhs, int num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) +StringSumHelper &operator+(const StringSumHelper &lhs, unsigned int num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, long num) +StringSumHelper &operator+(const StringSumHelper &lhs, long num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) +StringSumHelper &operator+(const StringSumHelper &lhs, unsigned long num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, float num) +StringSumHelper &operator+(const StringSumHelper &lhs, float num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, double num) +StringSumHelper &operator+(const StringSumHelper &lhs, double num) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(num)) a.invalidate(); + return a; } -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) +StringSumHelper &operator+(const StringSumHelper &lhs, const __FlashStringHelper *rhs) { - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) a.invalidate(); - return a; + StringSumHelper &a = const_cast(lhs); + if (!a.concat(rhs)) a.invalidate(); + return a; } /*********************************************/ @@ -435,75 +449,77 @@ StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHel int String::compareTo(const String &s) const { - if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, s.buffer); + if (!buffer || !s.buffer) + { + if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; + if (buffer && len > 0) return *(unsigned char *)buffer; + return 0; + } + return strcmp(buffer, s.buffer); } unsigned char String::equals(const String &s2) const { - return (len == s2.len && compareTo(s2) == 0); + return (len == s2.len && compareTo(s2) == 0); } unsigned char String::equals(const char *cstr) const { - if (len == 0) return (cstr == NULL || *cstr == 0); - if (cstr == NULL) return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; + if (len == 0) return (cstr == NULL || *cstr == 0); + if (cstr == NULL) return buffer[0] == 0; + return strcmp(buffer, cstr) == 0; } unsigned char String::operator<(const String &rhs) const { - return compareTo(rhs) < 0; + return compareTo(rhs) < 0; } unsigned char String::operator>(const String &rhs) const { - return compareTo(rhs) > 0; + return compareTo(rhs) > 0; } unsigned char String::operator<=(const String &rhs) const { - return compareTo(rhs) <= 0; + return compareTo(rhs) <= 0; } unsigned char String::operator>=(const String &rhs) const { - return compareTo(rhs) >= 0; + return compareTo(rhs) >= 0; } -unsigned char String::equalsIgnoreCase( const String &s2 ) const +unsigned char String::equalsIgnoreCase(const String &s2) const { - if (this == &s2) return 1; - if (len != s2.len) return 0; - if (len == 0) return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while (*p1) { - if (tolower(*p1++) != tolower(*p2++)) return 0; - } - return 1; + if (this == &s2) return 1; + if (len != s2.len) return 0; + if (len == 0) return 1; + const char *p1 = buffer; + const char *p2 = s2.buffer; + while (*p1) + { + if (tolower(*p1++) != tolower(*p2++)) return 0; + } + return 1; } -unsigned char String::startsWith( const String &s2 ) const +unsigned char String::startsWith(const String &s2) const { - if (len < s2.len) return 0; - return startsWith(s2, 0); + if (len < s2.len) return 0; + return startsWith(s2, 0); } -unsigned char String::startsWith( const String &s2, unsigned int offset ) const +unsigned char String::startsWith(const String &s2, unsigned int offset) const { - if (offset > len - s2.len || !buffer || !s2.buffer) return 0; - return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; + if (offset > len - s2.len || !buffer || !s2.buffer) return 0; + return strncmp(&buffer[offset], s2.buffer, s2.len) == 0; } -unsigned char String::endsWith( const String &s2 ) const +unsigned char String::endsWith(const String &s2) const { - if ( len < s2.len || !buffer || !s2.buffer) return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; + if (len < s2.len || !buffer || !s2.buffer) return 0; + return strcmp(&buffer[len - s2.len], s2.buffer) == 0; } /*********************************************/ @@ -512,41 +528,43 @@ unsigned char String::endsWith( const String &s2 ) const char String::charAt(unsigned int loc) const { - return operator[](loc); + return operator[](loc); } -void String::setCharAt(unsigned int loc, char c) +void String::setCharAt(unsigned int loc, char c) { - if (loc < len) buffer[loc] = c; + if (loc < len) buffer[loc] = c; } -char & String::operator[](unsigned int index) +char &String::operator[](unsigned int index) { - static char dummy_writable_char; - if (index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; + static char dummy_writable_char; + if (index >= len || !buffer) + { + dummy_writable_char = 0; + return dummy_writable_char; + } + return buffer[index]; } -char String::operator[]( unsigned int index ) const +char String::operator[](unsigned int index) const { - if (index >= len || !buffer) return 0; - return buffer[index]; + if (index >= len || !buffer) return 0; + return buffer[index]; } void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const { - if (!bufsize || !buf) return; - if (index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); - buf[n] = 0; + if (!bufsize || !buf) return; + if (index >= len) + { + buf[0] = 0; + return; + } + unsigned int n = bufsize - 1; + if (n > len - index) n = len - index; + strncpy((char *)buf, buffer + index, n); + buf[n] = 0; } /*********************************************/ @@ -555,79 +573,81 @@ void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int ind int String::indexOf(char c) const { - return indexOf(c, 0); + return indexOf(c, 0); } -int String::indexOf( char ch, unsigned int fromIndex ) const +int String::indexOf(char ch, unsigned int fromIndex) const { - if (fromIndex >= len) return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if (temp == NULL) return -1; - return temp - buffer; + if (fromIndex >= len) return -1; + const char *temp = strchr(buffer + fromIndex, ch); + if (temp == NULL) return -1; + return temp - buffer; } int String::indexOf(const String &s2) const { - return indexOf(s2, 0); + return indexOf(s2, 0); } int String::indexOf(const String &s2, unsigned int fromIndex) const { - if (fromIndex >= len) return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if (found == NULL) return -1; - return found - buffer; + if (fromIndex >= len) return -1; + const char *found = strstr(buffer + fromIndex, s2.buffer); + if (found == NULL) return -1; + return found - buffer; } -int String::lastIndexOf( char theChar ) const +int String::lastIndexOf(char theChar) const { - return lastIndexOf(theChar, len - 1); + return lastIndexOf(theChar, len - 1); } int String::lastIndexOf(char ch, unsigned int fromIndex) const { - if (fromIndex >= len) return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( buffer, ch ); - buffer[fromIndex + 1] = tempchar; - if (temp == NULL) return -1; - return temp - buffer; + if (fromIndex >= len) return -1; + char tempchar = buffer[fromIndex + 1]; + buffer[fromIndex + 1] = '\0'; + char *temp = strrchr(buffer, ch); + buffer[fromIndex + 1] = tempchar; + if (temp == NULL) return -1; + return temp - buffer; } int String::lastIndexOf(const String &s2) const { - return lastIndexOf(s2, len - s2.len); + return lastIndexOf(s2, len - s2.len); } int String::lastIndexOf(const String &s2, unsigned int fromIndex) const { - if (s2.len == 0 || len == 0 || s2.len > len) return -1; - if (fromIndex >= len) fromIndex = len - 1; - int found = -1; - for (char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; - } - return found; + if (s2.len == 0 || len == 0 || s2.len > len) return -1; + if (fromIndex >= len) fromIndex = len - 1; + int found = -1; + for (char *p = buffer; p <= buffer + fromIndex; p++) + { + p = strstr(p, s2.buffer); + if (!p) break; + if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; + } + return found; } String String::substring(unsigned int left, unsigned int right) const { - if (left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if (left >= len) return out; - if (right > len) right = len; - char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; - out = buffer + left; // pointer arithmetic - buffer[right] = temp; //restore character - return out; + if (left > right) + { + unsigned int temp = right; + right = left; + left = temp; + } + String out; + if (left >= len) return out; + if (right > len) right = len; + char temp = buffer[right]; // save the replaced character + buffer[right] = '\0'; + out = buffer + left; // pointer arithmetic + buffer[right] = temp; //restore character + return out; } /*********************************************/ @@ -636,98 +656,121 @@ String String::substring(unsigned int left, unsigned int right) const void String::replace(char find, char replace) { - if (!buffer) return; - for (char *p = buffer; *p; p++) { - if (*p == find) *p = replace; - } -} - -void String::replace(const String& find, const String& replace) -{ - if (len == 0 || find.len == 0) return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if (diff == 0) { - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if (diff < 0) { - char *writeTo = buffer; - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - unsigned int n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); - writeTo += n; - memcpy(writeTo, replace.buffer, replace.len); - writeTo += replace.len; - readFrom = foundAt + find.len; - len += diff; - } - strcpy(writeTo, readFrom); - } else { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if (size == len) return; - if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } -} - -void String::remove(unsigned int index){ - // Pass the biggest integer as the count. The remove method - // below will take care of truncating it at the end of the - // string. - remove(index, (unsigned int)-1); -} - -void String::remove(unsigned int index, unsigned int count){ - if (index >= len) { return; } - if (count <= 0) { return; } - if (count > len - index) { count = len - index; } - char *writeTo = buffer + index; - len = len - count; - strncpy(writeTo, buffer + index + count,len - index); - buffer[len] = 0; + if (!buffer) return; + for (char *p = buffer; *p; p++) + { + if (*p == find) *p = replace; + } +} + +void String::replace(const String &find, const String &replace) +{ + if (len == 0 || find.len == 0) return; + int diff = replace.len - find.len; + char *readFrom = buffer; + char *foundAt; + if (diff == 0) + { + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) + { + memcpy(foundAt, replace.buffer, replace.len); + readFrom = foundAt + replace.len; + } + } + else if (diff < 0) + { + char *writeTo = buffer; + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) + { + unsigned int n = foundAt - readFrom; + memcpy(writeTo, readFrom, n); + writeTo += n; + memcpy(writeTo, replace.buffer, replace.len); + writeTo += replace.len; + readFrom = foundAt + find.len; + len += diff; + } + strcpy(writeTo, readFrom); + } + else + { + unsigned int size = len; // compute size needed for result + while ((foundAt = strstr(readFrom, find.buffer)) != NULL) + { + readFrom = foundAt + find.len; + size += diff; + } + if (size == len) return; + if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! + int index = len - 1; + while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) + { + readFrom = buffer + index + find.len; + memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); + len += diff; + buffer[len] = 0; + memcpy(buffer + index, replace.buffer, replace.len); + index--; + } + } +} + +void String::remove(unsigned int index) +{ + // Pass the biggest integer as the count. The remove method + // below will take care of truncating it at the end of the + // string. + remove(index, (unsigned int)-1); +} + +void String::remove(unsigned int index, unsigned int count) +{ + if (index >= len) + { + return; + } + if (count <= 0) + { + return; + } + if (count > len - index) + { + count = len - index; + } + char *writeTo = buffer + index; + len = len - count; + strncpy(writeTo, buffer + index + count, len - index); + buffer[len] = 0; } void String::toLowerCase(void) { - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = tolower(*p); - } + if (!buffer) return; + for (char *p = buffer; *p; p++) + { + *p = tolower(*p); + } } void String::toUpperCase(void) { - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = toupper(*p); - } + if (!buffer) return; + for (char *p = buffer; *p; p++) + { + *p = toupper(*p); + } } void String::trim(void) { - if (!buffer || len == 0) return; - char *begin = buffer; - while (isspace(*begin)) begin++; - char *end = buffer + len - 1; - while (isspace(*end) && end >= begin) end--; - len = end + 1 - begin; - if (begin > buffer) memcpy(buffer, begin, len); - buffer[len] = 0; + if (!buffer || len == 0) return; + char *begin = buffer; + while (isspace(*begin)) begin++; + char *end = buffer + len - 1; + while (isspace(*end) && end >= begin) end--; + len = end + 1 - begin; + if (begin > buffer) memcpy(buffer, begin, len); + buffer[len] = 0; } /*********************************************/ @@ -736,17 +779,17 @@ void String::trim(void) long String::toInt(void) const { - if (buffer) return atol(buffer); - return 0; + if (buffer) return atol(buffer); + return 0; } float String::toFloat(void) const { - return float(toDouble()); + return float(toDouble()); } double String::toDouble(void) const { - if (buffer) return atof(buffer); - return 0; + if (buffer) return atof(buffer); + return 0; } diff --git a/megaavr/cores/coreX-corefiles/api/String.h b/megaavr/cores/coreX-corefiles/api/String.h index f2c6dd9..db5230e 100644 --- a/megaavr/cores/coreX-corefiles/api/String.h +++ b/megaavr/cores/coreX-corefiles/api/String.h @@ -48,185 +48,231 @@ class StringSumHelper; // The string class class String { - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const {} - -public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const String &str); - String(const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String(String &&rval); - String(StringSumHelper &&rval); - #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base=10); - explicit String(int, unsigned char base=10); - explicit String(unsigned int, unsigned char base=10); - explicit String(long, unsigned char base=10); - explicit String(unsigned long, unsigned char base=10); - explicit String(float, unsigned char decimalPlaces=2); - explicit String(double, unsigned char decimalPlaces=2); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const {return len;} - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator = (const String &rhs); - String & operator = (const char *cstr); - String & operator = (const __FlashStringHelper *str); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - String & operator = (String &&rval); - String & operator = (StringSumHelper &&rval); - #endif - - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(char c); - unsigned char concat(unsigned char c); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - unsigned char concat(float num); - unsigned char concat(double num); - unsigned char concat(const __FlashStringHelper * str); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator += (const String &rhs) {concat(rhs); return (*this);} - String & operator += (const char *cstr) {concat(cstr); return (*this);} - String & operator += (char c) {concat(c); return (*this);} - String & operator += (unsigned char num) {concat(num); return (*this);} - String & operator += (int num) {concat(num); return (*this);} - String & operator += (unsigned int num) {concat(num); return (*this);} - String & operator += (long num) {concat(num); return (*this);} - String & operator += (unsigned long num) {concat(num); return (*this);} - String & operator += (float num) {concat(num); return (*this);} - String & operator += (double num) {concat(num); return (*this);} - String & operator += (const __FlashStringHelper *str){concat(str); return (*this);} - - friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, float num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, double num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } - int compareTo(const String &s) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - unsigned char operator == (const String &rhs) const {return equals(rhs);} - unsigned char operator == (const char *cstr) const {return equals(cstr);} - unsigned char operator != (const String &rhs) const {return !equals(rhs);} - unsigned char operator != (const char *cstr) const {return !equals(cstr);} - unsigned char operator < (const String &rhs) const; - unsigned char operator > (const String &rhs) const; - unsigned char operator <= (const String &rhs) const; - unsigned char operator >= (const String &rhs) const; - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char startsWith( const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [] (unsigned int index) const; - char& operator [] (unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const - { getBytes((unsigned char *)buf, bufsize, index); } - const char* c_str() const { return buffer; } - char* begin() { return buffer; } - char* end() { return buffer + length(); } - const char* begin() const { return c_str(); } - const char* end() const { return c_str() + length(); } - - // search - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); }; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void remove(unsigned int index); - void remove(unsigned int index, unsigned int count); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - float toFloat(void) const; - double toDouble(void) const; - -protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') -protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - unsigned char concat(const char *cstr, unsigned int length); - - // copy and move - String & copy(const char *cstr, unsigned int length); - String & copy(const __FlashStringHelper *pstr, unsigned int length); - #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - void move(String &rhs); - #endif + // use a function pointer to allow for "if (s)" without the + // complications of an operator bool(). for more information, see: + // http://www.artima.com/cppsource/safebool.html + typedef void (String::*StringIfHelperType)() const; + void StringIfHelper() const {} + + public: + // constructors + // creates a copy of the initial value. + // if the initial value is null or invalid, or if memory allocation + // fails, the string will be marked as invalid (i.e. "if (s)" will + // be false). + String(const char *cstr = ""); + String(const String &str); + String(const __FlashStringHelper *str); +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String(String &&rval); + String(StringSumHelper &&rval); +#endif + explicit String(char c); + explicit String(unsigned char, unsigned char base = 10); + explicit String(int, unsigned char base = 10); + explicit String(unsigned int, unsigned char base = 10); + explicit String(long, unsigned char base = 10); + explicit String(unsigned long, unsigned char base = 10); + explicit String(float, unsigned char decimalPlaces = 2); + explicit String(double, unsigned char decimalPlaces = 2); + ~String(void); + + // memory management + // return true on success, false on failure (in which case, the string + // is left unchanged). reserve(0), if successful, will validate an + // invalid string (i.e., "if (s)" will be true afterwards) + unsigned char reserve(unsigned int size); + inline unsigned int length(void) const { return len; } + + // creates a copy of the assigned value. if the value is null or + // invalid, or if the memory allocation fails, the string will be + // marked as invalid ("if (s)" will be false). + String &operator=(const String &rhs); + String &operator=(const char *cstr); + String &operator=(const __FlashStringHelper *str); +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + String &operator=(String &&rval); + String &operator=(StringSumHelper &&rval); +#endif + + // concatenate (works w/ built-in types) + + // returns true on success, false on failure (in which case, the string + // is left unchanged). if the argument is null or invalid, the + // concatenation is considered unsucessful. + unsigned char concat(const String &str); + unsigned char concat(const char *cstr); + unsigned char concat(char c); + unsigned char concat(unsigned char c); + unsigned char concat(int num); + unsigned char concat(unsigned int num); + unsigned char concat(long num); + unsigned char concat(unsigned long num); + unsigned char concat(float num); + unsigned char concat(double num); + unsigned char concat(const __FlashStringHelper *str); + + // if there's not enough memory for the concatenated value, the string + // will be left unchanged (but this isn't signalled in any way) + String &operator+=(const String &rhs) + { + concat(rhs); + return (*this); + } + String &operator+=(const char *cstr) + { + concat(cstr); + return (*this); + } + String &operator+=(char c) + { + concat(c); + return (*this); + } + String &operator+=(unsigned char num) + { + concat(num); + return (*this); + } + String &operator+=(int num) + { + concat(num); + return (*this); + } + String &operator+=(unsigned int num) + { + concat(num); + return (*this); + } + String &operator+=(long num) + { + concat(num); + return (*this); + } + String &operator+=(unsigned long num) + { + concat(num); + return (*this); + } + String &operator+=(float num) + { + concat(num); + return (*this); + } + String &operator+=(double num) + { + concat(num); + return (*this); + } + String &operator+=(const __FlashStringHelper *str) + { + concat(str); + return (*this); + } + + friend StringSumHelper &operator+(const StringSumHelper &lhs, const String &rhs); + friend StringSumHelper &operator+(const StringSumHelper &lhs, const char *cstr); + friend StringSumHelper &operator+(const StringSumHelper &lhs, char c); + friend StringSumHelper &operator+(const StringSumHelper &lhs, unsigned char num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, int num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, unsigned int num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, long num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, unsigned long num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, float num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, double num); + friend StringSumHelper &operator+(const StringSumHelper &lhs, const __FlashStringHelper *rhs); + + // comparison (only works w/ Strings and "strings") + operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } + int compareTo(const String &s) const; + unsigned char equals(const String &s) const; + unsigned char equals(const char *cstr) const; + unsigned char operator==(const String &rhs) const { return equals(rhs); } + unsigned char operator==(const char *cstr) const { return equals(cstr); } + unsigned char operator!=(const String &rhs) const { return !equals(rhs); } + unsigned char operator!=(const char *cstr) const { return !equals(cstr); } + unsigned char operator<(const String &rhs) const; + unsigned char operator>(const String &rhs) const; + unsigned char operator<=(const String &rhs) const; + unsigned char operator>=(const String &rhs) const; + unsigned char equalsIgnoreCase(const String &s) const; + unsigned char startsWith(const String &prefix) const; + unsigned char startsWith(const String &prefix, unsigned int offset) const; + unsigned char endsWith(const String &suffix) const; + + // character acccess + char charAt(unsigned int index) const; + void setCharAt(unsigned int index, char c); + char operator[](unsigned int index) const; + char &operator[](unsigned int index); + void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index = 0) const; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const + { + getBytes((unsigned char *)buf, bufsize, index); + } + const char *c_str() const { return buffer; } + char *begin() { return buffer; } + char *end() { return buffer + length(); } + const char *begin() const { return c_str(); } + const char *end() const { return c_str() + length(); } + + // search + int indexOf(char ch) const; + int indexOf(char ch, unsigned int fromIndex) const; + int indexOf(const String &str) const; + int indexOf(const String &str, unsigned int fromIndex) const; + int lastIndexOf(char ch) const; + int lastIndexOf(char ch, unsigned int fromIndex) const; + int lastIndexOf(const String &str) const; + int lastIndexOf(const String &str, unsigned int fromIndex) const; + String substring(unsigned int beginIndex) const { return substring(beginIndex, len); }; + String substring(unsigned int beginIndex, unsigned int endIndex) const; + + // modification + void replace(char find, char replace); + void replace(const String &find, const String &replace); + void remove(unsigned int index); + void remove(unsigned int index, unsigned int count); + void toLowerCase(void); + void toUpperCase(void); + void trim(void); + + // parsing/conversion + long toInt(void) const; + float toFloat(void) const; + double toDouble(void) const; + + protected: + char *buffer; // the actual char array + unsigned int capacity; // the array length minus one (for the '\0') + unsigned int len; // the String length (not counting the '\0') + protected: + void init(void); + void invalidate(void); + unsigned char changeBuffer(unsigned int maxStrLen); + unsigned char concat(const char *cstr, unsigned int length); + + // copy and move + String ©(const char *cstr, unsigned int length); + String ©(const __FlashStringHelper *pstr, unsigned int length); +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) + void move(String &rhs); +#endif }; class StringSumHelper : public String { -public: - StringSumHelper(const String &s) : String(s) {} - StringSumHelper(const char *p) : String(p) {} - StringSumHelper(char c) : String(c) {} - StringSumHelper(unsigned char num) : String(num) {} - StringSumHelper(int num) : String(num) {} - StringSumHelper(unsigned int num) : String(num) {} - StringSumHelper(long num) : String(num) {} - StringSumHelper(unsigned long num) : String(num) {} - StringSumHelper(float num) : String(num) {} - StringSumHelper(double num) : String(num) {} + public: + StringSumHelper(const String &s) : String(s) {} + StringSumHelper(const char *p) : String(p) {} + StringSumHelper(char c) : String(c) {} + StringSumHelper(unsigned char num) : String(num) {} + StringSumHelper(int num) : String(num) {} + StringSumHelper(unsigned int num) : String(num) {} + StringSumHelper(long num) : String(num) {} + StringSumHelper(unsigned long num) : String(num) {} + StringSumHelper(float num) : String(num) {} + StringSumHelper(double num) : String(num) {} }; -#endif // __cplusplus +#endif // __cplusplus diff --git a/megaavr/cores/coreX-corefiles/api/USBAPI.h b/megaavr/cores/coreX-corefiles/api/USBAPI.h index 8743ab4..3283106 100644 --- a/megaavr/cores/coreX-corefiles/api/USBAPI.h +++ b/megaavr/cores/coreX-corefiles/api/USBAPI.h @@ -30,17 +30,18 @@ typedef struct __attribute__((packed)) { union { uint8_t bmRequestType; - struct { + struct + { uint8_t direction : 5; uint8_t type : 2; uint8_t transferDirection : 1; }; }; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; + uint8_t bRequest; + uint8_t wValueL; + uint8_t wValueH; + uint16_t wIndex; + uint16_t wLength; } USBSetup; //================================================================================ @@ -50,11 +51,11 @@ int USB_SendControl(uint8_t flags, const void* d, int len); int USB_RecvControl(void* d, int len); int USB_RecvControlLong(void* d, int len); -uint8_t USB_Available(uint8_t ep); +uint8_t USB_Available(uint8_t ep); uint8_t USB_SendSpace(uint8_t ep); -int USB_Send(uint8_t ep, const void* data, int len); // blocking -int USB_Recv(uint8_t ep, void* data, int len); // non-blocking -int USB_Recv(uint8_t ep); // non-blocking +int USB_Send(uint8_t ep, const void* data, int len); // blocking +int USB_Recv(uint8_t ep, void* data, int len); // non-blocking +int USB_Recv(uint8_t ep); // non-blocking void USB_Flush(uint8_t ep); #endif \ No newline at end of file diff --git a/megaavr/cores/coreX-corefiles/api/Udp.h b/megaavr/cores/coreX-corefiles/api/Udp.h index 9058165..252f7a4 100644 --- a/megaavr/cores/coreX-corefiles/api/Udp.h +++ b/megaavr/cores/coreX-corefiles/api/Udp.h @@ -36,51 +36,54 @@ #include "Stream.h" #include "IPAddress.h" - -class UDP : public Stream { - -public: - virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use - virtual void stop() =0; // Finish with the UDP socket +namespace arduino { +class UDP : public Stream +{ + public: + virtual uint8_t begin(uint16_t) = 0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual void stop() = 0; // Finish with the UDP socket // Sending UDP packets - + // Start building up a packet to send to the remote host specific in ip and port // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port - virtual int beginPacket(IPAddress ip, uint16_t port) =0; + virtual int beginPacket(IPAddress ip, uint16_t port) = 0; // Start building up a packet to send to the remote host specific in host and port // Returns 1 if successful, 0 if there was a problem resolving the hostname or port - virtual int beginPacket(const char *host, uint16_t port) =0; + virtual int beginPacket(const char* host, uint16_t port) = 0; // Finish off this packet and send it // Returns 1 if the packet was sent successfully, 0 if there was an error - virtual int endPacket() =0; + virtual int endPacket() = 0; // Write a single byte into the packet - virtual size_t write(uint8_t) =0; + virtual size_t write(uint8_t) = 0; // Write size bytes from buffer into the packet - virtual size_t write(const uint8_t *buffer, size_t size) =0; + virtual size_t write(const uint8_t* buffer, size_t size) = 0; // Start processing the next available incoming packet // Returns the size of the packet in bytes, or 0 if no packets are available - virtual int parsePacket() =0; + virtual int parsePacket() = 0; // Number of bytes remaining in the current packet - virtual int available() =0; + virtual int available() = 0; // Read a single byte from the current packet - virtual int read() =0; + virtual int read() = 0; // Read up to len bytes from the current packet and place them into buffer // Returns the number of bytes read, or 0 if none are available - virtual int read(unsigned char* buffer, size_t len) =0; + virtual int read(unsigned char* buffer, size_t len) = 0; // Read up to len characters from the current packet and place them into buffer // Returns the number of characters read, or 0 if none are available - virtual int read(char* buffer, size_t len) =0; + virtual int read(char* buffer, size_t len) = 0; // Return the next byte from the current packet without moving on to the next byte - virtual int peek() =0; - virtual void flush() =0; // Finish reading the current packet + virtual int peek() = 0; + virtual void flush() = 0; // Finish reading the current packet // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() =0; + virtual IPAddress remoteIP() = 0; // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() =0; -protected: + virtual uint16_t remotePort() = 0; + + protected: uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; }; +} +using arduino::UDP; diff --git a/megaavr/cores/coreX-corefiles/api/Udp.h.orig b/megaavr/cores/coreX-corefiles/api/Udp.h.orig index b695002..56c5f1d 100644 --- a/megaavr/cores/coreX-corefiles/api/Udp.h.orig +++ b/megaavr/cores/coreX-corefiles/api/Udp.h.orig @@ -42,7 +42,7 @@ namespace arduino { class UDP : public Stream { public: - virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use + virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use virtual void stop() =0; // Finish with the UDP socket // Sending UDP packets @@ -76,7 +76,7 @@ public: virtual int read(char* buffer, size_t len) =0; // Return the next byte from the current packet without moving on to the next byte virtual int peek() =0; - virtual void flush() =0; // Finish reading the current packet + virtual void flush() =0; // Finish reading the current packet // Return the IP address of the host who sent the current incoming packet virtual IPAddress remoteIP() =0; @@ -86,4 +86,4 @@ protected: uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; }; -} \ No newline at end of file +} diff --git a/megaavr/cores/coreX-corefiles/api/WCharacter.h b/megaavr/cores/coreX-corefiles/api/WCharacter.h index 4ce89ee..5db7d9b 100644 --- a/megaavr/cores/coreX-corefiles/api/WCharacter.h +++ b/megaavr/cores/coreX-corefiles/api/WCharacter.h @@ -38,131 +38,115 @@ inline bool isUpperCase(int c) __attribute__((always_inline)); inline bool isHexadecimalDigit(int c) __attribute__((always_inline)); inline int toAscii(int c) __attribute__((always_inline)); inline int toLowerCase(int c) __attribute__((always_inline)); -inline int toUpperCase(int c)__attribute__((always_inline)); +inline int toUpperCase(int c) __attribute__((always_inline)); - -// Checks for an alphanumeric character. +// Checks for an alphanumeric character. // It is equivalent to (isalpha(c) || isdigit(c)). -inline bool isAlphaNumeric(int c) +inline bool isAlphaNumeric(int c) { - return ( isalnum(c) == 0 ? false : true); + return (isalnum(c) == 0 ? false : true); } - -// Checks for an alphabetic character. +// Checks for an alphabetic character. // It is equivalent to (isupper(c) || islower(c)). inline bool isAlpha(int c) { - return ( isalpha(c) == 0 ? false : true); + return (isalpha(c) == 0 ? false : true); } - -// Checks whether c is a 7-bit unsigned char value +// Checks whether c is a 7-bit unsigned char value // that fits into the ASCII character set. inline bool isAscii(int c) { - return ( isascii (c) == 0 ? false : true); + return (isascii(c) == 0 ? false : true); } - // Checks for a blank character, that is, a space or a tab. inline bool isWhitespace(int c) { - return ( isblank (c) == 0 ? false : true); + return (isblank(c) == 0 ? false : true); } - // Checks for a control character. inline bool isControl(int c) { - return ( iscntrl (c) == 0 ? false : true); + return (iscntrl(c) == 0 ? false : true); } - // Checks for a digit (0 through 9). inline bool isDigit(int c) { - return ( isdigit (c) == 0 ? false : true); + return (isdigit(c) == 0 ? false : true); } - // Checks for any printable character except space. inline bool isGraph(int c) { - return ( isgraph (c) == 0 ? false : true); + return (isgraph(c) == 0 ? false : true); } - // Checks for a lower-case character. inline bool isLowerCase(int c) { - return (islower (c) == 0 ? false : true); + return (islower(c) == 0 ? false : true); } - // Checks for any printable character including space. inline bool isPrintable(int c) { - return ( isprint (c) == 0 ? false : true); + return (isprint(c) == 0 ? false : true); } - -// Checks for any printable character which is not a space +// Checks for any printable character which is not a space // or an alphanumeric character. inline bool isPunct(int c) { - return ( ispunct (c) == 0 ? false : true); + return (ispunct(c) == 0 ? false : true); } - -// Checks for white-space characters. For the avr-libc library, -// these are: space, formfeed ('\f'), newline ('\n'), carriage +// Checks for white-space characters. For the avr-libc library, +// these are: space, formfeed ('\f'), newline ('\n'), carriage // return ('\r'), horizontal tab ('\t'), and vertical tab ('\v'). inline bool isSpace(int c) { - return ( isspace (c) == 0 ? false : true); + return (isspace(c) == 0 ? false : true); } - // Checks for an uppercase letter. inline bool isUpperCase(int c) { - return ( isupper (c) == 0 ? false : true); + return (isupper(c) == 0 ? false : true); } - -// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 +// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7 // 8 9 a b c d e f A B C D E F. inline bool isHexadecimalDigit(int c) { - return ( isxdigit (c) == 0 ? false : true); + return (isxdigit(c) == 0 ? false : true); } - -// Converts c to a 7-bit unsigned char value that fits into the +// Converts c to a 7-bit unsigned char value that fits into the // ASCII character set, by clearing the high-order bits. inline int toAscii(int c) { - return toascii (c); + return toascii(c); } - // Warning: -// Many people will be unhappy if you use this function. -// This function will convert accented letters into random +// Many people will be unhappy if you use this function. +// This function will convert accented letters into random // characters. // Converts the letter c to lower case, if possible. inline int toLowerCase(int c) { - return tolower (c); + return tolower(c); } - // Converts the letter c to upper case, if possible. inline int toUpperCase(int c) { - return toupper (c); + return toupper(c); } #endif \ No newline at end of file diff --git a/megaavr/cores/coreX-corefiles/api/itoa.h b/megaavr/cores/coreX-corefiles/api/itoa.h index 55b2849..c94f733 100644 --- a/megaavr/cores/coreX-corefiles/api/itoa.h +++ b/megaavr/cores/coreX-corefiles/api/itoa.h @@ -23,15 +23,15 @@ // core should supply an implementation of them. #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -extern char* itoa(int value, char *string, int radix); -extern char* ltoa(long value, char *string, int radix); -extern char* utoa(unsigned value, char *string, int radix); -extern char* ultoa(unsigned long value, char *string, int radix); + extern char* itoa(int value, char* string, int radix); + extern char* ltoa(long value, char* string, int radix); + extern char* utoa(unsigned value, char* string, int radix); + extern char* ultoa(unsigned long value, char* string, int radix); #ifdef __cplusplus } // extern "C" #endif - diff --git a/megaavr/cores/coreX-corefiles/hooks.c b/megaavr/cores/coreX-corefiles/hooks.c index 641eabc..a61b5ef 100644 --- a/megaavr/cores/coreX-corefiles/hooks.c +++ b/megaavr/cores/coreX-corefiles/hooks.c @@ -26,6 +26,6 @@ * real cooperative scheduler. */ static void __empty() { - // Empty + // Empty } void yield(void) __attribute__ ((weak, alias("__empty"))); diff --git a/megaavr/cores/coreX-corefiles/main.cpp b/megaavr/cores/coreX-corefiles/main.cpp index 17aa21d..d79a464 100644 --- a/megaavr/cores/coreX-corefiles/main.cpp +++ b/megaavr/cores/coreX-corefiles/main.cpp @@ -20,33 +20,28 @@ #include // Declared weak in Arduino.h to allow user redefinitions. -int atexit(void (* /*func*/ )()) { return 0; } - -// Weak empty variant initialization function. -// May be redefined by variant files. -void initVariant() __attribute__((weak)); -void initVariant() { } +int atexit(void (* /*func*/)()) { return 0; } void setupUSB() __attribute__((weak)); -void setupUSB() { } +void setupUSB() {} int main(void) { - init(); + init(); - initVariant(); + initVariant(); #if defined(USBCON) - USBDevice.attach(); + USBDevice.attach(); #endif - setup(); + setup(); - for (;;) { - loop(); - if (serialEventRun) serialEventRun(); - } + for (;;) + { + loop(); + if (serialEventRun) serialEventRun(); + } - return 0; + return 0; } - diff --git a/megaavr/cores/coreX-corefiles/new.cpp b/megaavr/cores/coreX-corefiles/new.cpp index cf6f89c..26403f1 100644 --- a/megaavr/cores/coreX-corefiles/new.cpp +++ b/megaavr/cores/coreX-corefiles/new.cpp @@ -18,19 +18,37 @@ #include -void *operator new(size_t size) { +void *operator new(size_t size) +{ return malloc(size); } -void *operator new[](size_t size) { +void *operator new[](size_t size) +{ return malloc(size); } -void operator delete(void * ptr) { +void operator delete(void *ptr) +{ free(ptr); } -void operator delete[](void * ptr) { +void operator delete[](void *ptr) +{ free(ptr); } +// C++14 introduces additional delete operators +#if __cplusplus >= 201402L + +void operator delete(void * ptr, size_t) +{ + ::operator delete(ptr); +} + +void operator delete[](void * ptr, size_t) +{ + ::operator delete(ptr); +} + +#endif // End language is C++14 or greater diff --git a/megaavr/cores/coreX-corefiles/new.h b/megaavr/cores/coreX-corefiles/new.h index 6e1b68f..66b9619 100644 --- a/megaavr/cores/coreX-corefiles/new.h +++ b/megaavr/cores/coreX-corefiles/new.h @@ -23,8 +23,13 @@ void * operator new(size_t size); void * operator new[](size_t size); -void operator delete(void * ptr); -void operator delete[](void * ptr); +void operator delete(void* ptr); +void operator delete[](void* ptr); -#endif +// C++14 introduces additional delete operators +#if __cplusplus >= 201402L +void operator delete(void * ptr, size_t); +void operator delete[](void * ptr, size_t); +#endif // end language is C++14 or greater +#endif diff --git a/megaavr/cores/coreX-corefiles/pwm_write.cpp b/megaavr/cores/coreX-corefiles/pwm_write.cpp new file mode 100644 index 0000000..d89739f --- /dev/null +++ b/megaavr/cores/coreX-corefiles/pwm_write.cpp @@ -0,0 +1,158 @@ +#include "Arduino.h" +#include "pins_arduino.h" +#include "wiring_private.h" + +void pwmWrite(pwm_timers_t pwmTimer, uint16_t val, timers_route_t timerRoute) { + // Set PORTMUX to route PWM to the correct pin + if (timerRoute != ROUTE_UNTOUCHED) { + if(timerRoute & 0x40) + PORTMUX.TCAROUTEA = timerRoute & 0x07; + else { + uint8_t tcb_index = (timerRoute >> 4) & 0x03; + uint8_t route_bit = timerRoute & 0x01; + uint8_t mask = (1 << tcb_index); + if(route_bit) + PORTMUX.TCBROUTEA |= mask; + else + PORTMUX.TCBROUTEA &= ~mask; + } + } + + // Find corresponding IO pin based on pwmTimer + uint8_t route = 0; + uint8_t pin_bp = 0; + uint8_t d_max = 0; + VPORT_t *vport; + if(pwmTimer <= TCA0_5) { + route = PORTMUX.TCAROUTEA; + pin_bp = pwmTimer; + vport = &VPORTA + route; + d_max = TCA0.SPLIT.LPER; + } else if(pwmTimer == TCB_0) { + route = PORTMUX.TCBROUTEA & 0x01; + pin_bp = route? PIN4_bp: PIN2_bp; + vport = route? &VPORTF: &VPORTA; + d_max = TCB0.CCMPL; + } else if(pwmTimer == TCB_1) { + route = PORTMUX.TCBROUTEA & 0x02; + pin_bp = route? PIN5_bp: PIN3_bp; + vport = route? &VPORTF: &VPORTA; + d_max = TCB1.CCMPL; + } else if(pwmTimer == TCB_2) { + route = PORTMUX.TCBROUTEA & 0x04; + pin_bp = route? PIN4_bp: PIN0_bp; + vport = route? &VPORTB: &VPORTC; + d_max = TCB2.CCMPL; + } + #if defined(TCB3) + else if(pwmTimer == TCB_3) { + route = PORTMUX.TCBROUTEA & 0x08; + pin_bp = route? PIN1_bp: PIN5_bp; + vport = route? &VPORTC: &VPORTB; + d_max = TCB3.CCMPL; + } + #endif + else { + return; + } + + // Set IO pin as output + vport->DIR |= (1< d_max) { + // Turn off PWM + uint8_t bitpos = pin_bp; + switch (pwmTimer) { + case TCA0_0...TCA0_5: + if (bitpos >= 3) ++bitpos; // Upper 3 bits are shifted by 1 + TCA0.SPLIT.CTRLB &= ~(1 << (TCA_SPLIT_LCMP0EN_bp + bitpos)); + break; + + case TCB_0: + case TCB_1: + case TCB_2: + #if defined(TCB3) + case TCB_3: + #endif + timer_B = &TCB0 + (pwmTimer-TCB_0); + timer_B->CTRLB &= ~(TCB_CCMPEN_bm); + break; + + default: + break; + } + // Set pin high or low + if(val <= 0) + vport->OUT &= ~(1<OUT |= (1<= 3) { + timer_cmp_out = ((uint8_t *)(&TCA0.SPLIT.HCMP0)) + 2*(pin_bp-3); + ++pin_bp; + } else { + timer_cmp_out = ((uint8_t *)(&TCA0.SPLIT.LCMP0)) + 2*pin_bp; + } + cli(); + *timer_cmp_out = val; + SREG = savedSREG; + TCA0.SPLIT.CTRLB |= (1 << (TCA_SPLIT_LCMP0EN_bp + pin_bp)); + break; + + case TCB_0: + case TCB_1: + case TCB_2: + #if defined(TCB3) + case TCB_3: + #endif + timer_B = &TCB0 + (pwmTimer-TCB_0); + savedSREG = SREG; + cli(); + timer_B->CCMPL = timer_B->CCMPL; + timer_B->CCMPH = val; + SREG = savedSREG; + timer_B->CTRLB |= (TCB_CCMPEN_bm); + break; + } + } +} + +void pwmPrescaler(pwm_timers_t pwmTimer, timers_prescaler_t prescaler) { + if(pwmTimer <= TCA0_5) + TCA0.SPLIT.CTRLA = prescaler | TCA_SPLIT_ENABLE_bm; + else { + TCB_t *timer_B = &TCB0 + (pwmTimer-TCB_0); + uint8_t p = (prescaler >> 4) & TCB_CLKSEL_gm; + timer_B->CTRLA = ((timer_B->CTRLA & ~TCB_CLKSEL_gm) | p); + } +} + +void pwmSetResolution(pwm_timers_t pwmTimer, uint8_t maxValue) { + // The max value will disable PWM and set pin high + uint8_t top = maxValue? maxValue-1: 1; + + if(pwmTimer <= TCA0_5) { + TCA0.SPLIT.LPER = + TCA0.SPLIT.HPER = top; + TCA0.SPLIT.LCMP0 = + TCA0.SPLIT.LCMP1 = + TCA0.SPLIT.LCMP2 = + TCA0.SPLIT.HCMP0 = + TCA0.SPLIT.HCMP1 = + TCA0.SPLIT.HCMP2 = top >> 1; + } else { + TCB_t *timer_B = &TCB0 + (pwmTimer-TCB_0); + timer_B->CCMPL = top; + timer_B->CCMPH = top >> 1; + } + +} \ No newline at end of file diff --git a/megaavr/cores/coreX-corefiles/timers.h b/megaavr/cores/coreX-corefiles/timers.h new file mode 100644 index 0000000..d468fbb --- /dev/null +++ b/megaavr/cores/coreX-corefiles/timers.h @@ -0,0 +1,11 @@ +#ifndef __TIMERS_H__ +#define __TIMERS_H__ + +// The assumption is that we have a 16 bit timer fully available for timing purposes. +#define TIME_TRACKING_TIMER_DIVIDER 1 // Timer F_CPU Clock divider (can be 1 or 2) +#define TIME_TRACKING_TIMER_COUNT (F_CPU / (1000 * TIME_TRACKING_TIMER_DIVIDER)) // Should correspond to exactly 1 ms, i.e. millis() + +#define PWM_TIMER_PERIOD 0xFE // For frequency +#define PWM_TIMER_COMPARE 0x80 // For duty cycle + +#endif diff --git a/megaavr/cores/coreX-corefiles/wiring.c b/megaavr/cores/coreX-corefiles/wiring.c index ef0d24d..a04037f 100644 --- a/megaavr/cores/coreX-corefiles/wiring.c +++ b/megaavr/cores/coreX-corefiles/wiring.c @@ -1,5 +1,5 @@ /* - wiring.c - Partial implementation of the Wiring API for the ATmega8. + wiring.c Part of Arduino - http://www.arduino.cc/ Copyright (c) 2005-2006 David A. Mellis @@ -18,391 +18,536 @@ Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "wiring_private.h" - -// the prescaler is set so that timer ticks every 64 clock cycles, and the -// the overflow handler is called every 256 ticks. -volatile uint16_t microseconds_per_timer_overflow; -volatile uint16_t microseconds_per_timer_tick; - -uint32_t F_CPU_CORRECTED = F_CPU; -// the whole number of milliseconds per timer overflow -uint16_t millis_inc; + Substantially rewritten by Egil Kvaleberg, 23 Sep 2019, to + use a dedicated 16 bit TSB timer for all timing purposes. This + cleans up a lot of things, and makes the code much simpler and + faster. The TCB timers have limitations making it impossible to + use the same timer for both PWM and timing, so this is no loss. -// the fractional number of milliseconds per timer overflow -uint16_t fract_inc; -#define FRACT_MAX (1000) +*/ -// whole number of microseconds per timer tick +#include "wiring_private.h" -volatile uint32_t timer_overflow_count = 0; volatile uint32_t timer_millis = 0; -static uint16_t timer_fract = 0; -inline uint16_t clockCyclesPerMicrosecondComp(uint32_t clk){ - return ( (clk) / 1000000L ); +inline uint16_t clockCyclesPerMicrosecondComp(uint32_t clk) +{ + return ((clk) / 1000000L); } -inline uint16_t clockCyclesPerMicrosecond(){ - return clockCyclesPerMicrosecondComp(F_CPU_CORRECTED); +inline uint16_t clockCyclesPerMicrosecond() +{ + return clockCyclesPerMicrosecondComp(F_CPU); } -inline unsigned long clockCyclesToMicroseconds(unsigned long cycles){ - return ( cycles / clockCyclesPerMicrosecond() ); +inline unsigned long clockCyclesToMicroseconds(unsigned long cycles) +{ + return (cycles / clockCyclesPerMicrosecond()); } -inline unsigned long microsecondsToClockCycles(unsigned long microseconds){ - return ( microseconds * clockCyclesPerMicrosecond() ); +inline unsigned long microsecondsToClockCycles(unsigned long microseconds) +{ + return (microseconds * clockCyclesPerMicrosecond()); } -static volatile TCB_t* _timer = +static volatile TCB_t *_timer = #if defined(MILLIS_USE_TIMERB0) - &TCB0; + &TCB0; #elif defined(MILLIS_USE_TIMERB1) - &TCB1; + &TCB1; #elif defined(MILLIS_USE_TIMERB2) - &TCB2; -#elif defined(MILLIS_USE_TIMERB3) - &TCB3; -#else - &TCB0; //TCB0 fallback + &TCB2; +#else // fallback or defined(MILLIS_USE_TIMERB3) + &TCB3; //TCB3 fallback #endif #if defined(MILLIS_USE_TIMERB0) - ISR(TCB0_INT_vect) +ISR(TCB0_INT_vect) #elif defined(MILLIS_USE_TIMERB1) - ISR(TCB1_INT_vect) +ISR(TCB1_INT_vect) #elif defined(MILLIS_USE_TIMERB2) - ISR(TCB2_INT_vect) -#elif defined(MILLIS_USE_TIMERB3) - ISR(TCB3_INT_vect) -#else //TCB0 fallback - ISR(TCB0_INT_vect) +ISR(TCB2_INT_vect) +#else // fallback or defined(MILLIS_USE_TIMERB3) +ISR(TCB3_INT_vect) #endif { - // copy these to local variables so they can be stored in registers - // (volatile variables must be read from memory on every access) - uint32_t m = timer_millis; - uint16_t f = timer_fract; - - m += millis_inc; - f += fract_inc; - if (f >= FRACT_MAX) { + timer_millis++; - f -= FRACT_MAX; - m += 1; - } - - timer_fract = f; - timer_millis = m; - timer_overflow_count++; - - /* Clear flag */ - _timer->INTFLAGS = TCB_CAPT_bm; + /* Clear flag */ + _timer->INTFLAGS = TCB_CAPT_bm; } unsigned long millis() { - unsigned long m; - - // disable interrupts while we read timer0_millis or we might get an - // inconsistent value (e.g. in the middle of a write to timer0_millis) - uint8_t status = SREG; - cli(); - m = timer_millis; - - SREG = status; + unsigned long m; - return m; -} - -unsigned long micros() { - unsigned long overflows, microseconds; - uint8_t ticks; - - /* Save current state and disable interrupts */ - uint8_t status = SREG; - cli(); + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer_millis) + uint8_t status = SREG; + cli(); - /* Get current number of overflows and timer count */ - overflows = timer_overflow_count; - ticks = _timer->CNTL; + m = timer_millis; - /* If the timer overflow flag is raised, we just missed it, - increment to account for it, & read new ticks */ - if(_timer->INTFLAGS & TCB_CAPT_bm){ - overflows++; - ticks = _timer->CNTL; - } + SREG = status; - /* Restore state */ - SREG = status; + return m; +} - /* Return microseconds of up time (resets every ~70mins) */ - microseconds = ((overflows * microseconds_per_timer_overflow) - + (ticks * microseconds_per_timer_tick)); - return microseconds; +unsigned long micros() +{ + uint32_t m; + uint16_t t; + + /* Save current state and disable interrupts */ + uint8_t status = SREG; + cli(); + + /* Get current number of millis (i.e. overflows) and timer count */ + m = timer_millis; + t = _timer->CNT; + + /* If the timer overflow flag is raised, we just missed it, + increment to account for it, & read new ticks */ + if (_timer->INTFLAGS & TCB_CAPT_bm) + { + m++; + t = _timer->CNT; + } + + // Restore SREG + SREG = status; + +#if (F_CPU == 20000000L) + t = t >> 4; + return m * 1000 + (t - (t >> 2) + (t >> 4) - (t >> 6)); +#elif (F_CPU == 16000000L) + return m * 1000 + (t >> 4); +#elif (F_CPU == 10000000L) + t = t >> 3; + return m * 1000 + (t - (t >> 2) + (t >> 4) - (t >> 6)); +#elif (F_CPU == 8000000L) + return m * 1000 + (t >> 3); +#elif (F_CPU == 5000000L) + t = t >> 2; + return m * 1000 + (t - (t >> 2) + (t >> 4) - (t >> 6)); +#elif (F_CPU == 4000000L) + return m * 1000 + (t >> 2); +#elif (F_CPU == 2000000L) + return m * 1000 + (t >> 1); +#elif (F_CPU == 1000000L) + return m * 1000 + t; +#else + return 0; +#endif } void delay(unsigned long ms) { - uint32_t start_time = micros(), delay_time = 1000*ms; - - /* Calculate future time to return */ - uint32_t return_time = start_time + delay_time; - - /* If return time overflows */ - if(return_time < delay_time){ - /* Wait until micros overflows */ - while(micros() > return_time); - } - - /* Wait until return time */ - while(micros() < return_time); + uint32_t start_time = micros(), delay_time = 1000 * ms; + + /* Calculate future time to return */ + uint32_t return_time = start_time + delay_time; + + /* If return time overflows */ + if (return_time < delay_time) + { + /* Wait until micros overflows */ + while (micros() > return_time) + ; + } + + /* Wait until return time */ + while (micros() < return_time) + ; } /* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */ +// BUG: should really be implemented using _timer instead!!!!!!!!!! void delayMicroseconds(unsigned int us) { - // call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable) + // call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable) - // calling avrlib's delay_us() function with low values (e.g. 1 or - // 2 microseconds) gives delays longer than desired. - //delay_us(us); + // calling avrlib's delay_us() function with low values (e.g. 1 or + // 2 microseconds) gives delays longer than desired. + //delay_us(us); #if F_CPU >= 24000000L - // for the 24 MHz clock for the aventurous ones, trying to overclock + // for the 24 MHz clock for the aventurous ones, trying to overclock - // zero delay fix - if (!us) return; // = 3 cycles, (4 when true) + // zero delay fix + if (!us) return; // = 3 cycles, (4 when true) - // the following loop takes a 1/6 of a microsecond (4 cycles) - // per iteration, so execute it six times for each microsecond of - // delay requested. - us *= 6; // x6 us, = 7 cycles + // the following loop takes a 1/6 of a microsecond (4 cycles) + // per iteration, so execute it six times for each microsecond of + // delay requested. + us *= 6; // x6 us, = 7 cycles - // account for the time taken in the preceeding commands. - // we just burned 22 (24) cycles above, remove 5, (5*4=20) - // us is at least 6 so we can substract 5 - us -= 5; //=2 cycles + // account for the time taken in the preceeding commands. + // we just burned 22 (24) cycles above, remove 5, (5*4=20) + // us is at least 6 so we can substract 5 + us -= 5; //=2 cycles #elif F_CPU >= 20000000L - // for the 20 MHz clock on rare Arduino boards - - // for a one-microsecond delay, simply return. the overhead - // of the function call takes 18 (20) cycles, which is 1us - __asm__ __volatile__ ( - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop"); //just waiting 4 cycles - if (us <= 1) return; // = 3 cycles, (4 when true) - - // the following loop takes a 1/5 of a microsecond (4 cycles) - // per iteration, so execute it five times for each microsecond of - // delay requested. - us = (us << 2) + us; // x5 us, = 7 cycles - - // account for the time taken in the preceeding commands. - // we just burned 26 (28) cycles above, remove 7, (7*4=28) - // us is at least 10 so we can substract 7 - us -= 7; // 2 cycles + + // for a one-microsecond delay, simply return. the overhead + // of the function call takes 18 (20) cycles, which is 1us + __asm__ __volatile__( + "nop" + "\n\t" + "nop" + "\n\t" + "nop" + "\n\t" + "nop"); //just waiting 4 cycles + if (us <= 1) return; // = 3 cycles, (4 when true) + + // the following loop takes a 1/5 of a microsecond (4 cycles) + // per iteration, so execute it five times for each microsecond of + // delay requested. + us = (us << 2) + us; // x5 us, = 7 cycles + + // account for the time taken in the preceeding commands. + // we just burned 26 (28) cycles above, remove 7, (7*4=28) + // us is at least 10 so we can substract 7 + us -= 7; // 2 cycles #elif F_CPU >= 16000000L - // for the 16 MHz clock on most Arduino boards - // for a one-microsecond delay, simply return. the overhead - // of the function call takes 14 (16) cycles, which is 1us - if (us <= 1) return; // = 3 cycles, (4 when true) + // for a one-microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 1us + if (us <= 1) return; // = 3 cycles, (4 when true) - // the following loop takes 1/4 of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; // x4 us, = 4 cycles + // the following loop takes 1/4 of a microsecond (4 cycles) + // per iteration, so execute it four times for each microsecond of + // delay requested. + us <<= 2; // x4 us, = 4 cycles - // account for the time taken in the preceeding commands. - // we just burned 19 (21) cycles above, remove 5, (5*4=20) - // us is at least 8 so we can substract 5 - us -= 5; // = 2 cycles, + // account for the time taken in the preceeding commands. + // we just burned 19 (21) cycles above, remove 5, (5*4=20) + // us is at least 8 so we can substract 5 + us -= 5; // = 2 cycles, #elif F_CPU >= 12000000L - // for the 12 MHz clock if somebody is working with USB - // for a 1 microsecond delay, simply return. the overhead - // of the function call takes 14 (16) cycles, which is 1.5us - if (us <= 1) return; // = 3 cycles, (4 when true) + // for a 1 microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 1.5us + if (us <= 1) return; // = 3 cycles, (4 when true) + + // the following loop takes 1/3 of a microsecond (4 cycles) + // per iteration, so execute it three times for each microsecond of + // delay requested. + us = (us << 1) + us; // x3 us, = 5 cycles + + // account for the time taken in the preceeding commands. + // we just burned 20 (22) cycles above, remove 5, (5*4=20) + // us is at least 6 so we can substract 5 + us -= 5; //2 cycles - // the following loop takes 1/3 of a microsecond (4 cycles) - // per iteration, so execute it three times for each microsecond of - // delay requested. - us = (us << 1) + us; // x3 us, = 5 cycles +#elif F_CPU >= 10000000L - // account for the time taken in the preceeding commands. - // we just burned 20 (22) cycles above, remove 5, (5*4=20) - // us is at least 6 so we can substract 5 - us -= 5; //2 cycles + // for a 1 microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 1.5us + if (us <= 1) return; // = 3 cycles, (4 when true) + + // the following loop takes 2/5 of a microsecond (4 cycles) + // per iteration, so execute it 2.5 times for each microsecond of + // delay requested. + us = (us << 1) + (us >> 1); // x2.5 us, = 5 cycles + + // account for the time taken in the preceding commands. + // we just burned 20 (22) cycles above, remove 5, (5*4=20) + // us is at least 6 so we can subtract 5 + us -= 5; //2 cycles #elif F_CPU >= 8000000L - // for the 8 MHz internal clock - // for a 1 and 2 microsecond delay, simply return. the overhead - // of the function call takes 14 (16) cycles, which is 2us - if (us <= 2) return; // = 3 cycles, (4 when true) + // for a 1 and 2 microsecond delay, simply return. the overhead + // of the function call takes 14 (16) cycles, which is 2us + if (us <= 2) return; // = 3 cycles, (4 when true) - // the following loop takes 1/2 of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; //x2 us, = 2 cycles + // the following loop takes 1/2 of a microsecond (4 cycles) + // per iteration, so execute it twice for each microsecond of + // delay requested. + us <<= 1; //x2 us, = 2 cycles - // account for the time taken in the preceeding commands. - // we just burned 17 (19) cycles above, remove 4, (4*4=16) - // us is at least 6 so we can substract 4 - us -= 4; // = 2 cycles + // account for the time taken in the preceeding commands. + // we just burned 17 (19) cycles above, remove 4, (4*4=16) + // us is at least 6 so we can substract 4 + us -= 4; // = 2 cycles -#else - // for the 1 MHz internal clock (default settings for common Atmega microcontrollers) +#elif F_CPU >= 5000000L + + // For a 1 ~ 3 microsecond delay, simply return. The overhead + // of the function call takes 14 (16) cycles, which is 3us + if (us <= 3) return; // = 3 cycles, (4 when true) - // the overhead of the function calls is 14 (16) cycles - if (us <= 16) return; //= 3 cycles, (4 when true) - if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22) + // The following loop takes 4/5th microsecond (4 cycles) + // per iteration, so we want to add it to 1/4th of itself + us += (us >> 2); - // compensate for the time taken by the preceeding and next commands (about 22 cycles) - us -= 22; // = 2 cycles - // the following loop takes 4 microseconds (4 cycles) - // per iteration, so execute it us/4 times - // us is at least 4, divided by 4 gives us 1 (no zero delay bug) - us >>= 2; // us div 4, = 4 cycles + us -= 2; // = 2 cycles +#elif F_CPU >= 4000000L + // The overhead of the function call is 14 (16) cycles which is 4 us + if (us <= 2) return; + + // Subtract microseconds that were wasted in this function + us -= 2; + + // We don't need to multiply here because one request microsecond is exactly one loop cycle + +#elif F_CPU >= 2000000L + // The overhead of the function call is 14 (16) cycles which is 8.68 us + // Plus the if-statement that takes 3 cycles (4 when true): ~11us + if (us <= 13) return; + + // Subtract microseconds that were wasted in this function + us -= 11; // 2 cycles + + us = (us >> 1); // 3 cycles + +#else + + // the overhead of the function calls is 14 (16) cycles + if (us <= 16) return; //= 3 cycles, (4 when true) + if (us <= 25) return; //= 3 cycles, (4 when true), (must be at least 25 if we want to substract 22) + + // compensate for the time taken by the preceeding and next commands (about 22 cycles) + us -= 22; // = 2 cycles + // the following loop takes 4 microseconds (4 cycles) + // per iteration, so execute it us/4 times + // us is at least 4, divided by 4 gives us 1 (no zero delay bug) + us >>= 2; // us div 4, = 4 cycles #endif - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); - // return = 4 cycles + // busy wait + __asm__ __volatile__( + "1: sbiw %0,1" + "\n\t" // 2 cycles + "brne 1b" + : "=w"(us) + : "0"(us) // 2 cycles + ); + // return = 4 cycles } void init() { - // this needs to be called before setup() or some functions won't - // work there - -/******************************** CLOCK STUFF *********************************/ - - /* We assume 5V operating frequency and FUSE.OSCCFG -> 16MHz */ - - int64_t cpu_freq; - - #if (F_CPU == 20000000) - cpu_freq = 20000000; - - /* No division on clock */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); - - #elif (F_CPU == 16000000) - cpu_freq = 16000000; - - /* No division on clock */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); - - #elif (F_CPU == 8000000) - cpu_freq = 8000000; - - /* Clock DIV2 */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc)); - - #elif (F_CPU == 4000000) - cpu_freq = 4000000; - - /* Clock DIV4 */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc)); - - #elif (F_CPU == 2000000) - cpu_freq = 2000000; - - /* Clock DIV8 */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_8X_gc)); - #else - - #ifndef F_CPU - # warning "F_CPU not defined" - #define F_CPU 16000000 - #endif - - # warning "F_CPU defined as an invalid value - may cause undefined behavior" - - /* Default value is 16MHz */ - cpu_freq = 16000000; - - /* No division on clock */ - _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); - #endif - - /* Apply calculated value to F_CPU_CORRECTED */ - F_CPU_CORRECTED = (uint32_t)cpu_freq; - - -/********************************* ADC ****************************************/ + // this needs to be called before setup() or some functions won't + // work there + + /******************************** CLOCK STUFF *********************************/ + +// Use external oscillator if already defined (in boards.txt, platformio.ini) +#if defined(USE_EXTERNAL_OSCILLATOR) + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLA, CLKCTRL_CLKSEL_EXTCLK_gc); + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); // Fallback to 16 MHz internal if no EXTCLK + +// Use internal oscillator if not defined. No need to manipulate the MCLKCTRLA register here +// because it's already done in the SYSCFG0 fuse byte +#else +#if (F_CPU == 20000000L) + /* No division on clock */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); +#elif (F_CPU == 16000000L) + /* No division on clock */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0x00); +#elif (F_CPU == 10000000L) + /* Clock DIV2 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc)); +#elif (F_CPU == 8000000L) + /* Clock DIV2 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc)); +#elif (F_CPU == 5000000L) + /* Clock DIV4 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc)); +#elif (F_CPU == 4000000L) + /* Clock DIV4 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc)); +#elif (F_CPU == 2000000L) + /* Clock DIV8 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_8X_gc)); +#elif (F_CPU == 1000000L) + /* Clock DIV16 */ + _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, (CLKCTRL_PEN_bm | CLKCTRL_PDIV_16X_gc)); +#else +#assert "This internal CPU clock is not supported" +#endif +#endif + + /********************************* ADC ****************************************/ #if defined(ADC0) - /* ADC clock between 50-200 kHz */ - - #if F_CPU >= 20000000 // 20 MHz / 128 = 156.250 kHz - ADC0.CTRLC |= ADC_PRESC_DIV128_gc; - #elif F_CPU >= 16000000 // 16 MHz / 128 = 125 kHz - ADC0.CTRLC |= ADC_PRESC_DIV128_gc; - #elif F_CPU >= 8000000 // 8 MHz / 64 = 125 kHz - ADC0.CTRLC |= ADC_PRESC_DIV64_gc; - #elif F_CPU >= 4000000 // 4 MHz / 32 = 125 kHz - ADC0.CTRLC |= ADC_PRESC_DIV32_gc; - #elif F_CPU >= 2000000 // 2 MHz / 16 = 125 kHz - ADC0.CTRLC |= ADC_PRESC_DIV16_gc; - #elif F_CPU >= 1000000 // 1 MHz / 8 = 125 kHz - ADC0.CTRLC |= ADC_PRESC_DIV8_gc; - #else // 128 kHz / 2 = 64 kHz -> This is the closest you can get, the prescaler is 2 - ADC0.CTRLC |= ADC_PRESC_DIV2_gc; - #endif - - /* Enable ADC */ - ADC0.CTRLA |= ADC_ENABLE_bm; - analogReference(VDD); + /* ADC clock between 50-200 kHz */ + +#if (F_CPU >= 20000000L) // 20 MHz / 128 = 156.250 kHz + ADC0.CTRLC |= ADC_PRESC_DIV128_gc; +#elif (F_CPU >= 16000000L) // 16 MHz / 128 = 125 kHz + ADC0.CTRLC |= ADC_PRESC_DIV128_gc; +#elif (F_CPU >= 8000000L) // 8 MHz / 64 = 125 kHz + ADC0.CTRLC |= ADC_PRESC_DIV64_gc; +#elif (F_CPU >= 4000000L) // 4 MHz / 32 = 125 kHz + ADC0.CTRLC |= ADC_PRESC_DIV32_gc; +#elif (F_CPU >= 2000000L) // 2 MHz / 16 = 125 kHz + ADC0.CTRLC |= ADC_PRESC_DIV16_gc; +#elif (F_CPU >= 1000000L) // 1 MHz / 8 = 125 kHz + ADC0.CTRLC |= ADC_PRESC_DIV8_gc; +#else // 128 kHz / 2 = 64 kHz -> This is the closest you can get, the prescaler is 2 + ADC0.CTRLC |= ADC_PRESC_DIV2_gc; +#endif + + /* Enable ADC */ + ADC0.CTRLA |= ADC_ENABLE_bm; + analogReference(VDD); #endif - PORTMUX.USARTROUTEA = 0; + PORTMUX.USARTROUTEA = 0; - setup_timers(); + setup_timers(); - /********************* TCB for system time tracking **************************/ + /********************* TCB for system time tracking **************************/ - /* Calculate relevant time tracking values */ - microseconds_per_timer_overflow = clockCyclesToMicroseconds(TIME_TRACKING_CYCLES_PER_OVF); - microseconds_per_timer_tick = microseconds_per_timer_overflow/TIME_TRACKING_TIMER_PERIOD; + // BUG: we can compensate for F_CPU by fine tuning value of TIME_TRACKING_TIMER_COUNT - millis_inc = microseconds_per_timer_overflow / 1000; - fract_inc = ((microseconds_per_timer_overflow % 1000)); + /* Select vanilla 16 bit periodic interrupt mode */ + _timer->CTRLB = TCB_CNTMODE_INT_gc; - /* Default Periodic Interrupt Mode */ - /* TOP value for overflow every 1024 clock cycles */ - _timer->CCMP = TIME_TRACKING_TIMER_PERIOD; + /* TOP value for overflow every N clock cycles */ + _timer->CCMP = TIME_TRACKING_TIMER_COUNT - 1; - /* Enable TCB interrupt */ - _timer->INTCTRL |= TCB_CAPT_bm; + /* Enable TCB interrupt */ + _timer->INTCTRL |= TCB_CAPT_bm; - /* Clock selection -> same as TCA (F_CPU/64 -- 250kHz) */ - _timer->CTRLA = TCB_CLKSEL_CLKTCA_gc; + /* Clock selection is F_CPU/N -- which is independent of TCA */ +#if TIME_TRACKING_TIMER_DIVIDER == 1 + _timer->CTRLA = TCB_CLKSEL_CLKDIV1_gc; /* F_CPU */ +#elif TIME_TRACKING_TIMER_DIVIDER == 2 + _timer->CTRLA = TCB_CLKSEL_CLKDIV2_gc; /* F_CPU/2 */ +#else +#assert "TIME_TRACKING_TIMER_DIVIDER not supported" +#endif - /* Enable & start */ - _timer->CTRLA |= TCB_ENABLE_bm; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */ + /* Enable & start */ + _timer->CTRLA |= TCB_ENABLE_bm; /* Keep this last before enabling interrupts to ensure tracking as accurate as possible */ -/*************************** ENABLE GLOBAL INTERRUPTS *************************/ + /*************************** ENABLE GLOBAL INTERRUPTS *************************/ - sei(); + sei(); } -void setup_timers(void) __attribute__((weak)); \ No newline at end of file +void setup_timers() +{ + // TYPE A TIMER + + // PORTMUX setting for TCA (defined in pins_arduino.h) + PORTMUX.TCAROUTEA = TCA0_PINS; + + // Enable split mode before anything else + TCA0.SPLIT.CTRLD = TCA_SINGLE_SPLITM_bm; + + // Period setting, two 8 bit registers + TCA0.SPLIT.LPER = + TCA0.SPLIT.HPER = PWM_TIMER_PERIOD; + + // Default duty 50%, will re-assign in analogWrite() + TCA0.SPLIT.LCMP0 = + TCA0.SPLIT.LCMP1 = + TCA0.SPLIT.LCMP2 = + TCA0.SPLIT.HCMP0 = + TCA0.SPLIT.HCMP1 = + TCA0.SPLIT.HCMP2 = PWM_TIMER_COMPARE; + +#if F_CPU <= 1000000L + // Use DIV4 prescaler (giving 250kHz clock on 1MHz), enable TCA timer + TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV4_gc) | (TCA_SPLIT_ENABLE_bm); +#elif F_CPU <= 2000000L + // Use DIV8 prescaler (giving 250kHz clock on 2MHz), enable TCA timer + TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV8_gc) | (TCA_SPLIT_ENABLE_bm); +#elif F_CPU <= 8000000L + // Use DIV16 prescaler (giving 250kHz clocke on 4MHz, 500kHz clock on 8MHz), enable TCA timer + TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV16_gc) | (TCA_SPLIT_ENABLE_bm); +#else + // Use DIV64 prescaler (giving 250kHz clock on 16MHz), enable TCA timer + TCA0.SPLIT.CTRLA = (TCA_SPLIT_CLKSEL_DIV64_gc) | (TCA_SPLIT_ENABLE_bm); +#endif + + // TYPE B TIMERS + + // Set up routing (defined in pins_arduino.h) + PORTMUX.TCBROUTEA = 0 +#if defined(TCB0) + | TCB0_PINS +#endif +#if defined(TCB1) + | TCB1_PINS +#endif +#if defined(TCB2) + | TCB2_PINS +#endif +#if defined(TCB3) + | TCB3_PINS +#endif + ; + + // Start with TCB0 + TCB_t *timer_B = (TCB_t *)&TCB0; + +// Find end timer +#if defined(TCB3) + TCB_t *timer_B_end = (TCB_t *)&TCB3; +#elif defined(TCB2) + TCB_t *timer_B_end = (TCB_t *)&TCB2; +#elif defined(TCB1) + TCB_t *timer_B_end = (TCB_t *)&TCB1; +#else + TCB_t *timer_B_end = (TCB_t *)&TCB0; +#endif + + // Timer B Setup loop for TCB[0:end] + do + { + // 8 bit PWM mode, but do not enable output yet, will do in analogWrite() + timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc); + + // Assign 8-bit period + timer_B->CCMPL = PWM_TIMER_PERIOD; + + // default duty 50%, set when output enabled + timer_B->CCMPH = PWM_TIMER_COMPARE; + + // Use TCA clock (250kHz) and enable + // (sync update commented out, might try to synchronize later + timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) + //|(TCB_SYNCUPD_bm) + | (TCB_ENABLE_bm); + + // Increment pointer to next TCB instance + timer_B++; + + // Stop when pointing to TCB3 + } while (timer_B <= timer_B_end); + + // Stuff for synchronizing PWM timers + // // Restart TCA to sync TCBs + // // should not be needed + // TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESTART_gc; + // TCA0.SINGLE.CTRLECLR = TCA_SINGLE_CMD_RESTART_gc; + // + // timer_B = (TCB_t *)&TCB0; + // + // // TCB are sync to TCA, remove setting + // for (uint8_t digitial_pin_timer = (TIMERB0 - TIMERB0); + // digitial_pin_timer < (TIMERB3 - TIMERB0); + // digitial_pin_timer++) + // { + // // disable sync with tca + // timer_B->CTRLA &= ~ (TCB_SYNCUPD_bm); + // + // // Add offset to register + // timer_B++; + // + // } +} diff --git a/megaavr/cores/coreX-corefiles/wiring_analog.c b/megaavr/cores/coreX-corefiles/wiring_analog.c index c5a715b..5305d72 100644 --- a/megaavr/cores/coreX-corefiles/wiring_analog.c +++ b/megaavr/cores/coreX-corefiles/wiring_analog.c @@ -22,95 +22,74 @@ Modified 28 September 2010 by Mark Sproul */ -#include "wiring_private.h" -#include "pins_arduino.h" #include "Arduino.h" - -uint8_t analog_reference = DEFAULT; +#include "pins_arduino.h" +#include "wiring_private.h" void analogReference(uint8_t mode) { - /* Clear relevant settings */ - ADC0.CTRLC &= ~(ADC_REFSEL_gm); - VREF.CTRLA &= ~(VREF_ADC0REFSEL_gm); - - /* If reference NOT using internal reference from VREF */ - if((mode == EXTERNAL) || (mode == VDD)) { - - /* Set reference in ADC peripheral */ - ADC0.CTRLC |= mode; - - /* If reference using internal reference from VREF */ - } else if ( - (mode == INTERNAL0V55) - || (mode == INTERNAL1V1) - || (mode == INTERNAL2V5) - || (mode == INTERNAL4V3) - || (mode == INTERNAL1V5)) { - - /* Set ADC reference to INTERNAL */ - ADC0.CTRLC |= INTERNAL; - - /* Configure VREF ADC0 reference */ - VREF.CTRLA |= (mode << VREF_ADC0REFSEL_gp); - - /* Non-standard values / default */ - } else { - - /* Non valid value will set default */ - /* Set ADC reference to INTERNAL */ - ADC0.CTRLC |= INTERNAL; - - /* Configure VREF ADC0 reference */ - VREF.CTRLA |= (INTERNAL0V55 << VREF_ADC0REFSEL_gp); - } + switch (mode) + { + case EXTERNAL: + case VDD: + ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | mode | ADC_SAMPCAP_bm; // Per datasheet, recommended SAMPCAP=1 at ref > 1v - we don't *KNOW* the external reference will be >1v, but it's probably more likely... + // VREF.CTRLA does not need to be reconfigured, as the voltage references only supply their specified voltage when requested to do so by the ADC. + break; + case INTERNAL0V55: + VREF.CTRLA = VREF.CTRLA & ~(VREF_ADC0REFSEL_gm); // These bits are all 0 for 0.55v reference, so no need to do the mode << VREF_ADC0REFSEL_gp here; + ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm | ADC_SAMPCAP_bm)) | INTERNAL; // Per datasheet, recommended SAMPCAP=0 at ref < 1v + break; + case INTERNAL1V1: + case INTERNAL2V5: + case INTERNAL4V34: + case INTERNAL1V5: + VREF.CTRLA = (VREF.CTRLA & ~(VREF_ADC0REFSEL_gm)) | (mode << VREF_ADC0REFSEL_gp); + ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | INTERNAL | ADC_SAMPCAP_bm; // Per datasheet, recommended SAMPCAP=1 at ref > 1v + break; + default: + ADC0.CTRLC = (ADC0.CTRLC & ~(ADC_REFSEL_gm)) | VDD | ADC_SAMPCAP_bm; // Per datasheet, recommended SAMPCAP=1 at ref > 1v - we don't *KNOW* the external reference will be >1v, but it's probably more likely... + } } int analogRead(uint8_t pin) { - pin = digitalPinToAnalogInput(pin); - if(pin > NUM_ANALOG_INPUTS) return NOT_A_PIN; - - /* Check if TWI is operating on double bonded pin (Master Enable is high - in both Master and Slave mode for bus error detection, so this can - indicate an active state for Wire) */ - if(isDoubleBondedActive(pin)) return 0; - - uint8_t low, high; - -#if defined(analogPinToChannel) - /* If analog pin number != adc0 channel */ -#endif + pin = digitalPinToAnalogInput(pin); + if (pin > 15) + return NOT_A_PIN; #if defined(ADC0) - /* Reference should be already set up */ - /* Select channel */ - ADC0.MUXPOS = (pin << ADC_MUXPOS_gp); - - /* Start conversion */ - ADC0.COMMAND = ADC_STCONV_bm; + /* Reference should be already set up */ + /* Select channel */ + ADC0.MUXPOS = (pin << ADC_MUXPOS_gp); - /* Wait for result ready */ - while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); + /* Start conversion */ + ADC0.COMMAND = ADC_STCONV_bm; - /* Save state */ - uint8_t status = SREG; - cli(); + /* Wait for result ready */ + while (!(ADC0.INTFLAGS & ADC_RESRDY_bm)) + ; - /* Read result */ - low = ADC0.RESL; - high = ADC0.RESH; + /* Combine two bytes */ + return ADC0.RES; - /* Restore state */ - SREG = status; - -#else /* No ADC, return 0 */ - low = 0; - high = 0; +#else /* No ADC, return 0 */ + return 0; #endif +} - /* Combine two bytes */ - return (high << 8) | low; +// analogReadResolution() has two legal values you can pass it, 8 or 10. +// According to the datasheet, you can clock the ADC faster if you set it to 8. +// Like the pinswap functions, if the user passes bogus values, we set it to the default and return false. +uint8_t analogReadResolution(uint8_t res) +{ + if (res==8) + { + ADC0.CTRLA |= ADC_RESSEL_bm; + return 1; + } + // If argument wasn't 8, we'll be putting it to default value either way + ADC0.CTRLA &= ~ADC_RESSEL_bm; + return (res == 10); // Only return true if the value passed was the valid option, 10. } // Right now, PWM output only works on the pins with @@ -119,76 +98,133 @@ int analogRead(uint8_t pin) // to digital output. void analogWrite(uint8_t pin, int val) { + uint8_t bit_pos = digitalPinToBitPosition(pin); + if (bit_pos == NOT_A_PIN) + return; + + // We need to make sure the PWM output is enabled for those pins + // that support it, as we turn it off when digitally reading or + // writing with them. Also, make sure the pin is in output mode + // for consistently with Wiring, which doesn't require a pinMode + // call for the analog output pins. + pinMode(pin, OUTPUT); + + if (val <= 0) + { /* if zero or negative drive digital low */ + digitalWrite(pin, LOW); + } + else if (val >= 255) + { /* if max or greater drive digital high */ + digitalWrite(pin, HIGH); + } + else + { /* handle pwm to generate analog value */ + + /* Get timer */ + uint8_t digital_pin_timer = digitalPinToTimer(pin); + + uint8_t *timer_cmp_out; + TCB_t *timer_B; + + uint8_t savedSREG; + + /* Find out Port and Pin to correctly handle port mux, and timer. */ + switch (digital_pin_timer) + { + case TIMERA0: + /* Split mode, 2x3 8 bit registers. (chapter 19.7) */ + if (bit_pos >= 3) + { + timer_cmp_out = ((uint8_t *)(&TCA0.SPLIT.HCMP0)) + 2 * (bit_pos - 3); + ++bit_pos; /* Upper 3 bits are shifted by 1 */ + } + else + { + /* Calculate correct compare buffer register */ + timer_cmp_out = ((uint8_t *)(&TCA0.SPLIT.LCMP0)) + 2 * bit_pos; + } + + /* Configure duty cycle for correct compare channel */ + savedSREG = SREG; + cli(); + (*timer_cmp_out) = (val); // non-atomic 16-bit write operation + SREG = savedSREG; + + /* Enable output on pin */ + TCA0.SPLIT.CTRLB |= (1 << (TCA_SPLIT_LCMP0EN_bp + bit_pos)); + break; + + case TIMERB0: + case TIMERB1: + case TIMERB2: + case TIMERB3: + + /* Get pointer to timer, TIMERB0 order definition in Arduino.h*/ + //assert (((TIMERB0 - TIMERB3) == 2)); + timer_B = ((TCB_t *)&TCB0 + (digital_pin_timer - TIMERB0)); + + // (16-bit read/write operation are non-atomic and use a temporary register) + savedSREG = SREG; + cli(); + timer_B->CCMPL = timer_B->CCMPL; // Copy CCMPL into temporary register + timer_B->CCMPH = val; // Set CCMPH value + copy temporary register content into CCMPL + SREG = savedSREG; + + /* Enable Timer Output */ + timer_B->CTRLB |= (TCB_CCMPEN_bm); + + break; + + /* If non timer pin, or unknown timer definition. */ + /* do a digital write */ + + case NOT_ON_TIMER: + default: + if (val < 128) + { + digitalWrite(pin, LOW); + } + else + { + digitalWrite(pin, HIGH); + } + break; + } + } +} - uint8_t bit_pos = digitalPinToBitPosition(pin); - if(bit_pos == NOT_A_PIN || isDoubleBondedActive(pin)) return; - - // We need to make sure the PWM output is enabled for those pins - // that support it, as we turn it off when digitally reading or - // writing with them. Also, make sure the pin is in output mode - // for consistently with Wiring, which doesn't require a pinMode - // call for the analog output pins. - pinMode(pin, OUTPUT); - - if(val < 1){ /* if zero or negative drive digital low */ - - digitalWrite(pin, LOW); - - } else if(val > 255){ /* if max or greater drive digital high */ - - digitalWrite(pin, HIGH); - - } else { /* handle pwm to generate analog value */ - - /* Get timer */ - uint8_t digital_pin_timer = digitalPinToTimer(pin); - - uint16_t* timer_cmp_out; - TCB_t *timer_B; - - /* Find out Port and Pin to correctly handle port mux, and timer. */ - switch (digital_pin_timer) { - - case TIMERA0: - /* Calculate correct compare buffer register */ - timer_cmp_out = ((uint16_t*) (&TCA0.SINGLE.CMP0BUF)) + bit_pos; - - /* Configure duty cycle for correct compare channel */ - (*timer_cmp_out) = (val); - - /* Enable output on pin */ - TCA0.SINGLE.CTRLB |= (1 << (TCA_SINGLE_CMP0EN_bp + bit_pos)); - - break; - - case TIMERB0: - case TIMERB1: - case TIMERB2: - case TIMERB3: - - /* Get pointer to timer, TIMERB0 order definition in Arduino.h*/ - //assert (((TIMERB0 - TIMERB3) == 2)); - timer_B = ((TCB_t *)&TCB0 + (digital_pin_timer - TIMERB0)); - - /* set duty cycle */ - timer_B->CCMPH = val; - - /* Enable Timer Output */ - timer_B->CTRLB |= (TCB_CCMPEN_bm); - - break; - - /* If non timer pin, or unknown timer definition. */ - /* do a digital write */ - - case NOT_ON_TIMER: - default: - if (val < 128) { - digitalWrite(pin, LOW); - } else { - digitalWrite(pin, HIGH); - } - break; - } - } -} \ No newline at end of file +// Set PWM repeat frequency for all PWM outputs with +// hardware support. +// The argument is the desired frequency in kHz. A +// best effort will be made to find something that matches. +// +void analogWriteFrequency(uint8_t kHz) +{ + static const byte index2setting[] = { +#if F_CPU > 1000000L +#if F_CPU > 2000000L +#if F_CPU > 4000000L +#if F_CPU > 8000000L + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV64_gc, // ~1 kHz PWM, ~250kHz clock +#endif + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV16_gc, // ~2 kHz is not possible, use 4 +#endif + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV16_gc, // ~4 kHz PWM, ~1MHz clock +#endif + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV8_gc, // ~8 kHz PWM, ~2MHz clock +#endif + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV4_gc, // ~16 kHz PWM, ~4MHz clock + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV2_gc, // ~32 kHz PWM, ~8MHz clock + TCA_SPLIT_ENABLE_bm | TCA_SPLIT_CLKSEL_DIV1_gc // ~64 kHz PWM, ~16MHz clock + }; + uint8_t index = 0; + + while (kHz > 1) + { // find approximate match + kHz >>= 1; + if (++index >= sizeof(index2setting) - 1) break; + } + TCA0.SPLIT.CTRLA = index2setting[index]; + + // note that this setting also influences Tone.cpp +} diff --git a/megaavr/cores/coreX-corefiles/wiring_digital.c b/megaavr/cores/coreX-corefiles/wiring_digital.c index 0d51d57..3f07a6e 100644 --- a/megaavr/cores/coreX-corefiles/wiring_digital.c +++ b/megaavr/cores/coreX-corefiles/wiring_digital.c @@ -26,52 +26,52 @@ #include "wiring_private.h" #include "pins_arduino.h" -__attribute__((weak)) bool isDoubleBondedActive(uint8_t pin __attribute__((unused))) { - return false; -}; - -void pinMode(uint8_t pin, PinMode mode) +void pinMode(uint8_t pin, uint8_t mode) { - uint8_t bit_mask = digitalPinToBitMask(pin); - - if ((bit_mask == NOT_A_PIN) || (mode > INPUT_PULLUP) || isDoubleBondedActive(pin)) return; - - PORT_t* port = digitalPinToPortStruct(pin); - if(port == NULL) return; - - if(mode == OUTPUT){ - - /* Configure direction as output */ - port->DIRSET = bit_mask; - - } else { /* mode == INPUT or INPUT_PULLUP */ - - uint8_t bit_pos = digitalPinToBitPosition(pin); - /* Calculate where pin control register is */ - volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); - - /* Save state */ - uint8_t status = SREG; - cli(); - - /* Configure direction as input */ - port->DIRCLR = bit_mask; - - /* Configure pull-up resistor */ - if(mode == INPUT_PULLUP){ - - /* Enable pull-up */ - *pin_ctrl_reg |= PORT_PULLUPEN_bm; - - } else { /* mode == INPUT (no pullup) */ - - /* Disable pull-up */ - *pin_ctrl_reg &= ~(PORT_PULLUPEN_bm); - } - - /* Restore state */ - SREG = status; - } + uint8_t bit_mask = digitalPinToBitMask(pin); + + if ((bit_mask == NOT_A_PIN) || (mode > INPUT_PULLUP)) + return; + + PORT_t *port = digitalPinToPortStruct(pin); + if (port == NULL) + return; + + if (mode == OUTPUT) + { + /* Configure direction as output */ + port->DIRSET = bit_mask; + } + else + { /* mode == INPUT or INPUT_PULLUP */ + + uint8_t bit_pos = digitalPinToBitPosition(pin); + /* Calculate where pin control register is */ + volatile uint8_t *pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); + + /* Save state */ + uint8_t status = SREG; + cli(); + + /* Configure direction as input */ + port->DIRCLR = bit_mask; + + /* Configure pull-up resistor */ + if (mode == INPUT_PULLUP) + { + /* Enable pull-up */ + *pin_ctrl_reg |= PORT_PULLUPEN_bm; + } + else + { /* mode == INPUT (no pullup) */ + + /* Disable pull-up */ + *pin_ctrl_reg &= ~(PORT_PULLUPEN_bm); + } + + /* Restore state */ + SREG = status; + } } // Forcing this inline keeps the callers from having to push their own stuff @@ -79,7 +79,8 @@ void pinMode(uint8_t pin, PinMode mode) // user than calling. (It will take more bytes on the 168.) // // But shouldn't this be moved into pinMode? Seems silly to check and do on -// each digitalread or write. +// each digitalread or write. One issue that then needs to be fixed is that +// current implementation on analogWrite() depends on this behaviour. // // Mark Sproul: // - Removed inline. Save 170 bytes on atmega1280 @@ -90,125 +91,176 @@ void pinMode(uint8_t pin, PinMode mode) //static inline void turnOffPWM(uint8_t timer) static void turnOffPWM(uint8_t pin) { - /* Actually turn off compare channel, not the timer */ - - /* Get pin's timer */ - uint8_t timer = digitalPinToTimer(pin); - if(timer == NOT_ON_TIMER) return; + /* Actually turn off compare channel, not the timer */ - uint8_t bit_pos; - TCB_t *timerB; + /* Get pin's timer */ + uint8_t timer = digitalPinToTimer(pin); + if (timer == NOT_ON_TIMER) + return; - switch (timer) { + uint8_t bit_pos; + TCB_t *timerB; - /* TCA0 */ - case TIMERA0: - /* Bit position will give output channel */ - bit_pos = digitalPinToBitPosition(pin); + switch (timer) + { + /* TCA0 */ + case TIMERA0: + /* Bit position will give output channel */ + bit_pos = digitalPinToBitPosition(pin); - /* Disable corresponding channel */ - TCA0.SINGLE.CTRLB &= ~(1 << (TCA_SINGLE_CMP0EN_bp + bit_pos)); + /* Disable corresponding channel */ + if (bit_pos >= 3) ++bit_pos; /* Upper 3 bits are shifted by 1 */ + TCA0.SPLIT.CTRLB &= ~(1 << (TCA_SPLIT_LCMP0EN_bp + bit_pos)); - break; + break; - /* TCB - only one output */ - case TIMERB0: - case TIMERB1: - case TIMERB2: - case TIMERB3: + /* TCB - only one output */ + case TIMERB0: + case TIMERB1: + case TIMERB2: + case TIMERB3: - timerB = (TCB_t *)&TCB0 + (timer - TIMERB0); + timerB = (TCB_t *)&TCB0 + (timer - TIMERB0); - /* Disable TCB compare channel */ - timerB->CTRLB &= ~(TCB_CCMPEN_bm); + /* Disable TCB compare channel */ + timerB->CTRLB &= ~(TCB_CCMPEN_bm); - break; - default: - break; - } + break; + default: + break; + } } -void digitalWrite(uint8_t pin, PinStatus val) +void digitalWrite(uint8_t pin, uint8_t val) { - /* Get bit mask for pin */ - uint8_t bit_mask = digitalPinToBitMask(pin); - if(bit_mask == NOT_A_PIN || isDoubleBondedActive(pin)) return; - - /* Turn off PWM if applicable */ - - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - turnOffPWM(pin); - - /* Assuming the direction is already output !! */ - - /* Get port */ - PORT_t *port = digitalPinToPortStruct(pin); - - /* Output direction */ - if(port->DIR & bit_mask){ - - /* Set output to value */ - if (val == LOW) { /* If LOW */ - port->OUTCLR = bit_mask; + /* Get bit mask for pin */ + uint8_t bit_mask = digitalPinToBitMask(pin); + if (bit_mask == NOT_A_PIN) + return; + + /* Turn off PWM if applicable */ + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + turnOffPWM(pin); + + /* Assuming the direction is already output !! */ + + /* Get port */ + PORT_t *port = digitalPinToPortStruct(pin); + + /* Output direction */ + if (port->DIR & bit_mask) + { + /* Set output to value */ + if (val == LOW) + { /* If LOW */ + port->OUTCLR = bit_mask; + } + else if (val == CHANGE) + { /* If TOGGLE */ + port->OUTTGL = bit_mask; + /* If HIGH OR > TOGGLE */ + } + else + { + port->OUTSET = bit_mask; + } + + /* Input direction */ + } + else + { + /* Old implementation has side effect when pin set as input - + pull up is enabled if this function is called. + Should we purposely implement this side effect? + */ + + /* Get bit position for getting pin ctrl reg */ + uint8_t bit_pos = digitalPinToBitPosition(pin); + + /* Calculate where pin control register is */ + volatile uint8_t *pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); + + /* Save system status and disable interrupts */ + uint8_t status = SREG; + cli(); + + if (val == LOW) + { + /* Disable pullup */ + *pin_ctrl_reg &= ~PORT_PULLUPEN_bm; + } + else + { + /* Enable pull-up */ + *pin_ctrl_reg |= PORT_PULLUPEN_bm; + } + + /* Restore system status */ + SREG = status; + } +} - } else if (val == CHANGE) { /* If TOGGLE */ - port->OUTTGL = bit_mask; - /* If HIGH OR > TOGGLE */ - } else { - port->OUTSET = bit_mask; - } +inline __attribute__((always_inline)) void digitalWriteFast(uint8_t pin, uint8_t val) +{ + // Make sure pin is constant and know at compile time + check_constant_pin(pin); + + // Mega-0, Tiny-1 style IOPORTs + // Assumes VPORTs exist starting at 0 for each PORT structure + uint8_t mask = 1 << digital_pin_to_bit_position[pin]; + uint8_t port = digital_pin_to_port[pin]; + VPORT_t *vport; + + // Write pin value from VPORTx.OUT register + vport = (VPORT_t *)(port * 4); + + if (val == HIGH) + vport->OUT |= mask; + else if (val == LOW) + vport->OUT &= ~mask; + else // CHANGE + vport->IN = mask; +} - /* Input direction */ - } else { - /* Old implementation has side effect when pin set as input - - pull up is enabled if this function is called. - Should we purposely implement this side effect? - */ +uint8_t digitalRead(uint8_t pin) +{ + /* Get bit mask and check valid pin */ + uint8_t bit_mask = digitalPinToBitMask(pin); + if (bit_mask == NOT_A_PIN) + return LOW; - /* Get bit position for getting pin ctrl reg */ - uint8_t bit_pos = digitalPinToBitPosition(pin); + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + turnOffPWM(pin); - /* Calculate where pin control register is */ - volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(port, bit_pos); + /* Get port and check valid port */ + PORT_t *port = digitalPinToPortStruct(pin); - /* Save system status and disable interrupts */ - uint8_t status = SREG; - cli(); + /* Read pin value from PORTx.IN register */ + if (port->IN & bit_mask) + return HIGH; + else + return LOW; - if(val == LOW){ - /* Disable pullup */ - *pin_ctrl_reg &= ~PORT_PULLUPEN_bm; + return LOW; +} - } else { - /* Enable pull-up */ - *pin_ctrl_reg |= PORT_PULLUPEN_bm; - } +inline __attribute__((always_inline)) uint8_t digitalReadFast(uint8_t pin) +{ + // Make sure pin is constant and know at compile time + check_constant_pin(pin); - /* Restore system status */ - SREG = status; - } + // Mega-0, Tiny-1 style IOPORTs + // Assumes VPORTs exist starting at 0 for each PORT structure + uint8_t mask = 1 << digital_pin_to_bit_position[pin]; + uint8_t port = digital_pin_to_port[pin]; + VPORT_t *vport; -} + // Old style port logic is a small integer 0 for PORTA, 1 for PORTB etc. + vport = (VPORT_t *)(port * 4); -PinStatus digitalRead(uint8_t pin) -{ - /* Get bit mask and check valid pin */ - uint8_t bit_mask = digitalPinToBitMask(pin); - if(bit_mask == NOT_A_PIN || isDoubleBondedActive(pin)) return LOW; - - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - turnOffPWM(pin); - - /* Get port and check valid port */ - PORT_t *port = digitalPinToPortStruct(pin); - - /* Read pin value from PORTx.IN register */ - if(port->IN & bit_mask){ - return HIGH; - } else { - return LOW; - } - return LOW; + // Read pin value from VPORTx.IN register + return !!(vport->IN & mask); } diff --git a/megaavr/cores/coreX-corefiles/wiring_private.h b/megaavr/cores/coreX-corefiles/wiring_private.h index 9597ed8..a38e94e 100644 --- a/megaavr/cores/coreX-corefiles/wiring_private.h +++ b/megaavr/cores/coreX-corefiles/wiring_private.h @@ -23,20 +23,21 @@ #ifndef WiringPrivate_h #define WiringPrivate_h -#include #include -#include +#include #include +#include #include "Arduino.h" #ifdef __cplusplus -extern "C"{ +extern "C" +{ #endif -uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops); + uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops); -typedef void (*voidFuncPtr)(void); + typedef void (*voidFuncPtr)(void); #ifdef __cplusplus } // extern "C" diff --git a/megaavr/cores/coreX-corefiles/wiring_pulse.c b/megaavr/cores/coreX-corefiles/wiring_pulse.c index 3d75cd8..c4fd7e4 100644 --- a/megaavr/cores/coreX-corefiles/wiring_pulse.c +++ b/megaavr/cores/coreX-corefiles/wiring_pulse.c @@ -20,8 +20,8 @@ Boston, MA 02111-1307 USA */ -#include "wiring_private.h" #include "pins_arduino.h" +#include "wiring_private.h" /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds @@ -32,24 +32,24 @@ */ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { - // cache the port and bit of the pin in order to speed up the - // pulse width measuring loop and achieve finer resolution. calling - // digitalRead() instead yields much coarser resolution. - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - uint8_t stateMask = (state ? bit : 0); + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t stateMask = (state ? bit : 0); - // convert the timeout from microseconds to a number of times through - // the initial loop; it takes approximately 16 clock cycles per iteration - unsigned long maxloops = microsecondsToClockCycles(timeout)/12; + // convert the timeout from microseconds to a number of times through + // the initial loop; it takes approximately 16 clock cycles per iteration + unsigned long maxloops = microsecondsToClockCycles(timeout) / 12; - unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops); + unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops); - // prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out - if (width) - return clockCyclesToMicroseconds(width * 16 + 16); - else - return 0; + // prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out + if (width) + return clockCyclesToMicroseconds(width * 16 + 16); + else + return 0; } /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH @@ -62,32 +62,35 @@ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) */ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) { - // cache the port and bit of the pin in order to speed up the - // pulse width measuring loop and achieve finer resolution. calling - // digitalRead() instead yields much coarser resolution. - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - uint8_t stateMask = (state ? bit : 0); + // cache the port and bit of the pin in order to speed up the + // pulse width measuring loop and achieve finer resolution. calling + // digitalRead() instead yields much coarser resolution. + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + uint8_t stateMask = (state ? bit : 0); - unsigned long startMicros = micros(); + unsigned long startMicros = micros(); - // wait for any previous pulse to end - while ((*portInputRegister(port) & bit) == stateMask) { - if (micros() - startMicros > timeout) - return 0; - } + // wait for any previous pulse to end + while ((*portInputRegister(port) & bit) == stateMask) + { + if (micros() - startMicros > timeout) + return 0; + } - // wait for the pulse to start - while ((*portInputRegister(port) & bit) != stateMask) { - if (micros() - startMicros > timeout) - return 0; - } + // wait for the pulse to start + while ((*portInputRegister(port) & bit) != stateMask) + { + if (micros() - startMicros > timeout) + return 0; + } - unsigned long start = micros(); - // wait for the pulse to stop - while ((*portInputRegister(port) & bit) == stateMask) { - if (micros() - startMicros > timeout) - return 0; - } - return micros() - start; + unsigned long start = micros(); + // wait for the pulse to stop + while ((*portInputRegister(port) & bit) == stateMask) + { + if (micros() - startMicros > timeout) + return 0; + } + return micros() - start; } \ No newline at end of file diff --git a/megaavr/cores/coreX-corefiles/wiring_shift.c b/megaavr/cores/coreX-corefiles/wiring_shift.c index 0848df9..6819e7e 100644 --- a/megaavr/cores/coreX-corefiles/wiring_shift.c +++ b/megaavr/cores/coreX-corefiles/wiring_shift.c @@ -20,34 +20,37 @@ Boston, MA 02111-1307 USA */ -#include - -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, BitOrder bitOrder) { - uint8_t value = 0; - uint8_t i; - - for (i = 0; i < 8; ++i) { - digitalWrite(clockPin, HIGH); - if (bitOrder == LSBFIRST) - value |= digitalRead(dataPin) << i; - else - value |= digitalRead(dataPin) << (7 - i); - digitalWrite(clockPin, LOW); - } - return value; +#include "Arduino.h" + +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) +{ + uint8_t value = 0; + uint8_t i; + + for (i = 0; i < 8; ++i) + { + digitalWrite(clockPin, HIGH); + if (bitOrder == LSBFIRST) + value |= digitalRead(dataPin) << i; + else + value |= digitalRead(dataPin) << (7 - i); + digitalWrite(clockPin, LOW); + } + return value; } -void shiftOut(uint8_t dataPin, uint8_t clockPin, BitOrder bitOrder, uint8_t val) +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) { - uint8_t i; - - for (i = 0; i < 8; i++) { - if (bitOrder == LSBFIRST) - digitalWrite(dataPin, !!(val & (1 << i))); - else - digitalWrite(dataPin, !!(val & (1 << (7 - i)))); - - digitalWrite(clockPin, HIGH); - digitalWrite(clockPin, LOW); - } + uint8_t i; + + for (i = 0; i < 8; i++) + { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + digitalWrite(clockPin, HIGH); + digitalWrite(clockPin, LOW); + } } diff --git a/megaavr/libraries/Comparator/README.md b/megaavr/libraries/Comparator/README.md new file mode 100644 index 0000000..4947834 --- /dev/null +++ b/megaavr/libraries/Comparator/README.md @@ -0,0 +1,182 @@ +# Comparator +A library for interfacing with the analog comparator peripheral in the megaAVR-0 series MCUs. +Developed by [MCUdude](https://github.com/MCUdude/). +The megaAVR-0 has one comparator where four positive and three negative pins are available for use. An alternative for the negative pin is to use an internally generated reference voltage instead. +More useful information about the analog comparator can be found in the [Microchip Application Note TB3211](http://ww1.microchip.com/downloads/en/AppNotes/TB3211-Getting-Started-with-AC-90003211A.pdf) and in the [megaAVR-0 family data sheet](http://ww1.microchip.com/downloads/en/DeviceDoc/megaAVR0-series-Family-Data-Sheet-DS40002015B.pdf). + + +## Comparator +Class for interfacing with the built-in comparator. Use the predefined objects `Comparator` or `Comparator0`. + + +### input_p +Variable for setting what input pin the positive input of the comparator should be connected to +Accepted values: +``` c++ +comparator::in_p::in0; // Use positive input pin 0 (PD2) as input +comparator::in_p::in1; // Use positive input pin 1 (PD4) as input +comparator::in_p::in2; // Use positive input pin 2 (PD6) as input +comparator::in_p::in3; // Use positive input pin 3 (PD1) as input +``` + +##### Usage +``` c++ +Comparator.input_p = comparator::in_p::in0; // Connect positive input pin 0 to the positive pin of the comparator +``` + +##### Default state +`Comparator.input_p` defaults to `comparator::in_p::in0` if not specified in the user program. + + +### input_n +Variable for setting what input pin the negative input of the comparator should be connected to +Accepted values: +``` c++ +comparator::in_n::in0; // Use positive input pin 0 (PD3) as input +comparator::in_n::in1; // Use positive input pin 1 (PD5) as input +comparator::in_n::in2; // Use positive input pin 2 (PD7) as input +comparator::in_n::dacref; // Use DACREF as input +``` + +##### Usage +``` c++ +Comparator.input_n = comparator::in_n::in0; // Connect negative input pin 0 to the negative pin of the comparator +``` + +##### Default state +`Comparator.input_n` defaults to `comparator::in_n::in0` if not specified in the user program. + + +### reference +Variable for setting what reference voltage the DACREF should be derived from. This voltage is internally generated. +Accepted values: +``` c++ +comparator::ref::disable; // Do not use any reference +comparator::ref::vref_0v55; // 0.55V internal voltage +comparator::ref::vref_1v1; // 1.1V internal voltage +comparator::ref::vref_1v5; // 1.5V internal voltage +comparator::ref::vref_2v5; // 2.5V internal voltage +comparator::ref::vref_4v3; // 4.3V internal voltage +comparator::ref::vref_avcc; // Use voltage on AVCC pin +``` + +##### Usage +``` c++ +Comparator.reference = comparator::ref::vref_2v5; // Use the internal 2.5V reference for the DACREF +``` + +##### Default state +`Comparator.reference` defaults to `comparator::ref::disable` if not specified in the user program. + + +### dacref +Variable for setting the DACREF value. This voltage can be selected as the input for the negative side of the comparator. +This is the formula for the DACREF output voltage: + + + +##### Usage +``` c++ +Comparator.dacref = 127; // Divide the reference voltage by two +``` + +##### Default state +`Comparator.dacref` defaults to `255` if not specified in the user program. + + +### hysteresis +Variable for setting the comparator input hysteresis. Useful for eliminating "bouncing". +Accepted values: +``` c++ +comparator::hyst::disable; // No hysteresis +comparator::hyst::small; // 10mV hysteresis (±5mV) +comparator::hyst::medium; // 25mV hysteresis (±12.5mV) +comparator::hyst::large; // 50mV hysteresis (±25mV) +``` + +##### Usage +``` c++ +Comparator.hysteresis = comparator::hyst::large; // Use 50V hysteresis +``` + +##### Default state +`Comparator.hysteresis` defaults to `comparator::hyst::disable` if not specified in the user program. + + +### output +Variable for setting the comparator output, internally and/or externally. +Accepted values: +``` c++ +comparator::out::disable; // No output pin, signal not inverted internally +comparator::out::disable_invert; // No output pin, signal inverted internally +comparator::out::enable; // Enable output pin (PA7), signal not inverted internally +comparator::out::invert; // Enable output pin (PA7), signal inverted internally +comparator::out::enable_invert; // Identical to out::invert +``` + +##### Usage +``` c++ +Comparator.output = comparator::out::enable; // Enable output pin (PA7) +``` + +##### Default state +`Comparator.output` defaults to `comparator::out::disable` if not specified in the user program. + + +## init() +Method for initializing the comparator. + +##### Usage +```c++ +Comparator.init(); // Initialize comparator +``` + + +## start() +Method for starting the analog comparator. +##### Usage +```c++ +Comparator.start(); // Start comparator +``` + + +## stop() +Method for stopping the analog comparator. + +##### Usage +```c++ +Comparator.stop(); // Stop comparator +``` + + +## read() +Reads the state of the analog comparator output. Works also when the physical output pin is disabled. + +##### Usage +```c++ +bool comp_state = Comparator.read(); // Read comparator +``` + + +## attachInterrupt() +Method for enabling analog comparator interrupt. The interrupt will trigger when the the comparator output changes. +Valid arguments for the third parameters are `RISING`, `FALLING` and `CHANGE`. + +##### Usage +```c++ +Comparator.attachInterrupt(blinkLED, RISING); // Run the blinkLED function when the comparator output goes high + +void blinkLED() +{ + digitalWrite(myLedPin, CHANGE); +} +``` + + +## detachInterrupt() +Method for disabling analog comparator interrupt. + +##### Usage +```c++ +Comparator.detachInterrupt(); // Disable interrupt +``` diff --git a/megaavr/libraries/Comparator/examples/Hysteresis/Hysteresis.ino b/megaavr/libraries/Comparator/examples/Hysteresis/Hysteresis.ino new file mode 100644 index 0000000..9fbb4d2 --- /dev/null +++ b/megaavr/libraries/Comparator/examples/Hysteresis/Hysteresis.ino @@ -0,0 +1,38 @@ +/***********************************************************************| +| megaAVR analog comparator library | +| | +| Hysteresis.ino | +| | +| A library for interfacing with the megaAVR analog comparator. | +| Developed in 2019 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we use the negative and positive input 0 of the | +| comparator. The output goes high if the positive input is higher than | +| the negative input, and low otherwise. We'll also use the built-in | +| hysteresis functionality to prevent false spikes. | +| | +| See Microchip's application note TB3211 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Configure relevant comparator parameters + Comparator.input_p = comparator::in_p::in0; // Use positive input 0 (PD2) + Comparator.input_n = comparator::in_n::in0; // Use negative input 0 (PD3) + Comparator.hysteresis = comparator::hyst::large; // Use a 50mV hysteresis + Comparator.output = comparator::out::enable; // Enable output on digital pin 7 (PA7) + + // Initialize comparator + Comparator.init(); + + // Start comparator + Comparator.start(); +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Comparator/examples/Internal_reference/Internal_reference.ino b/megaavr/libraries/Comparator/examples/Internal_reference/Internal_reference.ino new file mode 100644 index 0000000..1ff6485 --- /dev/null +++ b/megaavr/libraries/Comparator/examples/Internal_reference/Internal_reference.ino @@ -0,0 +1,43 @@ +/***********************************************************************| +| megaAVR analog comparator library | +| | +| Internal_reference.ino | +| | +| A library for interfacing with the megaAVR analog comparator. | +| Developed in 2019 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we use an internal reference voltage instead of an | +| external one on the negative pin. This eliminates the need for an | +| external voltage divider to generate a reference. Note that the | +| internal reference requires a stable voltage to function properly. | +| | +| This is the formula for the generated voltage: | +| Vdacref = (DACREF / 256) * Vref | +| | +| See Microchip's application note TB3211 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Configure relevant comparator parameters + Comparator.input_p = comparator::in_p::in0; // Use positive input 0 (PD2) + Comparator.input_n = comparator::in_n::dacref; // Connect the negative pin to the DACREF voltage + Comparator.reference = comparator::ref::vref_2v5; // Set the DACREF voltage to 2.5V + Comparator.dacref = 127; // Gives us 1.24V -> (127 / 256) * 2.5V = 1.24V + Comparator.hysteresis = comparator::hyst::large; // Use a 50mV hysteresis + Comparator.output = comparator::out::enable; // Enable output on digital pin 7 (PA7) + + // Initialize comparator + Comparator.init(); + + // Start comparator + Comparator.start(); +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Comparator/examples/Interrupt/Interrupt.ino b/megaavr/libraries/Comparator/examples/Interrupt/Interrupt.ino new file mode 100644 index 0000000..2677f2d --- /dev/null +++ b/megaavr/libraries/Comparator/examples/Interrupt/Interrupt.ino @@ -0,0 +1,57 @@ +/***********************************************************************| +| megaAVR analog comparator library | +| | +| Interrupt.ino | +| | +| A library for interfacing with the megaAVR analog comparator. | +| Developed in 2019 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we use an internal reference voltage instead of an | +| external one on the negative pin. This eliminates the need for an | +| external voltage divider to generate a reference. Note that the | +| internal reference requires a stable voltage to function properly. | +| Instead of using a physical output pin we're instead triggering an | +| interrupt that will run a user defined function. | +| | +| This is the formula for the generated voltage: | +| Vdacref = (DACREF / 256) * Vref | +| | +| See Microchip's application note TB3211 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Configure serial port + Serial2.begin(9600); + + // Configure relevant comparator parameters + Comparator.input_p = comparator::in_p::in0; // Use positive input 0 (PD2) + Comparator.input_n = comparator::in_n::dacref; // Connect the negative pin to the DACREF voltage + Comparator.reference = comparator::ref::vref_2v5; // Set the DACREF voltage to 2.5V + Comparator.dacref = 255; // Gives us 2.5V -> (255 / 256) * 2.5V = 2.5V + Comparator.hysteresis = comparator::hyst::large; // Use a 50mV hysteresis + Comparator.output = comparator::out::disable; // Use interrupt trigger instead of output pin + + // Initialize comparator + Comparator.init(); + + // Set interrupt (supports RISING, FALLING and CHANGE) + Comparator.attachInterrupt(interruptFunction, RISING); + + // Start comparator + Comparator.start(); +} + +void loop() +{ + +} + +// This function runs when an interrupt occurs +void interruptFunction() +{ + Serial2.println("Output of analog comparator went high!"); +} diff --git a/megaavr/libraries/Comparator/examples/Simple_comparator/Simple_comparator.ino b/megaavr/libraries/Comparator/examples/Simple_comparator/Simple_comparator.ino new file mode 100644 index 0000000..29278eb --- /dev/null +++ b/megaavr/libraries/Comparator/examples/Simple_comparator/Simple_comparator.ino @@ -0,0 +1,36 @@ +/***********************************************************************| +| megaAVR analog comparator library | +| | +| Simple_comparator.ino | +| | +| A library for interfacing with the megaAVR analog comparator. | +| Developed in 2019 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we use the negative and positive input 0 of the | +| comparator. The output goes high if the positive input is higher than | +| the negative input, and low otherwise. | +| | +| See Microchip's application note TB3211 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Configure relevant comparator parameters + Comparator.input_p = comparator::in_p::in0; // Use positive input 0 (PD2) + Comparator.input_n = comparator::in_n::in0; // Use negative input 0 (PD3) + Comparator.output = comparator::out::enable; // Enable output on digital pin 7 (PA7) + + // Initialize comparator + Comparator.init(); + + // Start comparator + Comparator.start(); +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Comparator/keywords.txt b/megaavr/libraries/Comparator/keywords.txt new file mode 100644 index 0000000..9f324e2 --- /dev/null +++ b/megaavr/libraries/Comparator/keywords.txt @@ -0,0 +1,38 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +start KEYWORD2 +stop KEYWORD2 +init KEYWORD2 +attachInterrupt KEYWORD2 +detachInterrupt KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Comparator KEYWORD2 +Comparator0 KEYWORD2 +Comparator1 KEYWORD2 +Comparator2 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +comparator LITERAL1 +out LITERAL1 +hyst LITERAL1 +in_p LITERAL1 +in_n LITERAL1 +ref LITERAL1 diff --git a/megaavr/libraries/Comparator/library.properties b/megaavr/libraries/Comparator/library.properties new file mode 100644 index 0000000..858879d --- /dev/null +++ b/megaavr/libraries/Comparator/library.properties @@ -0,0 +1,10 @@ +name=Comparator +version=1.1.1 +author=MCUdude +maintainer=MCUdude +sentence=A library for interfacing with the built-in analog comparator +paragraph= +category=Signal Input/Output +url=https://github.com/MCUdude/MegaCoreX +dot_a_linkage=true +architectures=megaavr diff --git a/megaavr/libraries/Comparator/src/Comparator.cpp b/megaavr/libraries/Comparator/src/Comparator.cpp new file mode 100644 index 0000000..eb5326b --- /dev/null +++ b/megaavr/libraries/Comparator/src/Comparator.cpp @@ -0,0 +1,68 @@ +#include "Comparator.h" + +AnalogComparator Comparator(0, AC0); + +AnalogComparator::AnalogComparator(const uint8_t comp_number, AC_t& ac) : comparator_number(comp_number), AC(ac) +{ +} + +void AnalogComparator::init() +{ + // Set voltage reference + if(reference != comparator::ref::disable) + { + VREF.CTRLA = (VREF.CTRLA & ~VREF_AC0REFSEL_AVDD_gc) | reference; + VREF.CTRLB = VREF_AC0REFEN_bm; + } + else + VREF.CTRLB &= ~VREF_AC0REFEN_bm; + + // Set DACREF + AC.DACREF = dacref; + + // Set hysteresis and output pin state + AC.CTRLA = (AC.CTRLA & ~AC_HYSMODE_gm) | hysteresis | (output & AC_OUTEN_bm); + + // Clear input pins + if(input_p == comparator::in_p::in0) + PORTD.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; + else if(input_p == comparator::in_p::in1) + PORTD.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc; + else if(input_p == comparator::in_p::in2) + PORTD.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; + else if(input_p == comparator::in_p::in3) + PORTD.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc; + if(input_n == comparator::in_n::in0) + PORTD.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc; + else if(input_n == comparator::in_n::in1) + PORTD.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc; + else if(input_n == comparator::in_n::in2) + PORTD.PIN7CTRL = PORT_ISC_INPUT_DISABLE_gc; + + // Set positive and negative pins, invert output if defined by the user + AC.MUXCTRLA = (AC.MUXCTRLA & ~0x1B) | (input_p << 3) | input_n | (output & AC_INVERT_bm); + + // Set output if enabled + if(output & AC_OUTEN_bm) + PORTA.DIRSET = PIN7_bm; + else + PORTA.DIRCLR = PIN7_bm; +} + +void AnalogComparator::start(bool state) +{ + if(state) + AC.CTRLA |= AC_ENABLE_bm; + else + AC.CTRLA &= ~AC_ENABLE_bm; +} + +void AnalogComparator::stop() +{ + start(false); +} + +bool AnalogComparator::read() +{ + return !!(AC0.STATUS & AC_STATE_bm); +} diff --git a/megaavr/libraries/Comparator/src/Comparator.h b/megaavr/libraries/Comparator/src/Comparator.h new file mode 100644 index 0000000..699eec6 --- /dev/null +++ b/megaavr/libraries/Comparator/src/Comparator.h @@ -0,0 +1,115 @@ +#ifndef COMPARATOR_h +#define COMPARATOR_h + +#include + +namespace comparator +{ + namespace out + { + enum output_t : uint8_t + { + disable = 0x00, + disable_invert = 0x80, + enable = 0x40, + invert = 0xC0, + enable_invert = 0xC0, + }; + }; + + namespace hyst + { + enum hysteresis_t : uint8_t + { + disable = 0x00, // No hysteresis + small = 0x02, // 10 mV + medium = 0x04, // 25 mV + large = 0x06, // 50 mV + }; + }; + + namespace in_p + { + enum inputP_t : uint8_t + { + in0 = 0x00, + in1 = 0x01, + in2 = 0x02, + in3 = 0x03, + }; + }; + + namespace in_n + { + enum inputN_t : uint8_t + { + in0 = 0x00, + in1 = 0x01, + in2 = 0x02, + dacref = 0x03, + }; + }; + + namespace ref + { + enum reference_t : uint8_t + { + vref_0v55 = 0x00, // 0.55V + vref_1v1 = 0x01, // 1.1V + vref_1v5 = 0x04, // 1.5V + vref_2v5 = 0x02, // 2.5V + vref_4v3 = 0x03, // 4.3V + vref_avcc = 0x07, // Vcc + disable = 0x08, + }; + }; +}; + +// Legacy definitions +namespace out { using namespace comparator::out; }; +namespace hyst { using namespace comparator::hyst; }; +namespace in_p { using namespace comparator::in_p; }; +namespace in_n { using namespace comparator::in_n; }; +namespace ref { using namespace comparator::ref; }; + +class AnalogComparator +{ + public: + AnalogComparator(const uint8_t comparator_number, AC_t& ac); + void init(); + void start(bool state = true); + void stop(); + bool read(); + void attachInterrupt(voidFuncPtr callback, uint8_t mode); + void detachInterrupt(); + + comparator::out::output_t output = comparator::out::disable; + comparator::hyst::hysteresis_t hysteresis = comparator::hyst::disable; + comparator::in_p::inputP_t input_p = comparator::in_p::in0; + comparator::in_n::inputN_t input_n = comparator::in_n::in0; + comparator::ref::reference_t reference = comparator::ref::disable; + uint8_t dacref = 0xff; + + private: + const uint8_t comparator_number; + AC_t& AC; + bool enable = false; +}; + +// Array for storing ISR function pointers +#if defined(AC2_AC_vect) +static volatile voidFuncPtr intFuncAC[3]; +#elif defined(AC1_AC_vect) +static volatile voidFuncPtr intFuncAC[2]; +#elif defined(AC0_AC_vect) +static volatile voidFuncPtr intFuncAC[1]; +#else +#error target does not have an analog comparator! +#endif + +#if defined(AC0_AC_vect) +extern AnalogComparator Comparator0; +#define Comparator Comparator0 +#endif + +#endif diff --git a/megaavr/libraries/Comparator/src/Comparator_ISR.cpp b/megaavr/libraries/Comparator/src/Comparator_ISR.cpp new file mode 100644 index 0000000..21af638 --- /dev/null +++ b/megaavr/libraries/Comparator/src/Comparator_ISR.cpp @@ -0,0 +1,71 @@ +// This file will be optimized away if attachInterrupt or detachInterrupt isn't used in +// user program, thanks to dot_a_linkage set in library.properties + +#include "Comparator.h" + +void AnalogComparator::attachInterrupt(void (*userFunc)(void), uint8_t mode) +{ + AC_INTMODE_t intmode; + switch (mode) + { + // Set RISING, FALLING or CHANGE interrupt trigger for the comparator output + case RISING: + intmode = AC_INTMODE_POSEDGE_gc; + break; + case FALLING: + intmode = AC_INTMODE_NEGEDGE_gc; + break; + case CHANGE: + intmode = AC_INTMODE_BOTHEDGE_gc; + break; + default: + // Only RISING, FALLING and CHANGE is supported + return; + } + AC.CTRLA = (AC.CTRLA & ~AC_INTMODE_POSEDGE_gc) | intmode; + + // Store function pointer + intFuncAC[comparator_number] = userFunc; + + // Enable interrupt + AC.INTCTRL |= AC_CMP_bm; +} + +void AnalogComparator::detachInterrupt() +{ + // Disable interrupt + AC.INTCTRL &= ~AC_CMP_bm; +} + +#ifdef AC0_AC_vect +ISR(AC0_AC_vect) +{ + // Run user function + intFuncAC[0](); + + // Clear flag + AC0.STATUS = AC_CMP_bm; +} +#endif + +#ifdef AC1_AC_vect +ISR(AC1_AC_vect) +{ + // Run user function + intFuncAC[1](); + + // Clear flag + AC1.STATUS = AC_CMP_bm; +} +#endif + +#ifdef AC2_AC_vect +ISR(AC2_AC_vect) +{ + // Run user function + intFuncAC[2](); + + // Clear flag + AC2.STATUS = AC_CMP_bm; +} +#endif diff --git a/megaavr/libraries/EEPROM/README.md b/megaavr/libraries/EEPROM/README.md index a624136..3e16839 100644 --- a/megaavr/libraries/EEPROM/README.md +++ b/megaavr/libraries/EEPROM/README.md @@ -1,13 +1,27 @@ -## **EEPROM Library V2.0** for Arduino +## **EEPROM Library V2.1** -**Written by:** _Christopher Andrews_. +**Written by:** _Christopher Andrews_. + +**Modified by:** _Spence Konde_ for better megaAVR support. ### **What is the EEPROM library.** -Th EEPROM library provides an easy to use interface to interact with the internal non-volatile storage found in AVR based Arduino boards. This library will work on many AVR devices like ATtiny and ATmega chips. +The EEPROM library provides an easy to use interface to interact with the internal non-volatile storage found on megaAVR ATtiny and ATmega devices. It was adapted for these devices by Spence Konde for distribution as part of [megaTinyCore](https://github.com/SpenceKonde/megaTinyCore). The interface is fully compatible with the standard Arduino EEPROM.h library. EEPROM memory will retain it's stored data when the device is powered off. If the EESAVE bit in the SYSCFG0 fuse is set, it will retain it's values even if a UPDI programmer is used to issue a Chip Erase command, unless the part has been "locked" via the LOCKBIT fuse, in which case the EEPROM is always cleared. + +### **Additional features when used with the megaavr devices** + +Like all AVR microcontrollers, the megaAVR devices have the usual complement of EEPROM memory available (See the datasheet or megaTinyCore part-specific documentation for more details). In addition to the standard EEPROM, the megaavr devices also have an additional "page" of memory available in what Atmel/Microchip refers to as the "user row". When using this version of EEPROM.h (Included in megaTinyCore 1.1.9 and later), the same methods described below work in the same way to read and write the user row. The library will treat any address greater than 0xFF (255) as pointing to the user row, as no currently available megaavr devices provide more than 256b of EEPROM memory. + +The user row can be used like normal EEPROM. Unlike normal EEPROM, when the chip is locked (via the LOCKBIT fuse), it can be *written to* (but not read from) via UPDI. It is still erased when a Chip Erase instruction is used. + +### **Library limitations** + +As with most Arduino libraries, this library sacrifices performance and functionality in favor of ease of use. This is particularly true of the megaAVR parts - unlike "classic" AVR devices, these provide a readiliy accessible facility for programming flash and EEPROM memory a whole page at a time (see the datasheet for additional information) - this library writes all memory one byte at a time. Providing a high performance library that made use of that would require that the library br aware of the page boundaries; after consideration, it was decided that the flash and performance overhead of such a system would not nr justified in the resource-constrained environment of a TinyAVR device as this version of the library is intended for. For applications where space is at a particular premium, megaTinyCore provides a minimal eeprom libtary called TinyEEPROM ( https://github.com/SpenceKonde/megaTinyCore/extras/TinyEEPROM.md .) + +No facility for wear leveling is provided, other than the `update()` and `put()` methods checking that the contents have not changed before writing. Under typical usage scenarios, further wear leveling methods are unnecessary - these devices are rated for 100,000 erase-write cycles, and according to the datasheet, the hardware only erases and writes bytes which have been written to the page buffer - it deos not perform a read-modify-write cycle on the whole page when any byte within the page is written or erased. If you do determine thas wear leveling is required for your application, many libraries that do this are available from various authors. Be aware that there is a bug in eeprom_is_ready() macro provided by the included with most versions of avr-libc, which impacts many third party EEPROM-rel;ated libraries. The symptom of this issue is an error referring to NVM_STATUS; to fix it, search the library code for eeprom_is_ready(). Replace `eeprom_is_ready()` with `!(NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm)` and the library should work, assuming they do not make use of direct register writes that would require hand-porting to other families of AVR. ### **How to use it** -The EEPROM library is included in your IDE download. To add its functionality to your sketch you'll need to reference the library header file. You do this by adding an include directive to the top of your sketch. +The EEPROM library is provided as part of all board packages for hardware with this sort of memory - this particular version is supplied with megaTinyCore. It will be used whenver you are compiling for ```Arduino #include @@ -66,7 +80,7 @@ This function returns a reference to the `object` passed in. It does not need to #### **Subscript operator: `EEPROM[address]`** [[_example_]](examples/eeprom_crc/eeprom_crc.ino) -This operator allows using the identifier `EEPROM` like an array. +This operator allows using the identifier `EEPROM` like an array. EEPROM cells can be read _and_ **_written_** directly using this method. This operator returns a reference to the EEPROM cell. @@ -113,7 +127,7 @@ unsigned char val = ref; //Read referenced cell. #### **`EEPtr` class** This object is a bidirectional pointer to EEPROM cells represented by `EERef` objects. -Just like a normal pointer type, this type can be dereferenced and repositioned using +Just like a normal pointer type, this type can be dereferenced and repositioned using increment/decrement operators. ```C++ @@ -128,12 +142,12 @@ ptr++; //Move to next EEPROM cell. #### **`EEPROM.begin()`** -This function returns an `EEPtr` pointing to the first cell in the EEPROM. +This function returns an `EEPtr` pointing to the first cell in the EEPROM. This is useful for STL objects, custom iteration and C++11 style ranged for loops. #### **`EEPROM.end()`** -This function returns an `EEPtr` pointing at the location after the last EEPROM cell. +This function returns an `EEPtr` pointing at the location after the last EEPROM cell. Used with `begin()` to provide custom iteration. -**Note:** The `EEPtr` returned is invalid as it is out of range. Infact the hardware causes wrapping of the address (overflow) and `EEPROM.end()` actually references the first EEPROM cell. +**Note:** The `EEPtr` returned is invalid as it is out of range. Infact the hardware causes wrapping of the address (overflow) and `EEPROM.end()` actually references the first EEPROM cell. \ No newline at end of file diff --git a/megaavr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino b/megaavr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino index f8694da..ec30bbd 100644 --- a/megaavr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino +++ b/megaavr/libraries/EEPROM/examples/eeprom_crc/eeprom_crc.ino @@ -1,10 +1,10 @@ /*** - Written by Christopher Andrews. - CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ). + Written by Christopher Andrews. + CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ). - A CRC is a simple way of checking whether data has changed or become corrupted. - This example calculates a CRC value directly on the EEPROM values. - The purpose of this example is to highlight how the EEPROM object can be used just like an array. + A CRC is a simple way of checking whether data has changed or become corrupted. + This example calculates a CRC value directly on the EEPROM values. + The purpose of this example is to highlight how the EEPROM object can be used just like an array. ***/ #include diff --git a/megaavr/libraries/EEPROM/library.properties b/megaavr/libraries/EEPROM/library.properties index 2bd5552..4c639be 100644 --- a/megaavr/libraries/EEPROM/library.properties +++ b/megaavr/libraries/EEPROM/library.properties @@ -1,9 +1,9 @@ name=EEPROM -version=2.0 +version=2.1 author=Arduino, Christopher Andrews -maintainer=Arduino -sentence=Enables reading and writing to the permanent board storage. -paragraph=This library allows to read and write data in a memory type, the EEPROM, that keeps its content also when the board is powered off. The amount of EEPROM available depends on the microcontroller type. +maintainer=MCUdude +sentence=Enables reading and writing to EEPROM and USERROW on megaAVR parts. +paragraph=This library allows a sketch to read and write data in a memory type, the EEPROM, that keeps its content also when the board is powered off. This version of the library also supports reading and writing the USERROW page on megaAVR parts. category=Data Storage url=http://www.arduino.cc/en/Reference/EEPROM architectures=megaavr diff --git a/megaavr/libraries/EEPROM/src/EEPROM.h b/megaavr/libraries/EEPROM/src/EEPROM.h index a600835..7ac7b08 100644 --- a/megaavr/libraries/EEPROM/src/EEPROM.h +++ b/megaavr/libraries/EEPROM/src/EEPROM.h @@ -2,144 +2,158 @@ EEPROM.h - EEPROM library Original Copyright (c) 2006 David A. Mellis. All right reserved. New version by Christopher Andrews 2015. - 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 St, Fifth Floor, Boston, MA 02110-1301 USA + Expanded by Spence Konde for megaTinyCore, with several new additions + First, owing to recently discovered */ #ifndef EEPROM_h #define EEPROM_h -#include -#include #include +#include /*** EERef class. - This object references an EEPROM cell. Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM. This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell. ***/ -struct EERef{ - - EERef( const int index ) - : index( index ) {} - - //Access/read members. - uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); } - operator uint8_t() const { return **this; } - - //Assignment/write members. - EERef &operator=( const EERef &ref ) { return *this = *ref; } - EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; } - EERef &operator +=( uint8_t in ) { return *this = **this + in; } - EERef &operator -=( uint8_t in ) { return *this = **this - in; } - EERef &operator *=( uint8_t in ) { return *this = **this * in; } - EERef &operator /=( uint8_t in ) { return *this = **this / in; } - EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; } - EERef &operator %=( uint8_t in ) { return *this = **this % in; } - EERef &operator &=( uint8_t in ) { return *this = **this & in; } - EERef &operator |=( uint8_t in ) { return *this = **this | in; } - EERef &operator <<=( uint8_t in ) { return *this = **this << in; } - EERef &operator >>=( uint8_t in ) { return *this = **this >> in; } - - EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; } - - /** Prefix increment/decrement **/ - EERef& operator++() { return *this += 1; } - EERef& operator--() { return *this -= 1; } - - /** Postfix increment/decrement **/ - uint8_t operator++ (int){ - uint8_t ret = **this; - return ++(*this), ret; - } - - uint8_t operator-- (int){ - uint8_t ret = **this; - return --(*this), ret; - } - - int index; //Index of current EEPROM cell. +#define nvm_read_byte(idx) *(uint8_t *)((idx & 0xFF) | ((idx & 0x100) ? USER_SIGNATURES_START : EEPROM_START)) + +static void nvm_write_byte(uint16_t idx, uint8_t dat) +{ + *(uint8_t *)((idx & 0xFF) | ((idx & 0x100) ? USER_SIGNATURES_START : EEPROM_START)) = dat; + uint8_t oldSREG = SREG; + cli(); + _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_PAGEERASEWRITE_gc); + SREG = oldSREG; + while (NVMCTRL.STATUS & NVMCTRL_EEBUSY_bm) + ; +} + +struct EERef +{ + EERef(const int index) + : index(index) {} + + //Access/read members. + uint8_t operator*() const { return nvm_read_byte(index); } + operator uint8_t() const { return **this; } + + //Assignment/write members. + EERef &operator=(const EERef &ref) { return *this = *ref; } + EERef &operator=(uint8_t in) { return nvm_write_byte(index, in), *this; } + EERef &operator+=(uint8_t in) { return *this = **this + in; } + EERef &operator-=(uint8_t in) { return *this = **this - in; } + EERef &operator*=(uint8_t in) { return *this = **this * in; } + EERef &operator/=(uint8_t in) { return *this = **this / in; } + EERef &operator^=(uint8_t in) { return *this = **this ^ in; } + EERef &operator%=(uint8_t in) { return *this = **this % in; } + EERef &operator&=(uint8_t in) { return *this = **this & in; } + EERef &operator|=(uint8_t in) { return *this = **this | in; } + EERef &operator<<=(uint8_t in) { return *this = **this << in; } + EERef &operator>>=(uint8_t in) { return *this = **this >> in; } + + EERef &update(uint8_t in) { return in != *this ? *this = in : *this; } + + /** Prefix increment/decrement **/ + EERef &operator++() { return *this += 1; } + EERef &operator--() { return *this -= 1; } + + /** Postfix increment/decrement **/ + uint8_t operator++(int) + { + uint8_t ret = **this; + return ++(*this), ret; + } + + uint8_t operator--(int) + { + uint8_t ret = **this; + return --(*this), ret; + } + + int index; //Index of current EEPROM cell. }; /*** EEPtr class. - This object is a bidirectional pointer to EEPROM cells represented by EERef objects. - Just like a normal pointer type, this can be dereferenced and repositioned using + Just like a normal pointer type, this can be dereferenced and repositioned using increment/decrement operators. ***/ -struct EEPtr{ - - EEPtr( const int index ) - : index( index ) {} - - operator int() const { return index; } - EEPtr &operator=( int in ) { return index = in, *this; } - - //Iterator functionality. - bool operator!=( const EEPtr &ptr ) { return index != ptr.index; } - EERef operator*() { return index; } - - /** Prefix & Postfix increment/decrement **/ - EEPtr& operator++() { return ++index, *this; } - EEPtr& operator--() { return --index, *this; } - EEPtr operator++ (int) { return index++; } - EEPtr operator-- (int) { return index--; } - - int index; //Index of current EEPROM cell. +struct EEPtr +{ + EEPtr(const int index) + : index(index) {} + + operator int() const { return index; } + EEPtr &operator=(int in) { return index = in, *this; } + + //Iterator functionality. + bool operator!=(const EEPtr &ptr) { return index != ptr.index; } + EERef operator*() { return index; } + + /** Prefix & Postfix increment/decrement **/ + EEPtr &operator++() { return ++index, *this; } + EEPtr &operator--() { return --index, *this; } + EEPtr operator++(int) { return index++; } + EEPtr operator--(int) { return index--; } + + int index; //Index of current EEPROM cell. }; /*** EEPROMClass class. - This object represents the entire EEPROM space. It wraps the functionality of EEPtr and EERef into a basic interface. This class is also 100% backwards compatible with earlier Arduino core releases. ***/ -struct EEPROMClass{ - - //Basic user access methods. - EERef operator[]( const int idx ) { return idx; } - uint8_t read( int idx ) { return EERef( idx ); } - void write( int idx, uint8_t val ) { (EERef( idx )) = val; } - void update( int idx, uint8_t val ) { EERef( idx ).update( val ); } - - //STL and C++11 iteration capability. - EEPtr begin() { return 0x00; } - EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. - uint16_t length() { return EEPROM_SIZE; } - - //Functionality to 'get' and 'put' objects to and from EEPROM. - template< typename T > T &get( int idx, T &t ){ - EEPtr e = idx; - uint8_t *ptr = (uint8_t*) &t; - for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e; - return t; - } - - template< typename T > const T &put( int idx, const T &t ){ - EEPtr e = idx; - const uint8_t *ptr = (const uint8_t*) &t; - for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ ); - return t; - } +struct EEPROMClass +{ + //Basic user access methods. + EERef operator[](const int idx) { return idx; } + uint8_t read(int idx) { return EERef(idx); } + void write(int idx, uint8_t val) { (EERef(idx)) = val; } + void update(int idx, uint8_t val) { EERef(idx).update(val); } + + //STL and C++11 iteration capability. + EEPtr begin() { return 0x00; } + EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. + uint16_t length() { return EEPROM_SIZE; } + + //Functionality to 'get' and 'put' objects to and from EEPROM. + template + T &get(int idx, T &t) + { + EEPtr e = idx; + uint8_t *ptr = (uint8_t *)&t; + for (int count = sizeof(T); count; --count, ++e) *ptr++ = *e; + return t; + } + + template + const T &put(int idx, const T &t) + { + EEPtr e = idx; + const uint8_t *ptr = (const uint8_t *)&t; + for (int count = sizeof(T); count; --count, ++e) (*e).update(*ptr++); + return t; + } }; static EEPROMClass EEPROM; diff --git a/megaavr/libraries/Event/README.md b/megaavr/libraries/Event/README.md new file mode 100644 index 0000000..a5a490f --- /dev/null +++ b/megaavr/libraries/Event/README.md @@ -0,0 +1,449 @@ +# Event +A library for interfacing with the built-in Event system on the megaAVR-0 series MCUs. +Developed by [MCUdude](https://github.com/MCUdude/). + +**From the datasheet:** +> The Event System (EVSYS) enables direct peripheral-to-peripheral signaling. It allows a change in one peripheral (the event generator) to trigger actions in other peripherals (the event users) through event channels, without using the CPU. It is designed to provide short and predictable response times between peripherals, allowing for autonomous peripheral control and interaction, and also for synchronized timing of actions in several peripheral modules. It is thus a powerful tool for reducing the complexity, size, and execution time of the software. + + +## Overview +The event system allows routing of signals from event "generators" (outputs on various peripherals) through an event "channel", which one or more "event users" can be connected. When an event signal coming from the generator is is "active" or "high", the users connected to the same channel as the generator will perform certain specified actions depending on the peripheral. Generators are often the sorts of things that generate an interrupt if that is enabled - but some things can generate constant level events (such as following the state of a pin). +The event users can do a wide variety of things. The ADC can kick off a staged measurement. Type A and B timers can count them, and type B timers can measure their duration or time between them with input capture. USARTs can even use them as their RX input! This is nice and all - but what really makes the Event system reach it's potential is CCL (configurable custom logic) which can use events as inputs, in addiion to having access to several more internal sourcesof "event-like" signals - and being event generators in their own right. + +More information about the Event system and how it works can be found in the [Microchip Application Note AN2451](http://ww1.microchip.com/downloads/en/AppNotes/DS00002451B.pdf) and in the [megaAVR-0 family data sheet](http://ww1.microchip.com/downloads/en/DeviceDoc/megaAVR0-series-Family-Data-Sheet-DS40002015B.pdf). + + +### Level vs. Pulse events +There are two types of events - a "pulse" interrupt, which lasts for the duration of a single clock cycle (either `CLK_PER` or a relevant (slower) clock - for example, the USART XCK generator provides a pulse event which lasts one XCK period, whuich is far slower than CLK_PER), or a "level" interrupt which lasts for the duration of some condition. +Often for a given even generator or user only one or the other makes sense. Less often, for some reason or another, you may need a level event, but all you have is a pulse event - or the other way around. A [CCL module (Logic.h)](../Logic/README.md) event between the two at the cost of the logic module and one event channel. In the case of timer WO (PWM) channels, the CCL already has level inputs. + + +### Synchronization +>Events can be either synchronous or asynchronous to the peripheral clock. Each Event System channel has two subchannels: one asynchronous and one synchronous. +>The asynchronous subchannel is identical to the event output from the generator. If the event generator generates a signal asynchronous to the peripheral clock, the signal on the asynchronous subchannel will be asynchronous. If the event generator generates a signal synchronous to the peripheral clock, the signal on the asynchronous subchannel +>will also be synchronous. +>The synchronous subchannel is identical to the event output from the generator, if the event generator generates a signal synchronous to the peripheral clock. If the event generator generates a signal asynchronous to the peripheral clock, this signal is first synchronized before being routed onto the synchronous subchannel. Depending on when the event occurs, synchronization will delay the it by two to three clock cycles. The Event System automatically perform this synchronization if an asynchronous generator is selected for an event channel. + +The event system, under the hood, is asynchronous - it can react faster than the system clock (often a lot faster). +The fact that it is asynchronous usually doesn't matter, but it is one of the things one should keep in mind when using these features, because every so often it does. + + +## Event +Class for interfacing with the Event system (EVSYS). Each event channel has its own object. +Use the predefined objects `Event0`, `Event1`, `Event2`, `Event3`, `Event4`, `Event5`, `Event6` or `Event7`. Refer to static functions by using `Event::`. Additionally, there is an `Event_empty` that is returned whenever you call a method that returns an Event reference, but it can't fulfil your request. +Note that different channels have different functionality, so make sure you use the right channel for the task. + + +In short terms: +* `event::genN::rtc_div8192`, `event::genN::rtc_div4096`, `event::genN::rtc_div2048` and `event::genN::rtc_div1024` are only available on odd numbered channels +* `event::genN::rtc_div512`, `event::genN::rtc_div256`, `event::genN::rtc_div128` and `event::genN::rtc_div64` are only available on even numbered channels +* PIN PA0..7 and PB0..5 can only be used as event generators on channel 0 and 1 +* PIN PC0..7 and PD0..7 can only be used as event generators on channel 2 and 3 +* PIN PE0..3 and PF0..6 can only be used as event generators on channel 4 and 5 + + +## get_channel_number() +Function to get the current channel number. Useful if the channel object has been passed to a function as reference. The `Event_empty` object has channel number 255. + +### Declaration +``` c++ +uint8_t get_channel_number(); +``` + +### Usage +``` c++ +uint8_t this_channel = Event0.get_channel_number(); // In this case, get_channel_number will return 0 +``` + + +## get_channel() +Static function that returns the event object of that number. Useful if you need to get the correct Event object based on an integer number. + +### Declaration +``` c++ +static Event& get_channel(uint8_t channel_number); +``` + +### Usage +```c++ +// Create a reference to the object get_channel() returns, which in this case will be the Event2 object +// myEvent can be futher used as a regular object +Event& myEvent = Event::get_channel(2); + +// Simple check to compare two objects +if(&myEvent == &Event2) +{ + // myEvent and Event2 is the same thing! +} +``` + + +## get_generator_channel() +Static function that returns the object used for a particular event generator. Useful to figure out which channel or object a generator is connected to. +Returns a reference to the `Event_empty` object if the generator is not connected to any channel. + +### Declaration +``` c++ +static Event& get_generator_channel(event::gen::generator_t generator); // For all other generators (event::gen, event::gen0...gen7) +static Event& get_generator_channel(uint8_t generator); // For Arduino pins +``` + +### Usage +```c++ +// Set ccl0_out as event generator for channel 2 +Event2.set_generator(event::gen::ccl0_out); + +// Now we want to get the channel/object connected to the ccl0_out generator +// Create a reference to the object get_generator_channel() returns. +Event& myEvent = Event::get_generator_channel(event::gen::ccl0_out); + +// myEvent is now a reference to Event2! +``` + + +## get_generator() +Function to get the generator used for a particular channel. + +### Declaration +``` c++ +uint8_t get_generator(); +``` + +### Usage +```c++ +uint8_t generator_used = Event0.get_generator(); +if(generator_used == event::gen::ccl0_out) { + Serial.println("We're using event::gen::ccl0_out as generator"); +} +``` + + +## set_generator(event::gen::generator_t) +Function to connect an event generator to a channel. Note that we use the prefix event::genN:: (where N is the channel number) when referring to generators unique to this particular channel. we use event::gen:: when referring to generators available on all generators. + +### Declaration +``` c++ +void set_generator(event::gen::generator_t generator); +void set_generator(event::gen0::generator_t generator); +//... +void set_generator(event::gen7::generator_t generator); +``` + +### Usage +```c++ +Event0.set_generator(event::gen::ccl0_out); // Use the output of logic block 0 (CCL0) as an event generator for Event0 +Event2.set_generator(event::gen2::pin_pc0); // Use pin PC0 as an event generator for Event2 +``` + +### Generator table +Below is a table with all possible generators for each channel. + +| All event channels | Event0 | Event1 | Event2 | Event3 | Event4 | Event5 | Event6 | Event7 | +|-----------------------------|------------------------------------------------------------|------------------------------------------------------------|------------------------------------------------------------|------------------------------------------------------------|-------------------------------------------------------------|-------------------------------------------------------------|----------------------------|---------------------------| +| `event::gen::disable` | `event::gen0::disable` | `event::gen1::disable` | `event::gen2::disable` | `event::gen3::disable` | `event::gen4::disable` | `event::gen5::disable` | `event::gen6::disable` | `event::gen7::disable` | +| `event::gen::updi_synch` | `event::gen0::rtc_div8192` | `event::gen1::rtc_div512` | `event::gen2::rtc_div8192` | `event::gen3::rtc_div512` | `event::gen4::rtc_div8192` | `event::gen5::rtc_div512` | `event::gen6::rtc_div8192` | `event::gen7::rtc_div512` | +| `event::gen::rtc_ovf` | `event::gen0::rtc_div4096` | `event::gen1::rtc_div256` | `event::gen2::rtc_div4096` | `event::gen3::rtc_div256` | `event::gen4::rtc_div4096` | `event::gen5::rtc_div256` | `event::gen6::rtc_div4096` | `event::gen7::rtc_div256` | +| `event::gen::rtc_cmp` | `event::gen0::rtc_div2048` | `event::gen1::rtc_div128` | `event::gen2::rtc_div2048` | `event::gen3::rtc_div128` | `event::gen4::rtc_div2048` | `event::gen5::rtc_div128` | `event::gen6::rtc_div2048` | `event::gen7::rtc_div128` | +| `event::gen::ccl0_out` | `event::gen0::rtc_div1024` | `event::gen1::rtc_div64` | `event::gen2::rtc_div1024` | `event::gen3::rtc_div64` | `event::gen4::rtc_div1024` | `event::gen5::rtc_div64` | `event::gen6::rtc_div1024` | `event::gen7::rtc_div64` | +| `event::gen::ccl1_out` | `event::gen0::pin_pa0` | `event::gen1::pin_pa0` | `event::gen2::pin_pc0` | `event::gen3::pin_pc0` | `event::gen4::pin_pe0`
(Only available on ATmegaX809) | `event::gen5::pin_pe0`
(Only available on ATmegaX809) | | | +| `event::gen::ccl2_out` | `event::gen0::pin_pa1` | `event::gen1::pin_pa1` | `event::gen2::pin_pc1` | `event::gen3::pin_pc1` | `event::gen4::pin_pe1`
(Only available on ATmegaX809) | `event::gen5::pin_pe1`
(Only available on ATmegaX809) | | | +| `event::gen::ccl3_out` | `event::gen0::pin_pa2` | `event::gen1::pin_pa2` | `event::gen2::pin_pc2` | `event::gen3::pin_pc2` | `event::gen4::pin_pe2`
(Only available on ATmegaX809) | `event::gen5::pin_pe2`
(Only available on ATmegaX809) | | | +| `event::gen::ac0_out` | `event::gen0::pin_pa3` | `event::gen1::pin_pa3` | `event::gen2::pin_pc3` | `event::gen3::pin_pc3` | `event::gen4::pin_pe3`
(Only available on ATmegaX809) | `event::gen5::pin_pe3`
(Only available on ATmegaX809) | | | +| `event::gen::adc0_ready` | `event::gen0::pin_pa4` | `event::gen1::pin_pa4` | `event::gen2::pin_pc4`
(Only available on ATmegaX809) | `event::gen3::pin_pc4`
(Only available on ATmegaX809) | | | | | +| `event::gen::usart0_xck` | `event::gen0::pin_pa5` | `event::gen1::pin_pa5` | `event::gen2::pin_pc5`
(Only available on ATmegaX809) | `event::gen3::pin_pc5`
(Only available on ATmegaX809) | | | | | +| `event::gen::usart1_xck` | `event::gen0::pin_pa6` | `event::gen1::pin_pa6` | `event::gen2::pin_pc6`
(Only available on ATmegaX809) | `event::gen3::pin_pc6`
(Only available on ATmegaX809) | | | | | +| `event::gen::usart2_xck` | `event::gen0::pin_pa7` | `event::gen1::pin_pa7` | `event::gen2::pin_pc7`
(Only available on ATmegaX809) | `event::gen3::pin_pc7`
(Only available on ATmegaX809) | | | | | +| `event::gen::usart3_xck` | `event::gen0::pin_pb0`
(Only available on ATmegaX809) | `event::gen1::pin_pb0`
(Only available on ATmegaX809) | `event::gen2::pin_pd0` | `event::gen3::pin_pd0` | `event::gen4::pin_pf0` | `event::gen5::pin_pf0` | | | +| `event::gen::spi0_sck` | `event::gen0::pin_pb1`
(Only available on ATmegaX809) | `event::gen1::pin_pb1`
(Only available on ATmegaX809) | `event::gen2::pin_pd1` | `event::gen3::pin_pd1` | `event::gen4::pin_pf1` | `event::gen5::pin_pf1` | | | +| `event::gen::tca0_ovf_lunf` | `event::gen0::pin_pb2`
(Only available on ATmegaX809) | `event::gen1::pin_pb2`
(Only available on ATmegaX809) | `event::gen2::pin_pd2` | `event::gen3::pin_pd2` | `event::gen4::pin_pf2`
(Not available on 28-pin parts) | `event::gen5::pin_pf2`
(Not available on 28-pin parts) | | | +| `event::gen::tca0_hunf` | `event::gen0::pin_pb3`
(Only available on ATmegaX809) | `event::gen1::pin_pb3`
(Only available on ATmegaX809) | `event::gen2::pin_pd3` | `event::gen3::pin_pd3` | `event::gen4::pin_pf3`
(Not available on 28-pin parts) | `event::gen5::pin_pf3`
(Not available on 28-pin parts) | | | +| `event::gen::tca0_cmp0` | `event::gen0::pin_pb4`
(Only available on ATmegaX809) | `event::gen1::pin_pb4`
(Only available on ATmegaX809) | `event::gen2::pin_pd4` | `event::gen3::pin_pd4` | `event::gen4::pin_pf4`
(Not available on 28-pin parts) | `event::gen5::pin_pf4`
(Not available on 28-pin parts) | | | +| `event::gen::tca0_cmp1` | `event::gen0::pin_pb5`
(Only available on ATmegaX809) | `event::gen1::pin_pb5`
(Only available on ATmegaX809) | `event::gen2::pin_pd5` | `event::gen3::pin_pd5` | `event::gen4::pin_pf5`
(Not available on 28-pin parts) | `event::gen5::pin_pf5`
(Not available on 28-pin parts) | | | +| `event::gen::tca0_cmp2` | | | `event::gen2::pin_pd6` | `event::gen3::pin_pd6` | `event::gen4::pin_pf6` | `event::gen5::pin_pf6` | | | +| `event::gen::tcb0_capt` | | | `event::gen2::pin_pd7` | `event::gen3::pin_pd7` | | | | | +| `event::gen::tcb1_capt` | | | | | | | | | +| `event::gen::tcb2_capt` | | | | | | | | | +| `event::gen::tcb3_capt` | | | | | | | | | +| `event::gen::tcb3_capt` | | | | | | | | | + + +### assign_generator(event::gen::generator_t) +Static function that connects an event generator to a channel. What's different compared to `set_generator()` is that this function returns a reference to the channel object the generator has been assigned to. In other words, you don't need to keep track of the exact channel number, it just assigns an available channel. +Note that this function only accepts generators that are present on all channels (event::gen::). It will return a reference to the `Event_empty` object if no channel is available. + +### Declaration +``` c++ +static Event& assign_generator(event::gen::generator_t event_generator); +``` + +### Usage +```c++ +Event& myEvent = Event::assign_generator(event::gen::ac0_out); // Assign the AC0 out generator to a channel +myEvent.start(); +``` + + +## set_generator(uint8_t pin_number) +Function that sets an Arduino pin as the event generator. Note that you will have to make sure a particular pin can be used as an event generator for the selected channel/object. **If this sounds like a hassle, use [assign_generator_pin()](#assign_generator_pin) instead.** + +### Declaration +``` c++ +void set_generator(uint8_t pin_number); +``` + +### Usage +```c++ +Event0.set_generator(PIN_PA0); // Will work. PA0 can be used as an event generator for channel 0 +Event1.set_generator(PIN_PC3); // WILL NOT WORK! PORTC cannot be used as an event generator for channel 1 +``` + + +## assign_generator_pin() +Static function that sets an Arduino pin as the event generator. Unlike set_generator(uint8_t pin_number), this function will return the object the generator has been assigned to. It will always try to use the lowest possible channel number as possible, and will return a reference to the object `Event_empty` (generator number 255) if the pin can't be assigned to a channel. + +### Declaration +``` c++ +static Event& assign_generator_pin(uint8_t pin_number); +``` + +### Usage +```c++ +// We're using PIN_PE2 as event generator, and the library finds a suited object +Event& myEvent = Event::assign_generator_pin(PIN_PE2); + +// The myEvent object can be used directly +myEvent.start(); +``` + + +## get_user_channel_number() +Static function to get what event channel a user is connected to. Returns -1 if not connected to any channel. +Note that we use `event::user::` as prefix when we refer to event users. Since this is a static function you don't have to specify an object to determine what channel the user is connected to. An event channel, and hence an event generator, can have as many event users are you want - but an event user can only have one event generator. +You cannot get a list or count of all users connected to a generator except by iterating over the list. + +### Declaration +``` c++ +static int8_t get_user_channel_number(event::user::user_t event_user); +``` + +### Usage +```c++ +int8_t connected_to = Event::get_user_channel_number(event::user::ccl0_event_a); // Returns the channel number ccl0_event_a is connected to +``` + + +## get_user_channel() +Static function that returns the Event channel object a particular user is connected to. unlike get_user_channel_number()`, this returns a reference to an Event object, and returns a referece to the `Event_empty` object if not connected to any event channel. + +### Declaration +``` c++ +static Event& get_user_channel(event::user::user_t event_user); +``` + +### Usage +```c++ +Event& myEvent = Event::get_user_channel(event::user::ccl0_event_a); +``` + + +## set_user() +Function to connect an event user to an event generator. Note that a generator can have multiple users. + +### Declaration +``` c++ +void set_user(event::user::user_t event_user); +``` + +### Usage +```c++ +Event0.set_generator(event::gen0::pin_pa0); // Set pin PA0` as event generator for Event0 +Event0.set_user(event::user::evoutc); // Set EVOUTC (pin PC2) as event user +Event0.set_user(event::user::evoutd); // Set evoutD (pin PD2) as event user +``` + +### User table +Below is a table with all possible event users. +Note that `evoutN_pin_pN7` is the same as `evoutN_pin_pN2` but where the pin is swapped from 2 to 7. This means that for instance, `evouta_pin_pa2` can't be used in combination with `evouta_pin_pa7.` + +| Event users | Notes | +|-------------------------------------------------|-----------------------------------------------------------------------| +| `event::user::ccl0_event_a` | | +| `event::user::ccl0_event_b` | | +| `event::user::ccl1_event_a` | | +| `event::user::ccl1_event_b` | | +| `event::user::ccl2_event_a` | | +| `event::user::ccl2_event_b` | | +| `event::user::ccl3_event_a` | | +| `event::user::ccl3_event_b` | | +| `event::user::adc0_start` | | +| `event::user::evouta_pin_pa2` | | +| `event::user::evouta_pin_pa7` | Pin swapped variant of `evouta_pin_pa2` | +| `event::user::evoutb_pin_pb2` | Only available on ATmegaX809 | +| `event::user::evoutc_pin_pc2` | | +| `event::user::evoutc_pin_pc7` | Pin swapped variant of `evoutc_pin_pc2`. Only available on ATmegaX809 | +| `event::user::evoutd_pin_pd2` | | +| `event::user::evoutd_pin_pd7` | Pin swapped variant of `evoutd_pin_pd2` | +| `event::user::evoute_pin_pe2` | Only available on ATmegaX809 | +| `event::user::evoutf_pin_pf2` | Not available on 28-pin parts | +| `event::user::usart0_irda` | | +| `event::user::usart1_irda` | | +| `event::user::usart2_irda` | | +| `event::user::usart3_irda` | | +| `event::user::tca0` or `event::user::tca0_capt` | | +| `event::user::tcb0` or `event::user::tcb0_capt` | | +| `event::user::tcb1` or `event::user::tcb1_capt` | | +| `event::user::tcb2` or `event::user::tcb2_capt` | | +| `event::user::tcb3` or `event::user::tcb3_capt` | | + + +## set_user_pin(uint8_t pin_number) +Function to set an Arduino pin as an event user. Note that only some pins can be used for this. See table below for more details + +### Declaration +``` c++ +int8_t set_user_pin(uint8_t pin_number); +``` + +### Usage +```c++ +Event0.set_user_pin(PIN_PA2); +``` + +### Arduino pin table +| Event pin users | Notes | +|-----------------|----------------------------------------------------------------------------------------------------------| +| PIN_PA2 | | +| PIN_PA7 | Pin swapped variant of PIN_PA2. Cannot be used in combination with PIN_PA2 | +| PIN_PB2 | Only available on ATmegaX809 | +| PIN_PC2 | | +| PIN_PC7 | Pin swapped variant of PIN_PC2. Cannot be used in combination with PIN_PC2. Only available on ATmegaX809 | +| PIN_PD2 | | +| PIN_PD7 | Pin swapped variant of PIN_PD2. Cannot be used in combination with PIN_PD2 | +| PIN_PE2 | Only available on ATmegaX809 | +| PIN_PF2 | Not available on 28-pin parts | + + +## clear_user() +Function to detach a user from a channel. Note that you don't need to know what channel to detach from, simply use `Event::clear_user()`. + +### Declaration +``` c++ +static void clear_user(event::user::user_t event_user); +``` + +### Usage +```c++ +Event::clear_user(event::user::evouta); // Remove the event::user::evouta from whatever event channel it is connected to +``` + + +## soft_event() +Creates a single software event - users connected to that channel will react to it in the same way as they would to one caused by the generator the channel is connected to. +Great if you have to force trigger something. Note that a software event only lasts a single system clock cycle, so it's rather fast! +The software events will invert the channel, and so will trigger something regardless of whether it needs a the event channel to go high or low. + +### Declaration +``` c++ +void soft_event(); +``` + +### Usage +```c++ +Event0.soft_event(); // Create a single software event on Event0 +``` + + +### long_soft_event() +`soft_event()` is only one system clock long, and might be difficult to catch in a real-life application. This function does the same thing as `soft_event()` but has a programmable interval for how long the soft event will last. + +The event lengths that are available are 2, 4, 6, 10 and 16 system clocks. (Any number less than 4 will give 2 clock-long pulse, only 4 will give a 4 clock long one. Anything between 4 and 10 will give 6, exactly 10 will give 10, and anything larger will give 16). + +#### Usage +```c++ +Event0.long_soft_event(4); // Will invert the state of the event channel for 4 system clock cycles (200ns at 20 MHz) +Event0.long_soft_event(10); // Will invert the state of the event channel for 10 system clock cycles (500ns at 20 MHz) + +``` +Don't forget that this is an invert, not a "high" or "low". It should be entirely possible for the event that normally drives it to occur resulting in the state changing during that pulse, depending on it's configuration. Note also that the overhead of long_soft_event is typically several times the length of the pulse due to calculating the bitmask to write; it's longer with higher numbered channels. + + +## start() +Starts an event generator channel by writing the generator selected by the `set_generator()` function. + +### Declaration +``` c++ +void start(bool state = true); +``` + +### Usage +```c++ +Event0.start(); // Starts the Event0 generator channel +``` + + +## stop() +Stops an event generator channel. The `Eventn` object retains memory of what generator it was previously set to. + +### Declaration +``` c++ +void stop(); +``` + +### Usage +```c++ +Event0.stop(); // Stops the Event0 generator channel +``` + + +## gen_from_peripheral() and user_from_peripheral() +These two static functions allow you to pass a reference to a peripheral module, and get back the generator or user associated with it. In this context the "Peripheral Modules" are the structs containing the registers, defined in the io headers; for example `TCB0` or `USART1` or `CCL`. + +This is most useful if you are writing portable (library) code that uses the Event library to interact with the event system. Say you made a library that lets users make one-shot pulses with timerB. You use the Event library to handle that part. You would of course need to know which timer to use - the natural way would be to ask the user to pass a reference or pointer. +But then what? The fact that you've got the pointer to something which, as it happens, is TCB0 (which itself is annoying to determine from an unknown pointer)... though even KNOWING THAT, you're not able to use it with the event library, since it needs event::user::tcb0 (or event::user::tcb0_capt). As the function names imply, one gives generators, the other gives users. They take 2 arguments, the first being a pointer to a peripheral struct. +The second, defaulting to 0, is the "type" of generator or user. Some peripherals have more than one event input or output. These are ordered in the same order as they are in the tables here and in the datasheet listings. + +### Usage +```c +// Here we see a typical use case - you get the generator, and immediately ask Event to assign a channel to it and give that to you. After getting it, you test to make sure it's not Event_empty, which indicates that either gen_from_peripheral failed, or assign_generator was out of event channels. Either way that's probably the user's fault, so you decide to return an error code. +uint8_t init(TCB_t* some_timer, /*and more arguments, most likely */) +{ + &Event_TCBnCapt = Event::assign_generator(Event::gen_from_peripheral(some_timer, 0)); + if (_TCBnCapt.get_channel_number() == 255) + return MY_ERROR_INVALID_TIMER_OR_NO_FREE_EVENT; + doMoreCoolStuff(); +} +``` + +Shown below, generators/user per instance (second argument should be less than this; zero-indexed), and the number of instances (for reference) + +| Peripheral | mega0 | +|------------|----------| +| TCAn | 5 / 1 x1 | +| TCBn | 1/1 x3-4 | +| CCL * | 4 / 8 | +| ACn | 1 / 0 x1 | +| USARTn | !/1 x3-4 | + +`*` - There is only one CCL peripheral, with multiple logic blocks. Each logic block has 1 event generator and 2 event users. If using the logic library, get the Logic instance number. The output generator is that number. The input is twice that number, and twice that number + 1. +`!` - These parts do have an option, but we didn't bother to implement it because it isn't particularly useful. But the Event RX mode combined with the TX input to the CCL permit arbitrary remapping of RX and very flexible remapping of TX. + +And what they are: + +| Peripheral | TCAn | TCBn | CCL* | ACn | USARTn | +|------------|----------|------|---------|-----|---------| +| gen 0 | OVF/LUNF | CAPT | LUT0OUT | OUT | ! | +| gen 1 | HUNF | | LUT1OUT | | | +| gen 2 | CMP0 | | LUT2OUT | | | +| gen 3 | CMP1 | | LUT3OUT | | | +| gen 4 | CMP2 | | ETC. | | | +| user 0 | EVACTA | CAPT | LUT0EVA | - | EVENTRX | +| user 1 | | | LUT0EVB | | | +| user 2 | | | LUT1EVA | | | +| user 3 | | | LUT1EVB | | | +| user 4 | | | ETC. | | | + +`*` - Since there's only one CCL, the pointer (or rather, its type) is just used to select which implementation is used. But this does mean that the CCL can have an insane number of options. But that's fine, because there are plenty of numbers between 0 and 255. +`!` - These parts do have an option, but we didn't bother to implement it because it isn't particularly useful. But the Event RX mode combined with the TX input to the CCL permit arbitrary remapping of RX and very flexible remapping of TX! + + +Asking for a generator that doesn't exist will return 0 (disabled); be sure to check for this in some way. Asking for a user that doesn't exist will return 255, which the library is smart enough not to accept. diff --git a/megaavr/libraries/Event/examples/Read_event_settings/Read_event_settings.ino b/megaavr/libraries/Event/examples/Read_event_settings/Read_event_settings.ino new file mode 100644 index 0000000..1acd561 --- /dev/null +++ b/megaavr/libraries/Event/examples/Read_event_settings/Read_event_settings.ino @@ -0,0 +1,68 @@ +/***********************************************************************| +| megaAVR event system library | +| | +| Read_event_settings.ino | +| | +| A library for interfacing with the megaAVR event system. | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example, we demonstrate the possibilities of reading out | +| which event channel we're working with, which generator is used, and | +| which channel an event user has been connected to. | +| | +| See Microchip's application note AN2451 for more information. | +|***********************************************************************/ + +#include + +// Function to print information about the passed event +void print_event_info(Event& my_event) +{ + Serial2.printf("This is event channel no. %d\n", my_event.get_channel_number()); + Serial2.printf("This channel uses generator no. 0x%02x, which you can find in Event.h\n", my_event.get_generator()); +} + +// Function to print information about the passed event user +void print_user_info(event::user::user_t my_user) +{ + // Event::get_user_channel() returns -1 if the user isn't connected to any event generator + Serial2.printf("User 0x%02x is connected to event channel no. %d\n\n", my_user, Event::get_user_channel_number(my_user)); +} + +void setup() +{ + Serial2.begin(9600); // Initialize hardware serial port + + Event1.set_generator(event::gen0::pin_pa3); // Set pin PA3 as event generator for event channel 1 + Event2.set_generator(event::gen2::pin_pc3); // Set pin PC3 as event generator for event channel 2 + Event& myEvent = Event::assign_generator_pin(PIN_PA2); // Set pin PA2 as event generator for an available channel + + // For more information about EVOUT, see the PORTMUX section in the datasheet + Event1.set_user(event::user::evoutc_pin_pc2); // Set EVOUTC as event user + Event2.set_user(event::user::evouta_pin_pa2); // Set EVOUTA as event user + myEvent.set_user_pin(PIN_PD2); // Set pin PD2 (EVOUTD) as event user + + // Start event channels + Event1.start(); + Event2.start(); + myEvent.start(); +} + +void loop() +{ + // Print info about Event4 and its event user + print_event_info(Event1); + print_user_info(event::user::evoutc_pin_pc2); + + // Print info about Event5 and its event user + print_event_info(Event2); + print_user_info(event::user::evouta_pin_pa2); + + // Print info about myEvent and its user + Event& myEvent = Event::get_generator_channel(PIN_PA2); + print_event_info(myEvent); + print_user_info(event::user::evoutd_pin_pd2); + + delay(5000); +} diff --git a/megaavr/libraries/Event/examples/Route_logic_pins/Route_logic_pins.ino b/megaavr/libraries/Event/examples/Route_logic_pins/Route_logic_pins.ino new file mode 100644 index 0000000..223cd40 --- /dev/null +++ b/megaavr/libraries/Event/examples/Route_logic_pins/Route_logic_pins.ino @@ -0,0 +1,61 @@ +/***********************************************************************| +| megaAVR event system library | +| | +| Route_logic_pins.ino | +| | +| A library for interfacing with the megaAVR event system. | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals on the | +| megaAVR to create a 3-input AND gate using logic block 0, but we | +| utilize the event system to route logic input 0 and 1 to pins PC0 and | +| PC1 instead of the default pins. | +| Here's how 0x80 turns out to be the correct value to create a 3-input | +| AND gate: | +| 3-input AND truth table: | +| If we look at the truth table |PA2|PC1|PC0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 0 | | +| be represented as 10000000. | 0 | 0 | 1 | 0 | | +| If we convert this 8-bit | 0 | 1 | 0 | 0 | | +| binary number into hex, we | 0 | 1 | 1 | 0 | | +| get 0x80. | 1 | 0 | 0 | 0 | | +| | 1 | 0 | 1 | 0 | | +| In this example the output pin, | 1 | 1 | 0 | 0 | | +| PA3 will go high if all three | 1 | 1 | 1 | 1 | | +| inputs are high. | +| | +| See Microchip's application note AN2451 for more information. | +|***********************************************************************/ + +#include +#include + +void setup() +{ + // Initialize Event channel 2 and 3 + Event2.set_generator(event::gen2::pin_pc0); // Set pin PC0 as event generator + Event3.set_generator(event::gen3::pin_pc1); // Set pin PC1 as event generator + Event2.set_user(event::user::ccl0_event_a); // Set CCL0 (Logic0) event A as user + Event3.set_user(event::user::ccl0_event_b); // Set CCL0 (Logic0) event B as user + + // Initialize logic block 0 + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::event_a; // Connect input 0 to ccl0_event_a (PC0 through Event2) + Logic0.input1 = logic::in::event_b; // Connect input 0 to ccl0_event_b (PC1 through Event3) + Logic0.input2 = logic::in::input; // Set PA2 as input + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.truth = 0x80; // Set truth table + Logic0.init(); + + // Start event channels and the logic hardware + Event2.start(); + Event3.start(); + Logic::start(); +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Event/examples/Simple_event/Simple_event.ino b/megaavr/libraries/Event/examples/Simple_event/Simple_event.ino new file mode 100644 index 0000000..68ec388 --- /dev/null +++ b/megaavr/libraries/Event/examples/Simple_event/Simple_event.ino @@ -0,0 +1,52 @@ +/***********************************************************************| +| megaAVR event system library | +| | +| Simple_Event.ino | +| | +| A library for interfacing with the megaAVR event system. | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we look at two different ways of setting up a simple | +| Event generator ans user. In the first example use pin PA0 as an | +| event generator, and pin PC2 and PD2 as event users. In practice, | +| pin PC2 and PD2 will follow PA0's state. | +| In the other example we just provide "Arduino pins" as generator and | +| user, and let the library take care of the rest. | +| | +| See Microchip's application note AN2451 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Since pin PE0 is only available on event generator channel 4 and 5, we use Event4 as our object + // Note that we use gen4:: to refer to functionality unique to event channel 4 + Event0.set_generator(event::gen0::pin_pa0); // Set pin PA0 as event generator + + // For more information about EVOUT, see the PORTMUX section in the datasheet + Event0.set_user(event::user::evoutc_pin_pc2); // Set EVOUTC as event user + Event0.set_user(event::user::evoutd_pin_pd2); // Set EVOUTD as event user + + // Start event channel + Event0.start(); + + + + // A different approach is to let the library itself take care of which Event channel to use: + + // Assign generator to an available channel + Event& myEvent = Event::assign_generator_pin(PIN_PA1); + + // Connect a user, in this case an Arduino pin, to the myEvent channel + myEvent.set_user_pin(PIN_PA2); + + // Start event channel + myEvent.start(); +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Event/keywords.txt b/megaavr/libraries/Event/keywords.txt new file mode 100644 index 0000000..0a21fe2 --- /dev/null +++ b/megaavr/libraries/Event/keywords.txt @@ -0,0 +1,60 @@ +####################################### +# Syntax Coloring Map For Event +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +get_channel_number KEYWORD2 +get_channel KEYWORD2 +get_generator_channel KEYWORD2 +get_generator KEYWORD2 +set_generator KEYWORD2 +assign_generator KEYWORD2 +assign_generator_pin KEYWORD2 +get_user_channel_number KEYWORD2 +get_user_channel KEYWORD2 +set_user KEYWORD2 +set_user_pin KEYWORD2 +clear_user KEYWORD2 +soft_event KEYWORD2 +gen_from_peripheral KEYWORD2 +user_from_peripheral KEYWORD2 +long_soft_event KEYWORD2 +start KEYWORD2 +stop KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Event KEYWORD2 +Event0 KEYWORD2 +Event1 KEYWORD2 +Event2 KEYWORD2 +Event3 KEYWORD2 +Event4 KEYWORD2 +Event5 KEYWORD2 +Event6 KEYWORD2 +Event7 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +event LITERAL1 +gen LITERAL1 +gen0 LITERAL1 +gen1 LITERAL1 +gen2 LITERAL1 +gen3 LITERAL1 +gen4 LITERAL1 +gen5 LITERAL1 +gen6 LITERAL1 +gen7 LITERAL1 +user LITERAL1 diff --git a/megaavr/libraries/Event/library.properties b/megaavr/libraries/Event/library.properties new file mode 100644 index 0000000..0f11f66 --- /dev/null +++ b/megaavr/libraries/Event/library.properties @@ -0,0 +1,9 @@ +name=Event System +version=1.2.1 +author=MCUdude +maintainer=MCUdude and Spence Konde +sentence=A library for interfacing with the built-in event system +paragraph= +category=Signal Input/Output +url=https://github.com/MCUdude/MegaCoreX +architectures=megaavr diff --git a/megaavr/libraries/Event/src/Event.cpp b/megaavr/libraries/Event/src/Event.cpp new file mode 100644 index 0000000..577c4ba --- /dev/null +++ b/megaavr/libraries/Event/src/Event.cpp @@ -0,0 +1,1180 @@ +#include "Event.h" + +// Pre-defined objects +#if defined(EVSYS_CHANNEL0) + Event Event0(0, EVSYS_CHANNEL0); + Event Event_empty(255, EVSYS_CHANNEL0); +#endif +#if defined(EVSYS_CHANNEL1) + Event Event1(1, EVSYS_CHANNEL1); +#endif +#if defined(EVSYS_CHANNEL2) + Event Event2(2, EVSYS_CHANNEL2); +#endif +#if defined(EVSYS_CHANNEL3) + Event Event3(3, EVSYS_CHANNEL3); +#endif +#if defined(EVSYS_CHANNEL4) + Event Event4(4, EVSYS_CHANNEL4); +#endif +#if defined(EVSYS_CHANNEL5) + Event Event5(5, EVSYS_CHANNEL5); +#endif +#if defined(EVSYS_CHANNEL6) + Event Event6(6, EVSYS_CHANNEL6); +#endif +#if defined(EVSYS_CHANNEL7) + Event Event7(7, EVSYS_CHANNEL7); +#endif +#if defined(EVSYS_CHANNEL8) + Event Event8(8, EVSYS_CHANNEL8); +#endif +#if defined(EVSYS_CHANNEL9) + Event Event9(9, EVSYS_CHANNEL9); +#endif + + +/** + * @brief Construct a new Event object + * + * @param channel_num Event channel number + * @param channel_addr Register address to channel generator + */ +Event::Event(uint8_t channel_num, volatile uint8_t &channel_addr) + : channel_number(channel_num), channel_address(channel_addr) { +} + + +/** + * @brief Returns the event channel number in use + * + * @return uint8_t Event channel number + */ +uint8_t Event::get_channel_number() { + return channel_number; +} + + +/** + * @brief Returns the object associated with the passed channel number + * + * @param ch_number Channel number + * @return Event& Event object associated with the channel number. + * Returns the Event_empty object if invalid channel number + */ +Event& Event::get_channel(uint8_t ch_number) { + #if defined(EVSYS_CHANNEL0) + if(Event0.channel_number == ch_number) { + return Event0; + } + #endif + #if defined(EVSYS_CHANNEL1) + if(Event1.channel_number == ch_number) { + return Event1; + } + #endif + #if defined(EVSYS_CHANNEL2) + if(Event2.channel_number == ch_number) { + return Event2; + } + #endif + #if defined(EVSYS_CHANNEL3) + if(Event3.channel_number == ch_number) { + return Event3; + } + #endif + #if defined(EVSYS_CHANNEL4) + if(Event4.channel_number == ch_number) { + return Event4; + } + #endif + #if defined(EVSYS_CHANNEL5) + if(Event5.channel_number == ch_number) { + return Event5; + } + #endif + #if defined(EVSYS_CHANNEL6) + if(Event6.channel_number == ch_number) { + return Event6; + } + #endif + #if defined(EVSYS_CHANNEL7) + if(Event7.channel_number == ch_number) { + return Event7; + } + #endif + #if defined(EVSYS_CHANNEL8) + if(Event8.channel_number == ch_number) { + return Event8; + } + #endif + #if defined(EVSYS_CHANNEL9) + if(Event9.channel_number == ch_number) { + return Event9; + } + #endif + + #if defined(EVSYS_CHANNEL0) + else { + return Event_empty; + } + #endif +} + + +/** + * @brief Returns the event channel object used for a particular event generator + * + * @param generator Event generator + * @return Event& Event channel object used with this event generator + */ +Event& Event::get_generator_channel(event::gen::generator_t generator) { + #if defined(EVSYS_CHANNEL0) + if(Event0.generator_type == generator) { + return Event0; + } + #endif + #if defined(EVSYS_CHANNEL1) + if(Event1.generator_type == generator) { + return Event1; + } + #endif + #if defined(EVSYS_CHANNEL2) + if(Event2.generator_type == generator) { + return Event2; + } + #endif + #if defined(EVSYS_CHANNEL3) + if(Event3.generator_type == generator) { + return Event3; + } + #endif + #if defined(EVSYS_CHANNEL4) + if(Event4.generator_type == generator) { + return Event4; + } + #endif + #if defined(EVSYS_CHANNEL5) + if(Event5.generator_type == generator) { + return Event5; + } + #endif + #if defined(EVSYS_CHANNEL6) + if(Event6.generator_type == generator) { + return Event6; + } + #endif + #if defined(EVSYS_CHANNEL7) + if(Event7.generator_type == generator) { + return Event7; + } + #endif + #if defined(EVSYS_CHANNEL8) + if(Event8.generator_type == generator) { + return Event8; + } + #endif + #if defined(EVSYS_CHANNEL9) + if(Event9.generator_type == generator) { + return Event9; + } + #endif + + #if defined(EVSYS_CHANNEL0) + else { + return Event_empty; + } + #endif +} + + +/** + * @brief Returns the event channel object used for a particular event generator Arduino pin + * + * @param generator_pin Event generator Arduino pin number + * @return Event& Event channel object used with this event generator + */ +Event& Event::get_generator_channel(uint8_t generator_pin) { + uint8_t port = digitalPinToPort(generator_pin); + uint8_t port_pin = digitalPinToBitPosition(generator_pin); + + if(port != NOT_A_PIN && port_pin != NOT_A_PIN) { + uint8_t gen = 0x40 | (port & 0x01) << 3 | port_pin; + if(port == PA || port == PB) { + #if defined(EVSYS_CHANNEL0) + if(Event0.generator_type == gen) { + return Event0; + } + #endif + #if defined(EVSYS_CHANNEL1) + else if(Event1.generator_type == gen) { + return Event1; + } + #endif + } + else if(port == PC || port == PD) { + #if defined(EVSYS_CHANNEL2) + if(Event2.generator_type == gen) { + return Event2; + } + #endif + #if defined(EVSYS_CHANNEL3) + else if(Event3.generator_type == gen) { + return Event3; + } + #endif + } + else if(port == PE || port == PF) { + #if defined(EVSYS_CHANNEL4) + if(Event4.generator_type == gen) { + return Event4; + } + #endif + #if defined(EVSYS_CHANNEL5) + else if(Event5.generator_type == gen) { + return Event5; + } + #endif + } + #if defined(Dx_64_PINS) + else if(port == PG) { + if(Event6.generator_type == gen) { + return Event6; + } + else if(Event7.generator_type == gen) { + return Event7; + } + } + #endif + } + + #if defined(EVSYS_CHANNEL0) + return Event_empty; + #endif +} + + +/** + * @brief Returns the generator type a particular channel has + * + * @return uint8_t Generator type. Returns 0 if no generator is used + */ +uint8_t Event::get_generator() { + return generator_type; +} + + +/** + * @brief Sets a generator for a particular event channel + * + * @param event_generator Set generator. + * Use event::gen:: for functionality present on all event channels. + * Use genN:: for functionality present on channel N. + */ +void Event::set_generator(event::gen::generator_t event_generator) { + // Store event generator setting for use in start() and stop() + generator_type = (uint8_t)event_generator; +} + + +/** + * @brief Function that lets you use an Arduino pin as event generator. + * Note that you'll have to manually keep track of which event channel + * objects to use to make sure the passed Arduino pin is supported. + * A different approach is to use Event::assign_generator_pin(), which + * automatically picks the correct event channel for you. + * + * @param pin_number Arduino pin number to use as event generator + */ +void Event::set_generator(uint8_t pin_number) { + uint8_t port = digitalPinToPort(pin_number); + uint8_t port_pin = digitalPinToBitPosition(pin_number); + + // Store event generator setting for use in start() and stop() + if(port != NOT_A_PIN && port_pin != NOT_A_PIN) { + generator_type = 0x40 | (port & 0x01) << 3 | port_pin; + } + else { + generator_type = event::gen::disable; + } +} + + +/** + * @brief Static member function that sets a port pin as event + * generator and returns the object it has select as event channel. + * It will always try to select the lowest channel number as possible. + * + * @param port Port to use as event generator + * @param port_pin Pin number on port to use as event generator + * @return Event& Event channel object used as the event channel. Returns the + * Event_empty object if passed Arduino pin is invalid or no event + * channel is available + */ +Event& Event::assign_generator_pin(uint8_t port, uint8_t port_pin) { + if(port != NOT_A_PIN && port_pin != NOT_A_PIN) { + #if defined(MEGACOREX) || defined(DXCORE) + uint8_t gen = 0x40 | (port & 0x01) << 3 | port_pin; + if(port == PA || port == PB) { + if(Event0.generator_type == event::gen::disable || Event0.generator_type == gen) { + Event0.generator_type = gen; + return Event0; + } + else if(Event1.generator_type == event::gen::disable || Event1.generator_type == gen) { + Event1.generator_type = gen; + return Event1; + } + } + else if(port == PC || port == PD) { + if(Event2.generator_type == event::gen::disable || Event2.generator_type == gen) { + Event2.generator_type = gen; + return Event2; + } + else if(Event3.generator_type == event::gen::disable || Event3.generator_type == gen) { + Event3.generator_type = gen; + return Event3; + } + } + else if(port == PE || port == PF) { + if(Event4.generator_type == event::gen::disable || Event4.generator_type == gen) { + Event4.generator_type = gen; + return Event4; + } + else if(Event5.generator_type == event::gen::disable || Event5.generator_type == gen) { + Event5.generator_type = gen; + return Event5; + } + } + #if defined(Dx_64_PINS) + else if(port == PG) { + if(Event6.generator_type == event::gen::disable || Event6.generator_type == gen) { + Event6.generator_type = gen; + return Event6; + } + else if(Event7.generator_type == event::gen::disable || Event7.generator_type == gen) { + Event7.generator_type = gen; + return Event7; + } + } + #endif + + return Event_empty; + #elif defined(TINY_2_SERIES) + if(port != PC) { + uint8_t gen = port_pin | (port == PB ? 0x40 : 0x48); + if(Event0.generator_type == event::gen::disable || Event0.generator_type == gen) { + Event0.generator_type = gen; + return Event0; + } + else if(Event1.generator_type == event::gen::disable || Event1.generator_type == gen) { + Event1.generator_type = gen; + return Event1; + } + } + if(port != PB) { + uint8_t gen = port_pin | (port == PA ? 0x40 : 0x48); + if(Event2.generator_type == event::gen::disable || Event2.generator_type == gen) { + Event2.generator_type = gen; + return Event2; + } + else if(Event3.generator_type == event::gen::disable || Event3.generator_type == gen) { + Event3.generator_type = gen; + return Event3; + } + } + if(port != PA) + { + uint8_t gen = port_pin | (port == PC ? 0x40 : 0x48); + if(Event4.generator_type == event::gen::disable || Event4.generator_type == gen) { + Event4.generator_type = gen; + return Event4; + } + else if(Event5.generator_type == event::gen::disable || Event5.generator_type == gen) { + Event5.generator_type = gen; + return Event5; + } + } + return Event_empty; + #elif defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + uint8_t gen = port_pin + 0x0A; + #if !defined(__AVR_ATtinyxy2__) + if(port == PA) { + #endif + if(Event2.generator_type == event::gen::disable || Event2.generator_type == gen) { + Event2.generator_type = gen; + return Event2; + } + gen += 3; + if(Event0.generator_type == event::gen::disable || Event0.generator_type == gen) { + Event0.generator_type = gen; + return Event0; + } + #if !defined(__AVR_ATtinyxy2__) + } + #endif + if(port == PB) { + if(Event3.generator_type == event::gen::disable || Event3.generator_type == gen) { + Event3.generator_type = gen; + return Event3; + } + #if defined(TINY_1_SERIES) // No Event1 on 0-series + gen -= 2; + if(Event1.generator_type == event::gen::disable || Event1.generator_type == gen) { + Event1.generator_type = gen; + return Event1; + } + #endif + } + #if defined(PIN_PC0) // can't test if PORTx is defined - all are defined everywhere) + if(port == PC) { + #if defined(TINY_1_SERIES) // no event 4 on 0-series + if(Event4.generator_type == event::gen::disable || Event4.generator_type == gen) { + Event4.generator_type = gen; + return Event4; + } + #endif + gen -= 3; + if(Event0.generator_type == event::gen::disable || Event0.generator_type == gen) { + Event0.generator_type = gen; + return Event0; + } + } + #endif // PC-bearing parts end here + + #endif // end of tiny 0/1 assign_generator_pin() + } + return Event_empty; +} + + +/** + * @brief Static member function that sets an Arduino pin as event + * generator and returns the object it has select as event channel. + * It will always try to select the lowest channel number as possible. + * + * @param pin_number Arduino pin number to use as event generator + * @return Event& Event channel object used as the event channel. Returns the + * Event_empty object if passed Arduino pin is invalid or no event + * channel is available + */ +Event& Event::assign_generator_pin(uint8_t pin_number) { + uint8_t port = digitalPinToPort(pin_number); + uint8_t port_pin = digitalPinToBitPosition(pin_number); + return Event::assign_generator_pin(port, port_pin); +} + + +/** + * @brief Static member function that takes a event::gen:: generator as a parameter and + * finds an available channel for it. Starts with the highest possible channel + * number, 7, and iterate down to 0 + * + * @param event_generator generator to assign to an event channel + * @return Event& Reference to the event object the generator has been assigned to. + * Returns the Event_empty object if no generator has been assigned to a channel + */ +Event& Event::assign_generator(event::gen::generator_t event_generator) { + // Check if generator is already in use + Event& channel = Event::get_generator_channel(event_generator); + if(channel.get_channel_number() != 255) { + return channel; + } + + else { + #if defined(EVSYS_CHANNEL9) + if(Event9.get_generator() == event::gen::disable) { + Event9.set_generator(event_generator); + return Event9; + } + else + #endif + #if defined(EVSYS_CHANNEL8) + if(Event8.get_generator() == event::gen::disable) { + Event8.set_generator(event_generator); + return Event8; + } + else + #endif + #if defined(EVSYS_CHANNEL7) + if(Event7.get_generator() == event::gen::disable) { + Event7.set_generator(event_generator); + return Event7; + } + else + #endif + #if defined(EVSYS_CHANNEL6) + if(Event6.get_generator() == event::gen::disable) { + Event6.set_generator(event_generator); + return Event6; + } + else + #endif + #if defined(EVSYS_CHANNEL5) + if(Event5.get_generator() == event::gen::disable) { + Event5.set_generator(event_generator); + return Event5; + } + else + #endif + #if defined(EVSYS_CHANNEL4) + if(Event4.get_generator() == event::gen::disable) { + Event4.set_generator(event_generator); + return Event4; + } + else + #endif + #if defined(EVSYS_CHANNEL3) + if(Event3.get_generator() == event::gen::disable) { + Event3.set_generator(event_generator); + return Event3; + } + else + #endif + #if defined(EVSYS_CHANNEL2) + if(Event2.get_generator() == event::gen::disable) { + Event2.set_generator(event_generator); + return Event2; + } + else + #endif + #if defined(EVSYS_CHANNEL1) + if(Event1.get_generator() == event::gen::disable) { + Event1.set_generator(event_generator); + return Event1; + } + else + #endif + #if defined(EVSYS_CHANNEL0) + if(Event0.get_generator() == event::gen::disable) { + Event0.set_generator(event_generator); + return Event0; + } + else + #endif + return channel; // if we're on this branch, we know chan is Event_empty + } +} + + +/** + * @brief Returns the Event channel number a particular user is connected to + * + * @param event_user The event user to check + * @return int8_t Event channel number. + * Returns -1 if not connected to any event channel + */ +int8_t Event::get_user_channel_number(event::user::user_t event_user) { + // Figure out what user register to read from to based on the passed parameter + volatile uint8_t *user_register = &EVSYS_USERCCLLUT0A + (volatile uint8_t&)event_user; + + // Return which channel the user is connected to + return *user_register - 1; +} + + +/** + * @brief Returns the Event channel object a particular user is connected to + * + * @param event_user The event user to check + * @return Event& Event channel object. Returns the Event_empty object if the + * user is not connected to any event channel + */ +Event& Event::get_user_channel(event::user::user_t event_user) { + int8_t ch_number = get_user_channel_number(event_user); + + #if defined(EVSYS_CHANNEL0) + if(Event0.channel_number == ch_number) { + return Event0; + } + #endif + #if defined(EVSYS_CHANNEL1) + if(Event1.channel_number == ch_number) { + return Event1; + } + #endif + #if defined(EVSYS_CHANNEL2) + if(Event2.channel_number == ch_number) { + return Event2; + } + #endif + #if defined(EVSYS_CHANNEL3) + if(Event3.channel_number == ch_number) { + return Event3; + } + #endif + #if defined(EVSYS_CHANNEL4) + if(Event4.channel_number == ch_number) { + return Event4; + } + #endif + #if defined(EVSYS_CHANNEL5) + if(Event5.channel_number == ch_number) { + return Event5; + } + #endif + #if defined(EVSYS_CHANNEL6) + if(Event6.channel_number == ch_number) { + return Event6; + } + #endif + #if defined(EVSYS_CHANNEL7) + if(Event7.channel_number == ch_number) { + return Event7; + } + #endif + #if defined(EVSYS_CHANNEL8) + if(Event8.channel_number == ch_number) { + return Event8; + } + #endif + #if defined(EVSYS_CHANNEL9) + if(Event9.channel_number == ch_number) { + return Event9; + } + #endif + + #if defined(EVSYS_CHANNEL0) + else { + return Event_empty; + } + #endif +} + + +/** + * @brief Sets a user for a particular event channel + * + * @param event_user The event user to connect to a particular channel + */ +void Event::set_user(event::user::user_t event_user) { + // Figure out what user register to write to based on the passed parameter + uint8_t event_user_mask = event_user & 0x7F; + + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + volatile uint8_t *user_register = &EVSYS_ASYNCUSER0 + (volatile uint8_t&)event_user_mask; + #else + volatile uint8_t *user_register = &EVSYS_USERCCLLUT0A + (volatile uint8_t&)event_user_mask; + #endif + + // Connect user to the channel we're working with + *user_register = channel_number + 1; + + // Set PORTMUX pin swap for EVOUT if selected as channel generator + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + if(event_user >= 0x08 && event_user <= 0x0A) { + PORTMUX.CTRLA |= (1 << (event_user - 0x08)); + } + #else + if(event_user & 0x80) { + #if defined(MEGACOREX) + PORTMUX_EVSYSROUTEA |= (1 << ((event_user & 0x7F) - 0x09)); + #elif defined(__AVR_DA__) + PORTMUX_EVSYSROUTEA |= (1 << ((event_user & 0x7F) - 0x0E)); + #elif defined(__AVR_DB__) || defined(__AVR_DD__) || defined(TINY_2_SERIES) + PORTMUX_EVSYSROUTEA |= (1 << ((event_user & 0x7F) - 0x0D)); + #endif + } + #endif +} + + +/** + * @brief Sets an Arduino pin as a user for a particular event channel + * + * @param pin_number The Arduino pin number to use as a channel user + * @return uint8_t Event channel user enum + (for instance event::user::evouta_pin_pa2 pin PIN_PA2 is passed) + * Returns -1 if invalid pin is passed + */ +int8_t Event::set_user_pin(uint8_t pin_number) { + uint8_t port = digitalPinToPort(pin_number); + uint8_t port_pin = digitalPinToBitPosition(pin_number); + int8_t event_user = -1; + + if(port != NOT_A_PIN && port_pin != NOT_A_PIN) { + uint8_t evout_user = (uint8_t)event::user::evouta_pin_pa2; + if(port_pin == 2) { + event_user = (event::user::user_t)(evout_user + port); + } + #if !defined(TINY_0_SERIES) && !defined(TINY_1_SERIES) + else if(port_pin == 7) { + event_user = (event::user::user_t)(evout_user + port); + } + + #endif + else { + return -1; + } + set_user((event::user::user_t)event_user); + } + return event_user; +} + + +/** + * @brief Clears/removed a user from a particular event channel if set + * + * @param event_user The event user to remove from a particular channel + */ +void Event::clear_user(event::user::user_t event_user) { + // Figure out what user register to write to based on the passed parameter + uint8_t event_user_mask = event_user & 0x7F; + volatile uint8_t *user_register = &EVSYS_USERCCLLUT0A + (volatile uint8_t&)event_user_mask; + + // Disconnect from event generator + *user_register = 0x00; + + // Clear PORTMUX pin swap for EVOUT if selected as channel generator + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + if(event_user >= 0x08 && event_user <= 0x0A) { + PORTMUX.CTRLA &= ~(1 << (event_user - 0x08)); + } + #else + if(event_user & 0x80) { + #if defined(MEGACOREX) + PORTMUX_EVSYSROUTEA &= ~(1 << ((event_user & 0x7F) - 0x09)); + #elif defined(__AVR_DA__) + PORTMUX_EVSYSROUTEA &= ~(1 << ((event_user & 0x7F) - 0x0E)); + #elif defined(__AVR_DB__) || defined(__AVR_DD__) || defined(TINY_2_SERIES) + PORTMUX_EVSYSROUTEA &= ~(1 << ((event_user & 0x7F) - 0x0D)); + #endif + } + #endif +} + + +/** + * @brief Creates a software event for a particular event channel + * + */ +void Event::soft_event() { + // Write to the bit that represent the channel in the strobe register + #if defined(EVSYS_STROBE) + // megaAVR 0-series calls the register EVSYS.STROBE + EVSYS.STROBE = (1 << channel_number); + #elif defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + // Channels 0 and 1 are the sync channels, which are strobbed with the syncstrobe registers. The others are the async channels, + // strobed with the asyncstrobe. Since the sync strobe has only 2 possible thing s to strobe, bit 0 or bit 1 corresponding to byte + // values 1 and 2, we can just add 1 to the byte value to achieve that. + if(channel_number < 2) { + EVSYS.SYNCSTROBE = (channel_number + 1); + } + else { + EVSYS.ASYNCSTROBE = (1 << (channel_number - 2)); + } + #else + // Everything newer calls the registers EVSYS.SWEVENTA or SWEVENTB for the few devices lucky enough to have more than 8 channels. + #if defined(EVSYS_SWEVENTB) + if(channel_number < 8) { + EVSYS.SWEVENTA = (1 << channel_number); + } + else { + /* Dirty trick: No available part has more than 10 event channels. + * So if we are strobing one of those last two, the value we are writing to the register is iwith 1 or 2 (as with sync channel + * on tiny 0/1). So channel number is 8 or 9, subtract 7 to get 1 or 2, and write that. + * Doesn't save much flash, but variable-shift operations are surprisignly inefficient in speed. The case for SWEVENTA involves + * a loop, 5 clocks in duration per bit + */ + EVSYS.SWEVENTB = channel_number - 7; + } + #else + EVSYS.SWEVENTA = (1 << channel_number); + #endif + #endif +} + + +/** + * @brief Creates a software event for a particular event channel with a set + * time duration + * + * @param length Length in CPU clock cycles + */ +void Event::long_soft_event(uint8_t length) { + uint8_t channel = channel_number; + uint16_t strobeaddr; + #if defined(EVSYS_STROBE) + strobeaddr = (uint16_t)&EVSYS_STROBE; + #elif defined(EVSYS_SYNCSTROBE) + if(channel > 1) + strobeaddr = (uint16_t)&EVSYS_ASYNCSTROBE; + else + strobeaddr = (uint16_t)&EVSYS_SYNCSTROBE; + #elif defined(EVSYS_SWEVENTB) + if(channel > 7) { + channel -= 8; + strobeaddr = (uint16_t)&EVSYS_SWEVENTB; + } + else { + strobeaddr = (uint16_t)&EVSYS_SWEVENTA; + } + #elif defined(EVSYS_SWEVENTA) + strobeaddr = (uint16_t)&EVSYS_SWEVENTA; + #else + #error "Don't know the strobe register!" + #endif + channel = (1 << channel); + __asm__ __volatile__ ( + "in r0, 0x3F" "\n\t" // Save SREG + "cli" "\n\t" // Interrupts off + "cpi %1, 4" "\n\t" + "brcs long_soft2" "\n\t" // Less than 4 -> 2 + "breq long_soft4" "\n\t" // Equal to 4 -> 4 + "cpi %1, 10" "\n\t" // Compare with 8 + "brcs long_soft6" "\n\t" // Less than 10 (but more than 4) -> 6 + "breq long_soft10""\n\t" // Equal to 10 -> 10 + "st Z, %0" "\n\t" // Otherwise they get 16. + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "long_soft10:" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "long_soft6:" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "long_soft4:" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "long_soft2:" "\n\t" + "st Z, %0" "\n\t" + "st Z, %0" "\n\t" + "out 0x3f, r0" "\n" // Restore SREG, reenable interrupts + ::"r"((uint8_t) channel),"d"((uint8_t) length),"z" ((uint16_t) strobeaddr)); +} + + +/** + * @brief Static function used to get the generator number the analog + * comparator peripheral + * + * @param comp Analog comparator struct + * @return event::gen::generator_t generator type + */ +event::gen::generator_t Event::gen_from_peripheral(AC_t& comp) +{ + #if defined(TINY_1_SERIES) && PROGMEM_SIZE > 8192 + // badCall("gen_from_peripheral() does not support channel-specific generators. The AC's larger 1-series are."); + #else + #if defined(AC0) + if(&comp == &AC0) { + return event::gen::ac0_out; + } + #if defined(AC1) + else if(&comp == &AC1) { + return event::gen::ac1_out; + } + #if defined(AC2) + else if(&comp == &AC2) { + return event::gen::ac2_out; + } + #endif + #endif + #endif + #endif + return (event::gen::generator_t) -1; +} + + +/** + * @brief Static function used to get the generator type from the CCL peripheral + * + * @param logic CCL struct + * @param logic_block Logic block number (0, 1, 2 or 3 for megaAVR-0's) + * @return event::gen::generator_t generator type + */ +event::gen::generator_t Event::gen_from_peripheral(CCL_t& logic, uint8_t logic_block) { + uint8_t retval = -1; + if(&logic == &CCL) { + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + if(logic_block < 2) + #elif defined(CCL_LUT4CTRLA) + if(logic_block < 6) + #else + if(logic_block < 4) + #endif + { + retval = (int8_t)(event::gen::ccl0_out) + logic_block; + } + } + return (event::gen::generator_t)retval; +} + + +/** + * @brief Static function used to get the possible users the CCL peripheral has + * to offer + * + * @param logic CCL struct + * @param user_type + * @return event::user::user_t CCL user number. + */ +event::user::user_t Event::user_from_peripheral(CCL_t& logic, uint8_t user_type) { + uint8_t retval = -1; + if(&logic == &CCL) { + #if !defined(TINY_0_SERIES) && !defined(TINY_1_SERIES) + #if defined(CCL_TRUTH4) + if(user_type < 13) + #else + if(user_type < 9) + #endif + { + retval = user_type; + } + #else + if(user_type < 5) { + retval = user_type + 2; + } + #endif + } + return (event::user::user_t)retval; +} + + +/** + * @brief Static function used to get the generator type from timer A + * + * @param logic TCA struct + * @param event_type TCA has multiple generators. This parameter provides the number, + * and ranges from 0 to 4 for megaAVR-0's + * @return event::gen::generator_t generator type + */ +event::gen::generator_t Event::gen_from_peripheral(TCA_t& timer, uint8_t event_type) { + uint8_t retval = -1; + if(event_type < 5) { + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + retval = event_type + 2; + #else + if(&TCA0 == &timer) { + retval = event_type + 0x80; + } + #if defined(TCA1) + else if(&TCA1 == &timer) { + retval = event_type += 0x88; + } + #endif + #endif + } + return (event::gen::generator_t)retval; +} + + +/** + * @brief Static function used to get the possible users the TCA timer has to offer + * + * @param timer TCA struct + * @param user_type TCA has only has one user on megaAVR-0's. + * Leave this parameter unused + * @return event::user::user_t TCA user number + */ +event::user::user_t Event::user_from_peripheral(TCA_t& timer, uint8_t user_type) { + uint8_t user = -1; + + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) || defined(MEGACOREX) + if(user_type != 0) { + return (event::user::user_t) -1; + } + #else + if(user_type > 1) { + return (event::user::user_t) -1; + } + #endif + user = user_type; // 0 or 1 for event user a or b (on parts with both, or 0 for parts that only have one + #if defined(TCA1) + if(&timer == &TCA1) { + user += 2; + } else + #endif + if(&timer != &TCA0) { + return (event::user::user_t) -1; + } + #if defined(__AVR_DA__) + user += 0x1B; + #elif defined(__AVR_DB__) || defined(__AVR_DD__) + user += 0x1A; + #elif defined(MEGACOREX) + user += 0x13; + #elif defined(TINY_2_SERIES) + user += 0x0E; + #else + user += 0x10; + #endif + return (event::user::user_t)user; +} + + +/** + * @brief Static function used to get the generator type from timer B + * + * @param timer TCB struct + * @param event_type TCB only has one generators on megaAVR-0's. + * Leave this parameter unused + * @return event::gen::generator_t generator type + */ +event::gen::generator_t Event::gen_from_peripheral(TCB_t& timer, uint8_t event_type) { + int8_t gentype = -1; + #if defined(TINY_0_OR_1_SERIES) + // badCall("gen_from_peripheral() does not support channel-specific generators. The TCBs on 0/1-series are."); + #else + #if defined(MEGACOREX) // Dx-series and 2-series have ovf event, others don't. + if(event_type != 1) { + return (event::gen::generator_t) -1; + } + else { + gentype = 0; + } + #else + if(event_type < 2) { + gentype = event_type; + } + #endif + if(&timer == &TCB0) { + gentype += (uint8_t)event::gen::tcb0_capt; + } else + #if defined(TCB1) + if (&timer == &TCB1) { + gentype += (uint8_t)event::gen::tcb1_capt; + } else + #endif + #if defined(TCB2) + if (&timer == &TCB2) { + gentype += (uint8_t)event::gen::tcb2_capt; + } else + #endif + #if defined(TCB3) + if (&timer == &TCB3) { + gentype += (uint8_t)event::gen::tcb3_capt; + } else + #endif + #if defined(TCB4) + if (&timer == &TCB4) { + gentype += (uint8_t)event::gen::tcb4_capt; + } else + #endif + { + gentype = -1; + } + #endif + return (event::gen::generator_t) gentype; +} + + +/** + * @brief Static function used to get the possible users the TCB timer has to offer + * + * @param timer TCB struct + * @param user_type + * @return event::user::user_t TCA user number + */ +event::user::user_t Event::user_from_peripheral(TCB_t& timer, uint8_t user_type) { + uint8_t user = -1; + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) || defined(MEGACOREX) // Dx-series and 2-series have event count input, others don't. + if (user_type != 1) { + return (event::user::user_t) -1; + } + else { + user = 0; + } + #else + if (user_type < 2) { + user = user_type; + } + #endif + if (&timer == &TCB0) { + user += (uint8_t)event::user::tcb0_capt; + } else + #if defined(TCB1) + if (&timer == &TCB1) { + user += (uint8_t)event::user::tcb1_capt; + } else + #endif + #if defined(TCB2) + if (&timer == &TCB2) { + user += (uint8_t)event::user::tcb2_capt; + } else + #endif + #if defined(TCB3) + if (&timer == &TCB3) { + user += (uint8_t)event::user::tcb3_capt; + } else + #endif + #if defined(TCB4) + if (&timer == &TCB4) { + user += (uint8_t)event::user::tcb4_capt; + } else + #endif + { + user = -1; + } + return (event::user::user_t)user; +} + + +/** + * @brief Static function used to get the possible users the USART peripheral has + * to offer + * + * @param usart USART struct + * @return event::user::user_t USART related event channel user + */ +event::user::user_t Event::user_from_peripheral(USART_t& usart) { + if(&usart == &USART0) { + return event::user::usart0_irda; + } + #if defined(USART1) + else if(&usart == &USART1) { + return event::user::usart1_irda; + } + #endif + #if defined(USART2) + else if(&usart == &USART2) { + return event::user::usart2_irda; + } + #endif + #if defined(USART3) + else if(&usart == &USART3) { + return event::user::usart3_irda; + } + #endif + #if defined(USART4) + else if(&usart == &USART4) { + return event::user::usart4_irda; + } + #endif + #if defined(USART5) + else if(&usart == &USART5) { + return event::user::usart5_irda; + } + #endif + return (event::user::user_t) -1; +} + + +/** + * @brief Starts the event generator for a particular event channel + * + * @param state Optional parameter. Defaults to true + */ +void Event::start(bool state) { + if(state) { + // Write event generator setting to EVSYS_CHANNELn register + channel_address = generator_type; + } + else { + // Disable event generator + channel_address = event::gen::disable; + } +} + + +/** + * @brief Stops the event generator for a particular event channel + * + */ +void Event::stop() { + start(false); +} diff --git a/megaavr/libraries/Event/src/Event.h b/megaavr/libraries/Event/src/Event.h new file mode 100644 index 0000000..512391e --- /dev/null +++ b/megaavr/libraries/Event/src/Event.h @@ -0,0 +1,1381 @@ +#ifndef EVENT_H +#define EVENT_H + +#include + +#if defined(MEGATINYCORE) + #if (MEGATINYCORE_SERIES == 0) + #define TINY_0_SERIES + #elif (MEGATINYCORE_SERIES == 1) + #define TINY_1_SERIES + #elif (MEGATINYCORE_SERIES == 2) + #define TINY_2_SERIES + #endif +#endif + +namespace event { +#if defined(MEGACOREX) || defined(DXCORE) + // Features present on all generator channels + namespace gen { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + updi_synch = 0x01, + rtc_ovf = 0x06, + rtc_cmp = 0x07, + ccl0_out = 0x10, + ccl1_out = 0x11, + ccl2_out = 0x12, + ccl3_out = 0x13, + ac0_out = 0x20, +#if defined(AC1) + ac1_out = 0x21, +#endif +#if defined(AC2) + ac2_out = 0x22, +#endif + adc0_ready = 0x24, + usart0_xck = 0x60, + usart1_xck = 0x61, + usart2_xck = 0x62, +#if defined(USART3) + usart3_xck = 0x63, +#endif + spi0_sck = 0x68, + tca0_ovf_lunf = 0x80, + tca0_hunf = 0x81, + tca0_cmp0 = 0x84, + tca0_cmp1 = 0x85, + tca0_cmp2 = 0x86, + tcb0_capt = 0xA0, + tcb0 = 0xA0, + tcb1_capt = 0xA2, + tcb1 = 0xA2, + tcb2_capt = 0xA4, + tcb2 = 0xA4, +#if defined(TCB3) + tcb3_capt = 0xA6, + tcb3 = 0xA6, +#endif +#if defined(TCB4) + tcb4_capt = 0xA8, + tcb4 = 0xA8, +#endif +#if defined(__AVR_DA__) || defined(__AVR_DB__) + ccl4_out = 0x14, + ccl5_out = 0x15, + zcd0_out = 0x30, + zcd1_out = 0x31, +#if defined(ZCD2) + zcd2_out = 0x32, +#endif +#if defined(USART4) + usart4_xck = 0x64, +#endif +#if defined(USART5) + usart5_xck = 0x65, +#endif + spi1_sck = 0x69, +#if defined(TCA1) + tca1_ovf_lunf = 0x88, + tca1_hunf = 0x89, + tca1_cmp0 = 0x8C, + tca1_cmp1 = 0x8D, + tca1_cmp2 = 0x8E, +#endif +#endif // defined(__AVR_DA__) || defined(__AVR_DB__) +#if defined(DXCORE) +// These are present on every modern part released since the 0/1-series and will probably continue to be, so check + tcb0_ovf = 0xA1, + tcb1_ovf = 0xA3, +#if defined(TCB2) + tcb2_ovf = 0xA5, +#endif +#if defined(TCB3) + tcb3_ovf = 0xA7, +#endif +#if defined(TCB4) + tcb4_ovf = 0xA9, +#endif +#endif +#if defined(TCD0) + tcd0_cmpbclr = 0xB0, + tcd0_cmpaset = 0xB1, + tcd0_cmpbset = 0xB2, + tcd0_progev = 0xB3, +#endif +#if defined(MVIO) + mvio_ok = 0x05, +#endif +#if defined(ZCD3) + zcd3_out = 0x30, // The ZCD is numbered differently, I think just because it's on different pins. Still has the same event channel +#endif +#if defined(__AVR_DB__) + opamp0_ready = 0x34, + opamp1_ready = 0x35, +#if defined(OPAMP2) + opamp2_ready = 0x36, +#endif +#endif // defined(__AVR_DB__) + }; + }; + +// Features unique to event generator channel 0 +#if defined(EVSYS_CHANNEL0) + namespace gen0 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, + pin_pa0 = 0x40, + pin_pa1 = 0x41, +#if !defined(DXCORE) || defined(PIN_PA2) + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, +#endif +#if defined(PIN_PB0) + pin_pb0 = 0x48, + pin_pb1 = 0x49, + pin_pb2 = 0x4A, + pin_pb3 = 0x4B, + pin_pb4 = 0x4C, + pin_pb5 = 0x4D, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x4E, + pin_pb7 = 0x4F, +#endif + }; + }; +#endif + +// Features unique to event generator channel 1 +#if defined(EVSYS_CHANNEL1) + namespace gen1 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, + pin_pa0 = 0x40, + pin_pa1 = 0x41, +#if defined(PIN_PA2) + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, +#endif +#if defined(PIN_PB0) + pin_pb0 = 0x48, + pin_pb1 = 0x49, + pin_pb2 = 0x4A, + pin_pb3 = 0x4B, + pin_pb4 = 0x4C, + pin_pb5 = 0x4D, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x4E, + pin_pb7 = 0x4F, +#endif + }; + }; +#endif + +// Features unique to event generator channel 2 +#if defined(EVSYS_CHANNEL2) + namespace gen2 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, +#if !defined(DD_14_PINS) // Can't just check PIN_PC0 - the 0-pin of any port with any pins present is always defined by DxCore. + // I considered both ways, but there are to many reasons we need to have the 0-pin defined. + pin_pc0 = 0x40, +#endif + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, + pin_pc6 = 0x46, + pin_pc7 = 0x47, +#endif +#if defined(PIN_PD1) // See above for note on PIN_PD0 and why we can't test that, this even impacts DBs. +#if !defined(MVIO) || defined(__AVR_ATmegax09__) || defined(Dx_48_PINS) || defined(Dx_64_PINS) + pin_pd0 = 0x48, +#endif + pin_pd1 = 0x49, + pin_pd2 = 0x4A, + pin_pd3 = 0x4B, +#endif + pin_pd4 = 0x4C, + pin_pd5 = 0x4D, + pin_pd6 = 0x4E, + pin_pd7 = 0x4F, + }; +}; +#endif + +// Features unique to event generator channel 3 +#if defined(EVSYS_CHANNEL3) + namespace gen3 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, +#if !defined(DD_14_PINS) + pin_pc0 = 0x40, +#endif + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, + pin_pc6 = 0x46, + pin_pc7 = 0x47, +#endif +#if defined(PIN_PD1) // See above for note on PIN_PD0 and why we can't test that, this even impacts DBs. +#if !defined(MVIO) || defined(__AVR_ATmegax09__) || defined(Dx_48_PINS) || defined(Dx_64_PINS) + pin_pd0 = 0x48, +#endif + pin_pd1 = 0x49, + pin_pd2 = 0x4A, + pin_pd3 = 0x4B, +#endif + pin_pd4 = 0x4C, + pin_pd5 = 0x4D, + pin_pd6 = 0x4E, + pin_pd7 = 0x4F, + }; + }; +#endif + +// Features unique to event generator channel 4 +#if defined(EVSYS_CHANNEL4) + namespace gen4 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, +#if defined(PIN_PE0) + pin_pe0 = 0x40, + pin_pe1 = 0x41, + pin_pe2 = 0x42, + pin_pe3 = 0x43, +#endif +#if defined(PIN_PE4) + pin_pe4 = 0x44, + pin_pe5 = 0x45, + pin_pe6 = 0x46, + pin_pe7 = 0x47, +#endif + pin_pf0 = 0x48, + pin_pf1 = 0x49, +#if defined(PIN_PF2) + pin_pf2 = 0x4A, + pin_pf3 = 0x4B, + pin_pf4 = 0x4C, + pin_pf5 = 0x4D, +#endif + pin_pf6 = 0x4E, +#if defined(PIN_PF7) + pin_pf7 = 0x4F, +#endif + }; + }; +#endif + +// Features unique to event generator channel 5 +#if defined(EVSYS_CHANNEL5) + namespace gen5 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, +#if defined(PIN_PE0) + pin_pe0 = 0x40, + pin_pe1 = 0x41, + pin_pe2 = 0x42, + pin_pe3 = 0x43, +#endif +#if defined(PIN_PE4) + pin_pe4 = 0x44, + pin_pe5 = 0x45, + pin_pe6 = 0x46, + pin_pe7 = 0x47, +#endif + pin_pf0 = 0x48, + pin_pf1 = 0x49, +#if defined(PIN_PF2) + pin_pf2 = 0x4A, + pin_pf3 = 0x4B, + pin_pf4 = 0x4C, + pin_pf5 = 0x4D, +#endif + pin_pf6 = 0x4E, +#if defined(PIN_PF7) + pin_pf7 = 0x4F, +#endif + }; + }; +#endif + +// Features unique to event generator channel 6 +#if defined(EVSYS_CHANNEL6) + namespace gen6 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, +#if defined(PIN_PG0) + pin_pg0 = 0x40, + pin_pg1 = 0x41, + pin_pg2 = 0x42, + pin_pg3 = 0x43, + pin_pg4 = 0x44, + pin_pg5 = 0x45, + pin_pg6 = 0x46, + pin_pg7 = 0x47, +#endif + }; + }; +#endif + +// Features unique to event generator channel 7 +#if defined(EVSYS_CHANNEL7) + namespace gen7 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, +#if defined(PIN_PG0) + pin_pg0 = 0x40, + pin_pg1 = 0x41, + pin_pg2 = 0x42, + pin_pg3 = 0x43, + pin_pg4 = 0x44, + pin_pg5 = 0x45, + pin_pg6 = 0x46, + pin_pg7 = 0x47, +#endif + }; + }; +#endif + +// Features unique to event generator channel 8 +#if defined(EVSYS_CHANNEL8) + namespace gen8 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, + }; + }; +#endif + +// Features unique to event generator channel 9 +#if defined(EVSYS_CHANNEL9) + namespace gen9 { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, + }; + }; +#endif + + +// Generator users + namespace user { + enum user_t : uint8_t { +#if defined(MEGACOREX) + ccl0_event_a = 0x00, + ccl0_event_b = 0x01, + ccl1_event_a = 0x02, + ccl1_event_b = 0x03, + ccl2_event_a = 0x04, + ccl2_event_b = 0x05, + ccl3_event_a = 0x06, + ccl3_event_b = 0x07, + adc0_start = 0x08, + evouta_pin_pa2 = 0x09, +#if defined(PIN_PB2) + evoutb_pin_pb2 = 0x0A, +#endif + evoutc_pin_pc2 = 0x0B, + evoutd_pin_pd2 = 0x0C, +#if defined(PIN_PE2) + evoute_pin_pe2 = 0x0D, +#endif + evoutf_pin_pf2 = 0x0E, + usart0_irda = 0x0F, + usart1_irda = 0x10, + usart2_irda = 0x11, +#if defined(USART3) + usart3_irda = 0x12, +#endif + tca0 = 0x13, + tca0_cnt_a = 0x13, + tcb0 = 0x14, + tcb0_capt = 0x14, + tcb1 = 0x15, + tcb1_capt = 0x15, + tcb2 = 0x16, + tcb2_capt = 0x16, +#if defined(TCB3) + tcb3 = 0x17, + tcb3_capt = 0x17, +#endif + // "Unofficial" user generators. Uses EVOUT, but swaps the output pin using PORTMUX + evouta_pin_pa7 = 0x89, +#if defined(PIN_PC7) + evoutc_pin_pc7 = 0x8B, +#endif + evoutd_pin_pd7 = 0x8C, +#endif // defined(MEGACOREX) + +#if defined(__AVR_DA__) + ccl0_event_a = 0x00, + ccl0_event_b = 0x01, + ccl1_event_a = 0x02, + ccl1_event_b = 0x03, + ccl2_event_a = 0x04, + ccl2_event_b = 0x05, + ccl3_event_a = 0x06, + ccl3_event_b = 0x07, +#if defined(LUT4) + ccl4_event_a = 0x08, + ccl4_event_b = 0x09, + ccl5_event_a = 0x0A, + ccl5_event_b = 0x0B, +#endif + adc0_start = 0x0C, + ptc_start = 0x0D, + evouta_pin_pa2 = 0x0E, +#if defined(PIN_PB2) + evoutb_pin_pb2 = 0x0F, +#endif + evoutc_pin_pc2 = 0x10, + evoutd_pin_pd2 = 0x11, +#if defined(PIN_PE2) + evoute_pin_pe2 = 0x12, +#endif +#if defined(PIN_PF2) + evoutf_pin_pf2 = 0x13, +#endif +#if defined(PIN_PG2) + evoutg_pin_pg2 = 0x14, +#endif + usart0_irda = 0x15, + usart1_irda = 0x16, + usart2_irda = 0x17, +#if defined(USART5) + usart3_irda = 0x18, +#endif +#if defined(USART4) + usart4_irda = 0x19, +#endif +#if defined(USART5) + usart5_irda = 0x1A, +#endif + tca0 = 0x1B, + tca0_cnt_a = 0x1B, + tca0_cnt_b = 0x1C, + tca1 = 0x1D, + tca1_cnt_a = 0x1D, + tca1_cnt_b = 0x1E, + tcb0_capt = 0x1F, + tcb0 = 0x1F, + tcb0_cnt = 0x20, + tcb1_capt = 0x21, + tcb1 = 0x21, + tcb1_cnt = 0x22, + tcb2_capt = 0x23, + tcb2 = 0x23, + tcb2_cnt = 0x24, +#if defined(TCB3) + tcb3_capt = 0x25, + tcb3 = 0x25, + tcb3_cnt = 0x26, +#endif +#if defined(TCB4) + tcb4_capt = 0x27, + tcb4 = 0x27, + tcb4_cnt = 0x28, +#endif + tcd0_in_a = 0x29, + tcd0_in_b = 0x2A, + // "Unofficial" user generators. Uses EVOUT, but swaps the output pin using PORTMUX + evouta_pin_pa7 = 0x8E, +#if defined(PIN_PB7) + evoutb_pin_pb7 = 0x8F, +#endif +#if defined(PIN_PC7) + evoutc_pin_pc7 = 0x90, +#endif + evoutd_pin_pd7 = 0x91, +#if defined(PIN_PE7) + evoute_pin_pe7 = 0x92, +#endif + // evoutf_pin_pf7 = 0x93, never available on DA/DB +#if defined(PIN_PG7) + evoutg_pin_pg7 = 0x94, +#endif +#endif // defined(__AVR_DA__) +#if defined(__AVR_DB__) + ccl0_event_a = 0x00, + ccl0_event_b = 0x01, + ccl1_event_a = 0x02, + ccl1_event_b = 0x03, + ccl2_event_a = 0x04, + ccl2_event_b = 0x05, + ccl3_event_a = 0x06, + ccl3_event_b = 0x07, +#if defined(LUT4) + ccl4_event_a = 0x08, + ccl4_event_b = 0x09, + ccl5_event_a = 0x0A, + ccl5_event_b = 0x0B, +#endif + adc0_start = 0x0C, + evouta_pin_pa2 = 0x0D, +#if defined(PIN_PB2) + evoutb_pin_pb2 = 0x0E, +#endif + evoutc_pin_pc2 = 0x0F, + evoutd_pin_pd2 = 0x10, +#if defined(PIN_PE2) + evoute_pin_pe2 = 0x11, +#endif +#if defined(PIN_PF2) + evoutf_pin_pf2 = 0x12, +#endif +#if defined(PIN_PG2) + evoutg_pin_pg2 = 0x13, +#endif + usart0_irda = 0x14, + usart1_irda = 0x15, + usart2_irda = 0x16, +#if defined(USART3) + usart3_irda = 0x17, +#endif +#if defined(USART4) + usart4_irda = 0x18, +#endif +#if defined(USART5) + usart5_irda = 0x19, +#endif + tca0 = 0x1A, + tca0_cnt_a = 0x1A, + tca0_cnt_b = 0x1B, + tca1 = 0x1C, + tca1_cnt_a = 0x1C, + tca1_cnt_b = 0x1D, + tcb0_capt = 0x1E, + tcb0_cnt = 0x1F, + tcb1_capt = 0x20, + tcb1_cnt = 0x21, + tcb2_capt = 0x22, + tcb2_cnt = 0x23, +#if defined(TCB3) + tcb3_capt = 0x24, + tcb3_cnt = 0x25, +#endif +#if defined(TCB4) + tcb4_capt = 0x26, + tcb4_cnt = 0x27, +#endif + tcd0_in_a = 0x28, + tcd0_in_b = 0x29, + opamp0_enable = 0x2A, + opamp0_disable = 0x2B, + opamp0_dump = 0x2C, + opamp0_drive = 0x2D, + opamp1_enable = 0x2E, + opamp1_disable = 0x2F, + opamp1_dump = 0x30, + opamp1_drive = 0x31, +#if defined(OPAMP2) + opamp2_enable = 0x32, + opamp2_disable = 0x33, + opamp2_dump = 0x34, + opamp2_drive = 0x35, +#endif + // "Unofficial" user generators. Uses EVOUT, but swaps the output pin using PORTMUX + evouta_pin_pa7 = 0x8D, +#if defined(PIN_PB7) + evoutb_pin_pb7 = 0x8E, +#endif +#if defined(PIN_PC7) + evoutc_pin_pc7 = 0x8F, +#endif + evoutd_pin_pd7 = 0x90, +#if defined(PIN_PE7) + evoute_pin_pe7 = 0x91, +#endif +#if defined(PIN_PG7) + evoutg_pin_pg7 = 0x93, +#endif +#endif // defined(__AVR_DB__) + +#if defined(__AVR_DD__) + ccl0_event_a = 0x00, + ccl0_event_b = 0x01, + ccl1_event_a = 0x02, + ccl1_event_b = 0x03, + ccl2_event_a = 0x04, + ccl2_event_b = 0x05, + ccl3_event_a = 0x06, + ccl3_event_b = 0x07, + adc0_start = 0x0C, +#if defined(PIN_PA2) // not on 14-pin ones. + evouta_pin_pa2 = 0x0D, +#endif + evoutc_pin_pc2 = 0x0F, +#if defined(PIN_PD2) // only on 28 or 32 pin ones. + evoutd_pin_pd2 = 0x10, +#endif +#if defined(PIN_PF2) // only on 32-pin ones. + evoutf_pin_pf2 = 0x12, +#endif + usart0_irda = 0x14, + usart1_irda = 0x15, + tca0 = 0x1A, + tca0_cnt_a = 0x1A, + tca0_cnt_b = 0x1B, + tcb0 = 0x1E, + tcb0_capt = 0x1E, + tcb0_cnt = 0x1F, + tcb1 = 0x20, + tcb1_capt = 0x20, + tcb1_cnt = 0x21, + tcb2 = 0x22, + tcb2_capt = 0x22, + tcb2_cnt = 0x23, + tcd0_in_a = 0x28, + tcd0_in_b = 0x29, +#if defined(PIN_PA7) // not on 14-pin ones. + evouta_pin_pa7 = 0x8D, +#endif +#if defined(PIN_PC7) + evoutc_pin_pc7 = 0x8F, +#endif + evoutd_pin_pd7 = 0x90, +#endif // __AVR_DD__ + }; +}; +// END MegaCorex and DxCore definitions + + +// tinyAVR-2 definitions +#elif defined(TINY_2_SERIES) + namespace gen { + enum generator_t : uint8_t { + disable = 0x00, + updi_synch = 0x1, + rtc_ovf = 0x6, + rtc_cmp = 0x7, + ccl0_out = 0x10, + ccl1_out = 0x11, + ccl2_out = 0x12, + ccl3_out = 0x13, + ac0_out = 0x20, + adc0_ready = 0x24, + adc0_sample = 0x25, + adc0_window = 0x26, + usart0_xck = 0x60, + usart1_xck = 0x61, + spi0_sck = 0x68, + tca0_ovf_lunf = 0x80, + tca0_hunf = 0x81, + tca0_cmp0 = 0x84, + tca0_cmp1 = 0x85, + tca0_cmp2 = 0x86, + tcb0 = 0xA0, + tcb0_capt = 0xA0, + tcb0_ovf = 0xA1, + tcb1 = 0xA2, + tcb1_capt = 0xA2, + tcb1_ovf = 0xA3, + }; + }; + + namespace gen0 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, + pin_pa0 = 0x40, + pin_pa1 = 0x41, + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, + pin_pb0 = 0x40, + pin_pb1 = 0x41, + pin_pb2 = 0x42, + pin_pb3 = 0x43, +#if defined(PIN_PB4) + pin_pb4 = 0x44, + pin_pb5 = 0x45, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x46, + pin_pb7 = 0x47, +#endif + }; + }; + + namespace gen1 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, + pin_pa0 = 0x40, + pin_pa1 = 0x41, + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, + pin_pb0 = 0x40, + pin_pb1 = 0x41, + pin_pb2 = 0x42, + pin_pb3 = 0x43, +#if defined(PIN_PB4) + pin_pb4 = 0x44, + pin_pb5 = 0x45, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x46, + pin_pb7 = 0x47, +#endif + }; + }; + + namespace gen2 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, +#if defined(PIN_PC0) + pin_pc0 = 0x40, + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, +#endif + pin_pa0 = 0x40, + pin_pa1 = 0x41, + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, + }; + }; + + namespace gen3 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, +#if defined(PIN_PC0) + pin_pc0 = 0x40, + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, +#endif + pin_pa0 = 0x40, + pin_pa1 = 0x41, + pin_pa2 = 0x42, + pin_pa3 = 0x43, + pin_pa4 = 0x44, + pin_pa5 = 0x45, + pin_pa6 = 0x46, + pin_pa7 = 0x47, + }; + }; + + namespace gen4 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div8192 = 0x08, + rtc_div4096 = 0x09, + rtc_div2048 = 0x0A, + rtc_div1024 = 0x0B, + pin_pb0 = 0x40, + pin_pb1 = 0x41, + pin_pb2 = 0x42, + pin_pb3 = 0x43, +#if defined(PIN_PB4) + pin_pb4 = 0x44, + pin_pb5 = 0x45, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x46, + pin_pb7 = 0x47, +#endif +#if defined(PIN_PC0) + pin_pc0 = 0x40, + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, +#endif + }; + }; + + namespace gen5 { + enum generator_t : uint8_t { + disable = 0x00, + rtc_div512 = 0x08, + rtc_div256 = 0x09, + rtc_div128 = 0x0A, + rtc_div64 = 0x0B, + pin_pb0 = 0x40, + pin_pb1 = 0x41, + pin_pb2 = 0x42, + pin_pb3 = 0x43, +#if defined(PIN_PB4) + pin_pb4 = 0x44, + pin_pb5 = 0x45, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x46, + pin_pb7 = 0x47, +#endif +#if defined(PIN_PC0) + pin_pc0 = 0x40, + pin_pc1 = 0x41, + pin_pc2 = 0x42, + pin_pc3 = 0x43, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x44, + pin_pc5 = 0x45, +#endif + }; + }; + + + namespace user { + enum user_t : uint8_t { + ccl0_event_a = 0x00, + ccl0_event_b = 0x01, + ccl1_event_a = 0x02, + ccl1_event_b = 0x03, + ccl2_event_a = 0x04, + ccl2_event_b = 0x05, + ccl3_event_a = 0x06, + ccl3_event_b = 0x07, + adc0_start = 0x08, + evouta_pin_pa2 = 0x09, + evouta_pin_pa7 = 0x89, + evoutb_pin_pb2 = 0x0A, +#if defined(PIN_PB7) + evoutb_pin_pb7 = 0x8A, +#endif +#if defined(PIN_PC2) + evoutc_pin_pc2 = 0x0B, +#endif + usart0_irda = 0x0C, + usart1_irda = 0x0D, + tca0 = 0x0E, + tca0_cnt_a = 0x0E, + tca0_cnt_b = 0x0F, + tcb0 = 0x11, + tcb0_capt = 0x11, + tcb0_cnt = 0x12, + tcb1 = 0x13, + tcb1_capt = 0x13, + tcb1_cnt = 0x14, + }; + }; + +// tinyAVR-0/1 definitions +#elif defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + namespace gen0 { + enum generator_t : uint8_t { +#if defined(PIN_PC0) + pin_pc0 = 0x07, + pin_pc1 = 0x08, + pin_pc2 = 0x09, + pin_pc3 = 0x0A, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x0B, + pin_pc5 = 0x0C, +#endif + pin_pa0 = 0x0D, + pin_pa1 = 0x0E, + pin_pa2 = 0x0F, + pin_pa3 = 0x10, + pin_pa4 = 0x11, + pin_pa5 = 0x12, + pin_pa6 = 0x13, + pin_pa7 = 0x14, +#if (PROGMEM_SIZE > 8192 && defined(TINY_1_SERIES)) + tcb1 = 0x15, + tcb1_capt = 0x15, +#endif + }; + }; + namespace gen2 { + enum generator_t : uint8_t { + pin_pa0 = 0x0A, + pin_pa1 = 0x0B, + pin_pa2 = 0x0C, + pin_pa3 = 0x0D, + pin_pa4 = 0x0E, + pin_pa5 = 0x0F, + pin_pa6 = 0x10, + pin_pa7 = 0x11, + updi = 0x12, +#if (PROGMEM_SIZE > 8192 && defined(TINY_1_SERIES)) + ac1_out = 0x13, + ac2_out = 0x14, +#endif + }; + }; + +// Only on parts with > 8 pins does this have any unique options +#if defined(__AVR_ATtinyxy4__) || defined(__AVR_ATtinyxy6__) || defined(__AVR_ATtinyxy7__) + namespace gen3 { + enum generator_t : uint8_t { + pin_pb0 = 0x0A, + pin_pb1 = 0x0B, + pin_pb2 = 0x0C, + pin_pb3 = 0x0D, +#if defined(PIN_PB4) + pin_pb4 = 0x0E, + pin_pb5 = 0x0F, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x10, + pin_pb7 = 0x11, +#endif +#if (PROGMEM_SIZE > 8192 && MEGATINYCORE_SERIES == 1) + ac1_out = 0x12, + ac2_out = 0x13, +#endif + }; + }; +#endif + +#if defined(TINY_1_SERIES) + +#if defined(__AVR_ATtinyxy4__) || defined(__AVR_ATtinyxy6__) || defined(__AVR_ATtinyxy7__) + // Only 1-series parts have second sync channel. + // Only on parts with > 8 pins does it have any unique options + namespace gen1 { + enum generator_t : uint8_t { + pin_pb0 = 0x08, + pin_pb1 = 0x09, + pin_pb2 = 0x0A, + pin_pb3 = 0x0B, +#if defined(PIN_PB0) + pin_pb4 = 0x0C, + pin_pb5 = 0x0D, +#endif +#if defined(PIN_PB6) + pin_pb6 = 0x0E, + pin_pb7 = 0x0F, +#endif +#if (PROGMEM_SIZE > 8192) // Only 16/32k 1-series, but only 1-series is here + tcb1 = 0x10, + tcb1_capt = 0x10, +#endif + }; + }; +#endif + + // Only 1-series parts have third and fourth async sync channel. + // and only parts with 20/24 pins, or the 1614 have any items on this list available +#if !(defined(__AVR_ATtinyxy2__) || (defined(__AVR_ATtinyxy4__) && PROGMEM_SIZE <= 8192)) + namespace gen4 { + enum generator_t : uint8_t { +#if defined(PIN_PC0) + pin_pc0 = 0x0A, + pin_pc1 = 0x0B, + pin_pc2 = 0x0C, + pin_pc3 = 0x0D, +#endif +#if defined(PIN_PC4) + pin_pc4 = 0x0E, + pin_pc5 = 0x0F, +#endif +#if (PROGMEM_SIZE > 8192) // Only 16/32k 1-series, but only 1-series is here + ac1_out = 0x10, + ac2_out = 0x11, +#endif + }; + }; +#endif + + namespace gen5 { + enum generator_t : uint8_t { + rtc_div8192 = 0x0A, + rtc_div4096 = 0x0B, + rtc_div2048 = 0x0C, + rtc_div1024 = 0x0D, + rtc_div512 = 0x0E, + rtc_div256 = 0x0F, + rtc_div128 = 0x10, + rtc_div64 = 0x11, +#if (PROGMEM_SIZE > 8192) // Only 16/32k 1-series + ac1_out = 0x12, + ac2_out = 0x13, +#endif + }; + }; +#endif // end of 1-series only part. + + namespace gens { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + tcb0 = 0x01, + tcb0_capt = 0x01, + tca0_ovf_lunf = 0x02, + tca0_hunf = 0x03, + tca0_cmp0 = 0x04, + tca0_cmp1 = 0x05, + tca0_cmp2 = 0x06, + }; + }; + + namespace gen { + enum generator_t : uint8_t { + disable = 0x00, + off = 0x00, + ccl_lut0 = 0x01, + ccl_lut1 = 0x02, + ac0_out = 0x03, +#if defined(TINY_1_SERIES) + tcd0_cmpbclr = 0x04, + tcd0_cmpaset = 0x05, + tcd0_cmpbset = 0x06, + tcd0_progev = 0x07, +#endif + rtc_ovf = 0x08, + rtc_cmp = 0x09, + }; + }; + + namespace user { + enum user_t : uint8_t { + tcb0 = 0x00, + tcb0_capt = 0x00, + adc0_start = 0x01, + ccl0_event_a = 0x02, + ccl1_event_a = 0x03, + ccl0_event_b = 0x04, + ccl1_event_b = 0x05, + tcd0_in_a = 0x06, + tcd0_in_b = 0x07, + evouta_pin_pa2 = 0x08, + evoutb_pin_pb2 = 0x09, + evoutc_pin_pc2 = 0x0A, + tcb1 = 0x0B, + tcb1_capt = 0x0B, + adc1_start = 0x0c, + tca0 = 0x10, + tca0_cnt_a = 0x10, + usart0_irda = 0x11, + }; + }; +#endif // TINY_0_SERIES || TINY_1_SERIES +}; + +// Legacy definitions +namespace user { using namespace event::user; }; +namespace gen { using namespace event::gen; }; +#if defined(EVSYS_CHANNEL0) +namespace gen0 { using namespace event::gen0; }; +#endif +#if defined(EVSYS_CHANNEL1) +namespace gen1 { using namespace event::gen1; }; +#endif +#if defined(EVSYS_CHANNEL2) +namespace gen2 { using namespace event::gen2; }; +#endif +#if defined(EVSYS_CHANNEL3) +namespace gen3 { using namespace event::gen3; }; +#endif +#if defined(EVSYS_CHANNEL4) +namespace gen4 { using namespace event::gen4; }; +#endif +#if defined(EVSYS_CHANNEL5) +namespace gen5 { using namespace event::gen5; }; +#endif +#if defined(EVSYS_CHANNEL6) +namespace gen6 { using namespace event::gen6; }; +#endif +#if defined(EVSYS_CHANNEL7) +namespace gen7 { using namespace event::gen7; }; +#endif +#if defined(EVSYS_CHANNEL8) +namespace gen8 { using namespace event::gen8; }; +#endif +#if defined(EVSYS_CHANNEL9) +namespace gen9 { using namespace event::gen9; }; +#endif +#if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) +namespace gens { using namespace event::gens; }; +#endif + +class Event { + public: + Event(uint8_t channel_num, volatile uint8_t &channel_addr); + uint8_t get_channel_number(); + static Event& get_channel(uint8_t channel_number); + static Event& get_generator_channel(event::gen::generator_t generator); + static Event& get_generator_channel(uint8_t generator_pin); + uint8_t get_generator(); + void set_generator(event::gen::generator_t generator); + static Event& assign_generator(event::gen::generator_t event_generator); + void set_generator(uint8_t pin_number); + static Event& assign_generator_pin(uint8_t port, uint8_t port_pin); + static Event& assign_generator_pin(uint8_t pin_number); + static int8_t get_user_channel_number(event::user::user_t event_user); + static Event& get_user_channel(event::user::user_t event_user); + void set_user(event::user::user_t event_user); + int8_t set_user_pin(uint8_t pin_number); + static void clear_user(event::user::user_t event_user); + void soft_event(); + void long_soft_event(uint8_t length); + // event_types: They start from 0x00 for inputs, outputs start at 0x40 + static event::gen::generator_t gen_from_peripheral(AC_t& comp); + static event::gen::generator_t gen_from_peripheral(CCL_t& logic, uint8_t event_type = 0); + static event::user::user_t user_from_peripheral(CCL_t& logic, uint8_t user_type = 0); + static event::gen::generator_t gen_from_peripheral(TCA_t& timer, uint8_t event_type = 0); + static event::user::user_t user_from_peripheral(TCA_t& timer, uint8_t user_type = 0); + static event::gen::generator_t gen_from_peripheral(TCB_t& timer, uint8_t event_type = 0); + static event::user::user_t user_from_peripheral(TCB_t& timer, uint8_t user_type = 0); + static event::user::user_t user_from_peripheral(USART_t& usart); + void start(bool state = true); + void stop(); + + #if defined(EVSYS_CHANNEL0) + void get_generator_channel(event::gen0::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen0::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL1) + void get_generator_channel(event::gen1::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen1::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL2) + void get_generator_channel(event::gen2::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen2::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL3) + void get_generator_channel(event::gen3::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen3::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL4) + void get_generator_channel(event::gen4::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen4::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL5) + void get_generator_channel(event::gen5::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen5::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL6) + void get_generator_channel(event::gen6::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen6::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL7) + void get_generator_channel(event::gen7::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen7::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL8) + void get_generator_channel(event::gen8::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen8::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(EVSYS_CHANNEL9) + void get_generator_channel(event::gen9::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen9::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + #if defined(TINY_0_SERIES) || defined(TINY_1_SERIES) + void get_generator_channel(event::gens::generator_t generator) { get_generator_channel((event::gen::generator_t)generator); } + void set_generator(event::gen::generator_t generator) { set_generator((event::gen::generator_t)generator); } + #endif + + private: + const uint8_t channel_number; // Holds the event generator channel number + volatile uint8_t &channel_address; // Reference to the event channel address + uint8_t generator_type; // Generator type the event channel is using +}; + +#if defined(MEGACOREX) || defined(DXCORE) || defined(TINY_2_SERIES) + #if defined(EVSYS_CHANNEL0) + extern Event Event0; + #endif + #if defined(EVSYS_CHANNEL1) + extern Event Event1; + #endif + #if defined(EVSYS_CHANNEL2) + extern Event Event2; + #endif + #if defined(EVSYS_CHANNEL3) + extern Event Event3; + #endif + #if defined(EVSYS_CHANNEL4) + extern Event Event4; + #endif + #if defined(EVSYS_CHANNEL5) + extern Event Event5; + #endif + #if defined(EVSYS_CHANNEL6) + extern Event Event6; + #endif + #if defined(EVSYS_CHANNEL7) + extern Event Event7; + #endif + #if defined(EVSYS_CHANNEL8) + extern Event Event8; + #endif + #if defined(EVSYS_CHANNEL9) + extern Event Event9; + #endif + +// tinyAVR-0/1 +#else +#if defined(EVSYS_SYNCCH0) + extern Event Event0; + #define EventSync0 Event0 + #define EVSYS_CHANNEL0 EVSYS_SYNCCH0 +#endif +#if defined(EVSYS_SYNCCH1) + extern Event Event1; + #define EventSync1 Event1 + #define EVSYS_CHANNEL1 EVSYS_SYNCCH1 +#endif +#if defined(EVSYS_ASYNCCH0) + extern Event Event2; + #define EventAsync0 Event2 + #define EVSYS_CHANNEL2 EVSYS_ASYNCCH0 +#endif +#if defined(EVSYS_ASYNCCH1) + extern Event Event3; + #define EventAsync1 Event3 + #define EVSYS_CHANNEL3 EVSYS_ASYNCCH1 +#endif +#if defined(EVSYS_ASYNCCH2) + extern Event Event4; + #define EventAsync2 Event4 + #define EVSYS_CHANNEL4 EVSYS_ASYNCCH2 +#endif +#if defined(EVSYS_ASYNCCH3) + extern Event Event5; + #define EventAsync3 Event5 + #define EVSYS_CHANNEL5 EVSYS_ASYNCCH3 +#endif +#if defined(EVSYS_SYNCUSER0) + #define EVSYS_USERTCA0CNTA EVSYS_SYNCUSER0 +#endif +#if defined(EVSYS_SYNCUSER1) + #define EVSYS_USERUSART0IRDA EVSYS_SYNCUSER1 +#endif +#if defined(EVSYS_ASYNCUSER0) + #define EVSYS_USERTCB0CAPT EVSYS_ASYNCUSER0 +#endif +#if defined(EVSYS_ASYNCUSER1) + #define EVSYS_USERADC0START EVSYS_ASYNCUSER1 +#endif +#if defined(EVSYS_ASYNCUSER2) + #define EVSYS_USERCCLLUT0A EVSYS_ASYNCUSER2 +#endif +#if defined(EVSYS_ASYNCUSER3) + #define EVSYS_USERCCLLUT1A EVSYS_ASYNCUSER3 +#endif +#if defined(EVSYS_ASYNCUSER4) + #define EVSYS_USERCCLLUT0B EVSYS_ASYNCUSER4 +#endif +#if defined(EVSYS_ASYNCUSER5) + #define EVSYS_USERCCLLUT1B EVSYS_ASYNCUSER5 +#endif +#if defined(EVSYS_ASYNCUSER6) + #define EVSYS_USERTCD0INPUTA EVSYS_ASYNCUSER6 +#endif +#if defined(EVSYS_ASYNCUSER7) + #define EVSYS_USERTCD0INPUTB EVSYS_ASYNCUSER7 +#endif +#if defined(EVSYS_ASYNCUSER8) + #define EVSYS_USEREVSYSEVOUTA EVSYS_ASYNCUSER8 +#endif +#if defined(EVSYS_ASYNCUSER9) + #define EVSYS_USEREVSYSEVOUTB EVSYS_ASYNCUSER9 +#endif +#if defined(EVSYS_ASYNCUSER10) + #define EVSYS_USEREVSYSEVOUTC EVSYS_ASYNCUSER10 +#endif +#if defined(EVSYS_ASYNCUSER11) + #define EVSYS_USERTCB1CAPT EVSYS_ASYNCUSER11 +#endif +#if defined(EVSYS_ASYNCUSER12) + #define EVSYS_USERADC1START EVSYS_ASYNCUSER12 +#endif +#endif // tinyAVR-0/1 + +#endif // EVENT_H diff --git a/megaavr/libraries/HID/library.properties b/megaavr/libraries/HID/library.properties deleted file mode 100644 index 499286d..0000000 --- a/megaavr/libraries/HID/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=HID -version=1.0 -author=Arduino -maintainer=Arduino -sentence=Module for PluggableUSB infrastructure. Exposes an API for devices like Keyboards, Mice and Gamepads. -paragraph= -category=Communication -url=http://www.arduino.cc/en/Reference/HID -architectures=megaavr diff --git a/megaavr/libraries/HID/src/HID.cpp b/megaavr/libraries/HID/src/HID.cpp deleted file mode 100644 index 21ede26..0000000 --- a/megaavr/libraries/HID/src/HID.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - Permission to use, copy, modify, and/or distribute this software for - any purpose with or without fee is hereby granted, provided that the - above copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR - BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES - OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. - */ - -#include "HID.h" - -#if defined(USBCON) - -HID_& HID() -{ - static HID_ obj; - return obj; -} - -int HID_::getInterface(uint8_t* interfaceCount) -{ - *interfaceCount += 1; // uses 1 - HIDDescriptor hidInterface = { - D_INTERFACE(pluggedInterface, 1, USB_DEVICE_CLASS_HUMAN_INTERFACE, HID_SUBCLASS_NONE, HID_PROTOCOL_NONE), - D_HIDREPORT(descriptorSize), - D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01) - }; - return USB_SendControl(0, &hidInterface, sizeof(hidInterface)); -} - -int HID_::getDescriptor(USBSetup& setup) -{ - // Check if this is a HID Class Descriptor request - if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; } - if (setup.wValueH != HID_REPORT_DESCRIPTOR_TYPE) { return 0; } - - // In a HID Class Descriptor wIndex cointains the interface number - if (setup.wIndex != pluggedInterface) { return 0; } - - int total = 0; - HIDSubDescriptor* node; - for (node = rootNode; node; node = node->next) { - int res = USB_SendControl(TRANSFER_PGM, node->data, node->length); - if (res == -1) - return -1; - total += res; - } - - // Reset the protocol on reenumeration. Normally the host should not assume the state of the protocol - // due to the USB specs, but Windows and Linux just assumes its in report mode. - protocol = HID_REPORT_PROTOCOL; - - return total; -} - -uint8_t HID_::getShortName(char *name) -{ - name[0] = 'H'; - name[1] = 'I'; - name[2] = 'D'; - name[3] = 'A' + (descriptorSize & 0x0F); - name[4] = 'A' + ((descriptorSize >> 4) & 0x0F); - return 5; -} - -void HID_::AppendDescriptor(HIDSubDescriptor *node) -{ - if (!rootNode) { - rootNode = node; - } else { - HIDSubDescriptor *current = rootNode; - while (current->next) { - current = current->next; - } - current->next = node; - } - descriptorSize += node->length; -} - -int HID_::SendReport(uint8_t id, const void* data, int len) -{ - auto ret = USB_Send(pluggedEndpoint, &id, 1); - if (ret < 0) return ret; - auto ret2 = USB_Send(pluggedEndpoint | TRANSFER_RELEASE, data, len); - if (ret2 < 0) return ret2; - return ret + ret2; -} - -bool HID_::setup(USBSetup& setup) -{ - if (pluggedInterface != setup.wIndex) { - return false; - } - - uint8_t request = setup.bRequest; - uint8_t requestType = setup.bmRequestType; - - if (requestType == REQUEST_DEVICETOHOST_CLASS_INTERFACE) - { - if (request == HID_GET_REPORT) { - // TODO: HID_GetReport(); - return true; - } - if (request == HID_GET_PROTOCOL) { - // TODO: Send8(protocol); - return true; - } - if (request == HID_GET_IDLE) { - // TODO: Send8(idle); - } - } - - if (requestType == REQUEST_HOSTTODEVICE_CLASS_INTERFACE) - { - if (request == HID_SET_PROTOCOL) { - // The USB Host tells us if we are in boot or report mode. - // This only works with a real boot compatible device. - protocol = setup.wValueL; - return true; - } - if (request == HID_SET_IDLE) { - idle = setup.wValueL; - return true; - } - if (request == HID_SET_REPORT) - { - //uint8_t reportID = setup.wValueL; - //uint16_t length = setup.wLength; - //uint8_t data[length]; - // Make sure to not read more data than USB_EP_SIZE. - // You can read multiple times through a loop. - // The first byte (may!) contain the reportID on a multreport. - //USB_RecvControl(data, length); - } - } - - return false; -} - -HID_::HID_(void) : PluggableUSBModule(1, 1, epType), - rootNode(NULL), descriptorSize(0), - protocol(HID_REPORT_PROTOCOL), idle(1) -{ - epType[0] = EP_TYPE_INTERRUPT_IN; - PluggableUSB().plug(this); -} - -int HID_::begin(void) -{ - return 0; -} - -#endif /* if defined(USBCON) */ diff --git a/megaavr/libraries/HID/src/HID.h b/megaavr/libraries/HID/src/HID.h deleted file mode 100644 index ad2b06b..0000000 --- a/megaavr/libraries/HID/src/HID.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - Copyright (c) 2015, Arduino LLC - Original code (pre-library): Copyright (c) 2011, Peter Barrett - - Permission to use, copy, modify, and/or distribute this software for - any purpose with or without fee is hereby granted, provided that the - above copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR - BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES - OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, - WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - SOFTWARE. - */ - -#ifndef HID_h -#define HID_h - -#include -#include -#include "api/PluggableUSB.h" - -#if defined(USBCON) - -#define _USING_HID - -// HID 'Driver' -// ------------ -#define HID_GET_REPORT 0x01 -#define HID_GET_IDLE 0x02 -#define HID_GET_PROTOCOL 0x03 -#define HID_SET_REPORT 0x09 -#define HID_SET_IDLE 0x0A -#define HID_SET_PROTOCOL 0x0B - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// HID subclass HID1.11 Page 8 4.2 Subclass -#define HID_SUBCLASS_NONE 0 -#define HID_SUBCLASS_BOOT_INTERFACE 1 - -// HID Keyboard/Mouse bios compatible protocols HID1.11 Page 9 4.3 Protocols -#define HID_PROTOCOL_NONE 0 -#define HID_PROTOCOL_KEYBOARD 1 -#define HID_PROTOCOL_MOUSE 2 - -// Normal or bios protocol (Keyboard/Mouse) HID1.11 Page 54 7.2.5 Get_Protocol Request -// "protocol" variable is used for this purpose. -#define HID_BOOT_PROTOCOL 0 -#define HID_REPORT_PROTOCOL 1 - -// HID Request Type HID1.11 Page 51 7.2.1 Get_Report Request -#define HID_REPORT_TYPE_INPUT 1 -#define HID_REPORT_TYPE_OUTPUT 2 -#define HID_REPORT_TYPE_FEATURE 3 - -typedef struct -{ - uint8_t len; // 9 - uint8_t dtype; // 0x21 - uint8_t addr; - uint8_t versionL; // 0x101 - uint8_t versionH; // 0x101 - uint8_t country; - uint8_t desctype; // 0x22 report - uint8_t descLenL; - uint8_t descLenH; -} HIDDescDescriptor; - -typedef struct -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; - -class HIDSubDescriptor { -public: - HIDSubDescriptor *next = NULL; - HIDSubDescriptor(const void *d, const uint16_t l) : data(d), length(l) { } - - const void* data; - const uint16_t length; -}; - -class HID_ : public PluggableUSBModule -{ -public: - HID_(void); - int begin(void); - int SendReport(uint8_t id, const void* data, int len); - void AppendDescriptor(HIDSubDescriptor* node); - -protected: - // Implementation of the PluggableUSBModule - int getInterface(uint8_t* interfaceCount); - int getDescriptor(USBSetup& setup); - bool setup(USBSetup& setup); - uint8_t getShortName(char* name); - -private: - unsigned int epType[1]; - - HIDSubDescriptor* rootNode; - uint16_t descriptorSize; - - uint8_t protocol; - uint8_t idle; -}; - -// Replacement for global singleton. -// This function prevents static-initialization-order-fiasco -// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use -HID_& HID(); - -#define D_HIDREPORT(length) { 9, 0x21, 0x01, 0x01, 0, 1, 0x22, lowByte(length), highByte(length) } - -#else - -#error "No Native USB support available on this board" - -#endif // USBCON - -#endif // HID_h diff --git a/megaavr/libraries/Logic/README.md b/megaavr/libraries/Logic/README.md new file mode 100644 index 0000000..c2fc999 --- /dev/null +++ b/megaavr/libraries/Logic/README.md @@ -0,0 +1,284 @@ +# Logic +A library for interfacing with the CCL (Configurable Custom Logic) peripherals of the megaAVR-0 MCUs. +Developed by MCUdude for use with [MegaCoreX](https://github.com/MCUdude/MegaCoreX), adapted to megaAVR ATtiny parts by [Tadashi G. Takaoka](https://github.com/tgtakaoka), and to Dx-series by [Spence Konde](https://github.com/SpenceKonde). +The library is compatible with all these parts, but this README only covers the megaAVR-0 functionality. +The megaAVR-0 has four independent internal logic blocks that can be individually customized. +All of the megaTiny parts have 2 blocks of CCL available. The examples included assume the use of megaTinyCore in their defines to detect the applicable part. +More useful information about CCL can be found in the [Microchip Application Note TB3218](http://ww1.microchip.com/downloads/en/AppNotes/TB3218-Getting-Started-with-CCL-90003218A.pdf) and in the [megaAVR-0 family data sheet](http://ww1.microchip.com/downloads/en/DeviceDoc/megaAVR0-series-Family-Data-Sheet-DS40002015B.pdf), part in question. + + +## Logic +Class for interfacing with the built-in logic block (sometimes referred to as `LUT`s - "LookUp Table"). +Use the predefined objects `Logic0`, `Logic1`, `Logic2` and `Logic3`. The logic blocks are paired, each pair sharing a single sequencer and `feedback` channel. +Additionally, each logic block is associated with a specific port, having it's input on pins 0 through 2, and it's output on pin 3 or 6. In order: `PORTA`, `PORTC`, `PORTD` and `PORTF`. + +These objects expose all configuration options as member variables as documented below, as well as member methods to set the applicable registers. + + +### enable +Variable for enabling or disabling a logic block. +Accepted values: +```c++ +true; // Enable the current logic block +false; // Disable the current logic block +``` + +##### Usage +```c++ +Logic0.enable = true; // Enable logic block 0 +``` + +##### Default state +`Logic0.enable` defaults to `false` if not specified in the user program. + +### input0..input2 +Variable for setting what mode input 0..2 on a logic block should have. + +Accepted values for megaAVR 0-series parts: + +``` c++ +logic::in::masked; // Pin not in use +logic::in::unused; // Pin not in use +logic::in::disable; // Pin not in use +logic::in::feedback; // Connect output of sequencer (if used) or even-numbered logic block (n or n-1) to this input +logic::in::link; // Connect output of logic block n+1 to this input +logic::in::event_0; // Connect input to event a +logic::in::event_a; // Connect input to event a +logic::in::event_1; // Connect input to event b +logic::in::event_b; // Connect input to event b +logic::in::pin; // Connect input to CCL IN0, IN1, IN2 for input 0, 1, 2, do not change pinMode +logic::in::input_pullup; // Connect input to CCL IN0, IN1, IN2 for input 0, 1, 2, set input, pullup on +logic::in::input; // Connect input to CCL IN0, IN1, IN2 for input 0, 1, 2, set input, pullup off +logic::in::input_no_pullup; // Connect input to CCL IN0, IN1, IN2 for input 0, 1, 2, set input, pullup off +logic::in::ac; // Connect input to the output of the internal analog comparator (input 0,1,2 from AC0,1,2) +logic::in::uart; // Connect input to UART TX. Input 0 connects to UART0 TX, input 1 to UART1 TX, and input 2 to UART2 TX +logic::in::spi; // Connect input to SPI. Input 0 and 1 connects to MOSI, and input 2 connects to SCK +logic::in::tca0; // Connect input to TCA0. Input 0 connects to WO0, input 1 to WO1 and input2 to WO2 +logic::in::tca; // Connect input to TCA0. Input 0 connects to WO0, input 1 to WO1 and input2 to WO2 +logic::in::tcb; // Connect input to TCB. Input 0 connects to TCB0 W0, input 1 to TCB1 WO, and input 2 to TCB2 WO. +``` + +Notes specific to ATmega parts +* On 28-pin versions of the ATmega 4808, 3208, 1608, and 808, IN1 and IN2 inputs for logic3 are not available. If all input pins for all logic blocks are needed, the event system can be used. +* According to the datasheet for SPI as input source, inputs 0 and 1 connect to MOSI. Thus, on these parts, there is no input to the logic blocks for MISO. +* If input on the highest-number Logic block is set to link, it will use the output of Logic0 +* If you need to link input to logic block other than the n+1 block, you can use the event system for that. + + +##### Usage +``` c++ +Logic0.input0 = logic::in::link; // Connect output from block 1 to input 0 of block 0 +Logic0.input1 = logic::in::input; // Connect the input 1 from block 0 to its GPIO +Logic0.input2 = logic::in::input_pullup; // Connect the input 2 from block 0 to its GPIO, with pullup on +``` + +##### Default state +`LogicN.inputN` defaults to `logic::in::unused` if not specified in the user program. + + +### output +Variable for changing the logic block output pin behavior. Note that the output of the logic block still can be used internally if the output pin is disabled. +Accepted values: +```c++ +logic::out::disable; // Disable the output GPIO pin. Useful when triggering an interrupt instead. +logic::out::enable; // Enable the output GPIO pin +``` + +##### Usage +```c++ +Logic0.output = logic::out::disable; // Disable the output GPIO pin. +``` + +##### Default state +`LogicN.output` defaults to `logic::out::disable` if not specified in the user program. + + +### output_swap +Variable for pin swapping the physical output pin to its alternative position. See the pinout diagrams in the main MegaCoreX README for detailed info. +Accepted values: +```c++ +logic::out::no_swap; // Use default pin position, pin 3 on the port +logic::out::pin_swap; // Use alternative position, pin 6 on the port +``` + +##### Usage +```c++ +Logic0.output_swap = logic::out::no_swap; // No pin swap for output of block0 +``` + +##### Default state +`LogicN.output_swap` defaults to `logic::out::no_swap` if not specified in the user program. + + +### filter +Variable to control whether the output passes through a synchronizer or filter. +Useful when multiple logic blocks are connected internally to prevent race conditions and glitches that could arise due to the asynchronous nature of CCL clocking. +Alternately, the delay itself may be desirable, or it can be combined with a configuration which would oscillate asynchronously to instead output a prescaled clock, which could, in turn, be used with "clock on event" to provide a type B timer with a prescaled clock. +Either filter or synchronizer is required for edge detector, below. +Accepted values: +```c++ +logic::filter::disable; // No filter used, asynchronous output. +logic::filter::synchronizer; // Connect synchronizer to output; delays output by 2 clock cycles. +logic::filter::synch; // Syntactic sugar for synchronizer +logic::filter::sync; // Syntactic sugar for synchronizer +logic::filter::filter; // Connect filter to output; delays output by 4 clock cycles, only passes output that is stable for >2 clock cycles. +``` + +##### Usage +```c++ +Logic0.filter = logic::filter::filter; // Enable filter on output of block 0 +``` + +##### Default state +`LogicN.filter` defaults to `logic::filter::disable` if not specified in the user program. + + +### clocksource +Variable to set the clock source for the logic block; this is used for the synchronizer and filter only (otherwise, the logic blocks are asynchronous). +If sequential logic is used, it is clocked from the clock source used by the even-numbered logic block. +Accepted values: +```c++ +logic::clocksource::clk_per; // Clock from the peripheral clock (ie, system clock) +logic::clocksource::in2; // Clock from the selected input2; it is treated as a 0 in the truth table. +``` + +##### Usage +```c++ +Logic0.clocksource = logic::clocksource::clk_per; +``` + +##### Default state +`LogicN.clocksource` defaults to `logic::clocksource::clk_per` if not specified in the user program. + + +### edgedetect +Variable for controlling use of the edge detector. The edge detector can be used to generate a pulse when detecting a rising edge on its input. To detect a falling edge, the TRUTH table should be programmed to provide inverted output. In order to avoid unpredictable behavior, a valid filter option must be enabled. Note that this is likely only of use when the output is being used for sequential logic or as the input to another logic block; it looks particularly useful on the odd LUT input to a J-K flip-flop sequential logic unit. + +```c++ +logic::edgedetect::disable; // No edge detection used +logic::edgedetect::enable; // Edge detection used +``` + +#### Usage +```c++ +Logic0.edgedetect = logic::edgedetect::enable; +``` + +##### Default state +`LogicN.edgedetect` defaults to `logic::edgedetect::disable` if not specified in the user program. + + +### sequencer +Variable for connecting a "sequencer" to the logic block output - these are latches or flip-flops which remember a state. There is 1 sequencer per 2 CCLs, each controls one of the two inputs to a flip flop or latch; this option is ignored for the odd-numbered logic blocks. Flip-flops are clocked from the same clock source as the even logic block, latches are asynchronous. + +Accepted values: +```c++ +logic::sequencer::disable; // No sequencer connected +logic::sequencer::d_flip_flop; // D flip flop sequencer connected +logic::sequencer::jk_flip_flop; // JK flip flop sequencer connected +logic::sequencer::d_latch; // Gated D latch sequencer connected - note that on most megaAVR parts, this doesn't work. See the Errata. +logic::sequencer::rs_latch; // RS latch sequencer connected +``` + +##### Usage +```c++ +Logic0.sequencer = logic::sequencer::disable; // Disable sequencer +``` + +##### Default state +`LogicN.sequencer` defaults to `logic::sequencer::disable` if not specified in the user program. + + +### truth +Variable to hold the 8-bit truth table value. +Accepted values between 0x00 and 0xFF. + +##### Usage +```c++ +Logic0.truth = 0xF0; +``` + +##### Default state +`LogicN.truth` defaults to `0x00` if not specified in the user program. + + + +## init() +Method for initializing a logic block; the settings you have previously configured will be applied and pins configured as requested at this time only. + +##### Usage +```c++ +Logic0.init(); // Initialize block 0 +Logic1.init(); // Initialize block 1 +``` + + +## start() +Method for starting the CCL hardware after desired blocks have been initialized using `LogicN.init()`. + +##### Usage +```c++ +Logic::start(); // Start CCL hardware +``` + + +## stop() +Method for stopping the CCL hardware, for example to reconfigure the logic blocks. + +##### Usage +```c++ +Logic::stop(); // Stop CCL +``` + +## Reconfiguring +There are TWO levels of "enable protection" on the CCL hardware. According to the Silicon Errata, only one of these is intended. +As always, it's anyone's guess when or if this issue will be corrected in a future silicon revision. +The intended enable-protection is that a given logic block cannot be reconfigured while enabled. +This is handled by `init()` - you can write your new setting to a logic block, call `LogicN.init()` and it will briefly disable the logic block, make the changes, and reenable it. + +The unintended layer is that no logic block can be reconfigured without also disabling the whole CCL system. +Changes can be freely made to the `Logic` classes, however, only the `init()` method will apply those changes, and you must call `Logic::stop()` before calling them, and `Logic::start()` afterwards. + +##### Example +```c++ +// logic blocks 0, 1 configured, initialized, and in use +Logic1.truth=0x55; // new truth table +Logic1.input2=logic::in::tca0; // and different input 2 +Logic3.enabled=true; // enable another LUT +Logic3.input0=logic::in::link; // Use link from LUT0 +Logic3.input1=logic::in::ac; // and the analog comparator +Logic3.input2=logic::in::pin; // and the LUT3 IN2 pin +Logic3.truth=0x79; // truth table for LUT3 + +Logic3.attachInterrupt(RISING,interruptFunction); + +// Interrupt now attached - but - Logic3 not enabled, and logic1 is using old settings + +Logic::stop(); // have to turn off Logic0 too, even though I might not want to +Logic1.init(); // apply changes to logic block 1 +Logic3.init(); // apply settings to logic block 3 for the first time +Logic::start(); // reenable +``` + +## attachInterrupt() +Method for enabling interrupts for a specific block. +Valid arguments for the third parameters are `RISING`, `FALLING` and `CHANGE`. + +##### Usage +```c++ +Logic0.attachInterrupt(blinkLED, RISING); // Runthe blinkLED function when the putput goes high + +void blinkLED() +{ + digitalWrite(myLedPin, CHANGE); +} +``` + + +## detachInterrupt() +Method for disabling interrupts for a specific block. + +##### Usage +```c++ +Logic0.detachInterrupt(); // Disable interrupts for block 0 +``` diff --git a/megaavr/libraries/Logic/examples/Five_input_NOR/Five_input_NOR.ino b/megaavr/libraries/Logic/examples/Five_input_NOR/Five_input_NOR.ino new file mode 100644 index 0000000..71fd7ef --- /dev/null +++ b/megaavr/libraries/Logic/examples/Five_input_NOR/Five_input_NOR.ino @@ -0,0 +1,56 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Five_input_NOR.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use two logic blocks to get five inputs. | +| The output of block 1 is connected to one of the inputs of block 0. | +| With the correct truth tables values we can make the output of | +| block 0 go high when all inputs are low. | +| | +| See Microchip's application note TB3218 for more information. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 1 + // Logic block 1 has three inputs, PC0, PC1 and PC2. + // It's output, PC3 is disabled because we connect the output signal to block 0 internally + Logic1.enable = true; // Enable logic block 1 + Logic1.input0 = logic::in::input_pullup; // Set PC0 as input with pullup + Logic1.input1 = logic::in::input_pullup; // Set PC1 as input with pullup + Logic1.input2 = logic::in::input_pullup; // Set PC2 as input with pullup + Logic1.output = logic::out::disable; // No output on PC3 + Logic1.filter = logic::filter::disable; // No output filter enabled + Logic1.truth = 0xFE; // Set truth table + + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // input2 is internally connected to the output of block1 (which means PA2 is freed up) + // Block 0 output on PA3 + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup + Logic0.input2 = logic::in::link; // Route output from block 1 to this input internally + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0x01; // Set truth table + + // Initialize logic block 0 and 1 + Logic0.init(); + Logic1.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Interrupt/Interrupt.ino b/megaavr/libraries/Logic/examples/Interrupt/Interrupt.ino new file mode 100644 index 0000000..12993ef --- /dev/null +++ b/megaavr/libraries/Logic/examples/Interrupt/Interrupt.ino @@ -0,0 +1,66 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Interrupt.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 3-input NOR gate using logic block 2 on PORT D. | +| We will use input on PD0, PD1 and PD2. Instead of having an output | +| pin the logic block will instead trigger an interrupt that runs a | +| user defined function. | +| | +| 3-input NOR truth table: | +| If we look at the truth table |PD2|PD1|PD0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 1 | | +| be represented as 00000001. | 0 | 0 | 1 | 0 | | +| If we convert this 8-bit | 0 | 1 | 0 | 0 | | +| binary number into hex, we | 0 | 1 | 1 | 0 | | +| get 0x01. | 1 | 0 | 0 | 0 | | +| | 1 | 0 | 1 | 0 | | +| In this example the output is | 1 | 1 | 0 | 0 | | +| true if all inputs are low. | 1 | 1 | 1 | 0 | | +| | +|***********************************************************************/ + +#include + +void setup() +{ + // Modify the serial port to match your hardware + Serial.begin(9600); + + // Initialize logic block 2 + // Logic block 2 has three inputs, PA0, PA1 and PA2. + // It has one output, but this is disabled because we're using an interrupt instead. + Logic2.enable = true; // Enable logic block 2 + Logic2.input0 = logic::in::input_pullup; // Set PD0 as input with pullup + Logic2.input1 = logic::in::input_pullup; // Set PD1 as input with pullup + Logic2.input2 = logic::in::input_pullup; // Set PD2 as input with pullup + Logic2.output = logic::out::disable; // Disable output on PD3 (we don't have to though) + Logic2.filter = logic::filter::disable; // No output filter enabled + Logic2.truth = 0x01; // Set truth table + + // Initialize logic block 2 + Logic2.init(); + + // Set interrupt (supports RISING, FALLING and CHANGE) + Logic2.attachInterrupt(interruptFunction, RISING); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} + +void interruptFunction() +{ + Serial.println("Output of logic block 2 went high!"); +} diff --git a/megaavr/libraries/Logic/examples/Three_input_AND/Three_input_AND.ino b/megaavr/libraries/Logic/examples/Three_input_AND/Three_input_AND.ino new file mode 100644 index 0000000..9f74d2e --- /dev/null +++ b/megaavr/libraries/Logic/examples/Three_input_AND/Three_input_AND.ino @@ -0,0 +1,56 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Three_input_AND.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 3-input AND gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| Here's how 0x80 turns out to be the correct value to create a 3-input | +| AND gate: | +| 3-input AND truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 0 | | +| be represented as 10000000. | 0 | 0 | 1 | 0 | | +| If we convert this 8-bit | 0 | 1 | 0 | 0 | | +| binary number into hex, we | 0 | 1 | 1 | 0 | | +| get 0x80. | 1 | 0 | 0 | 0 | | +| | 1 | 0 | 1 | 0 | | +| In this example the output pin, | 1 | 1 | 0 | 0 | | +| PA3 will go high if all three | 1 | 1 | 1 | 1 | | +| inputs are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup + Logic0.input2 = logic::in::input_pullup; // Set PA2 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0x80; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Three_input_NAND/Three_input_NAND.ino b/megaavr/libraries/Logic/examples/Three_input_NAND/Three_input_NAND.ino new file mode 100644 index 0000000..652dc2a --- /dev/null +++ b/megaavr/libraries/Logic/examples/Three_input_NAND/Three_input_NAND.ino @@ -0,0 +1,56 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Three_input_NAND.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 3-input NAND gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| Here's how 0x7F turns out to be the correct value to create a 3-input | +| NAND gate: | +| 3-input NAND truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 1 | | +| be represented as 01111111. | 0 | 0 | 1 | 1 | | +| If we convert this 8-bit | 0 | 1 | 0 | 1 | | +| binary number into hex, we | 0 | 1 | 1 | 1 | | +| get 0x7F. | 1 | 0 | 0 | 1 | | +| | 1 | 0 | 1 | 1 | | +| In this example the output pin | 1 | 1 | 0 | 1 | | +| PA3 will go low if all three | 1 | 1 | 1 | 0 | | +| inputs are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup + Logic0.input2 = logic::in::input_pullup; // Set PA2 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0x7F; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Three_input_OR/Three_input_OR.ino b/megaavr/libraries/Logic/examples/Three_input_OR/Three_input_OR.ino new file mode 100644 index 0000000..0c9b473 --- /dev/null +++ b/megaavr/libraries/Logic/examples/Three_input_OR/Three_input_OR.ino @@ -0,0 +1,56 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Three_input_OR.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 3-input OR gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| Here's how 0xFE turns out to be the correct value to create a 3-input | +| OR gate: | +| 3-input OR truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 0 | | +| be represented as 11111110. | 0 | 0 | 1 | 1 | | +| If we convert this 8-bit | 0 | 1 | 0 | 1 | | +| binary number into hex, we | 0 | 1 | 1 | 1 | | +| get 0xFE. | 1 | 0 | 0 | 1 | | +| | 1 | 0 | 1 | 1 | | +| In this example the output pin, | 1 | 1 | 0 | 1 | | +| PA3 will go high if one or more | 1 | 1 | 1 | 1 | | +| inputs are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup + Logic0.input2 = logic::in::input_pullup; // Set PA2 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0xFE; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Two_input_AND/Two_input_AND.ino b/megaavr/libraries/Logic/examples/Two_input_AND/Two_input_AND.ino new file mode 100644 index 0000000..c7ed698 --- /dev/null +++ b/megaavr/libraries/Logic/examples/Two_input_AND/Two_input_AND.ino @@ -0,0 +1,57 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Two_input_AND.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 2-input AND gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| We will only use PA0 and PA1 as inputs. When the last input is | +| disabled it will always be read as 0. | +| Here's how 0x08 turns out to be the correct value to create a 2-input | +| NAND gate: | +| 2-input AND truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 0 | | +| be represented as 00001000. | 0 | 0 | 1 | 0 | | +| If we convert this 8-bit | 0 | 1 | 0 | 0 | | +| binary number into hex, we | 0 | 1 | 1 | 1 | | +| get 0x08. | 1 | 0 | 0 | 0 | PA2 is always 0 | +| | 1 | 0 | 1 | 0 | PA2 is always 0 | +| In this example the output pin, | 1 | 1 | 0 | 0 | PA2 is always 0 | +| PA3 will only go high if the | 1 | 1 | 1 | 0 | PA2 is always 0 | +| two input pins are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0x08; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Two_input_NAND/Two_input_NAND.ino b/megaavr/libraries/Logic/examples/Two_input_NAND/Two_input_NAND.ino new file mode 100644 index 0000000..5f5e529 --- /dev/null +++ b/megaavr/libraries/Logic/examples/Two_input_NAND/Two_input_NAND.ino @@ -0,0 +1,57 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Two_input_NAND.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 2-input NAND gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| We will only use PA0 and PA1 as inputs. when the last input is | +| disabled it will always be read as 0. | +| Here's how 0xF7 turns out to be the correct value to create a 2-input | +| NAND gate: | +| 2-input NAND truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 1 | | +| be represented as 11110111. | 0 | 0 | 1 | 1 | | +| If we convert this 8-bit | 0 | 1 | 0 | 1 | | +| binary number into hex, we | 0 | 1 | 1 | 0 | | +| get 0xF7. | 1 | 0 | 0 | 1 | PA2 is always 0 | +| | 1 | 0 | 1 | 1 | PA2 is always 0 | +| In this example the output pin, | 1 | 1 | 0 | 1 | PA2 is always 0 | +| PA3 will only go low if the | 1 | 1 | 1 | 1 | PA2 is always 0 | +| two input pins are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0xF7; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/examples/Two_input_OR/Two_input_OR.ino b/megaavr/libraries/Logic/examples/Two_input_OR/Two_input_OR.ino new file mode 100644 index 0000000..de622bb --- /dev/null +++ b/megaavr/libraries/Logic/examples/Two_input_OR/Two_input_OR.ino @@ -0,0 +1,57 @@ +/***********************************************************************| +| megaAVR Configurable Custom Logic library | +| | +| Two_input_OR.ino | +| | +| A library for interfacing with the megaAVR Configurable Custom Logic. | +| Developed in 2019 by MCUdude. | +| https://github.com/MCUdude/ | +| | +| In this example we use the configurable logic peripherals the the | +| megaAVR to create a 2-input OR gate using logic block 0 on PORT A. | +| The example is pretty straight forward, but the truth table value may | +| be a little difficult to understand at first glance. | +| We will only use PA0 and PA1 as inputs. When the last input is | +| disabled it will always be read as 0. | +| Here's how 0xFE turns out to be the correct value to create a 2-input | +| OR gate: | +| 2-input OR truth table: | +| If we look at the truth table |PA2|PA1|PA0| Y | | +| to the right, we can see that |---|---|---|---| | +| all binary values for Y can | 0 | 0 | 0 | 0 | | +| be represented as 11111110. | 0 | 0 | 1 | 1 | | +| If we convert this 8-bit | 0 | 1 | 0 | 1 | | +| binary number into hex, we | 0 | 1 | 1 | 1 | | +| get 0xFE. | 1 | 0 | 0 | 1 | PA2 is always 0 | +| | 1 | 0 | 1 | 1 | PA2 is always 0 | +| In this example the output pin, | 1 | 1 | 0 | 1 | PA2 is always 0 | +| PA3 will go high if one of | 1 | 1 | 1 | 1 | PA2 is always 0 | +| the input pins are high. | +|***********************************************************************/ + +#include + +void setup() +{ + // Initialize logic block 0 + // Logic block 0 has three inputs, PA0, PA1 and PA2. + // It has one output, PA3, but can be swapped to PA6 if needed + Logic0.enable = true; // Enable logic block 0 + Logic0.input0 = logic::in::input_pullup; // Set PA0 as input with pullup + Logic0.input1 = logic::in::input_pullup; // Set PA1 as input with pullup +//Logic0.output_swap = logic::out::pin_swap; // Uncomment this line to route the output to PA6 instead of PA3 + Logic0.output = logic::out::enable; // Enable logic block 0 output pin (PA3) + Logic0.filter = logic::filter::disable; // No output filter enabled + Logic0.truth = 0xFE; // Set truth table + + // Initialize logic block 0 + Logic0.init(); + + // Start the AVR logic hardware + Logic::start(); +} + +void loop() +{ + // When using configurable custom logic the CPU isn't doing anything! +} diff --git a/megaavr/libraries/Logic/keywords.txt b/megaavr/libraries/Logic/keywords.txt new file mode 100644 index 0000000..6ad19d5 --- /dev/null +++ b/megaavr/libraries/Logic/keywords.txt @@ -0,0 +1,40 @@ +####################################### +# Syntax Coloring Map For Logic +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +start KEYWORD2 +stop KEYWORD2 +init KEYWORD2 +attachInterrupt KEYWORD2 +detachInterrupt KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Logic KEYWORD2 +Logic0 KEYWORD2 +Logic1 KEYWORD2 +Logic2 KEYWORD2 +Logic3 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +logic LITERAL1 +in LITERAL1 +out LITERAL1 +filter LITERAL1 +clocksource LITERAL1 +edgedetect LITERAL1 +sequencer LITERAL1 diff --git a/megaavr/libraries/Logic/library.properties b/megaavr/libraries/Logic/library.properties new file mode 100644 index 0000000..5c1249b --- /dev/null +++ b/megaavr/libraries/Logic/library.properties @@ -0,0 +1,10 @@ +name=Logic +version=1.2.0 +author=MCUdude and Spence Konde +maintainer=MCUdude and Spence Konde +sentence=A library for interfacing with the customizable logic in megaAVR 0-series, tinyAVR 0/1-series, and Dx-series chips. MegaCoreX version of documentation and examples. +paragraph= +category=Signal Input/Output +url=https://github.com/MCUdude/MegaCoreX +dot_a_linkage=true +architectures=megaavr diff --git a/megaavr/libraries/Logic/src/Logic.cpp b/megaavr/libraries/Logic/src/Logic.cpp new file mode 100644 index 0000000..32abadb --- /dev/null +++ b/megaavr/libraries/Logic/src/Logic.cpp @@ -0,0 +1,133 @@ +#include "Logic.h" + + +#if defined(CCL_TRUTH0) + Logic Logic0(0); +#endif +#if defined(CCL_TRUTH1) + Logic Logic1(1); +#endif +#if defined(CCL_TRUTH2) + Logic Logic2(2); +#endif +#if defined(CCL_TRUTH3) + Logic Logic3(3); +#endif +#if defined(CCL_TRUTH4) + Logic Logic4(4); +#endif +#if defined(CCL_TRUTH5) + Logic Logic5(5); +#endif + +Logic::Logic(const uint8_t block_number) + : enable(false), + input0(logic::in::masked), + input1(logic::in::masked), + input2(logic::in::masked), + output(logic::out::disable), + output_swap(logic::out::no_swap), + filter(logic::filter::disable), + edgedetect(logic::edgedetect::disable), + truth(0x00), + sequencer(logic::sequencer::disable), + clocksource(logic::clocksource::clk_per), + block(blocks[block_number]) { +} + +// static +void Logic::start(bool state) { + CCL.CTRLA = (state ? CCL_ENABLE_bm : 0); +} + + +// static +void Logic::stop() { + start(false); +} + +static volatile register8_t &PINCTRL(PORT_t &port, const uint8_t pin_bm) { + if (pin_bm == PIN0_bm) { + return port.PIN0CTRL; + } + if (pin_bm == PIN1_bm) { + return port.PIN1CTRL; + } + if (pin_bm == PIN2_bm) { + return port.PIN2CTRL; + } + if (pin_bm == PIN3_bm) { + return port.PIN3CTRL; + } + if (pin_bm == PIN4_bm) { + return port.PIN4CTRL; + } + if (pin_bm == PIN5_bm) { + return port.PIN5CTRL; + } + if (pin_bm == PIN6_bm) { + return port.PIN6CTRL; + } + return port.PIN7CTRL; +} + +void Logic::initInput(logic::in::input_t &input, PORT_t &port, const uint8_t pin_bm) { + if ((input & 0x30) && pin_bm) { // Input pin is either set to input or input with pullup + port.DIRCLR = pin_bm; + + if (input == logic::in::input) { + PINCTRL(port, pin_bm) &= ~PORT_PULLUPEN_bm; + } else { + PINCTRL(port, pin_bm) |= PORT_PULLUPEN_bm; + } + } +} + +void Logic::init() +{ + // Clear LUTCTRLA in case the CCL block gets reinitialized + block.LUTCTRLA = 0x00; + + // Configure input pins + initInput(input0, block.PORT_IN, block.input0_bm); + initInput(input1, block.PORT_IN, block.input1_bm); + initInput(input2, block.PORT_IN, block.input2_bm); + + // Set output pin state and output pin swap + if (output == logic::out::enable) { + if (output_swap == logic::out::pin_swap && block.output_alt_bm) { + #if defined(PORTMUX_CCL) + PORTMUX_CCL |= PORTMUX_ALTOUT_bm; + #endif + block.PORT_OUT.DIRSET = block.output_alt_bm; + } else if (output_swap == logic::out::no_swap && block.output_bm) { + #if defined(PORTMUX_CCL) + PORTMUX_CCL &= ~PORTMUX_ALTOUT_bm; + #endif + block.PORT_ALT_OUT.DIRSET = block.output_bm; + } + } + + // Set inputs modes + block.LUTCTRLB = ((input1 & 0x0f) << CCL_INSEL1_gp) | ((input0 & 0x0f) << CCL_INSEL0_gp); + block.LUTCTRLC = ((input2 & 0x0f) << CCL_INSEL2_gp); + + // Set truth table + block.TRUTH = truth; + + // Set sequencer + if (!(block.number & 0x01)) { + block.SEQCTRL = sequencer; + } + + // Set logic output state and output filter + block.LUTCTRLA = (output ? CCL_OUTEN_bm : 0) + | (edgedetect ? CCL_EDGEDET_EN_gc : 0) + | (filter << CCL_FILTSEL_gp) + #ifdef CCL_CLKSRC_gp + | (clocksource << CCL_CLKSRC_gp) + #else + | (clocksource << CCL_CLKSRC_bm) + #endif + | (enable ? CCL_ENABLE_bm : 0); +} diff --git a/megaavr/libraries/Logic/src/Logic.h b/megaavr/libraries/Logic/src/Logic.h new file mode 100644 index 0000000..958c83c --- /dev/null +++ b/megaavr/libraries/Logic/src/Logic.h @@ -0,0 +1,629 @@ +#ifndef LOGIC_h +#define LOGIC_h + +#include + +namespace logic { + namespace in { + enum input_t : uint8_t { + #if defined(__AVR_ATmega808__) || defined(__AVR_ATmega1608__) || \ + defined(__AVR_ATmega3208__) || defined(__AVR_ATmega4808__) || \ + defined(__AVR_ATmega809__) || defined(__AVR_ATmega1609__) || \ + defined(__AVR_ATmega3209__) || defined(__AVR_ATmega4809__) || \ + defined(__AVR_ATtiny3227__) || defined(__AVR_ATtiny3226__) || \ + defined(__AVR_ATtiny3224__) || defined(__AVR_ATtiny1627__) || \ + defined(__AVR_ATtiny1626__) || defined(__AVR_ATtiny1624__) || \ + defined(__AVR_ATtiny827__) || defined(__AVR_ATtiny826__) || \ + defined(__AVR_ATtiny824__) || defined(__AVR_ATtiny427__) || \ + defined(__AVR_ATtiny426__) || defined(__AVR_ATtiny424__) + masked = 0x00, + unused = 0x00, + disable = 0x00, + feedback = 0x01, + link = 0x02, + event_0 = 0x03, + event_a = 0x03, + event_1 = 0x04, + event_b = 0x04, + pin = 0x05, + ac = 0x06, + uart = 0x08, + usart = 0x08, + spi = 0x09, + tca0 = 0x0A, + tca = 0x0A, + tcb = 0x0C, + input_pullup = 0x15, + input = 0x25, + input_no_pullup = 0x25, + #elif defined(__AVR_AVR128DA64__) || defined(__AVR_AVR128DA48__) || \ + defined(__AVR_AVR128DA32__) || defined(__AVR_AVR128DA32__) || \ + defined(__AVR_AVR64DA64__) || defined(__AVR_AVR64DA48__) || \ + defined(__AVR_AVR64DA32__) || defined(__AVR_AVR64DA28__) || \ + defined(__AVR_AVR32DA64__) || defined(__AVR_AVR32DA48__) || \ + defined(__AVR_AVR32DA32__) || defined(__AVR_AVR32DA28__) || \ + defined(__AVR_AVR128DB64__) || defined(__AVR_AVR128DB48__) || \ + defined(__AVR_AVR128DB32__) || defined(__AVR_AVR128DB32__) || \ + defined(__AVR_AVR64DB64__) || defined(__AVR_AVR64DB48__) || \ + defined(__AVR_AVR64DB32__) || defined(__AVR_AVR64DB28__) || \ + defined(__AVR_AVR32DB64__) || defined(__AVR_AVR32DB48__) || \ + defined(__AVR_AVR32DB32__) || defined(__AVR_AVR32DB28__) + masked = 0x00, + unused = 0x00, + disable = 0x00, + feedback = 0x01, + link = 0x02, + event_0 = 0x03, + event_a = 0x03, + event_1 = 0x04, + event_b = 0x04, + pin = 0x05, + ac = 0x06, + zcd = 0x07, + usart = 0x08, + spi = 0x09, + tca0 = 0x0A, + tca = 0x0A, + tca1 = 0x0B, + tcb = 0x0C, + tcd = 0x0D, + input_pullup = 0x15, + input = 0x25, + input_no_pullup = 0x25, + #elif defined(__AVR_AVR64DD20__) || defined(__AVR_AVR64DD14__) || \ + defined(__AVR_AVR32DD20__) || defined(__AVR_AVR32DD14__) || \ + defined(__AVR_AVR16DD20__) || defined(__AVR_AVR16DD14__) || \ + defined(__AVR_AVR64DD32__) || defined(__AVR_AVR64DD28__) || \ + defined(__AVR_AVR32DD32__) || defined(__AVR_AVR32DD28__) || \ + defined(__AVR_AVR16DD32__) || defined(__AVR_AVR16DD28__) + // educated guess - these have at least one of everything the rest of DA-series has, + // and these lists have been super consistent since v1.0 (tinyAVR 0/1-series) + masked = 0x00, + unused = 0x00, + disable = 0x00, + feedback = 0x01, + link = 0x02, + event_0 = 0x03, + event_a = 0x03, + event_1 = 0x04, + event_b = 0x04, + pin = 0x05, + ac = 0x06, + zcd = 0x07, + usart = 0x08, + spi = 0x09, + tca0 = 0x0A, + tca = 0x0A, + tcb = 0x0C, + tcd = 0x0D, + input_pullup = 0x15, + input = 0x25, + input_no_pullup = 0x25, + #elif defined(__AVR_AVR64EA28__) || defined(__AVR_AVR32EA28__) || \ + defined(__AVR_AVR16EA28__) || defined(__AVR_AVR8EA28__) || \ + defined(__AVR_AVR64EA32__) || defined(__AVR_AVR32EA32__) || \ + defined(__AVR_AVR16EA32__) || defined(__AVR_AVR8EA32__) || \ + defined(__AVR_AVR64EA48__) || defined(__AVR_AVR32EA48__) || \ + defined(__AVR_AVR16EA48__) + // educated guess based on recent consistency and which peripherals they have + masked = 0x00, + unused = 0x00, + disable = 0x00, + feedback = 0x01, + link = 0x02, + event_0 = 0x03, + event_a = 0x03, + event_1 = 0x04, + event_b = 0x04, + pin = 0x05, + ac = 0x06, + usart = 0x08, + spi = 0x09, + tca0 = 0x0A, + tca = 0x0A, + tca1 = 0x0B, + tcb = 0x0C, + input_pullup = 0x15, + input = 0x25, + input_no_pullup = 0x25, + + #else //tinyAVR 0/1-series + masked = 0x00, + unused = 0x00, + disable = 0x00, + feedback = 0x01, + link = 0x02, + event_0 = 0x03, + event_a = 0x03, + event_1 = 0x04, + event_b = 0x04, + pin = 0x05, + ac = 0x06, + ac0 = 0x06, + tcb0 = 0x07, + tcb = 0x07, + tca = 0x08, + tca0 = 0x08, + tcd0 = 0x09, + usart = 0x0A, + usart0 = 0x0A, + spi = 0x0B, + spi0 = 0x0B, + ac1 = 0x0C, + tcb1 = 0x0D, + ac2 = 0x0E, + input_pullup = 0x15, + input = 0x25, + input_no_pullup = 0x25, + #endif + }; + }; + + // Use out:: when working with logic outputs + namespace out { + enum output_t : uint8_t { + disable = 0x00, + enable = 0x01, + }; + enum pinswap_t : uint8_t { + no_swap = 0x00, + pin_swap = 0x01, + }; + }; + + // Use filter:: when working with logic output filter + namespace filter { + enum filter_t : uint8_t { + disable = 0x00, + synchronizer = 0x01, + synch = 0x01, + sync = 0x01, + filter = 0x02, + }; + }; + + // Use clocksource:: when working with logic clock source + namespace clocksource { + enum clocksource_t : uint8_t { + clk_per = 0x00, + in2 = 0x01, + #ifdef CCL_CLKSEL_gm + oschf = 0x04, + osc32k = 0x05, + osc1k = 0x06, + #endif + }; + }; + + // Use edgedetect:: when using edge detection with filter + namespace edgedetect { + enum edgedet_t : uint8_t { + disable = 0x00, + enable = 0x01 + }; + }; + + // Use sequencer:: when working with LUT sequencer + namespace sequencer { + enum sequencer_t : uint8_t { + disable = 0x00, + d_flip_flop = 0x01, + jk_flip_flop = 0x02, + d_latch = 0x03, + sr_latch = 0x04, + rs_latch = 0x04, + }; + }; +}; + +// Legacy definitions +namespace in { using namespace logic::in; }; +namespace out { using namespace logic::out; }; +namespace filter { using namespace logic::filter; }; +namespace clocksource { using namespace logic::clocksource; }; +namespace edgedetect { using namespace logic::edgedetect; }; +namespace sequencer { using namespace logic::sequencer; }; + +class Logic { + public: + static void start(bool state = true); + static void stop(); + + Logic(const uint8_t block_number); + void init(); + #if defined(CCL_CCL_vect) + void attachInterrupt(voidFuncPtr callback, uint8_t mode); + void detachInterrupt(); + #endif + + bool enable; + logic::in::input_t input0; + logic::in::input_t input1; + logic::in::input_t input2; + logic::out::output_t output; + logic::out::pinswap_t output_swap; + logic::filter::filter_t filter; + logic::edgedetect::edgedet_t edgedetect; + uint8_t truth; + logic::sequencer::sequencer_t sequencer; + logic::clocksource::clocksource_t clocksource; + + struct CCLBlock; + + private: + const struct CCLBlock █ + + void initInput(logic::in::input_t &input, PORT_t &port, const uint8_t pin_bm); +}; + +// Array for storing ISR function pointers +#if defined(CCL_CCL_vect) + #if defined(TRUTH5) + static volatile voidFuncPtr intFuncCCL[6]; + #else + static volatile voidFuncPtr intFuncCCL[4]; + #endif +#endif + +struct Logic::CCLBlock { + const uint8_t number; + const uint8_t input0_bm; + const uint8_t input1_bm; + const uint8_t input2_bm; + const uint8_t output_bm; + const uint8_t output_alt_bm; + PORT_t &PORT_IN; + PORT_t &PORT_OUT; + PORT_t &PORT_ALT_OUT; + volatile register8_t &SEQCTRL; + volatile register8_t &LUTCTRLA; + volatile register8_t &LUTCTRLB; + volatile register8_t &LUTCTRLC; + volatile register8_t &TRUTH; +}; + +static const struct Logic::CCLBlock blocks[] = { + #if defined(__AVR_ATtiny202__) || defined(__AVR_ATtiny402__) || \ + defined(__AVR_ATtiny204__) || defined(__AVR_ATtiny404__) || \ + defined(__AVR_ATtiny804__) || defined(__AVR_ATtiny1604__) || \ + defined(__AVR_ATtiny212__) || defined(__AVR_ATtiny412__) || \ + defined(__AVR_ATtiny214__) || defined(__AVR_ATtiny414__) || \ + defined(__AVR_ATtiny814__) || defined(__AVR_ATtiny1614__) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, 0, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + 0, 0, 0, PIN7_bm, 0, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + #endif + #if defined(__AVR_ATtiny406__) || defined(__AVR_ATtiny806__) || \ + defined(__AVR_ATtiny1606__) || \ + defined(__AVR_ATtiny416__) || defined(__AVR_ATtiny816__) || \ + defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) + #define PORTMUX_CCL PORTMUX.CTRLA + #define PORTMUX_ALTOUT_bm (1 << (block.number + 4)) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, PIN4_bm, + PORTA, PORTA, PORTB, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + PIN3_bm, 0, 0, PIN7_bm, PIN1_bm, + PORTC, PORTA, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + #endif + #if defined(__AVR_ATtiny807__) || defined(__AVR_ATtiny1607__) || \ + defined(__AVR_ATtiny417__) || defined(__AVR_ATtiny817__) || \ + defined(__AVR_ATtiny1617__) || defined(__AVR_ATtiny3217__) + #define PORTMUX_CCL PORTMUX.CTRLA + #define PORTMUX_ALTOUT_bm (1 << (block.number + 4)) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, PIN4_bm, + PORTA, PORTA, PORTB, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + PIN3_bm, PIN4_bm, PIN5_bm, PIN7_bm, PIN1_bm, + PORTC, PORTA, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + #endif + #if defined(__AVR_ATtiny424__) || defined(__AVR_ATtiny824__) || \ + defined(__AVR_ATtiny1624__) || defined(__AVR_ATtiny3224__) + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, 0, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + 0, 0, 0, PIN7_bm, 0, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + { + 2, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, 0, + PORTB, PORTB, PORTA, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + { + 3, + 0, 0, 0, 0, PIN5_bm, + PORTC, PORTA, PORTA, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #if defined(__AVR_ATtiny426__) || defined(__AVR_ATtiny826__) || \ + defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, PIN4_bm, + PORTA, PORTA, PORTB, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + PIN3_bm, 0, 0, PIN7_bm, PIN1_bm, + PORTC, PORTA, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + { + 2, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, 0, + PORTB, PORTB, PORTA, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + { + 3, + PIN0_bm, PIN1_bm, PIN2_bm, 0, PIN5_bm, + PORTC, PORTA, PORTA, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #if defined(__AVR_ATtiny427__) || defined(__AVR_ATtiny827__) || \ + defined(__AVR_ATtiny1617__) || defined(__AVR_ATtiny3217__) + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN6_bm, PIN4_bm, + PORTA, PORTA, PORTB, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + PIN3_bm, PIN4_bm, PIN5_bm, PIN7_bm, PIN1_bm, + PORTC, PORTA, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + { + 2, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTB, PORTB, PORTB, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + { + 3, + PIN0_bm, PIN1_bm, PIN2_bm, PIN4_bm, PIN5_bm, + PORTC, PORTC, PORTA, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #if defined(__AVR_AVR64DD20__) || defined(__AVR_AVR64DD14__) || \ + defined(__AVR_AVR32DD20__) || defined(__AVR_AVR32DD14__) || \ + defined(__AVR_AVR16DD20__) || defined(__AVR_AVR16DD14__) + + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + 0, PIN1_bm, PIN2_bm, PIN3_bm, 0, + PORTC, PORTC, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + { + 2, + 0, 0, 0, 0, PIN6_bm, + PORTD, PORTD, PORTD, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + { + 3, + 0, 0, 0, 0, 0, + PORTA, PORTA, PORTA, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #if defined(__AVR_ATmega808__) || defined(__AVR_ATmega1608__) || \ + defined(__AVR_ATmega3208__) || defined(__AVR_ATmega4808__) || \ + defined(__AVR_AVR128DA32__) || defined(__AVR_AVR128DA28__) || \ + defined(__AVR_AVR64DA32__) || defined(__AVR_AVR64DA28__) || \ + defined(__AVR_AVR32DA32__) || defined(__AVR_AVR32DA28__) || \ + defined(__AVR_AVR128DB32__) || defined(__AVR_AVR128DB28__) || \ + defined(__AVR_AVR64DB32__) || defined(__AVR_AVR64DB28__) || \ + defined(__AVR_AVR32DB32__) || defined(__AVR_AVR32DB28__) || \ + defined(__AVR_AVR64DD32__) || defined(__AVR_AVR64DD28__) || \ + defined(__AVR_AVR32DD32__) || defined(__AVR_AVR32DD28__) || \ + defined(__AVR_AVR16DD32__) || defined(__AVR_AVR16DD28__) || \ + defined(__AVR_AVR64EA32__) || defined(__AVR_AVR64EA28__) || \ + defined(__AVR_AVR32EA32__) || defined(__AVR_AVR32EA28__) || \ + defined(__AVR_AVR16EA32__) || defined(__AVR_AVR16EA28__) || \ + defined(__AVR_AVR8EA32__) || defined(__AVR_AVR8EA28__) + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + 1, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, 0, + PORTC, PORTC, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + #if defined(__AVR_AVR128DB32__) || defined(__AVR_AVR128DB28__) || \ + defined(__AVR_AVR64DB32__) || defined(__AVR_AVR64DB28__) || \ + defined(__AVR_AVR32DB32__) || defined(__AVR_AVR32DB28__) || \ + defined(__AVR_AVR64DD32__) || defined(__AVR_AVR64DD28__) || \ + defined(__AVR_AVR32DD32__) || defined(__AVR_AVR32DD28__) || \ + defined(__AVR_AVR16DD32__) || defined(__AVR_AVR16DD28__) + // These have no PD0, because it was sacrificed for VDDIO2 + { + 2, + 0, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTD, PORTD, PORTD, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + #else + { + 2, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTD, PORTD, PORTD, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + #endif + #if defined(__AVR_AVR128DA28__)|| defined(__AVR_AVR64DA28__) || \ + defined(__AVR_AVR32DA28__) || defined(__AVR_AVR64EA28__) || \ + defined(__AVR_AVR32EA28__) || defined(__AVR_AVR16EA28__) || \ + defined(__AVR_AVR8EA28__) || defined(__AVR_AVR64DD28__) || \ + defined(__AVR_AVR32DD28__) || defined(__AVR_AVR16DD28__) + // only has PF0, PF1, and even if RESET set GPIO, is input only + { + 3, + PIN0_bm, PIN1_bm, 0, 0, 0, + PORTF, PORTF, PORTF, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #elif defined(__AVR_AVR128DA32__)|| defined(__AVR_AVR64DA32__) || \ + defined(__AVR_AVR32DA32__) || defined(__AVR_AVR64EA32__) || \ + defined(__AVR_AVR32EA32__) || defined(__AVR_AVR16EA32__) || \ + defined(__AVR_AVR8EA32__) || defined(__AVR_AVR64DD32__) || \ + defined(__AVR_AVR32DD32__) || defined(__AVR_AVR16DD32__) + // even if RESET set GPIO, is input only + { + 3, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, 0, + PORTF, PORTF, PORTF, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #else + // megaAVR 0-series with 32-pins + // Note that PF6 is Reset, which must be set as GPIO to use as alt output. + { + 3, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTF, PORTF, PORTF, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #endif + #if defined(__AVR_ATmega809__) || defined(__AVR_ATmega1609__) || \ + defined(__AVR_ATmega3209__) || defined(__AVR_ATmega4809__) || \ + defined(__AVR_AVR128DA64__) || defined(__AVR_AVR128DA48__) || \ + defined(__AVR_AVR64DA64__) || defined(__AVR_AVR64DA48__) || \ + defined(__AVR_AVR32DA64__) || defined(__AVR_AVR32DA48__) || \ + defined(__AVR_AVR128DB64__) || defined(__AVR_AVR128DB48__) || \ + defined(__AVR_AVR64DB64__) || defined(__AVR_AVR64DB48__) || \ + defined(__AVR_AVR32DB64__) || defined(__AVR_AVR32DB48__) || \ + defined(__AVR_AVR64EA48__) || defined(__AVR_AVR32EA48__) || \ + defined(__AVR_AVR16EA48__) + #define PORTMUX_CCL PORTMUX.CCLROUTEA + #define PORTMUX_ALTOUT_bm (1 << block.number) + { + 0, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTA, PORTA, PORTA, + CCL.SEQCTRL0, CCL.LUT0CTRLA, CCL.LUT0CTRLB, CCL.LUT0CTRLC, CCL.TRUTH0, + }, + { + // Note: 40-Pin version doesn't have output_alt, but the parts cannot + // be programmatically distinguished - it's a 48-pin die in 40-pin package + 1, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTC, PORTC, PORTC, + CCL.SEQCTRL0, CCL.LUT1CTRLA, CCL.LUT1CTRLB, CCL.LUT1CTRLC, CCL.TRUTH1, + }, + { + 2, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTD, PORTD, PORTD, + CCL.SEQCTRL1, CCL.LUT2CTRLA, CCL.LUT2CTRLB, CCL.LUT2CTRLC, CCL.TRUTH2, + }, + { + 3, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTF, PORTF, PORTF, + CCL.SEQCTRL1, CCL.LUT3CTRLA, CCL.LUT3CTRLB, CCL.LUT3CTRLC, CCL.TRUTH3, + }, + #endif + #if defined(__AVR_AVR128DA64__) || defined(__AVR_AVR128DA48__) || \ + defined(__AVR_AVR64DA64__) || defined(__AVR_AVR64DA48__) || \ + defined(__AVR_AVR32DA64__) || defined(__AVR_AVR32DA48__) || \ + defined(__AVR_AVR128DB64__) || defined(__AVR_AVR128DB48__) || \ + defined(__AVR_AVR64DB64__) || defined(__AVR_AVR64DB48__) || \ + defined(__AVR_AVR32DB64__) || defined(__AVR_AVR32DB48__) + { + 4, + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTB, PORTB, PORTB, + CCL.SEQCTRL2, CCL.LUT4CTRLA, CCL.LUT4CTRLB, CCL.LUT4CTRLC, CCL.TRUTH4, + }, + { + 5, + #ifdef PORTG + PIN0_bm, PIN1_bm, PIN2_bm, PIN3_bm, PIN6_bm, + PORTG, PORTG, PORTG, + #else + 0,0,0,0,0, + PORTA,PORTA,PORTA, + #endif + CCL.SEQCTRL2, CCL.LUT5CTRLA, CCL.LUT5CTRLB, CCL.LUT5CTRLC, CCL.TRUTH5, + }, + #endif +}; + +#if defined(CCL_TRUTH0) + extern Logic Logic0; +#endif +#if defined(CCL_TRUTH1) + extern Logic Logic1; +#endif +#if defined(CCL_TRUTH2) + extern Logic Logic2; +#endif +#if defined(CCL_TRUTH3) + extern Logic Logic3; +#endif +#if defined(CCL_TRUTH4) + extern Logic Logic4; +#endif +#if defined(CCL_TRUTH5) + extern Logic Logic5; +#endif + +#endif diff --git a/megaavr/libraries/Logic/src/Logic_ISR.cpp b/megaavr/libraries/Logic/src/Logic_ISR.cpp new file mode 100644 index 0000000..5fe697b --- /dev/null +++ b/megaavr/libraries/Logic/src/Logic_ISR.cpp @@ -0,0 +1,104 @@ +// This file will be optimized away if attachInterrupt or detachInterrupt isn't used in +// user program, thanks to dot_a_linkage set in library.properties + +#include "Logic.h" + +#if defined(CCL_CCL_vect) +void Logic::attachInterrupt(void (*userFunc)(void), uint8_t mode) { + CCL_INTMODE0_t intmode; + switch (mode) { + // Set RISING, FALLING or CHANGE interrupt trigger for a block output + case RISING: + intmode = CCL_INTMODE0_RISING_gc; + break; + case FALLING: + intmode = CCL_INTMODE0_FALLING_gc; + break; + case CHANGE: + intmode = CCL_INTMODE0_BOTH_gc; + break; + default: + // Only RISING, FALLING and CHANGE is supported + return; + } + #if defined(CCL_TRUTH4) + if (block.number > 3) { + const int16_t intmode_bp = (block.number & 0x03) * 2; + CCL.INTCTRL1 = (CCL.INTCTRL1 & ~(CCL_INTMODE0_gm << intmode_bp)) | (intmode << intmode_bp); + } else { + const int16_t intmode_bp = (block.number & 0x03) * 2; + CCL.INTCTRL0 = (CCL.INTCTRL0 & ~(CCL_INTMODE0_gm << intmode_bp)) | (intmode << intmode_bp); + } + #else + const int16_t intmode_bp = block.number * 2; + CCL.INTCTRL0 = (CCL.INTCTRL0 & ~(CCL_INTMODE0_gm << intmode_bp)) | (intmode << intmode_bp); + #endif + // Store function pointer + intFuncCCL[block.number] = userFunc; +} + +void Logic::detachInterrupt() { + // Disable interrupt for a given block output + #if defined(CCL_TRUTH4) + if (block.number > 4) { + CCL.INTCTRL1 &= ~(CCL_INTMODE1_gm << ((block.number & 3) * 2)); + } else { + CCL.INTCTRL0 &= ~(CCL_INTMODE0_gm << (block.number * 2)); + } + #else + CCL.INTCTRL0 &= ~(CCL_INTMODE0_gm << (block.number * 2)); + #endif +} + +// CCL interrupt service routine +// Use attachIntterupt to activate this. +ISR(CCL_CCL_vect) { + // Check for block 0 interrupt + if (CCL.INTFLAGS & CCL_INT0_bm) { + // Run user function + intFuncCCL[CCL_INT0_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT0_bm; + } + // Check for block 1 interrupt + if (CCL.INTFLAGS & CCL_INT1_bm) { + // Run user function + intFuncCCL[CCL_INT1_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT1_bm; + } + // Check for block 2 interrupt + if (CCL.INTFLAGS & CCL_INT2_bm) { + // Run user function + intFuncCCL[CCL_INT2_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT2_bm; + } + // Check for block 3 interrupt + if (CCL.INTFLAGS & CCL_INT3_bm) { + // Run user function + intFuncCCL[CCL_INT3_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT3_bm; + } + #if defined(TRUTH4) + // Check for block 4 interrupt + if (CCL.INTFLAGS & CCL_INT4_bm) { + // Run user function + intFuncCCL[CCL_INT4_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT4_bm; + } + #endif + #if defined(TRUTH5) + // Check for block 5 interrupt + if (CCL.INTFLAGS & CCL_INT5_bm) { + // Run user function + intFuncCCL[CCL_INT5_bp](); + // Clear flag + CCL.INTFLAGS |= CCL_INT5_bm; + } +#endif // CCL_CCL_vect +} + +#endif \ No newline at end of file diff --git a/megaavr/libraries/MegaCoreX/keywords.txt b/megaavr/libraries/MegaCoreX/keywords.txt new file mode 100644 index 0000000..b746e2b --- /dev/null +++ b/megaavr/libraries/MegaCoreX/keywords.txt @@ -0,0 +1,4319 @@ +# This file is a work in progress. The plan is to add (all/most) AVR specific words, so +# they get highlighted in the Arduino IDE when used +# More libraries will be added later + +# FUNCTIONS are color coded with KEYWORD2 +# MACROS WITH PARAMETERS are are color coded with KEYWORD3 RESERVED_WORD +# MACROS WITHOUT PARAMETERS are color coded with LITERAL2 RESERVED_WORD_2 + + + +#OTHER +megacorex LITERAL2 RESERVED_WORD_2 +MegaCoreX LITERAL2 RESERVED_WORD_2 +MEGACOREX LITERAL2 RESERVED_WORD_2 +__AVR_ATmega808__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega809__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega1608__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega1609__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega3208__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega3209__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega4808__ LITERAL2 RESERVED_WORD_2 +__AVR_ATmega4809__ LITERAL2 RESERVED_WORD_2 + +__ASM__ KEYWORD3 RESERVED_WORD +F_CPU LITERAL2 RESERVED_WORD_2 +main KEYWORD3 RESERVED_WORD +size_t LITERAL2 RESERVED_WORD_2 +_SFR_IO8 KEYWORD3 RESERVED_WORD +_SFR_IO16 KEYWORD3 RESERVED_WORD +_SFR_MEM8 KEYWORD3 RESERVED_WORD +_SFR_MEM16 KEYWORD3 RESERVED_WORD + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html +ATOMIC_BLOCK KEYWORD3 RESERVED_WORD +NONATOMIC_BLOCK KEYWORD3 RESERVED_WORD +ATOMIC_RESTORESTATE LITERAL2 RESERVED_WORD_2 +ATOMIC_FORCEON LITERAL2 RESERVED_WORD_2 +NONATOMIC_RESTORESTATE LITERAL2 RESERVED_WORD_2 +NONATOMIC_FORCEOFF LITERAL2 RESERVED_WORD_2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__sfr.html +bit_is_set KEYWORD3 RESERVED_WORD +bit_is_clear KEYWORD3 RESERVED_WORD +_BV KEYWORD3 RESERVED_WORD +loop_until_bit_is_set KEYWORD3 RESERVED_WORD +loop_until_bit_is_clear KEYWORD3 RESERVED_WORD + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html +_delay_ms KEYWORD2 +_delay_us KEYWORD2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html +ISR KEYWORD3 RESERVED_WORD +SIGNAL KEYWORD3 RESERVED_WORD +EMPTY_INTERRUPT KEYWORD3 RESERVED_WORD +ISR_ALIAS KEYWORD3 RESERVED_WORD +reti KEYWORD3 RESERVED_WORD +cli KEYWORD3 RESERVED_WORD +sei KEYWORD3 RESERVED_WORD +BADISR_vect LITERAL2 RESERVED_WORD_2 +ISR_BLOCK LITERAL2 RESERVED_WORD_2 +ISR_NOBLOCK LITERAL2 RESERVED_WORD_2 +ISR_NAKED LITERAL2 RESERVED_WORD_2 +ISR_ALIASOF KEYWORD3 RESERVED_WORD + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__math.html +M_E LITERAL2 RESERVED_WORD_2 +M_LOG2E LITERAL2 RESERVED_WORD_2 +M_LOG10E LITERAL2 RESERVED_WORD_2 +M_LN2 LITERAL2 RESERVED_WORD_2 +M_LN10 LITERAL2 RESERVED_WORD_2 +M_PI LITERAL2 RESERVED_WORD_2 +M_PI_2 LITERAL2 RESERVED_WORD_2 +M_PI_4 LITERAL2 RESERVED_WORD_2 +M_1_PI LITERAL2 RESERVED_WORD_2 +M_2_PI LITERAL2 RESERVED_WORD_2 +M_2_SQRTPI LITERAL2 RESERVED_WORD_2 +M_SQRT2 LITERAL2 RESERVED_WORD_2 +M_SQRT1_2 LITERAL2 RESERVED_WORD_2 +NAN LITERAL2 RESERVED_WORD_2 +INFINITY LITERAL2 RESERVED_WORD_2 +cosf KEYWORD3 RESERVED_WORD +sinf KEYWORD3 RESERVED_WORD +tanf KEYWORD3 RESERVED_WORD +fabsf KEYWORD3 RESERVED_WORD +fmodf KEYWORD3 RESERVED_WORD +cbrtf KEYWORD3 RESERVED_WORD +cbrt KEYWORD2 +hypotf KEYWORD3 RESERVED_WORD +hypot KEYWORD2 +squaref KEYWORD3 RESERVED_WORD +square KEYWORD2 +floorf KEYWORD3 RESERVED_WORD +ceilf KEYWORD3 RESERVED_WORD +frexpf KEYWORD3 RESERVED_WORD +ldexpf KEYWORD3 RESERVED_WORD +expf KEYWORD3 RESERVED_WORD +coshf KEYWORD3 RESERVED_WORD +sinhf KEYWORD3 RESERVED_WORD +tanhf KEYWORD3 RESERVED_WORD +acosf KEYWORD3 RESERVED_WORD +asinf KEYWORD3 RESERVED_WORD +atanf KEYWORD3 RESERVED_WORD +atan2f KEYWORD3 RESERVED_WORD +logf KEYWORD3 RESERVED_WORD +log10f KEYWORD3 RESERVED_WORD +powf KEYWORD3 RESERVED_WORD +isnanf KEYWORD3 RESERVED_WORD +isnan KEYWORD2 +isinff KEYWORD3 RESERVED_WORD +isinf KEYWORD2 +isfinitef KEYWORD3 RESERVED_WORD +isfinite KEYWORD2 +copysign KEYWORD2 +copysignf KEYWORD3 RESERVED_WORD +signbitf KEYWORD3 RESERVED_WORD +signbit KEYWORD2 +fdimf KEYWORD3 RESERVED_WORD +fdim KEYWORD2 +fmaf KEYWORD3 RESERVED_WORD +fma KEYWORD2 +fmaxf KEYWORD3 RESERVED_WORD +fmax KEYWORD2 +fminf KEYWORD3 RESERVED_WORD +fmin KEYWORD2 +truncf KEYWORD3 RESERVED_WORD +trunc KEYWORD2 +roundf KEYWORD3 RESERVED_WORD +lroundf KEYWORD3 RESERVED_WORD +lround KEYWORD2 +lrintf KEYWORD3 RESERVED_WORD +lrint KEYWORD2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/power_8h.html +power_adc_disable KEYWORD2 +power_spi_disable KEYWORD2 +power_timer0_disable KEYWORD2 +power_timer1_disable KEYWORD2 +power_timer2_disable KEYWORD2 +power_timer3_disable KEYWORD2 +power_usart0_disable KEYWORD2 +power_usart1_disable KEYWORD2 +power_all_disable KEYWORD2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/sleep_8h.html +sleep_enable KEYWORD2 +sleep_disable KEYWORD2 +sleep_cpu KEYWORD2 +sleep_mode KEYWORD2 +sleep_bod_disable KEYWORD2 +_SLEEP_CONTROL_REG LITERAL2 RESERVED_WORD_2 +_SLEEP_ENABLE_MASK LITERAL2 RESERVED_WORD_2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html +_FFS KEYWORD3 RESERVED_WORD +ffs KEYWORD2 +ffsl KEYWORD2 +ffsll KEYWORD2 +memccpy KEYWORD2 +memmem KEYWORD2 +memrchr KEYWORD2 +strcasecmp KEYWORD2 +strcasestr KEYWORD2 +strchrnul KEYWORD2 +strdup KEYWORD2 +strlcat KEYWORD2 +strlcpy KEYWORD2 +strnlen KEYWORD2 +strlwr KEYWORD2 +strncasecmp KEYWORD2 +strrev KEYWORD2 +strsep KEYWORD2 +strtok_r KEYWORD2 +strupr KEYWORD2 + + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html +__USING_MINT8 LITERAL2 RESERVED_WORD_2 +__CONCATenate KEYWORD3 RESERVED_WORD +__CONCAT KEYWORD3 RESERVED_WORD +intptr_t LITERAL2 RESERVED_WORD_2 +uintptr_t LITERAL2 RESERVED_WORD_2 +int_least8_t LITERAL2 RESERVED_WORD_2 +uint_least8_t LITERAL2 RESERVED_WORD_2 +int_least16_t LITERAL2 RESERVED_WORD_2 +uint_least16_t LITERAL2 RESERVED_WORD_2 +int_least32_t LITERAL2 RESERVED_WORD_2 +uint_least32_t LITERAL2 RESERVED_WORD_2 +int_least64_t LITERAL2 RESERVED_WORD_2 +uint_least64_t LITERAL2 RESERVED_WORD_2 +int_fast8_t LITERAL2 RESERVED_WORD_2 +uint_fast8_t LITERAL2 RESERVED_WORD_2 +int_fast16_t LITERAL2 RESERVED_WORD_2 +uint_fast16_t LITERAL2 RESERVED_WORD_2 +int_fast32_t LITERAL2 RESERVED_WORD_2 +uint_fast32_t LITERAL2 RESERVED_WORD_2 +int_fast64_t LITERAL2 RESERVED_WORD_2 +uint_fast64_t LITERAL2 RESERVED_WORD_2 +intmax_t LITERAL2 RESERVED_WORD_2 +uintmax_t LITERAL2 RESERVED_WORD_2 +INT8_MAX LITERAL2 RESERVED_WORD_2 +INT8_MIN LITERAL2 RESERVED_WORD_2 +UINT8_MAX LITERAL2 RESERVED_WORD_2 +INT16_MAX LITERAL2 RESERVED_WORD_2 +INT16_MIN LITERAL2 RESERVED_WORD_2 +UINT16_MAX LITERAL2 RESERVED_WORD_2 +INT32_MAX LITERAL2 RESERVED_WORD_2 +INT32_MIN LITERAL2 RESERVED_WORD_2 +UINT32_MAX LITERAL2 RESERVED_WORD_2 +INT64_MAX LITERAL2 RESERVED_WORD_2 +INT64_MIN LITERAL2 RESERVED_WORD_2 +UINT64_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST8_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST8_MIN LITERAL2 RESERVED_WORD_2 +UINT_LEAST8_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST16_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST16_MIN LITERAL2 RESERVED_WORD_2 +UINT_LEAST16_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST32_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST32_MIN LITERAL2 RESERVED_WORD_2 +UINT_LEAST32_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST64_MAX LITERAL2 RESERVED_WORD_2 +INT_LEAST64_MIN LITERAL2 RESERVED_WORD_2 +UINT_LEAST64_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST8_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST8_MIN LITERAL2 RESERVED_WORD_2 +UINT_FAST8_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST16_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST16_MIN LITERAL2 RESERVED_WORD_2 +UINT_FAST16_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST32_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST32_MIN LITERAL2 RESERVED_WORD_2 +UINT_FAST32_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST64_MAX LITERAL2 RESERVED_WORD_2 +INT_FAST64_MIN LITERAL2 RESERVED_WORD_2 +UINT_FAST64_MAX LITERAL2 RESERVED_WORD_2 +INTPTR_MAX LITERAL2 RESERVED_WORD_2 +INTPTR_MIN LITERAL2 RESERVED_WORD_2 +UINTPTR_MAX LITERAL2 RESERVED_WORD_2 +INTMAX_MAX LITERAL2 RESERVED_WORD_2 +INTMAX_MIN LITERAL2 RESERVED_WORD_2 +UINTMAX_MAX LITERAL2 RESERVED_WORD_2 +PTRDIFF_MAX LITERAL2 RESERVED_WORD_2 +PTRDIFF_MIN LITERAL2 RESERVED_WORD_2 +SIG_ATOMIC_MAX LITERAL2 RESERVED_WORD_2 +SIG_ATOMIC_MIN LITERAL2 RESERVED_WORD_2 +SIZE_MAX LITERAL2 RESERVED_WORD_2 +WCHAR_MAX LITERAL2 RESERVED_WORD_2 +WCHAR_MIN LITERAL2 RESERVED_WORD_2 +WINT_MAX LITERAL2 RESERVED_WORD_2 +WINT_MIN LITERAL2 RESERVED_WORD_2 + + + +# - http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html +wdt_reset KEYWORD3 RESERVED_WORD +wdt_enable KEYWORD3 RESERVED_WORD +wdt_disable KEYWORD3 RESERVED_WORD +WDTO_15MS LITERAL2 RESERVED_WORD_2 +WDTO_30MS LITERAL2 RESERVED_WORD_2 +WDTO_60MS LITERAL2 RESERVED_WORD_2 +WDTO_120MS LITERAL2 RESERVED_WORD_2 +WDTO_250MS LITERAL2 RESERVED_WORD_2 +WDTO_500MS LITERAL2 RESERVED_WORD_2 +WDTO_1S LITERAL2 RESERVED_WORD_2 +WDTO_2S LITERAL2 RESERVED_WORD_2 +WDTO_4S LITERAL2 RESERVED_WORD_2 +WDTO_8S LITERAL2 RESERVED_WORD_2 + + + +# - definitions, interrupt & vectors +SPH LITERAL2 RESERVED_WORD_2 +SP15 KEYWORD3 RESERVED_WORD +SP14 KEYWORD3 RESERVED_WORD +SP13 KEYWORD3 RESERVED_WORD +SP12 KEYWORD3 RESERVED_WORD +SP11 KEYWORD3 RESERVED_WORD +SP10 KEYWORD3 RESERVED_WORD +SP9 KEYWORD3 RESERVED_WORD +SP8 KEYWORD3 RESERVED_WORD + + + +CCP LITERAL1 +SPH LITERAL1 +SPL LITERAL1 +SREG LITERAL1 +GPIOR0 LITERAL1 +GPIOR1 LITERAL1 +GPIOR2 LITERAL1 +GPIOR3 LITERAL1 +GPIO0 LITERAL1 +GPIO1 LITERAL1 +GPIO2 LITERAL1 +GPIO3 LITERAL1 + +register8_t LITERAL1 +register16_t LITERAL1 +register32_t LITERAL1 + +_WORDREGISTER KEYWORD3 RESERVED_WORD + + +CTRLA LITERAL1 +reserved_0x01 LITERAL1 +MUXCTRLA LITERAL1 +reserved_0x03 LITERAL1 +DACREF LITERAL1 +reserved_0x05 LITERAL1 +INTCTRL LITERAL1 +STATUS LITERAL1 +AC_t LITERAL1 + +AC_HYSMODE_OFF_gc KEYWORD3 RESERVED_WORD +AC_HYSMODE_10mV_gc KEYWORD3 RESERVED_WORD +AC_HYSMODE_25mV_gc KEYWORD3 RESERVED_WORD +AC_HYSMODE_50mV_gc KEYWORD3 RESERVED_WORD +AC_HYSMODE_t LITERAL1 + +AC_INTMODE_BOTHEDGE_gc KEYWORD3 RESERVED_WORD +AC_INTMODE_NEGEDGE_gc KEYWORD3 RESERVED_WORD +AC_INTMODE_POSEDGE_gc KEYWORD3 RESERVED_WORD +AC_INTMODE_t LITERAL1 + +AC_LPMODE_DIS_gc KEYWORD3 RESERVED_WORD +AC_LPMODE_EN_gc KEYWORD3 RESERVED_WORD +AC_LPMODE_t LITERAL1 + +AC_MUXNEG_PIN0_gc KEYWORD3 RESERVED_WORD +AC_MUXNEG_PIN1_gc KEYWORD3 RESERVED_WORD +AC_MUXNEG_PIN2_gc KEYWORD3 RESERVED_WORD +AC_MUXNEG_DACREF_gc KEYWORD3 RESERVED_WORD +AC_MUXNEG_t LITERAL1 + +AC_MUXPOS_PIN0_gc KEYWORD3 RESERVED_WORD +AC_MUXPOS_PIN1_gc KEYWORD3 RESERVED_WORD +AC_MUXPOS_PIN2_gc KEYWORD3 RESERVED_WORD +AC_MUXPOS_PIN3_gc KEYWORD3 RESERVED_WORD +AC_MUXPOS_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +CTRLC LITERAL1 +CTRLD LITERAL1 +CTRLE LITERAL1 +SAMPCTRL LITERAL1 +MUXPOS LITERAL1 +reserved_0x07 LITERAL1 +COMMAND LITERAL1 +EVCTRL LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +DBGCTRL LITERAL1 +TEMP LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +_WORDREGISTER(RES); KEYWORD3 RESERVED_WORD +_WORDREGISTER(WINLT); KEYWORD3 RESERVED_WORD +_WORDREGISTER(WINHT); KEYWORD3 RESERVED_WORD +CALIB LITERAL1 +reserved_0x17 LITERAL1 +ADC_t LITERAL1 + +ADC_ASDV_ASVOFF_gc KEYWORD3 RESERVED_WORD +ADC_ASDV_ASVON_gc KEYWORD3 RESERVED_WORD +ADC_ASDV_t LITERAL1 + +ADC_DUTYCYC_DUTY50_gc KEYWORD3 RESERVED_WORD +ADC_DUTYCYC_DUTY25_gc KEYWORD3 RESERVED_WORD +ADC_DUTYCYC_t LITERAL1 + +ADC_INITDLY_DLY0_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_DLY16_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_DLY32_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_DLY64_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_DLY128_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_DLY256_gc KEYWORD3 RESERVED_WORD +ADC_INITDLY_t LITERAL1 + +ADC_MUXPOS_AIN0_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN1_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_DACREF_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_TEMPSENSE_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_GND_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN2_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN3_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN4_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN5_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN6_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN7_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN8_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN9_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN10_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN11_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN12_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN13_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN14_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_AIN15_gc KEYWORD3 RESERVED_WORD +ADC_MUXPOS_t LITERAL1 + +ADC_PRESC_DIV2_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV4_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV8_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV16_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV32_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV64_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV128_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_DIV256_gc KEYWORD3 RESERVED_WORD +ADC_PRESC_t LITERAL1 + +ADC_REFSEL_INTREF_gc KEYWORD3 RESERVED_WORD +ADC_REFSEL_VDDREF_gc KEYWORD3 RESERVED_WORD +ADC_REFSEL_VREFA_gc KEYWORD3 RESERVED_WORD +ADC_REFSEL_t LITERAL1 + +ADC_RESSEL_10BIT_gc KEYWORD3 RESERVED_WORD +ADC_RESSEL_8BIT_gc KEYWORD3 RESERVED_WORD +ADC_RESSEL_t LITERAL1 + +ADC_SAMPNUM_ACC1_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC2_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC4_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC8_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC16_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC32_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_ACC64_gc KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_t LITERAL1 + +ADC_WINCM_NONE_gc KEYWORD3 RESERVED_WORD +ADC_WINCM_BELOW_gc KEYWORD3 RESERVED_WORD +ADC_WINCM_ABOVE_gc KEYWORD3 RESERVED_WORD +ADC_WINCM_INSIDE_gc KEYWORD3 RESERVED_WORD +ADC_WINCM_OUTSIDE_gc KEYWORD3 RESERVED_WORD +ADC_WINCM_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +reserved_0x02 LITERAL1 +reserved_0x03 LITERAL1 +reserved_0x04 LITERAL1 +reserved_0x05 LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +VLMCTRLA LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +STATUS LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +BOD_t LITERAL1 + +BOD_ACTIVE_DIS_gc KEYWORD3 RESERVED_WORD +BOD_ACTIVE_ENABLED_gc KEYWORD3 RESERVED_WORD +BOD_ACTIVE_SAMPLED_gc KEYWORD3 RESERVED_WORD +BOD_ACTIVE_ENWAKE_gc KEYWORD3 RESERVED_WORD +BOD_ACTIVE_t LITERAL1 + +BOD_LVL_BODLEVEL0_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL1_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL2_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL3_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL4_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL5_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL6_gc KEYWORD3 RESERVED_WORD +BOD_LVL_BODLEVEL7_gc KEYWORD3 RESERVED_WORD +BOD_LVL_t LITERAL1 + +BOD_SAMPFREQ_1KHZ_gc KEYWORD3 RESERVED_WORD +BOD_SAMPFREQ_125HZ_gc KEYWORD3 RESERVED_WORD +BOD_SAMPFREQ_t LITERAL1 + +BOD_SLEEP_DIS_gc KEYWORD3 RESERVED_WORD +BOD_SLEEP_ENABLED_gc KEYWORD3 RESERVED_WORD +BOD_SLEEP_SAMPLED_gc KEYWORD3 RESERVED_WORD +BOD_SLEEP_t LITERAL1 + +BOD_VLMCFG_BELOW_gc KEYWORD3 RESERVED_WORD +BOD_VLMCFG_ABOVE_gc KEYWORD3 RESERVED_WORD +BOD_VLMCFG_CROSS_gc KEYWORD3 RESERVED_WORD +BOD_VLMCFG_t LITERAL1 + +BOD_VLMLVL_5ABOVE_gc KEYWORD3 RESERVED_WORD +BOD_VLMLVL_15ABOVE_gc KEYWORD3 RESERVED_WORD +BOD_VLMLVL_25ABOVE_gc KEYWORD3 RESERVED_WORD +BOD_VLMLVL_t LITERAL1 + + +CTRLA LITERAL1 +SEQCTRL0 LITERAL1 +SEQCTRL1 LITERAL1 +reserved_0x03 LITERAL1 +reserved_0x04 LITERAL1 +INTCTRL0 LITERAL1 +reserved_0x06 LITERAL1 +INTFLAGS LITERAL1 +LUT0CTRLA LITERAL1 +LUT0CTRLB LITERAL1 +LUT0CTRLC LITERAL1 +TRUTH0 LITERAL1 +LUT1CTRLA LITERAL1 +LUT1CTRLB LITERAL1 +LUT1CTRLC LITERAL1 +TRUTH1 LITERAL1 +LUT2CTRLA LITERAL1 +LUT2CTRLB LITERAL1 +LUT2CTRLC LITERAL1 +TRUTH2 LITERAL1 +LUT3CTRLA LITERAL1 +LUT3CTRLB LITERAL1 +LUT3CTRLC LITERAL1 +TRUTH3 LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +reserved_0x20 LITERAL1 +reserved_0x21 LITERAL1 +reserved_0x22 LITERAL1 +reserved_0x23 LITERAL1 +reserved_0x24 LITERAL1 +reserved_0x25 LITERAL1 +reserved_0x26 LITERAL1 +reserved_0x27 LITERAL1 +reserved_0x28 LITERAL1 +reserved_0x29 LITERAL1 +reserved_0x2A LITERAL1 +reserved_0x2B LITERAL1 +reserved_0x2C LITERAL1 +reserved_0x2D LITERAL1 +reserved_0x2E LITERAL1 +reserved_0x2F LITERAL1 +reserved_0x30 LITERAL1 +reserved_0x31 LITERAL1 +reserved_0x32 LITERAL1 +reserved_0x33 LITERAL1 +reserved_0x34 LITERAL1 +reserved_0x35 LITERAL1 +reserved_0x36 LITERAL1 +reserved_0x37 LITERAL1 +reserved_0x38 LITERAL1 +reserved_0x39 LITERAL1 +reserved_0x3A LITERAL1 +reserved_0x3B LITERAL1 +reserved_0x3C LITERAL1 +reserved_0x3D LITERAL1 +reserved_0x3E LITERAL1 +reserved_0x3F LITERAL1 +CCL_t LITERAL1 + +CCL_CLKSRC_CLKPER_gc KEYWORD3 RESERVED_WORD +CCL_CLKSRC_IN2_gc KEYWORD3 RESERVED_WORD +CCL_CLKSRC_OSC20M_gc KEYWORD3 RESERVED_WORD +CCL_CLKSRC_OSCULP32K_gc KEYWORD3 RESERVED_WORD +CCL_CLKSRC_OSCULP1K_gc KEYWORD3 RESERVED_WORD +CCL_CLKSRC_t LITERAL1 + +CCL_EDGEDET_DIS_gc KEYWORD3 RESERVED_WORD +CCL_EDGEDET_EN_gc KEYWORD3 RESERVED_WORD +CCL_EDGEDET_t LITERAL1 + +CCL_FILTSEL_DISABLE_gc KEYWORD3 RESERVED_WORD +CCL_FILTSEL_SYNCH_gc KEYWORD3 RESERVED_WORD +CCL_FILTSEL_FILTER_gc KEYWORD3 RESERVED_WORD +CCL_FILTSEL_t LITERAL1 + +CCL_INSEL0_MASK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_FEEDBACK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_LINK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_EVENTA_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_EVENTB_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_IO_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_AC0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_USART0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_SPI0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_TCA0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_TCB0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL0_t LITERAL1 + +CCL_INSEL1_MASK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_FEEDBACK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_LINK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_EVENTA_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_EVENTB_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_IO_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_AC0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_USART1_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_SPI0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_TCA0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_TCB1_gc KEYWORD3 RESERVED_WORD +CCL_INSEL1_t LITERAL1 + +CCL_INSEL2_MASK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_FEEDBACK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_LINK_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_EVENTA_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_EVENTB_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_IO_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_AC0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_USART2_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_SPI0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_TCA0_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_TCB2_gc KEYWORD3 RESERVED_WORD +CCL_INSEL2_t LITERAL1 + +CCL_INTMODE0_INTDISABLE_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE0_RISING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE0_FALLING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE0_BOTH_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE0_t LITERAL1 + +CCL_INTMODE1_INTDISABLE_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE1_RISING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE1_FALLING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE1_BOTH_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE1_t LITERAL1 + +CCL_INTMODE2_INTDISABLE_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE2_RISING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE2_FALLING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE2_BOTH_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE2_t LITERAL1 + +CCL_INTMODE3_INTDISABLE_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE3_RISING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE3_FALLING_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE3_BOTH_gc KEYWORD3 RESERVED_WORD +CCL_INTMODE3_t LITERAL1 + +CCL_SEQSEL0_DISABLE_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_DFF_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_JK_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_LATCH_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_RS_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_t LITERAL1 + +CCL_SEQSEL1_DISABLE_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_DFF_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_JK_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_LATCH_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_RS_gc KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_t LITERAL1 + + +MCLKCTRLA LITERAL1 +MCLKCTRLB LITERAL1 +MCLKLOCK LITERAL1 +MCLKSTATUS LITERAL1 +reserved_0x04 LITERAL1 +reserved_0x05 LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +reserved_0x08 LITERAL1 +reserved_0x09 LITERAL1 +reserved_0x0A LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +OSC20MCTRLA LITERAL1 +OSC20MCALIBA LITERAL1 +OSC20MCALIBB LITERAL1 +reserved_0x13 LITERAL1 +reserved_0x14 LITERAL1 +reserved_0x15 LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +OSC32KCTRLA LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +XOSC32KCTRLA LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +CLKCTRL_t LITERAL1 + +CLKCTRL_CLKSEL_OSC20M_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL_OSCULP32K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL_XOSC32K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL_EXTCLK_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL_t LITERAL1 + +CLKCTRL_CSUT_1K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_16K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_32K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_64K_gc KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_t LITERAL1 + +CLKCTRL_PDIV_2X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_4X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_8X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_16X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_32X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_64X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_6X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_10X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_12X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_24X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_48X_gc KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_t LITERAL1 + + +CCP_SPM_gc KEYWORD3 RESERVED_WORD +CCP_IOREG_gc KEYWORD3 RESERVED_WORD +CCP_t LITERAL1 + + +CTRLA LITERAL1 +STATUS LITERAL1 +LVL0PRI LITERAL1 +LVL1VEC LITERAL1 +CPUINT_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +STATUS LITERAL1 +reserved_0x03 LITERAL1 +CRCSCAN_t LITERAL1 + +CRCSCAN_MODE_PRIORITY_gc KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_RESERVED_gc KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_BACKGROUND_gc KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_CONTINUOUS_gc KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_t LITERAL1 + +CRCSCAN_SRC_FLASH_gc KEYWORD3 RESERVED_WORD +CRCSCAN_SRC_APPLICATION_gc KEYWORD3 RESERVED_WORD +CRCSCAN_SRC_BOOT_gc KEYWORD3 RESERVED_WORD +CRCSCAN_SRC_t LITERAL1 + + +STROBE LITERAL1 +reserved_0x01 LITERAL1 +reserved_0x02 LITERAL1 +reserved_0x03 LITERAL1 +reserved_0x04 LITERAL1 +reserved_0x05 LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +reserved_0x08 LITERAL1 +reserved_0x09 LITERAL1 +reserved_0x0A LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +CHANNEL0 LITERAL1 +CHANNEL1 LITERAL1 +CHANNEL2 LITERAL1 +CHANNEL3 LITERAL1 +CHANNEL4 LITERAL1 +CHANNEL5 LITERAL1 +CHANNEL6 LITERAL1 +CHANNEL7 LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +USERCCLLUT0A LITERAL1 +USERCCLLUT0B LITERAL1 +USERCCLLUT1A LITERAL1 +USERCCLLUT1B LITERAL1 +USERCCLLUT2A LITERAL1 +USERCCLLUT2B LITERAL1 +USERCCLLUT3A LITERAL1 +USERCCLLUT3B LITERAL1 +USERADC0 LITERAL1 +USEREVOUTA LITERAL1 +USEREVOUTB LITERAL1 +USEREVOUTC LITERAL1 +USEREVOUTD LITERAL1 +USEREVOUTE LITERAL1 +USEREVOUTF LITERAL1 +USERUSART0 LITERAL1 +USERUSART1 LITERAL1 +USERUSART2 LITERAL1 +USERUSART3 LITERAL1 +USERTCA0 LITERAL1 +USERTCB0 LITERAL1 +USERTCB1 LITERAL1 +USERTCB2 LITERAL1 +USERTCB3 LITERAL1 +reserved_0x38 LITERAL1 +reserved_0x39 LITERAL1 +reserved_0x3A LITERAL1 +reserved_0x3B LITERAL1 +reserved_0x3C LITERAL1 +reserved_0x3D LITERAL1 +reserved_0x3E LITERAL1 +reserved_0x3F LITERAL1 +EVSYS_t LITERAL1 + +EVSYS_CHANNEL_OFF_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL0_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL1_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL2_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL3_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL4_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL5_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL6_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_CHANNEL7_gc KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_t LITERAL1 + +EVSYS_GENERATOR_OFF_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_UPDI_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_CCL_LUT0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_CCL_LUT1_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_CCL_LUT2_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_CCL_LUT3_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_AC0_OUT_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_ADC0_COMP_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN1_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN2_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN3_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN4_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN5_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN6_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT0_PIN7_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN1_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN2_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN3_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN4_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN5_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN6_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_PORT1_PIN7_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_OVF_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_USART0_XCK_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_USART1_XCK_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_USART2_XCK_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_USART3_XCK_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_SPI0_SCK_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_CMP_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_PIT0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCA0_OVF_LUNF_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCA0_HUNF_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCA0_CMP0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCA0_CMP1_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCA0_CMP2_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_PIT1_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_PIT2_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCB0_CMP0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCB1_CMP0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCB2_CMP0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_TCB3_CMP0_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_RTC_PIT3_gc KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_t LITERAL1 + +EVSYS_STROBE0_EV_STROBE_CH0_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH1_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH2_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH3_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH4_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH5_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH6_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_EV_STROBE_CH7_gc KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_t LITERAL1 + + +WDTCFG LITERAL1 +BODCFG LITERAL1 +OSCCFG LITERAL1 +reserved_0x03 LITERAL1 +reserved_0x04 LITERAL1 +SYSCFG0 LITERAL1 +SYSCFG1 LITERAL1 +APPEND LITERAL1 +BOOTEND LITERAL1 +FUSE_t LITERAL1 + + +ACTIVE_DIS_gc KEYWORD3 RESERVED_WORD +ACTIVE_ENABLED_gc KEYWORD3 RESERVED_WORD +ACTIVE_SAMPLED_gc KEYWORD3 RESERVED_WORD +ACTIVE_ENWAKE_gc KEYWORD3 RESERVED_WORD +ACTIVE_t LITERAL1 + +CRCSRC_FLASH_gc KEYWORD3 RESERVED_WORD +CRCSRC_BOOT_gc KEYWORD3 RESERVED_WORD +CRCSRC_BOOTAPP_gc KEYWORD3 RESERVED_WORD +CRCSRC_NOCRC_gc KEYWORD3 RESERVED_WORD +CRCSRC_t LITERAL1 + +FREQSEL_16MHZ_gc KEYWORD3 RESERVED_WORD +FREQSEL_20MHZ_gc KEYWORD3 RESERVED_WORD +FREQSEL_t LITERAL1 + +LVL_BODLEVEL0_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL1_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL2_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL3_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL4_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL5_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL6_gc KEYWORD3 RESERVED_WORD +LVL_BODLEVEL7_gc KEYWORD3 RESERVED_WORD +LVL_t LITERAL1 + +PERIOD_OFF_gc KEYWORD3 RESERVED_WORD +PERIOD_8CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_16CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_32CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_64CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_128CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_256CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_512CLK_gc KEYWORD3 RESERVED_WORD +PERIOD_1KCLK_gc KEYWORD3 RESERVED_WORD +PERIOD_2KCLK_gc KEYWORD3 RESERVED_WORD +PERIOD_4KCLK_gc KEYWORD3 RESERVED_WORD +PERIOD_8KCLK_gc KEYWORD3 RESERVED_WORD +PERIOD_t LITERAL1 + +RSTPINCFG_GPIO_gc KEYWORD3 RESERVED_WORD +RSTPINCFG_RST_gc KEYWORD3 RESERVED_WORD +RSTPINCFG_t LITERAL1 + +SAMPFREQ_1KHZ_gc KEYWORD3 RESERVED_WORD +SAMPFREQ_125HZ_gc KEYWORD3 RESERVED_WORD +SAMPFREQ_t LITERAL1 + +SLEEP_DIS_gc KEYWORD3 RESERVED_WORD +SLEEP_ENABLED_gc KEYWORD3 RESERVED_WORD +SLEEP_SAMPLED_gc KEYWORD3 RESERVED_WORD +SLEEP_t LITERAL1 + +SUT_0MS_gc KEYWORD3 RESERVED_WORD +SUT_1MS_gc KEYWORD3 RESERVED_WORD +SUT_2MS_gc KEYWORD3 RESERVED_WORD +SUT_4MS_gc KEYWORD3 RESERVED_WORD +SUT_8MS_gc KEYWORD3 RESERVED_WORD +SUT_16MS_gc KEYWORD3 RESERVED_WORD +SUT_32MS_gc KEYWORD3 RESERVED_WORD +SUT_64MS_gc KEYWORD3 RESERVED_WORD +SUT_t LITERAL1 + +WINDOW_OFF_gc KEYWORD3 RESERVED_WORD +WINDOW_8CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_16CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_32CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_64CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_128CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_256CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_512CLK_gc KEYWORD3 RESERVED_WORD +WINDOW_1KCLK_gc KEYWORD3 RESERVED_WORD +WINDOW_2KCLK_gc KEYWORD3 RESERVED_WORD +WINDOW_4KCLK_gc KEYWORD3 RESERVED_WORD +WINDOW_8KCLK_gc KEYWORD3 RESERVED_WORD +WINDOW_t LITERAL1 + + +LOCKBIT LITERAL1 +reserved_0x01 LITERAL1 +LOCKBIT_t LITERAL1 + +LB_RWLOCK_gc KEYWORD3 RESERVED_WORD +LB_NOLOCK_gc KEYWORD3 RESERVED_WORD +LB_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +STATUS LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +reserved_0x05 LITERAL1 +_WORDREGISTER(DATA); KEYWORD3 RESERVED_WORD +_WORDREGISTER(ADDR); KEYWORD3 RESERVED_WORD +reserved_0x0A LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +NVMCTRL_t LITERAL1 + +NVMCTRL_CMD_NONE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_PAGEWRITE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_PAGEERASE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_PAGEERASEWRITE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_PAGEBUFCLR_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_CHIPERASE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_EEERASE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_FUSEWRITE_gc KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_t LITERAL1 + + +DIR LITERAL1 +DIRSET LITERAL1 +DIRCLR LITERAL1 +DIRTGL LITERAL1 +OUT LITERAL1 +OUTSET LITERAL1 +OUTCLR LITERAL1 +OUTTGL LITERAL1 +IN LITERAL1 +INTFLAGS LITERAL1 +PORTCTRL LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +PIN0CTRL LITERAL1 +PIN1CTRL LITERAL1 +PIN2CTRL LITERAL1 +PIN3CTRL LITERAL1 +PIN4CTRL LITERAL1 +PIN5CTRL LITERAL1 +PIN6CTRL LITERAL1 +PIN7CTRL LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +PORT_t LITERAL1 + +PORT_ISC_INTDISABLE_gc KEYWORD3 RESERVED_WORD +PORT_ISC_BOTHEDGES_gc KEYWORD3 RESERVED_WORD +PORT_ISC_RISING_gc KEYWORD3 RESERVED_WORD +PORT_ISC_FALLING_gc KEYWORD3 RESERVED_WORD +PORT_ISC_INPUT_DISABLE_gc KEYWORD3 RESERVED_WORD +PORT_ISC_LEVEL_gc KEYWORD3 RESERVED_WORD +PORT_ISC_t LITERAL1 + + +EVSYSROUTEA LITERAL1 +CCLROUTEA LITERAL1 +USARTROUTEA LITERAL1 +TWISPIROUTEA LITERAL1 +TCAROUTEA LITERAL1 +TCBROUTEA LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +reserved_0x08 LITERAL1 +reserved_0x09 LITERAL1 +reserved_0x0A LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +PORTMUX_t LITERAL1 + +PORTMUX_SPI0_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_SPI0_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_SPI0_ALT2_gc KEYWORD3 RESERVED_WORD +PORTMUX_SPI0_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_SPI0_t LITERAL1 + +PORTMUX_TCA0_PORTA_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_PORTB_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_PORTC_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_PORTD_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_PORTE_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_PORTF_gc KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_t LITERAL1 + +PORTMUX_TWI0_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_ALT2_gc KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_t LITERAL1 + +PORTMUX_USART0_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART0_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART0_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART0_t LITERAL1 + +PORTMUX_USART1_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART1_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART1_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART1_t LITERAL1 + +PORTMUX_USART2_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART2_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART2_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART2_t LITERAL1 + +PORTMUX_USART3_DEFAULT_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART3_ALT1_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART3_NONE_gc KEYWORD3 RESERVED_WORD +PORTMUX_USART3_t LITERAL1 + + +RSTFR LITERAL1 +SWRR LITERAL1 +reserved_0x02 LITERAL1 +reserved_0x03 LITERAL1 +RSTCTRL_t LITERAL1 + + +CTRLA LITERAL1 +STATUS LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +TEMP LITERAL1 +DBGCTRL LITERAL1 +CALIB LITERAL1 +CLKSEL LITERAL1 +_WORDREGISTER(CNT); KEYWORD3 RESERVED_WORD +_WORDREGISTER(PER); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP); KEYWORD3 RESERVED_WORD +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +PITCTRLA LITERAL1 +PITSTATUS LITERAL1 +PITINTCTRL LITERAL1 +PITINTFLAGS LITERAL1 +reserved_0x14 LITERAL1 +PITDBGCTRL LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +RTC_t LITERAL1 + +RTC_CLKSEL_INT32K_gc KEYWORD3 RESERVED_WORD +RTC_CLKSEL_INT1K_gc KEYWORD3 RESERVED_WORD +RTC_CLKSEL_TOSC32K_gc KEYWORD3 RESERVED_WORD +RTC_CLKSEL_EXTCLK_gc KEYWORD3 RESERVED_WORD +RTC_CLKSEL_t LITERAL1 + +RTC_PERIOD_OFF_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC4_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC8_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC16_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC32_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC64_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC128_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC256_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC512_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC1024_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC2048_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC4096_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC8192_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC16384_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_CYC32768_gc KEYWORD3 RESERVED_WORD +RTC_PERIOD_t LITERAL1 + +RTC_PRESCALER_DIV1_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV2_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV4_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV8_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV16_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV32_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV64_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV128_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV256_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV512_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV1024_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV2048_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV4096_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV8192_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV16384_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_DIV32768_gc KEYWORD3 RESERVED_WORD +RTC_PRESCALER_t LITERAL1 + + +DEVICEID0 LITERAL1 +DEVICEID1 LITERAL1 +DEVICEID2 LITERAL1 +SERNUM0 LITERAL1 +SERNUM1 LITERAL1 +SERNUM2 LITERAL1 +SERNUM3 LITERAL1 +SERNUM4 LITERAL1 +SERNUM5 LITERAL1 +SERNUM6 LITERAL1 +SERNUM7 LITERAL1 +SERNUM8 LITERAL1 +SERNUM9 LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +reserved_0x10 LITERAL1 +reserved_0x11 LITERAL1 +reserved_0x12 LITERAL1 +reserved_0x13 LITERAL1 +OSCCAL32K LITERAL1 +reserved_0x15 LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +OSCCAL16M0 LITERAL1 +OSCCAL16M1 LITERAL1 +OSCCAL20M0 LITERAL1 +OSCCAL20M1 LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +TEMPSENSE0 LITERAL1 +TEMPSENSE1 LITERAL1 +OSC16ERR3V LITERAL1 +OSC16ERR5V LITERAL1 +OSC20ERR3V LITERAL1 +OSC20ERR5V LITERAL1 +reserved_0x26 LITERAL1 +reserved_0x27 LITERAL1 +reserved_0x28 LITERAL1 +reserved_0x29 LITERAL1 +reserved_0x2A LITERAL1 +reserved_0x2B LITERAL1 +reserved_0x2C LITERAL1 +reserved_0x2D LITERAL1 +reserved_0x2E LITERAL1 +CHECKSUM1 LITERAL1 +reserved_0x30 LITERAL1 +reserved_0x31 LITERAL1 +reserved_0x32 LITERAL1 +reserved_0x33 LITERAL1 +reserved_0x34 LITERAL1 +reserved_0x35 LITERAL1 +reserved_0x36 LITERAL1 +reserved_0x37 LITERAL1 +reserved_0x38 LITERAL1 +reserved_0x39 LITERAL1 +reserved_0x3A LITERAL1 +reserved_0x3B LITERAL1 +reserved_0x3C LITERAL1 +reserved_0x3D LITERAL1 +reserved_0x3E LITERAL1 +reserved_0x3F LITERAL1 +SIGROW_t LITERAL1 + + +CTRLA LITERAL1 +reserved_0x01 LITERAL1 +SLPCTRL_t LITERAL1 + +SLPCTRL_SMODE_IDLE_gc KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE_STDBY_gc KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE_PDOWN_gc KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE_t LITERAL1 +#define KEYWORD3 RESERVED_WORD +#define KEYWORD3 RESERVED_WORD +#define KEYWORD3 RESERVED_WORD + + +CTRLA LITERAL1 +CTRLB LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +DATA LITERAL1 +reserved_0x05 LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +SPI_t LITERAL1 + +SPI_MODE_0_gc KEYWORD3 RESERVED_WORD +SPI_MODE_1_gc KEYWORD3 RESERVED_WORD +SPI_MODE_2_gc KEYWORD3 RESERVED_WORD +SPI_MODE_3_gc KEYWORD3 RESERVED_WORD +SPI_MODE_t LITERAL1 + +SPI_PRESC_DIV4_gc KEYWORD3 RESERVED_WORD +SPI_PRESC_DIV16_gc KEYWORD3 RESERVED_WORD +SPI_PRESC_DIV64_gc KEYWORD3 RESERVED_WORD +SPI_PRESC_DIV128_gc KEYWORD3 RESERVED_WORD +SPI_PRESC_t LITERAL1 + + +reserved_0x00 LITERAL1 +REVID LITERAL1 +EXTBRK LITERAL1 +reserved_0x03 LITERAL1 +reserved_0x04 LITERAL1 +reserved_0x05 LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +reserved_0x08 LITERAL1 +reserved_0x09 LITERAL1 +reserved_0x0A LITERAL1 +reserved_0x0B LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +reserved_0x10 LITERAL1 +reserved_0x11 LITERAL1 +reserved_0x12 LITERAL1 +reserved_0x13 LITERAL1 +reserved_0x14 LITERAL1 +reserved_0x15 LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +OCDM LITERAL1 +OCDMS LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +SYSCFG_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +CTRLC LITERAL1 +CTRLD LITERAL1 +CTRLECLR LITERAL1 +CTRLESET LITERAL1 +CTRLFCLR LITERAL1 +CTRLFSET LITERAL1 +reserved_0x08 LITERAL1 +EVCTRL LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +DBGCTRL LITERAL1 +TEMP LITERAL1 +reserved_0x10 LITERAL1 +reserved_0x11 LITERAL1 +reserved_0x12 LITERAL1 +reserved_0x13 LITERAL1 +reserved_0x14 LITERAL1 +reserved_0x15 LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +_WORDREGISTER(CNT); KEYWORD3 RESERVED_WORD +reserved_0x22 LITERAL1 +reserved_0x23 LITERAL1 +reserved_0x24 LITERAL1 +reserved_0x25 LITERAL1 +_WORDREGISTER(PER); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP0); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP1); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP2); KEYWORD3 RESERVED_WORD +reserved_0x2E LITERAL1 +reserved_0x2F LITERAL1 +reserved_0x30 LITERAL1 +reserved_0x31 LITERAL1 +reserved_0x32 LITERAL1 +reserved_0x33 LITERAL1 +reserved_0x34 LITERAL1 +reserved_0x35 LITERAL1 +_WORDREGISTER(PERBUF); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP0BUF); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP1BUF); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CMP2BUF); KEYWORD3 RESERVED_WORD +reserved_0x3E LITERAL1 +reserved_0x3F LITERAL1 +TCA_SINGLE_t LITERAL1 + +CTRLA LITERAL1 +CTRLB LITERAL1 +CTRLC LITERAL1 +CTRLD LITERAL1 +CTRLECLR LITERAL1 +CTRLESET LITERAL1 +reserved_0x06 LITERAL1 +reserved_0x07 LITERAL1 +reserved_0x08 LITERAL1 +reserved_0x09 LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +reserved_0x0C LITERAL1 +reserved_0x0D LITERAL1 +DBGCTRL LITERAL1 +reserved_0x0F LITERAL1 +reserved_0x10 LITERAL1 +reserved_0x11 LITERAL1 +reserved_0x12 LITERAL1 +reserved_0x13 LITERAL1 +reserved_0x14 LITERAL1 +reserved_0x15 LITERAL1 +reserved_0x16 LITERAL1 +reserved_0x17 LITERAL1 +reserved_0x18 LITERAL1 +reserved_0x19 LITERAL1 +reserved_0x1A LITERAL1 +reserved_0x1B LITERAL1 +reserved_0x1C LITERAL1 +reserved_0x1D LITERAL1 +reserved_0x1E LITERAL1 +reserved_0x1F LITERAL1 +LCNT LITERAL1 +HCNT LITERAL1 +reserved_0x22 LITERAL1 +reserved_0x23 LITERAL1 +reserved_0x24 LITERAL1 +reserved_0x25 LITERAL1 +LPER LITERAL1 +HPER LITERAL1 +LCMP0 LITERAL1 +HCMP0 LITERAL1 +LCMP1 LITERAL1 +HCMP1 LITERAL1 +LCMP2 LITERAL1 +HCMP2 LITERAL1 +reserved_0x2E LITERAL1 +reserved_0x2F LITERAL1 +reserved_0x30 LITERAL1 +reserved_0x31 LITERAL1 +reserved_0x32 LITERAL1 +reserved_0x33 LITERAL1 +reserved_0x34 LITERAL1 +reserved_0x35 LITERAL1 +reserved_0x36 LITERAL1 +reserved_0x37 LITERAL1 +reserved_0x38 LITERAL1 +reserved_0x39 LITERAL1 +reserved_0x3A LITERAL1 +reserved_0x3B LITERAL1 +reserved_0x3C LITERAL1 +reserved_0x3D LITERAL1 +reserved_0x3E LITERAL1 +reserved_0x3F LITERAL1 +TCA_SPLIT_t LITERAL1 + +TCA_SINGLE_t KEYWORD3 RESERVED_WORD +TCA_SPLIT_t KEYWORD3 RESERVED_WORD +TCA_t LITERAL1 + +TCA_SINGLE_CLKSEL_DIV1_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV2_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV4_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV8_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV16_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV64_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV256_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_DIV1024_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_t LITERAL1 + +TCA_SINGLE_CMD_NONE_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_UPDATE_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_RESTART_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_RESET_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_t LITERAL1 + +TCA_SINGLE_DIR_UP_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_DIR_DOWN_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_DIR_t LITERAL1 + +TCA_SINGLE_EVACT_POSEDGE_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_ANYEDGE_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_HIGHLVL_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_UPDOWN_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_t LITERAL1 + +TCA_SINGLE_WGMODE_NORMAL_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_FRQ_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_SINGLESLOPE_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_DSTOP_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_DSBOTH_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_DSBOTTOM_gc KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_t LITERAL1 + +TCA_SPLIT_CLKSEL_DIV1_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV2_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV4_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV8_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV16_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV64_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV256_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_DIV1024_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_t LITERAL1 + +TCA_SPLIT_CMD_NONE_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD_UPDATE_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD_RESTART_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD_RESET_gc KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +reserved_0x02 LITERAL1 +reserved_0x03 LITERAL1 +EVCTRL LITERAL1 +INTCTRL LITERAL1 +INTFLAGS LITERAL1 +STATUS LITERAL1 +DBGCTRL LITERAL1 +TEMP LITERAL1 +_WORDREGISTER(CNT); KEYWORD3 RESERVED_WORD +_WORDREGISTER(CCMP); KEYWORD3 RESERVED_WORD +reserved_0x0E LITERAL1 +reserved_0x0F LITERAL1 +TCB_t LITERAL1 + +TCB_CLKSEL_CLKDIV1_gc KEYWORD3 RESERVED_WORD +TCB_CLKSEL_CLKDIV2_gc KEYWORD3 RESERVED_WORD +TCB_CLKSEL_CLKTCA_gc KEYWORD3 RESERVED_WORD +TCB_CLKSEL_t LITERAL1 + +TCB_CNTMODE_INT_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_TIMEOUT_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_CAPT_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_FRQ_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_PW_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_FRQPW_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_SINGLE_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_PWM8_gc KEYWORD3 RESERVED_WORD +TCB_CNTMODE_t LITERAL1 + + +CTRLA LITERAL1 +DUALCTRL LITERAL1 +DBGCTRL LITERAL1 +MCTRLA LITERAL1 +MCTRLB LITERAL1 +MSTATUS LITERAL1 +MBAUD LITERAL1 +MADDR LITERAL1 +MDATA LITERAL1 +SCTRLA LITERAL1 +SCTRLB LITERAL1 +SSTATUS LITERAL1 +SADDR LITERAL1 +SDATA LITERAL1 +SADDRMASK LITERAL1 +reserved_0x0F LITERAL1 +TWI_t LITERAL1 + +TWI_ACKACT_ACK_gc KEYWORD3 RESERVED_WORD +TWI_ACKACT_NACK_gc KEYWORD3 RESERVED_WORD +TWI_ACKACT_t LITERAL1 + +TWI_AP_STOP_gc KEYWORD3 RESERVED_WORD +TWI_AP_ADR_gc KEYWORD3 RESERVED_WORD +TWI_AP_t LITERAL1 + +TWI_BUSSTATE_UNKNOWN_gc KEYWORD3 RESERVED_WORD +TWI_BUSSTATE_IDLE_gc KEYWORD3 RESERVED_WORD +TWI_BUSSTATE_OWNER_gc KEYWORD3 RESERVED_WORD +TWI_BUSSTATE_BUSY_gc KEYWORD3 RESERVED_WORD +TWI_BUSSTATE_t LITERAL1 + +TWI_MCMD_NOACT_gc KEYWORD3 RESERVED_WORD +TWI_MCMD_REPSTART_gc KEYWORD3 RESERVED_WORD +TWI_MCMD_RECVTRANS_gc KEYWORD3 RESERVED_WORD +TWI_MCMD_STOP_gc KEYWORD3 RESERVED_WORD +TWI_MCMD_t LITERAL1 + +TWI_SCMD_NOACT_gc KEYWORD3 RESERVED_WORD +TWI_SCMD_COMPTRANS_gc KEYWORD3 RESERVED_WORD +TWI_SCMD_RESPONSE_gc KEYWORD3 RESERVED_WORD +TWI_SCMD_t LITERAL1 + +TWI_SDAHOLD_OFF_gc KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_50NS_gc KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_300NS_gc KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_500NS_gc KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_t LITERAL1 + +TWI_SDASETUP_4CYC_gc KEYWORD3 RESERVED_WORD +TWI_SDASETUP_8CYC_gc KEYWORD3 RESERVED_WORD +TWI_SDASETUP_t LITERAL1 + +TWI_TIMEOUT_DISABLED_gc KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_50US_gc KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_100US_gc KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_200US_gc KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_t LITERAL1 + + +RXDATAL LITERAL1 +RXDATAH LITERAL1 +TXDATAL LITERAL1 +TXDATAH LITERAL1 +STATUS LITERAL1 +CTRLA LITERAL1 +CTRLB LITERAL1 +CTRLC LITERAL1 +_WORDREGISTER(BAUD); KEYWORD3 RESERVED_WORD +CTRLD LITERAL1 +DBGCTRL LITERAL1 +EVCTRL LITERAL1 +TXPLCTRL LITERAL1 +RXPLCTRL LITERAL1 +reserved_0x0F LITERAL1 +USART_t LITERAL1 + +USART_ABW_WDW0_gc KEYWORD3 RESERVED_WORD +USART_ABW_WDW1_gc KEYWORD3 RESERVED_WORD +USART_ABW_WDW2_gc KEYWORD3 RESERVED_WORD +USART_ABW_WDW3_gc KEYWORD3 RESERVED_WORD +USART_ABW_t LITERAL1 + +USART_CHSIZE_5BIT_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_6BIT_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_7BIT_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_8BIT_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_9BITL_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_9BITH_gc KEYWORD3 RESERVED_WORD +USART_CHSIZE_t LITERAL1 + +USART_CMODE_ASYNCHRONOUS_gc KEYWORD3 RESERVED_WORD +USART_CMODE_SYNCHRONOUS_gc KEYWORD3 RESERVED_WORD +USART_CMODE_IRCOM_gc KEYWORD3 RESERVED_WORD +USART_CMODE_MSPI_gc KEYWORD3 RESERVED_WORD +USART_CMODE_t LITERAL1 + +USART_PMODE_DISABLED_gc KEYWORD3 RESERVED_WORD +USART_PMODE_EVEN_gc KEYWORD3 RESERVED_WORD +USART_PMODE_ODD_gc KEYWORD3 RESERVED_WORD +USART_PMODE_t LITERAL1 + +USART_RS485_OFF_gc KEYWORD3 RESERVED_WORD +USART_RS485_EXT_gc KEYWORD3 RESERVED_WORD +USART_RS485_INT_gc KEYWORD3 RESERVED_WORD +USART_RS485_t LITERAL1 + +USART_RXMODE_NORMAL_gc KEYWORD3 RESERVED_WORD +USART_RXMODE_CLK2X_gc KEYWORD3 RESERVED_WORD +USART_RXMODE_GENAUTO_gc KEYWORD3 RESERVED_WORD +USART_RXMODE_LINAUTO_gc KEYWORD3 RESERVED_WORD +USART_RXMODE_t LITERAL1 + +USART_SBMODE_1BIT_gc KEYWORD3 RESERVED_WORD +USART_SBMODE_2BIT_gc KEYWORD3 RESERVED_WORD +USART_SBMODE_t LITERAL1 + + +USERROW0 LITERAL1 +USERROW1 LITERAL1 +USERROW2 LITERAL1 +USERROW3 LITERAL1 +USERROW4 LITERAL1 +USERROW5 LITERAL1 +USERROW6 LITERAL1 +USERROW7 LITERAL1 +USERROW8 LITERAL1 +USERROW9 LITERAL1 +USERROW10 LITERAL1 +USERROW11 LITERAL1 +USERROW12 LITERAL1 +USERROW13 LITERAL1 +USERROW14 LITERAL1 +USERROW15 LITERAL1 +USERROW16 LITERAL1 +USERROW17 LITERAL1 +USERROW18 LITERAL1 +USERROW19 LITERAL1 +USERROW20 LITERAL1 +USERROW21 LITERAL1 +USERROW22 LITERAL1 +USERROW23 LITERAL1 +USERROW24 LITERAL1 +USERROW25 LITERAL1 +USERROW26 LITERAL1 +USERROW27 LITERAL1 +USERROW28 LITERAL1 +USERROW29 LITERAL1 +USERROW30 LITERAL1 +USERROW31 LITERAL1 +USERROW32 LITERAL1 +USERROW33 LITERAL1 +USERROW34 LITERAL1 +USERROW35 LITERAL1 +USERROW36 LITERAL1 +USERROW37 LITERAL1 +USERROW38 LITERAL1 +USERROW39 LITERAL1 +USERROW40 LITERAL1 +USERROW41 LITERAL1 +USERROW42 LITERAL1 +USERROW43 LITERAL1 +USERROW44 LITERAL1 +USERROW45 LITERAL1 +USERROW46 LITERAL1 +USERROW47 LITERAL1 +USERROW48 LITERAL1 +USERROW49 LITERAL1 +USERROW50 LITERAL1 +USERROW51 LITERAL1 +USERROW52 LITERAL1 +USERROW53 LITERAL1 +USERROW54 LITERAL1 +USERROW55 LITERAL1 +USERROW56 LITERAL1 +USERROW57 LITERAL1 +USERROW58 LITERAL1 +USERROW59 LITERAL1 +USERROW60 LITERAL1 +USERROW61 LITERAL1 +USERROW62 LITERAL1 +USERROW63 LITERAL1 +USERROW_t LITERAL1 + + +DIR LITERAL1 +OUT LITERAL1 +IN LITERAL1 +INTFLAGS LITERAL1 +VPORT_t LITERAL1 + + +CTRLA LITERAL1 +CTRLB LITERAL1 +VREF_t LITERAL1 + +VREF_AC0REFSEL_0V55_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_1V1_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_2V5_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_4V34_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_1V5_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_AVDD_gc KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_t LITERAL1 + +VREF_ADC0REFSEL_0V55_gc KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_1V1_gc KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_2V5_gc KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_4V34_gc KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_1V5_gc KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_t LITERAL1 + + +CTRLA LITERAL1 +STATUS LITERAL1 +WDT_t LITERAL1 + +WDT_PERIOD_OFF_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_8CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_16CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_32CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_64CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_128CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_256CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_512CLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_1KCLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_2KCLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_4KCLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_8KCLK_gc KEYWORD3 RESERVED_WORD +WDT_PERIOD_t LITERAL1 + +WDT_WINDOW_OFF_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_8CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_16CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_32CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_64CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_128CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_256CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_512CLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_1KCLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_2KCLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_4KCLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_8KCLK_gc KEYWORD3 RESERVED_WORD +WDT_WINDOW_t LITERAL1 + +VPORTA KEYWORD2 +VPORTB KEYWORD2 +VPORTC KEYWORD2 +VPORTD KEYWORD2 +VPORTE KEYWORD2 +VPORTF KEYWORD2 +RSTCTRL KEYWORD2 +SLPCTRL KEYWORD2 +CLKCTRL KEYWORD2 +BOD KEYWORD2 +VREF KEYWORD2 +WDT KEYWORD2 +CPUINT KEYWORD2 +CRCSCAN KEYWORD2 +RTC KEYWORD2 +EVSYS KEYWORD2 +CCL KEYWORD2 +PORTA KEYWORD2 +PORTB KEYWORD2 +PORTC KEYWORD2 +PORTD KEYWORD2 +PORTE KEYWORD2 +PORTF KEYWORD2 +PORTMUX KEYWORD2 +ADC0 KEYWORD2 +AC0 KEYWORD2 +USART0 KEYWORD2 +USART1 KEYWORD2 +USART2 KEYWORD2 +USART3 KEYWORD2 +TWI0 KEYWORD2 +SPI0 KEYWORD2 +TCA0 KEYWORD2 +TCB0 KEYWORD2 +TCB1 KEYWORD2 +TCB2 KEYWORD2 +TCB3 KEYWORD2 +SYSCFG KEYWORD2 +NVMCTRL KEYWORD2 +SIGROW KEYWORD2 +FUSE KEYWORD2 +LOCKBIT KEYWORD2 +USERROW KEYWORD2 + + +VPORTA_DIR LITERAL1 +VPORTA_OUT LITERAL1 +VPORTA_IN LITERAL1 +VPORTA_INTFLAGS LITERAL1 + +VPORTB_DIR LITERAL1 +VPORTB_OUT LITERAL1 +VPORTB_IN LITERAL1 +VPORTB_INTFLAGS LITERAL1 + +VPORTC_DIR LITERAL1 +VPORTC_OUT LITERAL1 +VPORTC_IN LITERAL1 +VPORTC_INTFLAGS LITERAL1 + +VPORTD_DIR LITERAL1 +VPORTD_OUT LITERAL1 +VPORTD_IN LITERAL1 +VPORTD_INTFLAGS LITERAL1 + +VPORTE_DIR LITERAL1 +VPORTE_OUT LITERAL1 +VPORTE_IN LITERAL1 +VPORTE_INTFLAGS LITERAL1 + +VPORTF_DIR LITERAL1 +VPORTF_OUT LITERAL1 +VPORTF_IN LITERAL1 +VPORTF_INTFLAGS LITERAL1 + +GPIO_GPIOR0 LITERAL1 +GPIO_GPIOR1 LITERAL1 +GPIO_GPIOR2 LITERAL1 +GPIO_GPIOR3 LITERAL1 + +GPIO_GPIO0 LITERAL1 +GPIO_GPIO1 LITERAL1 +GPIO_GPIO2 LITERAL1 +GPIO_GPIO3 LITERAL1 + +CPU_CCP LITERAL1 +CPU_SPL LITERAL1 +CPU_SPH LITERAL1 +CPU_SREG LITERAL1 + +RSTCTRL_RSTFR LITERAL1 +RSTCTRL_SWRR LITERAL1 + +SLPCTRL_CTRLA LITERAL1 + +CLKCTRL_MCLKCTRLA LITERAL1 +CLKCTRL_MCLKCTRLB LITERAL1 +CLKCTRL_MCLKLOCK LITERAL1 +CLKCTRL_MCLKSTATUS LITERAL1 +CLKCTRL_OSC20MCTRLA LITERAL1 +CLKCTRL_OSC20MCALIBA LITERAL1 +CLKCTRL_OSC20MCALIBB LITERAL1 +CLKCTRL_OSC32KCTRLA LITERAL1 +CLKCTRL_XOSC32KCTRLA LITERAL1 + +BOD_CTRLA LITERAL1 +BOD_CTRLB LITERAL1 +BOD_VLMCTRLA LITERAL1 +BOD_INTCTRL LITERAL1 +BOD_INTFLAGS LITERAL1 +BOD_STATUS LITERAL1 + +VREF_CTRLA LITERAL1 +VREF_CTRLB LITERAL1 + +WDT_CTRLA LITERAL1 +WDT_STATUS LITERAL1 + +CPUINT_CTRLA LITERAL1 +CPUINT_STATUS LITERAL1 +CPUINT_LVL0PRI LITERAL1 +CPUINT_LVL1VEC LITERAL1 + +CRCSCAN_CTRLA LITERAL1 +CRCSCAN_CTRLB LITERAL1 +CRCSCAN_STATUS LITERAL1 + +RTC_CTRLA LITERAL1 +RTC_STATUS LITERAL1 +RTC_INTCTRL LITERAL1 +RTC_INTFLAGS LITERAL1 +RTC_TEMP LITERAL1 +RTC_DBGCTRL LITERAL1 +RTC_CALIB LITERAL1 +RTC_CLKSEL LITERAL1 +RTC_CNT LITERAL1 +RTC_CNTL LITERAL1 +RTC_CNTH LITERAL1 +RTC_PER LITERAL1 +RTC_PERL LITERAL1 +RTC_PERH LITERAL1 +RTC_CMP LITERAL1 +RTC_CMPL LITERAL1 +RTC_CMPH LITERAL1 +RTC_PITCTRLA LITERAL1 +RTC_PITSTATUS LITERAL1 +RTC_PITINTCTRL LITERAL1 +RTC_PITINTFLAGS LITERAL1 +RTC_PITDBGCTRL LITERAL1 + +EVSYS_STROBE LITERAL1 +EVSYS_CHANNEL0 LITERAL1 +EVSYS_CHANNEL1 LITERAL1 +EVSYS_CHANNEL2 LITERAL1 +EVSYS_CHANNEL3 LITERAL1 +EVSYS_CHANNEL4 LITERAL1 +EVSYS_CHANNEL5 LITERAL1 +EVSYS_CHANNEL6 LITERAL1 +EVSYS_CHANNEL7 LITERAL1 +EVSYS_USERCCLLUT0A LITERAL1 +EVSYS_USERCCLLUT0B LITERAL1 +EVSYS_USERCCLLUT1A LITERAL1 +EVSYS_USERCCLLUT1B LITERAL1 +EVSYS_USERCCLLUT2A LITERAL1 +EVSYS_USERCCLLUT2B LITERAL1 +EVSYS_USERCCLLUT3A LITERAL1 +EVSYS_USERCCLLUT3B LITERAL1 +EVSYS_USERADC0 LITERAL1 +EVSYS_USEREVOUTA LITERAL1 +EVSYS_USEREVOUTB LITERAL1 +EVSYS_USEREVOUTC LITERAL1 +EVSYS_USEREVOUTD LITERAL1 +EVSYS_USEREVOUTE LITERAL1 +EVSYS_USEREVOUTF LITERAL1 +EVSYS_USERUSART0 LITERAL1 +EVSYS_USERUSART1 LITERAL1 +EVSYS_USERUSART2 LITERAL1 +EVSYS_USERUSART3 LITERAL1 +EVSYS_USERTCA0 LITERAL1 +EVSYS_USERTCB0 LITERAL1 +EVSYS_USERTCB1 LITERAL1 +EVSYS_USERTCB2 LITERAL1 +EVSYS_USERTCB3 LITERAL1 + +CCL_CTRLA LITERAL1 +CCL_SEQCTRL0 LITERAL1 +CCL_SEQCTRL1 LITERAL1 +CCL_INTCTRL0 LITERAL1 +CCL_INTFLAGS LITERAL1 +CCL_LUT0CTRLA LITERAL1 +CCL_LUT0CTRLB LITERAL1 +CCL_LUT0CTRLC LITERAL1 +CCL_TRUTH0 LITERAL1 +CCL_LUT1CTRLA LITERAL1 +CCL_LUT1CTRLB LITERAL1 +CCL_LUT1CTRLC LITERAL1 +CCL_TRUTH1 LITERAL1 +CCL_LUT2CTRLA LITERAL1 +CCL_LUT2CTRLB LITERAL1 +CCL_LUT2CTRLC LITERAL1 +CCL_TRUTH2 LITERAL1 +CCL_LUT3CTRLA LITERAL1 +CCL_LUT3CTRLB LITERAL1 +CCL_LUT3CTRLC LITERAL1 +CCL_TRUTH3 LITERAL1 + +PORTA_DIR LITERAL1 +PORTA_DIRSET LITERAL1 +PORTA_DIRCLR LITERAL1 +PORTA_DIRTGL LITERAL1 +PORTA_OUT LITERAL1 +PORTA_OUTSET LITERAL1 +PORTA_OUTCLR LITERAL1 +PORTA_OUTTGL LITERAL1 +PORTA_IN LITERAL1 +PORTA_INTFLAGS LITERAL1 +PORTA_PORTCTRL LITERAL1 +PORTA_PIN0CTRL LITERAL1 +PORTA_PIN1CTRL LITERAL1 +PORTA_PIN2CTRL LITERAL1 +PORTA_PIN3CTRL LITERAL1 +PORTA_PIN4CTRL LITERAL1 +PORTA_PIN5CTRL LITERAL1 +PORTA_PIN6CTRL LITERAL1 +PORTA_PIN7CTRL LITERAL1 + +PORTB_DIR LITERAL1 +PORTB_DIRSET LITERAL1 +PORTB_DIRCLR LITERAL1 +PORTB_DIRTGL LITERAL1 +PORTB_OUT LITERAL1 +PORTB_OUTSET LITERAL1 +PORTB_OUTCLR LITERAL1 +PORTB_OUTTGL LITERAL1 +PORTB_IN LITERAL1 +PORTB_INTFLAGS LITERAL1 +PORTB_PORTCTRL LITERAL1 +PORTB_PIN0CTRL LITERAL1 +PORTB_PIN1CTRL LITERAL1 +PORTB_PIN2CTRL LITERAL1 +PORTB_PIN3CTRL LITERAL1 +PORTB_PIN4CTRL LITERAL1 +PORTB_PIN5CTRL LITERAL1 +PORTB_PIN6CTRL LITERAL1 +PORTB_PIN7CTRL LITERAL1 + +PORTC_DIR LITERAL1 +PORTC_DIRSET LITERAL1 +PORTC_DIRCLR LITERAL1 +PORTC_DIRTGL LITERAL1 +PORTC_OUT LITERAL1 +PORTC_OUTSET LITERAL1 +PORTC_OUTCLR LITERAL1 +PORTC_OUTTGL LITERAL1 +PORTC_IN LITERAL1 +PORTC_INTFLAGS LITERAL1 +PORTC_PORTCTRL LITERAL1 +PORTC_PIN0CTRL LITERAL1 +PORTC_PIN1CTRL LITERAL1 +PORTC_PIN2CTRL LITERAL1 +PORTC_PIN3CTRL LITERAL1 +PORTC_PIN4CTRL LITERAL1 +PORTC_PIN5CTRL LITERAL1 +PORTC_PIN6CTRL LITERAL1 +PORTC_PIN7CTRL LITERAL1 + +PORTD_DIR LITERAL1 +PORTD_DIRSET LITERAL1 +PORTD_DIRCLR LITERAL1 +PORTD_DIRTGL LITERAL1 +PORTD_OUT LITERAL1 +PORTD_OUTSET LITERAL1 +PORTD_OUTCLR LITERAL1 +PORTD_OUTTGL LITERAL1 +PORTD_IN LITERAL1 +PORTD_INTFLAGS LITERAL1 +PORTD_PORTCTRL LITERAL1 +PORTD_PIN0CTRL LITERAL1 +PORTD_PIN1CTRL LITERAL1 +PORTD_PIN2CTRL LITERAL1 +PORTD_PIN3CTRL LITERAL1 +PORTD_PIN4CTRL LITERAL1 +PORTD_PIN5CTRL LITERAL1 +PORTD_PIN6CTRL LITERAL1 +PORTD_PIN7CTRL LITERAL1 + +PORTE_DIR LITERAL1 +PORTE_DIRSET LITERAL1 +PORTE_DIRCLR LITERAL1 +PORTE_DIRTGL LITERAL1 +PORTE_OUT LITERAL1 +PORTE_OUTSET LITERAL1 +PORTE_OUTCLR LITERAL1 +PORTE_OUTTGL LITERAL1 +PORTE_IN LITERAL1 +PORTE_INTFLAGS LITERAL1 +PORTE_PORTCTRL LITERAL1 +PORTE_PIN0CTRL LITERAL1 +PORTE_PIN1CTRL LITERAL1 +PORTE_PIN2CTRL LITERAL1 +PORTE_PIN3CTRL LITERAL1 +PORTE_PIN4CTRL LITERAL1 +PORTE_PIN5CTRL LITERAL1 +PORTE_PIN6CTRL LITERAL1 +PORTE_PIN7CTRL LITERAL1 + +PORTF_DIR LITERAL1 +PORTF_DIRSET LITERAL1 +PORTF_DIRCLR LITERAL1 +PORTF_DIRTGL LITERAL1 +PORTF_OUT LITERAL1 +PORTF_OUTSET LITERAL1 +PORTF_OUTCLR LITERAL1 +PORTF_OUTTGL LITERAL1 +PORTF_IN LITERAL1 +PORTF_INTFLAGS LITERAL1 +PORTF_PORTCTRL LITERAL1 +PORTF_PIN0CTRL LITERAL1 +PORTF_PIN1CTRL LITERAL1 +PORTF_PIN2CTRL LITERAL1 +PORTF_PIN3CTRL LITERAL1 +PORTF_PIN4CTRL LITERAL1 +PORTF_PIN5CTRL LITERAL1 +PORTF_PIN6CTRL LITERAL1 +PORTF_PIN7CTRL LITERAL1 + +PORTMUX_EVSYSROUTEA LITERAL1 +PORTMUX_CCLROUTEA LITERAL1 +PORTMUX_USARTROUTEA LITERAL1 +PORTMUX_TWISPIROUTEA LITERAL1 +PORTMUX_TCAROUTEA LITERAL1 +PORTMUX_TCBROUTEA LITERAL1 + +ADC0_CTRLA LITERAL1 +ADC0_CTRLB LITERAL1 +ADC0_CTRLC LITERAL1 +ADC0_CTRLD LITERAL1 +ADC0_CTRLE LITERAL1 +ADC0_SAMPCTRL LITERAL1 +ADC0_MUXPOS LITERAL1 +ADC0_COMMAND LITERAL1 +ADC0_EVCTRL LITERAL1 +ADC0_INTCTRL LITERAL1 +ADC0_INTFLAGS LITERAL1 +ADC0_DBGCTRL LITERAL1 +ADC0_TEMP LITERAL1 +ADC0_RES LITERAL1 +ADC0_RESL LITERAL1 +ADC0_RESH LITERAL1 +ADC0_WINLT LITERAL1 +ADC0_WINLTL LITERAL1 +ADC0_WINLTH LITERAL1 +ADC0_WINHT LITERAL1 +ADC0_WINHTL LITERAL1 +ADC0_WINHTH LITERAL1 +ADC0_CALIB LITERAL1 + +AC0_CTRLA LITERAL1 +AC0_MUXCTRLA LITERAL1 +AC0_DACREF LITERAL1 +AC0_INTCTRL LITERAL1 +AC0_STATUS LITERAL1 + +USART0_RXDATAL LITERAL1 +USART0_RXDATAH LITERAL1 +USART0_TXDATAL LITERAL1 +USART0_TXDATAH LITERAL1 +USART0_STATUS LITERAL1 +USART0_CTRLA LITERAL1 +USART0_CTRLB LITERAL1 +USART0_CTRLC LITERAL1 +USART0_BAUD LITERAL1 +USART0_BAUDL LITERAL1 +USART0_BAUDH LITERAL1 +USART0_CTRLD LITERAL1 +USART0_DBGCTRL LITERAL1 +USART0_EVCTRL LITERAL1 +USART0_TXPLCTRL LITERAL1 +USART0_RXPLCTRL LITERAL1 + +USART1_RXDATAL LITERAL1 +USART1_RXDATAH LITERAL1 +USART1_TXDATAL LITERAL1 +USART1_TXDATAH LITERAL1 +USART1_STATUS LITERAL1 +USART1_CTRLA LITERAL1 +USART1_CTRLB LITERAL1 +USART1_CTRLC LITERAL1 +USART1_BAUD LITERAL1 +USART1_BAUDL LITERAL1 +USART1_BAUDH LITERAL1 +USART1_CTRLD LITERAL1 +USART1_DBGCTRL LITERAL1 +USART1_EVCTRL LITERAL1 +USART1_TXPLCTRL LITERAL1 +USART1_RXPLCTRL LITERAL1 + +USART2_RXDATAL LITERAL1 +USART2_RXDATAH LITERAL1 +USART2_TXDATAL LITERAL1 +USART2_TXDATAH LITERAL1 +USART2_STATUS LITERAL1 +USART2_CTRLA LITERAL1 +USART2_CTRLB LITERAL1 +USART2_CTRLC LITERAL1 +USART2_BAUD LITERAL1 +USART2_BAUDL LITERAL1 +USART2_BAUDH LITERAL1 +USART2_CTRLD LITERAL1 +USART2_DBGCTRL LITERAL1 +USART2_EVCTRL LITERAL1 +USART2_TXPLCTRL LITERAL1 +USART2_RXPLCTRL LITERAL1 + +USART3_RXDATAL LITERAL1 +USART3_RXDATAH LITERAL1 +USART3_TXDATAL LITERAL1 +USART3_TXDATAH LITERAL1 +USART3_STATUS LITERAL1 +USART3_CTRLA LITERAL1 +USART3_CTRLB LITERAL1 +USART3_CTRLC LITERAL1 +USART3_BAUD LITERAL1 +USART3_BAUDL LITERAL1 +USART3_BAUDH LITERAL1 +USART3_CTRLD LITERAL1 +USART3_DBGCTRL LITERAL1 +USART3_EVCTRL LITERAL1 +USART3_TXPLCTRL LITERAL1 +USART3_RXPLCTRL LITERAL1 + +TWI0_CTRLA LITERAL1 +TWI0_DUALCTRL LITERAL1 +TWI0_DBGCTRL LITERAL1 +TWI0_MCTRLA LITERAL1 +TWI0_MCTRLB LITERAL1 +TWI0_MSTATUS LITERAL1 +TWI0_MBAUD LITERAL1 +TWI0_MADDR LITERAL1 +TWI0_MDATA LITERAL1 +TWI0_SCTRLA LITERAL1 +TWI0_SCTRLB LITERAL1 +TWI0_SSTATUS LITERAL1 +TWI0_SADDR LITERAL1 +TWI0_SDATA LITERAL1 +TWI0_SADDRMASK LITERAL1 + +SPI0_CTRLA LITERAL1 +SPI0_CTRLB LITERAL1 +SPI0_INTCTRL LITERAL1 +SPI0_INTFLAGS LITERAL1 +SPI0_DATA LITERAL1 + +TCA0_SINGLE_CTRLA LITERAL1 +TCA0_SINGLE_CTRLB LITERAL1 +TCA0_SINGLE_CTRLC LITERAL1 +TCA0_SINGLE_CTRLD LITERAL1 +TCA0_SINGLE_CTRLECLR LITERAL1 +TCA0_SINGLE_CTRLESET LITERAL1 +TCA0_SINGLE_CTRLFCLR LITERAL1 +TCA0_SINGLE_CTRLFSET LITERAL1 +TCA0_SINGLE_EVCTRL LITERAL1 +TCA0_SINGLE_INTCTRL LITERAL1 +TCA0_SINGLE_INTFLAGS LITERAL1 +TCA0_SINGLE_DBGCTRL LITERAL1 +TCA0_SINGLE_TEMP LITERAL1 +TCA0_SINGLE_CNT LITERAL1 +TCA0_SINGLE_PER LITERAL1 +TCA0_SINGLE_CMP0 LITERAL1 +TCA0_SINGLE_CMP1 LITERAL1 +TCA0_SINGLE_CMP2 LITERAL1 +TCA0_SINGLE_PERBUF LITERAL1 +TCA0_SINGLE_CMP0BUF LITERAL1 +TCA0_SINGLE_CMP1BUF LITERAL1 +TCA0_SINGLE_CMP2BUF LITERAL1 +TCA0_SPLIT_CTRLA LITERAL1 +TCA0_SPLIT_CTRLB LITERAL1 +TCA0_SPLIT_CTRLC LITERAL1 +TCA0_SPLIT_CTRLD LITERAL1 +TCA0_SPLIT_CTRLECLR LITERAL1 +TCA0_SPLIT_CTRLESET LITERAL1 +TCA0_SPLIT_INTCTRL LITERAL1 +TCA0_SPLIT_INTFLAGS LITERAL1 +TCA0_SPLIT_DBGCTRL LITERAL1 +TCA0_SPLIT_LCNT LITERAL1 +TCA0_SPLIT_HCNT LITERAL1 +TCA0_SPLIT_LPER LITERAL1 +TCA0_SPLIT_HPER LITERAL1 +TCA0_SPLIT_LCMP0 LITERAL1 +TCA0_SPLIT_HCMP0 LITERAL1 +TCA0_SPLIT_LCMP1 LITERAL1 +TCA0_SPLIT_HCMP1 LITERAL1 +TCA0_SPLIT_LCMP2 LITERAL1 +TCA0_SPLIT_HCMP2 LITERAL1 + +TCB0_CTRLA LITERAL1 +TCB0_CTRLB LITERAL1 +TCB0_EVCTRL LITERAL1 +TCB0_INTCTRL LITERAL1 +TCB0_INTFLAGS LITERAL1 +TCB0_STATUS LITERAL1 +TCB0_DBGCTRL LITERAL1 +TCB0_TEMP LITERAL1 +TCB0_CNT LITERAL1 +TCB0_CNTL LITERAL1 +TCB0_CNTH LITERAL1 +TCB0_CCMP LITERAL1 +TCB0_CCMPL LITERAL1 +TCB0_CCMPH LITERAL1 + +TCB1_CTRLA LITERAL1 +TCB1_CTRLB LITERAL1 +TCB1_EVCTRL LITERAL1 +TCB1_INTCTRL LITERAL1 +TCB1_INTFLAGS LITERAL1 +TCB1_STATUS LITERAL1 +TCB1_DBGCTRL LITERAL1 +TCB1_TEMP LITERAL1 +TCB1_CNT LITERAL1 +TCB1_CNTL LITERAL1 +TCB1_CNTH LITERAL1 +TCB1_CCMP LITERAL1 +TCB1_CCMPL LITERAL1 +TCB1_CCMPH LITERAL1 + +TCB2_CTRLA LITERAL1 +TCB2_CTRLB LITERAL1 +TCB2_EVCTRL LITERAL1 +TCB2_INTCTRL LITERAL1 +TCB2_INTFLAGS LITERAL1 +TCB2_STATUS LITERAL1 +TCB2_DBGCTRL LITERAL1 +TCB2_TEMP LITERAL1 +TCB2_CNT LITERAL1 +TCB2_CNTL LITERAL1 +TCB2_CNTH LITERAL1 +TCB2_CCMP LITERAL1 +TCB2_CCMPL LITERAL1 +TCB2_CCMPH LITERAL1 + +TCB3_CTRLA LITERAL1 +TCB3_CTRLB LITERAL1 +TCB3_EVCTRL LITERAL1 +TCB3_INTCTRL LITERAL1 +TCB3_INTFLAGS LITERAL1 +TCB3_STATUS LITERAL1 +TCB3_DBGCTRL LITERAL1 +TCB3_TEMP LITERAL1 +TCB3_CNT LITERAL1 +TCB3_CNTL LITERAL1 +TCB3_CNTH LITERAL1 +TCB3_CCMP LITERAL1 +TCB3_CCMPL LITERAL1 +TCB3_CCMPH LITERAL1 + +SYSCFG_REVID LITERAL1 +SYSCFG_EXTBRK LITERAL1 +SYSCFG_OCDM LITERAL1 +SYSCFG_OCDMS LITERAL1 + +NVMCTRL_CTRLA LITERAL1 +NVMCTRL_CTRLB LITERAL1 +NVMCTRL_STATUS LITERAL1 +NVMCTRL_INTCTRL LITERAL1 +NVMCTRL_INTFLAGS LITERAL1 +NVMCTRL_DATA LITERAL1 +NVMCTRL_DATAL LITERAL1 +NVMCTRL_DATAH LITERAL1 +NVMCTRL_ADDR LITERAL1 +NVMCTRL_ADDRL LITERAL1 +NVMCTRL_ADDRH LITERAL1 + +SIGROW_DEVICEID0 LITERAL1 +SIGROW_DEVICEID1 LITERAL1 +SIGROW_DEVICEID2 LITERAL1 +SIGROW_SERNUM0 LITERAL1 +SIGROW_SERNUM1 LITERAL1 +SIGROW_SERNUM2 LITERAL1 +SIGROW_SERNUM3 LITERAL1 +SIGROW_SERNUM4 LITERAL1 +SIGROW_SERNUM5 LITERAL1 +SIGROW_SERNUM6 LITERAL1 +SIGROW_SERNUM7 LITERAL1 +SIGROW_SERNUM8 LITERAL1 +SIGROW_SERNUM9 LITERAL1 +SIGROW_OSCCAL32K LITERAL1 +SIGROW_OSCCAL16M0 LITERAL1 +SIGROW_OSCCAL16M1 LITERAL1 +SIGROW_OSCCAL20M0 LITERAL1 +SIGROW_OSCCAL20M1 LITERAL1 +SIGROW_TEMPSENSE0 LITERAL1 +SIGROW_TEMPSENSE1 LITERAL1 +SIGROW_OSC16ERR3V LITERAL1 +SIGROW_OSC16ERR5V LITERAL1 +SIGROW_OSC20ERR3V LITERAL1 +SIGROW_OSC20ERR5V LITERAL1 +SIGROW_CHECKSUM1 LITERAL1 + +FUSE_WDTCFG LITERAL1 +FUSE_BODCFG LITERAL1 +FUSE_OSCCFG LITERAL1 +FUSE_SYSCFG0 LITERAL1 +FUSE_SYSCFG1 LITERAL1 +FUSE_APPEND LITERAL1 +FUSE_BOOTEND LITERAL1 + +LOCKBIT_LOCKBIT LITERAL1 + +USERROW_USERROW0 LITERAL1 +USERROW_USERROW1 LITERAL1 +USERROW_USERROW2 LITERAL1 +USERROW_USERROW3 LITERAL1 +USERROW_USERROW4 LITERAL1 +USERROW_USERROW5 LITERAL1 +USERROW_USERROW6 LITERAL1 +USERROW_USERROW7 LITERAL1 +USERROW_USERROW8 LITERAL1 +USERROW_USERROW9 LITERAL1 +USERROW_USERROW10 LITERAL1 +USERROW_USERROW11 LITERAL1 +USERROW_USERROW12 LITERAL1 +USERROW_USERROW13 LITERAL1 +USERROW_USERROW14 LITERAL1 +USERROW_USERROW15 LITERAL1 +USERROW_USERROW16 LITERAL1 +USERROW_USERROW17 LITERAL1 +USERROW_USERROW18 LITERAL1 +USERROW_USERROW19 LITERAL1 +USERROW_USERROW20 LITERAL1 +USERROW_USERROW21 LITERAL1 +USERROW_USERROW22 LITERAL1 +USERROW_USERROW23 LITERAL1 +USERROW_USERROW24 LITERAL1 +USERROW_USERROW25 LITERAL1 +USERROW_USERROW26 LITERAL1 +USERROW_USERROW27 LITERAL1 +USERROW_USERROW28 LITERAL1 +USERROW_USERROW29 LITERAL1 +USERROW_USERROW30 LITERAL1 +USERROW_USERROW31 LITERAL1 +USERROW_USERROW32 LITERAL1 +USERROW_USERROW33 LITERAL1 +USERROW_USERROW34 LITERAL1 +USERROW_USERROW35 LITERAL1 +USERROW_USERROW36 LITERAL1 +USERROW_USERROW37 LITERAL1 +USERROW_USERROW38 LITERAL1 +USERROW_USERROW39 LITERAL1 +USERROW_USERROW40 LITERAL1 +USERROW_USERROW41 LITERAL1 +USERROW_USERROW42 LITERAL1 +USERROW_USERROW43 LITERAL1 +USERROW_USERROW44 LITERAL1 +USERROW_USERROW45 LITERAL1 +USERROW_USERROW46 LITERAL1 +USERROW_USERROW47 LITERAL1 +USERROW_USERROW48 LITERAL1 +USERROW_USERROW49 LITERAL1 +USERROW_USERROW50 LITERAL1 +USERROW_USERROW51 LITERAL1 +USERROW_USERROW52 LITERAL1 +USERROW_USERROW53 LITERAL1 +USERROW_USERROW54 LITERAL1 +USERROW_USERROW55 LITERAL1 +USERROW_USERROW56 LITERAL1 +USERROW_USERROW57 LITERAL1 +USERROW_USERROW58 LITERAL1 +USERROW_USERROW59 LITERAL1 +USERROW_USERROW60 LITERAL1 +USERROW_USERROW61 LITERAL1 +USERROW_USERROW62 LITERAL1 +USERROW_USERROW63 LITERAL1 + + +AC_ENABLE_bm KEYWORD3 RESERVED_WORD +AC_ENABLE_bp KEYWORD3 RESERVED_WORD +AC_HYSMODE_gm KEYWORD3 RESERVED_WORD +AC_HYSMODE_gp KEYWORD3 RESERVED_WORD +AC_HYSMODE0_bm KEYWORD3 RESERVED_WORD +AC_HYSMODE0_bp KEYWORD3 RESERVED_WORD +AC_HYSMODE1_bm KEYWORD3 RESERVED_WORD +AC_HYSMODE1_bp KEYWORD3 RESERVED_WORD +AC_LPMODE_bm KEYWORD3 RESERVED_WORD +AC_LPMODE_bp KEYWORD3 RESERVED_WORD +AC_INTMODE_gm KEYWORD3 RESERVED_WORD +AC_INTMODE_gp KEYWORD3 RESERVED_WORD +AC_INTMODE0_bm KEYWORD3 RESERVED_WORD +AC_INTMODE0_bp KEYWORD3 RESERVED_WORD +AC_INTMODE1_bm KEYWORD3 RESERVED_WORD +AC_INTMODE1_bp KEYWORD3 RESERVED_WORD +AC_OUTEN_bm KEYWORD3 RESERVED_WORD +AC_OUTEN_bp KEYWORD3 RESERVED_WORD +AC_RUNSTDBY_bm KEYWORD3 RESERVED_WORD +AC_RUNSTDBY_bp KEYWORD3 RESERVED_WORD + +AC_MUXNEG_gm KEYWORD3 RESERVED_WORD +AC_MUXNEG_gp KEYWORD3 RESERVED_WORD +AC_MUXNEG0_bm KEYWORD3 RESERVED_WORD +AC_MUXNEG0_bp KEYWORD3 RESERVED_WORD +AC_MUXNEG1_bm KEYWORD3 RESERVED_WORD +AC_MUXNEG1_bp KEYWORD3 RESERVED_WORD +AC_MUXPOS_gm KEYWORD3 RESERVED_WORD +AC_MUXPOS_gp KEYWORD3 RESERVED_WORD +AC_MUXPOS0_bm KEYWORD3 RESERVED_WORD +AC_MUXPOS0_bp KEYWORD3 RESERVED_WORD +AC_MUXPOS1_bm KEYWORD3 RESERVED_WORD +AC_MUXPOS1_bp KEYWORD3 RESERVED_WORD +AC_INVERT_bm KEYWORD3 RESERVED_WORD +AC_INVERT_bp KEYWORD3 RESERVED_WORD + +AC_DATA_gm KEYWORD3 RESERVED_WORD +AC_DATA_gp KEYWORD3 RESERVED_WORD +AC_DATA0_bm KEYWORD3 RESERVED_WORD +AC_DATA0_bp KEYWORD3 RESERVED_WORD +AC_DATA1_bm KEYWORD3 RESERVED_WORD +AC_DATA1_bp KEYWORD3 RESERVED_WORD +AC_DATA2_bm KEYWORD3 RESERVED_WORD +AC_DATA2_bp KEYWORD3 RESERVED_WORD +AC_DATA3_bm KEYWORD3 RESERVED_WORD +AC_DATA3_bp KEYWORD3 RESERVED_WORD +AC_DATA4_bm KEYWORD3 RESERVED_WORD +AC_DATA4_bp KEYWORD3 RESERVED_WORD +AC_DATA5_bm KEYWORD3 RESERVED_WORD +AC_DATA5_bp KEYWORD3 RESERVED_WORD +AC_DATA6_bm KEYWORD3 RESERVED_WORD +AC_DATA6_bp KEYWORD3 RESERVED_WORD +AC_DATA7_bm KEYWORD3 RESERVED_WORD +AC_DATA7_bp KEYWORD3 RESERVED_WORD + +AC_CMP_bm KEYWORD3 RESERVED_WORD +AC_CMP_bp KEYWORD3 RESERVED_WORD + + +AC_STATE_bm KEYWORD3 RESERVED_WORD +AC_STATE_bp KEYWORD3 RESERVED_WORD + + +ADC_ENABLE_bm KEYWORD3 RESERVED_WORD +ADC_ENABLE_bp KEYWORD3 RESERVED_WORD +ADC_FREERUN_bm KEYWORD3 RESERVED_WORD +ADC_FREERUN_bp KEYWORD3 RESERVED_WORD +ADC_RESSEL_bm KEYWORD3 RESERVED_WORD +ADC_RESSEL_bp KEYWORD3 RESERVED_WORD +ADC_RUNSTBY_bm KEYWORD3 RESERVED_WORD +ADC_RUNSTBY_bp KEYWORD3 RESERVED_WORD + +ADC_SAMPNUM_gm KEYWORD3 RESERVED_WORD +ADC_SAMPNUM_gp KEYWORD3 RESERVED_WORD +ADC_SAMPNUM0_bm KEYWORD3 RESERVED_WORD +ADC_SAMPNUM0_bp KEYWORD3 RESERVED_WORD +ADC_SAMPNUM1_bm KEYWORD3 RESERVED_WORD +ADC_SAMPNUM1_bp KEYWORD3 RESERVED_WORD +ADC_SAMPNUM2_bm KEYWORD3 RESERVED_WORD +ADC_SAMPNUM2_bp KEYWORD3 RESERVED_WORD + +ADC_PRESC_gm KEYWORD3 RESERVED_WORD +ADC_PRESC_gp KEYWORD3 RESERVED_WORD +ADC_PRESC0_bm KEYWORD3 RESERVED_WORD +ADC_PRESC0_bp KEYWORD3 RESERVED_WORD +ADC_PRESC1_bm KEYWORD3 RESERVED_WORD +ADC_PRESC1_bp KEYWORD3 RESERVED_WORD +ADC_PRESC2_bm KEYWORD3 RESERVED_WORD +ADC_PRESC2_bp KEYWORD3 RESERVED_WORD +ADC_REFSEL_gm KEYWORD3 RESERVED_WORD +ADC_REFSEL_gp KEYWORD3 RESERVED_WORD +ADC_REFSEL0_bm KEYWORD3 RESERVED_WORD +ADC_REFSEL0_bp KEYWORD3 RESERVED_WORD +ADC_REFSEL1_bm KEYWORD3 RESERVED_WORD +ADC_REFSEL1_bp KEYWORD3 RESERVED_WORD +ADC_SAMPCAP_bm KEYWORD3 RESERVED_WORD +ADC_SAMPCAP_bp KEYWORD3 RESERVED_WORD + +ADC_SAMPDLY_gm KEYWORD3 RESERVED_WORD +ADC_SAMPDLY_gp KEYWORD3 RESERVED_WORD +ADC_SAMPDLY0_bm KEYWORD3 RESERVED_WORD +ADC_SAMPDLY0_bp KEYWORD3 RESERVED_WORD +ADC_SAMPDLY1_bm KEYWORD3 RESERVED_WORD +ADC_SAMPDLY1_bp KEYWORD3 RESERVED_WORD +ADC_SAMPDLY2_bm KEYWORD3 RESERVED_WORD +ADC_SAMPDLY2_bp KEYWORD3 RESERVED_WORD +ADC_SAMPDLY3_bm KEYWORD3 RESERVED_WORD +ADC_SAMPDLY3_bp KEYWORD3 RESERVED_WORD +ADC_ASDV_bm KEYWORD3 RESERVED_WORD +ADC_ASDV_bp KEYWORD3 RESERVED_WORD +ADC_INITDLY_gm KEYWORD3 RESERVED_WORD +ADC_INITDLY_gp KEYWORD3 RESERVED_WORD +ADC_INITDLY0_bm KEYWORD3 RESERVED_WORD +ADC_INITDLY0_bp KEYWORD3 RESERVED_WORD +ADC_INITDLY1_bm KEYWORD3 RESERVED_WORD +ADC_INITDLY1_bp KEYWORD3 RESERVED_WORD +ADC_INITDLY2_bm KEYWORD3 RESERVED_WORD +ADC_INITDLY2_bp KEYWORD3 RESERVED_WORD + +ADC_WINCM_gm KEYWORD3 RESERVED_WORD +ADC_WINCM_gp KEYWORD3 RESERVED_WORD +ADC_WINCM0_bm KEYWORD3 RESERVED_WORD +ADC_WINCM0_bp KEYWORD3 RESERVED_WORD +ADC_WINCM1_bm KEYWORD3 RESERVED_WORD +ADC_WINCM1_bp KEYWORD3 RESERVED_WORD +ADC_WINCM2_bm KEYWORD3 RESERVED_WORD +ADC_WINCM2_bp KEYWORD3 RESERVED_WORD + +ADC_SAMPLEN_gm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN_gp KEYWORD3 RESERVED_WORD +ADC_SAMPLEN0_bm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN0_bp KEYWORD3 RESERVED_WORD +ADC_SAMPLEN1_bm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN1_bp KEYWORD3 RESERVED_WORD +ADC_SAMPLEN2_bm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN2_bp KEYWORD3 RESERVED_WORD +ADC_SAMPLEN3_bm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN3_bp KEYWORD3 RESERVED_WORD +ADC_SAMPLEN4_bm KEYWORD3 RESERVED_WORD +ADC_SAMPLEN4_bp KEYWORD3 RESERVED_WORD + +ADC_MUXPOS_gm KEYWORD3 RESERVED_WORD +ADC_MUXPOS_gp KEYWORD3 RESERVED_WORD +ADC_MUXPOS0_bm KEYWORD3 RESERVED_WORD +ADC_MUXPOS0_bp KEYWORD3 RESERVED_WORD +ADC_MUXPOS1_bm KEYWORD3 RESERVED_WORD +ADC_MUXPOS1_bp KEYWORD3 RESERVED_WORD +ADC_MUXPOS2_bm KEYWORD3 RESERVED_WORD +ADC_MUXPOS2_bp KEYWORD3 RESERVED_WORD +ADC_MUXPOS3_bm KEYWORD3 RESERVED_WORD +ADC_MUXPOS3_bp KEYWORD3 RESERVED_WORD +ADC_MUXPOS4_bm KEYWORD3 RESERVED_WORD +ADC_MUXPOS4_bp KEYWORD3 RESERVED_WORD + +ADC_STCONV_bm KEYWORD3 RESERVED_WORD +ADC_STCONV_bp KEYWORD3 RESERVED_WORD + +ADC_STARTEI_bm KEYWORD3 RESERVED_WORD +ADC_STARTEI_bp KEYWORD3 RESERVED_WORD + +ADC_RESRDY_bm KEYWORD3 RESERVED_WORD +ADC_RESRDY_bp KEYWORD3 RESERVED_WORD +ADC_WCMP_bm KEYWORD3 RESERVED_WORD +ADC_WCMP_bp KEYWORD3 RESERVED_WORD + + + + +ADC_DBGRUN_bm KEYWORD3 RESERVED_WORD +ADC_DBGRUN_bp KEYWORD3 RESERVED_WORD + +ADC_TEMP_gm KEYWORD3 RESERVED_WORD +ADC_TEMP_gp KEYWORD3 RESERVED_WORD +ADC_TEMP0_bm KEYWORD3 RESERVED_WORD +ADC_TEMP0_bp KEYWORD3 RESERVED_WORD +ADC_TEMP1_bm KEYWORD3 RESERVED_WORD +ADC_TEMP1_bp KEYWORD3 RESERVED_WORD +ADC_TEMP2_bm KEYWORD3 RESERVED_WORD +ADC_TEMP2_bp KEYWORD3 RESERVED_WORD +ADC_TEMP3_bm KEYWORD3 RESERVED_WORD +ADC_TEMP3_bp KEYWORD3 RESERVED_WORD +ADC_TEMP4_bm KEYWORD3 RESERVED_WORD +ADC_TEMP4_bp KEYWORD3 RESERVED_WORD +ADC_TEMP5_bm KEYWORD3 RESERVED_WORD +ADC_TEMP5_bp KEYWORD3 RESERVED_WORD +ADC_TEMP6_bm KEYWORD3 RESERVED_WORD +ADC_TEMP6_bp KEYWORD3 RESERVED_WORD +ADC_TEMP7_bm KEYWORD3 RESERVED_WORD +ADC_TEMP7_bp KEYWORD3 RESERVED_WORD + +ADC_DUTYCYC_bm KEYWORD3 RESERVED_WORD +ADC_DUTYCYC_bp KEYWORD3 RESERVED_WORD + + +BOD_SLEEP_gm KEYWORD3 RESERVED_WORD +BOD_SLEEP_gp KEYWORD3 RESERVED_WORD +BOD_SLEEP0_bm KEYWORD3 RESERVED_WORD +BOD_SLEEP0_bp KEYWORD3 RESERVED_WORD +BOD_SLEEP1_bm KEYWORD3 RESERVED_WORD +BOD_SLEEP1_bp KEYWORD3 RESERVED_WORD +BOD_ACTIVE_gm KEYWORD3 RESERVED_WORD +BOD_ACTIVE_gp KEYWORD3 RESERVED_WORD +BOD_ACTIVE0_bm KEYWORD3 RESERVED_WORD +BOD_ACTIVE0_bp KEYWORD3 RESERVED_WORD +BOD_ACTIVE1_bm KEYWORD3 RESERVED_WORD +BOD_ACTIVE1_bp KEYWORD3 RESERVED_WORD +BOD_SAMPFREQ_bm KEYWORD3 RESERVED_WORD +BOD_SAMPFREQ_bp KEYWORD3 RESERVED_WORD + +BOD_LVL_gm KEYWORD3 RESERVED_WORD +BOD_LVL_gp KEYWORD3 RESERVED_WORD +BOD_LVL0_bm KEYWORD3 RESERVED_WORD +BOD_LVL0_bp KEYWORD3 RESERVED_WORD +BOD_LVL1_bm KEYWORD3 RESERVED_WORD +BOD_LVL1_bp KEYWORD3 RESERVED_WORD +BOD_LVL2_bm KEYWORD3 RESERVED_WORD +BOD_LVL2_bp KEYWORD3 RESERVED_WORD + +BOD_VLMLVL_gm KEYWORD3 RESERVED_WORD +BOD_VLMLVL_gp KEYWORD3 RESERVED_WORD +BOD_VLMLVL0_bm KEYWORD3 RESERVED_WORD +BOD_VLMLVL0_bp KEYWORD3 RESERVED_WORD +BOD_VLMLVL1_bm KEYWORD3 RESERVED_WORD +BOD_VLMLVL1_bp KEYWORD3 RESERVED_WORD + +BOD_VLMIE_bm KEYWORD3 RESERVED_WORD +BOD_VLMIE_bp KEYWORD3 RESERVED_WORD +BOD_VLMCFG_gm KEYWORD3 RESERVED_WORD +BOD_VLMCFG_gp KEYWORD3 RESERVED_WORD +BOD_VLMCFG0_bm KEYWORD3 RESERVED_WORD +BOD_VLMCFG0_bp KEYWORD3 RESERVED_WORD +BOD_VLMCFG1_bm KEYWORD3 RESERVED_WORD +BOD_VLMCFG1_bp KEYWORD3 RESERVED_WORD + +BOD_VLMIF_bm KEYWORD3 RESERVED_WORD +BOD_VLMIF_bp KEYWORD3 RESERVED_WORD + +BOD_VLMS_bm KEYWORD3 RESERVED_WORD +BOD_VLMS_bp KEYWORD3 RESERVED_WORD + + +CCL_ENABLE_bm KEYWORD3 RESERVED_WORD +CCL_ENABLE_bp KEYWORD3 RESERVED_WORD +CCL_RUNSTDBY_bm KEYWORD3 RESERVED_WORD +CCL_RUNSTDBY_bp KEYWORD3 RESERVED_WORD + +CCL_SEQSEL0_gm KEYWORD3 RESERVED_WORD +CCL_SEQSEL0_gp KEYWORD3 RESERVED_WORD +CCL_SEQSEL00_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL00_bp KEYWORD3 RESERVED_WORD +CCL_SEQSEL01_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL01_bp KEYWORD3 RESERVED_WORD +CCL_SEQSEL02_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL02_bp KEYWORD3 RESERVED_WORD + +CCL_SEQSEL1_gm KEYWORD3 RESERVED_WORD +CCL_SEQSEL1_gp KEYWORD3 RESERVED_WORD +CCL_SEQSEL10_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL10_bp KEYWORD3 RESERVED_WORD +CCL_SEQSEL11_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL11_bp KEYWORD3 RESERVED_WORD +CCL_SEQSEL12_bm KEYWORD3 RESERVED_WORD +CCL_SEQSEL12_bp KEYWORD3 RESERVED_WORD + +CCL_INTMODE0_gm KEYWORD3 RESERVED_WORD +CCL_INTMODE0_gp KEYWORD3 RESERVED_WORD +CCL_INTMODE00_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE00_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE01_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE01_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE1_gm KEYWORD3 RESERVED_WORD +CCL_INTMODE1_gp KEYWORD3 RESERVED_WORD +CCL_INTMODE10_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE10_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE11_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE11_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE2_gm KEYWORD3 RESERVED_WORD +CCL_INTMODE2_gp KEYWORD3 RESERVED_WORD +CCL_INTMODE20_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE20_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE21_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE21_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE3_gm KEYWORD3 RESERVED_WORD +CCL_INTMODE3_gp KEYWORD3 RESERVED_WORD +CCL_INTMODE30_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE30_bp KEYWORD3 RESERVED_WORD +CCL_INTMODE31_bm KEYWORD3 RESERVED_WORD +CCL_INTMODE31_bp KEYWORD3 RESERVED_WORD + +CCL_INT_gm KEYWORD3 RESERVED_WORD +CCL_INT_gp KEYWORD3 RESERVED_WORD +CCL_INT0_bm KEYWORD3 RESERVED_WORD +CCL_INT0_bp KEYWORD3 RESERVED_WORD +CCL_INT1_bm KEYWORD3 RESERVED_WORD +CCL_INT1_bp KEYWORD3 RESERVED_WORD +CCL_INT2_bm KEYWORD3 RESERVED_WORD +CCL_INT2_bp KEYWORD3 RESERVED_WORD +CCL_INT3_bm KEYWORD3 RESERVED_WORD +CCL_INT3_bp KEYWORD3 RESERVED_WORD + + +CCL_CLKSRC_gm KEYWORD3 RESERVED_WORD +CCL_CLKSRC_gp KEYWORD3 RESERVED_WORD +CCL_CLKSRC0_bm KEYWORD3 RESERVED_WORD +CCL_CLKSRC0_bp KEYWORD3 RESERVED_WORD +CCL_CLKSRC1_bm KEYWORD3 RESERVED_WORD +CCL_CLKSRC1_bp KEYWORD3 RESERVED_WORD +CCL_CLKSRC2_bm KEYWORD3 RESERVED_WORD +CCL_CLKSRC2_bp KEYWORD3 RESERVED_WORD +CCL_FILTSEL_gm KEYWORD3 RESERVED_WORD +CCL_FILTSEL_gp KEYWORD3 RESERVED_WORD +CCL_FILTSEL0_bm KEYWORD3 RESERVED_WORD +CCL_FILTSEL0_bp KEYWORD3 RESERVED_WORD +CCL_FILTSEL1_bm KEYWORD3 RESERVED_WORD +CCL_FILTSEL1_bp KEYWORD3 RESERVED_WORD +CCL_OUTEN_bm KEYWORD3 RESERVED_WORD +CCL_OUTEN_bp KEYWORD3 RESERVED_WORD +CCL_EDGEDET_bm KEYWORD3 RESERVED_WORD +CCL_EDGEDET_bp KEYWORD3 RESERVED_WORD + +CCL_INSEL0_gm KEYWORD3 RESERVED_WORD +CCL_INSEL0_gp KEYWORD3 RESERVED_WORD +CCL_INSEL00_bm KEYWORD3 RESERVED_WORD +CCL_INSEL00_bp KEYWORD3 RESERVED_WORD +CCL_INSEL01_bm KEYWORD3 RESERVED_WORD +CCL_INSEL01_bp KEYWORD3 RESERVED_WORD +CCL_INSEL02_bm KEYWORD3 RESERVED_WORD +CCL_INSEL02_bp KEYWORD3 RESERVED_WORD +CCL_INSEL03_bm KEYWORD3 RESERVED_WORD +CCL_INSEL03_bp KEYWORD3 RESERVED_WORD +CCL_INSEL1_gm KEYWORD3 RESERVED_WORD +CCL_INSEL1_gp KEYWORD3 RESERVED_WORD +CCL_INSEL10_bm KEYWORD3 RESERVED_WORD +CCL_INSEL10_bp KEYWORD3 RESERVED_WORD +CCL_INSEL11_bm KEYWORD3 RESERVED_WORD +CCL_INSEL11_bp KEYWORD3 RESERVED_WORD +CCL_INSEL12_bm KEYWORD3 RESERVED_WORD +CCL_INSEL12_bp KEYWORD3 RESERVED_WORD +CCL_INSEL13_bm KEYWORD3 RESERVED_WORD +CCL_INSEL13_bp KEYWORD3 RESERVED_WORD + +CCL_INSEL2_gm KEYWORD3 RESERVED_WORD +CCL_INSEL2_gp KEYWORD3 RESERVED_WORD +CCL_INSEL20_bm KEYWORD3 RESERVED_WORD +CCL_INSEL20_bp KEYWORD3 RESERVED_WORD +CCL_INSEL21_bm KEYWORD3 RESERVED_WORD +CCL_INSEL21_bp KEYWORD3 RESERVED_WORD +CCL_INSEL22_bm KEYWORD3 RESERVED_WORD +CCL_INSEL22_bp KEYWORD3 RESERVED_WORD +CCL_INSEL23_bm KEYWORD3 RESERVED_WORD +CCL_INSEL23_bp KEYWORD3 RESERVED_WORD + + +CLKCTRL_CLKSEL_gm KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL_gp KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL0_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL0_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL1_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CLKSEL1_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CLKOUT_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CLKOUT_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_PEN_bm KEYWORD3 RESERVED_WORD +CLKCTRL_PEN_bp KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_gm KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV_gp KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV0_bm KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV0_bp KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV1_bm KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV1_bp KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV2_bm KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV2_bp KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV3_bm KEYWORD3 RESERVED_WORD +CLKCTRL_PDIV3_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_LOCKEN_bm KEYWORD3 RESERVED_WORD +CLKCTRL_LOCKEN_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_SOSC_bm KEYWORD3 RESERVED_WORD +CLKCTRL_SOSC_bp KEYWORD3 RESERVED_WORD +CLKCTRL_OSC20MS_bm KEYWORD3 RESERVED_WORD +CLKCTRL_OSC20MS_bp KEYWORD3 RESERVED_WORD +CLKCTRL_OSC32KS_bm KEYWORD3 RESERVED_WORD +CLKCTRL_OSC32KS_bp KEYWORD3 RESERVED_WORD +CLKCTRL_XOSC32KS_bm KEYWORD3 RESERVED_WORD +CLKCTRL_XOSC32KS_bp KEYWORD3 RESERVED_WORD +CLKCTRL_EXTS_bm KEYWORD3 RESERVED_WORD +CLKCTRL_EXTS_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_RUNSTDBY_bm KEYWORD3 RESERVED_WORD +CLKCTRL_RUNSTDBY_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_CAL20M_gm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M_gp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M0_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M0_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M1_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M1_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M2_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M2_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M3_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M3_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M4_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M4_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M5_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M5_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M6_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CAL20M6_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_TEMPCAL20M_gm KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M_gp KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M0_bm KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M0_bp KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M1_bm KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M1_bp KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M2_bm KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M2_bp KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M3_bm KEYWORD3 RESERVED_WORD +CLKCTRL_TEMPCAL20M3_bp KEYWORD3 RESERVED_WORD +CLKCTRL_LOCK_bm KEYWORD3 RESERVED_WORD +CLKCTRL_LOCK_bp KEYWORD3 RESERVED_WORD + + + +CLKCTRL_ENABLE_bm KEYWORD3 RESERVED_WORD +CLKCTRL_ENABLE_bp KEYWORD3 RESERVED_WORD + +CLKCTRL_SEL_bm KEYWORD3 RESERVED_WORD +CLKCTRL_SEL_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_gm KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT_gp KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT0_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT0_bp KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT1_bm KEYWORD3 RESERVED_WORD +CLKCTRL_CSUT1_bp KEYWORD3 RESERVED_WORD + + +CPU_CCP_gm KEYWORD3 RESERVED_WORD +CPU_CCP_gp KEYWORD3 RESERVED_WORD +CPU_CCP0_bm KEYWORD3 RESERVED_WORD +CPU_CCP0_bp KEYWORD3 RESERVED_WORD +CPU_CCP1_bm KEYWORD3 RESERVED_WORD +CPU_CCP1_bp KEYWORD3 RESERVED_WORD +CPU_CCP2_bm KEYWORD3 RESERVED_WORD +CPU_CCP2_bp KEYWORD3 RESERVED_WORD +CPU_CCP3_bm KEYWORD3 RESERVED_WORD +CPU_CCP3_bp KEYWORD3 RESERVED_WORD +CPU_CCP4_bm KEYWORD3 RESERVED_WORD +CPU_CCP4_bp KEYWORD3 RESERVED_WORD +CPU_CCP5_bm KEYWORD3 RESERVED_WORD +CPU_CCP5_bp KEYWORD3 RESERVED_WORD +CPU_CCP6_bm KEYWORD3 RESERVED_WORD +CPU_CCP6_bp KEYWORD3 RESERVED_WORD +CPU_CCP7_bm KEYWORD3 RESERVED_WORD +CPU_CCP7_bp KEYWORD3 RESERVED_WORD + +CPU_C_bm KEYWORD3 RESERVED_WORD +CPU_C_bp KEYWORD3 RESERVED_WORD +CPU_Z_bm KEYWORD3 RESERVED_WORD +CPU_Z_bp KEYWORD3 RESERVED_WORD +CPU_N_bm KEYWORD3 RESERVED_WORD +CPU_N_bp KEYWORD3 RESERVED_WORD +CPU_V_bm KEYWORD3 RESERVED_WORD +CPU_V_bp KEYWORD3 RESERVED_WORD +CPU_S_bm KEYWORD3 RESERVED_WORD +CPU_S_bp KEYWORD3 RESERVED_WORD +CPU_H_bm KEYWORD3 RESERVED_WORD +CPU_H_bp KEYWORD3 RESERVED_WORD +CPU_T_bm KEYWORD3 RESERVED_WORD +CPU_T_bp KEYWORD3 RESERVED_WORD +CPU_I_bm KEYWORD3 RESERVED_WORD +CPU_I_bp KEYWORD3 RESERVED_WORD + + +CPUINT_LVL0RR_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0RR_bp KEYWORD3 RESERVED_WORD +CPUINT_CVT_bm KEYWORD3 RESERVED_WORD +CPUINT_CVT_bp KEYWORD3 RESERVED_WORD +CPUINT_IVSEL_bm KEYWORD3 RESERVED_WORD +CPUINT_IVSEL_bp KEYWORD3 RESERVED_WORD + +CPUINT_LVL0EX_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0EX_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1EX_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1EX_bp KEYWORD3 RESERVED_WORD +CPUINT_NMIEX_bm KEYWORD3 RESERVED_WORD +CPUINT_NMIEX_bp KEYWORD3 RESERVED_WORD + +CPUINT_LVL0PRI_gm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI_gp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI0_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI0_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI1_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI1_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI2_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI2_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI3_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI3_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI4_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI4_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI5_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI5_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI6_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI6_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI7_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL0PRI7_bp KEYWORD3 RESERVED_WORD + +CPUINT_LVL1VEC_gm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC_gp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC0_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC0_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC1_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC1_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC2_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC2_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC3_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC3_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC4_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC4_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC5_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC5_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC6_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC6_bp KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC7_bm KEYWORD3 RESERVED_WORD +CPUINT_LVL1VEC7_bp KEYWORD3 RESERVED_WORD + + +CRCSCAN_ENABLE_bm KEYWORD3 RESERVED_WORD +CRCSCAN_ENABLE_bp KEYWORD3 RESERVED_WORD +CRCSCAN_NMIEN_bm KEYWORD3 RESERVED_WORD +CRCSCAN_NMIEN_bp KEYWORD3 RESERVED_WORD +CRCSCAN_RESET_bm KEYWORD3 RESERVED_WORD +CRCSCAN_RESET_bp KEYWORD3 RESERVED_WORD + +CRCSCAN_SRC_gm KEYWORD3 RESERVED_WORD +CRCSCAN_SRC_gp KEYWORD3 RESERVED_WORD +CRCSCAN_SRC0_bm KEYWORD3 RESERVED_WORD +CRCSCAN_SRC0_bp KEYWORD3 RESERVED_WORD +CRCSCAN_SRC1_bm KEYWORD3 RESERVED_WORD +CRCSCAN_SRC1_bp KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_gm KEYWORD3 RESERVED_WORD +CRCSCAN_MODE_gp KEYWORD3 RESERVED_WORD +CRCSCAN_MODE0_bm KEYWORD3 RESERVED_WORD +CRCSCAN_MODE0_bp KEYWORD3 RESERVED_WORD +CRCSCAN_MODE1_bm KEYWORD3 RESERVED_WORD +CRCSCAN_MODE1_bp KEYWORD3 RESERVED_WORD + +CRCSCAN_BUSY_bm KEYWORD3 RESERVED_WORD +CRCSCAN_BUSY_bp KEYWORD3 RESERVED_WORD +CRCSCAN_OK_bm KEYWORD3 RESERVED_WORD +CRCSCAN_OK_bp KEYWORD3 RESERVED_WORD + + +EVSYS_STROBE0_gm KEYWORD3 RESERVED_WORD +EVSYS_STROBE0_gp KEYWORD3 RESERVED_WORD +EVSYS_STROBE00_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE00_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE01_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE01_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE02_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE02_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE03_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE03_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE04_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE04_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE05_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE05_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE06_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE06_bp KEYWORD3 RESERVED_WORD +EVSYS_STROBE07_bm KEYWORD3 RESERVED_WORD +EVSYS_STROBE07_bp KEYWORD3 RESERVED_WORD + +EVSYS_GENERATOR_gm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR_gp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR0_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR0_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR1_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR1_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR2_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR2_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR3_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR3_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR4_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR4_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR5_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR5_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR6_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR6_bp KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR7_bm KEYWORD3 RESERVED_WORD +EVSYS_GENERATOR7_bp KEYWORD3 RESERVED_WORD + + +EVSYS_CHANNEL_gm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL_gp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL0_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL0_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL1_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL1_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL2_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL2_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL3_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL3_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL4_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL4_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL5_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL5_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL6_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL6_bp KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL7_bm KEYWORD3 RESERVED_WORD +EVSYS_CHANNEL7_bp KEYWORD3 RESERVED_WORD + + +FUSE_PERIOD_gm KEYWORD3 RESERVED_WORD +FUSE_PERIOD_gp KEYWORD3 RESERVED_WORD +FUSE_PERIOD0_bm KEYWORD3 RESERVED_WORD +FUSE_PERIOD0_bp KEYWORD3 RESERVED_WORD +FUSE_PERIOD1_bm KEYWORD3 RESERVED_WORD +FUSE_PERIOD1_bp KEYWORD3 RESERVED_WORD +FUSE_PERIOD2_bm KEYWORD3 RESERVED_WORD +FUSE_PERIOD2_bp KEYWORD3 RESERVED_WORD +FUSE_PERIOD3_bm KEYWORD3 RESERVED_WORD +FUSE_PERIOD3_bp KEYWORD3 RESERVED_WORD +FUSE_WINDOW_gm KEYWORD3 RESERVED_WORD +FUSE_WINDOW_gp KEYWORD3 RESERVED_WORD +FUSE_WINDOW0_bm KEYWORD3 RESERVED_WORD +FUSE_WINDOW0_bp KEYWORD3 RESERVED_WORD +FUSE_WINDOW1_bm KEYWORD3 RESERVED_WORD +FUSE_WINDOW1_bp KEYWORD3 RESERVED_WORD +FUSE_WINDOW2_bm KEYWORD3 RESERVED_WORD +FUSE_WINDOW2_bp KEYWORD3 RESERVED_WORD +FUSE_WINDOW3_bm KEYWORD3 RESERVED_WORD +FUSE_WINDOW3_bp KEYWORD3 RESERVED_WORD + +FUSE_SLEEP_gm KEYWORD3 RESERVED_WORD +FUSE_SLEEP_gp KEYWORD3 RESERVED_WORD +FUSE_SLEEP0_bm KEYWORD3 RESERVED_WORD +FUSE_SLEEP0_bp KEYWORD3 RESERVED_WORD +FUSE_SLEEP1_bm KEYWORD3 RESERVED_WORD +FUSE_SLEEP1_bp KEYWORD3 RESERVED_WORD +FUSE_ACTIVE_gm KEYWORD3 RESERVED_WORD +FUSE_ACTIVE_gp KEYWORD3 RESERVED_WORD +FUSE_ACTIVE0_bm KEYWORD3 RESERVED_WORD +FUSE_ACTIVE0_bp KEYWORD3 RESERVED_WORD +FUSE_ACTIVE1_bm KEYWORD3 RESERVED_WORD +FUSE_ACTIVE1_bp KEYWORD3 RESERVED_WORD +FUSE_SAMPFREQ_bm KEYWORD3 RESERVED_WORD +FUSE_SAMPFREQ_bp KEYWORD3 RESERVED_WORD +FUSE_LVL_gm KEYWORD3 RESERVED_WORD +FUSE_LVL_gp KEYWORD3 RESERVED_WORD +FUSE_LVL0_bm KEYWORD3 RESERVED_WORD +FUSE_LVL0_bp KEYWORD3 RESERVED_WORD +FUSE_LVL1_bm KEYWORD3 RESERVED_WORD +FUSE_LVL1_bp KEYWORD3 RESERVED_WORD +FUSE_LVL2_bm KEYWORD3 RESERVED_WORD +FUSE_LVL2_bp KEYWORD3 RESERVED_WORD + +FUSE_FREQSEL_gm KEYWORD3 RESERVED_WORD +FUSE_FREQSEL_gp KEYWORD3 RESERVED_WORD +FUSE_FREQSEL0_bm KEYWORD3 RESERVED_WORD +FUSE_FREQSEL0_bp KEYWORD3 RESERVED_WORD +FUSE_FREQSEL1_bm KEYWORD3 RESERVED_WORD +FUSE_FREQSEL1_bp KEYWORD3 RESERVED_WORD +FUSE_OSCLOCK_bm KEYWORD3 RESERVED_WORD +FUSE_OSCLOCK_bp KEYWORD3 RESERVED_WORD + +FUSE_EESAVE_bm KEYWORD3 RESERVED_WORD +FUSE_EESAVE_bp KEYWORD3 RESERVED_WORD +FUSE_RSTPINCFG_bm KEYWORD3 RESERVED_WORD +FUSE_RSTPINCFG_bp KEYWORD3 RESERVED_WORD +FUSE_CRCSRC_gm KEYWORD3 RESERVED_WORD +FUSE_CRCSRC_gp KEYWORD3 RESERVED_WORD +FUSE_CRCSRC0_bm KEYWORD3 RESERVED_WORD +FUSE_CRCSRC0_bp KEYWORD3 RESERVED_WORD +FUSE_CRCSRC1_bm KEYWORD3 RESERVED_WORD +FUSE_CRCSRC1_bp KEYWORD3 RESERVED_WORD + +FUSE_SUT_gm KEYWORD3 RESERVED_WORD +FUSE_SUT_gp KEYWORD3 RESERVED_WORD +FUSE_SUT0_bm KEYWORD3 RESERVED_WORD +FUSE_SUT0_bp KEYWORD3 RESERVED_WORD +FUSE_SUT1_bm KEYWORD3 RESERVED_WORD +FUSE_SUT1_bp KEYWORD3 RESERVED_WORD +FUSE_SUT2_bm KEYWORD3 RESERVED_WORD +FUSE_SUT2_bp KEYWORD3 RESERVED_WORD + + +LOCKBIT_LB_gm KEYWORD3 RESERVED_WORD +LOCKBIT_LB_gp KEYWORD3 RESERVED_WORD +LOCKBIT_LB0_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB0_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB1_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB1_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB2_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB2_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB3_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB3_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB4_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB4_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB5_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB5_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB6_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB6_bp KEYWORD3 RESERVED_WORD +LOCKBIT_LB7_bm KEYWORD3 RESERVED_WORD +LOCKBIT_LB7_bp KEYWORD3 RESERVED_WORD + + +NVMCTRL_CMD_gm KEYWORD3 RESERVED_WORD +NVMCTRL_CMD_gp KEYWORD3 RESERVED_WORD +NVMCTRL_CMD0_bm KEYWORD3 RESERVED_WORD +NVMCTRL_CMD0_bp KEYWORD3 RESERVED_WORD +NVMCTRL_CMD1_bm KEYWORD3 RESERVED_WORD +NVMCTRL_CMD1_bp KEYWORD3 RESERVED_WORD +NVMCTRL_CMD2_bm KEYWORD3 RESERVED_WORD +NVMCTRL_CMD2_bp KEYWORD3 RESERVED_WORD + +NVMCTRL_APCWP_bm KEYWORD3 RESERVED_WORD +NVMCTRL_APCWP_bp KEYWORD3 RESERVED_WORD +NVMCTRL_BOOTLOCK_bm KEYWORD3 RESERVED_WORD +NVMCTRL_BOOTLOCK_bp KEYWORD3 RESERVED_WORD + +NVMCTRL_FBUSY_bm KEYWORD3 RESERVED_WORD +NVMCTRL_FBUSY_bp KEYWORD3 RESERVED_WORD +NVMCTRL_EEBUSY_bm KEYWORD3 RESERVED_WORD +NVMCTRL_EEBUSY_bp KEYWORD3 RESERVED_WORD +NVMCTRL_WRERROR_bm KEYWORD3 RESERVED_WORD +NVMCTRL_WRERROR_bp KEYWORD3 RESERVED_WORD + +NVMCTRL_EEREADY_bm KEYWORD3 RESERVED_WORD +NVMCTRL_EEREADY_bp KEYWORD3 RESERVED_WORD + +PORT_INT_gm KEYWORD3 RESERVED_WORD +PORT_INT_gp KEYWORD3 RESERVED_WORD +PORT_INT0_bm KEYWORD3 RESERVED_WORD +PORT_INT0_bp KEYWORD3 RESERVED_WORD +PORT_INT1_bm KEYWORD3 RESERVED_WORD +PORT_INT1_bp KEYWORD3 RESERVED_WORD +PORT_INT2_bm KEYWORD3 RESERVED_WORD +PORT_INT2_bp KEYWORD3 RESERVED_WORD +PORT_INT3_bm KEYWORD3 RESERVED_WORD +PORT_INT3_bp KEYWORD3 RESERVED_WORD +PORT_INT4_bm KEYWORD3 RESERVED_WORD +PORT_INT4_bp KEYWORD3 RESERVED_WORD +PORT_INT5_bm KEYWORD3 RESERVED_WORD +PORT_INT5_bp KEYWORD3 RESERVED_WORD +PORT_INT6_bm KEYWORD3 RESERVED_WORD +PORT_INT6_bp KEYWORD3 RESERVED_WORD +PORT_INT7_bm KEYWORD3 RESERVED_WORD +PORT_INT7_bp KEYWORD3 RESERVED_WORD + +PORT_SRL_bm KEYWORD3 RESERVED_WORD +PORT_SRL_bp KEYWORD3 RESERVED_WORD + +PORT_ISC_gm KEYWORD3 RESERVED_WORD +PORT_ISC_gp KEYWORD3 RESERVED_WORD +PORT_ISC0_bm KEYWORD3 RESERVED_WORD +PORT_ISC0_bp KEYWORD3 RESERVED_WORD +PORT_ISC1_bm KEYWORD3 RESERVED_WORD +PORT_ISC1_bp KEYWORD3 RESERVED_WORD +PORT_ISC2_bm KEYWORD3 RESERVED_WORD +PORT_ISC2_bp KEYWORD3 RESERVED_WORD +PORT_PULLUPEN_bm KEYWORD3 RESERVED_WORD +PORT_PULLUPEN_bp KEYWORD3 RESERVED_WORD +PORT_INVEN_bm KEYWORD3 RESERVED_WORD +PORT_INVEN_bp KEYWORD3 RESERVED_WORD + +PORTMUX_EVOUT0_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT0_bp KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT1_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT1_bp KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT2_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT2_bp KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT3_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT3_bp KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT4_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT4_bp KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT5_bm KEYWORD3 RESERVED_WORD +PORTMUX_EVOUT5_bp KEYWORD3 RESERVED_WORD + +PORTMUX_LUT0_bm KEYWORD3 RESERVED_WORD +PORTMUX_LUT0_bp KEYWORD3 RESERVED_WORD +PORTMUX_LUT1_bm KEYWORD3 RESERVED_WORD +PORTMUX_LUT1_bp KEYWORD3 RESERVED_WORD +PORTMUX_LUT2_bm KEYWORD3 RESERVED_WORD +PORTMUX_LUT2_bp KEYWORD3 RESERVED_WORD +PORTMUX_LUT3_bm KEYWORD3 RESERVED_WORD +PORTMUX_LUT3_bp KEYWORD3 RESERVED_WORD + +PORTMUX_USART0_gm KEYWORD3 RESERVED_WORD +PORTMUX_USART0_gp KEYWORD3 RESERVED_WORD +PORTMUX_USART00_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART00_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART01_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART01_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART1_gm KEYWORD3 RESERVED_WORD +PORTMUX_USART1_gp KEYWORD3 RESERVED_WORD +PORTMUX_USART10_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART10_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART11_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART11_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART2_gm KEYWORD3 RESERVED_WORD +PORTMUX_USART2_gp KEYWORD3 RESERVED_WORD +PORTMUX_USART20_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART20_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART21_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART21_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART3_gm KEYWORD3 RESERVED_WORD +PORTMUX_USART3_gp KEYWORD3 RESERVED_WORD +PORTMUX_USART30_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART30_bp KEYWORD3 RESERVED_WORD +PORTMUX_USART31_bm KEYWORD3 RESERVED_WORD +PORTMUX_USART31_bp KEYWORD3 RESERVED_WORD + +PORTMUX_SPI0_gm KEYWORD3 RESERVED_WORD +PORTMUX_SPI0_gp KEYWORD3 RESERVED_WORD +PORTMUX_SPI00_bm KEYWORD3 RESERVED_WORD +PORTMUX_SPI00_bp KEYWORD3 RESERVED_WORD +PORTMUX_SPI01_bm KEYWORD3 RESERVED_WORD +PORTMUX_SPI01_bp KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_gm KEYWORD3 RESERVED_WORD +PORTMUX_TWI0_gp KEYWORD3 RESERVED_WORD +PORTMUX_TWI00_bm KEYWORD3 RESERVED_WORD +PORTMUX_TWI00_bp KEYWORD3 RESERVED_WORD +PORTMUX_TWI01_bm KEYWORD3 RESERVED_WORD +PORTMUX_TWI01_bp KEYWORD3 RESERVED_WORD + +PORTMUX_TCA0_gm KEYWORD3 RESERVED_WORD +PORTMUX_TCA0_gp KEYWORD3 RESERVED_WORD +PORTMUX_TCA00_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCA00_bp KEYWORD3 RESERVED_WORD +PORTMUX_TCA01_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCA01_bp KEYWORD3 RESERVED_WORD +PORTMUX_TCA02_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCA02_bp KEYWORD3 RESERVED_WORD + +PORTMUX_TCB0_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCB0_bp KEYWORD3 RESERVED_WORD +PORTMUX_TCB1_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCB1_bp KEYWORD3 RESERVED_WORD +PORTMUX_TCB2_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCB2_bp KEYWORD3 RESERVED_WORD +PORTMUX_TCB3_bm KEYWORD3 RESERVED_WORD +PORTMUX_TCB3_bp KEYWORD3 RESERVED_WORD + + +RSTCTRL_PORF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_PORF_bp KEYWORD3 RESERVED_WORD +RSTCTRL_BORF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_BORF_bp KEYWORD3 RESERVED_WORD +RSTCTRL_EXTRF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_EXTRF_bp KEYWORD3 RESERVED_WORD +RSTCTRL_WDRF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_WDRF_bp KEYWORD3 RESERVED_WORD +RSTCTRL_SWRF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_SWRF_bp KEYWORD3 RESERVED_WORD +RSTCTRL_UPDIRF_bm KEYWORD3 RESERVED_WORD +RSTCTRL_UPDIRF_bp KEYWORD3 RESERVED_WORD + +RSTCTRL_SWRE_bm KEYWORD3 RESERVED_WORD +RSTCTRL_SWRE_bp KEYWORD3 RESERVED_WORD + + +RTC_RTCEN_bm KEYWORD3 RESERVED_WORD +RTC_RTCEN_bp KEYWORD3 RESERVED_WORD +RTC_PRESCALER_gm KEYWORD3 RESERVED_WORD +RTC_PRESCALER_gp KEYWORD3 RESERVED_WORD +RTC_PRESCALER0_bm KEYWORD3 RESERVED_WORD +RTC_PRESCALER0_bp KEYWORD3 RESERVED_WORD +RTC_PRESCALER1_bm KEYWORD3 RESERVED_WORD +RTC_PRESCALER1_bp KEYWORD3 RESERVED_WORD +RTC_PRESCALER2_bm KEYWORD3 RESERVED_WORD +RTC_PRESCALER2_bp KEYWORD3 RESERVED_WORD +RTC_PRESCALER3_bm KEYWORD3 RESERVED_WORD +RTC_PRESCALER3_bp KEYWORD3 RESERVED_WORD +RTC_RUNSTDBY_bm KEYWORD3 RESERVED_WORD +RTC_RUNSTDBY_bp KEYWORD3 RESERVED_WORD + +RTC_CTRLABUSY_bm KEYWORD3 RESERVED_WORD +RTC_CTRLABUSY_bp KEYWORD3 RESERVED_WORD +RTC_CNTBUSY_bm KEYWORD3 RESERVED_WORD +RTC_CNTBUSY_bp KEYWORD3 RESERVED_WORD +RTC_PERBUSY_bm KEYWORD3 RESERVED_WORD +RTC_PERBUSY_bp KEYWORD3 RESERVED_WORD +RTC_CMPBUSY_bm KEYWORD3 RESERVED_WORD +RTC_CMPBUSY_bp KEYWORD3 RESERVED_WORD + +RTC_OVF_bm KEYWORD3 RESERVED_WORD +RTC_OVF_bp KEYWORD3 RESERVED_WORD +RTC_CMP_bm KEYWORD3 RESERVED_WORD +RTC_CMP_bp KEYWORD3 RESERVED_WORD + + + + +RTC_DBGRUN_bm KEYWORD3 RESERVED_WORD +RTC_DBGRUN_bp KEYWORD3 RESERVED_WORD + +RTC_ERROR_gm KEYWORD3 RESERVED_WORD +RTC_ERROR_gp KEYWORD3 RESERVED_WORD +RTC_ERROR0_bm KEYWORD3 RESERVED_WORD +RTC_ERROR0_bp KEYWORD3 RESERVED_WORD +RTC_ERROR1_bm KEYWORD3 RESERVED_WORD +RTC_ERROR1_bp KEYWORD3 RESERVED_WORD +RTC_ERROR2_bm KEYWORD3 RESERVED_WORD +RTC_ERROR2_bp KEYWORD3 RESERVED_WORD +RTC_ERROR3_bm KEYWORD3 RESERVED_WORD +RTC_ERROR3_bp KEYWORD3 RESERVED_WORD +RTC_ERROR4_bm KEYWORD3 RESERVED_WORD +RTC_ERROR4_bp KEYWORD3 RESERVED_WORD +RTC_ERROR5_bm KEYWORD3 RESERVED_WORD +RTC_ERROR5_bp KEYWORD3 RESERVED_WORD +RTC_ERROR6_bm KEYWORD3 RESERVED_WORD +RTC_ERROR6_bp KEYWORD3 RESERVED_WORD +RTC_SIGN_bm KEYWORD3 RESERVED_WORD +RTC_SIGN_bp KEYWORD3 RESERVED_WORD + +RTC_CLKSEL_gm KEYWORD3 RESERVED_WORD +RTC_CLKSEL_gp KEYWORD3 RESERVED_WORD +RTC_CLKSEL0_bm KEYWORD3 RESERVED_WORD +RTC_CLKSEL0_bp KEYWORD3 RESERVED_WORD +RTC_CLKSEL1_bm KEYWORD3 RESERVED_WORD +RTC_CLKSEL1_bp KEYWORD3 RESERVED_WORD + +RTC_PITEN_bm KEYWORD3 RESERVED_WORD +RTC_PITEN_bp KEYWORD3 RESERVED_WORD +RTC_PERIOD_gm KEYWORD3 RESERVED_WORD +RTC_PERIOD_gp KEYWORD3 RESERVED_WORD +RTC_PERIOD0_bm KEYWORD3 RESERVED_WORD +RTC_PERIOD0_bp KEYWORD3 RESERVED_WORD +RTC_PERIOD1_bm KEYWORD3 RESERVED_WORD +RTC_PERIOD1_bp KEYWORD3 RESERVED_WORD +RTC_PERIOD2_bm KEYWORD3 RESERVED_WORD +RTC_PERIOD2_bp KEYWORD3 RESERVED_WORD +RTC_PERIOD3_bm KEYWORD3 RESERVED_WORD +RTC_PERIOD3_bp KEYWORD3 RESERVED_WORD + +RTC_CTRLBUSY_bm KEYWORD3 RESERVED_WORD +RTC_CTRLBUSY_bp KEYWORD3 RESERVED_WORD + +RTC_PI_bm KEYWORD3 RESERVED_WORD +RTC_PI_bp KEYWORD3 RESERVED_WORD + + +SLPCTRL_SEN_bm KEYWORD3 RESERVED_WORD +SLPCTRL_SEN_bp KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE_gm KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE_gp KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE0_bm KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE0_bp KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE1_bm KEYWORD3 RESERVED_WORD +SLPCTRL_SMODE1_bp KEYWORD3 RESERVED_WORD + + +SPI_ENABLE_bm KEYWORD3 RESERVED_WORD +SPI_ENABLE_bp KEYWORD3 RESERVED_WORD +SPI_PRESC_gm KEYWORD3 RESERVED_WORD +SPI_PRESC_gp KEYWORD3 RESERVED_WORD +SPI_PRESC0_bm KEYWORD3 RESERVED_WORD +SPI_PRESC0_bp KEYWORD3 RESERVED_WORD +SPI_PRESC1_bm KEYWORD3 RESERVED_WORD +SPI_PRESC1_bp KEYWORD3 RESERVED_WORD +SPI_CLK2X_bm KEYWORD3 RESERVED_WORD +SPI_CLK2X_bp KEYWORD3 RESERVED_WORD +SPI_MASTER_bm KEYWORD3 RESERVED_WORD +SPI_MASTER_bp KEYWORD3 RESERVED_WORD +SPI_DORD_bm KEYWORD3 RESERVED_WORD +SPI_DORD_bp KEYWORD3 RESERVED_WORD + +SPI_MODE_gm KEYWORD3 RESERVED_WORD +SPI_MODE_gp KEYWORD3 RESERVED_WORD +SPI_MODE0_bm KEYWORD3 RESERVED_WORD +SPI_MODE0_bp KEYWORD3 RESERVED_WORD +SPI_MODE1_bm KEYWORD3 RESERVED_WORD +SPI_MODE1_bp KEYWORD3 RESERVED_WORD +SPI_SSD_bm KEYWORD3 RESERVED_WORD +SPI_SSD_bp KEYWORD3 RESERVED_WORD +SPI_BUFWR_bm KEYWORD3 RESERVED_WORD +SPI_BUFWR_bp KEYWORD3 RESERVED_WORD +SPI_BUFEN_bm KEYWORD3 RESERVED_WORD +SPI_BUFEN_bp KEYWORD3 RESERVED_WORD + +SPI_IE_bm KEYWORD3 RESERVED_WORD +SPI_IE_bp KEYWORD3 RESERVED_WORD +SPI_SSIE_bm KEYWORD3 RESERVED_WORD +SPI_SSIE_bp KEYWORD3 RESERVED_WORD +SPI_DREIE_bm KEYWORD3 RESERVED_WORD +SPI_DREIE_bp KEYWORD3 RESERVED_WORD +SPI_TXCIE_bm KEYWORD3 RESERVED_WORD +SPI_TXCIE_bp KEYWORD3 RESERVED_WORD +SPI_RXCIE_bm KEYWORD3 RESERVED_WORD +SPI_RXCIE_bp KEYWORD3 RESERVED_WORD + +SPI_BUFOVF_bm KEYWORD3 RESERVED_WORD +SPI_BUFOVF_bp KEYWORD3 RESERVED_WORD +SPI_SSIF_bm KEYWORD3 RESERVED_WORD +SPI_SSIF_bp KEYWORD3 RESERVED_WORD +SPI_DREIF_bm KEYWORD3 RESERVED_WORD +SPI_DREIF_bp KEYWORD3 RESERVED_WORD +SPI_TXCIF_bm KEYWORD3 RESERVED_WORD +SPI_TXCIF_bp KEYWORD3 RESERVED_WORD +SPI_WRCOL_bm KEYWORD3 RESERVED_WORD +SPI_WRCOL_bp KEYWORD3 RESERVED_WORD +SPI_RXCIF_bm KEYWORD3 RESERVED_WORD +SPI_RXCIF_bp KEYWORD3 RESERVED_WORD +SPI_IF_bm KEYWORD3 RESERVED_WORD +SPI_IF_bp KEYWORD3 RESERVED_WORD + + +SYSCFG_ENEXTBRK_bm KEYWORD3 RESERVED_WORD +SYSCFG_ENEXTBRK_bp KEYWORD3 RESERVED_WORD + +SYSCFG_OCDMR_bm KEYWORD3 RESERVED_WORD +SYSCFG_OCDMR_bp KEYWORD3 RESERVED_WORD + + +TCA_SINGLE_ENABLE_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_ENABLE_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_gm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL_gp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL0_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL0_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL1_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL1_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL2_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CLKSEL2_bp KEYWORD3 RESERVED_WORD + +TCA_SINGLE_WGMODE_gm KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE_gp KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE0_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE0_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE1_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE1_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE2_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_WGMODE2_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_ALUPD_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_ALUPD_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0EN_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0EN_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1EN_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1EN_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2EN_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2EN_bp KEYWORD3 RESERVED_WORD + +TCA_SINGLE_CMP0OV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0OV_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1OV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1OV_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2OV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2OV_bp KEYWORD3 RESERVED_WORD + +TCA_SINGLE_SPLITM_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_SPLITM_bp KEYWORD3 RESERVED_WORD + +TCA_SINGLE_DIR_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_DIR_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_LUPD_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_LUPD_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_gm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD_gp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD0_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD0_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD1_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMD1_bp KEYWORD3 RESERVED_WORD + + + + + +TCA_SINGLE_PERBV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_PERBV_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0BV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0BV_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1BV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1BV_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2BV_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2BV_bp KEYWORD3 RESERVED_WORD + + + + + + +TCA_SINGLE_CNTEI_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CNTEI_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_gm KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT_gp KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT0_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT0_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT1_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_EVACT1_bp KEYWORD3 RESERVED_WORD + +TCA_SINGLE_OVF_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_OVF_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP0_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP1_bp KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_CMP2_bp KEYWORD3 RESERVED_WORD + + + + + + +TCA_SINGLE_DBGRUN_bm KEYWORD3 RESERVED_WORD +TCA_SINGLE_DBGRUN_bp KEYWORD3 RESERVED_WORD + +TCA_SPLIT_ENABLE_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_ENABLE_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_gm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL_gp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL0_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL0_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL1_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL1_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL2_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CLKSEL2_bp KEYWORD3 RESERVED_WORD + +TCA_SPLIT_LCMP0EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP0EN_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1EN_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2EN_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP0EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP0EN_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP1EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP1EN_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP2EN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP2EN_bp KEYWORD3 RESERVED_WORD + +TCA_SPLIT_LCMP0OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP0OV_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1OV_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2OV_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP0OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP0OV_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP1OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP1OV_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP2OV_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HCMP2OV_bp KEYWORD3 RESERVED_WORD + +TCA_SPLIT_SPLITM_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_SPLITM_bp KEYWORD3 RESERVED_WORD + +TCA_SPLIT_CMD_gm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD_gp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD0_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD0_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD1_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_CMD1_bp KEYWORD3 RESERVED_WORD + + + +TCA_SPLIT_LUNF_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LUNF_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_HUNF_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_HUNF_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP0_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP0_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP1_bp KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_LCMP2_bp KEYWORD3 RESERVED_WORD + + + + + + + +TCA_SPLIT_DBGRUN_bm KEYWORD3 RESERVED_WORD +TCA_SPLIT_DBGRUN_bp KEYWORD3 RESERVED_WORD + + +TCB_ENABLE_bm KEYWORD3 RESERVED_WORD +TCB_ENABLE_bp KEYWORD3 RESERVED_WORD +TCB_CLKSEL_gm KEYWORD3 RESERVED_WORD +TCB_CLKSEL_gp KEYWORD3 RESERVED_WORD +TCB_CLKSEL0_bm KEYWORD3 RESERVED_WORD +TCB_CLKSEL0_bp KEYWORD3 RESERVED_WORD +TCB_CLKSEL1_bm KEYWORD3 RESERVED_WORD +TCB_CLKSEL1_bp KEYWORD3 RESERVED_WORD +TCB_SYNCUPD_bm KEYWORD3 RESERVED_WORD +TCB_SYNCUPD_bp KEYWORD3 RESERVED_WORD +TCB_RUNSTDBY_bm KEYWORD3 RESERVED_WORD +TCB_RUNSTDBY_bp KEYWORD3 RESERVED_WORD + +TCB_CNTMODE_gm KEYWORD3 RESERVED_WORD +TCB_CNTMODE_gp KEYWORD3 RESERVED_WORD +TCB_CNTMODE0_bm KEYWORD3 RESERVED_WORD +TCB_CNTMODE0_bp KEYWORD3 RESERVED_WORD +TCB_CNTMODE1_bm KEYWORD3 RESERVED_WORD +TCB_CNTMODE1_bp KEYWORD3 RESERVED_WORD +TCB_CNTMODE2_bm KEYWORD3 RESERVED_WORD +TCB_CNTMODE2_bp KEYWORD3 RESERVED_WORD +TCB_CCMPEN_bm KEYWORD3 RESERVED_WORD +TCB_CCMPEN_bp KEYWORD3 RESERVED_WORD +TCB_CCMPINIT_bm KEYWORD3 RESERVED_WORD +TCB_CCMPINIT_bp KEYWORD3 RESERVED_WORD +TCB_ASYNC_bm KEYWORD3 RESERVED_WORD +TCB_ASYNC_bp KEYWORD3 RESERVED_WORD + +TCB_CAPTEI_bm KEYWORD3 RESERVED_WORD +TCB_CAPTEI_bp KEYWORD3 RESERVED_WORD +TCB_EDGE_bm KEYWORD3 RESERVED_WORD +TCB_EDGE_bp KEYWORD3 RESERVED_WORD +TCB_FILTER_bm KEYWORD3 RESERVED_WORD +TCB_FILTER_bp KEYWORD3 RESERVED_WORD + +TCB_CAPT_bm KEYWORD3 RESERVED_WORD +TCB_CAPT_bp KEYWORD3 RESERVED_WORD + + + +TCB_RUN_bm KEYWORD3 RESERVED_WORD +TCB_RUN_bp KEYWORD3 RESERVED_WORD + +TCB_DBGRUN_bm KEYWORD3 RESERVED_WORD +TCB_DBGRUN_bp KEYWORD3 RESERVED_WORD + + +TWI_FMPEN_bm KEYWORD3 RESERVED_WORD +TWI_FMPEN_bp KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_gm KEYWORD3 RESERVED_WORD +TWI_SDAHOLD_gp KEYWORD3 RESERVED_WORD +TWI_SDAHOLD0_bm KEYWORD3 RESERVED_WORD +TWI_SDAHOLD0_bp KEYWORD3 RESERVED_WORD +TWI_SDAHOLD1_bm KEYWORD3 RESERVED_WORD +TWI_SDAHOLD1_bp KEYWORD3 RESERVED_WORD +TWI_SDASETUP_bm KEYWORD3 RESERVED_WORD +TWI_SDASETUP_bp KEYWORD3 RESERVED_WORD + +TWI_ENABLE_bm KEYWORD3 RESERVED_WORD +TWI_ENABLE_bp KEYWORD3 RESERVED_WORD + + + +TWI_DBGRUN_bm KEYWORD3 RESERVED_WORD +TWI_DBGRUN_bp KEYWORD3 RESERVED_WORD + + +TWI_SMEN_bm KEYWORD3 RESERVED_WORD +TWI_SMEN_bp KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_gm KEYWORD3 RESERVED_WORD +TWI_TIMEOUT_gp KEYWORD3 RESERVED_WORD +TWI_TIMEOUT0_bm KEYWORD3 RESERVED_WORD +TWI_TIMEOUT0_bp KEYWORD3 RESERVED_WORD +TWI_TIMEOUT1_bm KEYWORD3 RESERVED_WORD +TWI_TIMEOUT1_bp KEYWORD3 RESERVED_WORD +TWI_QCEN_bm KEYWORD3 RESERVED_WORD +TWI_QCEN_bp KEYWORD3 RESERVED_WORD +TWI_WIEN_bm KEYWORD3 RESERVED_WORD +TWI_WIEN_bp KEYWORD3 RESERVED_WORD +TWI_RIEN_bm KEYWORD3 RESERVED_WORD +TWI_RIEN_bp KEYWORD3 RESERVED_WORD + +TWI_MCMD_gm KEYWORD3 RESERVED_WORD +TWI_MCMD_gp KEYWORD3 RESERVED_WORD +TWI_MCMD0_bm KEYWORD3 RESERVED_WORD +TWI_MCMD0_bp KEYWORD3 RESERVED_WORD +TWI_MCMD1_bm KEYWORD3 RESERVED_WORD +TWI_MCMD1_bp KEYWORD3 RESERVED_WORD +TWI_ACKACT_bm KEYWORD3 RESERVED_WORD +TWI_ACKACT_bp KEYWORD3 RESERVED_WORD +TWI_FLUSH_bm KEYWORD3 RESERVED_WORD +TWI_FLUSH_bp KEYWORD3 RESERVED_WORD + +TWI_BUSSTATE_gm KEYWORD3 RESERVED_WORD +TWI_BUSSTATE_gp KEYWORD3 RESERVED_WORD +TWI_BUSSTATE0_bm KEYWORD3 RESERVED_WORD +TWI_BUSSTATE0_bp KEYWORD3 RESERVED_WORD +TWI_BUSSTATE1_bm KEYWORD3 RESERVED_WORD +TWI_BUSSTATE1_bp KEYWORD3 RESERVED_WORD +TWI_BUSERR_bm KEYWORD3 RESERVED_WORD +TWI_BUSERR_bp KEYWORD3 RESERVED_WORD +TWI_ARBLOST_bm KEYWORD3 RESERVED_WORD +TWI_ARBLOST_bp KEYWORD3 RESERVED_WORD +TWI_RXACK_bm KEYWORD3 RESERVED_WORD +TWI_RXACK_bp KEYWORD3 RESERVED_WORD +TWI_CLKHOLD_bm KEYWORD3 RESERVED_WORD +TWI_CLKHOLD_bp KEYWORD3 RESERVED_WORD +TWI_WIF_bm KEYWORD3 RESERVED_WORD +TWI_WIF_bp KEYWORD3 RESERVED_WORD +TWI_RIF_bm KEYWORD3 RESERVED_WORD +TWI_RIF_bp KEYWORD3 RESERVED_WORD + + + +TWI_PMEN_bm KEYWORD3 RESERVED_WORD +TWI_PMEN_bp KEYWORD3 RESERVED_WORD +TWI_PIEN_bm KEYWORD3 RESERVED_WORD +TWI_PIEN_bp KEYWORD3 RESERVED_WORD +TWI_APIEN_bm KEYWORD3 RESERVED_WORD +TWI_APIEN_bp KEYWORD3 RESERVED_WORD +TWI_DIEN_bm KEYWORD3 RESERVED_WORD +TWI_DIEN_bp KEYWORD3 RESERVED_WORD + +TWI_SCMD_gm KEYWORD3 RESERVED_WORD +TWI_SCMD_gp KEYWORD3 RESERVED_WORD +TWI_SCMD0_bm KEYWORD3 RESERVED_WORD +TWI_SCMD0_bp KEYWORD3 RESERVED_WORD +TWI_SCMD1_bm KEYWORD3 RESERVED_WORD +TWI_SCMD1_bp KEYWORD3 RESERVED_WORD + + +TWI_AP_bm KEYWORD3 RESERVED_WORD +TWI_AP_bp KEYWORD3 RESERVED_WORD +TWI_DIR_bm KEYWORD3 RESERVED_WORD +TWI_DIR_bp KEYWORD3 RESERVED_WORD + +TWI_COLL_bm KEYWORD3 RESERVED_WORD +TWI_COLL_bp KEYWORD3 RESERVED_WORD + + +TWI_APIF_bm KEYWORD3 RESERVED_WORD +TWI_APIF_bp KEYWORD3 RESERVED_WORD +TWI_DIF_bm KEYWORD3 RESERVED_WORD +TWI_DIF_bp KEYWORD3 RESERVED_WORD + +TWI_ADDREN_bm KEYWORD3 RESERVED_WORD +TWI_ADDREN_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK_gm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK_gp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK0_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK0_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK1_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK1_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK2_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK2_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK3_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK3_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK4_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK4_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK5_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK5_bp KEYWORD3 RESERVED_WORD +TWI_ADDRMASK6_bm KEYWORD3 RESERVED_WORD +TWI_ADDRMASK6_bp KEYWORD3 RESERVED_WORD + + +USART_DATA_gm KEYWORD3 RESERVED_WORD +USART_DATA_gp KEYWORD3 RESERVED_WORD +USART_DATA0_bm KEYWORD3 RESERVED_WORD +USART_DATA0_bp KEYWORD3 RESERVED_WORD +USART_DATA1_bm KEYWORD3 RESERVED_WORD +USART_DATA1_bp KEYWORD3 RESERVED_WORD +USART_DATA2_bm KEYWORD3 RESERVED_WORD +USART_DATA2_bp KEYWORD3 RESERVED_WORD +USART_DATA3_bm KEYWORD3 RESERVED_WORD +USART_DATA3_bp KEYWORD3 RESERVED_WORD +USART_DATA4_bm KEYWORD3 RESERVED_WORD +USART_DATA4_bp KEYWORD3 RESERVED_WORD +USART_DATA5_bm KEYWORD3 RESERVED_WORD +USART_DATA5_bp KEYWORD3 RESERVED_WORD +USART_DATA6_bm KEYWORD3 RESERVED_WORD +USART_DATA6_bp KEYWORD3 RESERVED_WORD +USART_DATA7_bm KEYWORD3 RESERVED_WORD +USART_DATA7_bp KEYWORD3 RESERVED_WORD + +USART_DATA8_bm KEYWORD3 RESERVED_WORD +USART_DATA8_bp KEYWORD3 RESERVED_WORD +USART_PERR_bm KEYWORD3 RESERVED_WORD +USART_PERR_bp KEYWORD3 RESERVED_WORD +USART_FERR_bm KEYWORD3 RESERVED_WORD +USART_FERR_bp KEYWORD3 RESERVED_WORD +USART_BUFOVF_bm KEYWORD3 RESERVED_WORD +USART_BUFOVF_bp KEYWORD3 RESERVED_WORD +USART_RXCIF_bm KEYWORD3 RESERVED_WORD +USART_RXCIF_bp KEYWORD3 RESERVED_WORD + + + + + +USART_WFB_bm KEYWORD3 RESERVED_WORD +USART_WFB_bp KEYWORD3 RESERVED_WORD +USART_BDF_bm KEYWORD3 RESERVED_WORD +USART_BDF_bp KEYWORD3 RESERVED_WORD +USART_ISFIF_bm KEYWORD3 RESERVED_WORD +USART_ISFIF_bp KEYWORD3 RESERVED_WORD +USART_RXSIF_bm KEYWORD3 RESERVED_WORD +USART_RXSIF_bp KEYWORD3 RESERVED_WORD +USART_DREIF_bm KEYWORD3 RESERVED_WORD +USART_DREIF_bp KEYWORD3 RESERVED_WORD +USART_TXCIF_bm KEYWORD3 RESERVED_WORD +USART_TXCIF_bp KEYWORD3 RESERVED_WORD + + +USART_RS485_gm KEYWORD3 RESERVED_WORD +USART_RS485_gp KEYWORD3 RESERVED_WORD +USART_RS4850_bm KEYWORD3 RESERVED_WORD +USART_RS4850_bp KEYWORD3 RESERVED_WORD +USART_RS4851_bm KEYWORD3 RESERVED_WORD +USART_RS4851_bp KEYWORD3 RESERVED_WORD +USART_ABEIE_bm KEYWORD3 RESERVED_WORD +USART_ABEIE_bp KEYWORD3 RESERVED_WORD +USART_LBME_bm KEYWORD3 RESERVED_WORD +USART_LBME_bp KEYWORD3 RESERVED_WORD +USART_RXSIE_bm KEYWORD3 RESERVED_WORD +USART_RXSIE_bp KEYWORD3 RESERVED_WORD +USART_DREIE_bm KEYWORD3 RESERVED_WORD +USART_DREIE_bp KEYWORD3 RESERVED_WORD +USART_TXCIE_bm KEYWORD3 RESERVED_WORD +USART_TXCIE_bp KEYWORD3 RESERVED_WORD +USART_RXCIE_bm KEYWORD3 RESERVED_WORD +USART_RXCIE_bp KEYWORD3 RESERVED_WORD + +USART_MPCM_bm KEYWORD3 RESERVED_WORD +USART_MPCM_bp KEYWORD3 RESERVED_WORD +USART_RXMODE_gm KEYWORD3 RESERVED_WORD +USART_RXMODE_gp KEYWORD3 RESERVED_WORD +USART_RXMODE0_bm KEYWORD3 RESERVED_WORD +USART_RXMODE0_bp KEYWORD3 RESERVED_WORD +USART_RXMODE1_bm KEYWORD3 RESERVED_WORD +USART_RXMODE1_bp KEYWORD3 RESERVED_WORD +USART_ODME_bm KEYWORD3 RESERVED_WORD +USART_ODME_bp KEYWORD3 RESERVED_WORD +USART_SFDEN_bm KEYWORD3 RESERVED_WORD +USART_SFDEN_bp KEYWORD3 RESERVED_WORD +USART_TXEN_bm KEYWORD3 RESERVED_WORD +USART_TXEN_bp KEYWORD3 RESERVED_WORD +USART_RXEN_bm KEYWORD3 RESERVED_WORD +USART_RXEN_bp KEYWORD3 RESERVED_WORD + +USART_UCPHA_bm KEYWORD3 RESERVED_WORD +USART_UCPHA_bp KEYWORD3 RESERVED_WORD +USART_UDORD_bm KEYWORD3 RESERVED_WORD +USART_UDORD_bp KEYWORD3 RESERVED_WORD +USART_CHSIZE_gm KEYWORD3 RESERVED_WORD +USART_CHSIZE_gp KEYWORD3 RESERVED_WORD +USART_CHSIZE0_bm KEYWORD3 RESERVED_WORD +USART_CHSIZE0_bp KEYWORD3 RESERVED_WORD +USART_CHSIZE1_bm KEYWORD3 RESERVED_WORD +USART_CHSIZE1_bp KEYWORD3 RESERVED_WORD +USART_CHSIZE2_bm KEYWORD3 RESERVED_WORD +USART_CHSIZE2_bp KEYWORD3 RESERVED_WORD +USART_SBMODE_bm KEYWORD3 RESERVED_WORD +USART_SBMODE_bp KEYWORD3 RESERVED_WORD +USART_PMODE_gm KEYWORD3 RESERVED_WORD +USART_PMODE_gp KEYWORD3 RESERVED_WORD +USART_PMODE0_bm KEYWORD3 RESERVED_WORD +USART_PMODE0_bp KEYWORD3 RESERVED_WORD +USART_PMODE1_bm KEYWORD3 RESERVED_WORD +USART_PMODE1_bp KEYWORD3 RESERVED_WORD +USART_CMODE_gm KEYWORD3 RESERVED_WORD +USART_CMODE_gp KEYWORD3 RESERVED_WORD +USART_CMODE0_bm KEYWORD3 RESERVED_WORD +USART_CMODE0_bp KEYWORD3 RESERVED_WORD +USART_CMODE1_bm KEYWORD3 RESERVED_WORD +USART_CMODE1_bp KEYWORD3 RESERVED_WORD + +USART_ABW_gm KEYWORD3 RESERVED_WORD +USART_ABW_gp KEYWORD3 RESERVED_WORD +USART_ABW0_bm KEYWORD3 RESERVED_WORD +USART_ABW0_bp KEYWORD3 RESERVED_WORD +USART_ABW1_bm KEYWORD3 RESERVED_WORD +USART_ABW1_bp KEYWORD3 RESERVED_WORD + +USART_DBGRUN_bm KEYWORD3 RESERVED_WORD +USART_DBGRUN_bp KEYWORD3 RESERVED_WORD +USART_ABMBP_bm KEYWORD3 RESERVED_WORD +USART_ABMBP_bp KEYWORD3 RESERVED_WORD + +USART_IREI_bm KEYWORD3 RESERVED_WORD +USART_IREI_bp KEYWORD3 RESERVED_WORD + +USART_TXPL_gm KEYWORD3 RESERVED_WORD +USART_TXPL_gp KEYWORD3 RESERVED_WORD +USART_TXPL0_bm KEYWORD3 RESERVED_WORD +USART_TXPL0_bp KEYWORD3 RESERVED_WORD +USART_TXPL1_bm KEYWORD3 RESERVED_WORD +USART_TXPL1_bp KEYWORD3 RESERVED_WORD +USART_TXPL2_bm KEYWORD3 RESERVED_WORD +USART_TXPL2_bp KEYWORD3 RESERVED_WORD +USART_TXPL3_bm KEYWORD3 RESERVED_WORD +USART_TXPL3_bp KEYWORD3 RESERVED_WORD +USART_TXPL4_bm KEYWORD3 RESERVED_WORD +USART_TXPL4_bp KEYWORD3 RESERVED_WORD +USART_TXPL5_bm KEYWORD3 RESERVED_WORD +USART_TXPL5_bp KEYWORD3 RESERVED_WORD +USART_TXPL6_bm KEYWORD3 RESERVED_WORD +USART_TXPL6_bp KEYWORD3 RESERVED_WORD +USART_TXPL7_bm KEYWORD3 RESERVED_WORD +USART_TXPL7_bp KEYWORD3 RESERVED_WORD + +USART_RXPL_gm KEYWORD3 RESERVED_WORD +USART_RXPL_gp KEYWORD3 RESERVED_WORD +USART_RXPL0_bm KEYWORD3 RESERVED_WORD +USART_RXPL0_bp KEYWORD3 RESERVED_WORD +USART_RXPL1_bm KEYWORD3 RESERVED_WORD +USART_RXPL1_bp KEYWORD3 RESERVED_WORD +USART_RXPL2_bm KEYWORD3 RESERVED_WORD +USART_RXPL2_bp KEYWORD3 RESERVED_WORD +USART_RXPL3_bm KEYWORD3 RESERVED_WORD +USART_RXPL3_bp KEYWORD3 RESERVED_WORD +USART_RXPL4_bm KEYWORD3 RESERVED_WORD +USART_RXPL4_bp KEYWORD3 RESERVED_WORD +USART_RXPL5_bm KEYWORD3 RESERVED_WORD +USART_RXPL5_bp KEYWORD3 RESERVED_WORD +USART_RXPL6_bm KEYWORD3 RESERVED_WORD +USART_RXPL6_bp KEYWORD3 RESERVED_WORD + + +VPORT_INT_gm KEYWORD3 RESERVED_WORD +VPORT_INT_gp KEYWORD3 RESERVED_WORD +VPORT_INT0_bm KEYWORD3 RESERVED_WORD +VPORT_INT0_bp KEYWORD3 RESERVED_WORD +VPORT_INT1_bm KEYWORD3 RESERVED_WORD +VPORT_INT1_bp KEYWORD3 RESERVED_WORD +VPORT_INT2_bm KEYWORD3 RESERVED_WORD +VPORT_INT2_bp KEYWORD3 RESERVED_WORD +VPORT_INT3_bm KEYWORD3 RESERVED_WORD +VPORT_INT3_bp KEYWORD3 RESERVED_WORD +VPORT_INT4_bm KEYWORD3 RESERVED_WORD +VPORT_INT4_bp KEYWORD3 RESERVED_WORD +VPORT_INT5_bm KEYWORD3 RESERVED_WORD +VPORT_INT5_bp KEYWORD3 RESERVED_WORD +VPORT_INT6_bm KEYWORD3 RESERVED_WORD +VPORT_INT6_bp KEYWORD3 RESERVED_WORD +VPORT_INT7_bm KEYWORD3 RESERVED_WORD +VPORT_INT7_bp KEYWORD3 RESERVED_WORD + + +VREF_AC0REFSEL_gm KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL_gp KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL0_bm KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL0_bp KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL1_bm KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL1_bp KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL2_bm KEYWORD3 RESERVED_WORD +VREF_AC0REFSEL2_bp KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_gm KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL_gp KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL0_bm KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL0_bp KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL1_bm KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL1_bp KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL2_bm KEYWORD3 RESERVED_WORD +VREF_ADC0REFSEL2_bp KEYWORD3 RESERVED_WORD + +VREF_AC0REFEN_bm KEYWORD3 RESERVED_WORD +VREF_AC0REFEN_bp KEYWORD3 RESERVED_WORD +VREF_ADC0REFEN_bm KEYWORD3 RESERVED_WORD +VREF_ADC0REFEN_bp KEYWORD3 RESERVED_WORD + + +WDT_PERIOD_gm KEYWORD3 RESERVED_WORD +WDT_PERIOD_gp KEYWORD3 RESERVED_WORD +WDT_PERIOD0_bm KEYWORD3 RESERVED_WORD +WDT_PERIOD0_bp KEYWORD3 RESERVED_WORD +WDT_PERIOD1_bm KEYWORD3 RESERVED_WORD +WDT_PERIOD1_bp KEYWORD3 RESERVED_WORD +WDT_PERIOD2_bm KEYWORD3 RESERVED_WORD +WDT_PERIOD2_bp KEYWORD3 RESERVED_WORD +WDT_PERIOD3_bm KEYWORD3 RESERVED_WORD +WDT_PERIOD3_bp KEYWORD3 RESERVED_WORD +WDT_WINDOW_gm KEYWORD3 RESERVED_WORD +WDT_WINDOW_gp KEYWORD3 RESERVED_WORD +WDT_WINDOW0_bm KEYWORD3 RESERVED_WORD +WDT_WINDOW0_bp KEYWORD3 RESERVED_WORD +WDT_WINDOW1_bm KEYWORD3 RESERVED_WORD +WDT_WINDOW1_bp KEYWORD3 RESERVED_WORD +WDT_WINDOW2_bm KEYWORD3 RESERVED_WORD +WDT_WINDOW2_bp KEYWORD3 RESERVED_WORD +WDT_WINDOW3_bm KEYWORD3 RESERVED_WORD +WDT_WINDOW3_bp KEYWORD3 RESERVED_WORD + +WDT_SYNCBUSY_bm KEYWORD3 RESERVED_WORD +WDT_SYNCBUSY_bp KEYWORD3 RESERVED_WORD +WDT_LOCK_bm KEYWORD3 RESERVED_WORD +WDT_LOCK_bp KEYWORD3 RESERVED_WORD +PIN0_bm KEYWORD3 RESERVED_WORD +PIN0_bp KEYWORD3 RESERVED_WORD +PIN1_bm KEYWORD3 RESERVED_WORD +PIN1_bp KEYWORD3 RESERVED_WORD +PIN2_bm KEYWORD3 RESERVED_WORD +PIN2_bp KEYWORD3 RESERVED_WORD +PIN3_bm KEYWORD3 RESERVED_WORD +PIN3_bp KEYWORD3 RESERVED_WORD +PIN4_bm KEYWORD3 RESERVED_WORD +PIN4_bp KEYWORD3 RESERVED_WORD +PIN5_bm KEYWORD3 RESERVED_WORD +PIN5_bp KEYWORD3 RESERVED_WORD +PIN6_bm KEYWORD3 RESERVED_WORD +PIN6_bp KEYWORD3 RESERVED_WORD +PIN7_bm KEYWORD3 RESERVED_WORD +PIN7_bp KEYWORD3 RESERVED_WORD + + + +CRCSCAN_NMI_vect_num LITERAL1 +CRCSCAN_NMI_vect LITERAL1 + +BOD_VLM_vect_num LITERAL1 +BOD_VLM_vect LITERAL1 + +RTC_CNT_vect_num LITERAL1 +RTC_CNT_vect LITERAL1 +RTC_PIT_vect_num LITERAL1 +RTC_PIT_vect LITERAL1 + +CCL_CCL_vect_num LITERAL1 +CCL_CCL_vect LITERAL1 + +PORTA_PORT_vect_num LITERAL1 +PORTA_PORT_vect LITERAL1 + +TCA0_LUNF_vect_num LITERAL1 +TCA0_LUNF_vect LITERAL1 +TCA0_OVF_vect_num LITERAL1 +TCA0_OVF_vect LITERAL1 +TCA0_HUNF_vect_num LITERAL1 +TCA0_HUNF_vect LITERAL1 +TCA0_LCMP0_vect_num LITERAL1 +TCA0_LCMP0_vect LITERAL1 +TCA0_CMP0_vect_num LITERAL1 +TCA0_CMP0_vect LITERAL1 +TCA0_CMP1_vect_num LITERAL1 +TCA0_CMP1_vect LITERAL1 +TCA0_LCMP1_vect_num LITERAL1 +TCA0_LCMP1_vect LITERAL1 +TCA0_LCMP2_vect_num LITERAL1 +TCA0_LCMP2_vect LITERAL1 +TCA0_CMP2_vect_num LITERAL1 +TCA0_CMP2_vect LITERAL1 + +TCB0_INT_vect_num LITERAL1 +TCB0_INT_vect LITERAL1 + +TCB1_INT_vect_num LITERAL1 +TCB1_INT_vect LITERAL1 + +TWI0_TWIS_vect_num LITERAL1 +TWI0_TWIS_vect LITERAL1 +TWI0_TWIM_vect_num LITERAL1 +TWI0_TWIM_vect LITERAL1 + +SPI0_INT_vect_num LITERAL1 +SPI0_INT_vect LITERAL1 + +USART0_RXC_vect_num LITERAL1 +USART0_RXC_vect LITERAL1 +USART0_DRE_vect_num LITERAL1 +USART0_DRE_vect LITERAL1 +USART0_TXC_vect_num LITERAL1 +USART0_TXC_vect LITERAL1 + +PORTD_PORT_vect_num LITERAL1 +PORTD_PORT_vect LITERAL1 + +AC0_AC_vect_num LITERAL1 +AC0_AC_vect LITERAL1 + +ADC0_RESRDY_vect_num LITERAL1 +ADC0_RESRDY_vect LITERAL1 +ADC0_WCOMP_vect_num LITERAL1 +ADC0_WCOMP_vect LITERAL1 + +PORTC_PORT_vect_num LITERAL1 +PORTC_PORT_vect LITERAL1 + +TCB2_INT_vect_num LITERAL1 +TCB2_INT_vect LITERAL1 + +USART1_RXC_vect_num LITERAL1 +USART1_RXC_vect LITERAL1 +USART1_DRE_vect_num LITERAL1 +USART1_DRE_vect LITERAL1 +USART1_TXC_vect_num LITERAL1 +USART1_TXC_vect LITERAL1 + +PORTF_PORT_vect_num LITERAL1 +PORTF_PORT_vect LITERAL1 + +NVMCTRL_EE_vect_num LITERAL1 +NVMCTRL_EE_vect LITERAL1 + +USART2_RXC_vect_num LITERAL1 +USART2_RXC_vect LITERAL1 +USART2_DRE_vect_num LITERAL1 +USART2_DRE_vect LITERAL1 +USART2_TXC_vect_num LITERAL1 +USART2_TXC_vect LITERAL1 + +PORTB_PORT_vect_num LITERAL1 +PORTB_PORT_vect LITERAL1 + +PORTE_PORT_vect_num LITERAL1 +PORTE_PORT_vect LITERAL1 + +TCB3_INT_vect_num LITERAL1 +TCB3_INT_vect LITERAL1 + +USART3_RXC_vect_num LITERAL1 +USART3_RXC_vect LITERAL1 +USART3_DRE_vect_num LITERAL1 +USART3_DRE_vect LITERAL1 +USART3_TXC_vect_num LITERAL1 +USART3_TXC_vect LITERAL1 +_VECTOR_SIZE LITERAL1 +_VECTORS_SIZE LITERAL1 + +DATAMEM_START LITERAL1 +DATAMEM_SIZE LITERAL1 +DATAMEM_START LITERAL1 +DATAMEM_SIZE LITERAL1 +DATAMEM_END LITERAL1 +EEPROM_START LITERAL1 +EEPROM_SIZE LITERAL1 +EEPROM_PAGE_SIZE LITERAL1 +EEPROM_START LITERAL1 +EEPROM_SIZE LITERAL1 +EEPROM_PAGE_SIZE LITERAL1 +EEPROM_END LITERAL1 + +MAPPED_EEPROM_START LITERAL1 +MAPPED_EEPROM_SIZE LITERAL1 +MAPPED_EEPROM_PAGE_SIZE LITERAL1 +MAPPED_EEPROM_END LITERAL1 +FUSES_START LITERAL1 +FUSES_SIZE LITERAL1 +FUSES_PAGE_SIZE LITERAL1 +FUSES_START LITERAL1 +FUSES_SIZE LITERAL1 +FUSES_PAGE_SIZE LITERAL1 +FUSES_END LITERAL1 +INTERNAL_SRAM_START LITERAL1 +INTERNAL_SRAM_SIZE LITERAL1 +INTERNAL_SRAM_PAGE_SIZE LITERAL1 +INTERNAL_SRAM_START LITERAL1 +INTERNAL_SRAM_SIZE LITERAL1 +INTERNAL_SRAM_PAGE_SIZE LITERAL1 +INTERNAL_SRAM_END LITERAL1 +IO_START LITERAL1 +IO_SIZE LITERAL1 +IO_PAGE_SIZE LITERAL1 +IO_START LITERAL1 +IO_SIZE LITERAL1 +IO_PAGE_SIZE LITERAL1 +IO_END LITERAL1 +LOCKBITS_START LITERAL1 +LOCKBITS_SIZE LITERAL1 +LOCKBITS_PAGE_SIZE LITERAL1 +LOCKBITS_START LITERAL1 +LOCKBITS_SIZE LITERAL1 +LOCKBITS_PAGE_SIZE LITERAL1 +LOCKBITS_END LITERAL1 +MAPPED_PROGMEM_START LITERAL1 +MAPPED_PROGMEM_SIZE LITERAL1 +MAPPED_PROGMEM_PAGE_SIZE LITERAL1 +MAPPED_PROGMEM_START LITERAL1 +MAPPED_PROGMEM_SIZE LITERAL1 +MAPPED_PROGMEM_PAGE_SIZE LITERAL1 +MAPPED_PROGMEM_END LITERAL1 +PROD_SIGNATURES_START LITERAL1 +PROD_SIGNATURES_SIZE LITERAL1 +PROD_SIGNATURES_PAGE_SIZE LITERAL1 +PROD_SIGNATURES_START LITERAL1 +PROD_SIGNATURES_SIZE LITERAL1 +PROD_SIGNATURES_PAGE_SIZE LITERAL1 +PROD_SIGNATURES_END LITERAL1 +SIGNATURES_START LITERAL1 +SIGNATURES_SIZE LITERAL1 +SIGNATURES_PAGE_SIZE LITERAL1 +SIGNATURES_START LITERAL1 +SIGNATURES_SIZE LITERAL1 +SIGNATURES_PAGE_SIZE LITERAL1 +SIGNATURES_END LITERAL1 +USER_SIGNATURES_START LITERAL1 +USER_SIGNATURES_SIZE LITERAL1 +USER_SIGNATURES_PAGE_SIZE LITERAL1 +USER_SIGNATURES_START LITERAL1 +USER_SIGNATURES_SIZE LITERAL1 +USER_SIGNATURES_PAGE_SIZE LITERAL1 +USER_SIGNATURES_END LITERAL1 +PROGMEM_START LITERAL1 +PROGMEM_SIZE LITERAL1 +PROGMEM_START LITERAL1 +PROGMEM_SIZE LITERAL1 +PROGMEM_END LITERAL1 +PROGMEM_START LITERAL1 +PROGMEM_SIZE LITERAL1 +PROGMEM_PAGE_SIZE LITERAL1 +PROGMEM_START LITERAL1 +PROGMEM_SIZE LITERAL1 +PROGMEM_PAGE_SIZE LITERAL1 +PROGMEM_END LITERAL1 +FLASHSTART LITERAL1 +FLASHEND LITERAL1 +RAMSTART LITERAL1 +RAMSIZE LITERAL1 +RAMEND LITERAL1 +E2END LITERAL1 +E2PAGESIZE LITERAL1 + +FUSE_MEMORY_SIZE LITERAL1 + +FUSE_PERIOD0 LITERAL1 +FUSE_PERIOD1 LITERAL1 +FUSE_PERIOD2 LITERAL1 +FUSE_PERIOD3 LITERAL1 +FUSE_WINDOW0 LITERAL1 +FUSE_WINDOW1 LITERAL1 +FUSE_WINDOW2 LITERAL1 +FUSE_WINDOW3 LITERAL1 +FUSE0_DEFAULT LITERAL1 +FUSE_WDTCFG_DEFAULT LITERAL1 + +FUSE_SLEEP0 LITERAL1 +FUSE_SLEEP1 LITERAL1 +FUSE_ACTIVE0 LITERAL1 +FUSE_ACTIVE1 LITERAL1 +FUSE_SAMPFREQ LITERAL1 +FUSE_LVL0 LITERAL1 +FUSE_LVL1 LITERAL1 +FUSE_LVL2 LITERAL1 +FUSE1_DEFAULT LITERAL1 +FUSE_BODCFG_DEFAULT LITERAL1 + +FUSE_FREQSEL0 LITERAL1 +FUSE_FREQSEL1 LITERAL1 +FUSE_OSCLOCK LITERAL1 +FUSE2_DEFAULT LITERAL1 +FUSE_OSCCFG_DEFAULT LITERAL1 + +FUSE_EESAVE LITERAL1 +FUSE_RSTPINCFG LITERAL1 +FUSE_CRCSRC0 LITERAL1 +FUSE_CRCSRC1 LITERAL1 +FUSE5_DEFAULT LITERAL1 +FUSE_SYSCFG0_DEFAULT LITERAL1 + +FUSE_SUT0 LITERAL1 +FUSE_SUT1 LITERAL1 +FUSE_SUT2 LITERAL1 +FUSE6_DEFAULT LITERAL1 +FUSE_SYSCFG1_DEFAULT LITERAL1 + +FUSE7_DEFAULT LITERAL1 +FUSE_APPEND_DEFAULT LITERAL1 + +FUSE8_DEFAULT LITERAL1 +FUSE_BOOTEND_DEFAULT LITERAL1 + +__LOCK_BITS_EXIST LITERAL1 + +SIGNATURE_0 LITERAL1 +SIGNATURE_1 LITERAL1 +SIGNATURE_2 LITERAL1 diff --git a/megaavr/libraries/MegaCoreX/library.properties b/megaavr/libraries/MegaCoreX/library.properties new file mode 100644 index 0000000..6afd7cf --- /dev/null +++ b/megaavr/libraries/MegaCoreX/library.properties @@ -0,0 +1,10 @@ +name=Keyword highlighter +version=0.1 +author=MCUdude +maintainer=MCUdude +sentence=Highlights relevant AVR keywords in the Arduino IDE +paragraph= +category=Other +url=https://github.com/MCUdude/MegaCoreX +architectures=megaavr +types=Arduino diff --git a/megaavr/libraries/MegaCoreX/src/AVR_keywords.h b/megaavr/libraries/MegaCoreX/src/AVR_keywords.h new file mode 100644 index 0000000..f3d5868 --- /dev/null +++ b/megaavr/libraries/MegaCoreX/src/AVR_keywords.h @@ -0,0 +1 @@ +// This file causes the Arduino IDE to see AVR_keywords as a valid library diff --git a/megaavr/libraries/Optiboot_flasher/README.md b/megaavr/libraries/Optiboot_flasher/README.md new file mode 100644 index 0000000..9db0f22 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/README.md @@ -0,0 +1,197 @@ +# Optiboot Flash +Two libraries are used to interface with the "write-to-flash" functionality the Optiboot bootloader has. Flash.h/cpp is a high-level library that makes it easy to store strings, variables, structs, etc. to the flash memory and easily retrieve them. optiboot.h/cpp is a low-level read/write library that does the actual reading and writing to flash. If your application needs more storage than the EEPROM can offer, Flash is the library for you. If you're very memory constrained and want to do the heavy lifting yourself, optiboot is the library for you. See the examples of how you can interface with these two libraries. + + +## Flash() +Class constructor for interfacing with the "write-to-flash" functionality. +For arguments has to be present. A reference to the allocated flash space array, the size of the allocated space, a RAM buffer, and its size. + +##### Usage: +```c++ +// Create object 'flash' with flash_space_array and ram_buffer +Flash flash(flash_space_array, sizeof(flash_space_array), ram_buffer, sizeof(ram_buffer)); +``` + + +## Flash[] +Operator overloaded object. This lets you use the object itself to access the RAM buffer. + +##### Usage: +```cpp +uint8_t data = flash[0x00]; // Read data from address 0x00 in the buffer +flash[0x00] = data; // Write the contents of 'data' to address 0x00 +``` + + +## check_writable() +Checks if a bootloader that has "write-to-flash" functionality is present + +##### Usage: +```cpp +bool valid_bootloader = flash.check_writable(); +``` + +##### Returns: +`bool` valid bootloader present + + +## clear_buffer() +Clears the RAM buffer. Sets all values to 0x00 if no parameter is present + +##### Usage: +```cpp +flash.clear_buffer(); // Write all zeros to the RAM buffer +flash.clear:buffer(0xff); // Write all 0xff's to the RAM buffer +``` + +##### Returns: +`void` + + +## read_buffer() +**Alternative to `flash[]`**. Reads a byte from the RAM buffer. + +##### Usage: +```cpp +uint8_t data = flash.read_buffer(0x00); // Read data from place 0x00 in the buffer +uint8_t data = flash.read_buffer(0x40); // Read data from place 0x40 +``` + +##### Returns: +`uint8_t` data in buffer place *N* + + +## write_buffer() +**Alternative to `flash[]`**. Writes a byte to the RAM buffer + +##### Usage: +```cpp +flash.write_buffer(0x00, 'H'); // Write character 'H' to buffer place 0x00 +``` + +##### Returns: +`void` + + +## buffer_size() +Returns the size of the allocated RAM buffer in bytes + +##### Usage: +```cpp +uint16_t allocated_buffer = flash.buffer_size(); +``` + +##### Returns: +`uint16_t` buffer size in bytes + + +## write_page() +Writes the RAM buffer to flash + +##### Usage: +```cpp +flash.write_page(1); // Write buffer to flash page 1 +``` + +##### Returns: +`void` + + +## fetch_page() +Fetches a flash page and stores it in the RAM buffer + +##### Usage: +```cpp +flash.fetch_page(1); // Fetch flash page 1 +``` + +##### Returns: +`void` + + +## fetch_data() +Fetches a given amount of data from flash. Note that the start and stop address is relative to the start of the flash space array. +This means that The span can't be larger than the size of the RAM buffer. + +##### Usage: +```cpp +flash.fetch_data(128, 192); // Read 64 bytes of data from beginning of flash page one (128 bytes flash page size) +``` + +##### Returns: +`void` + + +## put() +Write any data type or object to flash + +##### Usage: +```cpp +float f = 123.456f; +char text[13] = "Hello World!"; +flash.put(0x00, f); // Store float value to flash, starting from address 0 +flash.put(sizeof(float), text); // Store text after the float variable +``` + + +## get() +Read any data type or object from flash + +##### Usage: +```cpp +float f; +char text[13]; +flash.get(0x00, f); // Fetch float variable from flash address 0 and store it to variable f +flash.getsizeof(float), text); // Fetch text after the float variable +``` + + +Optiboot +====== + +## optiboot_check_writable() +Checks if a bootloader that has "write-to-flash" functionality is present + +##### Usage: +```cpp +bool valid_bootloader = optiboot_check_writable(); +``` + +##### Returns: +`bool` valid bootloader present + + +## optiboot_read() +Reads data from the flash memory into a buffer + +##### Usage: +```cpp +optiboot_read(flash_space_array, ram_buffer, page_number, page_start_address, page_stop_address); +``` + +##### Returns: +`void` + + +## optiboot_readPage() +Reads an entire flash page into a buffer + +##### Usage: +```cpp +optiboot_readPage(flash_space_array, ram_buffer, page_number); +``` + +##### Returns: +`void` + + +## optiboot_writePage() +Writes data to a flash page + +##### Usage: +```cpp +optiboot_writePage(flash_space_array, ram_buffer, page_number); +``` + +##### Returns: +`void` diff --git a/megaavr/libraries/Optiboot_flasher/examples/Flash_iterate/Flash_iterate.ino b/megaavr/libraries/Optiboot_flasher/examples/Flash_iterate/Flash_iterate.ino new file mode 100644 index 0000000..a87750b --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/examples/Flash_iterate/Flash_iterate.ino @@ -0,0 +1,104 @@ +/***********************************************************************| +| Optiboot Flash read/write interface library | +| | +| Flash_iterate.ino | +| | +| A library for interfacing with Optiboot Flash's write functionality | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we fill the flash[] buffer with numbers and write it | +| to flash page 0. After a reset or power cycle, we read the values | +| back and prints them to the serial monitor. | +| | +| A RAM buffer (ram_buffer) is required for this library to work. It | +| acts as a memory pool you can read from and write to, and recommended | +| size for this buffer is one flash page, 256/128/64 bytes depending on | +| what chip you're using. ram_buffer[] and flash[] is the exact same | +| array, flash[] is just pointing to ram_buffer[]. | +|***********************************************************************/ + +#include + +// RAM buffer needed by the Flash library. Use flash[] to access the buffer +uint8_t ram_buffer[SPM_PAGESIZE]; + +// Allocate two flash pages for storing data +#define NUMBER_OF_PAGES 2 +const uint8_t flashSpace[SPM_PAGESIZE * NUMBER_OF_PAGES] __attribute__((aligned(SPM_PAGESIZE))) = {}; + +// Flash constructor +Flash flash(flashSpace, sizeof(flashSpace), ram_buffer, sizeof(ram_buffer)); + +void write_data() +{ + // First, make sure there are no content in out buffer + flash.clear_buffer(); + + // Fill buffer with numbers, starting from 0 + for(uint8_t i = 0; i < 64; i++) + flash[i] = i + 100; + + // Write buffer to the first allocated flash page (page 0) + flash.write_page(0); + + // Now let's set a flag on another flash page to indicate that the flash memory contains content + // Here we're treating the object as an array + flash.clear_buffer(); + flash[5] = 'X'; + flash.write_page(1); + + Serial.println("Page 0 written to!\nReset your board to view the contents!\n"); +} + +void read_data() +{ + // Fetch first flash page + flash.fetch_page(0); + + for(uint16_t i = 0; i < flash.buffer_size(); i++) + { + Serial.print("Addr: "); + Serial.print(i); + Serial.print(" \tData: "); + Serial.println(flash[i]); + } +} + +void setup() +{ + delay(2000); + Serial.begin(9600); + + if(!flash.check_writable()) + { + Serial.println("Incompatible or no bootloader present! Please burn correct bootloader"); + while(1); + } + + // Fetch flash page 1, where we may have a flag + flash.fetch_page(1); + + // Check if our flag is present + if(flash[5] == 'X') + { + Serial.println("Content found!"); + read_data(); + } + else + { + Serial.print("Flash page size for this chip: "); + Serial.print(SPM_PAGESIZE); + Serial.print(" bytes\nTotal assigned flash space: "); + Serial.print(NUMBER_OF_PAGES * SPM_PAGESIZE); + Serial.println(" bytes"); + + Serial.println("No content found! Writing new content..."); + write_data(); + } +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Optiboot_flasher/examples/Flash_put_get/Flash_put_get.ino b/megaavr/libraries/Optiboot_flasher/examples/Flash_put_get/Flash_put_get.ino new file mode 100644 index 0000000..927dc7f --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/examples/Flash_put_get/Flash_put_get.ino @@ -0,0 +1,140 @@ +/***********************************************************************| +| Optiboot Flash read/write interface library | +| | +| Flash_get_put.ino | +| | +| A library for interfacing with Optiboot Flash's write functionality | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this example we write a float and a struct to flash page 0, and we | +| set a flag on flash page 1 to indicate there is content to be read | +| afterwards. After a reset we read back the flash content and prints | +| them to the serial monitor. | +| | +| A RAM buffer (ram_buffer) is required for this library to work. It | +| acts as a memory pool you can read from and write to, and recommended | +| size for this buffer is one flash page, 256/128/64 bytes depending on | +| what chip you're using. ram_buffer[] and flash[] is the exact same | +| array, flash[] is just pointing to ram_buffer[]. | +|***********************************************************************/ + +#include + +struct MyObject +{ + float field1; + uint8_t field2; + char name[10]; +}; + +// RAM buffer needed by the Flash library. Use flash[] to access the buffer +uint8_t ram_buffer[SPM_PAGESIZE]; + +// Allocate two flash pages for storing data +#define NUMBER_OF_PAGES 2 +const uint8_t flashSpace[SPM_PAGESIZE * NUMBER_OF_PAGES] __attribute__((aligned(SPM_PAGESIZE))) = {}; + +// Flash constructor +Flash flash(flashSpace, sizeof(flashSpace), ram_buffer, sizeof(ram_buffer)); + +void write_data() +{ + float f = 123.456f; + uint8_t buffer_address = 0; + + // First, make sure there are no content in out buffer + flash.clear_buffer(); + + // One simple call, with the address first and the object second + flash.put(buffer_address, f); + + Serial.println("Written float data type!"); + + // Data to store + MyObject customVar = + { + 3.14f, + 65, + "MCUdude" + }; + + // Move address to the next byte after float 'f' + buffer_address += sizeof(float); + flash.put(buffer_address, customVar); + + // Write buffer to the first allocated flash page (page 0) + flash.write_page(0); + + // Now let's set a flag on another flash page to indicate that the flash memory contains content + // Here we're treating the object as an array + flash.clear_buffer(); + flash[5] = 'X'; + flash.write_page(1); + + Serial.println("Written custom data type!\nReset your board to view the contents!\n"); +} + +void read_data() +{ + Serial.println("Read float from flash: "); + + // Fetch first flash page + flash.fetch_page(0); + + float f = 0.00f; // Variable to store data read from flash + uint8_t buffer_address = 0; // Buffer address to start from + + // Get the float data from flash at position 'buffer_address' + flash.get(buffer_address, f); + Serial.print("The value of f is now: "); + Serial.println(f, 3); + + buffer_address += sizeof(float); // Move address to the next byte after float 'f' + MyObject customVar; // Variable to store custom object read from flash. + + flash.get(buffer_address, customVar); + + Serial.println("Read custom object from flash: "); + Serial.println(customVar.field1); + Serial.println(customVar.field2); + Serial.println(customVar.name); +} + +void setup() +{ + delay(2000); + Serial.begin(9600); + + if(!flash.check_writable()) + { + Serial.println("Incompatible or no bootloader present! Please burn correct bootloader"); + while(1); + } + + // Fetch flash page 1, where we may have a flag + flash.fetch_page(1); + + // Check if our flag is present + if(flash[5] == 'X') + { + Serial.println("Content found!"); + read_data(); + } + else + { + Serial.print("Flash page size for this chip: "); + Serial.print(SPM_PAGESIZE); + Serial.print(" bytes\nTotal assigned flash space: "); + Serial.print(NUMBER_OF_PAGES * SPM_PAGESIZE); + Serial.println(" bytes"); + + Serial.println("No content found! Writing new content..."); + write_data(); + } +} + +void loop() +{ + +} diff --git a/megaavr/libraries/Optiboot_flasher/examples/Read_write_without_buffer/Read_write_without_buffer.ino b/megaavr/libraries/Optiboot_flasher/examples/Read_write_without_buffer/Read_write_without_buffer.ino new file mode 100644 index 0000000..54a8716 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/examples/Read_write_without_buffer/Read_write_without_buffer.ino @@ -0,0 +1,105 @@ +/***********************************************************************| +| Optiboot Flash read/write | +| | +| Read_write_without_buffer.ino | +| | +| A library for interfacing with Optiboot Flash's write functionality | +| Developed in 2021 by MCUdude | +| https://github.com/MCUdude/ | +| | +| In this low-level example we write 16-bit values to one flash page, | +| and 8-bit values to another page. What's different about this | +| example is that we do this without using a RAM buffer where the | +| contents are stored before writing to flash. Instead, the internal, | +| temporary buffer is used. By doing this we reduce RAM usage, but it | +| is not nearly as user friendly as using the Flash library. | +| | +| IMPORTANT THINGS: | +| - All flash content gets erased after each upload cycle | +| - Allocated flash space must be page aligned (it is in this example) | +|***********************************************************************/ + + +#include + + +// Allocate one flash pages for storing data +#define NUMBER_OF_PAGES 2 +const uint8_t flashSpace[SPM_PAGESIZE * NUMBER_OF_PAGES] __attribute__((aligned(SPM_PAGESIZE))) = {}; + + +// Function for writing 16-bit integers to a flash page +void flash_write_int(const uint8_t base_addr[], uint16_t offset_addr, int16_t data) +{ + // Write the 16-bit value to the buffer + optiboot_page_fill((uint16_t)base_addr + offset_addr, (uint16_t)data); + + // Write the buffer to flash when the buffer is full + if ((offset_addr & 0xFF) == (SPM_PAGESIZE - 2)) + optiboot_page_erase_write(); +} + + +// Function to write bytes to a flash page +void flash_write_byte(const uint8_t base_addr[], uint16_t offset_addr, uint8_t data) +{ + // Write the 8-bit value to the buffer + optiboot_page_fill((uint16_t)base_addr + offset_addr, data); + + if ((offset_addr & 0xFF) == (SPM_PAGESIZE - 2)) + optiboot_page_erase_write(); +} + + +// Function to force a flash page write operation +void flash_end_write(uint16_t offset_addr) +{ + // Write the buffer to flash if there are any contents in the buffer + if ((offset_addr & 0xFF) != 0x00) + optiboot_page_erase_write(); +} + + +void setup() +{ + delay(2000); + Serial.begin(9600); + + static uint16_t addr = 0; + + Serial.print("Filling up flash page 0 with 16-bit values...\n"); + // Fill the first flash page (page 0) with 16-bit values (0x100 to 0x01FF) + for(uint8_t data = 0; data < (SPM_PAGESIZE / 2); data++) + { + flash_write_int(flashSpace, addr, data + 0x0100); // Write data + addr += 2; // Increase memory address by two since we're writing 16-bit values + } + // Force an end write in case it hasn't already been done in flash_write_int + flash_end_write(--addr); + + + Serial.print("Filling up flash page 1 with 8-bit values...\n"); + // Fill the second flash page (page 1) with 0-bit values (0x00 to 0x0FF) + for(uint16_t data = 0; data < SPM_PAGESIZE; data++) + { + addr++; // Increase memory address by one since we're writing 8-bit values + flash_write_byte(flashSpace, addr, data); // Write data + } + // Force an end write in case it hasn't already been done in flash_write_byte + flash_end_write(addr); + + + Serial.print("Flash pages filled. Reading back their content.\nPage 0:\n"); + for(uint16_t i = 0; i < SPM_PAGESIZE; i += 2) + Serial.printf("Flash mem addr: 0x%04x, content: 0x%04x\n", flashSpace + i, (pgm_read_byte(flashSpace + i + 1) << 8) + (pgm_read_byte(flashSpace + i))); + + Serial.println(F("\n\nPage 1:")); + for(uint16_t i = 0; i < SPM_PAGESIZE; i++) + Serial.printf("Flash mem addr: 0x%04x, content: 0x%02x\n", flashSpace + SPM_PAGESIZE + i, pgm_read_byte(flashSpace + SPM_PAGESIZE + i)); +} + + +void loop() +{ + +} diff --git a/megaavr/libraries/Optiboot_flasher/examples/Serial_read_write/Serial_read_write.ino b/megaavr/libraries/Optiboot_flasher/examples/Serial_read_write/Serial_read_write.ino new file mode 100644 index 0000000..c2dc370 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/examples/Serial_read_write/Serial_read_write.ino @@ -0,0 +1,240 @@ +/*------------ Optiboot flasher example for the MightyCore -----------------| + | | + | Created May 2016 by MCUdude, https://github.com/MCUdude | + | Based on the work done by Marek Wodzinski, https://github.com/majekw | + | Released to public domain | + | | + | This is example how to use optiboot.h together with Optiboot | + | bootloader to write to FLASH memory by application code. | + | | + | IMPORTANT THINGS: | + | - All flash content gets erased after each upload cycle | + | - Buffer must be page aligned (see declaration of flash_buffer) | + | - Interrupts must be disabled during SPM | + | - Writing to EEPROM destroys temporary buffer | + | - You can write only once into one location of temporary buffer | + | - Only safely and always working sequence is erase-fill-write | + | - If you want to do fill-erase-write, you must put code in NRWW | + | and pass data!=0 for erase. It's not easy, but possible. | + | | + | WRITE SEQUENCE - OPTION 1 (used in this example) | + | 1. Erase page by optiboot_page_erase | + | 2. Write contents of page into temporary buffer by optiboot_page_fill | + | 3. Write temporary buffer to FLASH by optiboot_page_write | + | | + | WRITE SEQUENCE - OPTION 2 (works only for code in NRWW) | + | 1. Write contents of page into temporary buffer by optiboot_page_fill | + | 2. Erase page by optiboot_page_erase (set data to NOT zero) | + | 3. Write temporary buffer to FLASH by optiboot_page_write | + |-------------------------------------------------------------------------*/ + +// optiboot.h contains the functions that lets you read to +// and write from the flash memory +#include + +// Define the number of pages you want to write to here (limited by flash size) +#define NUMBER_OF_PAGES 8 + +// Define your termination and blank character here +const char terminationChar = '@'; + +// The temporary data (data that's read or is about to get written) is stored here +uint8_t ramBuffer[SPM_PAGESIZE]; + +// This array allocates the space you'll be able to write to +const uint8_t flashSpace[SPM_PAGESIZE * NUMBER_OF_PAGES] __attribute__ (( aligned(SPM_PAGESIZE) )) = { + "This some default content stored on page one" +}; + + +void setup() +{ + delay(1000); + // Initialize serial + Serial.begin(9600); + + if(!optiboot_check_writable()) + { + Serial.println("Incompatible or no bootloader present! Please burn the correct bootloader"); + while(1); + } +} + + +void loop() +{ + // Print main menu + Serial.println(); + Serial.println("|------------------------------------------------|"); + Serial.println("| Welcome to the Optiboot flash writer example! |"); + Serial.print("| Each flash page is "); + Serial.print(SPM_PAGESIZE); + Serial.println(" bytes long. |"); + Serial.print("| There are "); + Serial.print(NUMBER_OF_PAGES); + Serial.println(" pages that can be read/written to. |"); + Serial.print("| Total assigned flash space: "); + Serial.print(NUMBER_OF_PAGES * SPM_PAGESIZE); + Serial.println(" bytes. |"); + Serial.println("| Change the NUMBER_OF_PAGES constant to |"); + Serial.println("| increase or decrease this number. |"); + Serial.println("| |"); + Serial.println("| What do you want to do? |"); + Serial.println("| 1. Show current flash content |"); + Serial.println("| 2. Write to flash memory |"); + Serial.println("|------------------------------------------------|"); + + // Static variables + static uint8_t charBuffer; + static char menuOption; + static uint16_t pageNumber; + static char returnToMenu; + + // Get menu option from the serial monitor + do + { + while(!Serial.available()); + menuOption = Serial.read(); + if(menuOption != '1' && menuOption != '2') + Serial.print("\nPlease enter a valid option! "); + } + while(menuOption != '1' && menuOption != '2'); + + Serial.print("\nOption "); + Serial.print(menuOption); + Serial.println(" selected."); + + + + // Read flash option selected + if(menuOption == '1') + { + Serial.print("Which page number do you want to read? Page 0 to "); + Serial.print(NUMBER_OF_PAGES - 1); + Serial.print(", Page "); + Serial.print(NUMBER_OF_PAGES); + Serial.print(" to show all pages: "); + + //Get page number from the serial monitor + do + { + while(!Serial.available()); + pageNumber = Serial.read() - 0x30; + if(pageNumber > NUMBER_OF_PAGES) + { + Serial.print("\nPlease enter a valid page between 0 and "); + Serial.print(NUMBER_OF_PAGES - 1); + Serial.println(". The number of pages can be extended by changing NUMBER_OF_PAGES constant"); + } + } + while(pageNumber > NUMBER_OF_PAGES); + + if(pageNumber <= NUMBER_OF_PAGES) + Serial.println(pageNumber); + + // READ SELECTED PAGE AND STORE THE CONTENT IN THE ramBuffer ARRAY + // flash_buffer is where the data is stored (contains the memory addresses) + // ramBuffer is where the data gets stored after reading from flash + // pageNumber is the page the data is read from + + uint8_t pageFirst = 0; + uint8_t pageLast = NUMBER_OF_PAGES; + + if(pageNumber != NUMBER_OF_PAGES) + { + pageFirst = pageNumber; + pageLast = pageNumber; + } + + for(uint8_t page = pageFirst; page < pageLast; page++) + { + optiboot_readPage(flashSpace, ramBuffer, page); + Serial.print("Page "); + Serial.print(page); + Serial.print(": "); + for(uint16_t i = 0; i < sizeof(ramBuffer); i++) + { + if(ramBuffer[i] == 0x00 || ramBuffer[i] == 0xff) + Serial.write('.'); + else + Serial.write(ramBuffer[i]); + } + Serial.println(""); + } + } // End of flash read option + + + + // Write flash option selected + else if(menuOption == '2') + { + // Clear pageNumber + pageNumber = 0xff; + + //Get page number from the serial monitor + Serial.print("\nWhich page do you want to write to? Page: "); + do + { + while(!Serial.available()); + pageNumber = Serial.read() - 0x30; + if(pageNumber > NUMBER_OF_PAGES - 1) + { + Serial.print("\nPlease enter a valid page between 0 and "); + Serial.print(NUMBER_OF_PAGES - 1); + Serial.println(". The number of pages can be extended by changing NUMBER_OF_PAGES constant"); + } + } + while(pageNumber >= NUMBER_OF_PAGES); + Serial.println(pageNumber); + + // Print prompt to enter some new characters to write to flash + Serial.print("Please type the characters you want to store (max "); + Serial.print(SPM_PAGESIZE); + Serial.println(" characters)"); + Serial.print("End the line by sending the '"); + Serial.write(terminationChar); + Serial.println("' character:"); + + // Get all characters from the serial monitor and store it to the ramBuffer + memset(ramBuffer, 0, sizeof(ramBuffer)); + uint16_t counter = 0; + while (counter < SPM_PAGESIZE && charBuffer != terminationChar) + { + if(Serial.available() > 0) + { + charBuffer = Serial.read(); // read character from serial + if(charBuffer != terminationChar) + { + Serial.write(charBuffer); // echo character back + ramBuffer[counter] = charBuffer; + counter++; + } + } + } + charBuffer = 0; + Serial.println("\n\nAll chars received \nWriting to flash..."); + + // WRITE RECEIVED DATA TO THE CURRENT FLASH PAGE + // flash_buffer is where the data is stored (contains the memory addresses) + // ramBuffer contains the data that's going to be stored in the flash + // pageNumber is the page the data is written to + optiboot_writePage(flashSpace, ramBuffer, pageNumber); + + Serial.println("Writing finished. You can now reset or power cycle the board and check for new contents!"); + } // End of flash write option + + + + //Return to the main menu if 'm' is sent + Serial.println("\ntype the character 'm' to return to to the main menu"); + do + { + while(!Serial.available()); + returnToMenu = Serial.read(); + if(returnToMenu != 'm') + Serial.print("\nPlease type a valid character! "); + } + while(returnToMenu != 'm'); + returnToMenu = 0; + +} // End of loop diff --git a/megaavr/libraries/Optiboot_flasher/keywords.txt b/megaavr/libraries/Optiboot_flasher/keywords.txt new file mode 100644 index 0000000..87fae6a --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/keywords.txt @@ -0,0 +1,40 @@ +############################################# +# Syntax Coloring Map For Flash and Optiboot +############################################# + +############################################# +# Datatypes (KEYWORD1) +############################################# + +Flash KEYWORD1 + +############################################# +# Methods and Functions (KEYWORD2) +############################################# + +# Flash class +set_far_address KEYWORD2 +check_writable KEYWORD2 +clear_buffer KEYWORD2 +read_buffer KEYWORD2 +write_buffer KEYWORD2 +buffer_size KEYWORD2 +write_page KEYWORD2 +fetch_page KEYWORD2 +fetch_data KEYWORD2 +get KEYWORD2 +put KEYWORD2 + +# Optiboot +do_spm_cli KEYWORD2 +optiboot_page_erase KEYWORD2 +optiboot_page_fill KEYWORD2 +optiboot_page_write KEYWORD2 +optiboot_readPage KEYWORD2 +optiboot_read KEYWORD2 +optiboot_writePage KEYWORD2 +optiboot_page_erase_write KEYWORD2 + +############################################ +# Constants (LITERAL1) +############################################ diff --git a/megaavr/libraries/Optiboot_flasher/library.properties b/megaavr/libraries/Optiboot_flasher/library.properties new file mode 100644 index 0000000..122faed --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/library.properties @@ -0,0 +1,11 @@ +name=Optiboot Flash +version=2.0 +author=majekw/MCUdude +maintainer=MCUdude +sentence=Read and write contents to the FLASH memory +paragraph= +category=Data Storage +url= +architectures=megaavr +types=Arduino + diff --git a/megaavr/libraries/Optiboot_flasher/src/Flash.cpp b/megaavr/libraries/Optiboot_flasher/src/Flash.cpp new file mode 100644 index 0000000..4fd09a6 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/src/Flash.cpp @@ -0,0 +1,182 @@ +#include "Flash.h" + +/** + * @brief Construct a new Flash:: Flash object + * + * @param flash_array the flash space array the library will utilize + * @param flash_array_size total size of the flash space array in bytes + * @param ram_array the RAM buffer array the library will utilize + * @param ram_array_size total size of the ram array in bytes. This is an + * optional parameter, and defaults to SPM_PAGESIZE, the flash page size if not + * present + */ +Flash::Flash(const uint8_t *flash_array, const uint16_t flash_array_size, uint8_t *ram_array, const uint16_t ram_array_size) + : _flash_array(flash_array), + _flash_array_size(flash_array_size), + _ram_array(ram_array), + _ram_array_size(ram_array_size) +{ +} + +/** + * @brief Lets you use the created object as a placeholder for the + * passed RAM buffer + * + * @param index Array index + * @return uint8_t& + */ +uint8_t& Flash::operator[](int16_t index) +{ + return _ram_array[index]; +} + + +#ifdef RAMPZ +/** + * @brief If you have allocated flash space in the far progmem, above 64kiB, + * you can't just pass your flash space array to the constructor because a + * 16-bit pointer isn't large enough. You therefore have to specify the address + * with this function. + * + * @param address The start address of the allocated flash space. + * You can get the address by using the pgm_get_far_address macro: + * set_far_address(pgm_get_far_address(flashSpace)) + */ +void Flash::set_far_address(uint32_t address) +{ + _far_flash_array_addr = address; +} +#endif + +/** + * @brief Checks if the microcontroller contains a bootloader that has flash + * writing capabilities. It does so by checking if a spesific number is placed + * at the very end of the flash memory + * + * @return true if compatible bootloader is present + * @return false if incompatible or no bootloader is present + */ +bool Flash::check_writable() +{ + return optiboot_check_writable(); +} + +/** + * @brief Clears the RAM buffer + * + * @param fill optional parameter to set what content the buffer will be + * filled with. Defaults to 0x00 if not present + */ +void Flash::clear_buffer(uint8_t fill) +{ + memset(_ram_array, fill, sizeof(_ram_array_size)); +} + +/** + * @brief Wrapper function for the RAM buffer. Lets you read a byte from a + * given memory location + * + * @param index memory address + * @return uint8_t 8-bit value stored in this address space + */ +uint8_t Flash::read_buffer(uint8_t index) +{ + return _ram_array[index]; +} + +/** + * @brief Wrapper function for the RAM buffer. Lets you write a byte to a given + * memory address + * + * @param index memory address + * @param value 8-bit value to write to the memory location + */ +void Flash::write_buffer(uint8_t index, uint8_t value) +{ + _ram_array[index] = value; +} + +/** + * @brief Function that returns the size of the allocated RAM buffer + * + * @return uint16_t RAM buffer size in bytes + */ +uint16_t Flash::buffer_size() +{ + return _ram_array_size; +} + +/** + * @brief Writes the current content of the RAM buffer to a flash page + * + * @param flash_page_number page number to write the buffer to + */ +void Flash::write_page(uint16_t flash_page_number) +{ + // For devices with 128kiB or more, and data is stored in far progmem + #ifdef RAMPZ + if(_far_flash_array_addr != 0x0000) + { + optiboot_writePage(_far_flash_array_addr, _ram_array, flash_page_number); + } + // For devices with where flash space is allocated in near progmem, <64kiB + else + #endif + { + optiboot_writePage(_flash_array, _ram_array, flash_page_number); + } +} + +/** + * @brief Reads a flash page and write its content to the RAM buffer + * + * @param flash_page_number page number to read from + */ +void Flash::fetch_page(uint16_t flash_page_number) +{ + // For devices with 128kiB or more, and data is stored in far progmem + #ifdef RAMPZ + if(_far_flash_array_addr != 0x0000) + { + optiboot_read(_far_flash_array_addr, _ram_array, flash_page_number, 0, _ram_array_size); + } + // For devices with where flash space is allocated in near progmem, <64kiB + else + #endif + { + optiboot_read(_flash_array, _ram_array, flash_page_number, 0, _ram_array_size); + } +} + +/** + * @brief Read bytes from the flash memory and write its content to the RAM + * buffer. You can read as many or as few bytes as you want. There are no page + * numbers here, the start address represents the address number from the start + * of the allocated space. This means that if you want to read 10 bytes from + * page two you set the start address to 512 and stop address to 522. Note that + * the span between the start and stop address can't be larger than the size of + * the RAM buffer. + * + * @param start_address address to start reading from + * @param stop_address address where we stop reading at + */ +void Flash::fetch_data(uint16_t start_address, uint16_t stop_address) +{ + uint16_t end_address; + if(stop_address - start_address > _ram_array_size) + end_address = _ram_array_size; + else + end_address = stop_address; + + #ifdef RAMPZ + if(_far_flash_array_addr != 0x0000) + { + optiboot_read(_far_flash_array_addr, _ram_array, 0, start_address, end_address); + } + // For devices with where flash space is allocated in near progmem, <64kiB + else + #endif + { + optiboot_read(_flash_array, _ram_array, 0, start_address, end_address); + } +} diff --git a/megaavr/libraries/Optiboot_flasher/src/Flash.h b/megaavr/libraries/Optiboot_flasher/src/Flash.h new file mode 100644 index 0000000..9a3f6c7 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/src/Flash.h @@ -0,0 +1,52 @@ +#ifndef FLASH_H +#define FLASH_H + +#include +#include + +class Flash +{ + public: + Flash(const uint8_t *flash_array, const uint16_t flash_array_size, uint8_t *ram_array, const uint16_t ram_array_size = SPM_PAGESIZE); + #ifdef RAMPZ + void set_far_address(uint32_t address); + #endif + bool check_writable(); + void clear_buffer(uint8_t fill = 0x00); + uint8_t read_buffer(uint8_t index); + void write_buffer(uint8_t index, uint8_t value); + uint16_t buffer_size(); + void write_page(uint16_t flash_page_number); + void fetch_page(uint16_t flash_page_number); + void fetch_data(uint16_t start_address, uint16_t stop_address); + + // Operator overload to be able to read and write directly to the RAM array from a byte level + uint8_t& operator[] (int16_t index); + + // Template function to 'put' objects in RAM array + template const T &put(uint16_t idx, const T &t) + { + const uint8_t *ptr = (const uint8_t*) &t; + for(uint16_t count = 0; count < sizeof(T); count++) + _ram_array[idx + count] = *ptr++; + return t; + } + + // Template function to 'get' objects from the RAM array + template T &get(uint16_t idx, T &t) + { + uint8_t *ptr = (uint8_t*) &t; + for(uint16_t count = 0; count < sizeof(T); count++) + *ptr++ = _ram_array[idx + count]; + return t; + } + + private: + const uint8_t *_flash_array; // Pointer to allocated flash space + uint32_t _far_flash_array_addr; // Address to far memory location if allocated space is above 64kiB + const uint16_t _flash_array_size; // Size of a flash page in bytes (64, 128 or 256 bytes) + uint8_t *_ram_array; // Pointer to allocated RAM array + const uint16_t _ram_array_size; // Size of allocated RAM array +}; + +#endif diff --git a/megaavr/libraries/Optiboot_flasher/src/optiboot.cpp b/megaavr/libraries/Optiboot_flasher/src/optiboot.cpp new file mode 100755 index 0000000..122b515 --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/src/optiboot.cpp @@ -0,0 +1,165 @@ +#include "optiboot.h" + + +/* + * The same as do_nvmctrl but with disable/restore interrupts state + * required to succesfull execution + * + */ +void do_nvmctrl_cli(optiboot_addr_t address, uint8_t command, uint16_t data) +{ + uint8_t sreg_save; + + sreg_save = SREG; // Save old SREG value + asm volatile("cli"); // Disable interrupts + do_nvmctrl(address, command, data); // 16 bit address - no problems to pass directly + SREG = sreg_save; // Restore last interrupts state +} + + +/** + * @brief Checks if the microcontroller contains a bootloader that has flash + * writing capabilities. It does so by checking if a spesific number is placed + * at the end of the bootloader section + * + * @return true if compatible bootloader is present + * @return false if incompatible or no bootloader is present + */ +bool optiboot_check_writable() +{ + uint8_t content = pgm_read_byte(0x1FF); + + if(content == 9) + return true; + else + return false; +} + + +/** + * @brief Erase flash page + * + * @param address flash page start address + */ +void optiboot_page_erase(optiboot_addr_t address) +{ + // Set page by writing to address + optiboot_page_fill(address, (uint8_t)0xFF); + do_nvmctrl_cli(0, NVMCTRL_CMD_PAGEERASE_gc, 0); // do actual erase +} + + +/** + * @brief Writes an 8-bit value to a temporary, internal buffer. Note that + * this temporary buffer gets destroyed if you read or write to EEPROM. It's + * therefore important that the buffer gets written to flash before doing + * anything EEPROM related. Also note that you can write only once to one + * location in the temporary buffer without erasing it first, which happens + * after a flash page erase or write. + * + * @param address address where to write the 8-bit data + * @param data data to write + */ +void optiboot_page_fill(optiboot_addr_t address, uint8_t data) +{ + do_nvmctrl(address, NVMCTRL_CMD_COPY_gc, data); +} + + +/** + * @brief Writes a word/16-bit value to a temporary, internal buffer. Note that + * this temporary buffer gets destroyed if you read or write to EEPROM. It's + * therefore important that the buffer gets written to flash before doing + * anything EEPROM related. Also note that you can write only once to one + * location in the temporary buffer without erasing it first, which happens + * after a flash page erase or write. + * + * @param address address where to write the 16-bit data + * @param data data to write + */ +void optiboot_page_fill(optiboot_addr_t address, uint16_t data) +{ + optiboot_page_fill(address, (uint8_t)(data & 0xFF)); + optiboot_page_fill(++address, (uint8_t)(data >> 8)); +} + + +/** + * @brief Write the temporary, internal buffer to flash + * + */ +void optiboot_page_erase_write() +{ + do_nvmctrl_cli(0, NVMCTRL_CMD_PAGEERASEWRITE_gc, 0); +} + + +/** + * @brief Write the temporary, internal buffer to flash + * + * @param address flash page start address + */ +void optiboot_page_write(optiboot_addr_t address) +{ + do_nvmctrl_cli(address, NVMCTRL_CMD_PAGEWRITE_gc, 0); +} + + +// Higher level functions for reading and writing from flash + + +/** + * @brief Read bytes from a given page and futher out in memory. It will + * continue to fill the storage_array until the stop_address is reached. Note + * that this function will only work for data stored in near progmem, below + * 64kiB. + * + * @param allocated_flash_space the allocated flash space to read from + * @param storage_array the array to store the flash content to + * @param page_number the flash page number to start reading from + * @param start_address the address to start reading from, relative to the flash page number + * @param stop_address the address where we stop reading, relative to the flash page number + */ +void optiboot_read(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page_number, uint16_t start_address, uint16_t stop_address) +{ + for(uint16_t j = start_address; j < stop_address; j++) + { + uint8_t read_character = allocated_flash_space[j + SPM_PAGESIZE * (page_number)]; + storage_array[j - start_address] = read_character; + } +} + + +/** + * @brief Reads an entire flash page and stores the content in storage_array. + * Note that this function will only work for data stored in near progmem, + * below 64kiB. + * + * @param allocated_flash_space the allocated flash space to read from + * @param storage_array the array to store the flash content to + * @param page_number the flash page number to read from + */ +void optiboot_readPage(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page_number) +{ + optiboot_read(allocated_flash_space, storage_array, page_number, 0, SPM_PAGESIZE); +} + + +/** + * @brief Writes the content of data_to_store to a flash page. + * Note that this function will only work for data stored in near progmem, + * below 64kiB. + * + * @param allocated_flash_space the allocated flash space to read from + * @param data_to_store an array that holds the data to store + * @param page_number the flash page number to write to + */ +void optiboot_writePage(const uint8_t allocated_flash_space[], uint8_t data_to_store[], uint16_t page_number) +{ + // Copy ram buffer to temporary flash buffer + for(uint16_t i = 0; i < SPM_PAGESIZE; i++) + optiboot_page_fill((optiboot_addr_t)&allocated_flash_space[i + SPM_PAGESIZE * page_number], data_to_store[i]); + + // Erase and then write page + optiboot_page_erase_write(); +} diff --git a/megaavr/libraries/Optiboot_flasher/src/optiboot.h b/megaavr/libraries/Optiboot_flasher/src/optiboot.h new file mode 100755 index 0000000..e3999ec --- /dev/null +++ b/megaavr/libraries/Optiboot_flasher/src/optiboot.h @@ -0,0 +1,64 @@ +/*------------------------ Optiboot header file ---------------------------| +| | +| June 2015 by Marek Wodzinski, https://github.com/majekw | +| Modified June 2016 by MCUdude, https://github.com/MCUdude | +| Revised March 2021 by MCUdude | +| Released to public domain | +| | +| This header file gives possibility to use SPM instruction | +| from Optiboot bootloader memory. | +| | +| There are 5 convenient functions available here: | +| * optiboot_page_erase - to erase a FLASH page | +| * optiboot_page_fill - to put words into temporary buffer | +| * optiboot_page_write - to write contents of temporary buffer into FLASH | +| * optiboot_readPage - higher level function to read a flash page and | +| store it in an array | +| * optiboot_writePage - higher level function to write content to | +| a flash page | +| | +| For some hardcore users, you could use 'do_spm' as raw entry to | +| bootloader spm function. | +|-------------------------------------------------------------------------*/ + + +#ifndef OPTIBOOT_H +#define OPTIBOOT_H + +#include +#include + +#define NVMCTRL_CMD_COPY_gc (NVMCTRL_CMD_gm + 1) // one beyond existing commands. +#define SPM_PAGESIZE (PROGMEM_PAGE_SIZE) + +/* + * Main 'magic' function - enter to bootloader do_spm function + * + * address - address to write (in bytes) but must be even number + * command - one of __BOOT_PAGE_WRITE, __BOOT_PAGE_ERASE or __BOOT_PAGE_FILL + * data - data to write in __BOOT_PAGE_FILL. In __BOOT_PAGE_ERASE or + * __BOOT_PAGE_WRITE it control if boot_rww_enable is run + * (0 = run, !0 = skip running boot_rww_enable) + * + */ + +// 'typedef' (in following line) and 'const' (few lines below) are a way to define external function at some arbitrary address +typedef void (*do_spm_t)(uint16_t address, uint8_t command, uint16_t data); +typedef uint16_t optiboot_addr_t; + +// Mega0/xTiny/etc. Bootloader is in low memory. +const do_spm_t do_nvmctrl = (do_spm_t)((PROGMEM_START + 2) >> 1); + + +void do_nvmctrl_cli(optiboot_addr_t address, uint8_t command, uint16_t data); +bool optiboot_check_writable(); +void optiboot_page_erase(optiboot_addr_t address); +void optiboot_page_fill(optiboot_addr_t address, uint8_t data); +void optiboot_page_fill(optiboot_addr_t address, uint16_t data); +void optiboot_page_erase_write(); +void optiboot_page_write(optiboot_addr_t address); +void optiboot_read(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page_number, uint16_t start_address, uint16_t stop_address); +void optiboot_readPage(const uint8_t allocated_flash_space[], uint8_t storage_array[], uint16_t page_number); +void optiboot_writePage(const uint8_t allocated_flash_space[], uint8_t data_to_store[], uint16_t page_number); + +#endif diff --git a/megaavr/libraries/SD/README.adoc b/megaavr/libraries/SD/README.adoc new file mode 100755 index 0000000..fb3ed03 --- /dev/null +++ b/megaavr/libraries/SD/README.adoc @@ -0,0 +1,26 @@ += SD Library for Arduino = + +image:https://travis-ci.org/arduino-libraries/SD.svg?branch=master[Build Status, link=https://travis-ci.org/arduino-libraries/SD] + +The SD library allows for reading from and writing to SD cards. + +For more information about this library please visit us at +http://www.arduino.cc/en/Reference/SD + +== License == + + Copyright (C) 2009 by William Greiman +Copyright (c) 2010 SparkFun Electronics + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/megaavr/libraries/SD/examples/CardInfo/CardInfo.ino b/megaavr/libraries/SD/examples/CardInfo/CardInfo.ino new file mode 100755 index 0000000..c48dcbd --- /dev/null +++ b/megaavr/libraries/SD/examples/CardInfo/CardInfo.ino @@ -0,0 +1,117 @@ +/* + SD card test + + This example shows how use the utility libraries on which the' + SD library is based in order to get info about your SD card. + Very useful for testing a card when you're not sure whether its working or not. + Pin numbers reflect the default SPI pins for Uno and Nano models + The circuit: + SD card attached to SPI bus as follows: + ** SDO - pin 11 on Arduino Uno/Duemilanove/Diecimila + ** SDI - pin 12 on Arduino Uno/Duemilanove/Diecimila + ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + created 28 Mar 2011 + by Limor Fried + modified 24 July 2020 + by Tom Igoe +*/ +// include the SD library: +#include +#include + +// set up variables using the SD utility library functions: +Sd2Card card; +SdVolume volume; +SdFile root; + +// change this to match your SD shield or module; +// Default SPI on Uno and Nano: pin 10 +// Arduino Ethernet shield: pin 4 +// Adafruit SD shields and modules: pin 10 +// Sparkfun SD shield: pin 8 +// MKRZero SD: SDCARD_SS_PIN +const int chipSelect = 10; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + while (!Serial) { + ; // wait for serial port to connect. Needed for native USB port only + } + + + Serial.print("\nInitializing SD card..."); + + // we'll use the initialization code from the utility libraries + // since we're just testing if the card is working! + if (!card.init(SPI_HALF_SPEED, chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("* is a card inserted?"); + Serial.println("* is your wiring correct?"); + Serial.println("* did you change the chipSelect pin to match your shield or module?"); + while (1); + } else { + Serial.println("Wiring is correct and a card is present."); + } + + // print the type of card + Serial.println(); + Serial.print("Card type: "); + switch (card.type()) { + case SD_CARD_TYPE_SD1: + Serial.println("SD1"); + break; + case SD_CARD_TYPE_SD2: + Serial.println("SD2"); + break; + case SD_CARD_TYPE_SDHC: + Serial.println("SDHC"); + break; + default: + Serial.println("Unknown"); + } + + // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32 + if (!volume.init(card)) { + Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card"); + while (1); + } + + Serial.print("Clusters: "); + Serial.println(volume.clusterCount()); + Serial.print("Blocks x Cluster: "); + Serial.println(volume.blocksPerCluster()); + + Serial.print("Total Blocks: "); + Serial.println(volume.blocksPerCluster() * volume.clusterCount()); + Serial.println(); + + // print the type and size of the first FAT-type volume + uint32_t volumesize; + Serial.print("Volume type is: FAT"); + Serial.println(volume.fatType(), DEC); + + volumesize = volume.blocksPerCluster(); // clusters are collections of blocks + volumesize *= volume.clusterCount(); // we'll have a lot of clusters + volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB) + Serial.print("Volume size (Kb): "); + Serial.println(volumesize); + Serial.print("Volume size (Mb): "); + volumesize /= 1024; + Serial.println(volumesize); + Serial.print("Volume size (Gb): "); + Serial.println((float)volumesize / 1024.0); + + Serial.println("\nFiles found on the card (name, date and size in bytes): "); + root.openRoot(volume); + + // list all files in the card with date and size + root.ls(LS_R | LS_DATE | LS_SIZE); + root.close(); +} + +void loop(void) { +} diff --git a/megaavr/libraries/SD/examples/Datalogger/Datalogger.ino b/megaavr/libraries/SD/examples/Datalogger/Datalogger.ino new file mode 100755 index 0000000..f265b76 --- /dev/null +++ b/megaavr/libraries/SD/examples/Datalogger/Datalogger.ino @@ -0,0 +1,78 @@ +/* + SD card datalogger + + This example shows how to log data from three analog sensors + to an SD card using the SD library. Pin numbers reflect the default + SPI pins for Uno and Nano models + + The circuit: + analog sensors on analog ins 0, 1, and 2 + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + created 24 Nov 2010 + modified 24 July 2020 + by Tom Igoe + + This example code is in the public domain. + +*/ + +#include +#include + +const int chipSelect = 10; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // wait for Serial Monitor to connect. Needed for native USB port boards only: + while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("1. is a card inserted?"); + Serial.println("2. is your wiring correct?"); + Serial.println("3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); + while (true); + } + + Serial.println("initialization done."); +} + +void loop() { + // make a string for assembling the data to log: + String dataString = ""; + + // read three sensors and append to the string: + for (int analogPin = 0; analogPin < 3; analogPin++) { + int sensor = analogRead(analogPin); + dataString += String(sensor); + if (analogPin < 2) { + dataString += ","; + } + } + + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + File dataFile = SD.open("datalog.txt", FILE_WRITE); + + // if the file is available, write to it: + if (dataFile) { + dataFile.println(dataString); + dataFile.close(); + // print to the serial port too: + Serial.println(dataString); + } + // if the file isn't open, pop up an error: + else { + Serial.println("error opening datalog.txt"); + } +} diff --git a/megaavr/libraries/SD/examples/DumpFile/DumpFile.ino b/megaavr/libraries/SD/examples/DumpFile/DumpFile.ino new file mode 100755 index 0000000..49f14d9 --- /dev/null +++ b/megaavr/libraries/SD/examples/DumpFile/DumpFile.ino @@ -0,0 +1,64 @@ +/* + SD card file dump + + This example shows how to read a file from the SD card using the + SD library and send it over the serial port. + Pin numbers reflect the default SPI pins for Uno and Nano models. + + The circuit: + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + created 22 December 2010 + by Limor Fried + modified 9 Apr 2012 + by Tom Igoe + + This example code is in the public domain. +*/ +#include + +const int chipSelect = 10; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // wait for Serial Monitor to connect. Needed for native USB port boards only: + while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("1. is a card inserted?"); + Serial.println("2. is your wiring correct?"); + Serial.println("3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); + while (true); + } + + Serial.println("initialization done."); + + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + File dataFile = SD.open("datalog.txt"); + + // if the file is available, write to it: + if (dataFile) { + while (dataFile.available()) { + Serial.write(dataFile.read()); + } + dataFile.close(); + } + // if the file isn't open, pop up an error: + else { + Serial.println("error opening datalog.txt"); + } +} + +void loop() { +} diff --git a/megaavr/libraries/SD/examples/Files/Files.ino b/megaavr/libraries/SD/examples/Files/Files.ino new file mode 100755 index 0000000..e79aae5 --- /dev/null +++ b/megaavr/libraries/SD/examples/Files/Files.ino @@ -0,0 +1,72 @@ +/* + SD card basic file example + + This example shows how to create and destroy an SD card file + The circuit. Pin numbers reflect the default + SPI pins for Uno and Nano models: + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + + created Nov 2010 + by David A. Mellis + modified 24 July 2020 + by Tom Igoe + + This example code is in the public domain. +*/ +#include + +const int chipSelect = 10; +File myFile; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // wait for Serial Monitor to connect. Needed for native USB port boards only: +while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(10)) { + Serial.println("initialization failed!"); + while (1); + } + Serial.println("initialization done."); + + if (SD.exists("example.txt")) { + Serial.println("example.txt exists."); + } else { + Serial.println("example.txt doesn't exist."); + } + + // open a new file and immediately close it: + Serial.println("Creating example.txt..."); + myFile = SD.open("example.txt", FILE_WRITE); + myFile.close(); + + // Check to see if the file exists: + if (SD.exists("example.txt")) { + Serial.println("example.txt exists."); + } else { + Serial.println("example.txt doesn't exist."); + } + + // delete the file: + Serial.println("Removing example.txt..."); + SD.remove("example.txt"); + + if (SD.exists("example.txt")) { + Serial.println("example.txt exists."); + } else { + Serial.println("example.txt doesn't exist."); + } +} + +void loop() { + // nothing happens after setup finishes. +} diff --git a/megaavr/libraries/SD/examples/NonBlockingWrite/NonBlockingWrite.ino b/megaavr/libraries/SD/examples/NonBlockingWrite/NonBlockingWrite.ino new file mode 100755 index 0000000..d7b785f --- /dev/null +++ b/megaavr/libraries/SD/examples/NonBlockingWrite/NonBlockingWrite.ino @@ -0,0 +1,117 @@ +/* + Non-blocking Write + + This example demonstrates how to perform non-blocking writes + to a file on a SD card. The file will contain the current millis() + value every 10ms. If the SD card is busy, the data will be dataBuffered + in order to not block the sketch. + + If data is successfully written, the built in LED will flash. After a few + seconds, check the card for a file called datalog.txt + + NOTE: myFile.availableForWrite() will automatically sync the + file contents as needed. You may lose some unsynced data + still if myFile.sync() or myFile.close() is not called. + + Pin numbers reflect the default SPI pins for Uno and Nano models + Updated for clarity and uniformity with other examples + + The circuit: + analog sensors on analog ins 0, 1, and 2 + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + modified 24 July 2020 + by Tom Igoe + + This example code is in the public domain. +*/ +#include + +const int chipSelect = 10; + +// file name to use for writing +const char filename[] = "datalog.txt"; + +// File object to represent file +File myFile; +// string to buffer output +String dataBuffer; +// last time data was written to card: +unsigned long lastMillis = 0; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // reserve 1kB for String used as a dataBuffer + dataBuffer.reserve(1024); + + // set LED pin to output, used to blink when writing + pinMode(LED_BUILTIN, OUTPUT); + + // wait for Serial Monitor to connect. Needed for native USB port boards only: + while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("1. is a card inserted?"); + Serial.println("2. is your wiring correct?"); + Serial.println("3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); + while (true); + } + + Serial.println("initialization done."); + + // If you want to start from an empty file, + // uncomment the next line: + // SD.remove(filename); + // try to open the file for writing + + myFile = SD.open(filename, FILE_WRITE); + if (!myFile) { + Serial.print("error opening "); + Serial.println(filename); + while (true); + } + + // add some new lines to start + myFile.println(); + myFile.println("Hello World!"); + Serial.println("Starting to write to file..."); +} + +void loop() { + // check if it's been over 10 ms since the last line added + unsigned long now = millis(); + if ((now - lastMillis) >= 10) { + // add a new line to the dataBuffer + dataBuffer += "Hello "; + dataBuffer += now; + dataBuffer += "\r\n"; + // print the buffer length. This will change depending on when + // data is actually written to the SD card file: + Serial.print("Unsaved data buffer length (in bytes): "); + Serial.println(dataBuffer.length()); + // note the time that the last line was added to the string + lastMillis = now; + } + + // check if the SD card is available to write data without blocking + // and if the dataBuffered data is enough for the full chunk size + unsigned int chunkSize = myFile.availableForWrite(); + if (chunkSize && dataBuffer.length() >= chunkSize) { + // write to file and blink LED + digitalWrite(LED_BUILTIN, HIGH); + myFile.write(dataBuffer.c_str(), chunkSize); + digitalWrite(LED_BUILTIN, LOW); + // remove written data from dataBuffer + dataBuffer.remove(0, chunkSize); + } +} diff --git a/megaavr/libraries/SD/examples/ReadWrite/ReadWrite.ino b/megaavr/libraries/SD/examples/ReadWrite/ReadWrite.ino new file mode 100755 index 0000000..a48e0c6 --- /dev/null +++ b/megaavr/libraries/SD/examples/ReadWrite/ReadWrite.ino @@ -0,0 +1,80 @@ +/* + SD card read/write + + This example shows how to read and write data to and from an SD card file + The circuit. Pin numbers reflect the default + SPI pins for Uno and Nano models: + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - pin 4 (For For Uno, Nano: pin 10) + + created Nov 2010 + by David A. Mellis + modified 24 July 2020 + by Tom Igoe + + This example code is in the public domain. + +*/ +#include + +const int chipSelect = 10; +File myFile; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // wait for Serial Monitor to connect. Needed for native USB port boards only: + while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("1. is a card inserted?"); + Serial.println("2. is your wiring correct?"); + Serial.println("3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); + while (true); + } + + Serial.println("initialization done."); + + // open the file. note that only one file can be open at a time, + // so you have to close this one before opening another. + myFile = SD.open("test.txt", FILE_WRITE); + + // if the file opened okay, write to it: + if (myFile) { + Serial.print("Writing to test.txt..."); + myFile.println("testing 1, 2, 3."); + // close the file: + myFile.close(); + Serial.println("done."); + } else { + // if the file didn't open, print an error: + Serial.println("error opening test.txt"); + } + + // re-open the file for reading: + myFile = SD.open("test.txt"); + if (myFile) { + Serial.println("test.txt:"); + + // read from the file until there's nothing else in it: + while (myFile.available()) { + Serial.write(myFile.read()); + } + // close the file: + myFile.close(); + } else { + // if the file didn't open, print an error: + Serial.println("error opening test.txt"); + } +} + +void loop() { + // nothing happens after setup +} diff --git a/megaavr/libraries/SD/examples/listfiles/listfiles.ino b/megaavr/libraries/SD/examples/listfiles/listfiles.ino new file mode 100755 index 0000000..7064563 --- /dev/null +++ b/megaavr/libraries/SD/examples/listfiles/listfiles.ino @@ -0,0 +1,86 @@ +/* + Listfiles + + This example shows how print out the files in a + directory on a SD card.Pin numbers reflect the default + SPI pins for Uno and Nano models + + The circuit: + SD card attached to SPI bus as follows: + ** SDO - pin 11 + ** SDI - pin 12 + ** CLK - pin 13 + ** CS - depends on your SD card shield or module. + Pin 10 used here for consistency with other Arduino examples + + + created Nov 2010 + by David A. Mellis + modified 9 Apr 2012 + by Tom Igoe + modified 2 Feb 2014 + by Scott Fitzgerald + modified 24 July 2020 + by Tom Igoe + + This example code is in the public domain. + +*/ +#include + +const int chipSelect = 10; +File root; + +void setup() { + // Open serial communications and wait for port to open: + Serial.begin(9600); + // wait for Serial Monitor to connect. Needed for native USB port boards only: + while (!Serial); + + Serial.print("Initializing SD card..."); + + if (!SD.begin(chipSelect)) { + Serial.println("initialization failed. Things to check:"); + Serial.println("1. is a card inserted?"); + Serial.println("2. is your wiring correct?"); + Serial.println("3. did you change the chipSelect pin to match your shield or module?"); + Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!"); + while (true); + } + + Serial.println("initialization done."); + + root = SD.open("/"); + + printDirectory(root, 0); + + Serial.println("done!"); +} + +void loop() { + // nothing happens after setup finishes. +} + +void printDirectory(File dir, int numTabs) { + while (true) { + + File entry = dir.openNextFile(); + if (! entry) { + // no more files + break; + } + for (uint8_t i = 0; i < numTabs; i++) { + Serial.print('\t'); + } + Serial.print(entry.name()); + if (entry.isDirectory()) { + Serial.println("/"); + printDirectory(entry, numTabs + 1); + } else { + // files have sizes, directories do not + Serial.print("\t\t"); + Serial.println(entry.size(), DEC); + } + entry.close(); + } +} diff --git a/megaavr/libraries/SD/extras/codespell-ignore-words-list.txt b/megaavr/libraries/SD/extras/codespell-ignore-words-list.txt new file mode 100755 index 0000000..e69de29 diff --git a/megaavr/libraries/SD/keywords.txt b/megaavr/libraries/SD/keywords.txt new file mode 100755 index 0000000..91e74b8 --- /dev/null +++ b/megaavr/libraries/SD/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map SD +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SD KEYWORD1 SD +File KEYWORD1 SD +SDFile KEYWORD1 SD + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +exists KEYWORD2 +mkdir KEYWORD2 +remove KEYWORD2 +rmdir KEYWORD2 +open KEYWORD2 +close KEYWORD2 +seek KEYWORD2 +position KEYWORD2 +size KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +FILE_READ LITERAL1 +FILE_WRITE LITERAL1 diff --git a/megaavr/libraries/SD/library.properties b/megaavr/libraries/SD/library.properties new file mode 100755 index 0000000..60e8859 --- /dev/null +++ b/megaavr/libraries/SD/library.properties @@ -0,0 +1,9 @@ +name=SD +version=1.2.4 +author=Arduino, SparkFun +maintainer=Arduino +sentence=Enables reading and writing on SD cards. +paragraph=Once an SD memory card is connected to the SPI interface of the Arduino or Genuino board you can create files and read/write on them. You can also move through directories on the SD card. +category=Data Storage +url=http://www.arduino.cc/en/Reference/SD +architectures=* diff --git a/megaavr/libraries/SD/src/File.cpp b/megaavr/libraries/SD/src/File.cpp new file mode 100755 index 0000000..3e27fb4 --- /dev/null +++ b/megaavr/libraries/SD/src/File.cpp @@ -0,0 +1,168 @@ +/* + + SD - a slightly more friendly wrapper for sdfatlib + + This library aims to expose a subset of SD card functionality + in the form of a higher level "wrapper" object. + + License: GNU General Public License V3 + (Because sdfatlib is licensed with this.) + + (C) Copyright 2010 SparkFun Electronics + +*/ + +#include + +/* for debugging file open/close leaks + uint8_t nfilecount=0; +*/ + +File::File(SdFile f, const char *n) { + // oh man you are kidding me, new() doesn't exist? Ok we do it by hand! + _file = (SdFile *)malloc(sizeof(SdFile)); + if (_file) { + memcpy(_file, &f, sizeof(SdFile)); + + strncpy(_name, n, 12); + _name[12] = 0; + + /* for debugging file open/close leaks + nfilecount++; + Serial.print("Created \""); + Serial.print(n); + Serial.print("\": "); + Serial.println(nfilecount, DEC); + */ + } +} + +File::File(void) { + _file = 0; + _name[0] = 0; + //Serial.print("Created empty file object"); +} + +// returns a pointer to the file name +char *File::name(void) { + return _name; +} + +// a directory is a special type of file +bool File::isDirectory(void) { + return (_file && _file->isDir()); +} + + +size_t File::write(uint8_t val) { + return write(&val, 1); +} + +size_t File::write(const uint8_t *buf, size_t size) { + size_t t; + if (!_file) { + setWriteError(); + return 0; + } + _file->clearWriteError(); + t = _file->write(buf, size); + if (_file->getWriteError()) { + setWriteError(); + return 0; + } + return t; +} + +int File::availableForWrite() { + if (_file) { + return _file->availableForWrite(); + } + return 0; +} + +int File::peek() { + if (! _file) { + return 0; + } + + int c = _file->read(); + if (c != -1) { + _file->seekCur(-1); + } + return c; +} + +int File::read() { + if (_file) { + return _file->read(); + } + return -1; +} + +// buffered read for more efficient, high speed reading +int File::read(void *buf, uint16_t nbyte) { + if (_file) { + return _file->read(buf, nbyte); + } + return 0; +} + +int File::available() { + if (! _file) { + return 0; + } + + uint32_t n = size() - position(); + + return n > 0X7FFF ? 0X7FFF : n; +} + +void File::flush() { + if (_file) { + _file->sync(); + } +} + +bool File::seek(uint32_t pos) { + if (! _file) { + return false; + } + + return _file->seekSet(pos); +} + +uint32_t File::position() { + if (! _file) { + return -1; + } + return _file->curPosition(); +} + +uint32_t File::size() { + if (! _file) { + return 0; + } + return _file->fileSize(); +} + +void File::close() { + if (_file) { + _file->close(); + free(_file); + _file = 0; + + /* for debugging file open/close leaks + nfilecount--; + Serial.print("Deleted "); + Serial.println(nfilecount, DEC); + */ + } +} + +File::operator bool() { + if (_file) { + return _file->isOpen(); + } + return false; +} + diff --git a/megaavr/libraries/SD/src/README.txt b/megaavr/libraries/SD/src/README.txt new file mode 100755 index 0000000..495ea4c --- /dev/null +++ b/megaavr/libraries/SD/src/README.txt @@ -0,0 +1,13 @@ + +** SD - a slightly more friendly wrapper for sdfatlib ** + +This library aims to expose a subset of SD card functionality in the +form of a higher level "wrapper" object. + +License: GNU General Public License V3 + (Because sdfatlib is licensed with this.) + +(C) Copyright 2010 SparkFun Electronics + +Now better than ever with optimization, multiple file support, directory handling, etc - ladyada! + diff --git a/megaavr/libraries/SD/src/SD.cpp b/megaavr/libraries/SD/src/SD.cpp new file mode 100755 index 0000000..69f348a --- /dev/null +++ b/megaavr/libraries/SD/src/SD.cpp @@ -0,0 +1,637 @@ +/* + + SD - a slightly more friendly wrapper for sdfatlib + + This library aims to expose a subset of SD card functionality + in the form of a higher level "wrapper" object. + + License: GNU General Public License V3 + (Because sdfatlib is licensed with this.) + + (C) Copyright 2010 SparkFun Electronics + + + This library provides four key benefits: + + Including `SD.h` automatically creates a global + `SD` object which can be interacted with in a similar + manner to other standard global objects like `Serial` and `Ethernet`. + + Boilerplate initialisation code is contained in one method named + `begin` and no further objects need to be created in order to access + the SD card. + + Calls to `open` can supply a full path name including parent + directories which simplifies interacting with files in subdirectories. + + Utility methods are provided to determine whether a file exists + and to create a directory hierarchy. + + + Note however that not all functionality provided by the underlying + sdfatlib library is exposed. + +*/ + +/* + + Implementation Notes + + In order to handle multi-directory path traversal, functionality that + requires this ability is implemented as callback functions. + + Individual methods call the `walkPath` function which performs the actual + directory traversal (swapping between two different directory/file handles + along the way) and at each level calls the supplied callback function. + + Some types of functionality will take an action at each level (e.g. exists + or make directory) which others will only take an action at the bottom + level (e.g. open). + +*/ + +#include "SD.h" + +namespace SDLib { + + // Used by `getNextPathComponent` +#define MAX_COMPONENT_LEN 12 // What is max length? +#define PATH_COMPONENT_BUFFER_LEN MAX_COMPONENT_LEN+1 + + bool getNextPathComponent(const char *path, unsigned int *p_offset, + char *buffer) { + /* + + Parse individual path components from a path. + + e.g. after repeated calls '/foo/bar/baz' will be split + into 'foo', 'bar', 'baz'. + + This is similar to `strtok()` but copies the component into the + supplied buffer rather than modifying the original string. + + + `buffer` needs to be PATH_COMPONENT_BUFFER_LEN in size. + + `p_offset` needs to point to an integer of the offset at + which the previous path component finished. + + Returns `true` if more components remain. + + Returns `false` if this is the last component. + (This means path ended with 'foo' or 'foo/'.) + + */ + + // TODO: Have buffer local to this function, so we know it's the + // correct length? + + int bufferOffset = 0; + + int offset = *p_offset; + + // Skip root or other separator + if (path[offset] == '/') { + offset++; + } + + // Copy the next next path segment + while (bufferOffset < MAX_COMPONENT_LEN + && (path[offset] != '/') + && (path[offset] != '\0')) { + buffer[bufferOffset++] = path[offset++]; + } + + buffer[bufferOffset] = '\0'; + + // Skip trailing separator so we can determine if this + // is the last component in the path or not. + if (path[offset] == '/') { + offset++; + } + + *p_offset = offset; + + return (path[offset] != '\0'); + } + + + + bool walkPath(const char *filepath, SdFile& parentDir, + bool(*callback)(SdFile& parentDir, + const char *filePathComponent, + bool isLastComponent, + void *object), + void *object = NULL) { + /* + + When given a file path (and parent directory--normally root), + this function traverses the directories in the path and at each + level calls the supplied callback function while also providing + the supplied object for context if required. + + e.g. given the path '/foo/bar/baz' + the callback would be called at the equivalent of + '/foo', '/foo/bar' and '/foo/bar/baz'. + + The implementation swaps between two different directory/file + handles as it traverses the directories and does not use recursion + in an attempt to use memory efficiently. + + If a callback wishes to stop the directory traversal it should + return false--in this case the function will stop the traversal, + tidy up and return false. + + If a directory path doesn't exist at some point this function will + also return false and not subsequently call the callback. + + If a directory path specified is complete, valid and the callback + did not indicate the traversal should be interrupted then this + function will return true. + + */ + + + SdFile subfile1; + SdFile subfile2; + + char buffer[PATH_COMPONENT_BUFFER_LEN]; + + unsigned int offset = 0; + + SdFile *p_parent; + SdFile *p_child; + + SdFile *p_tmp_sdfile; + + p_child = &subfile1; + + p_parent = &parentDir; + + while (true) { + + bool moreComponents = getNextPathComponent(filepath, &offset, buffer); + + bool shouldContinue = callback((*p_parent), buffer, !moreComponents, object); + + if (!shouldContinue) { + // TODO: Don't repeat this code? + // If it's one we've created then we + // don't need the parent handle anymore. + if (p_parent != &parentDir) { + (*p_parent).close(); + } + return false; + } + + if (!moreComponents) { + break; + } + + bool exists = (*p_child).open(*p_parent, buffer, O_RDONLY); + + // If it's one we've created then we + // don't need the parent handle anymore. + if (p_parent != &parentDir) { + (*p_parent).close(); + } + + // Handle case when it doesn't exist and we can't continue... + if (exists) { + // We alternate between two file handles as we go down + // the path. + if (p_parent == &parentDir) { + p_parent = &subfile2; + } + + p_tmp_sdfile = p_parent; + p_parent = p_child; + p_child = p_tmp_sdfile; + } else { + return false; + } + } + + if (p_parent != &parentDir) { + (*p_parent).close(); // TODO: Return/ handle different? + } + + return true; + } + + + + /* + + The callbacks used to implement various functionality follow. + + Each callback is supplied with a parent directory handle, + character string with the name of the current file path component, + a flag indicating if this component is the last in the path and + a pointer to an arbitrary object used for context. + + */ + + bool callback_pathExists(SdFile& parentDir, const char *filePathComponent, + bool /* isLastComponent */, void * /* object */) { + /* + + Callback used to determine if a file/directory exists in parent + directory. + + Returns true if file path exists. + + */ + SdFile child; + + bool exists = child.open(parentDir, filePathComponent, O_RDONLY); + + if (exists) { + child.close(); + } + + return exists; + } + + + + bool callback_makeDirPath(SdFile& parentDir, const char *filePathComponent, + bool isLastComponent, void *object) { + /* + + Callback used to create a directory in the parent directory if + it does not already exist. + + Returns true if a directory was created or it already existed. + + */ + bool result = false; + SdFile child; + + result = callback_pathExists(parentDir, filePathComponent, isLastComponent, object); + if (!result) { + result = child.makeDir(parentDir, filePathComponent); + } + + return result; + } + + + /* + + bool callback_openPath(SdFile& parentDir, char *filePathComponent, + bool isLastComponent, void *object) { + + Callback used to open a file specified by a filepath that may + specify one or more directories above it. + + Expects the context object to be an instance of `SDClass` and + will use the `file` property of the instance to open the requested + file/directory with the associated file open mode property. + + Always returns true if the directory traversal hasn't reached the + bottom of the directory hierarchy. + + Returns false once the file has been opened--to prevent the traversal + from descending further. (This may be unnecessary.) + + if (isLastComponent) { + SDClass *p_SD = static_cast(object); + p_SD->file.open(parentDir, filePathComponent, p_SD->fileOpenMode); + if (p_SD->fileOpenMode == FILE_WRITE) { + p_SD->file.seekSet(p_SD->file.fileSize()); + } + // TODO: Return file open result? + return false; + } + return true; + } + */ + + + + bool callback_remove(SdFile& parentDir, const char *filePathComponent, + bool isLastComponent, void * /* object */) { + if (isLastComponent) { + return SdFile::remove(parentDir, filePathComponent); + } + return true; + } + + bool callback_rmdir(SdFile& parentDir, const char *filePathComponent, + bool isLastComponent, void * /* object */) { + if (isLastComponent) { + SdFile f; + if (!f.open(parentDir, filePathComponent, O_READ)) { + return false; + } + return f.rmDir(); + } + return true; + } + + + + /* Implementation of class used to create `SDCard` object. */ + + + + bool SDClass::begin(uint8_t csPin) { + if (root.isOpen()) { + root.close(); + } + + /* + + Performs the initialisation required by the sdfatlib library. + + Return true if initialization succeeds, false otherwise. + + */ + return card.init(SPI_HALF_SPEED, csPin) && + volume.init(card) && + root.openRoot(volume); + } + + bool SDClass::begin(uint32_t clock, uint8_t csPin) { + if (root.isOpen()) { + root.close(); + } + + return card.init(SPI_HALF_SPEED, csPin) && + card.setSpiClock(clock) && + volume.init(card) && + root.openRoot(volume); + } + + //call this when a card is removed. It will allow you to insert and initialise a new card. + void SDClass::end() { + root.close(); + } + + // this little helper is used to traverse paths + SdFile SDClass::getParentDir(const char *filepath, int *index) { + // get parent directory + SdFile d1; + SdFile d2; + + d1.openRoot(volume); // start with the mostparent, root! + + // we'll use the pointers to swap between the two objects + SdFile *parent = &d1; + SdFile *subdir = &d2; + + const char *origpath = filepath; + + while (strchr(filepath, '/')) { + + // get rid of leading /'s + if (filepath[0] == '/') { + filepath++; + continue; + } + + if (! strchr(filepath, '/')) { + // it was in the root directory, so leave now + break; + } + + // extract just the name of the next subdirectory + uint8_t idx = strchr(filepath, '/') - filepath; + if (idx > 12) { + idx = 12; // don't let them specify long names + } + char subdirname[13]; + strncpy(subdirname, filepath, idx); + subdirname[idx] = 0; + + // close the subdir (we reuse them) if open + subdir->close(); + if (! subdir->open(parent, subdirname, O_READ)) { + // failed to open one of the subdirectories + return SdFile(); + } + // move forward to the next subdirectory + filepath += idx; + + // we reuse the objects, close it. + parent->close(); + + // swap the pointers + SdFile *t = parent; + parent = subdir; + subdir = t; + } + + *index = (int)(filepath - origpath); + // parent is now the parent directory of the file! + return *parent; + } + + + File SDClass::open(const char *filepath, uint8_t mode) { + /* + + Open the supplied file path for reading or writing. + + The file content can be accessed via the `file` property of + the `SDClass` object--this property is currently + a standard `SdFile` object from `sdfatlib`. + + Defaults to read only. + + If `write` is true, default action (when `append` is true) is to + append data to the end of the file. + + If `append` is false then the file will be truncated first. + + If the file does not exist and it is opened for writing the file + will be created. + + An attempt to open a file for reading that does not exist is an + error. + + */ + + int pathidx; + + // do the interactive search + SdFile parentdir = getParentDir(filepath, &pathidx); + // no more subdirs! + + filepath += pathidx; + + if (! filepath[0]) { + // it was the directory itself! + return File(parentdir, "/"); + } + + // Open the file itself + SdFile file; + + // failed to open a subdir! + if (!parentdir.isOpen()) { + return File(); + } + + if (! file.open(parentdir, filepath, mode)) { + return File(); + } + // close the parent + parentdir.close(); + + if ((mode & (O_APPEND | O_WRITE)) == (O_APPEND | O_WRITE)) { + file.seekSet(file.fileSize()); + } + return File(file, filepath); + } + + + /* + File SDClass::open(char *filepath, uint8_t mode) { + // + + Open the supplied file path for reading or writing. + + The file content can be accessed via the `file` property of + the `SDClass` object--this property is currently + a standard `SdFile` object from `sdfatlib`. + + Defaults to read only. + + If `write` is true, default action (when `append` is true) is to + append data to the end of the file. + + If `append` is false then the file will be truncated first. + + If the file does not exist and it is opened for writing the file + will be created. + + An attempt to open a file for reading that does not exist is an + error. + + // + + // TODO: Allow for read&write? (Possibly not, as it requires seek.) + + fileOpenMode = mode; + walkPath(filepath, root, callback_openPath, this); + + return File(); + + } + */ + + + //bool SDClass::close() { + // /* + // + // Closes the file opened by the `open` method. + // + // */ + // file.close(); + //} + + + bool SDClass::exists(const char *filepath) { + /* + + Returns true if the supplied file path exists. + + */ + return walkPath(filepath, root, callback_pathExists); + } + + + //bool SDClass::exists(char *filepath, SdFile& parentDir) { + // /* + // + // Returns true if the supplied file path rooted at `parentDir` + // exists. + // + // */ + // return walkPath(filepath, parentDir, callback_pathExists); + //} + + + bool SDClass::mkdir(const char *filepath) { + /* + + Makes a single directory or a hierarchy of directories. + + A rough equivalent to `mkdir -p`. + + */ + return walkPath(filepath, root, callback_makeDirPath); + } + + bool SDClass::rmdir(const char *filepath) { + /* + + Remove a single directory or a hierarchy of directories. + + A rough equivalent to `rm -rf`. + + */ + return walkPath(filepath, root, callback_rmdir); + } + + bool SDClass::remove(const char *filepath) { + return walkPath(filepath, root, callback_remove); + } + + + // allows you to recurse into a directory + File File::openNextFile(uint8_t mode) { + dir_t p; + + //Serial.print("\t\treading dir..."); + while (_file->readDir(&p) > 0) { + + // done if past last used entry + if (p.name[0] == DIR_NAME_FREE) { + //Serial.println("end"); + return File(); + } + + // skip deleted entry and entries for . and .. + if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.') { + //Serial.println("dots"); + continue; + } + + // only list subdirectories and files + if (!DIR_IS_FILE_OR_SUBDIR(&p)) { + //Serial.println("notafile"); + continue; + } + + // print file name with possible blank fill + SdFile f; + char name[13]; + _file->dirName(p, name); + //Serial.print("try to open file "); + //Serial.println(name); + + if (f.open(_file, name, mode)) { + //Serial.println("OK!"); + return File(f, name); + } else { + //Serial.println("ugh"); + return File(); + } + } + + //Serial.println("nothing"); + return File(); + } + + void File::rewindDirectory(void) { + if (isDirectory()) { + _file->rewind(); + } + } + + SDClass SD; + +}; diff --git a/megaavr/libraries/SD/src/SD.h b/megaavr/libraries/SD/src/SD.h new file mode 100755 index 0000000..c81a7d3 --- /dev/null +++ b/megaavr/libraries/SD/src/SD.h @@ -0,0 +1,138 @@ +/* + + SD - a slightly more friendly wrapper for sdfatlib + + This library aims to expose a subset of SD card functionality + in the form of a higher level "wrapper" object. + + License: GNU General Public License V3 + (Because sdfatlib is licensed with this.) + + (C) Copyright 2010 SparkFun Electronics + +*/ + +#ifndef __SD_H__ +#define __SD_H__ + +#include + +#include "utility/SdFat.h" +#include "utility/SdFatUtil.h" + +#define FILE_READ O_READ +#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND) + +namespace SDLib { + + class File : public Stream { + private: + char _name[13]; // our name + SdFile *_file; // underlying file pointer + + public: + File(SdFile f, const char *name); // wraps an underlying SdFile + File(void); // 'empty' constructor + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *buf, size_t size); + virtual int availableForWrite(); + virtual int read(); + virtual int peek(); + virtual int available(); + virtual void flush(); + int read(void *buf, uint16_t nbyte); + bool seek(uint32_t pos); + uint32_t position(); + uint32_t size(); + void close(); + operator bool(); + char * name(); + + bool isDirectory(void); + File openNextFile(uint8_t mode = O_RDONLY); + void rewindDirectory(void); + + using Print::write; + }; + + class SDClass { + + private: + // These are required for initialisation and use of sdfatlib + Sd2Card card; + SdVolume volume; + SdFile root; + + // my quick&dirty iterator, should be replaced + SdFile getParentDir(const char *filepath, int *indx); + public: + // This needs to be called to set up the connection to the SD card + // before other methods are used. + bool begin(uint8_t csPin = SD_CHIP_SELECT_PIN); + bool begin(uint32_t clock, uint8_t csPin); + + //call this when a card is removed. It will allow you to insert and initialise a new card. + void end(); + + // Open the specified file/directory with the supplied mode (e.g. read or + // write, etc). Returns a File object for interacting with the file. + // Note that currently only one file can be open at a time. + File open(const char *filename, uint8_t mode = FILE_READ); + File open(const String &filename, uint8_t mode = FILE_READ) { + return open(filename.c_str(), mode); + } + + // Methods to determine if the requested file path exists. + bool exists(const char *filepath); + bool exists(const String &filepath) { + return exists(filepath.c_str()); + } + + // Create the requested directory heirarchy--if intermediate directories + // do not exist they will be created. + bool mkdir(const char *filepath); + bool mkdir(const String &filepath) { + return mkdir(filepath.c_str()); + } + + // Delete the file. + bool remove(const char *filepath); + bool remove(const String &filepath) { + return remove(filepath.c_str()); + } + + bool rmdir(const char *filepath); + bool rmdir(const String &filepath) { + return rmdir(filepath.c_str()); + } + + private: + + // This is used to determine the mode used to open a file + // it's here because it's the easiest place to pass the + // information through the directory walking function. But + // it's probably not the best place for it. + // It shouldn't be set directly--it is set via the parameters to `open`. + int fileOpenMode; + + friend class File; + friend bool callback_openPath(SdFile&, const char *, bool, void *); + }; + + extern SDClass SD; + +}; + +// We enclose File and SD classes in namespace SDLib to avoid conflicts +// with others legacy libraries that redefines File class. + +// This ensure compatibility with sketches that uses only SD library +using namespace SDLib; + +// This allows sketches to use SDLib::File with other libraries (in the +// sketch you must use SDFile instead of File to disambiguate) +typedef SDLib::File SDFile; +typedef SDLib::SDClass SDFileSystemClass; +#define SDFileSystem SDLib::SD + +#endif diff --git a/megaavr/libraries/SD/src/utility/FatStructs.h b/megaavr/libraries/SD/src/utility/FatStructs.h new file mode 100755 index 0000000..aefef9c --- /dev/null +++ b/megaavr/libraries/SD/src/utility/FatStructs.h @@ -0,0 +1,418 @@ +/* Arduino SdFat Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#ifndef FatStructs_h +#define FatStructs_h +/** + \file + FAT file structures +*/ +/* + mostly from Microsoft document fatgen103.doc + http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx +*/ +//------------------------------------------------------------------------------ +/** Value for byte 510 of boot block or MBR */ +uint8_t const BOOTSIG0 = 0X55; +/** Value for byte 511 of boot block or MBR */ +uint8_t const BOOTSIG1 = 0XAA; +//------------------------------------------------------------------------------ +/** + \struct partitionTable + \brief MBR partition table entry + + A partition table entry for a MBR formatted storage device. + The MBR partition table has four entries. +*/ +struct partitionTable { + /** + Boot Indicator . Indicates whether the volume is the active + partition. Legal values include: 0X00. Do not use for booting. + 0X80 Active partition. + */ + uint8_t boot; + /** + Head part of Cylinder-head-sector address of the first block in + the partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t beginHead; + /** + Sector part of Cylinder-head-sector address of the first block in + the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned beginSector : 6; + /** High bits cylinder for first block in partition. */ + unsigned beginCylinderHigh : 2; + /** + Combine beginCylinderLow with beginCylinderHigh. Legal values + are 0-1023. Only used in old PC BIOS. + */ + uint8_t beginCylinderLow; + /** + Partition type. See defines that begin with PART_TYPE_ for + some Microsoft partition types. + */ + uint8_t type; + /** + head part of cylinder-head-sector address of the last sector in the + partition. Legal values are 0-255. Only used in old PC BIOS. + */ + uint8_t endHead; + /** + Sector part of cylinder-head-sector address of the last sector in + the partition. Legal values are 1-63. Only used in old PC BIOS. + */ + unsigned endSector : 6; + /** High bits of end cylinder */ + unsigned endCylinderHigh : 2; + /** + Combine endCylinderLow with endCylinderHigh. Legal values + are 0-1023. Only used in old PC BIOS. + */ + uint8_t endCylinderLow; + /** Logical block address of the first block in the partition. */ + uint32_t firstSector; + /** Length of the partition, in blocks. */ + uint32_t totalSectors; +} __attribute__((packed)); +/** Type name for partitionTable */ +typedef struct partitionTable part_t; +//------------------------------------------------------------------------------ +/** + \struct masterBootRecord + + \brief Master Boot Record + + The first block of a storage device that is formatted with a MBR. +*/ +struct masterBootRecord { + /** Code Area for master boot program. */ + uint8_t codeArea[440]; + /** Optional WindowsNT disk signature. May contain more boot code. */ + uint32_t diskSignature; + /** Usually zero but may be more boot code. */ + uint16_t usuallyZero; + /** Partition tables. */ + part_t part[4]; + /** First MBR signature byte. Must be 0X55 */ + uint8_t mbrSig0; + /** Second MBR signature byte. Must be 0XAA */ + uint8_t mbrSig1; +} __attribute__((packed)); +/** Type name for masterBootRecord */ +typedef struct masterBootRecord mbr_t; +//------------------------------------------------------------------------------ +/** + \struct biosParmBlock + + \brief BIOS parameter block + + The BIOS parameter block describes the physical layout of a FAT volume. +*/ +struct biosParmBlock { + /** + Count of bytes per sector. This value may take on only the + following values: 512, 1024, 2048 or 4096 + */ + uint16_t bytesPerSector; + /** + Number of sectors per allocation unit. This value must be a + power of 2 that is greater than 0. The legal values are + 1, 2, 4, 8, 16, 32, 64, and 128. + */ + uint8_t sectorsPerCluster; + /** + Number of sectors before the first FAT. + This value must not be zero. + */ + uint16_t reservedSectorCount; + /** The count of FAT data structures on the volume. This field should + always contain the value 2 for any FAT volume of any type. + */ + uint8_t fatCount; + /** + For FAT12 and FAT16 volumes, this field contains the count of + 32-byte directory entries in the root directory. For FAT32 volumes, + this field must be set to 0. For FAT12 and FAT16 volumes, this + value should always specify a count that when multiplied by 32 + results in a multiple of bytesPerSector. FAT16 volumes should + use the value 512. + */ + uint16_t rootDirEntryCount; + /** + This field is the old 16-bit total count of sectors on the volume. + This count includes the count of all sectors in all four regions + of the volume. This field can be 0; if it is 0, then totalSectors32 + must be non-zero. For FAT32 volumes, this field must be 0. For + FAT12 and FAT16 volumes, this field contains the sector count, and + totalSectors32 is 0 if the total sector count fits + (is less than 0x10000). + */ + uint16_t totalSectors16; + /** + This dates back to the old MS-DOS 1.x media determination and is + no longer usually used for anything. 0xF8 is the standard value + for fixed (non-removable) media. For removable media, 0xF0 is + frequently used. Legal values are 0xF0 or 0xF8-0xFF. + */ + uint8_t mediaType; + /** + Count of sectors occupied by one FAT on FAT12/FAT16 volumes. + On FAT32 volumes this field must be 0, and sectorsPerFat32 + contains the FAT size count. + */ + uint16_t sectorsPerFat16; + /** Sectors per track for interrupt 0x13. Not used otherwise. */ + uint16_t sectorsPerTrtack; + /** Number of heads for interrupt 0x13. Not used otherwise. */ + uint16_t headCount; + /** + Count of hidden sectors preceding the partition that contains this + FAT volume. This field is generally only relevant for media + visible on interrupt 0x13. + */ + uint32_t hidddenSectors; + /** + This field is the new 32-bit total count of sectors on the volume. + This count includes the count of all sectors in all four regions + of the volume. This field can be 0; if it is 0, then + totalSectors16 must be non-zero. + */ + uint32_t totalSectors32; + /** + Count of sectors occupied by one FAT on FAT32 volumes. + */ + uint32_t sectorsPerFat32; + /** + This field is only defined for FAT32 media and does not exist on + FAT12 and FAT16 media. + Bits 0-3 -- Zero-based number of active FAT. + Only valid if mirroring is disabled. + Bits 4-6 -- Reserved. + Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs. + -- 1 means only one FAT is active; it is the one referenced in bits 0-3. + Bits 8-15 -- Reserved. + */ + uint16_t fat32Flags; + /** + FAT32 version. High byte is major revision number. + Low byte is minor revision number. Only 0.0 define. + */ + uint16_t fat32Version; + /** + Cluster number of the first cluster of the root directory for FAT32. + This usually 2 but not required to be 2. + */ + uint32_t fat32RootCluster; + /** + Sector number of FSINFO structure in the reserved area of the + FAT32 volume. Usually 1. + */ + uint16_t fat32FSInfo; + /** + If non-zero, indicates the sector number in the reserved area + of the volume of a copy of the boot record. Usually 6. + No value other than 6 is recommended. + */ + uint16_t fat32BackBootBlock; + /** + Reserved for future expansion. Code that formats FAT32 volumes + should always set all of the bytes of this field to 0. + */ + uint8_t fat32Reserved[12]; +} __attribute__((packed)); +/** Type name for biosParmBlock */ +typedef struct biosParmBlock bpb_t; +//------------------------------------------------------------------------------ +/** + \struct fat32BootSector + + \brief Boot sector for a FAT16 or FAT32 volume. + +*/ +struct fat32BootSector { + /** X86 jmp to boot program */ + uint8_t jmpToBootCode[3]; + /** informational only - don't depend on it */ + char oemName[8]; + /** BIOS Parameter Block */ + bpb_t bpb; + /** for int0x13 use value 0X80 for hard drive */ + uint8_t driveNumber; + /** used by Windows NT - should be zero for FAT */ + uint8_t reserved1; + /** 0X29 if next three fields are valid */ + uint8_t bootSignature; + /** usually generated by combining date and time */ + uint32_t volumeSerialNumber; + /** should match volume label in root dir */ + char volumeLabel[11]; + /** informational only - don't depend on it */ + char fileSystemType[8]; + /** X86 boot code */ + uint8_t bootCode[420]; + /** must be 0X55 */ + uint8_t bootSectorSig0; + /** must be 0XAA */ + uint8_t bootSectorSig1; +} __attribute__((packed)); +//------------------------------------------------------------------------------ +// End Of Chain values for FAT entries +/** FAT16 end of chain value used by Microsoft. */ +uint16_t const FAT16EOC = 0XFFFF; +/** Minimum value for FAT16 EOC. Use to test for EOC. */ +uint16_t const FAT16EOC_MIN = 0XFFF8; +/** FAT32 end of chain value used by Microsoft. */ +uint32_t const FAT32EOC = 0X0FFFFFFF; +/** Minimum value for FAT32 EOC. Use to test for EOC. */ +uint32_t const FAT32EOC_MIN = 0X0FFFFFF8; +/** Mask a for FAT32 entry. Entries are 28 bits. */ +uint32_t const FAT32MASK = 0X0FFFFFFF; + +/** Type name for fat32BootSector */ +typedef struct fat32BootSector fbs_t; +//------------------------------------------------------------------------------ +/** + \struct directoryEntry + \brief FAT short directory entry + + Short means short 8.3 name, not the entry size. + + Date Format. A FAT directory entry date stamp is a 16-bit field that is + basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the + format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the + 16-bit word): + + Bits 9-15: Count of years from 1980, valid value range 0-127 + inclusive (1980-2107). + + Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive. + + Bits 0-4: Day of month, valid value range 1-31 inclusive. + + Time Format. A FAT directory entry time stamp is a 16-bit field that has + a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the + 16-bit word, bit 15 is the MSB of the 16-bit word). + + Bits 11-15: Hours, valid value range 0-23 inclusive. + + Bits 5-10: Minutes, valid value range 0-59 inclusive. + + Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds). + + The valid time range is from Midnight 00:00:00 to 23:59:58. +*/ +struct directoryEntry { + /** + Short 8.3 name. + The first eight bytes contain the file name with blank fill. + The last three bytes contain the file extension with blank fill. + */ + uint8_t name[11]; + /** Entry attributes. + + The upper two bits of the attribute byte are reserved and should + always be set to 0 when a file is created and never modified or + looked at after that. See defines that begin with DIR_ATT_. + */ + uint8_t attributes; + /** + Reserved for use by Windows NT. Set value to 0 when a file is + created and never modify or look at it after that. + */ + uint8_t reservedNT; + /** + The granularity of the seconds part of creationTime is 2 seconds + so this field is a count of tenths of a second and its valid + value range is 0-199 inclusive. (WHG note - seems to be hundredths) + */ + uint8_t creationTimeTenths; + /** Time file was created. */ + uint16_t creationTime; + /** Date file was created. */ + uint16_t creationDate; + /** + Last access date. Note that there is no last access time, only + a date. This is the date of last read or write. In the case of + a write, this should be set to the same date as lastWriteDate. + */ + uint16_t lastAccessDate; + /** + High word of this entry's first cluster number (always 0 for a + FAT12 or FAT16 volume). + */ + uint16_t firstClusterHigh; + /** Time of last write. File creation is considered a write. */ + uint16_t lastWriteTime; + /** Date of last write. File creation is considered a write. */ + uint16_t lastWriteDate; + /** Low word of this entry's first cluster number. */ + uint16_t firstClusterLow; + /** 32-bit unsigned holding this file's size in bytes. */ + uint32_t fileSize; +} __attribute__((packed)); +//------------------------------------------------------------------------------ +// Definitions for directory entries +// +/** Type name for directoryEntry */ +typedef struct directoryEntry dir_t; +/** escape for name[0] = 0XE5 */ +uint8_t const DIR_NAME_0XE5 = 0X05; +/** name[0] value for entry that is free after being "deleted" */ +uint8_t const DIR_NAME_DELETED = 0XE5; +/** name[0] value for entry that is free and no allocated entries follow */ +uint8_t const DIR_NAME_FREE = 0X00; +/** file is read-only */ +uint8_t const DIR_ATT_READ_ONLY = 0X01; +/** File should hidden in directory listings */ +uint8_t const DIR_ATT_HIDDEN = 0X02; +/** Entry is for a system file */ +uint8_t const DIR_ATT_SYSTEM = 0X04; +/** Directory entry contains the volume label */ +uint8_t const DIR_ATT_VOLUME_ID = 0X08; +/** Entry is for a directory */ +uint8_t const DIR_ATT_DIRECTORY = 0X10; +/** Old DOS archive bit for backup support */ +uint8_t const DIR_ATT_ARCHIVE = 0X20; +/** Test value for long name entry. Test is + (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */ +uint8_t const DIR_ATT_LONG_NAME = 0X0F; +/** Test mask for long name entry */ +uint8_t const DIR_ATT_LONG_NAME_MASK = 0X3F; +/** defined attribute bits */ +uint8_t const DIR_ATT_DEFINED_BITS = 0X3F; +/** Directory entry is part of a long name */ +static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) { + return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME; +} +/** Mask for file/subdirectory tests */ +uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY); +/** Directory entry is for a file */ +static inline uint8_t DIR_IS_FILE(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0; +} +/** Directory entry is for a subdirectory */ +static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY; +} +/** Directory entry is for a file or subdirectory */ +static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { + return (dir->attributes & DIR_ATT_VOLUME_ID) == 0; +} +#endif // FatStructs_h diff --git a/megaavr/libraries/SD/src/utility/Sd2Card.cpp b/megaavr/libraries/SD/src/utility/Sd2Card.cpp new file mode 100755 index 0000000..fc3d857 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/Sd2Card.cpp @@ -0,0 +1,777 @@ +/* Arduino Sd2Card Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino Sd2Card Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino Sd2Card Library. If not, see + . +*/ +#define USE_SPI_LIB +#include +#include "Sd2Card.h" +//------------------------------------------------------------------------------ +#ifndef SOFTWARE_SPI +#ifdef USE_SPI_LIB + + #ifndef SDCARD_SPI + #define SDCARD_SPI SPI + #endif + + #include + static SPISettings settings; +#endif +// functions for hardware SPI +/** Send a byte to the card */ +static void spiSend(uint8_t b) { + #ifndef USE_SPI_LIB + SPDR = b; + while (!(SPSR & (1 << SPIF))) + ; + #else + SDCARD_SPI.transfer(b); + #endif +} +/** Receive a byte from the card */ +static uint8_t spiRec(void) { + #ifndef USE_SPI_LIB + spiSend(0XFF); + return SPDR; + #else + return SDCARD_SPI.transfer(0xFF); + #endif +} +#else // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** nop to tune soft SPI timing */ +#define nop asm volatile ("nop\n\t") +//------------------------------------------------------------------------------ +/** Soft SPI receive */ +uint8_t spiRec(void) { + uint8_t data = 0; + // no interrupts during byte receive - about 8 us + cli(); + // output pin high - like sending 0XFF + fastDigitalWrite(SPI_MOSI_PIN, HIGH); + + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, HIGH); + + // adjust so SCK is nice + nop; + nop; + + data <<= 1; + + if (fastDigitalRead(SPI_MISO_PIN)) { + data |= 1; + } + + fastDigitalWrite(SPI_SCK_PIN, LOW); + } + // enable interrupts + sei(); + return data; +} +//------------------------------------------------------------------------------ +/** Soft SPI send */ +void spiSend(uint8_t data) { + // no interrupts during byte send - about 8 us + cli(); + for (uint8_t i = 0; i < 8; i++) { + fastDigitalWrite(SPI_SCK_PIN, LOW); + + fastDigitalWrite(SPI_MOSI_PIN, data & 0X80); + + data <<= 1; + + fastDigitalWrite(SPI_SCK_PIN, HIGH); + } + // hold SCK high for a few ns + nop; + nop; + nop; + nop; + + fastDigitalWrite(SPI_SCK_PIN, LOW); + // enable interrupts + sei(); +} +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +// send command and return error code. Return zero for OK +uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) { + // end read if in partialBlockRead mode + readEnd(); + + // select card + chipSelectLow(); + + // wait up to 300 ms if busy + waitNotBusy(300); + + // send command + spiSend(cmd | 0x40); + + // send argument + for (int8_t s = 24; s >= 0; s -= 8) { + spiSend(arg >> s); + } + + // send CRC + uint8_t crc = 0XFF; + if (cmd == CMD0) { + crc = 0X95; // correct crc for CMD0 with arg 0 + } + if (cmd == CMD8) { + crc = 0X87; // correct crc for CMD8 with arg 0X1AA + } + spiSend(crc); + + // wait for response + for (uint8_t i = 0; ((status_ = spiRec()) & 0X80) && i != 0XFF; i++) + ; + return status_; +} +//------------------------------------------------------------------------------ +/** + Determine the size of an SD flash memory card. + + \return The number of 512 byte data blocks in the card + or zero if an error occurs. +*/ +uint32_t Sd2Card::cardSize(void) { + csd_t csd; + if (!readCSD(&csd)) { + return 0; + } + if (csd.v1.csd_ver == 0) { + uint8_t read_bl_len = csd.v1.read_bl_len; + uint16_t c_size = (csd.v1.c_size_high << 10) + | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low; + uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1) + | csd.v1.c_size_mult_low; + return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7); + } else if (csd.v2.csd_ver == 1) { + uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16) + | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low; + return (c_size + 1) << 10; + } else { + error(SD_CARD_ERROR_BAD_CSD); + return 0; + } +} +//------------------------------------------------------------------------------ +static uint8_t chip_select_asserted = 0; + +void Sd2Card::chipSelectHigh(void) { + digitalWrite(chipSelectPin_, HIGH); + #ifdef USE_SPI_LIB + if (chip_select_asserted) { + chip_select_asserted = 0; + SDCARD_SPI.endTransaction(); + } + #endif +} +//------------------------------------------------------------------------------ +void Sd2Card::chipSelectLow(void) { + #ifdef USE_SPI_LIB + if (!chip_select_asserted) { + chip_select_asserted = 1; + SDCARD_SPI.beginTransaction(settings); + } + #endif + digitalWrite(chipSelectPin_, LOW); +} +//------------------------------------------------------------------------------ +/** Erase a range of blocks. + + \param[in] firstBlock The address of the first block in the range. + \param[in] lastBlock The address of the last block in the range. + + \note This function requests the SD card to do a flash erase for a + range of blocks. The data on the card after an erase operation is + either 0 or 1, depends on the card vendor. The card must support + single block erase. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) { + if (!eraseSingleBlockEnable()) { + error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK); + goto fail; + } + if (type_ != SD_CARD_TYPE_SDHC) { + firstBlock <<= 9; + lastBlock <<= 9; + } + if (cardCommand(CMD32, firstBlock) + || cardCommand(CMD33, lastBlock) + || cardCommand(CMD38, 0)) { + error(SD_CARD_ERROR_ERASE); + goto fail; + } + if (!waitNotBusy(SD_ERASE_TIMEOUT)) { + error(SD_CARD_ERROR_ERASE_TIMEOUT); + goto fail; + } + chipSelectHigh(); + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Determine if card supports single block erase. + + \return The value one, true, is returned if single block erase is supported. + The value zero, false, is returned if single block erase is not supported. +*/ +uint8_t Sd2Card::eraseSingleBlockEnable(void) { + csd_t csd; + return readCSD(&csd) ? csd.v1.erase_blk_en : 0; +} +//------------------------------------------------------------------------------ +/** + Initialize an SD flash memory card. + + \param[in] sckRateID SPI clock rate selector. See setSckRate(). + \param[in] chipSelectPin SD chip select pin number. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. The reason for failure + can be determined by calling errorCode() and errorData(). +*/ +uint8_t Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { + errorCode_ = inBlock_ = partialBlockRead_ = type_ = 0; + chipSelectPin_ = chipSelectPin; + // 16-bit init start time allows over a minute + unsigned int t0 = millis(); + uint32_t arg; + + // set pin modes + pinMode(chipSelectPin_, OUTPUT); + digitalWrite(chipSelectPin_, HIGH); + #ifndef USE_SPI_LIB + pinMode(SPI_MISO_PIN, INPUT); + pinMode(SPI_MOSI_PIN, OUTPUT); + pinMode(SPI_SCK_PIN, OUTPUT); + #endif + + #ifndef SOFTWARE_SPI + #ifndef USE_SPI_LIB + // SS must be in output mode even it is not chip select + pinMode(SS_PIN, OUTPUT); + digitalWrite(SS_PIN, HIGH); // disable any SPI device using hardware SS pin + // Enable SPI, Master, clock rate f_osc/128 + SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); + // clear double speed + SPSR &= ~(1 << SPI2X); + #else // USE_SPI_LIB + SDCARD_SPI.begin(); + settings = SPISettings(250000, MSBFIRST, SPI_MODE0); + #endif // USE_SPI_LIB + #endif // SOFTWARE_SPI + + // must supply min of 74 clock cycles with CS high. + #ifdef USE_SPI_LIB + SDCARD_SPI.beginTransaction(settings); + #endif + for (uint8_t i = 0; i < 10; i++) { + spiSend(0XFF); + } + #ifdef USE_SPI_LIB + SDCARD_SPI.endTransaction(); + #endif + + chipSelectLow(); + + // command to go idle in SPI mode + while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) { + unsigned int d = millis() - t0; + if (d > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_CMD0); + goto fail; + } + } + // check SD version + if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) { + type(SD_CARD_TYPE_SD1); + } else { + // only need last byte of r7 response + for (uint8_t i = 0; i < 4; i++) { + status_ = spiRec(); + } + if (status_ != 0XAA) { + error(SD_CARD_ERROR_CMD8); + goto fail; + } + type(SD_CARD_TYPE_SD2); + } + // initialize card and send host supports SDHC if SD2 + arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0; + + while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) { + // check for timeout + unsigned int d = millis() - t0; + if (d > SD_INIT_TIMEOUT) { + error(SD_CARD_ERROR_ACMD41); + goto fail; + } + } + // if SD2 read OCR register to check for SDHC card + if (type() == SD_CARD_TYPE_SD2) { + if (cardCommand(CMD58, 0)) { + error(SD_CARD_ERROR_CMD58); + goto fail; + } + if ((spiRec() & 0XC0) == 0XC0) { + type(SD_CARD_TYPE_SDHC); + } + // discard rest of ocr - contains allowed voltage range + for (uint8_t i = 0; i < 3; i++) { + spiRec(); + } + } + chipSelectHigh(); + + #ifndef SOFTWARE_SPI + return setSckRate(sckRateID); + #else // SOFTWARE_SPI + return true; + #endif // SOFTWARE_SPI + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + Enable or disable partial block reads. + + Enabling partial block reads improves performance by allowing a block + to be read over the SPI bus as several sub-blocks. Errors may occur + if the time between reads is too long since the SD card may timeout. + The SPI SS line will be held low until the entire block is read or + readEnd() is called. + + Use this for applications like the Adafruit Wave Shield. + + \param[in] value The value TRUE (non-zero) or FALSE (zero).) +*/ +void Sd2Card::partialBlockRead(uint8_t value) { + readEnd(); + partialBlockRead_ = value; +} +//------------------------------------------------------------------------------ +/** + Read a 512 byte block from an SD card device. + + \param[in] block Logical block to be read. + \param[out] dst Pointer to the location that will receive the data. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::readBlock(uint32_t block, uint8_t* dst) { + return readData(block, 0, 512, dst); +} +//------------------------------------------------------------------------------ +/** + Read part of a 512 byte block from an SD card. + + \param[in] block Logical block to be read. + \param[in] offset Number of bytes to skip at start of block + \param[out] dst Pointer to the location that will receive the data. + \param[in] count Number of bytes to read + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::readData(uint32_t block, + uint16_t offset, uint16_t count, uint8_t* dst) { + if (count == 0) { + return true; + } + if ((count + offset) > 512) { + goto fail; + } + if (!inBlock_ || block != block_ || offset < offset_) { + block_ = block; + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) { + block <<= 9; + } + if (cardCommand(CMD17, block)) { + error(SD_CARD_ERROR_CMD17); + goto fail; + } + if (!waitStartBlock()) { + goto fail; + } + offset_ = 0; + inBlock_ = 1; + } + + #ifdef OPTIMIZE_HARDWARE_SPI + // start first spi transfer + SPDR = 0XFF; + + // skip data before offset + for (; offset_ < offset; offset_++) { + while (!(SPSR & (1 << SPIF))) + ; + SPDR = 0XFF; + } + // transfer data + n = count - 1; + for (uint16_t i = 0; i < n; i++) { + while (!(SPSR & (1 << SPIF))) + ; + dst[i] = SPDR; + SPDR = 0XFF; + } + // wait for last byte + while (!(SPSR & (1 << SPIF))) + ; + dst[n] = SPDR; + + #else // OPTIMIZE_HARDWARE_SPI + + // skip data before offset + for (; offset_ < offset; offset_++) { + spiRec(); + } + // transfer data + for (uint16_t i = 0; i < count; i++) { + dst[i] = spiRec(); + } + #endif // OPTIMIZE_HARDWARE_SPI + + offset_ += count; + if (!partialBlockRead_ || offset_ >= 512) { + // read rest of data, checksum and set chip select high + readEnd(); + } + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Skip remaining data in a block when in partial block read mode. */ +void Sd2Card::readEnd(void) { + if (inBlock_) { + // skip data and crc + #ifdef OPTIMIZE_HARDWARE_SPI + // optimize skip for hardware + SPDR = 0XFF; + while (offset_++ < 513) { + while (!(SPSR & (1 << SPIF))) + ; + SPDR = 0XFF; + } + // wait for last crc byte + while (!(SPSR & (1 << SPIF))) + ; + #else // OPTIMIZE_HARDWARE_SPI + while (offset_++ < 514) { + spiRec(); + } + #endif // OPTIMIZE_HARDWARE_SPI + chipSelectHigh(); + inBlock_ = 0; + } +} +//------------------------------------------------------------------------------ +/** read CID or CSR register */ +uint8_t Sd2Card::readRegister(uint8_t cmd, void* buf) { + uint8_t* dst = reinterpret_cast(buf); + if (cardCommand(cmd, 0)) { + error(SD_CARD_ERROR_READ_REG); + goto fail; + } + if (!waitStartBlock()) { + goto fail; + } + // transfer data + for (uint16_t i = 0; i < 16; i++) { + dst[i] = spiRec(); + } + spiRec(); // get first crc byte + spiRec(); // get second crc byte + chipSelectHigh(); + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + Set the SPI clock rate. + + \param[in] sckRateID A value in the range [0, 6]. + + The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum + SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128 + for \a scsRateID = 6. + + \return The value one, true, is returned for success and the value zero, + false, is returned for an invalid value of \a sckRateID. +*/ +uint8_t Sd2Card::setSckRate(uint8_t sckRateID) { + if (sckRateID > 6) { + error(SD_CARD_ERROR_SCK_RATE); + return false; + } + #ifndef USE_SPI_LIB + // see avr processor datasheet for SPI register bit definitions + if ((sckRateID & 1) || sckRateID == 6) { + SPSR &= ~(1 << SPI2X); + } else { + SPSR |= (1 << SPI2X); + } + SPCR &= ~((1 << SPR1) | (1 << SPR0)); + SPCR |= (sckRateID & 4 ? (1 << SPR1) : 0) + | (sckRateID & 2 ? (1 << SPR0) : 0); + #else // USE_SPI_LIB + switch (sckRateID) { + case 0: settings = SPISettings(25000000, MSBFIRST, SPI_MODE0); break; + case 1: settings = SPISettings(4000000, MSBFIRST, SPI_MODE0); break; + case 2: settings = SPISettings(2000000, MSBFIRST, SPI_MODE0); break; + case 3: settings = SPISettings(1000000, MSBFIRST, SPI_MODE0); break; + case 4: settings = SPISettings(500000, MSBFIRST, SPI_MODE0); break; + case 5: settings = SPISettings(250000, MSBFIRST, SPI_MODE0); break; + default: settings = SPISettings(125000, MSBFIRST, SPI_MODE0); + } + #endif // USE_SPI_LIB + return true; +} +#ifdef USE_SPI_LIB +//------------------------------------------------------------------------------ +// set the SPI clock frequency +uint8_t Sd2Card::setSpiClock(uint32_t clock) { + settings = SPISettings(clock, MSBFIRST, SPI_MODE0); + return true; +} +#endif +//------------------------------------------------------------------------------ +// wait for card to go not busy +uint8_t Sd2Card::waitNotBusy(unsigned int timeoutMillis) { + unsigned int t0 = millis(); + unsigned int d; + do { + if (spiRec() == 0XFF) { + return true; + } + d = millis() - t0; + } while (d < timeoutMillis); + return false; +} +//------------------------------------------------------------------------------ +/** Wait for start block token */ +uint8_t Sd2Card::waitStartBlock(void) { + unsigned int t0 = millis(); + while ((status_ = spiRec()) == 0XFF) { + unsigned int d = millis() - t0; + if (d > SD_READ_TIMEOUT) { + error(SD_CARD_ERROR_READ_TIMEOUT); + goto fail; + } + } + if (status_ != DATA_START_BLOCK) { + error(SD_CARD_ERROR_READ); + goto fail; + } + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** + Writes a 512 byte block to an SD card. + + \param[in] blockNumber Logical block to be written. + \param[in] src Pointer to the location of the data to be written. + \param[in] blocking If the write should be blocking. + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking) { + #if SD_PROTECT_BLOCK_ZERO + // don't allow write to first block + if (blockNumber == 0) { + error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); + goto fail; + } + #endif // SD_PROTECT_BLOCK_ZERO + + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) { + blockNumber <<= 9; + } + if (cardCommand(CMD24, blockNumber)) { + error(SD_CARD_ERROR_CMD24); + goto fail; + } + if (!writeData(DATA_START_BLOCK, src)) { + goto fail; + } + if (blocking) { + // wait for flash programming to complete + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_TIMEOUT); + goto fail; + } + // response is r2 so get and check two bytes for nonzero + if (cardCommand(CMD13, 0) || spiRec()) { + error(SD_CARD_ERROR_WRITE_PROGRAMMING); + goto fail; + } + } + chipSelectHigh(); + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Write one data block in a multiple block write sequence */ +uint8_t Sd2Card::writeData(const uint8_t* src) { + // wait for previous write to finish + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + error(SD_CARD_ERROR_WRITE_MULTIPLE); + chipSelectHigh(); + return false; + } + return writeData(WRITE_MULTIPLE_TOKEN, src); +} +//------------------------------------------------------------------------------ +// send one block of data for write block or write multiple blocks +uint8_t Sd2Card::writeData(uint8_t token, const uint8_t* src) { + #ifdef OPTIMIZE_HARDWARE_SPI + + // send data - optimized loop + SPDR = token; + + // send two byte per iteration + for (uint16_t i = 0; i < 512; i += 2) { + while (!(SPSR & (1 << SPIF))) + ; + SPDR = src[i]; + while (!(SPSR & (1 << SPIF))) + ; + SPDR = src[i + 1]; + } + + // wait for last data byte + while (!(SPSR & (1 << SPIF))) + ; + + #else // OPTIMIZE_HARDWARE_SPI + spiSend(token); + for (uint16_t i = 0; i < 512; i++) { + spiSend(src[i]); + } + #endif // OPTIMIZE_HARDWARE_SPI + spiSend(0xff); // dummy crc + spiSend(0xff); // dummy crc + + status_ = spiRec(); + if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) { + error(SD_CARD_ERROR_WRITE); + chipSelectHigh(); + return false; + } + return true; +} +//------------------------------------------------------------------------------ +/** Start a write multiple blocks sequence. + + \param[in] blockNumber Address of first block in sequence. + \param[in] eraseCount The number of blocks to be pre-erased. + + \note This function is used with writeData() and writeStop() + for optimized multiple block writes. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) { + #if SD_PROTECT_BLOCK_ZERO + // don't allow write to first block + if (blockNumber == 0) { + error(SD_CARD_ERROR_WRITE_BLOCK_ZERO); + goto fail; + } + #endif // SD_PROTECT_BLOCK_ZERO + // send pre-erase count + if (cardAcmd(ACMD23, eraseCount)) { + error(SD_CARD_ERROR_ACMD23); + goto fail; + } + // use address if not SDHC card + if (type() != SD_CARD_TYPE_SDHC) { + blockNumber <<= 9; + } + if (cardCommand(CMD25, blockNumber)) { + error(SD_CARD_ERROR_CMD25); + goto fail; + } + return true; + +fail: + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** End a write multiple blocks sequence. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t Sd2Card::writeStop(void) { + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + goto fail; + } + spiSend(STOP_TRAN_TOKEN); + if (!waitNotBusy(SD_WRITE_TIMEOUT)) { + goto fail; + } + chipSelectHigh(); + return true; + +fail: + error(SD_CARD_ERROR_STOP_TRAN); + chipSelectHigh(); + return false; +} +//------------------------------------------------------------------------------ +/** Check if the SD card is busy + + \return The value one, true, is returned when is busy and + the value zero, false, is returned for when is NOT busy. +*/ +uint8_t Sd2Card::isBusy(void) { + chipSelectLow(); + byte b = spiRec(); + chipSelectHigh(); + + return (b != 0XFF); +} diff --git a/megaavr/libraries/SD/src/utility/Sd2Card.h b/megaavr/libraries/SD/src/utility/Sd2Card.h new file mode 100755 index 0000000..59ec95b --- /dev/null +++ b/megaavr/libraries/SD/src/utility/Sd2Card.h @@ -0,0 +1,273 @@ +/* Arduino Sd2Card Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino Sd2Card Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino Sd2Card Library. If not, see + . +*/ +#ifndef Sd2Card_h +#define Sd2Card_h +/** + \file + Sd2Card class +*/ +#include "Sd2PinMap.h" +#include "SdInfo.h" +/** Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate(). */ +uint8_t const SPI_FULL_SPEED = 0; +/** Set SCK rate to F_CPU/4. See Sd2Card::setSckRate(). */ +uint8_t const SPI_HALF_SPEED = 1; +/** Set SCK rate to F_CPU/8. Sd2Card::setSckRate(). */ +uint8_t const SPI_QUARTER_SPEED = 2; +/** + USE_SPI_LIB: if set, use the SPI library bundled with Arduino IDE, otherwise + run with a standalone driver for AVR. +*/ +#define USE_SPI_LIB +/** + Define MEGA_SOFT_SPI non-zero to use software SPI on Mega Arduinos. + Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. + + MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used + on Mega Arduinos. Software SPI works well with GPS Shield V1.1 + but many SD cards will fail with GPS Shield V1.0. +*/ +#define MEGA_SOFT_SPI 0 +//------------------------------------------------------------------------------ +#if MEGA_SOFT_SPI && (defined(__AVR_ATmega1280__)||defined(__AVR_ATmega2560__)) + #define SOFTWARE_SPI +#endif // MEGA_SOFT_SPI +//------------------------------------------------------------------------------ +// SPI pin definitions +// +#ifndef SOFTWARE_SPI + // hardware pin defs + + // include pins_arduino.h or variant.h depending on architecture, via Arduino.h + #include + + /** + SD Chip Select pin + + Warning if this pin is redefined the hardware SS will pin will be enabled + as an output by init(). An avr processor will not function as an SPI + master unless SS is set to output mode. + */ + #ifndef SDCARD_SS_PIN + /** The default chip select pin for the SD card is SS. */ + uint8_t const SD_CHIP_SELECT_PIN = SS; + #else + uint8_t const SD_CHIP_SELECT_PIN = SDCARD_SS_PIN; + #endif + + // The following three pins must not be redefined for hardware SPI, + // so ensure that they are taken from pins_arduino.h or variant.h, depending on architecture. + #ifndef SDCARD_MOSI_PIN + /** SPI Master Out Slave In pin */ + uint8_t const SPI_MOSI_PIN = MOSI; + /** SPI Master In Slave Out pin */ + uint8_t const SPI_MISO_PIN = MISO; + /** SPI Clock pin */ + uint8_t const SPI_SCK_PIN = SCK; + #else + uint8_t const SPI_MOSI_PIN = SDCARD_MOSI_PIN; + uint8_t const SPI_MISO_PIN = SDCARD_MISO_PIN; + uint8_t const SPI_SCK_PIN = SDCARD_SCK_PIN; + #endif + + /** optimize loops for hardware SPI */ + #ifndef USE_SPI_LIB + #define OPTIMIZE_HARDWARE_SPI + #endif + +#else // SOFTWARE_SPI + // define software SPI pins so Mega can use unmodified GPS Shield + /** SPI chip select pin */ + uint8_t const SD_CHIP_SELECT_PIN = 10; + /** SPI Master Out Slave In pin */ + uint8_t const SPI_MOSI_PIN = 11; + /** SPI Master In Slave Out pin */ + uint8_t const SPI_MISO_PIN = 12; + /** SPI Clock pin */ + uint8_t const SPI_SCK_PIN = 13; +#endif // SOFTWARE_SPI +//------------------------------------------------------------------------------ +/** Protect block zero from write if nonzero */ +#define SD_PROTECT_BLOCK_ZERO 1 +/** init timeout ms */ +unsigned int const SD_INIT_TIMEOUT = 2000; +/** erase timeout ms */ +unsigned int const SD_ERASE_TIMEOUT = 10000; +/** read timeout ms */ +unsigned int const SD_READ_TIMEOUT = 300; +/** write time out ms */ +unsigned int const SD_WRITE_TIMEOUT = 600; +//------------------------------------------------------------------------------ +// SD card errors +/** timeout error for command CMD0 */ +uint8_t const SD_CARD_ERROR_CMD0 = 0X1; +/** CMD8 was not accepted - not a valid SD card*/ +uint8_t const SD_CARD_ERROR_CMD8 = 0X2; +/** card returned an error response for CMD17 (read block) */ +uint8_t const SD_CARD_ERROR_CMD17 = 0X3; +/** card returned an error response for CMD24 (write block) */ +uint8_t const SD_CARD_ERROR_CMD24 = 0X4; +/** WRITE_MULTIPLE_BLOCKS command failed */ +uint8_t const SD_CARD_ERROR_CMD25 = 0X05; +/** card returned an error response for CMD58 (read OCR) */ +uint8_t const SD_CARD_ERROR_CMD58 = 0X06; +/** SET_WR_BLK_ERASE_COUNT failed */ +uint8_t const SD_CARD_ERROR_ACMD23 = 0X07; +/** card's ACMD41 initialization process timeout */ +uint8_t const SD_CARD_ERROR_ACMD41 = 0X08; +/** card returned a bad CSR version field */ +uint8_t const SD_CARD_ERROR_BAD_CSD = 0X09; +/** erase block group command failed */ +uint8_t const SD_CARD_ERROR_ERASE = 0X0A; +/** card not capable of single block erase */ +uint8_t const SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0X0B; +/** Erase sequence timed out */ +uint8_t const SD_CARD_ERROR_ERASE_TIMEOUT = 0X0C; +/** card returned an error token instead of read data */ +uint8_t const SD_CARD_ERROR_READ = 0X0D; +/** read CID or CSD failed */ +uint8_t const SD_CARD_ERROR_READ_REG = 0X0E; +/** timeout while waiting for start of read data */ +uint8_t const SD_CARD_ERROR_READ_TIMEOUT = 0X0F; +/** card did not accept STOP_TRAN_TOKEN */ +uint8_t const SD_CARD_ERROR_STOP_TRAN = 0X10; +/** card returned an error token as a response to a write operation */ +uint8_t const SD_CARD_ERROR_WRITE = 0X11; +/** attempt to write protected block zero */ +uint8_t const SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0X12; +/** card did not go ready for a multiple block write */ +uint8_t const SD_CARD_ERROR_WRITE_MULTIPLE = 0X13; +/** card returned an error to a CMD13 status check after a write */ +uint8_t const SD_CARD_ERROR_WRITE_PROGRAMMING = 0X14; +/** timeout occurred during write programming */ +uint8_t const SD_CARD_ERROR_WRITE_TIMEOUT = 0X15; +/** incorrect rate selected */ +uint8_t const SD_CARD_ERROR_SCK_RATE = 0X16; +//------------------------------------------------------------------------------ +// card types +/** Standard capacity V1 SD card */ +uint8_t const SD_CARD_TYPE_SD1 = 1; +/** Standard capacity V2 SD card */ +uint8_t const SD_CARD_TYPE_SD2 = 2; +/** High Capacity SD card */ +uint8_t const SD_CARD_TYPE_SDHC = 3; +//------------------------------------------------------------------------------ +/** + \class Sd2Card + \brief Raw access to SD and SDHC flash memory cards. +*/ +class Sd2Card { + public: + /** Construct an instance of Sd2Card. */ + Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0) {} + uint32_t cardSize(void); + uint8_t erase(uint32_t firstBlock, uint32_t lastBlock); + uint8_t eraseSingleBlockEnable(void); + /** + \return error code for last error. See Sd2Card.h for a list of error codes. + */ + uint8_t errorCode(void) const { + return errorCode_; + } + /** \return error data for last error. */ + uint8_t errorData(void) const { + return status_; + } + /** + Initialize an SD flash memory card with default clock rate and chip + select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(void) { + return init(SPI_FULL_SPEED, SD_CHIP_SELECT_PIN); + } + /** + Initialize an SD flash memory card with the selected SPI clock rate + and the default SD chip select pin. + See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin). + */ + uint8_t init(uint8_t sckRateID) { + return init(sckRateID, SD_CHIP_SELECT_PIN); + } + uint8_t init(uint8_t sckRateID, uint8_t chipSelectPin); + void partialBlockRead(uint8_t value); + /** Returns the current value, true or false, for partial block read. */ + uint8_t partialBlockRead(void) const { + return partialBlockRead_; + } + uint8_t readBlock(uint32_t block, uint8_t* dst); + uint8_t readData(uint32_t block, + uint16_t offset, uint16_t count, uint8_t* dst); + /** + Read a cards CID register. The CID contains card identification + information such as Manufacturer ID, Product name, Product serial + number and Manufacturing date. */ + uint8_t readCID(cid_t* cid) { + return readRegister(CMD10, cid); + } + /** + Read a cards CSD register. The CSD contains Card-Specific Data that + provides information regarding access to the card's contents. */ + uint8_t readCSD(csd_t* csd) { + return readRegister(CMD9, csd); + } + void readEnd(void); + uint8_t setSckRate(uint8_t sckRateID); + #ifdef USE_SPI_LIB + uint8_t setSpiClock(uint32_t clock); + #endif + /** Return the card type: SD V1, SD V2 or SDHC */ + uint8_t type(void) const { + return type_; + } + uint8_t writeBlock(uint32_t blockNumber, const uint8_t* src, uint8_t blocking = 1); + uint8_t writeData(const uint8_t* src); + uint8_t writeStart(uint32_t blockNumber, uint32_t eraseCount); + uint8_t writeStop(void); + uint8_t isBusy(void); + private: + uint32_t block_; + uint8_t chipSelectPin_; + uint8_t errorCode_; + uint8_t inBlock_; + uint16_t offset_; + uint8_t partialBlockRead_; + uint8_t status_; + uint8_t type_; + // private functions + uint8_t cardAcmd(uint8_t cmd, uint32_t arg) { + cardCommand(CMD55, 0); + return cardCommand(cmd, arg); + } + uint8_t cardCommand(uint8_t cmd, uint32_t arg); + void error(uint8_t code) { + errorCode_ = code; + } + uint8_t readRegister(uint8_t cmd, void* buf); + uint8_t sendWriteCommand(uint32_t blockNumber, uint32_t eraseCount); + void chipSelectHigh(void); + void chipSelectLow(void); + void type(uint8_t value) { + type_ = value; + } + uint8_t waitNotBusy(unsigned int timeoutMillis); + uint8_t writeData(uint8_t token, const uint8_t* src); + uint8_t waitStartBlock(void); +}; +#endif // Sd2Card_h diff --git a/megaavr/libraries/SD/src/utility/Sd2PinMap.h b/megaavr/libraries/SD/src/utility/Sd2PinMap.h new file mode 100755 index 0000000..8a26848 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/Sd2PinMap.h @@ -0,0 +1,528 @@ +/* Arduino SdFat Library + Copyright (C) 2010 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#if defined(__arm__) // Arduino Due Board follows + +#ifndef Sd2PinMap_h + #define Sd2PinMap_h + + #include + + uint8_t const SS_PIN = SS; + uint8_t const MOSI_PIN = MOSI; + uint8_t const MISO_PIN = MISO; + uint8_t const SCK_PIN = SCK; + +#endif // Sd2PinMap_h + +#elif defined(__AVR_ATmega4809__) || defined(__AVR_ATmega4808__) || \ +defined(__AVR_ATmega3209__) || defined(__AVR_ATmega3208__) || \ +defined(__AVR_ATmega1609__) || defined(__AVR_ATmega1608__) || \ +defined(__AVR_ATmega809__) || defined(__AVR_ATmega808__) + +#ifndef Sd2PinMap_h + #define Sd2PinMap_h + + #include + + uint8_t const SS_PIN = SS; + uint8_t const MOSI_PIN = MOSI; + uint8_t const MISO_PIN = MISO; + uint8_t const SCK_PIN = SCK; + +#endif // Sd2PinMap_h + +#elif defined(__AVR__) // Other AVR based Boards follows + +// Warning this file was generated by a program. +#ifndef Sd2PinMap_h +#define Sd2PinMap_h +#include + +//------------------------------------------------------------------------------ +/** struct for mapping digital pins */ +struct pin_map_t { + volatile uint8_t* ddr; + volatile uint8_t* pin; + volatile uint8_t* port; + uint8_t bit; +}; +//------------------------------------------------------------------------------ +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// Mega + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 20; +uint8_t const SCL_PIN = 21; + +// SPI port +uint8_t const SS_PIN = 53; +uint8_t const MOSI_PIN = 51; +uint8_t const MISO_PIN = 50; +uint8_t const SCK_PIN = 52; + +static const pin_map_t digitalPinMap[] = { + {&DDRE, &PINE, &PORTE, 0}, // E0 0 + {&DDRE, &PINE, &PORTE, 1}, // E1 1 + {&DDRE, &PINE, &PORTE, 4}, // E4 2 + {&DDRE, &PINE, &PORTE, 5}, // E5 3 + {&DDRG, &PING, &PORTG, 5}, // G5 4 + {&DDRE, &PINE, &PORTE, 3}, // E3 5 + {&DDRH, &PINH, &PORTH, 3}, // H3 6 + {&DDRH, &PINH, &PORTH, 4}, // H4 7 + {&DDRH, &PINH, &PORTH, 5}, // H5 8 + {&DDRH, &PINH, &PORTH, 6}, // H6 9 + {&DDRB, &PINB, &PORTB, 4}, // B4 10 + {&DDRB, &PINB, &PORTB, 5}, // B5 11 + {&DDRB, &PINB, &PORTB, 6}, // B6 12 + {&DDRB, &PINB, &PORTB, 7}, // B7 13 + {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14 + {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15 + {&DDRH, &PINH, &PORTH, 1}, // H1 16 + {&DDRH, &PINH, &PORTH, 0}, // H0 17 + {&DDRD, &PIND, &PORTD, 3}, // D3 18 + {&DDRD, &PIND, &PORTD, 2}, // D2 19 + {&DDRD, &PIND, &PORTD, 1}, // D1 20 + {&DDRD, &PIND, &PORTD, 0}, // D0 21 + {&DDRA, &PINA, &PORTA, 0}, // A0 22 + {&DDRA, &PINA, &PORTA, 1}, // A1 23 + {&DDRA, &PINA, &PORTA, 2}, // A2 24 + {&DDRA, &PINA, &PORTA, 3}, // A3 25 + {&DDRA, &PINA, &PORTA, 4}, // A4 26 + {&DDRA, &PINA, &PORTA, 5}, // A5 27 + {&DDRA, &PINA, &PORTA, 6}, // A6 28 + {&DDRA, &PINA, &PORTA, 7}, // A7 29 + {&DDRC, &PINC, &PORTC, 7}, // C7 30 + {&DDRC, &PINC, &PORTC, 6}, // C6 31 + {&DDRC, &PINC, &PORTC, 5}, // C5 32 + {&DDRC, &PINC, &PORTC, 4}, // C4 33 + {&DDRC, &PINC, &PORTC, 3}, // C3 34 + {&DDRC, &PINC, &PORTC, 2}, // C2 35 + {&DDRC, &PINC, &PORTC, 1}, // C1 36 + {&DDRC, &PINC, &PORTC, 0}, // C0 37 + {&DDRD, &PIND, &PORTD, 7}, // D7 38 + {&DDRG, &PING, &PORTG, 2}, // G2 39 + {&DDRG, &PING, &PORTG, 1}, // G1 40 + {&DDRG, &PING, &PORTG, 0}, // G0 41 + {&DDRL, &PINL, &PORTL, 7}, // L7 42 + {&DDRL, &PINL, &PORTL, 6}, // L6 43 + {&DDRL, &PINL, &PORTL, 5}, // L5 44 + {&DDRL, &PINL, &PORTL, 4}, // L4 45 + {&DDRL, &PINL, &PORTL, 3}, // L3 46 + {&DDRL, &PINL, &PORTL, 2}, // L2 47 + {&DDRL, &PINL, &PORTL, 1}, // L1 48 + {&DDRL, &PINL, &PORTL, 0}, // L0 49 + {&DDRB, &PINB, &PORTB, 3}, // B3 50 + {&DDRB, &PINB, &PORTB, 2}, // B2 51 + {&DDRB, &PINB, &PORTB, 1}, // B1 52 + {&DDRB, &PINB, &PORTB, 0}, // B0 53 + {&DDRF, &PINF, &PORTF, 0}, // F0 54 + {&DDRF, &PINF, &PORTF, 1}, // F1 55 + {&DDRF, &PINF, &PORTF, 2}, // F2 56 + {&DDRF, &PINF, &PORTF, 3}, // F3 57 + {&DDRF, &PINF, &PORTF, 4}, // F4 58 + {&DDRF, &PINF, &PORTF, 5}, // F5 59 + {&DDRF, &PINF, &PORTF, 6}, // F6 60 + {&DDRF, &PINF, &PORTF, 7}, // F7 61 + {&DDRK, &PINK, &PORTK, 0}, // K0 62 + {&DDRK, &PINK, &PORTK, 1}, // K1 63 + {&DDRK, &PINK, &PORTK, 2}, // K2 64 + {&DDRK, &PINK, &PORTK, 3}, // K3 65 + {&DDRK, &PINK, &PORTK, 4}, // K4 66 + {&DDRK, &PINK, &PORTK, 5}, // K5 67 + {&DDRK, &PINK, &PORTK, 6}, // K6 68 + {&DDRK, &PINK, &PORTK, 7} // K7 69 +}; +//------------------------------------------------------------------------------ +#elif (defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)) && defined(CORE_MICRODUINO) +// Microduino Core+ + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 20; +uint8_t const SCL_PIN = 21; + +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 0}, // D0 PD0 + {&DDRD, &PIND, &PORTD, 1}, // D1 PD1 + {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 + {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 + {&DDRB, &PINB, &PORTB, 0}, // D4 PB0 + {&DDRB, &PINB, &PORTB, 1}, // D5 PB1 + {&DDRB, &PINB, &PORTB, 2}, // D6 PB2 + {&DDRB, &PINB, &PORTB, 3}, // D7 PB3 + {&DDRD, &PIND, &PORTD, 6}, // D8 PD6 + {&DDRD, &PIND, &PORTD, 5}, // D9 PD5 + {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 + {&DDRB, &PINB, &PORTB, 5}, // D11 PB5 + {&DDRB, &PINB, &PORTB, 6}, // D12 PB6 + {&DDRB, &PINB, &PORTB, 7}, // D13 PB7 + {&DDRC, &PINC, &PORTC, 7}, // D14 PC7 + {&DDRC, &PINC, &PORTC, 6}, // D15 PC6 + {&DDRC, &PINC, &PORTC, 5}, // D16 PC5 + {&DDRC, &PINC, &PORTC, 4}, // D17 PC4 + {&DDRC, &PINC, &PORTC, 3}, // D18 PC3 + {&DDRC, &PINC, &PORTC, 2}, // D19 PC2 + {&DDRC, &PINC, &PORTC, 1}, // D20 PC1 + {&DDRC, &PINC, &PORTC, 0}, // D21 PC0 + {&DDRD, &PIND, &PORTD, 4}, // D22 PD4 + {&DDRD, &PIND, &PORTD, 7}, // D23 PD7 + {&DDRA, &PINA, &PORTA, 7}, // D24 PA7 + {&DDRA, &PINA, &PORTA, 6}, // D25 PA6 + {&DDRA, &PINA, &PORTA, 5}, // D26 PA5 + {&DDRA, &PINA, &PORTA, 4}, // D27 PA4 + {&DDRA, &PINA, &PORTA, 3}, // D28 PA3 + {&DDRA, &PINA, &PORTA, 2}, // D29 PA2 + {&DDRA, &PINA, &PORTA, 1}, // D30 PA1 + {&DDRA, &PINA, &PORTA, 0} // D31 PA0 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega128RFA1__) && defined(CORE_MICRODUINO) +// Microduino Core RF + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 18; +uint8_t const SCL_PIN = 19; + +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PINE, &PORTE, 0}, // D0 PE0 + {&DDRD, &PINE, &PORTE, 1}, // D1 PE1 + {&DDRD, &PIND, &PORTD, 2}, // D2 PD2 + {&DDRD, &PIND, &PORTD, 3}, // D3 PD3 + {&DDRB, &PINE, &PORTE, 3}, // D4 PE3 + {&DDRB, &PINE, &PORTE, 4}, // D5 PE4 + {&DDRB, &PINE, &PORTE, 5}, // D6 PE5 + {&DDRB, &PINB, &PORTB, 7}, // D7 PB7 + {&DDRD, &PINB, &PORTB, 6}, // D8 PB6 + {&DDRD, &PINB, &PORTB, 5}, // D9 PB5 + {&DDRB, &PINB, &PORTB, 4}, // D10 PB4 + {&DDRB, &PINB, &PORTB, 2}, // D11 PB2 + {&DDRB, &PINB, &PORTB, 3}, // D12 PB3 + {&DDRB, &PINB, &PORTB, 1}, // D13 PB1 + {&DDRF, &PINF, &PORTF, 7}, // D14 PF7 + {&DDRF, &PINF, &PORTF, 6}, // D15 PF6 + {&DDRF, &PINF, &PORTF, 5}, // D16 PF5 + {&DDRF, &PINF, &PORTF, 4}, // D17 PF4 + {&DDRD, &PIND, &PORTD, 1}, // D18 PD1 + {&DDRD, &PIND, &PORTD, 0}, // D19 PD0 + {&DDRF, &PINF, &PORTF, 3}, // D20 PF3 + {&DDRF, &PINF, &PORTF, 2}, // D21 PF2 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega32U4__) && defined(CORE_MICRODUINO) +// Microduino Core USB + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 18; +uint8_t const SCL_PIN = 19; + +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 2}, // D0 - PD2 + {&DDRD, &PIND, &PORTD, 3}, // D1 - PD3 + {&DDRE, &PINE, &PORTE, 6}, // D2 - PE6 + {&DDRD, &PIND, &PORTD, 6}, // D3 - PD6 + {&DDRD, &PIND, &PORTD, 7}, // D4 - PD7 + {&DDRC, &PINC, &PORTC, 6}, // D5 - PC6 + {&DDRC, &PINC, &PORTC, 7}, // D6 - PC7 + {&DDRE, &PINE, &PORTE, 7}, // D7 - PE7 + {&DDRB, &PINB, &PORTB, 6}, // D8 - PB6 + {&DDRB, &PINB, &PORTB, 5}, // D9 - PB5 + {&DDRB, &PINB, &PORTB, 0}, // D10 - PB0 + {&DDRB, &PINB, &PORTB, 2}, // D11 - MOSI - PB2 + {&DDRB, &PINB, &PORTB, 3}, // D12 -MISO - PB3 + {&DDRB, &PINB, &PORTB, 1}, // D13 -SCK - PB1 + {&DDRF, &PINF, &PORTF, 7}, // D14 - A0 - PF7 + {&DDRF, &PINF, &PORTF, 6}, // D15 - A1 - PF6 + {&DDRF, &PINF, &PORTF, 5}, // D16 - A2 - PF5 + {&DDRF, &PINF, &PORTF, 4}, // D17 - A3 - PF4 + {&DDRD, &PIND, &PORTD, 1}, // D18 - PD1 + {&DDRD, &PIND, &PORTD, 0}, // D19 - PD0 + {&DDRF, &PINF, &PORTF, 1}, // D20 - A6 - PF1 + {&DDRF, &PINF, &PORTF, 0}, // D21 - A7 - PF0 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) +// Sanguino + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 17; +uint8_t const SCL_PIN = 18; + +// SPI port +uint8_t const SS_PIN = 4; +uint8_t const MOSI_PIN = 5; +uint8_t const MISO_PIN = 6; +uint8_t const SCK_PIN = 7; + +static const pin_map_t digitalPinMap[] = { + {&DDRB, &PINB, &PORTB, 0}, // B0 0 + {&DDRB, &PINB, &PORTB, 1}, // B1 1 + {&DDRB, &PINB, &PORTB, 2}, // B2 2 + {&DDRB, &PINB, &PORTB, 3}, // B3 3 + {&DDRB, &PINB, &PORTB, 4}, // B4 4 + {&DDRB, &PINB, &PORTB, 5}, // B5 5 + {&DDRB, &PINB, &PORTB, 6}, // B6 6 + {&DDRB, &PINB, &PORTB, 7}, // B7 7 + {&DDRD, &PIND, &PORTD, 0}, // D0 8 + {&DDRD, &PIND, &PORTD, 1}, // D1 9 + {&DDRD, &PIND, &PORTD, 2}, // D2 10 + {&DDRD, &PIND, &PORTD, 3}, // D3 11 + {&DDRD, &PIND, &PORTD, 4}, // D4 12 + {&DDRD, &PIND, &PORTD, 5}, // D5 13 + {&DDRD, &PIND, &PORTD, 6}, // D6 14 + {&DDRD, &PIND, &PORTD, 7}, // D7 15 + {&DDRC, &PINC, &PORTC, 0}, // C0 16 + {&DDRC, &PINC, &PORTC, 1}, // C1 17 + {&DDRC, &PINC, &PORTC, 2}, // C2 18 + {&DDRC, &PINC, &PORTC, 3}, // C3 19 + {&DDRC, &PINC, &PORTC, 4}, // C4 20 + {&DDRC, &PINC, &PORTC, 5}, // C5 21 + {&DDRC, &PINC, &PORTC, 6}, // C6 22 + {&DDRC, &PINC, &PORTC, 7}, // C7 23 + {&DDRA, &PINA, &PORTA, 7}, // A7 24 + {&DDRA, &PINA, &PORTA, 6}, // A6 25 + {&DDRA, &PINA, &PORTA, 5}, // A5 26 + {&DDRA, &PINA, &PORTA, 4}, // A4 27 + {&DDRA, &PINA, &PORTA, 3}, // A3 28 + {&DDRA, &PINA, &PORTA, 2}, // A2 29 + {&DDRA, &PINA, &PORTA, 1}, // A1 30 + {&DDRA, &PINA, &PORTA, 0} // A0 31 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_ATmega32U4__) +// Leonardo + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 2; +uint8_t const SCL_PIN = 3; + +// SPI port +uint8_t const SS_PIN = 17; +uint8_t const MOSI_PIN = 16; +uint8_t const MISO_PIN = 14; +uint8_t const SCK_PIN = 15; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 2}, // D2 0 + {&DDRD, &PIND, &PORTD, 3}, // D3 1 + {&DDRD, &PIND, &PORTD, 1}, // D1 2 + {&DDRD, &PIND, &PORTD, 0}, // D0 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRC, &PINC, &PORTC, 6}, // C6 5 + {&DDRD, &PIND, &PORTD, 7}, // D7 6 + {&DDRE, &PINE, &PORTE, 6}, // E6 7 + {&DDRB, &PINB, &PORTB, 4}, // B4 8 + {&DDRB, &PINB, &PORTB, 5}, // B5 9 + {&DDRB, &PINB, &PORTB, 6}, // B6 10 + {&DDRB, &PINB, &PORTB, 7}, // B7 11 + {&DDRD, &PIND, &PORTD, 6}, // D6 12 + {&DDRC, &PINC, &PORTC, 7}, // C7 13 + {&DDRB, &PINB, &PORTB, 3}, // B3 14 + {&DDRB, &PINB, &PORTB, 1}, // B1 15 + {&DDRB, &PINB, &PORTB, 2}, // B2 16 + {&DDRB, &PINB, &PORTB, 0}, // B0 17 + {&DDRF, &PINF, &PORTF, 7}, // F7 18 + {&DDRF, &PINF, &PORTF, 6}, // F6 19 + {&DDRF, &PINF, &PORTF, 5}, // F5 20 + {&DDRF, &PINF, &PORTF, 4}, // F4 21 + {&DDRF, &PINF, &PORTF, 1}, // F1 22 + {&DDRF, &PINF, &PORTF, 0}, // F0 23 +}; +//------------------------------------------------------------------------------ +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +// Teensy++ 1.0 & 2.0 + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 1; +uint8_t const SCL_PIN = 0; + +// SPI port +uint8_t const SS_PIN = 20; +uint8_t const MOSI_PIN = 22; +uint8_t const MISO_PIN = 23; +uint8_t const SCK_PIN = 21; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRE, &PINE, &PORTE, 0}, // E0 8 + {&DDRE, &PINE, &PORTE, 1}, // E1 9 + {&DDRC, &PINC, &PORTC, 0}, // C0 10 + {&DDRC, &PINC, &PORTC, 1}, // C1 11 + {&DDRC, &PINC, &PORTC, 2}, // C2 12 + {&DDRC, &PINC, &PORTC, 3}, // C3 13 + {&DDRC, &PINC, &PORTC, 4}, // C4 14 + {&DDRC, &PINC, &PORTC, 5}, // C5 15 + {&DDRC, &PINC, &PORTC, 6}, // C6 16 + {&DDRC, &PINC, &PORTC, 7}, // C7 17 + {&DDRE, &PINE, &PORTE, 6}, // E6 18 + {&DDRE, &PINE, &PORTE, 7}, // E7 19 + {&DDRB, &PINB, &PORTB, 0}, // B0 20 + {&DDRB, &PINB, &PORTB, 1}, // B1 21 + {&DDRB, &PINB, &PORTB, 2}, // B2 22 + {&DDRB, &PINB, &PORTB, 3}, // B3 23 + {&DDRB, &PINB, &PORTB, 4}, // B4 24 + {&DDRB, &PINB, &PORTB, 5}, // B5 25 + {&DDRB, &PINB, &PORTB, 6}, // B6 26 + {&DDRB, &PINB, &PORTB, 7}, // B7 27 + {&DDRA, &PINA, &PORTA, 0}, // A0 28 + {&DDRA, &PINA, &PORTA, 1}, // A1 29 + {&DDRA, &PINA, &PORTA, 2}, // A2 30 + {&DDRA, &PINA, &PORTA, 3}, // A3 31 + {&DDRA, &PINA, &PORTA, 4}, // A4 32 + {&DDRA, &PINA, &PORTA, 5}, // A5 33 + {&DDRA, &PINA, &PORTA, 6}, // A6 34 + {&DDRA, &PINA, &PORTA, 7}, // A7 35 + {&DDRE, &PINE, &PORTE, 4}, // E4 36 + {&DDRE, &PINE, &PORTE, 5}, // E5 37 + {&DDRF, &PINF, &PORTF, 0}, // F0 38 + {&DDRF, &PINF, &PORTF, 1}, // F1 39 + {&DDRF, &PINF, &PORTF, 2}, // F2 40 + {&DDRF, &PINF, &PORTF, 3}, // F3 41 + {&DDRF, &PINF, &PORTF, 4}, // F4 42 + {&DDRF, &PINF, &PORTF, 5}, // F5 43 + {&DDRF, &PINF, &PORTF, 6}, // F6 44 + {&DDRF, &PINF, &PORTF, 7} // F7 45 +}; +//------------------------------------------------------------------------------ +#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// 168 and 328 Arduinos + +// Two Wire (aka I2C) ports +uint8_t const SDA_PIN = 18; +uint8_t const SCL_PIN = 19; + +// SPI port +uint8_t const SS_PIN = 10; +uint8_t const MOSI_PIN = 11; +uint8_t const MISO_PIN = 12; +uint8_t const SCK_PIN = 13; + +static const pin_map_t digitalPinMap[] = { + {&DDRD, &PIND, &PORTD, 0}, // D0 0 + {&DDRD, &PIND, &PORTD, 1}, // D1 1 + {&DDRD, &PIND, &PORTD, 2}, // D2 2 + {&DDRD, &PIND, &PORTD, 3}, // D3 3 + {&DDRD, &PIND, &PORTD, 4}, // D4 4 + {&DDRD, &PIND, &PORTD, 5}, // D5 5 + {&DDRD, &PIND, &PORTD, 6}, // D6 6 + {&DDRD, &PIND, &PORTD, 7}, // D7 7 + {&DDRB, &PINB, &PORTB, 0}, // B0 8 + {&DDRB, &PINB, &PORTB, 1}, // B1 9 + {&DDRB, &PINB, &PORTB, 2}, // B2 10 + {&DDRB, &PINB, &PORTB, 3}, // B3 11 + {&DDRB, &PINB, &PORTB, 4}, // B4 12 + {&DDRB, &PINB, &PORTB, 5}, // B5 13 + {&DDRC, &PINC, &PORTC, 0}, // C0 14 + {&DDRC, &PINC, &PORTC, 1}, // C1 15 + {&DDRC, &PINC, &PORTC, 2}, // C2 16 + {&DDRC, &PINC, &PORTC, 3}, // C3 17 + {&DDRC, &PINC, &PORTC, 4}, // C4 18 + {&DDRC, &PINC, &PORTC, 5} // C5 19 +}; +#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +//------------------------------------------------------------------------------ +static const uint8_t digitalPinCount = sizeof(digitalPinMap) / sizeof(pin_map_t); + +uint8_t badPinNumber(void) +__attribute__((error("Pin number is too large or not a constant"))); + +static inline __attribute__((always_inline)) +uint8_t getPinMode(uint8_t pin) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1; + } else { + return badPinNumber(); + } +} +static inline __attribute__((always_inline)) +void setPinMode(uint8_t pin, uint8_t mode) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + if (mode) { + *digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit; + } else { + *digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit); + } + } else { + badPinNumber(); + } +} +static inline __attribute__((always_inline)) +uint8_t fastDigitalRead(uint8_t pin) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1; + } else { + return badPinNumber(); + } +} +static inline __attribute__((always_inline)) +void fastDigitalWrite(uint8_t pin, uint8_t value) { + if (__builtin_constant_p(pin) && pin < digitalPinCount) { + if (value) { + *digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit; + } else { + *digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit); + } + } else { + badPinNumber(); + } +} +#endif // Sd2PinMap_h + +#elif defined (__CPU_ARC__) + +#if defined (__ARDUINO_ARC__) + // Two Wire (aka I2C) ports + uint8_t const SDA_PIN = 18; + uint8_t const SCL_PIN = 19; + + // SPI port + uint8_t const SS_PIN = 10; + uint8_t const MOSI_PIN = 11; + uint8_t const MISO_PIN = 12; + uint8_t const SCK_PIN = 13; + +#endif // Arduino ARC + +#else +#error Architecture or board not supported. +#endif diff --git a/megaavr/libraries/SD/src/utility/SdFat.h b/megaavr/libraries/SD/src/utility/SdFat.h new file mode 100755 index 0000000..1c73615 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdFat.h @@ -0,0 +1,641 @@ +/* Arduino SdFat Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#ifndef SdFat_h +#define SdFat_h +/** + \file + SdFile and SdVolume classes +*/ +#if defined (__AVR__) || defined (__CPU_ARC__) + #include +#endif +#include "Sd2Card.h" +#include "FatStructs.h" +#include +//------------------------------------------------------------------------------ +/** + Allow use of deprecated functions if non-zero +*/ +#define ALLOW_DEPRECATED_FUNCTIONS 1 +//------------------------------------------------------------------------------ +// forward declaration since SdVolume is used in SdFile +class SdVolume; +//============================================================================== +// SdFile class + +#ifdef O_RDONLY //ARDUINO_ARCH_MBED + #undef O_READ + #undef O_RDONLY + #undef O_WRITE + #undef O_WRONLY + #undef O_RDWR + #undef O_ACCMODE + #undef O_APPEND + #undef O_SYNC + #undef O_CREAT + #undef O_EXCL + #undef O_TRUNC +#endif + +// flags for ls() +/** ls() flag to print modify date */ +uint8_t const LS_DATE = 1; +/** ls() flag to print file size */ +uint8_t const LS_SIZE = 2; +/** ls() flag for recursive list of subdirectories */ +uint8_t const LS_R = 4; + +// use the gnu style oflag in open() +/** open() oflag for reading */ +uint8_t const O_READ = 0X01; +/** open() oflag - same as O_READ */ +uint8_t const O_RDONLY = O_READ; +/** open() oflag for write */ +uint8_t const O_WRITE = 0X02; +/** open() oflag - same as O_WRITE */ +uint8_t const O_WRONLY = O_WRITE; +/** open() oflag for reading and writing */ +uint8_t const O_RDWR = (O_READ | O_WRITE); +/** open() oflag mask for access modes */ +uint8_t const O_ACCMODE = (O_READ | O_WRITE); +/** The file offset shall be set to the end of the file prior to each write. */ +uint8_t const O_APPEND = 0X04; +/** synchronous writes - call sync() after each write */ +uint8_t const O_SYNC = 0X08; +/** create the file if nonexistent */ +uint8_t const O_CREAT = 0X10; +/** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */ +uint8_t const O_EXCL = 0X20; +/** truncate the file to zero length */ +uint8_t const O_TRUNC = 0X40; + +// flags for timestamp +/** set the file's last access date */ +uint8_t const T_ACCESS = 1; +/** set the file's creation date and time */ +uint8_t const T_CREATE = 2; +/** Set the file's write date and time */ +uint8_t const T_WRITE = 4; +// values for type_ +/** This SdFile has not been opened. */ +uint8_t const FAT_FILE_TYPE_CLOSED = 0; +/** SdFile for a file */ +uint8_t const FAT_FILE_TYPE_NORMAL = 1; +/** SdFile for a FAT16 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT16 = 2; +/** SdFile for a FAT32 root directory */ +uint8_t const FAT_FILE_TYPE_ROOT32 = 3; +/** SdFile for a subdirectory */ +uint8_t const FAT_FILE_TYPE_SUBDIR = 4; +/** Test value for directory type */ +uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16; + +/** date field for FAT directory entry */ +static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { + return (year - 1980) << 9 | month << 5 | day; +} +/** year part of FAT directory date field */ +static inline uint16_t FAT_YEAR(uint16_t fatDate) { + return 1980 + (fatDate >> 9); +} +/** month part of FAT directory date field */ +static inline uint8_t FAT_MONTH(uint16_t fatDate) { + return (fatDate >> 5) & 0XF; +} +/** day part of FAT directory date field */ +static inline uint8_t FAT_DAY(uint16_t fatDate) { + return fatDate & 0X1F; +} +/** time field for FAT directory entry */ +static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { + return hour << 11 | minute << 5 | second >> 1; +} +/** hour part of FAT directory time field */ +static inline uint8_t FAT_HOUR(uint16_t fatTime) { + return fatTime >> 11; +} +/** minute part of FAT directory time field */ +static inline uint8_t FAT_MINUTE(uint16_t fatTime) { + return (fatTime >> 5) & 0X3F; +} +/** second part of FAT directory time field */ +static inline uint8_t FAT_SECOND(uint16_t fatTime) { + return 2 * (fatTime & 0X1F); +} +/** Default date for file timestamps is 1 Jan 2000 */ +uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1; +/** Default time for file timestamp is 1 am */ +uint16_t const FAT_DEFAULT_TIME = (1 << 11); +//------------------------------------------------------------------------------ +/** + \class SdFile + \brief Access FAT16 and FAT32 files on SD and SDHC cards. +*/ +class SdFile : public Print { + public: + /** Create an instance of SdFile. */ + SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {} + /** + writeError is set to true if an error occurs during a write(). + Set writeError to false before calling print() and/or write() and check + for true after calls to print() and/or write(). + */ + //bool writeError; + /** + Cancel unbuffered reads for this file. + See setUnbufferedRead() + */ + void clearUnbufferedRead(void) { + flags_ &= ~F_FILE_UNBUFFERED_READ; + } + uint8_t close(void); + uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + uint8_t createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size); + /** \return The current cluster number for a file or directory. */ + uint32_t curCluster(void) const { + return curCluster_; + } + /** \return The current position for a file or directory. */ + uint32_t curPosition(void) const { + return curPosition_; + } + /** + Set the date/time callback function + + \param[in] dateTime The user's call back function. The callback + function is of the form: + + \code + void dateTime(uint16_t* date, uint16_t* time) { + uint16_t year; + uint8_t month, day, hour, minute, second; + + // User gets date and time from GPS or real-time clock here + + // return date using FAT_DATE macro to format fields + * *date = FAT_DATE(year, month, day); + + // return time using FAT_TIME macro to format fields + * *time = FAT_TIME(hour, minute, second); + } + \endcode + + Sets the function that is called when a file is created or when + a file's directory entry is modified by sync(). All timestamps, + access, creation, and modify, are set when a file is created. + sync() maintains the last access date and last modify date/time. + + See the timestamp() function. + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t* date, uint16_t* time)) { + dateTime_ = dateTime; + } + /** + Cancel the date/time callback function. + */ + static void dateTimeCallbackCancel(void) { + // use explicit zero since NULL is not defined for Sanguino + dateTime_ = 0; + } + /** \return Address of the block that contains this file's directory. */ + uint32_t dirBlock(void) const { + return dirBlock_; + } + uint8_t dirEntry(dir_t* dir); + /** \return Index of this file's directory in the block dirBlock. */ + uint8_t dirIndex(void) const { + return dirIndex_; + } + static void dirName(const dir_t& dir, char* name); + /** \return The total number of bytes in a file or directory. */ + uint32_t fileSize(void) const { + return fileSize_; + } + /** \return The first cluster number for a file or directory. */ + uint32_t firstCluster(void) const { + return firstCluster_; + } + /** \return True if this is a SdFile for a directory else false. */ + uint8_t isDir(void) const { + return type_ >= FAT_FILE_TYPE_MIN_DIR; + } + /** \return True if this is a SdFile for a file else false. */ + uint8_t isFile(void) const { + return type_ == FAT_FILE_TYPE_NORMAL; + } + /** \return True if this is a SdFile for an open file/directory else false. */ + uint8_t isOpen(void) const { + return type_ != FAT_FILE_TYPE_CLOSED; + } + /** \return True if this is a SdFile for a subdirectory else false. */ + uint8_t isSubDir(void) const { + return type_ == FAT_FILE_TYPE_SUBDIR; + } + /** \return True if this is a SdFile for the root directory. */ + uint8_t isRoot(void) const { + return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32; + } + void ls(uint8_t flags = 0, uint8_t indent = 0); + uint8_t makeDir(SdFile* dir, const char* dirName); + uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag); + uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag); + + uint8_t openRoot(SdVolume* vol); + static void printDirName(const dir_t& dir, uint8_t width); + static void printFatDate(uint16_t fatDate); + static void printFatTime(uint16_t fatTime); + static void printTwoDigits(uint8_t v); + /** + Read the next byte from a file. + + \return For success read returns the next byte in the file as an int. + If an error occurs or end of file is reached -1 is returned. + */ + int16_t read(void) { + uint8_t b; + return read(&b, 1) == 1 ? b : -1; + } + int16_t read(void* buf, uint16_t nbyte); + int8_t readDir(dir_t* dir); + static uint8_t remove(SdFile* dirFile, const char* fileName); + uint8_t remove(void); + /** Set the file's current position to zero. */ + void rewind(void) { + curPosition_ = curCluster_ = 0; + } + uint8_t rmDir(void); + uint8_t rmRfStar(void); + /** Set the files position to current position + \a pos. See seekSet(). */ + uint8_t seekCur(uint32_t pos) { + return seekSet(curPosition_ + pos); + } + /** + Set the files current position to end of file. Useful to position + a file for append. See seekSet(). + */ + uint8_t seekEnd(void) { + return seekSet(fileSize_); + } + uint8_t seekSet(uint32_t pos); + /** + Use unbuffered reads to access this file. Used with Wave + Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP. + + Not recommended for normal applications. + */ + void setUnbufferedRead(void) { + if (isFile()) { + flags_ |= F_FILE_UNBUFFERED_READ; + } + } + uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day, + uint8_t hour, uint8_t minute, uint8_t second); + uint8_t sync(uint8_t blocking = 1); + /** Type of this SdFile. You should use isFile() or isDir() instead of type() + if possible. + + \return The file or directory type. + */ + uint8_t type(void) const { + return type_; + } + uint8_t truncate(uint32_t size); + /** \return Unbuffered read flag. */ + uint8_t unbufferedRead(void) const { + return flags_ & F_FILE_UNBUFFERED_READ; + } + /** \return SdVolume that contains this file. */ + SdVolume* volume(void) const { + return vol_; + } + size_t write(uint8_t b); + size_t write(const void* buf, uint16_t nbyte); + size_t write(const char* str); + #ifdef __AVR__ + void write_P(PGM_P str); + void writeln_P(PGM_P str); + #endif + int availableForWrite(void); + //------------------------------------------------------------------------------ + #if ALLOW_DEPRECATED_FUNCTIONS + // Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: + uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock); + */ + uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT + return contiguousRange(&bgnBlock, &endBlock); + } + /** \deprecated Use: + uint8_t SdFile::createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size) + */ + uint8_t createContiguous(SdFile& dirFile, // NOLINT + const char* fileName, uint32_t size) { + return createContiguous(&dirFile, fileName, size); + } + + /** + \deprecated Use: + static void SdFile::dateTimeCallback( + void (*dateTime)(uint16_t* date, uint16_t* time)); + */ + static void dateTimeCallback( + void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT + oldDateTime_ = dateTime; + dateTime_ = dateTime ? oldToNew : 0; + } + /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */ + uint8_t dirEntry(dir_t& dir) { + return dirEntry(&dir); // NOLINT + } + /** \deprecated Use: + uint8_t SdFile::makeDir(SdFile* dir, const char* dirName); + */ + uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT + return makeDir(&dir, dirName); + } + /** \deprecated Use: + uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag); + */ + uint8_t open(SdFile& dirFile, // NOLINT + const char* fileName, uint8_t oflag) { + return open(&dirFile, fileName, oflag); + } + /** \deprecated Do not use in new apps */ + uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT + return open(dirFile, fileName, O_RDWR); + } + /** \deprecated Use: + uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag); + */ + uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT + return open(&dirFile, index, oflag); + } + /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */ + uint8_t openRoot(SdVolume& vol) { + return openRoot(&vol); // NOLINT + } + + /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */ + int8_t readDir(dir_t& dir) { + return readDir(&dir); // NOLINT + } + /** \deprecated Use: + static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName); + */ + static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT + return remove(&dirFile, fileName); + } + //------------------------------------------------------------------------------ + // rest are private + private: + static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT + static void oldToNew(uint16_t* date, uint16_t* time) { + uint16_t d; + uint16_t t; + oldDateTime_(d, t); + *date = d; + *time = t; + } + #endif // ALLOW_DEPRECATED_FUNCTIONS + private: + // bits defined in flags_ + // should be 0XF + static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC); + // available bits + static uint8_t const F_FILE_NON_BLOCKING_WRITE = 0X10; + // a new cluster was added to the file + static uint8_t const F_FILE_CLUSTER_ADDED = 0X20; + // use unbuffered SD read + static uint8_t const F_FILE_UNBUFFERED_READ = 0X40; + // sync of directory entry required + static uint8_t const F_FILE_DIR_DIRTY = 0X80; + + // make sure F_OFLAG is ok + #if ((F_FILE_NON_BLOCKING_WRITE | F_FILE_CLUSTER_ADDED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG) +#error flags_ bits conflict + #endif // flags_ bits + + // private data + uint8_t flags_; // See above for definition of flags_ bits + uint8_t type_; // type of file see above for values + uint32_t curCluster_; // cluster for current file position + uint32_t curPosition_; // current file position in bytes from beginning + uint32_t dirBlock_; // SD block that contains directory entry for file + uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF + uint32_t fileSize_; // file size in bytes + uint32_t firstCluster_; // first cluster of file + SdVolume* vol_; // volume where file is located + + // private functions + uint8_t addCluster(void); + uint8_t addDirCluster(void); + dir_t* cacheDirEntry(uint8_t action); + static void (*dateTime_)(uint16_t* date, uint16_t* time); + static uint8_t make83Name(const char* str, uint8_t* name); + uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags); + dir_t* readDirCache(void); +}; +//============================================================================== +// SdVolume class +/** + \brief Cache for an SD data block +*/ +union cache_t { + /** Used to access cached file data blocks. */ + uint8_t data[512]; + /** Used to access cached FAT16 entries. */ + uint16_t fat16[256]; + /** Used to access cached FAT32 entries. */ + uint32_t fat32[128]; + /** Used to access cached directory entries. */ + dir_t dir[16]; + /** Used to access a cached MasterBoot Record. */ + mbr_t mbr; + /** Used to access to a cached FAT boot sector. */ + fbs_t fbs; +}; +//------------------------------------------------------------------------------ +/** + \class SdVolume + \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. +*/ +class SdVolume { + public: + /** Create an instance of SdVolume */ + SdVolume(void) : allocSearchStart_(2), fatType_(0) {} + /** Clear the cache and returns a pointer to the cache. Used by the WaveRP + recorder to do raw write to the SD card. Not for normal apps. + */ + static uint8_t* cacheClear(void) { + cacheFlush(); + cacheBlockNumber_ = 0XFFFFFFFF; + return cacheBuffer_.data; + } + /** + Initialize a FAT volume. Try partition one first then try super + floppy format. + + \param[in] dev The Sd2Card where the volume is located. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. Reasons for + failure include not finding a valid partition, not finding a valid + FAT file system or an I/O error. + */ + uint8_t init(Sd2Card* dev) { + return init(dev, 1) ? true : init(dev, 0); + } + uint8_t init(Sd2Card* dev, uint8_t part); + + // inline functions that return volume info + /** \return The volume's cluster size in blocks. */ + uint8_t blocksPerCluster(void) const { + return blocksPerCluster_; + } + /** \return The number of blocks in one FAT. */ + uint32_t blocksPerFat(void) const { + return blocksPerFat_; + } + /** \return The total number of clusters in the volume. */ + uint32_t clusterCount(void) const { + return clusterCount_; + } + /** \return The shift count required to multiply by blocksPerCluster. */ + uint8_t clusterSizeShift(void) const { + return clusterSizeShift_; + } + /** \return The logical block number for the start of file data. */ + uint32_t dataStartBlock(void) const { + return dataStartBlock_; + } + /** \return The number of FAT structures on the volume. */ + uint8_t fatCount(void) const { + return fatCount_; + } + /** \return The logical block number for the start of the first FAT. */ + uint32_t fatStartBlock(void) const { + return fatStartBlock_; + } + /** \return The FAT type of the volume. Values are 12, 16 or 32. */ + uint8_t fatType(void) const { + return fatType_; + } + /** \return The number of entries in the root directory for FAT16 volumes. */ + uint32_t rootDirEntryCount(void) const { + return rootDirEntryCount_; + } + /** \return The logical block number for the start of the root directory + on FAT16 volumes or the first cluster number on FAT32 volumes. */ + uint32_t rootDirStart(void) const { + return rootDirStart_; + } + /** return a pointer to the Sd2Card object for this volume */ + static Sd2Card* sdCard(void) { + return sdCard_; + } + //------------------------------------------------------------------------------ + #if ALLOW_DEPRECATED_FUNCTIONS + // Deprecated functions - suppress cpplint warnings with NOLINT comment + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */ + uint8_t init(Sd2Card& dev) { + return init(&dev); // NOLINT + } + + /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */ + uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT + return init(&dev, part); + } + #endif // ALLOW_DEPRECATED_FUNCTIONS + //------------------------------------------------------------------------------ + private: + // Allow SdFile access to SdVolume private data. + friend class SdFile; + + // value for action argument in cacheRawBlock to indicate read from cache + static uint8_t const CACHE_FOR_READ = 0; + // value for action argument in cacheRawBlock to indicate cache dirty + static uint8_t const CACHE_FOR_WRITE = 1; + + static cache_t cacheBuffer_; // 512 byte cache for device blocks + static uint32_t cacheBlockNumber_; // Logical number of block in the cache + static Sd2Card* sdCard_; // Sd2Card object for cache + static uint8_t cacheDirty_; // cacheFlush() will write block if true + static uint32_t cacheMirrorBlock_; // block number for mirror FAT + // + uint32_t allocSearchStart_; // start cluster for alloc search + uint8_t blocksPerCluster_; // cluster size in blocks + uint32_t blocksPerFat_; // FAT size in blocks + uint32_t clusterCount_; // clusters in one FAT + uint8_t clusterSizeShift_; // shift to convert cluster count to block count + uint32_t dataStartBlock_; // first data block number + uint8_t fatCount_; // number of FATs on volume + uint32_t fatStartBlock_; // start block for first FAT + uint8_t fatType_; // volume type (12, 16, OR 32) + uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir + uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 + //---------------------------------------------------------------------------- + uint8_t allocContiguous(uint32_t count, uint32_t* curCluster); + uint8_t blockOfCluster(uint32_t position) const { + return (position >> 9) & (blocksPerCluster_ - 1); + } + uint32_t clusterStartBlock(uint32_t cluster) const { + return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); + } + uint32_t blockNumber(uint32_t cluster, uint32_t position) const { + return clusterStartBlock(cluster) + blockOfCluster(position); + } + static uint8_t cacheFlush(uint8_t blocking = 1); + static uint8_t cacheMirrorBlockFlush(uint8_t blocking); + static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action); + static void cacheSetDirty(void) { + cacheDirty_ |= CACHE_FOR_WRITE; + } + static uint8_t cacheZeroBlock(uint32_t blockNumber); + uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const; + uint8_t fatGet(uint32_t cluster, uint32_t* value) const; + uint8_t fatPut(uint32_t cluster, uint32_t value); + uint8_t fatPutEOC(uint32_t cluster) { + return fatPut(cluster, 0x0FFFFFFF); + } + uint8_t freeChain(uint32_t cluster); + uint8_t isEOC(uint32_t cluster) const { + return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN); + } + uint8_t readBlock(uint32_t block, uint8_t* dst) { + return sdCard_->readBlock(block, dst); + } + uint8_t readData(uint32_t block, uint16_t offset, + uint16_t count, uint8_t* dst) { + return sdCard_->readData(block, offset, count, dst); + } + uint8_t writeBlock(uint32_t block, const uint8_t* dst, uint8_t blocking = 1) { + return sdCard_->writeBlock(block, dst, blocking); + } + uint8_t isBusy(void) { + return sdCard_->isBusy(); + } + uint8_t isCacheMirrorBlockDirty(void) { + return (cacheMirrorBlock_ != 0); + } +}; +#endif // SdFat_h diff --git a/megaavr/libraries/SD/src/utility/SdFatUtil.h b/megaavr/libraries/SD/src/utility/SdFatUtil.h new file mode 100755 index 0000000..2fb6289 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdFatUtil.h @@ -0,0 +1,77 @@ +/* Arduino SdFat Library + Copyright (C) 2008 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#ifndef SdFatUtil_h +#define SdFatUtil_h +/** + \file + Useful utility functions. +*/ +#include +#ifdef __AVR__ + #include + /** Store and print a string in flash memory.*/ + #define PgmPrint(x) SerialPrint_P(PSTR(x)) + /** Store and print a string in flash memory followed by a CR/LF.*/ + #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) + /** Defined so doxygen works for function definitions. */ +#endif +#define NOINLINE __attribute__((noinline,unused)) +#define UNUSEDOK __attribute__((unused)) +//------------------------------------------------------------------------------ +/** Return the number of bytes currently free in RAM. */ +static UNUSEDOK int FreeRam(void) { + extern int __bss_end; + extern int* __brkval; + int free_memory; + if (reinterpret_cast(__brkval) == 0) { + // if no heap use from end of bss section + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(&__bss_end); + } else { + // use from top of stack to heap + free_memory = reinterpret_cast(&free_memory) + - reinterpret_cast(__brkval); + } + return free_memory; +} +#ifdef __AVR__ +//------------------------------------------------------------------------------ +/** + %Print a string in flash memory to the serial port. + + \param[in] str Pointer to string stored in flash memory. +*/ +static NOINLINE void SerialPrint_P(PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) { + Serial.write(c); + } +} +//------------------------------------------------------------------------------ +/** + %Print a string in flash memory followed by a CR/LF. + + \param[in] str Pointer to string stored in flash memory. +*/ +static NOINLINE void SerialPrintln_P(PGM_P str) { + SerialPrint_P(str); + Serial.println(); +} +#endif // __AVR__ +#endif // #define SdFatUtil_h diff --git a/megaavr/libraries/SD/src/utility/SdFatmainpage.h b/megaavr/libraries/SD/src/utility/SdFatmainpage.h new file mode 100755 index 0000000..0a42e85 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdFatmainpage.h @@ -0,0 +1,202 @@ +/* Arduino SdFat Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ + +/** + \mainpage Arduino SdFat Library +
Copyright © 2009 by William Greiman +
+ + \section Intro Introduction + The Arduino SdFat Library is a minimal implementation of FAT16 and FAT32 + file systems on SD flash memory cards. Standard SD and high capacity + SDHC cards are supported. + + The SdFat only supports short 8.3 names. + + The main classes in SdFat are Sd2Card, SdVolume, and SdFile. + + The Sd2Card class supports access to standard SD cards and SDHC cards. Most + applications will only need to call the Sd2Card::init() member function. + + The SdVolume class supports FAT16 and FAT32 partitions. Most applications + will only need to call the SdVolume::init() member function. + + The SdFile class provides file access functions such as open(), read(), + remove(), write(), close() and sync(). This class supports access to the root + directory and subdirectories. + + A number of example are provided in the SdFat/examples folder. These were + developed to test SdFat and illustrate its use. + + SdFat was developed for high speed data recording. SdFat was used to implement + an audio record/play class, WaveRP, for the Adafruit Wave Shield. This + application uses special Sd2Card calls to write to contiguous files in raw mode. + These functions reduce write latency so that audio can be recorded with the + small amount of RAM in the Arduino. + + \section SDcard SD\SDHC Cards + + Arduinos access SD cards using the cards SPI protocol. PCs, Macs, and + most consumer devices use the 4-bit parallel SD protocol. A card that + functions well on A PC or Mac may not work well on the Arduino. + + Most cards have good SPI read performance but cards vary widely in SPI + write performance. Write performance is limited by how efficiently the + card manages internal erase/remapping operations. The Arduino cannot + optimize writes to reduce erase operations because of its limit RAM. + + SanDisk cards generally have good write performance. They seem to have + more internal RAM buffering than other cards and therefore can limit + the number of flash erase operations that the Arduino forces due to its + limited RAM. + + \section Hardware Hardware Configuration + + SdFat was developed using an + Adafruit Industries + Wave Shield. + + The hardware interface to the SD card should not use a resistor based level + shifter. SdFat sets the SPI bus frequency to 8 MHz which results in signal + rise times that are too slow for the edge detectors in many newer SD card + controllers when resistor voltage dividers are used. + + The 5 to 3.3 V level shifter for 5 V Arduinos should be IC based like the + 74HC4050N based circuit shown in the file SdLevel.png. The Adafruit Wave Shield + uses a 74AHC125N. Gravitech sells SD and MicroSD Card Adapters based on the + 74LCX245. + + If you are using a resistor based level shifter and are having problems try + setting the SPI bus frequency to 4 MHz. This can be done by using + card.init(SPI_HALF_SPEED) to initialize the SD card. + + \section comment Bugs and Comments + + If you wish to report bugs or have comments, send email to fat16lib@sbcglobal.net. + + \section SdFatClass SdFat Usage + + SdFat uses a slightly restricted form of short names. + Only printable ASCII characters are supported. No characters with code point + values greater than 127 are allowed. Space is not allowed even though space + was allowed in the API of early versions of DOS. + + Short names are limited to 8 characters followed by an optional period (.) + and extension of up to 3 characters. The characters may be any combination + of letters and digits. The following special characters are also allowed: + + $ % ' - _ @ ~ ` ! ( ) { } ^ # & + + Short names are always converted to upper case and their original case + value is lost. + + \note + The Arduino Print class uses character + at a time writes so it was necessary to use a \link SdFile::sync() sync() \endlink + function to control when data is written to the SD card. + + \par + An application which writes to a file using \link Print::print() print()\endlink, + \link Print::println() println() \endlink + or \link SdFile::write write() \endlink must call \link SdFile::sync() sync() \endlink + at the appropriate time to force data and directory information to be written + to the SD Card. Data and directory information are also written to the SD card + when \link SdFile::close() close() \endlink is called. + + \par + Applications must use care calling \link SdFile::sync() sync() \endlink + since 2048 bytes of I/O is required to update file and + directory information. This includes writing the current data block, reading + the block that contains the directory entry for update, writing the directory + block back and reading back the current data block. + + It is possible to open a file with two or more instances of SdFile. A file may + be corrupted if data is written to the file by more than one instance of SdFile. + + \section HowTo How to format SD Cards as FAT Volumes + + You should use a freshly formatted SD card for best performance. FAT + file systems become slower if many files have been created and deleted. + This is because the directory entry for a deleted file is marked as deleted, + but is not deleted. When a new file is created, these entries must be scanned + before creating the file, a flaw in the FAT design. Also files can become + fragmented which causes reads and writes to be slower. + + Microsoft operating systems support removable media formatted with a + Master Boot Record, MBR, or formatted as a super floppy with a FAT Boot Sector + in block zero. + + Microsoft operating systems expect MBR formatted removable media + to have only one partition. The first partition should be used. + + Microsoft operating systems do not support partitioning SD flash cards. + If you erase an SD card with a program like KillDisk, Most versions of + Windows will format the card as a super floppy. + + The best way to restore an SD card's format is to use SDFormatter + which can be downloaded from: + + http://www.sdcard.org/consumers/formatter/ + + SDFormatter aligns flash erase boundaries with file + system structures which reduces write latency and file system overhead. + + SDFormatter does not have an option for FAT type so it may format + small cards as FAT12. + + After the MBR is restored by SDFormatter you may need to reformat small + cards that have been formatted FAT12 to force the volume type to be FAT16. + + If you reformat the SD card with an OS utility, choose a cluster size that + will result in: + + 4084 < CountOfClusters && CountOfClusters < 65525 + + The volume will then be FAT16. + + If you are formatting an SD card on OS X or Linux, be sure to use the first + partition. Format this partition with a cluster count in above range. + + \section References References + + Adafruit Industries: + + http://www.adafruit.com/ + + http://www.ladyada.net/make/waveshield/ + + The Arduino site: + + http://www.arduino.cc/ + + For more information about FAT file systems see: + + http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx + + For information about using SD cards as SPI devices see: + + http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf + + The ATmega328 datasheet: + + http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf + + +*/ diff --git a/megaavr/libraries/SD/src/utility/SdFile.cpp b/megaavr/libraries/SD/src/utility/SdFile.cpp new file mode 100755 index 0000000..70be4b5 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdFile.cpp @@ -0,0 +1,1527 @@ +/* Arduino SdFat Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#include "SdFat.h" +#ifdef __AVR__ + #include +#endif +#include +//------------------------------------------------------------------------------ +// callback function for date/time +void (*SdFile::dateTime_)(uint16_t* date, uint16_t* time) = NULL; + +#if ALLOW_DEPRECATED_FUNCTIONS + // suppress cpplint warnings with NOLINT comment + void (*SdFile::oldDateTime_)(uint16_t& date, uint16_t& time) = NULL; // NOLINT +#endif // ALLOW_DEPRECATED_FUNCTIONS +//------------------------------------------------------------------------------ +// add a cluster to a file +uint8_t SdFile::addCluster() { + if (!vol_->allocContiguous(1, &curCluster_)) { + return false; + } + + // if first cluster of file link to directory entry + if (firstCluster_ == 0) { + firstCluster_ = curCluster_; + flags_ |= F_FILE_DIR_DIRTY; + } + flags_ |= F_FILE_CLUSTER_ADDED; + return true; +} +//------------------------------------------------------------------------------ +// Add a cluster to a directory file and zero the cluster. +// return with first block of cluster in the cache +uint8_t SdFile::addDirCluster(void) { + if (!addCluster()) { + return false; + } + + // zero data in cluster insure first cluster is in cache + uint32_t block = vol_->clusterStartBlock(curCluster_); + for (uint8_t i = vol_->blocksPerCluster_; i != 0; i--) { + if (!SdVolume::cacheZeroBlock(block + i - 1)) { + return false; + } + } + // Increase directory file size by cluster size + fileSize_ += 512UL << vol_->clusterSizeShift_; + return true; +} +//------------------------------------------------------------------------------ +// cache a file's directory entry +// return pointer to cached entry or null for failure +dir_t* SdFile::cacheDirEntry(uint8_t action) { + if (!SdVolume::cacheRawBlock(dirBlock_, action)) { + return NULL; + } + return SdVolume::cacheBuffer_.dir + dirIndex_; +} +//------------------------------------------------------------------------------ +/** + Close a file and force cached data and directory information + to be written to the storage device. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include no file is open or an I/O error. +*/ +uint8_t SdFile::close(void) { + if (!sync()) { + return false; + } + type_ = FAT_FILE_TYPE_CLOSED; + return true; +} +//------------------------------------------------------------------------------ +/** + Check for contiguous file and return its raw block range. + + \param[out] bgnBlock the first block address for the file. + \param[out] endBlock the last block address for the file. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include file is not contiguous, file has zero length + or an I/O error occurred. +*/ +uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock) { + // error if no blocks + if (firstCluster_ == 0) { + return false; + } + + for (uint32_t c = firstCluster_; ; c++) { + uint32_t next; + if (!vol_->fatGet(c, &next)) { + return false; + } + + // check for contiguous + if (next != (c + 1)) { + // error if not end of chain + if (!vol_->isEOC(next)) { + return false; + } + *bgnBlock = vol_->clusterStartBlock(firstCluster_); + *endBlock = vol_->clusterStartBlock(c) + + vol_->blocksPerCluster_ - 1; + return true; + } + } +} +//------------------------------------------------------------------------------ +/** + Create and open a new contiguous file of a specified size. + + \note This function only supports short DOS 8.3 names. + See open() for more information. + + \param[in] dirFile The directory where the file will be created. + \param[in] fileName A valid DOS 8.3 file name. + \param[in] size The desired file size. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include \a fileName contains + an invalid DOS 8.3 file name, the FAT volume has not been initialized, + a file is already open, the file already exists, the root + directory is full or an I/O error. + +*/ +uint8_t SdFile::createContiguous(SdFile* dirFile, + const char* fileName, uint32_t size) { + // don't allow zero length file + if (size == 0) { + return false; + } + if (!open(dirFile, fileName, O_CREAT | O_EXCL | O_RDWR)) { + return false; + } + + // calculate number of clusters needed + uint32_t count = ((size - 1) >> (vol_->clusterSizeShift_ + 9)) + 1; + + // allocate clusters + if (!vol_->allocContiguous(count, &firstCluster_)) { + remove(); + return false; + } + fileSize_ = size; + + // insure sync() will update dir entry + flags_ |= F_FILE_DIR_DIRTY; + return sync(); +} +//------------------------------------------------------------------------------ +/** + Return a files directory entry + + \param[out] dir Location for return of the files directory entry. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t SdFile::dirEntry(dir_t* dir) { + // make sure fields on SD are correct + if (!sync()) { + return false; + } + + // read entry + dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_READ); + if (!p) { + return false; + } + + // copy to caller's struct + memcpy(dir, p, sizeof(dir_t)); + return true; +} +//------------------------------------------------------------------------------ +/** + Format the name field of \a dir into the 13 byte array + \a name in standard 8.3 short name format. + + \param[in] dir The directory structure containing the name. + \param[out] name A 13 byte char array for the formatted name. +*/ +void SdFile::dirName(const dir_t& dir, char* name) { + uint8_t j = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ') { + continue; + } + if (i == 8) { + name[j++] = '.'; + } + name[j++] = dir.name[i]; + } + name[j] = 0; +} +//------------------------------------------------------------------------------ +/** List directory contents to Serial. + + \param[in] flags The inclusive OR of + + LS_DATE - %Print file modification date + + LS_SIZE - %Print file size. + + LS_R - Recursive list of subdirectories. + + \param[in] indent Amount of space before file name. Used for recursive + list to indicate subdirectory level. +*/ +void SdFile::ls(uint8_t flags, uint8_t indent) { + dir_t* p; + + rewind(); + while ((p = readDirCache())) { + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) { + break; + } + + // skip deleted entry and entries for . and .. + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + continue; + } + + // only list subdirectories and files + if (!DIR_IS_FILE_OR_SUBDIR(p)) { + continue; + } + + // print any indent spaces + for (int8_t i = 0; i < indent; i++) { + Serial.print(' '); + } + + // print file name with possible blank fill + printDirName(*p, flags & (LS_DATE | LS_SIZE) ? 14 : 0); + + // print modify date/time if requested + if (flags & LS_DATE) { + printFatDate(p->lastWriteDate); + Serial.print(' '); + printFatTime(p->lastWriteTime); + } + // print size if requested + if (!DIR_IS_SUBDIR(p) && (flags & LS_SIZE)) { + Serial.print(' '); + Serial.print(p->fileSize); + } + Serial.println(); + + // list subdirectory content if requested + if ((flags & LS_R) && DIR_IS_SUBDIR(p)) { + uint16_t index = curPosition() / 32 - 1; + SdFile s; + if (s.open(this, index, O_READ)) { + s.ls(flags, indent + 2); + } + seekSet(32 * (index + 1)); + } + } +} +//------------------------------------------------------------------------------ +// format directory name field from a 8.3 name string +uint8_t SdFile::make83Name(const char* str, uint8_t* name) { + uint8_t c; + uint8_t n = 7; // max index for part before dot + uint8_t i = 0; + // blank fill name and extension + while (i < 11) { + name[i++] = ' '; + } + i = 0; + while ((c = *str++) != '\0') { + if (c == '.') { + if (n == 10) { + return false; // only one dot allowed + } + n = 10; // max index for full 8.3 name + i = 8; // place for extension + } else { + // illegal FAT characters + uint8_t b; + #if defined(__AVR__) + PGM_P p = PSTR("|<>^+=?/[];,*\"\\"); + while ((b = pgm_read_byte(p++))) if (b == c) { + return false; + } + #elif defined(__arm__) + const uint8_t valid[] = "|<>^+=?/[];,*\"\\"; + const uint8_t *p = valid; + while ((b = *p++)) if (b == c) { + return false; + } + #endif + // check size and only allow ASCII printable characters + if (i > n || c < 0X21 || c > 0X7E) { + return false; + } + // only upper case allowed in 8.3 names - convert lower to upper + name[i++] = c < 'a' || c > 'z' ? c : c + ('A' - 'a'); + } + } + // must have a file name, extension is optional + return name[0] != ' '; +} +//------------------------------------------------------------------------------ +/** Make a new directory. + + \param[in] dir An open SdFat instance for the directory that will containing + the new directory. + + \param[in] dirName A valid 8.3 DOS name for the new directory. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include this SdFile is already open, \a dir is not a + directory, \a dirName is invalid or already exists in \a dir. +*/ +uint8_t SdFile::makeDir(SdFile* dir, const char* dirName) { + dir_t d; + + // create a normal file + if (!open(dir, dirName, O_CREAT | O_EXCL | O_RDWR)) { + return false; + } + + // convert SdFile to directory + flags_ = O_READ; + type_ = FAT_FILE_TYPE_SUBDIR; + + // allocate and zero first cluster + if (!addDirCluster()) { + return false; + } + + // force entry to SD + if (!sync()) { + return false; + } + + // cache entry - should already be in cache due to sync() call + dir_t* p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) { + return false; + } + + // change directory entry attribute + p->attributes = DIR_ATT_DIRECTORY; + + // make entry for '.' + memcpy(&d, p, sizeof(d)); + for (uint8_t i = 1; i < 11; i++) { + d.name[i] = ' '; + } + d.name[0] = '.'; + + // cache block for '.' and '..' + uint32_t block = vol_->clusterStartBlock(firstCluster_); + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { + return false; + } + + // copy '.' to block + memcpy(&SdVolume::cacheBuffer_.dir[0], &d, sizeof(d)); + + // make entry for '..' + d.name[1] = '.'; + if (dir->isRoot()) { + d.firstClusterLow = 0; + d.firstClusterHigh = 0; + } else { + d.firstClusterLow = dir->firstCluster_ & 0XFFFF; + d.firstClusterHigh = dir->firstCluster_ >> 16; + } + // copy '..' to block + memcpy(&SdVolume::cacheBuffer_.dir[1], &d, sizeof(d)); + + // set position after '..' + curPosition_ = 2 * sizeof(d); + + // write first block + return SdVolume::cacheFlush(); +} +//------------------------------------------------------------------------------ +/** + Open a file or directory by name. + + \param[in] dirFile An open SdFat instance for the directory containing the + file to be opened. + + \param[in] fileName A valid 8.3 DOS name for a file to be opened. + + \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + OR of flags from the following list + + O_READ - Open for reading. + + O_RDONLY - Same as O_READ. + + O_WRITE - Open for writing. + + O_WRONLY - Same as O_WRITE. + + O_RDWR - Open for reading and writing. + + O_APPEND - If set, the file offset shall be set to the end of the + file prior to each write. + + O_CREAT - If the file exists, this flag has no effect except as noted + under O_EXCL below. Otherwise, the file shall be created + + O_EXCL - If O_CREAT and O_EXCL are set, open() shall fail if the file exists. + + O_SYNC - Call sync() after each write. This flag should not be used with + write(uint8_t), write_P(PGM_P), writeln_P(PGM_P), or the Arduino Print class. + These functions do character at a time writes so sync() will be called + after each byte. + + O_TRUNC - If the file exists and is a regular file, and the file is + successfully opened and is not read only, its length shall be truncated to 0. + + \note Directory files must be opened read only. Write and truncation is + not allowed for directory files. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include this SdFile is already open, \a difFile is not + a directory, \a fileName is invalid, the file does not exist + or can't be opened in the access mode specified by oflag. +*/ +uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag) { + uint8_t dname[11]; + dir_t* p; + + // error if already open + if (isOpen()) { + return false; + } + + if (!make83Name(fileName, dname)) { + return false; + } + vol_ = dirFile->vol_; + dirFile->rewind(); + + // bool for empty entry found + uint8_t emptyFound = false; + + // search for file + while (dirFile->curPosition_ < dirFile->fileSize_) { + uint8_t index = 0XF & (dirFile->curPosition_ >> 5); + p = dirFile->readDirCache(); + if (p == NULL) { + return false; + } + + if (p->name[0] == DIR_NAME_FREE || p->name[0] == DIR_NAME_DELETED) { + // remember first empty slot + if (!emptyFound) { + emptyFound = true; + dirIndex_ = index; + dirBlock_ = SdVolume::cacheBlockNumber_; + } + // done if no entries follow + if (p->name[0] == DIR_NAME_FREE) { + break; + } + } else if (!memcmp(dname, p->name, 11)) { + // don't open existing file if O_CREAT and O_EXCL + if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { + return false; + } + + // open found file + return openCachedEntry(0XF & index, oflag); + } + } + // only create file if O_CREAT and O_WRITE + if ((oflag & (O_CREAT | O_WRITE)) != (O_CREAT | O_WRITE)) { + return false; + } + + // cache found slot or add cluster if end of file + if (emptyFound) { + p = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!p) { + return false; + } + } else { + if (dirFile->type_ == FAT_FILE_TYPE_ROOT16) { + return false; + } + + // add and zero cluster for dirFile - first cluster is in cache for write + if (!dirFile->addDirCluster()) { + return false; + } + + // use first entry in cluster + dirIndex_ = 0; + p = SdVolume::cacheBuffer_.dir; + } + // initialize as empty file + memset(p, 0, sizeof(dir_t)); + memcpy(p->name, dname, 11); + + // set timestamps + if (dateTime_) { + // call user function + dateTime_(&p->creationDate, &p->creationTime); + } else { + // use default date/time + p->creationDate = FAT_DEFAULT_DATE; + p->creationTime = FAT_DEFAULT_TIME; + } + p->lastAccessDate = p->creationDate; + p->lastWriteDate = p->creationDate; + p->lastWriteTime = p->creationTime; + + // force write of entry to SD + if (!SdVolume::cacheFlush()) { + return false; + } + + // open entry in cache + return openCachedEntry(dirIndex_, oflag); +} +//------------------------------------------------------------------------------ +/** + Open a file by index. + + \param[in] dirFile An open SdFat instance for the directory. + + \param[in] index The \a index of the directory entry for the file to be + opened. The value for \a index is (directory file position)/32. + + \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive + OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC. + + See open() by fileName for definition of flags and return values. + +*/ +uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag) { + // error if already open + if (isOpen()) { + return false; + } + + // don't open existing file if O_CREAT and O_EXCL - user call error + if ((oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { + return false; + } + + vol_ = dirFile->vol_; + + // seek to location of entry + if (!dirFile->seekSet(32 * index)) { + return false; + } + + // read entry into cache + dir_t* p = dirFile->readDirCache(); + if (p == NULL) { + return false; + } + + // error if empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_FREE || + p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + return false; + } + // open cached entry + return openCachedEntry(index & 0XF, oflag); +} +//------------------------------------------------------------------------------ +// open a cached directory entry. Assumes vol_ is initializes +uint8_t SdFile::openCachedEntry(uint8_t dirIndex, uint8_t oflag) { + // location of entry in cache + dir_t* p = SdVolume::cacheBuffer_.dir + dirIndex; + + // write or truncate is an error for a directory or read-only file + if (p->attributes & (DIR_ATT_READ_ONLY | DIR_ATT_DIRECTORY)) { + if (oflag & (O_WRITE | O_TRUNC)) { + return false; + } + } + // remember location of directory entry on SD + dirIndex_ = dirIndex; + dirBlock_ = SdVolume::cacheBlockNumber_; + + // copy first cluster number for directory fields + firstCluster_ = (uint32_t)p->firstClusterHigh << 16; + firstCluster_ |= p->firstClusterLow; + + // make sure it is a normal file or subdirectory + if (DIR_IS_FILE(p)) { + fileSize_ = p->fileSize; + type_ = FAT_FILE_TYPE_NORMAL; + } else if (DIR_IS_SUBDIR(p)) { + if (!vol_->chainSize(firstCluster_, &fileSize_)) { + return false; + } + type_ = FAT_FILE_TYPE_SUBDIR; + } else { + return false; + } + // save open flags for read/write + flags_ = oflag & (O_ACCMODE | O_SYNC | O_APPEND); + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // truncate file to zero length if requested + if (oflag & O_TRUNC) { + return truncate(0); + } + return true; +} +//------------------------------------------------------------------------------ +/** + Open a volume's root directory. + + \param[in] vol The FAT volume containing the root directory to be opened. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include the FAT volume has not been initialized + or it a FAT12 volume. +*/ +uint8_t SdFile::openRoot(SdVolume* vol) { + // error if file is already open + if (isOpen()) { + return false; + } + + if (vol->fatType() == 16) { + type_ = FAT_FILE_TYPE_ROOT16; + firstCluster_ = 0; + fileSize_ = 32 * vol->rootDirEntryCount(); + } else if (vol->fatType() == 32) { + type_ = FAT_FILE_TYPE_ROOT32; + firstCluster_ = vol->rootDirStart(); + if (!vol->chainSize(firstCluster_, &fileSize_)) { + return false; + } + } else { + // volume is not initialized or FAT12 + return false; + } + vol_ = vol; + // read only + flags_ = O_READ; + + // set to start of file + curCluster_ = 0; + curPosition_ = 0; + + // root has no directory entry + dirBlock_ = 0; + dirIndex_ = 0; + return true; +} +//------------------------------------------------------------------------------ +/** %Print the name field of a directory entry in 8.3 format to Serial. + + \param[in] dir The directory structure containing the name. + \param[in] width Blank fill name if length is less than \a width. +*/ +void SdFile::printDirName(const dir_t& dir, uint8_t width) { + uint8_t w = 0; + for (uint8_t i = 0; i < 11; i++) { + if (dir.name[i] == ' ') { + continue; + } + if (i == 8) { + Serial.print('.'); + w++; + } + Serial.write(dir.name[i]); + w++; + } + if (DIR_IS_SUBDIR(&dir)) { + Serial.print('/'); + w++; + } + while (w < width) { + Serial.print(' '); + w++; + } +} +//------------------------------------------------------------------------------ +/** %Print a directory date field to Serial. + + Format is yyyy-mm-dd. + + \param[in] fatDate The date field from a directory entry. +*/ +void SdFile::printFatDate(uint16_t fatDate) { + Serial.print(FAT_YEAR(fatDate)); + Serial.print('-'); + printTwoDigits(FAT_MONTH(fatDate)); + Serial.print('-'); + printTwoDigits(FAT_DAY(fatDate)); +} +//------------------------------------------------------------------------------ +/** %Print a directory time field to Serial. + + Format is hh:mm:ss. + + \param[in] fatTime The time field from a directory entry. +*/ +void SdFile::printFatTime(uint16_t fatTime) { + printTwoDigits(FAT_HOUR(fatTime)); + Serial.print(':'); + printTwoDigits(FAT_MINUTE(fatTime)); + Serial.print(':'); + printTwoDigits(FAT_SECOND(fatTime)); +} +//------------------------------------------------------------------------------ +/** %Print a value as two digits to Serial. + + \param[in] v Value to be printed, 0 <= \a v <= 99 +*/ +void SdFile::printTwoDigits(uint8_t v) { + char str[3]; + str[0] = '0' + v / 10; + str[1] = '0' + v % 10; + str[2] = 0; + Serial.print(str); +} +//------------------------------------------------------------------------------ +/** + Read data from a file starting at the current position. + + \param[out] buf Pointer to the location that will receive the data. + + \param[in] nbyte Maximum number of bytes to read. + + \return For success read() returns the number of bytes read. + A value less than \a nbyte, including zero, will be returned + if end of file is reached. + If an error occurs, read() returns -1. Possible errors include + read() called before a file has been opened, corrupt file system + or an I/O error occurred. +*/ +int16_t SdFile::read(void* buf, uint16_t nbyte) { + uint8_t* dst = reinterpret_cast(buf); + + // error if not open or write only + if (!isOpen() || !(flags_ & O_READ)) { + return -1; + } + + // max bytes left in file + if (nbyte > (fileSize_ - curPosition_)) { + nbyte = fileSize_ - curPosition_; + } + + // amount left to read + uint16_t toRead = nbyte; + while (toRead > 0) { + uint32_t block; // raw device block number + uint16_t offset = curPosition_ & 0X1FF; // offset in block + if (type_ == FAT_FILE_TYPE_ROOT16) { + block = vol_->rootDirStart() + (curPosition_ >> 9); + } else { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + if (offset == 0 && blockOfCluster == 0) { + // start of new cluster + if (curPosition_ == 0) { + // use first cluster in file + curCluster_ = firstCluster_; + } else { + // get next cluster from FAT + if (!vol_->fatGet(curCluster_, &curCluster_)) { + return -1; + } + } + } + block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + } + uint16_t n = toRead; + + // amount to be read from current block + if (n > (512 - offset)) { + n = 512 - offset; + } + + // no buffering needed if n == 512 or user requests no buffering + if ((unbufferedRead() || n == 512) && + block != SdVolume::cacheBlockNumber_) { + if (!vol_->readData(block, offset, n, dst)) { + return -1; + } + dst += n; + } else { + // read block to cache and copy data to caller + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_READ)) { + return -1; + } + uint8_t* src = SdVolume::cacheBuffer_.data + offset; + uint8_t* end = src + n; + while (src != end) { + *dst++ = *src++; + } + } + curPosition_ += n; + toRead -= n; + } + return nbyte; +} +//------------------------------------------------------------------------------ +/** + Read the next directory entry from a directory file. + + \param[out] dir The dir_t struct that will receive the data. + + \return For success readDir() returns the number of bytes read. + A value of zero will be returned if end of file is reached. + If an error occurs, readDir() returns -1. Possible errors include + readDir() called before a directory has been opened, this is not + a directory file or an I/O error occurred. +*/ +int8_t SdFile::readDir(dir_t* dir) { + int8_t n; + // if not a directory file or miss-positioned return an error + if (!isDir() || (0X1F & curPosition_)) { + return -1; + } + + while ((n = read(dir, sizeof(dir_t))) == sizeof(dir_t)) { + // last entry if DIR_NAME_FREE + if (dir->name[0] == DIR_NAME_FREE) { + break; + } + // skip empty entries and entry for . and .. + if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') { + continue; + } + // return if normal file or subdirectory + if (DIR_IS_FILE_OR_SUBDIR(dir)) { + return n; + } + } + // error, end of file, or past last entry + return n < 0 ? -1 : 0; +} +//------------------------------------------------------------------------------ +// Read next directory entry into the cache +// Assumes file is correctly positioned +dir_t* SdFile::readDirCache(void) { + // error if not directory + if (!isDir()) { + return NULL; + } + + // index of entry in cache + uint8_t i = (curPosition_ >> 5) & 0XF; + + // use read to locate and cache block + if (read() < 0) { + return NULL; + } + + // advance to next entry + curPosition_ += 31; + + // return pointer to entry + return (SdVolume::cacheBuffer_.dir + i); +} +//------------------------------------------------------------------------------ +/** + Remove a file. + + The directory entry and all data for the file are deleted. + + \note This function should not be used to delete the 8.3 version of a + file that has a long name. For example if a file has the long name + "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include the file read-only, is a directory, + or an I/O error occurred. +*/ +uint8_t SdFile::remove(void) { + // free any clusters - will fail if read-only or directory + if (!truncate(0)) { + return false; + } + + // cache directory entry + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) { + return false; + } + + // mark entry deleted + d->name[0] = DIR_NAME_DELETED; + + // set this SdFile closed + type_ = FAT_FILE_TYPE_CLOSED; + + // write entry to SD + return SdVolume::cacheFlush(); +} +//------------------------------------------------------------------------------ +/** + Remove a file. + + The directory entry and all data for the file are deleted. + + \param[in] dirFile The directory that contains the file. + \param[in] fileName The name of the file to be removed. + + \note This function should not be used to delete the 8.3 version of a + file that has a long name. For example if a file has the long name + "New Text Document.txt" you should not delete the 8.3 name "NEWTEX~1.TXT". + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include the file is a directory, is read only, + \a dirFile is not a directory, \a fileName is not found + or an I/O error occurred. +*/ +uint8_t SdFile::remove(SdFile* dirFile, const char* fileName) { + SdFile file; + if (!file.open(dirFile, fileName, O_WRITE)) { + return false; + } + return file.remove(); +} +//------------------------------------------------------------------------------ +/** Remove a directory file. + + The directory file will be removed only if it is empty and is not the + root directory. rmDir() follows DOS and Windows and ignores the + read-only attribute for the directory. + + \note This function should not be used to delete the 8.3 version of a + directory that has a long name. For example if a directory has the + long name "New folder" you should not delete the 8.3 name "NEWFOL~1". + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include the file is not a directory, is the root + directory, is not empty, or an I/O error occurred. +*/ +uint8_t SdFile::rmDir(void) { + // must be open subdirectory + if (!isSubDir()) { + return false; + } + + rewind(); + + // make sure directory is empty + while (curPosition_ < fileSize_) { + dir_t* p = readDirCache(); + if (p == NULL) { + return false; + } + // done if past last used entry + if (p->name[0] == DIR_NAME_FREE) { + break; + } + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + continue; + } + // error not empty + if (DIR_IS_FILE_OR_SUBDIR(p)) { + return false; + } + } + // convert empty directory to normal file for remove + type_ = FAT_FILE_TYPE_NORMAL; + flags_ |= O_WRITE; + return remove(); +} +//------------------------------------------------------------------------------ +/** Recursively delete a directory and all contained files. + + This is like the Unix/Linux 'rm -rf *' if called with the root directory + hence the name. + + Warning - This will remove all contents of the directory including + subdirectories. The directory will then be removed if it is not root. + The read-only attribute for files will be ignored. + + \note This function should not be used to delete the 8.3 version of + a directory that has a long name. See remove() and rmDir(). + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t SdFile::rmRfStar(void) { + rewind(); + while (curPosition_ < fileSize_) { + SdFile f; + + // remember position + uint16_t index = curPosition_ / 32; + + dir_t* p = readDirCache(); + if (!p) { + return false; + } + + // done if past last entry + if (p->name[0] == DIR_NAME_FREE) { + break; + } + + // skip empty slot or '.' or '..' + if (p->name[0] == DIR_NAME_DELETED || p->name[0] == '.') { + continue; + } + + // skip if part of long file name or volume label in root + if (!DIR_IS_FILE_OR_SUBDIR(p)) { + continue; + } + + if (!f.open(this, index, O_READ)) { + return false; + } + if (f.isSubDir()) { + // recursively delete + if (!f.rmRfStar()) { + return false; + } + } else { + // ignore read-only + f.flags_ |= O_WRITE; + if (!f.remove()) { + return false; + } + } + // position to next entry if required + if (curPosition_ != (32u * (index + 1))) { + if (!seekSet(32u * (index + 1))) { + return false; + } + } + } + // don't try to delete root + if (isRoot()) { + return true; + } + return rmDir(); +} +//------------------------------------------------------------------------------ +/** + Sets a file's position. + + \param[in] pos The new position in bytes from the beginning of the file. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t SdFile::seekSet(uint32_t pos) { + // error if file not open or seek past end of file + if (!isOpen() || pos > fileSize_) { + return false; + } + + if (type_ == FAT_FILE_TYPE_ROOT16) { + curPosition_ = pos; + return true; + } + if (pos == 0) { + // set position to start of file + curCluster_ = 0; + curPosition_ = 0; + return true; + } + // calculate cluster index for cur and new position + uint32_t nCur = (curPosition_ - 1) >> (vol_->clusterSizeShift_ + 9); + uint32_t nNew = (pos - 1) >> (vol_->clusterSizeShift_ + 9); + + if (nNew < nCur || curPosition_ == 0) { + // must follow chain from first cluster + curCluster_ = firstCluster_; + } else { + // advance from curPosition + nNew -= nCur; + } + while (nNew--) { + if (!vol_->fatGet(curCluster_, &curCluster_)) { + return false; + } + } + curPosition_ = pos; + return true; +} +//------------------------------------------------------------------------------ +/** + The sync() call causes all modified data and directory fields + to be written to the storage device. + + \param[in] blocking If the sync should block until fully complete. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include a call to sync() before a file has been + opened or an I/O error. +*/ +uint8_t SdFile::sync(uint8_t blocking) { + // only allow open files and directories + if (!isOpen()) { + return false; + } + + if (flags_ & F_FILE_DIR_DIRTY) { + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) { + return false; + } + + // do not set filesize for dir files + if (!isDir()) { + d->fileSize = fileSize_; + } + + // update first cluster fields + d->firstClusterLow = firstCluster_ & 0XFFFF; + d->firstClusterHigh = firstCluster_ >> 16; + + // set modify time if user supplied a callback date/time function + if (dateTime_) { + dateTime_(&d->lastWriteDate, &d->lastWriteTime); + d->lastAccessDate = d->lastWriteDate; + } + // clear directory dirty + flags_ &= ~F_FILE_DIR_DIRTY; + } + + if (!blocking) { + flags_ &= ~F_FILE_NON_BLOCKING_WRITE; + } + + return SdVolume::cacheFlush(blocking); +} +//------------------------------------------------------------------------------ +/** + Set a file's timestamps in its directory entry. + + \param[in] flags Values for \a flags are constructed by a bitwise-inclusive + OR of flags from the following list + + T_ACCESS - Set the file's last access date. + + T_CREATE - Set the file's creation date and time. + + T_WRITE - Set the file's last write/modification date and time. + + \param[in] year Valid range 1980 - 2107 inclusive. + + \param[in] month Valid range 1 - 12 inclusive. + + \param[in] day Valid range 1 - 31 inclusive. + + \param[in] hour Valid range 0 - 23 inclusive. + + \param[in] minute Valid range 0 - 59 inclusive. + + \param[in] second Valid range 0 - 59 inclusive + + \note It is possible to set an invalid date since there is no check for + the number of days in a month. + + \note + Modify and access timestamps may be overwritten if a date time callback + function has been set by dateTimeCallback(). + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. +*/ +uint8_t SdFile::timestamp(uint8_t flags, uint16_t year, uint8_t month, + uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) { + if (!isOpen() + || year < 1980 + || year > 2107 + || month < 1 + || month > 12 + || day < 1 + || day > 31 + || hour > 23 + || minute > 59 + || second > 59) { + return false; + } + dir_t* d = cacheDirEntry(SdVolume::CACHE_FOR_WRITE); + if (!d) { + return false; + } + + uint16_t dirDate = FAT_DATE(year, month, day); + uint16_t dirTime = FAT_TIME(hour, minute, second); + if (flags & T_ACCESS) { + d->lastAccessDate = dirDate; + } + if (flags & T_CREATE) { + d->creationDate = dirDate; + d->creationTime = dirTime; + // seems to be units of 1/100 second not 1/10 as Microsoft states + d->creationTimeTenths = second & 1 ? 100 : 0; + } + if (flags & T_WRITE) { + d->lastWriteDate = dirDate; + d->lastWriteTime = dirTime; + } + SdVolume::cacheSetDirty(); + return sync(); +} +//------------------------------------------------------------------------------ +/** + Truncate a file to a specified length. The current file position + will be maintained if it is less than or equal to \a length otherwise + it will be set to end of file. + + \param[in] length The desired length for the file. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. + Reasons for failure include file is read only, file is a directory, + \a length is greater than the current file size or an I/O error occurs. +*/ +uint8_t SdFile::truncate(uint32_t length) { + // error if not a normal file or read-only + if (!isFile() || !(flags_ & O_WRITE)) { + return false; + } + + // error if length is greater than current size + if (length > fileSize_) { + return false; + } + + // fileSize and length are zero - nothing to do + if (fileSize_ == 0) { + return true; + } + + // remember position for seek after truncation + uint32_t newPos = curPosition_ > length ? length : curPosition_; + + // position to last cluster in truncated file + if (!seekSet(length)) { + return false; + } + + if (length == 0) { + // free all clusters + if (!vol_->freeChain(firstCluster_)) { + return false; + } + firstCluster_ = 0; + } else { + uint32_t toFree; + if (!vol_->fatGet(curCluster_, &toFree)) { + return false; + } + + if (!vol_->isEOC(toFree)) { + // free extra clusters + if (!vol_->freeChain(toFree)) { + return false; + } + + // current cluster is end of chain + if (!vol_->fatPutEOC(curCluster_)) { + return false; + } + } + } + fileSize_ = length; + + // need to update directory entry + flags_ |= F_FILE_DIR_DIRTY; + + if (!sync()) { + return false; + } + + // set file to correct position + return seekSet(newPos); +} +//------------------------------------------------------------------------------ +/** + Write data to an open file. + + \note Data is moved to the cache but may not be written to the + storage device until sync() is called. + + \param[in] buf Pointer to the location of the data to be written. + + \param[in] nbyte Number of bytes to write. + + \return For success write() returns the number of bytes written, always + \a nbyte. If an error occurs, write() returns 0. Possible errors + include write() is called before a file has been opened, write is called + for a read-only file, device is full, a corrupt file system or an I/O error. + +*/ +size_t SdFile::write(const void* buf, uint16_t nbyte) { + // convert void* to uint8_t* - must be before goto statements + const uint8_t* src = reinterpret_cast(buf); + + // number of bytes left to write - must be before goto statements + uint16_t nToWrite = nbyte; + // if blocking writes should be used + uint8_t blocking = (flags_ & F_FILE_NON_BLOCKING_WRITE) == 0x00; + + // error if not a normal file or is read-only + if (!isFile() || !(flags_ & O_WRITE)) { + goto writeErrorReturn; + } + + // seek to end of file if append flag + if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { + if (!seekEnd()) { + goto writeErrorReturn; + } + } + + while (nToWrite > 0) { + uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_); + uint16_t blockOffset = curPosition_ & 0X1FF; + if (blockOfCluster == 0 && blockOffset == 0) { + // start of new cluster + if (curCluster_ == 0) { + if (firstCluster_ == 0) { + // allocate first cluster of file + if (!addCluster()) { + goto writeErrorReturn; + } + } else { + curCluster_ = firstCluster_; + } + } else { + uint32_t next; + if (!vol_->fatGet(curCluster_, &next)) { + return false; + } + if (vol_->isEOC(next)) { + // add cluster if at end of chain + if (!addCluster()) { + goto writeErrorReturn; + } + } else { + curCluster_ = next; + } + } + } + // max space in block + uint16_t n = 512 - blockOffset; + + // lesser of space and amount to write + if (n > nToWrite) { + n = nToWrite; + } + + // block for data write + uint32_t block = vol_->clusterStartBlock(curCluster_) + blockOfCluster; + if (n == 512) { + // full block - don't need to use cache + // invalidate cache if block is in cache + if (SdVolume::cacheBlockNumber_ == block) { + SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; + } + if (!vol_->writeBlock(block, src, blocking)) { + goto writeErrorReturn; + } + src += 512; + } else { + if (blockOffset == 0 && curPosition_ >= fileSize_) { + // start of new block don't need to read into cache + if (!SdVolume::cacheFlush()) { + goto writeErrorReturn; + } + SdVolume::cacheBlockNumber_ = block; + SdVolume::cacheSetDirty(); + } else { + // rewrite part of block + if (!SdVolume::cacheRawBlock(block, SdVolume::CACHE_FOR_WRITE)) { + goto writeErrorReturn; + } + } + uint8_t* dst = SdVolume::cacheBuffer_.data + blockOffset; + uint8_t* end = dst + n; + while (dst != end) { + *dst++ = *src++; + } + } + nToWrite -= n; + curPosition_ += n; + } + if (curPosition_ > fileSize_) { + // update fileSize and insure sync will update dir entry + fileSize_ = curPosition_; + flags_ |= F_FILE_DIR_DIRTY; + } else if (dateTime_ && nbyte) { + // insure sync will update modified date and time + flags_ |= F_FILE_DIR_DIRTY; + } + + if (flags_ & O_SYNC) { + if (!sync()) { + goto writeErrorReturn; + } + } + return nbyte; + +writeErrorReturn: + // return for write error + //writeError = true; + setWriteError(); + return 0; +} +//------------------------------------------------------------------------------ +/** + Write a byte to a file. Required by the Arduino Print class. + + Use SdFile::writeError to check for errors. +*/ +size_t SdFile::write(uint8_t b) { + return write(&b, 1); +} +//------------------------------------------------------------------------------ +/** + Write a string to a file. Used by the Arduino Print class. + + Use SdFile::writeError to check for errors. +*/ +size_t SdFile::write(const char* str) { + return write(str, strlen(str)); +} +#ifdef __AVR__ +//------------------------------------------------------------------------------ +/** + Write a PROGMEM string to a file. + + Use SdFile::writeError to check for errors. +*/ +void SdFile::write_P(PGM_P str) { + for (uint8_t c; (c = pgm_read_byte(str)); str++) { + write(c); + } +} +//------------------------------------------------------------------------------ +/** + Write a PROGMEM string followed by CR/LF to a file. + + Use SdFile::writeError to check for errors. +*/ +void SdFile::writeln_P(PGM_P str) { + write_P(str); + println(); +} +#endif +//------------------------------------------------------------------------------ +/** + Check how many bytes can be written without blocking. + + \return The number of bytes that can be written without blocking. +*/ +int SdFile::availableForWrite() { + if (!isFile() || !(flags_ & O_WRITE)) { + return 0; + } + + // seek to end of file if append flag + if ((flags_ & O_APPEND) && curPosition_ != fileSize_) { + if (!seekEnd()) { + return 0; + } + } + + if (vol_->isBusy()) { + return 0; + } + + if (flags_ & F_FILE_CLUSTER_ADDED) { + // new cluster added, trigger a non-blocking sync + sync(0); + flags_ &= ~F_FILE_CLUSTER_ADDED; + return 0; + } + + if (vol_->isCacheMirrorBlockDirty()) { + // cache mirror block is dirty, trigger a non-blocking sync + vol_->cacheMirrorBlockFlush(0); + return 0; + } + + flags_ |= F_FILE_NON_BLOCKING_WRITE; + + uint16_t blockOffset = curPosition_ & 0X1FF; + uint16_t n = 512 - blockOffset; + + return n; +} diff --git a/megaavr/libraries/SD/src/utility/SdInfo.h b/megaavr/libraries/SD/src/utility/SdInfo.h new file mode 100755 index 0000000..e9c80db --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdInfo.h @@ -0,0 +1,232 @@ +/* Arduino Sd2Card Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino Sd2Card Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino Sd2Card Library. If not, see + . +*/ +#ifndef SdInfo_h +#define SdInfo_h +#include +// Based on the document: +// +// SD Specifications +// Part 1 +// Physical Layer +// Simplified Specification +// Version 2.00 +// September 25, 2006 +// +// www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf +//------------------------------------------------------------------------------ +// SD card commands +/** GO_IDLE_STATE - init card in spi mode if CS low */ +uint8_t const CMD0 = 0X00; +/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/ +uint8_t const CMD8 = 0X08; +/** SEND_CSD - read the Card Specific Data (CSD register) */ +uint8_t const CMD9 = 0X09; +/** SEND_CID - read the card identification information (CID register) */ +uint8_t const CMD10 = 0X0A; +/** SEND_STATUS - read the card status register */ +uint8_t const CMD13 = 0X0D; +/** READ_BLOCK - read a single data block from the card */ +uint8_t const CMD17 = 0X11; +/** WRITE_BLOCK - write a single data block to the card */ +uint8_t const CMD24 = 0X18; +/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */ +uint8_t const CMD25 = 0X19; +/** ERASE_WR_BLK_START - sets the address of the first block to be erased */ +uint8_t const CMD32 = 0X20; +/** ERASE_WR_BLK_END - sets the address of the last block of the continuous + range to be erased*/ +uint8_t const CMD33 = 0X21; +/** ERASE - erase all previously selected blocks */ +uint8_t const CMD38 = 0X26; +/** APP_CMD - escape for application specific command */ +uint8_t const CMD55 = 0X37; +/** READ_OCR - read the OCR register of a card */ +uint8_t const CMD58 = 0X3A; +/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be + pre-erased before writing */ +uint8_t const ACMD23 = 0X17; +/** SD_SEND_OP_COMD - Sends host capacity support information and + activates the card's initialization process */ +uint8_t const ACMD41 = 0X29; +//------------------------------------------------------------------------------ +/** status for card in the ready state */ +uint8_t const R1_READY_STATE = 0X00; +/** status for card in the idle state */ +uint8_t const R1_IDLE_STATE = 0X01; +/** status bit for illegal command */ +uint8_t const R1_ILLEGAL_COMMAND = 0X04; +/** start data token for read or write single block*/ +uint8_t const DATA_START_BLOCK = 0XFE; +/** stop token for write multiple blocks*/ +uint8_t const STOP_TRAN_TOKEN = 0XFD; +/** start data token for write multiple blocks*/ +uint8_t const WRITE_MULTIPLE_TOKEN = 0XFC; +/** mask for data response tokens after a write block operation */ +uint8_t const DATA_RES_MASK = 0X1F; +/** write data accepted token */ +uint8_t const DATA_RES_ACCEPTED = 0X05; +//------------------------------------------------------------------------------ +typedef struct CID { + // byte 0 + uint8_t mid; // Manufacturer ID + // byte 1-2 + char oid[2]; // OEM/Application ID + // byte 3-7 + char pnm[5]; // Product name + // byte 8 + unsigned prv_m : 4; // Product revision n.m + unsigned prv_n : 4; + // byte 9-12 + uint32_t psn; // Product serial number + // byte 13 + unsigned mdt_year_high : 4; // Manufacturing date + unsigned reserved : 4; + // byte 14 + unsigned mdt_month : 4; + unsigned mdt_year_low : 4; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +} cid_t; +//------------------------------------------------------------------------------ +// CSD for version 1.00 cards +typedef struct CSDV1 { + // byte 0 + unsigned reserved1 : 6; + unsigned csd_ver : 2; + // byte 1 + uint8_t taac; + // byte 2 + uint8_t nsac; + // byte 3 + uint8_t tran_speed; + // byte 4 + uint8_t ccc_high; + // byte 5 + unsigned read_bl_len : 4; + unsigned ccc_low : 4; + // byte 6 + unsigned c_size_high : 2; + unsigned reserved2 : 2; + unsigned dsr_imp : 1; + unsigned read_blk_misalign : 1; + unsigned write_blk_misalign : 1; + unsigned read_bl_partial : 1; + // byte 7 + uint8_t c_size_mid; + // byte 8 + unsigned vdd_r_curr_max : 3; + unsigned vdd_r_curr_min : 3; + unsigned c_size_low : 2; + // byte 9 + unsigned c_size_mult_high : 2; + unsigned vdd_w_cur_max : 3; + unsigned vdd_w_curr_min : 3; + // byte 10 + unsigned sector_size_high : 6; + unsigned erase_blk_en : 1; + unsigned c_size_mult_low : 1; + // byte 11 + unsigned wp_grp_size : 7; + unsigned sector_size_low : 1; + // byte 12 + unsigned write_bl_len_high : 2; + unsigned r2w_factor : 3; + unsigned reserved3 : 2; + unsigned wp_grp_enable : 1; + // byte 13 + unsigned reserved4 : 5; + unsigned write_partial : 1; + unsigned write_bl_len_low : 2; + // byte 14 + unsigned reserved5: 2; + unsigned file_format : 2; + unsigned tmp_write_protect : 1; + unsigned perm_write_protect : 1; + unsigned copy : 1; + unsigned file_format_grp : 1; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +} csd1_t; +//------------------------------------------------------------------------------ +// CSD for version 2.00 cards +typedef struct CSDV2 { + // byte 0 + unsigned reserved1 : 6; + unsigned csd_ver : 2; + // byte 1 + uint8_t taac; + // byte 2 + uint8_t nsac; + // byte 3 + uint8_t tran_speed; + // byte 4 + uint8_t ccc_high; + // byte 5 + unsigned read_bl_len : 4; + unsigned ccc_low : 4; + // byte 6 + unsigned reserved2 : 4; + unsigned dsr_imp : 1; + unsigned read_blk_misalign : 1; + unsigned write_blk_misalign : 1; + unsigned read_bl_partial : 1; + // byte 7 + unsigned reserved3 : 2; + unsigned c_size_high : 6; + // byte 8 + uint8_t c_size_mid; + // byte 9 + uint8_t c_size_low; + // byte 10 + unsigned sector_size_high : 6; + unsigned erase_blk_en : 1; + unsigned reserved4 : 1; + // byte 11 + unsigned wp_grp_size : 7; + unsigned sector_size_low : 1; + // byte 12 + unsigned write_bl_len_high : 2; + unsigned r2w_factor : 3; + unsigned reserved5 : 2; + unsigned wp_grp_enable : 1; + // byte 13 + unsigned reserved6 : 5; + unsigned write_partial : 1; + unsigned write_bl_len_low : 2; + // byte 14 + unsigned reserved7: 2; + unsigned file_format : 2; + unsigned tmp_write_protect : 1; + unsigned perm_write_protect : 1; + unsigned copy : 1; + unsigned file_format_grp : 1; + // byte 15 + unsigned always1 : 1; + unsigned crc : 7; +} csd2_t; +//------------------------------------------------------------------------------ +// union of old and new style CSD register +union csd_t { + csd1_t v1; + csd2_t v2; +}; +#endif // SdInfo_h diff --git a/megaavr/libraries/SD/src/utility/SdVolume.cpp b/megaavr/libraries/SD/src/utility/SdVolume.cpp new file mode 100755 index 0000000..b8b6025 --- /dev/null +++ b/megaavr/libraries/SD/src/utility/SdVolume.cpp @@ -0,0 +1,351 @@ +/* Arduino SdFat Library + Copyright (C) 2009 by William Greiman + + This file is part of the Arduino SdFat Library + + This Library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Arduino SdFat Library. If not, see + . +*/ +#include "SdFat.h" +//------------------------------------------------------------------------------ +// raw block cache +// init cacheBlockNumber_to invalid SD block number +uint32_t SdVolume::cacheBlockNumber_ = 0XFFFFFFFF; +cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card +Sd2Card* SdVolume::sdCard_; // pointer to SD card object +uint8_t SdVolume::cacheDirty_ = 0; // cacheFlush() will write block if true +uint32_t SdVolume::cacheMirrorBlock_ = 0; // mirror block for second FAT +//------------------------------------------------------------------------------ +// find a contiguous group of clusters +uint8_t SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) { + // start of group + uint32_t bgnCluster; + + // flag to save place to start next search + uint8_t setStart; + + // set search start cluster + if (*curCluster) { + // try to make file contiguous + bgnCluster = *curCluster + 1; + + // don't save new start location + setStart = false; + } else { + // start at likely place for free cluster + bgnCluster = allocSearchStart_; + + // save next search start if one cluster + setStart = 1 == count; + } + // end of group + uint32_t endCluster = bgnCluster; + + // last cluster of FAT + uint32_t fatEnd = clusterCount_ + 1; + + // search the FAT for free clusters + for (uint32_t n = 0;; n++, endCluster++) { + // can't find space checked all clusters + if (n >= clusterCount_) { + return false; + } + + // past end - start from beginning of FAT + if (endCluster > fatEnd) { + bgnCluster = endCluster = 2; + } + uint32_t f; + if (!fatGet(endCluster, &f)) { + return false; + } + + if (f != 0) { + // cluster in use try next cluster as bgnCluster + bgnCluster = endCluster + 1; + } else if ((endCluster - bgnCluster + 1) == count) { + // done - found space + break; + } + } + // mark end of chain + if (!fatPutEOC(endCluster)) { + return false; + } + + // link clusters + while (endCluster > bgnCluster) { + if (!fatPut(endCluster - 1, endCluster)) { + return false; + } + endCluster--; + } + if (*curCluster != 0) { + // connect chains + if (!fatPut(*curCluster, bgnCluster)) { + return false; + } + } + // return first cluster number to caller + *curCluster = bgnCluster; + + // remember possible next free cluster + if (setStart) { + allocSearchStart_ = bgnCluster + 1; + } + + return true; +} +//------------------------------------------------------------------------------ +uint8_t SdVolume::cacheFlush(uint8_t blocking) { + if (cacheDirty_) { + if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data, blocking)) { + return false; + } + + if (!blocking) { + return true; + } + + // mirror FAT tables + if (!cacheMirrorBlockFlush(blocking)) { + return false; + } + cacheDirty_ = 0; + } + return true; +} +//------------------------------------------------------------------------------ +uint8_t SdVolume::cacheMirrorBlockFlush(uint8_t blocking) { + if (cacheMirrorBlock_) { + if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data, blocking)) { + return false; + } + cacheMirrorBlock_ = 0; + } + return true; +} +//------------------------------------------------------------------------------ +uint8_t SdVolume::cacheRawBlock(uint32_t blockNumber, uint8_t action) { + if (cacheBlockNumber_ != blockNumber) { + if (!cacheFlush()) { + return false; + } + if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) { + return false; + } + cacheBlockNumber_ = blockNumber; + } + cacheDirty_ |= action; + return true; +} +//------------------------------------------------------------------------------ +// cache a zero block for blockNumber +uint8_t SdVolume::cacheZeroBlock(uint32_t blockNumber) { + if (!cacheFlush()) { + return false; + } + + // loop take less flash than memset(cacheBuffer_.data, 0, 512); + for (uint16_t i = 0; i < 512; i++) { + cacheBuffer_.data[i] = 0; + } + cacheBlockNumber_ = blockNumber; + cacheSetDirty(); + return true; +} +//------------------------------------------------------------------------------ +// return the size in bytes of a cluster chain +uint8_t SdVolume::chainSize(uint32_t cluster, uint32_t* size) const { + uint32_t s = 0; + do { + if (!fatGet(cluster, &cluster)) { + return false; + } + s += 512UL << clusterSizeShift_; + } while (!isEOC(cluster)); + *size = s; + return true; +} +//------------------------------------------------------------------------------ +// Fetch a FAT entry +uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const { + if (cluster > (clusterCount_ + 1)) { + return false; + } + uint32_t lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + if (lba != cacheBlockNumber_) { + if (!cacheRawBlock(lba, CACHE_FOR_READ)) { + return false; + } + } + if (fatType_ == 16) { + *value = cacheBuffer_.fat16[cluster & 0XFF]; + } else { + *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK; + } + return true; +} +//------------------------------------------------------------------------------ +// Store a FAT entry +uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) { + // error if reserved cluster + if (cluster < 2) { + return false; + } + + // error if not in FAT + if (cluster > (clusterCount_ + 1)) { + return false; + } + + // calculate block address for entry + uint32_t lba = fatStartBlock_; + lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7; + + if (lba != cacheBlockNumber_) { + if (!cacheRawBlock(lba, CACHE_FOR_READ)) { + return false; + } + } + // store entry + if (fatType_ == 16) { + cacheBuffer_.fat16[cluster & 0XFF] = value; + } else { + cacheBuffer_.fat32[cluster & 0X7F] = value; + } + cacheSetDirty(); + + // mirror second FAT + if (fatCount_ > 1) { + cacheMirrorBlock_ = lba + blocksPerFat_; + } + return true; +} +//------------------------------------------------------------------------------ +// free a cluster chain +uint8_t SdVolume::freeChain(uint32_t cluster) { + // clear free cluster location + allocSearchStart_ = 2; + + do { + uint32_t next; + if (!fatGet(cluster, &next)) { + return false; + } + + // free cluster + if (!fatPut(cluster, 0)) { + return false; + } + + cluster = next; + } while (!isEOC(cluster)); + + return true; +} +//------------------------------------------------------------------------------ +/** + Initialize a FAT volume. + + \param[in] dev The SD card where the volume is located. + + \param[in] part The partition to be used. Legal values for \a part are + 1-4 to use the corresponding partition on a device formatted with + a MBR, Master Boot Record, or zero if the device is formatted as + a super floppy with the FAT boot sector in block zero. + + \return The value one, true, is returned for success and + the value zero, false, is returned for failure. Reasons for + failure include not finding a valid partition, not finding a valid + FAT file system in the specified partition or an I/O error. +*/ +uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) { + uint32_t volumeStartBlock = 0; + sdCard_ = dev; + // if part == 0 assume super floppy with FAT boot sector in block zero + // if part > 0 assume mbr volume with partition table + if (part) { + if (part > 4) { + return false; + } + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { + return false; + } + part_t* p = &cacheBuffer_.mbr.part[part - 1]; + if ((p->boot & 0X7F) != 0 || + p->totalSectors < 100 || + p->firstSector == 0) { + // not a valid partition + return false; + } + volumeStartBlock = p->firstSector; + } + if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) { + return false; + } + bpb_t* bpb = &cacheBuffer_.fbs.bpb; + if (bpb->bytesPerSector != 512 || + bpb->fatCount == 0 || + bpb->reservedSectorCount == 0 || + bpb->sectorsPerCluster == 0) { + // not valid FAT volume + return false; + } + fatCount_ = bpb->fatCount; + blocksPerCluster_ = bpb->sectorsPerCluster; + + // determine shift that is same as multiply by blocksPerCluster_ + clusterSizeShift_ = 0; + while (blocksPerCluster_ != (1 << clusterSizeShift_)) { + // error if not power of 2 + if (clusterSizeShift_++ > 7) { + return false; + } + } + blocksPerFat_ = bpb->sectorsPerFat16 ? + bpb->sectorsPerFat16 : bpb->sectorsPerFat32; + + fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount; + + // count for FAT16 zero for FAT32 + rootDirEntryCount_ = bpb->rootDirEntryCount; + + // directory start for FAT16 dataStart for FAT32 + rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_; + + // data start for FAT16 and FAT32 + dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511) / 512); + + // total blocks for FAT16 or FAT32 + uint32_t totalBlocks = bpb->totalSectors16 ? + bpb->totalSectors16 : bpb->totalSectors32; + // total data blocks + clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock); + + // divide by cluster size to get cluster count + clusterCount_ >>= clusterSizeShift_; + + // FAT type is determined by cluster count + if (clusterCount_ < 4085) { + fatType_ = 12; + } else if (clusterCount_ < 65525) { + fatType_ = 16; + } else { + rootDirStart_ = bpb->fat32RootCluster; + fatType_ = 32; + } + return true; +} diff --git a/megaavr/libraries/SPI/keywords.txt b/megaavr/libraries/SPI/keywords.txt index fa76165..efb6175 100644 --- a/megaavr/libraries/SPI/keywords.txt +++ b/megaavr/libraries/SPI/keywords.txt @@ -13,6 +13,8 @@ SPI KEYWORD1 ####################################### begin KEYWORD2 end KEYWORD2 +swap KEYWORD2 +pins KEYWORD2 transfer KEYWORD2 setBitOrder KEYWORD2 setDataMode KEYWORD2 diff --git a/megaavr/libraries/SPI/src/SPI.cpp b/megaavr/libraries/SPI/src/SPI.cpp index ba6c28f..811135b 100644 --- a/megaavr/libraries/SPI/src/SPI.cpp +++ b/megaavr/libraries/SPI/src/SPI.cpp @@ -26,30 +26,100 @@ const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); -SPIClass::SPIClass(uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, uint8_t uc_pinSS, uint8_t uc_mux) +SPIClass::SPIClass() { initialized = false; - // pins - _uc_mux = uc_mux; - _uc_pinMiso = uc_pinMISO; - _uc_pinSCK = uc_pinSCK; - _uc_pinMosi = uc_pinMOSI; - _uc_pinSS = uc_pinSS; + // Default mux setting + #if defined(SPI_MUX) + _uc_mux = SPI_MUX; + #endif +} + +bool SPIClass::pins(uint8_t pinMOSI, uint8_t pinMISO, uint8_t pinSCK, uint8_t pinSS) +{ +#if defined(SPI_MUX) + #if defined(SPI_MUX_PINSWAP_1) || defined(SPI_MUX_PINSWAP_2) + + _uc_mux = SPI_MUX; + #if defined(SPI_MUX_PINSWAP_1) && defined(PIN_SPI_MOSI_PINSWAP_1) + if(pinMOSI == PIN_SPI_MOSI_PINSWAP_1 && pinMISO == PIN_SPI_MISO_PINSWAP_1 && pinSCK == PIN_SPI_SCK_PINSWAP_1 && pinSS == PIN_SPI_SS_PINSWAP_1) + { + _uc_mux = SPI_MUX_PINSWAP_1; + } + #endif + #if defined(SPI_MUX_PINSWAP_2) && defined(PIN_SPI_MOSI_PINSWAP_2) + if(pinMOSI == PIN_SPI_MOSI_PINSWAP_2 && pinMISO == PIN_SPI_MISO_PINSWAP_2 && pinSCK == PIN_SPI_SCK_PINSWAP_2 && pinSS == PIN_SPI_SS_PINSWAP_2) + { + _uc_mux = SPI_MUX_PINSWAP_2; + } + #endif + + if(_uc_mux != SPI_MUX) + return true; + + #endif + + return pinMOSI == PIN_SPI_MOSI && pinMISO == PIN_SPI_MISO && pinSCK == PIN_SPI_SCK && pinSS == PIN_SPI_SS; +#else + return false; +#endif +} + +bool SPIClass::swap(uint8_t state) +{ + if(state == 0) + { + _uc_mux = SPI_MUX; + pins(PIN_SPI_MOSI, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_SS); + return true; + } + #if defined(SPI_MUX_PINSWAP_1) + else if(state == 1) + { + _uc_mux = SPI_MUX_PINSWAP_1; + return true; + } + #endif + #if defined(SPI_MUX_PINSWAP_2) + else if(state == 2) + { + _uc_mux = SPI_MUX_PINSWAP_2; + return true; + } + #endif + else + return false; } void SPIClass::begin() { init(); - PORTMUX.TWISPIROUTEA |= _uc_mux; + PORTMUX.TWISPIROUTEA = _uc_mux | (PORTMUX.TWISPIROUTEA & ~3); - // We don't need HW SS since salve/master mode is selected via registers, so make it simply INPUT - pinMode(_uc_pinSS, INPUT); - pinMode(_uc_pinMosi, OUTPUT); - pinMode(_uc_pinSCK, OUTPUT); // MISO is set to input by the controller - + if(_uc_mux == SPI_MUX) + { + pinMode(PIN_SPI_MOSI, OUTPUT); + pinMode(PIN_SPI_SCK, OUTPUT); + } + #if defined(SPI_MUX_PINSWAP_1) + else if(_uc_mux == SPI_MUX_PINSWAP_1) + { + pinMode(PIN_SPI_MOSI_PINSWAP_1, OUTPUT); + pinMode(PIN_SPI_SCK_PINSWAP_1, OUTPUT); + } + #endif + #if defined(SPI_MUX_PINSWAP_2) + else if(_uc_mux == SPI_MUX_PINSWAP_2) + { + pinMode(PIN_SPI_MOSI_PINSWAP_2, OUTPUT); + pinMode(PIN_SPI_SCK_PINSWAP_2, OUTPUT); + } + #endif + + // We don't need HW SS since salve/master mode is selected via registers SPI0.CTRLB |= (SPI_SSD_bm); SPI0.CTRLA |= (SPI_ENABLE_bm | SPI_MASTER_bm); @@ -131,7 +201,7 @@ void SPIClass::detachMaskedInterrupts() { uint8_t shift = 0; while (temp != 0) { if (temp & 1) { - uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); + volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); irqMap[shift] = *pin_ctrl_reg; *pin_ctrl_reg &= ~(PORT_ISC_gm); } @@ -142,7 +212,7 @@ void SPIClass::detachMaskedInterrupts() { shift = 32; while (temp != 0) { if (temp & 1) { - uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); + volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); irqMap[shift] = *pin_ctrl_reg; *pin_ctrl_reg &= ~(PORT_ISC_gm); } @@ -156,7 +226,7 @@ void SPIClass::reattachMaskedInterrupts() { uint8_t shift = 0; while (temp != 0) { if (temp & 1) { - uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); + volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); *pin_ctrl_reg |= irqMap[shift]; } temp = temp >> 1; @@ -166,7 +236,7 @@ void SPIClass::reattachMaskedInterrupts() { shift = 32; while (temp != 0) { if (temp & 1) { - uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); + volatile uint8_t* pin_ctrl_reg = getPINnCTRLregister(portToPortStruct(shift/8), shift%8); *pin_ctrl_reg |= irqMap[shift]; } temp = temp >> 1; @@ -203,9 +273,9 @@ void SPIClass::endTransaction(void) } } -void SPIClass::setBitOrder(BitOrder order) +void SPIClass::setBitOrder(uint8_t bitOrder) { - if (order == LSBFIRST) + if (bitOrder == LSBFIRST) SPI0.CTRLA |= (SPI_DORD_bm); else SPI0.CTRLA &= ~(SPI_DORD_bm); @@ -219,7 +289,7 @@ void SPIClass::setDataMode(uint8_t mode) void SPIClass::setClockDivider(uint8_t div) { SPI0.CTRLA = ((SPI0.CTRLA & - ((~SPI_PRESC_gm) | (~SPI_CLK2X_bm) )) // mask out values + (~(SPI_PRESC_gm | SPI_CLK2X_bm))) // mask out values | div); // write value } @@ -264,5 +334,5 @@ void SPIClass::transfer(void *buf, size_t count) } #if SPI_INTERFACES_COUNT > 0 - SPIClass SPI (PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI, PIN_SPI_SS, SPI_MUX); -#endif \ No newline at end of file + SPIClass SPI; +#endif diff --git a/megaavr/libraries/SPI/src/SPI.h b/megaavr/libraries/SPI/src/SPI.h index dd427e1..8a478e8 100644 --- a/megaavr/libraries/SPI/src/SPI.h +++ b/megaavr/libraries/SPI/src/SPI.h @@ -52,7 +52,7 @@ class SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { if (__builtin_constant_p(clock)) { init_AlwaysInline(clock, bitOrder, dataMode); } else { @@ -64,11 +64,11 @@ class SPISettings { SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } private: - void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) { init_AlwaysInline(clock, bitOrder, dataMode); } - void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { + void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { // Clock settings are defined as follows. Note that this shows SPI2X // inverted, so the bits form increasing numbers. Also note that // fosc/64 appears twice. If FOSC is 16 Mhz @@ -93,12 +93,11 @@ class SPISettings { // away. When clock is not known, use a loop instead, which generates // shorter code. - /* This is no longer the case since, F_CPU_CORRECTED is variable */ /* set at run time. */ uint32_t clockSetting = 0; - clockSetting = F_CPU_CORRECTED / 2; + clockSetting = F_CPU / 2; clockDiv = 0; while ((clockDiv < 6) && (clock < clockSetting)) { clockSetting /= 2; @@ -145,7 +144,7 @@ class SPISettings { class SPIClass { public: - SPIClass(uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, uint8_t uc_pinSS, uint8_t uc_mux); + SPIClass(); byte transfer(uint8_t data); uint16_t transfer16(uint16_t data); @@ -156,11 +155,13 @@ class SPIClass { void notUsingInterrupt(int interruptNumber); void beginTransaction(SPISettings settings); void endTransaction(void); - + + bool pins(uint8_t pinMOSI, uint8_t pinMISO, uint8_t pinSCK, uint8_t pinSS); + bool swap(uint8_t state = 1); void begin(); void end(); - void setBitOrder(BitOrder order); + void setBitOrder(uint8_t bitOrder); void setDataMode(uint8_t uc_mode); void setClockDivider(uint8_t uc_div); diff --git a/megaavr/libraries/Servo/README.adoc b/megaavr/libraries/Servo/README.adoc new file mode 100644 index 0000000..dd3f0ba --- /dev/null +++ b/megaavr/libraries/Servo/README.adoc @@ -0,0 +1,25 @@ += Servo Library for Arduino = + +This library allows an Arduino board to control RC (hobby) servo motors. + +For more information about this library please visit us at +http://www.arduino.cc/en/Reference/Servo + +== License == + +Copyright (c) 2013 Arduino LLC. All right reserved. +Copyright (c) 2009 Michael Margolis. All right reserved. + +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 St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/megaavr/libraries/Servo/examples/Knob/Knob.ino b/megaavr/libraries/Servo/examples/Knob/Knob.ino new file mode 100644 index 0000000..0db8770 --- /dev/null +++ b/megaavr/libraries/Servo/examples/Knob/Knob.ino @@ -0,0 +1,27 @@ +/* + Controlling a servo position using a potentiometer (variable resistor) + by Michal Rinott + + modified on 8 Nov 2013 + by Scott Fitzgerald + http://www.arduino.cc/en/Tutorial/Knob +*/ + +#include + +Servo myservo; // create servo object to control a servo + +int potpin = 0; // analog pin used to connect the potentiometer +int val; // variable to read the value from the analog pin + +void setup() { + myservo.attach(9); // attaches the servo on pin 9 to the servo object +} + +void loop() { + val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023) + val = map(val, 0, 1023, 0, 180); // scale it to use it with the servo (value between 0 and 180) + myservo.write(val); // sets the servo position according to the scaled value + delay(15); // waits for the servo to get there +} + diff --git a/megaavr/libraries/Servo/examples/Sweep/Sweep.ino b/megaavr/libraries/Servo/examples/Sweep/Sweep.ino new file mode 100644 index 0000000..df904af --- /dev/null +++ b/megaavr/libraries/Servo/examples/Sweep/Sweep.ino @@ -0,0 +1,32 @@ +/* Sweep + by BARRAGAN + This example code is in the public domain. + + modified 8 Nov 2013 + by Scott Fitzgerald + http://www.arduino.cc/en/Tutorial/Sweep +*/ + +#include + +Servo myservo; // create servo object to control a servo +// twelve servo objects can be created on most boards + +int pos = 0; // variable to store the servo position + +void setup() { + myservo.attach(9); // attaches the servo on pin 9 to the servo object +} + +void loop() { + for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees + // in steps of 1 degree + myservo.write(pos); // tell servo to go to position in variable 'pos' + delay(15); // waits 15ms for the servo to reach the position + } + for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees + myservo.write(pos); // tell servo to go to position in variable 'pos' + delay(15); // waits 15ms for the servo to reach the position + } +} + diff --git a/megaavr/libraries/HID/keywords.txt b/megaavr/libraries/Servo/keywords.txt similarity index 69% rename from megaavr/libraries/HID/keywords.txt rename to megaavr/libraries/Servo/keywords.txt index 32a9ba5..0a7ca1e 100644 --- a/megaavr/libraries/HID/keywords.txt +++ b/megaavr/libraries/Servo/keywords.txt @@ -1,21 +1,24 @@ ####################################### -# Syntax Coloring Map HID +# Syntax Coloring Map Servo ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### -HID KEYWORD1 +Servo KEYWORD1 Servo ####################################### # Methods and Functions (KEYWORD2) ####################################### -begin KEYWORD2 -SendReport KEYWORD2 -AppendDescriptor KEYWORD2 +attach KEYWORD2 +detach KEYWORD2 +write KEYWORD2 +read KEYWORD2 +attached KEYWORD2 +writeMicroseconds KEYWORD2 +readMicroseconds KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### -HID_TX LITERAL1 \ No newline at end of file diff --git a/megaavr/libraries/Servo/library.properties b/megaavr/libraries/Servo/library.properties new file mode 100644 index 0000000..043ab06 --- /dev/null +++ b/megaavr/libraries/Servo/library.properties @@ -0,0 +1,9 @@ +name=Servo +version=1.2.1 +author=Spence Konde and MCUdude based on work by Michael Margolis, Arduino +maintainer=MCUdude +sentence=Allows megaAVR0 chips to control a variety of servo motors. +paragraph=This library can control a great number of servos.
It makes careful use of timers: the library can control 12 servos using only 1 timer.
+category=Device Control +url=http://www.arduino.cc/en/Reference/Servo +architectures=megaavr diff --git a/megaavr/libraries/Servo/src/Servo.h b/megaavr/libraries/Servo/src/Servo.h new file mode 100644 index 0000000..9f092f7 --- /dev/null +++ b/megaavr/libraries/Servo/src/Servo.h @@ -0,0 +1,114 @@ +/* + Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 + Copyright (c) 2009 Michael Margolis. All right reserved. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + A servo is activated by creating an instance of the Servo class passing + the desired pin to the attach() method. + The servos are pulsed in the background using the value most recently + written using the write() method. + + Note that analogWrite of PWM on pins associated with the timer are + disabled when the first servo is attached. + Timers are seized as needed in groups of 12 servos - 24 servos use two + timers, 48 servos will use four. + The sequence used to sieze timers is defined in timers.h + + The methods are: + + Servo - Class for manipulating servo motors connected to Arduino pins. + + attach(pin ) - Attaches a servo motor to an i/o pin. + attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds + default min is 544, max is 2400 + + write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) + writeMicroseconds() - Sets the servo pulse width in microseconds + read() - Gets the last written servo pulse width as an angle between 0 and 180. + readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release) + attached() - Returns true if there is a servo attached. + detach() - Stops an attached servos from pulsing its i/o pin. + */ + +#ifndef Servo_h +#define Servo_h +#include + +/* + Defines for 16 bit timers used with Servo library + + If _useTimerX is defined then TimerX is a 16 bit timer on the current board + timer16_Sequence_t enumerates the sequence that the timers should be allocated + _Nbr_16timers indicates how many 16 bit timers are available. +*/ + +// Architecture specific include +#if defined(ARDUINO_ARCH_MEGAAVR) + #include "megaavr/ServoTimers.h" + #if (F_CPU == 1000000L) + #warning "Running at 1MHz results in unstable servo signal." + #endif +#else + #error "This is an architecture specific library for ARDUINO_ARCH_MEGAAVR, but this device is not of that architecture" +#endif + +#define Servo_VERSION 2 // software version of this library + +#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo +#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo +#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached +#define REFRESH_INTERVAL 20000UL // minumim time to refresh servos in microseconds + +#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer +#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER) + +#define INVALID_SERVO 255 // flag indicating an invalid servo index + +typedef struct { + //uint8_t nbr; // a pin number from 0 to 63 + // the original implementation with bitslices and just isActive and nbr in a single byte saved 2 bytes of ram per servo, as a cost of a very small amount of flash. + // optimization it supports (losing digitalWrite() in the ISR) has surprisingly little impact - though I do think it has a more significant impact on time spent + // in the ISR, which you don't see most of the time... + uint8_t isActive; // true if this channel is enabled, pin not pulsed if false + uint8_t port; + uint8_t bitmask; +} ServoPin_t; + +typedef struct { + ServoPin_t Pin; + volatile uint16_t ticks; +} servo_t; + +class Servo { + public: + Servo(); + uint8_t attach(uint8_t pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure + uint8_t attach(uint8_t pin, int16_t min, int16_t max); // as above but also sets min and max values for writes. + void detach(); + void write(uint16_t value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds + void writeMicroseconds(uint16_t value); // Write pulse width in microseconds + int16_t read(); // returns current pulse width as an angle between 0 and 180 degrees + uint16_t readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release) + bool attached(); // return true if this servo is attached, otherwise false + private: + uint8_t servoIndex; // index into the channel data for this servo + int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH + int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH +}; + +#endif diff --git a/megaavr/libraries/Servo/src/ServoMegaCoreX.h b/megaavr/libraries/Servo/src/ServoMegaCoreX.h new file mode 100644 index 0000000..44144c1 --- /dev/null +++ b/megaavr/libraries/Servo/src/ServoMegaCoreX.h @@ -0,0 +1,3 @@ +// Dummy file to deal with issue https://github.com/MCUdude/MegaCoreX/issues/167 + +#include diff --git a/megaavr/libraries/Servo/src/megaavr/Servo.cpp b/megaavr/libraries/Servo/src/megaavr/Servo.cpp new file mode 100644 index 0000000..2699c15 --- /dev/null +++ b/megaavr/libraries/Servo/src/megaavr/Servo.cpp @@ -0,0 +1,231 @@ +#if defined(ARDUINO_ARCH_MEGAAVR) + +#include +#include + +#if (F_CPU > 10000000L) + #define usToTicks(_us) ((( (_us) / 2) * clockCyclesPerMicrosecond())) // converts microseconds to tick + #define ticksToUs(_ticks) (((unsigned) (_ticks) * 2) / clockCyclesPerMicrosecond()) // converts from ticks back to microseconds + #define TRIM_DURATION 37 // compensation ticks to trim adjust for digitalWrite delays +#else + #define usToTicks(_us) ((( _us ) * clockCyclesPerMicrosecond())) // converts microseconds to tick + #define ticksToUs(_ticks) (((unsigned) _ticks ) / clockCyclesPerMicrosecond()) // converts from ticks back to microseconds + #define TRIM_DURATION 74 // compensation ticks to trim adjust for digitalWrite delays +#endif + +static servo_t servos[MAX_SERVOS]; // static array of servo structures + +uint8_t ServoCount = 0; // the total number of attached servos + +static volatile int8_t currentServoIndex[_Nbr_16timers]; // index for the servo being pulsed for each timer (or -1 if refresh interval) + +// convenience macros +#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo +#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer +#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel +#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel + +#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo +#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo + +void ServoHandler(int16_t timer) { + static uint32_t currentCycleTicks = 0; + if (currentServoIndex[timer] < 0) { + // we're at servo index -1... but before we go further - we need to see if we've waited through a refresh cycle... + if (currentCycleTicks < usToTicks(REFRESH_INTERVAL)) { + uint32_t tval=usToTicks(REFRESH_INTERVAL)-currentCycleTicks; + uint16_t tval16=(tval>65535)?65535:tval; + _timer->CCMP = tval16; + currentCycleTicks+=tval16; + // wait longer, and terminate the ISR without further action./* Clear flag */ + _timer->INTFLAGS = TCB_CAPT_bm; + return; + } else { + // current cycle is done, so reset the currentCycleTicks, and run the rest of things... + currentCycleTicks=0; + } + } else { + if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) { + //digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW); // pulse this channel low if activated + ((PORT_t *)&PORTA + SERVO(timer, currentServoIndex[timer]).Pin.port)->OUTCLR = SERVO(timer, currentServoIndex[timer]).Pin.bitmask; + } + } + + // Select the next servo controlled by this timer + currentServoIndex[timer]++; + + if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) { + if (SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) { // check if activated + //digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high + ((PORT_t *)&PORTA + SERVO(timer, currentServoIndex[timer]).Pin.port)->OUTSET = SERVO(timer, currentServoIndex[timer]).Pin.bitmask; + } + + // Get the counter value + _timer->CCMP = SERVO(timer, currentServoIndex[timer]).ticks; + currentCycleTicks += SERVO(timer, currentServoIndex[timer]).ticks; + } else { + // finished all channels so wait for the refresh period to expire before starting over + if (currentCycleTicks + 100 < usToTicks(REFRESH_INTERVAL)) { // let's not bother if it's gonna take less than 100 ticks for the next + uint32_t tval = usToTicks(REFRESH_INTERVAL) - currentCycleTicks; + uint16_t tval16 = tval > 65535 ? 65535 : tval; + _timer->CCMP = tval16; + currentCycleTicks += tval16; + } else { // in this case it's less than 100 ticks for next interval, so we just set it to that... + currentCycleTicks = usToTicks(REFRESH_INTERVAL); + } + currentServoIndex[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel + } + /* Clear flag */ + _timer->INTFLAGS = TCB_CAPT_bm; +} + +#if defined(SERVO_USE_TIMERB0) +ISR(TCB0_INT_vect) +#elif defined(SERVO_USE_TIMERB1) +ISR(TCB1_INT_vect) +#elif defined(SERVO_USE_TIMERB2) +ISR(TCB2_INT_vect) +#elif defined(SERVO_USE_TIMERB3) +ISR(TCB3_INT_vect) +#endif +{ + ServoHandler(0); +} + +static void initISR() { + //divide CLK_PER by 2 instead of using TCA0-prescaled at 16/20MHz + #if (F_CPU > 10000000L) + _timer->CTRLA = TCB_CLKSEL_CLKDIV2_gc; + #else // and don't divide it at all at lower clock speeds + _timer->CTRLA = TCB_CLKSEL_CLKDIV1_gc; + #endif + // Timer to Periodic interrupt mode + // This write will also disable any active PWM outputs + _timer->CTRLB = TCB_CNTMODE_INT_gc; + + _timer->CCMP = 0x8000; //Experience has shown that without this, it goes off the rails + // Enable interrupt + _timer->INTCTRL = TCB_CAPTEI_bm; + // Enable timer + _timer->CTRLA |= TCB_ENABLE_bm; +} + +static void finISR() { + // Disable interrupt + _timer->INTCTRL = 0; +} + +static bool isTimerActive(timer16_Sequence_t timer) { + // returns true if any servo is active on this timer + for (uint8_t channel = 0; channel < SERVOS_PER_TIMER; channel++) { + if (SERVO(timer, channel).Pin.isActive == true) { + return true; + } + } + return false; +} + +/****************** end of static functions ******************************/ + +Servo::Servo() { + if (ServoCount < MAX_SERVOS) { + this->servoIndex = ServoCount++; // assign a servo index to this instance + servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values + } else { + this->servoIndex = INVALID_SERVO; // too many servos + } +} + +uint8_t Servo::attach(uint8_t pin) { + return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH); +} + +uint8_t Servo::attach(uint8_t pin, int16_t min, int16_t max) { + timer16_Sequence_t timer; + + if (this->servoIndex < MAX_SERVOS) { + //pinMode(pin, OUTPUT); // set servo pin to output + //servos[this->servoIndex].Pin.nbr = pin; + uint8_t bitmask = digitalPinToBitMask(pin); + if (bitmask == NOT_A_PIN) + return NOT_A_PIN; + servos[this->servoIndex].Pin.bitmask = bitmask; + uint8_t prt = digitalPinToPort(pin); + servos[this->servoIndex].Pin.port = prt; + PORT_t *port=((PORT_t *)&PORTA + prt); + port->DIRSET=bitmask; + // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128 + this->min = (MIN_PULSE_WIDTH - min) / 4; //resolution of min/max is 4 uS + this->max = (MAX_PULSE_WIDTH - max) / 4; + // initialize the timer if it has not already been initialized + timer = SERVO_INDEX_TO_TIMER(servoIndex); + if (isTimerActive(timer) == false) { + initISR(); + } + servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive + } + return this->servoIndex; +} + +void Servo::detach() { + timer16_Sequence_t timer; + + servos[this->servoIndex].Pin.isActive = false; + timer = SERVO_INDEX_TO_TIMER(servoIndex); + if (isTimerActive(timer) == false) { + finISR(); + } +} + +void Servo::write(uint16_t value) { + // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds) + if (value < MIN_PULSE_WIDTH) { + // ditch this, the argument is an unsigned int, so this is pointless... + //if (value < 0) { + // value = 0; + //} else + if (value > 180) { + value = 180; + } + + value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX()); + } + writeMicroseconds(value); +} + + +void Servo::writeMicroseconds(uint16_t value) { + // calculate and store the values for the given channel + uint8_t channel = this->servoIndex; + if ((channel < MAX_SERVOS)) { // ensure channel is valid + if (value < (uint16_t) SERVO_MIN()) { // ensure pulse width is valid + value = SERVO_MIN(); + } else if (value > (uint16_t) SERVO_MAX()) { + value = SERVO_MAX(); + } + + + value = usToTicks(value); // convert to ticks BEFORE compensating for interrupt overhead + value = value - TRIM_DURATION; + servos[channel].ticks = value; + } +} + +int16_t Servo::read() { // return the value as degrees + return map(readMicroseconds() + 1, SERVO_MIN(), SERVO_MAX(), 0, 180); +} + +uint16_t Servo::readMicroseconds() { + uint16_t pulsewidth; + if (this->servoIndex != INVALID_SERVO) { + pulsewidth = ticksToUs(servos[this->servoIndex].ticks + TRIM_DURATION); + } else { + pulsewidth = 0; + } + return pulsewidth; +} + +bool Servo::attached() { + return servos[this->servoIndex].Pin.isActive; +} +#endif diff --git a/megaavr/libraries/Servo/src/megaavr/ServoTimers.h b/megaavr/libraries/Servo/src/megaavr/ServoTimers.h new file mode 100644 index 0000000..6762ed8 --- /dev/null +++ b/megaavr/libraries/Servo/src/megaavr/ServoTimers.h @@ -0,0 +1,59 @@ +/* + Copyright (c) 2018 Arduino LLC. All right reserved. + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* + * Defines for 16 bit timers used with Servo library + * + */ + +#ifndef __SERVO_TIMERS_H__ +#define __SERVO_TIMERS_H__ + +#if !defined(SERVO_USE_TIMERB0) || !defined(SERVO_USE_TIMERB1) || !defined(SERVO_USE_TIMERB2) || !defined(SERVO_USE_TIMERB3) + #if defined(__AVR_ATmega808__) || defined(__AVR_ATmega1608__) \ + || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega4808__) \ + || defined(NANO_EVERY_PINOUT) || defined(UNO_WIFI_REV2_PINOUT) + #define SERVO_USE_TIMERB1 + #elif defined(__AVR_ATmega809__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega3209__) || defined(__AVR_ATmega4809__) + #define SERVO_USE_TIMERB3 + #else + #error "No timers allowed for Servo" + #endif +#endif + +__attribute__ ((used)) static volatile TCB_t* _timer = +#if defined(SERVO_USE_TIMERB0) + &TCB0; +#endif +#if defined(SERVO_USE_TIMERB1) + &TCB1; +#endif +#if defined(SERVO_USE_TIMERB2) + &TCB2; +#endif +#if defined(SERVO_USE_TIMERB3) + &TCB3; +#endif + +typedef enum { + timer0, + _Nbr_16timers +} timer16_Sequence_t; + + +#endif /* __SERVO_TIMERS_H__ */ diff --git a/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.cpp index b90e4c9..b6cb8e4 100644 --- a/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -1,459 +1,459 @@ -/* -SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) - -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 St, Fifth Floor, Boston, MA 02110-1301 USA - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -// When set, _DEBUG co-opts pins 11 and 13 for debugging with an -// oscilloscope or logic analyzer. Beware: it also slightly modifies -// the bit times, so don't rely on it too much at high baud rates -#define _DEBUG 0 -#define _DEBUG_PIN1 11 -#define _DEBUG_PIN2 13 -// -// Includes -// -#include -#include -#include -#include -#include - -// -// Statics -// -SoftwareSerial *SoftwareSerial::active_object = 0; -uint8_t SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; -volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; -volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; - -// -// Debugging -// -// This function generates a brief pulse -// for debugging or measuring on an oscilloscope. -#if _DEBUG -inline void DebugPulse(uint8_t pin, uint8_t count) -{ - volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); - - uint8_t val = *pport; - while (count--) - { - *pport = val | digitalPinToBitMask(pin); - *pport = val; - } -} -#else -inline void DebugPulse(uint8_t, uint8_t) {} -#endif - -// -// Private methods -// - -/* static */ -inline void SoftwareSerial::tunedDelay(uint16_t delay) { - _delay_loop_2(delay); -} - -// This function sets the current object as the "listening" -// one and returns true if it replaces another -bool SoftwareSerial::listen() -{ - if (!_rx_delay_stopbit) - return false; - - if (active_object != this) - { - if (active_object) - active_object->stopListening(); - - _buffer_overflow = false; - _receive_buffer_head = _receive_buffer_tail = 0; - active_object = this; - - setRxIntMsk(true); - return true; - } - - return false; -} - -// Stop listening. Returns true if we were actually listening. -bool SoftwareSerial::stopListening() -{ - if (active_object == this) - { - setRxIntMsk(false); - active_object = NULL; - return true; - } - return false; -} - -// -// The receive routine called by the interrupt handler -// -void SoftwareSerial::recv() -{ - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Preserve the registers that the compiler misses -// (courtesy of Arduino forum user *etracer*) - asm volatile( - "push r18 \n\t" - "push r19 \n\t" - "push r20 \n\t" - "push r21 \n\t" - "push r22 \n\t" - "push r23 \n\t" - "push r26 \n\t" - "push r27 \n\t" - ::); -#endif - - uint8_t d = 0; - - // If RX line is high, then we don't see any start bit - // so interrupt is probably not for us - if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) - { - // Disable further interrupts during reception, this prevents - // triggering another interrupt directly after we return, which can - // cause problems at higher baudrates. - setRxIntMsk(false); - - // Wait approximately 1/2 of a bit width to "center" the sample - tunedDelay(_rx_delay_centering); - DebugPulse(_DEBUG_PIN2, 1); - - // Read each of the 8 bits - for (uint8_t i=8; i > 0; --i) - { - tunedDelay(_rx_delay_intrabit); - d >>= 1; - DebugPulse(_DEBUG_PIN2, 1); - if (rx_pin_read()) - d |= 0x80; - } - - if (_inverse_logic) - d = ~d; - - // if buffer full, set the overflow flag and return - uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; - if (next != _receive_buffer_head) - { - // save new data in buffer: tail points to where byte goes - _receive_buffer[_receive_buffer_tail] = d; // save new byte - _receive_buffer_tail = next; - } - else - { - DebugPulse(_DEBUG_PIN1, 1); - _buffer_overflow = true; - } - - // skip the stop bit - tunedDelay(_rx_delay_stopbit); - DebugPulse(_DEBUG_PIN1, 1); - - // Re-enable interrupts when we're sure to be inside the stop bit - setRxIntMsk(true); - - } - -#if GCC_VERSION < 40302 -// Work-around for avr-gcc 4.3.0 OSX version bug -// Restore the registers that the compiler misses - asm volatile( - "pop r27 \n\t" - "pop r26 \n\t" - "pop r23 \n\t" - "pop r22 \n\t" - "pop r21 \n\t" - "pop r20 \n\t" - "pop r19 \n\t" - "pop r18 \n\t" - ::); -#endif -} - -uint8_t SoftwareSerial::rx_pin_read() -{ - return *_receivePortRegister & _receiveBitMask; -} - -// -// Interrupt handling -// - -/* static */ -inline void SoftwareSerial::handle_interrupt() -{ - if (active_object) - { - active_object->recv(); - } -} - -// -// Constructor -// -SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : - _rx_delay_centering(0), - _rx_delay_intrabit(0), - _rx_delay_stopbit(0), - _tx_delay(0), - _buffer_overflow(false), - _inverse_logic(inverse_logic) -{ - setTX(transmitPin); - setRX(receivePin); -} - -// -// Destructor -// -SoftwareSerial::~SoftwareSerial() -{ - end(); -} - -void SoftwareSerial::setTX(uint8_t tx) -{ - // First write, then set output. If we do this the other way around, - // the pin would be output low for a short while before switching to - // output high. Now, it is input with pullup for a short while, which - // is fine. With inverse logic, either order is fine. - digitalWrite(tx, _inverse_logic ? LOW : HIGH); - pinMode(tx, OUTPUT); - _transmitBitMask = digitalPinToBitMask(tx); - uint8_t port = digitalPinToPort(tx); - _transmitPortRegister = portOutputRegister(port); -} - -void SoftwareSerial::setRX(uint8_t rx) -{ - pinMode(rx, INPUT); - if (!_inverse_logic) - digitalWrite(rx, HIGH); // pullup for normal logic! - _receivePin = rx; - _receiveBitMask = digitalPinToBitMask(rx); - uint8_t port = digitalPinToPort(rx); - _receivePortRegister = portInputRegister(port); -} - -uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { - if (num > sub) - return num - sub; - else - return 1; -} - -// -// Public methods -// - -void SoftwareSerial::begin(long speed) -{ - _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; - - // Precalculate the various delays, in number of 4-cycle delays - uint16_t bit_delay = (F_CPU / speed) / 4; - - // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, - // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, - // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit - // These are all close enough to just use 15 cycles, since the inter-bit - // timings are the most critical (deviations stack 8 times) - _tx_delay = subtract_cap(bit_delay, 15 / 4); - - // Only setup rx when we have a valid PCINT for this pin - if (1) { - #if GCC_VERSION > 40800 - // Timings counted from gcc 4.8.2 output. This works up to 115200 on - // 16Mhz and 57600 on 8Mhz. - // - // When the start bit occurs, there are 3 or 4 cycles before the - // interrupt flag is set, 4 cycles before the PC is set to the right - // interrupt vector address and the old PC is pushed on the stack, - // and then 75 cycles of instructions (including the RJMP in the - // ISR vector table) until the first delay. After the delay, there - // are 17 more cycles until the pin value is read (excluding the - // delay in the loop). - // We want to have a total delay of 1.5 bit time. Inside the loop, - // we already wait for 1 bit time - 23 cycles, so here we wait for - // 0.5 bit time - (71 + 18 - 22) cycles. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); - - // There are 23 cycles in each loop iteration (excluding the delay) - _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); - - // There are 37 cycles from the last bit read to the start of - // stopbit delay and 11 cycles from the delay until the interrupt - // mask is enabled again (which _must_ happen during the stopbit). - // This delay aims at 3/4 of a bit time, meaning the end of the - // delay will be at 1/4th of the stopbit. This allows some extra - // time for ISR cleanup, which makes 115200 baud at 16Mhz work more - // reliably - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); - #else // Timings counted from gcc 4.3.2 output - // Note that this code is a _lot_ slower, mostly due to bad register - // allocation choices of gcc. This works up to 57600 on 16Mhz and - // 38400 on 8Mhz. - _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); - _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); - _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); - #endif - - attachInterrupt(_receivePin, SoftwareSerial::handle_interrupt, CHANGE); - - tunedDelay(_tx_delay); // if we were low this establishes the end - } - -#if _DEBUG - pinMode(_DEBUG_PIN1, OUTPUT); - pinMode(_DEBUG_PIN2, OUTPUT); -#endif - - listen(); -} - -void SoftwareSerial::setRxIntMsk(bool enable) -{ - if (enable) - *_pcint_maskreg |= _pcint_maskvalue; - else - *_pcint_maskreg &= ~_pcint_maskvalue; -} - -void SoftwareSerial::end() -{ - stopListening(); -} - - -// Read data from buffer -int SoftwareSerial::read() -{ - if (!isListening()) - return -1; - - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; - - // Read from "head" - uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte - _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; - return d; -} - -int SoftwareSerial::available() -{ - if (!isListening()) - return 0; - - return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; -} - -size_t SoftwareSerial::write(uint8_t b) -{ - if (_tx_delay == 0) { - setWriteError(); - return 0; - } - - // By declaring these as local variables, the compiler will put them - // in registers _before_ disabling interrupts and entering the - // critical timing sections below, which makes it a lot easier to - // verify the cycle timings - volatile uint8_t *reg = _transmitPortRegister; - uint8_t reg_mask = _transmitBitMask; - uint8_t inv_mask = ~_transmitBitMask; - uint8_t oldSREG = SREG; - bool inv = _inverse_logic; - uint16_t delay = _tx_delay; - - if (inv) - b = ~b; - - cli(); // turn off interrupts for a clean txmit - - // Write the start bit - if (inv) - *reg |= reg_mask; - else - *reg &= inv_mask; - - tunedDelay(delay); - - // Write each of the 8 bits - for (uint8_t i = 8; i > 0; --i) - { - if (b & 1) // choose bit - *reg |= reg_mask; // send 1 - else - *reg &= inv_mask; // send 0 - - tunedDelay(delay); - b >>= 1; - } - - // restore pin to natural state - if (inv) - *reg &= inv_mask; - else - *reg |= reg_mask; - - SREG = oldSREG; // turn interrupts back on - tunedDelay(_tx_delay); - - return 1; -} - -void SoftwareSerial::flush() -{ - // There is no tx buffering, simply return -} - -int SoftwareSerial::peek() -{ - if (!isListening()) - return -1; - - // Empty buffer? - if (_receive_buffer_head == _receive_buffer_tail) - return -1; - - // Read from "head" - return _receive_buffer[_receive_buffer_head]; -} +/* +SoftwareSerial.cpp (formerly NewSoftSerial.cpp) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada + (http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) + +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 St, Fifth Floor, Boston, MA 02110-1301 USA + +The latest version of this library can always be found at +http://arduiniana.org. +*/ + +// When set, _DEBUG co-opts pins 11 and 13 for debugging with an +// oscilloscope or logic analyzer. Beware: it also slightly modifies +// the bit times, so don't rely on it too much at high baud rates +#define _DEBUG 0 +#define _DEBUG_PIN1 11 +#define _DEBUG_PIN2 13 +// +// Includes +// +#include +#include +#include +#include +#include + +// +// Statics +// +SoftwareSerial *SoftwareSerial::active_object = 0; +uint8_t SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF]; +volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0; +volatile uint8_t SoftwareSerial::_receive_buffer_head = 0; + +// +// Debugging +// +// This function generates a brief pulse +// for debugging or measuring on an oscilloscope. +#if _DEBUG +inline void DebugPulse(uint8_t pin, uint8_t count) +{ + volatile uint8_t *pport = portOutputRegister(digitalPinToPort(pin)); + + uint8_t val = *pport; + while (count--) + { + *pport = val | digitalPinToBitMask(pin); + *pport = val; + } +} +#else +inline void DebugPulse(uint8_t, uint8_t) {} +#endif + +// +// Private methods +// + +/* static */ +inline void SoftwareSerial::tunedDelay(uint16_t delay) { + _delay_loop_2(delay); +} + +// This function sets the current object as the "listening" +// one and returns true if it replaces another +bool SoftwareSerial::listen() +{ + if (!_rx_delay_stopbit) + return false; + + if (active_object != this) + { + if (active_object) + active_object->stopListening(); + + _buffer_overflow = false; + _receive_buffer_head = _receive_buffer_tail = 0; + active_object = this; + + setRxIntMsk(true); + return true; + } + + return false; +} + +// Stop listening. Returns true if we were actually listening. +bool SoftwareSerial::stopListening() +{ + if (active_object == this) + { + setRxIntMsk(false); + active_object = NULL; + return true; + } + return false; +} + +// +// The receive routine called by the interrupt handler +// +void SoftwareSerial::recv() +{ + +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Preserve the registers that the compiler misses +// (courtesy of Arduino forum user *etracer*) + asm volatile( + "push r18 \n\t" + "push r19 \n\t" + "push r20 \n\t" + "push r21 \n\t" + "push r22 \n\t" + "push r23 \n\t" + "push r26 \n\t" + "push r27 \n\t" + ::); +#endif + + uint8_t d = 0; + + // If RX line is high, then we don't see any start bit + // so interrupt is probably not for us + if (_inverse_logic ? rx_pin_read() : !rx_pin_read()) + { + // Disable further interrupts during reception, this prevents + // triggering another interrupt directly after we return, which can + // cause problems at higher baudrates. + setRxIntMsk(false); + + // Wait approximately 1/2 of a bit width to "center" the sample + tunedDelay(_rx_delay_centering); + DebugPulse(_DEBUG_PIN2, 1); + + // Read each of the 8 bits + for (uint8_t i=8; i > 0; --i) + { + tunedDelay(_rx_delay_intrabit); + d >>= 1; + DebugPulse(_DEBUG_PIN2, 1); + if (rx_pin_read()) + d |= 0x80; + } + + if (_inverse_logic) + d = ~d; + + // if buffer full, set the overflow flag and return + uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF; + if (next != _receive_buffer_head) + { + // save new data in buffer: tail points to where byte goes + _receive_buffer[_receive_buffer_tail] = d; // save new byte + _receive_buffer_tail = next; + } + else + { + DebugPulse(_DEBUG_PIN1, 1); + _buffer_overflow = true; + } + + // skip the stop bit + tunedDelay(_rx_delay_stopbit); + DebugPulse(_DEBUG_PIN1, 1); + + // Re-enable interrupts when we're sure to be inside the stop bit + setRxIntMsk(true); + + } + +#if GCC_VERSION < 40302 +// Work-around for avr-gcc 4.3.0 OSX version bug +// Restore the registers that the compiler misses + asm volatile( + "pop r27 \n\t" + "pop r26 \n\t" + "pop r23 \n\t" + "pop r22 \n\t" + "pop r21 \n\t" + "pop r20 \n\t" + "pop r19 \n\t" + "pop r18 \n\t" + ::); +#endif +} + +uint8_t SoftwareSerial::rx_pin_read() +{ + return *_receivePortRegister & _receiveBitMask; +} + +// +// Interrupt handling +// + +/* static */ +inline void SoftwareSerial::handle_interrupt() +{ + if (active_object) + { + active_object->recv(); + } +} + +// +// Constructor +// +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : + _rx_delay_centering(0), + _rx_delay_intrabit(0), + _rx_delay_stopbit(0), + _tx_delay(0), + _buffer_overflow(false), + _inverse_logic(inverse_logic) +{ + setTX(transmitPin); + setRX(receivePin); +} + +// +// Destructor +// +SoftwareSerial::~SoftwareSerial() +{ + end(); +} + +void SoftwareSerial::setTX(uint8_t tx) +{ + // First write, then set output. If we do this the other way around, + // the pin would be output low for a short while before switching to + // output high. Now, it is input with pullup for a short while, which + // is fine. With inverse logic, either order is fine. + digitalWrite(tx, _inverse_logic ? LOW : HIGH); + pinMode(tx, OUTPUT); + _transmitBitMask = digitalPinToBitMask(tx); + uint8_t port = digitalPinToPort(tx); + _transmitPortRegister = portOutputRegister(port); +} + +void SoftwareSerial::setRX(uint8_t rx) +{ + pinMode(rx, INPUT); + if (!_inverse_logic) + digitalWrite(rx, HIGH); // pullup for normal logic! + _receivePin = rx; + _receiveBitMask = digitalPinToBitMask(rx); + uint8_t port = digitalPinToPort(rx); + _receivePortRegister = portInputRegister(port); +} + +uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) { + if (num > sub) + return num - sub; + else + return 1; +} + +// +// Public methods +// + +void SoftwareSerial::begin(long speed) +{ + _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0; + + // Precalculate the various delays, in number of 4-cycle delays + uint16_t bit_delay = (F_CPU / speed) / 4; + + // 12 (gcc 4.8.2) or 13 (gcc 4.3.2) cycles from start bit to first bit, + // 15 (gcc 4.8.2) or 16 (gcc 4.3.2) cycles between bits, + // 12 (gcc 4.8.2) or 14 (gcc 4.3.2) cycles from last bit to stop bit + // These are all close enough to just use 15 cycles, since the inter-bit + // timings are the most critical (deviations stack 8 times) + _tx_delay = subtract_cap(bit_delay, 15 / 4); + + // Only setup rx when we have a valid PCINT for this pin + if (1) { + #if GCC_VERSION > 40800 + // Timings counted from gcc 4.8.2 output. This works up to 115200 on + // 16Mhz and 57600 on 8Mhz. + // + // When the start bit occurs, there are 3 or 4 cycles before the + // interrupt flag is set, 4 cycles before the PC is set to the right + // interrupt vector address and the old PC is pushed on the stack, + // and then 75 cycles of instructions (including the RJMP in the + // ISR vector table) until the first delay. After the delay, there + // are 17 more cycles until the pin value is read (excluding the + // delay in the loop). + // We want to have a total delay of 1.5 bit time. Inside the loop, + // we already wait for 1 bit time - 23 cycles, so here we wait for + // 0.5 bit time - (71 + 18 - 22) cycles. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 75 + 17 - 23) / 4); + + // There are 23 cycles in each loop iteration (excluding the delay) + _rx_delay_intrabit = subtract_cap(bit_delay, 23 / 4); + + // There are 37 cycles from the last bit read to the start of + // stopbit delay and 11 cycles from the delay until the interrupt + // mask is enabled again (which _must_ happen during the stopbit). + // This delay aims at 3/4 of a bit time, meaning the end of the + // delay will be at 1/4th of the stopbit. This allows some extra + // time for ISR cleanup, which makes 115200 baud at 16Mhz work more + // reliably + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (37 + 11) / 4); + #else // Timings counted from gcc 4.3.2 output + // Note that this code is a _lot_ slower, mostly due to bad register + // allocation choices of gcc. This works up to 57600 on 16Mhz and + // 38400 on 8Mhz. + _rx_delay_centering = subtract_cap(bit_delay / 2, (4 + 4 + 97 + 29 - 11) / 4); + _rx_delay_intrabit = subtract_cap(bit_delay, 11 / 4); + _rx_delay_stopbit = subtract_cap(bit_delay * 3 / 4, (44 + 17) / 4); + #endif + + attachInterrupt(_receivePin, SoftwareSerial::handle_interrupt, CHANGE); + + tunedDelay(_tx_delay); // if we were low this establishes the end + } + +#if _DEBUG + pinMode(_DEBUG_PIN1, OUTPUT); + pinMode(_DEBUG_PIN2, OUTPUT); +#endif + + listen(); +} + +void SoftwareSerial::setRxIntMsk(bool enable) +{ + if (enable) + *_pcint_maskreg |= _pcint_maskvalue; + else + *_pcint_maskreg &= ~_pcint_maskvalue; +} + +void SoftwareSerial::end() +{ + stopListening(); +} + + +// Read data from buffer +int SoftwareSerial::read() +{ + if (!isListening()) + return -1; + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; + + // Read from "head" + uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte + _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; + return d; +} + +int SoftwareSerial::available() +{ + if (!isListening()) + return 0; + + return ((uint16_t)(_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head)) % _SS_MAX_RX_BUFF; +} + +size_t SoftwareSerial::write(uint8_t b) +{ + if (_tx_delay == 0) { + setWriteError(); + return 0; + } + + // By declaring these as local variables, the compiler will put them + // in registers _before_ disabling interrupts and entering the + // critical timing sections below, which makes it a lot easier to + // verify the cycle timings + volatile uint8_t *reg = _transmitPortRegister; + uint8_t reg_mask = _transmitBitMask; + uint8_t inv_mask = ~_transmitBitMask; + uint8_t oldSREG = SREG; + bool inv = _inverse_logic; + uint16_t delay = _tx_delay; + + if (inv) + b = ~b; + + cli(); // turn off interrupts for a clean txmit + + // Write the start bit + if (inv) + *reg |= reg_mask; + else + *reg &= inv_mask; + + tunedDelay(delay); + + // Write each of the 8 bits + for (uint8_t i = 8; i > 0; --i) + { + if (b & 1) // choose bit + *reg |= reg_mask; // send 1 + else + *reg &= inv_mask; // send 0 + + tunedDelay(delay); + b >>= 1; + } + + // restore pin to natural state + if (inv) + *reg &= inv_mask; + else + *reg |= reg_mask; + + SREG = oldSREG; // turn interrupts back on + tunedDelay(_tx_delay); + + return 1; +} + +void SoftwareSerial::flush() +{ + // There is no tx buffering, simply return +} + +int SoftwareSerial::peek() +{ + if (!isListening()) + return -1; + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + return -1; + + // Read from "head" + return _receive_buffer[_receive_buffer_head]; +} diff --git a/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.h b/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.h index b1a37c4..ca4fd75 100644 --- a/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/megaavr/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -1,123 +1,123 @@ -/* -SoftwareSerial.h (formerly NewSoftSerial.h) - -Multi-instance software serial library for Arduino/Wiring --- Interrupt-driven receive and other improvements by ladyada - (http://ladyada.net) --- Tuning, circular buffer, derivation from class Print/Stream, - multi-instance support, porting to 8MHz processors, - various optimizations, PROGMEM delay tables, inverse logic and - direct port writing by Mikal Hart (http://www.arduiniana.org) --- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) --- 20MHz processor support by Garrett Mace (http://www.macetech.com) --- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) - -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 St, Fifth Floor, Boston, MA 02110-1301 USA - -The latest version of this library can always be found at -http://arduiniana.org. -*/ - -#ifndef SoftwareSerial_h -#define SoftwareSerial_h - -#include -#include - -/****************************************************************************** -* Definitions -******************************************************************************/ - -#ifndef _SS_MAX_RX_BUFF -#define _SS_MAX_RX_BUFF 64 // RX buffer size -#endif - -#ifndef GCC_VERSION -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - -class SoftwareSerial : public Stream -{ -private: - // per object data - uint8_t _receivePin; - uint8_t _receiveBitMask; - volatile uint8_t *_receivePortRegister; - uint8_t _transmitBitMask; - volatile uint8_t *_transmitPortRegister; - volatile uint8_t *_pcint_maskreg; - uint8_t _pcint_maskvalue; - - // Expressed as 4-cycle delays (must never be 0!) - uint16_t _rx_delay_centering; - uint16_t _rx_delay_intrabit; - uint16_t _rx_delay_stopbit; - uint16_t _tx_delay; - - uint16_t _buffer_overflow:1; - uint16_t _inverse_logic:1; - - // static data - static uint8_t _receive_buffer[_SS_MAX_RX_BUFF]; - static volatile uint8_t _receive_buffer_tail; - static volatile uint8_t _receive_buffer_head; - static SoftwareSerial *active_object; - - // private methods - inline void recv() __attribute__((__always_inline__)); - uint8_t rx_pin_read(); - void setTX(uint8_t transmitPin); - void setRX(uint8_t receivePin); - inline void setRxIntMsk(bool enable) __attribute__((__always_inline__)); - - // Return num - sub, or 1 if the result would be < 1 - static uint16_t subtract_cap(uint16_t num, uint16_t sub); - - // private static method for timing - static inline void tunedDelay(uint16_t delay); - -public: - // public methods - SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); - ~SoftwareSerial(); - void begin(long speed); - bool listen(); - void end(); - bool isListening() { return this == active_object; } - bool stopListening(); - bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } - int peek(); - - virtual size_t write(uint8_t byte); - virtual int read(); - virtual int available(); - virtual void flush(); - operator bool() { return true; } - - using Print::write; - - // public only for easy access by interrupt handlers - static inline void handle_interrupt() __attribute__((__always_inline__)); -}; - -// Arduino 0012 workaround -#undef int -#undef char -#undef long -#undef byte -#undef float -#undef abs -#undef round - -#endif +/* +SoftwareSerial.h (formerly NewSoftSerial.h) - +Multi-instance software serial library for Arduino/Wiring +-- Interrupt-driven receive and other improvements by ladyada + (http://ladyada.net) +-- Tuning, circular buffer, derivation from class Print/Stream, + multi-instance support, porting to 8MHz processors, + various optimizations, PROGMEM delay tables, inverse logic and + direct port writing by Mikal Hart (http://www.arduiniana.org) +-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com) +-- 20MHz processor support by Garrett Mace (http://www.macetech.com) +-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/) + +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 St, Fifth Floor, Boston, MA 02110-1301 USA + +The latest version of this library can always be found at +http://arduiniana.org. +*/ + +#ifndef SoftwareSerial_h +#define SoftwareSerial_h + +#include +#include + +/****************************************************************************** +* Definitions +******************************************************************************/ + +#ifndef _SS_MAX_RX_BUFF +#define _SS_MAX_RX_BUFF 64 // RX buffer size +#endif + +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#endif + +class SoftwareSerial : public Stream +{ +private: + // per object data + uint8_t _receivePin; + uint8_t _receiveBitMask; + volatile uint8_t *_receivePortRegister; + uint8_t _transmitBitMask; + volatile uint8_t *_transmitPortRegister; + volatile uint8_t *_pcint_maskreg; + uint8_t _pcint_maskvalue; + + // Expressed as 4-cycle delays (must never be 0!) + uint16_t _rx_delay_centering; + uint16_t _rx_delay_intrabit; + uint16_t _rx_delay_stopbit; + uint16_t _tx_delay; + + uint16_t _buffer_overflow:1; + uint16_t _inverse_logic:1; + + // static data + static uint8_t _receive_buffer[_SS_MAX_RX_BUFF]; + static volatile uint8_t _receive_buffer_tail; + static volatile uint8_t _receive_buffer_head; + static SoftwareSerial *active_object; + + // private methods + inline void recv() __attribute__((__always_inline__)); + uint8_t rx_pin_read(); + void setTX(uint8_t transmitPin); + void setRX(uint8_t receivePin); + inline void setRxIntMsk(bool enable) __attribute__((__always_inline__)); + + // Return num - sub, or 1 if the result would be < 1 + static uint16_t subtract_cap(uint16_t num, uint16_t sub); + + // private static method for timing + static inline void tunedDelay(uint16_t delay); + +public: + // public methods + SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + ~SoftwareSerial(); + void begin(long speed); + bool listen(); + void end(); + bool isListening() { return this == active_object; } + bool stopListening(); + bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; } + int peek(); + + virtual size_t write(uint8_t byte); + virtual int read(); + virtual int available(); + virtual void flush(); + explicit operator bool() { return true; } + + using Print::write; + + // public only for easy access by interrupt handlers + static inline void handle_interrupt() __attribute__((__always_inline__)); +}; + +// Arduino 0012 workaround +#undef int +#undef char +#undef long +#undef byte +#undef float +#undef abs +#undef round + +#endif diff --git a/megaavr/libraries/Wire/keywords.txt b/megaavr/libraries/Wire/keywords.txt index 5e3d2b1..5ad6fce 100644 --- a/megaavr/libraries/Wire/keywords.txt +++ b/megaavr/libraries/Wire/keywords.txt @@ -11,6 +11,8 @@ ####################################### begin KEYWORD2 +pins KEYWORD2 +swap KEYWORD2 setClock KEYWORD2 beginTransmission KEYWORD2 endTransmission KEYWORD2 diff --git a/megaavr/libraries/Wire/src/Wire.cpp b/megaavr/libraries/Wire/src/Wire.cpp index 060e92a..68b62cf 100644 --- a/megaavr/libraries/Wire/src/Wire.cpp +++ b/megaavr/libraries/Wire/src/Wire.cpp @@ -15,16 +15,17 @@ 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 St, Fifth Floor, Boston, MA 02110-1301 USA - + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts Modified 2017 by Chuck Todd (ctodd@cableone.net) to correct Unconfigured Slave Mode reboot */ -extern "C" { - #include - #include - #include - #include "utility/twi.h" +extern "C" +{ +#include +#include +#include +#include "utility/twi.h" } #include "Wire.h" @@ -33,14 +34,14 @@ extern "C" { // Initialize Class Variables ////////////////////////////////////////////////// -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; //head -uint8_t TwoWire::rxBufferLength = 0; //tail +uint8_t TwoWire::rxBuffer[TWI_BUFFER_SIZE]; +uint8_t TwoWire::rxBufferIndex = 0; //head +uint8_t TwoWire::rxBufferLength = 0; //tail uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; //head -uint8_t TwoWire::txBufferLength = 0; //tail +uint8_t TwoWire::txBuffer[TWI_BUFFER_SIZE]; +uint8_t TwoWire::txBufferIndex = 0; //head +uint8_t TwoWire::txBufferLength = 0; //tail uint8_t TwoWire::transmitting = 0; void (*TwoWire::user_onRequest)(void); @@ -54,74 +55,164 @@ TwoWire::TwoWire() // Public Methods ////////////////////////////////////////////////////////////// +// Special for megaAVR 0-series: Select which pins to use for I2C interface +// True if pin specification actually exists +// Note that we do not currently support the dual TWI mode +bool TwoWire::pins(uint8_t sda_pin, uint8_t scl_pin) +{ +#if defined(PIN_WIRE_SDA_PINSWAP_1) && defined(PIN_WIRE_SCL_PINSWAP_1) + if (sda_pin == PIN_WIRE_SDA_PINSWAP_1 && scl_pin == PIN_WIRE_SCL_PINSWAP_1) + { + // Use pin swap + PORTMUX.TWISPIROUTEA = TWI_MUX_PINSWAP | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return true; + } + else if (sda_pin == PIN_WIRE_SDA && scl_pin == PIN_WIRE_SCL) + { + // Use default configuration + PORTMUX.TWISPIROUTEA = TWI_MUX | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return true; + } + else + { + // Assume default configuration + PORTMUX.TWISPIROUTEA = TWI_MUX | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return false; + } +#else + (void)sda_pin; // Mute unused parameter warning + (void)scl_pin; + return false; +#endif + +} + +bool TwoWire::swap(uint8_t state) +{ +#if defined(PIN_WIRE_SDA_PINSWAP_1) && defined(PIN_WIRE_SCL_PINSWAP_1) + if (state == 1) + { + // Use pin swap + PORTMUX.TWISPIROUTEA = TWI_MUX_PINSWAP | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return true; + } + else if (state == 0) + { + // Use default configuration + PORTMUX.TWISPIROUTEA = TWI_MUX | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return true; + } + else + { + // Assume default configuration + PORTMUX.TWISPIROUTEA = TWI_MUX | (PORTMUX.TWISPIROUTEA & ~(3 << 4)); + return true; + } +#else + (void)state; // Mute unused parameter warning + return false; +#endif +} + void TwoWire::begin(void) { - rxBufferIndex = 0; - rxBufferLength = 0; + rxBufferIndex = 0; + rxBufferLength = 0; - txBufferIndex = 0; - txBufferLength = 0; + txBufferIndex = 0; + txBufferLength = 0; - TWI_MasterInit(DEFAULT_FREQUENCY); + TWI_MasterInit(DEFAULT_FREQUENCY); } -void TwoWire::begin(uint8_t address) +void TwoWire::begin(uint8_t address, bool receive_broadcast, uint8_t second_address) +{ + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + TWI_SlaveInit(address, receive_broadcast, second_address); + + TWI_attachSlaveTxEvent(onRequestService, txBuffer); // default callback must exist + TWI_attachSlaveRxEvent(onReceiveService, rxBuffer, TWI_BUFFER_SIZE); // default callback must exist +} + +void TwoWire::begin(int address, bool receive_broadcast, uint8_t second_address) { - rxBufferIndex = 0; - rxBufferLength = 0; + begin((uint8_t)address, receive_broadcast, second_address); +} - txBufferIndex = 0; - txBufferLength = 0; - - TWI_SlaveInit(address); - - TWI_attachSlaveTxEvent(onRequestService, txBuffer); // default callback must exist - TWI_attachSlaveRxEvent(onReceiveService, rxBuffer, BUFFER_LENGTH); // default callback must exist - +void TwoWire::begin(uint8_t address, bool receive_broadcast) +{ + begin(address, receive_broadcast, 0); +} + +void TwoWire::begin(int address, bool receive_broadcast) +{ + begin((uint8_t)address, receive_broadcast, 0); +} + +void TwoWire::begin(uint8_t address) +{ + begin(address, 0, 0); } void TwoWire::begin(int address) { - begin((uint8_t)address); + begin((uint8_t)address, 0, 0); } void TwoWire::end(void) { - TWI_Disable(); + TWI_Disable(); } -void TwoWire::setClock(uint32_t clock) +void TwoWire::setClock(uint32_t frequency) { - TWI_MasterSetBaud(clock); + TWI_MasterSetBaud(frequency); } -uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool sendStop) { - if(quantity > BUFFER_LENGTH){ - quantity = BUFFER_LENGTH; - } - - uint8_t bytes_read = TWI_MasterRead(address, rxBuffer, quantity, sendStop); - - /* Initialize read variables */ - rxBufferIndex = 0; - rxBufferLength = bytes_read; +uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool sendStop) +{ + if (quantity > TWI_BUFFER_SIZE) + { + quantity = TWI_BUFFER_SIZE; + } - return bytes_read; + uint8_t bytes_read = TWI_MasterRead(address, rxBuffer, quantity, sendStop); + + /* Initialize read variables */ + rxBufferIndex = 0; + rxBufferLength = bytes_read; + + return bytes_read; +} + +uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +{ + return requestFrom((uint8_t)address, (size_t)quantity, (bool)sendStop); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) +{ + return requestFrom((uint8_t)address, (size_t)quantity, (bool)sendStop); } uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity) { - return requestFrom(address, quantity, true); + return requestFrom(address, quantity, true); } -uint8_t TwoWire::requestFrom(int address, int quantity) +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { - return requestFrom((uint8_t)address, (size_t)quantity, true); + return requestFrom(address, (size_t)quantity, true); } -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) +uint8_t TwoWire::requestFrom(int address, int quantity) { - return requestFrom((uint8_t)address, (size_t)quantity, (bool)sendStop); + return requestFrom((uint8_t)address, (size_t)quantity, true); } void TwoWire::beginTransmission(uint8_t address) @@ -137,39 +228,39 @@ void TwoWire::beginTransmission(uint8_t address) void TwoWire::beginTransmission(int address) { - beginTransmission((uint8_t)address); + beginTransmission((uint8_t)address); } // -// Originally, 'endTransmission' was an f(void) function. -// It has been modified to take one parameter indicating -// whether or not a STOP should be performed on the bus. -// Calling endTransmission(false) allows a sketch to -// perform a repeated start. +// Originally, 'endTransmission' was an f(void) function. +// It has been modified to take one parameter indicating +// whether or not a STOP should be performed on the bus. +// Calling endTransmission(false) allows a sketch to +// perform a repeated start. // -// WARNING: Nothing in the library keeps track of whether -// the bus tenure has been properly ended with a STOP. It -// is very possible to leave the bus in a hung state if -// no call to endTransmission(true) is made. Some I2C -// devices will behave oddly if they do not see a STOP. +// WARNING: Nothing in the library keeps track of whether +// the bus tenure has been properly ended with a STOP. It +// is very possible to leave the bus in a hung state if +// no call to endTransmission(true) is made. Some I2C +// devices will behave oddly if they do not see a STOP. // uint8_t TwoWire::endTransmission(bool sendStop) { - // transmit buffer (blocking) - uint8_t status = TWI_MasterWrite(txAddress, txBuffer, txBufferLength, sendStop); - - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - - // indicate that we are done transmitting - transmitting = 0; - - return status; -} - -// This provides backwards compatibility with the original -// definition, and expected behaviour, of endTransmission + // transmit buffer (blocking) + uint8_t status = TWI_MasterWrite(txAddress, txBuffer, txBufferLength, sendStop); + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + transmitting = 0; + + return status; +} + +// This provides backwards compatibility with the original +// definition, and expected behaviour, of endTransmission // uint8_t TwoWire::endTransmission(void) { @@ -181,20 +272,21 @@ uint8_t TwoWire::endTransmission(void) // or after beginTransmission(address) size_t TwoWire::write(uint8_t data) { - /* Check if buffer is full */ - if(txBufferLength >= BUFFER_LENGTH){ - setWriteError(); - return 0; - } + /* Check if buffer is full */ + if (txBufferLength >= TWI_BUFFER_SIZE) + { + setWriteError(); + return 0; + } + + /* Put byte in txBuffer */ + txBuffer[txBufferIndex] = data; + txBufferIndex++; - /* Put byte in txBuffer */ - txBuffer[txBufferIndex] = data; - txBufferIndex++; + /* Update buffer length */ + txBufferLength = txBufferIndex; - /* Update buffer length */ - txBufferLength = txBufferIndex; - - return 1; + return 1; } // must be called in: @@ -202,122 +294,127 @@ size_t TwoWire::write(uint8_t data) // or after beginTransmission(address) size_t TwoWire::write(const uint8_t *data, size_t quantity) { + for (size_t i = 0; i < quantity; i++) + { + write(*(data + i)); + } - for(size_t i = 0; i < quantity; i++){ - write(*(data + i)); - } - - return quantity; + return quantity; } // must be called in: // slave rx event callback // or after requestFrom(address, numBytes) -int TwoWire::available(void) +int TwoWire::available() { - return rxBufferLength - rxBufferIndex; + return rxBufferLength - rxBufferIndex; } // must be called in: // slave rx event callback // or after requestFrom(address, numBytes) -int TwoWire::read(void) +int TwoWire::read() { - int value = -1; - - // get each successive byte on each call - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - rxBufferIndex++; - } + int value = -1; - return value; + // get each successive byte on each call + if (rxBufferIndex < rxBufferLength) + { + value = rxBuffer[rxBufferIndex]; + rxBufferIndex++; + } + + return value; } // must be called in: // slave rx event callback // or after requestFrom(address, numBytes) -int TwoWire::peek(void) +int TwoWire::peek() { - int value = -1; - - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - } + int value = -1; + + if (rxBufferIndex < rxBufferLength) + { + value = rxBuffer[rxBufferIndex]; + } - return value; + return value; } -// can be used to get out of an error state in TWI module +// can be used to get out of an error state in TWI module // e.g. when MDATA regsiter is written before MADDR -void TwoWire::flush(void) -{ -// /* Clear buffers */ -// for(uint8_t i = 0; i < BUFFER_LENGTH; i++){ -// txBuffer[i] = 0; -// rxBuffer[i] = 0; -// } -// -// /* Clear buffer variables */ -// txBufferIndex = 0; -// txBufferLength = 0; -// rxBufferIndex = 0; -// rxBufferLength = 0; -// -// /* Turn off and on TWI module */ -// TWI_Flush(); +void TwoWire::flush() +{ + // /* Clear buffers */ + // for(uint8_t i = 0; i < TWI_BUFFER_SIZE; i++){ + // txBuffer[i] = 0; + // rxBuffer[i] = 0; + // } + // + // /* Clear buffer variables */ + // txBufferIndex = 0; + // txBufferLength = 0; + // rxBufferIndex = 0; + // rxBufferLength = 0; + // + // /* Turn off and on TWI module */ + // TWI_Flush(); } // behind the scenes function that is called when data is received void TwoWire::onReceiveService(int numBytes) { - // don't bother if user hasn't registered a callback - if(!user_onReceive){ - return; - } - // don't bother if rx buffer is in use by a master requestFrom() op - // i know this drops data, but it allows for slight stupidity - // meaning, they may not have read all the master requestFrom() data yet - if(rxBufferIndex < rxBufferLength){ - return; - } - - // set rx iterator vars - rxBufferIndex = 0; - rxBufferLength = numBytes; - - // alert user program - user_onReceive(numBytes); + // don't bother if user hasn't registered a callback + if (!user_onReceive) + { + return; + } + // don't bother if rx buffer is in use by a master requestFrom() op + // i know this drops data, but it allows for slight stupidity + // meaning, they may not have read all the master requestFrom() data yet + if (rxBufferIndex < rxBufferLength) + { + return; + } + + // set rx iterator vars + rxBufferIndex = 0; + rxBufferLength = numBytes; + + // alert user program + user_onReceive(numBytes); } // behind the scenes function that is called when data is requested -uint8_t TwoWire::onRequestService(void) +uint8_t TwoWire::onRequestService() { - // don't bother if user hasn't registered a callback - if(!user_onRequest){ - return 0; - } - - // reset slave write buffer iterator var - txBufferIndex = 0; - txBufferLength = 0; - - // alert user program - user_onRequest(); + // don't bother if user hasn't registered a callback + if (!user_onRequest) + { + return 0; + } + + // reset slave write buffer iterator var + txBufferIndex = 0; + txBufferLength = 0; + + // alert user program + user_onRequest(); - return txBufferLength; + return txBufferLength; } // sets function called on slave write -void TwoWire::onReceive( void (*function)(int) ) +void TwoWire::onReceive(void (*function)(int)) { - user_onReceive = function; + user_onReceive = function; } // sets function called on slave read -void TwoWire::onRequest( void (*function)(void) ) +void TwoWire::onRequest(void (*function)(void)) { - user_onRequest = function; + user_onRequest = function; } // Preinstantiate Objects ////////////////////////////////////////////////////// diff --git a/megaavr/libraries/Wire/src/Wire.h b/megaavr/libraries/Wire/src/Wire.h index 0cc157c..ff5c9bc 100644 --- a/megaavr/libraries/Wire/src/Wire.h +++ b/megaavr/libraries/Wire/src/Wire.h @@ -24,12 +24,21 @@ #include -#define BUFFER_LENGTH 128 +#ifndef TWI_BUFFER_SIZE +#if ((RAMEND - RAMSTART) < 1023) +#define TWI_BUFFER_SIZE 16 +#elif ((RAMEND - RAMSTART) < 4095) +#define TWI_BUFFER_SIZE 32 +#elif ((RAMEND - RAMSTART) < 8191) +#define TWI_BUFFER_SIZE 64 +#else +#define TWI_BUFFER_SIZE 128 +#endif +#endif // WIRE_HAS_END means Wire has end() #define WIRE_HAS_END 1 - -class TwoWire : public HardwareI2C +class TwoWire : public Stream { private: static uint8_t rxBuffer[]; @@ -42,38 +51,47 @@ class TwoWire : public HardwareI2C static uint8_t txBufferLength; static uint8_t transmitting; - static void (*user_onRequest)(void); + static void (*user_onRequest)(); static void (*user_onReceive)(int); - static uint8_t onRequestService(void); + static uint8_t onRequestService(); static void onReceiveService(int); + public: TwoWire(); + bool pins(uint8_t sda_pin, uint8_t scl_pin); + bool swap(uint8_t state = 1); void begin(); - void begin(uint8_t); - void begin(int); + void begin(uint8_t address); + void begin(int address); + void begin(uint8_t address, bool receive_broadcast, uint8_t second_address); + void begin(int address, bool receive_broadcast, uint8_t second_address); + void begin(uint8_t address, bool receive_broadcast); + void begin(int address, bool receive_broadcast); void end(); - void setClock(uint32_t); - void beginTransmission(uint8_t); - void beginTransmission(int); - uint8_t endTransmission(void); - uint8_t endTransmission(bool); - uint8_t requestFrom(uint8_t, size_t); - uint8_t requestFrom(uint8_t, size_t, bool); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *, size_t); - virtual int available(void); - virtual int read(void); - virtual int peek(void); - virtual void flush(void); - void onReceive( void (*)(int) ); - void onRequest( void (*)(void) ); + void setClock(uint32_t frequency); + void beginTransmission(uint8_t address); + void beginTransmission(int address); + uint8_t endTransmission(); + uint8_t endTransmission(bool sendStop); + uint8_t requestFrom(uint8_t address, size_t quantity, bool sendStop); + uint8_t requestFrom(int address, int quantity, int sendStop); + uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop); + uint8_t requestFrom(uint8_t address, size_t quantity); + uint8_t requestFrom(uint8_t address, uint8_t quantity); + uint8_t requestFrom(int address, int quantity); + virtual size_t write(uint8_t data); + virtual size_t write(const uint8_t *data, size_t quantity); + virtual int available(); + virtual int read(); + virtual int peek(); + virtual void flush(); + void onReceive(void (*)(int)); + void onRequest(void (*)(void)); - inline size_t write(unsigned long n) { return write((uint8_t)n); } - inline size_t write(long n) { return write((uint8_t)n); } - inline size_t write(unsigned int n) { return write((uint8_t)n); } - inline size_t write(int n) { return write((uint8_t)n); } + inline size_t write(unsigned long data) { return write((uint8_t)data); } + inline size_t write(long data) { return write((uint8_t)data); } + inline size_t write(unsigned int data) { return write((uint8_t)data); } + inline size_t write(int data) { return write((uint8_t)data); } using Print::write; }; diff --git a/megaavr/libraries/Wire/src/utility/twi.c b/megaavr/libraries/Wire/src/utility/twi.c index 71e5d1b..b5909d2 100644 --- a/megaavr/libraries/Wire/src/utility/twi.c +++ b/megaavr/libraries/Wire/src/utility/twi.c @@ -1,767 +1,839 @@ -/****************************************************************************** -* (c) 2018 Microchip Technology Inc. and its subsidiaries. -* -* Subject to your compliance with these terms, you may use Microchip software -* and any derivatives exclusively with Microchip products. It is your -* responsibility to comply with third party license terms applicable to your -* use of third party software (including open source software) that may -* accompany Microchip software. -* -* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR -* PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, -* PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY -* KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP -* HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN -* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -* - *****************************************************************************/ - -#include "twi.h" -#include "Arduino.h" - -/* Master variables */ -static register8_t master_slaveAddress; /*!< Slave address */ -static register8_t* master_writeData; /*!< Data to write */ -static register8_t* master_readData; /*!< Read data */ -static register8_t master_bytesToWrite; /*!< Number of bytes to write */ -static register8_t master_bytesToRead; /*!< Number of bytes to read */ -static register8_t master_bytesWritten; /*!< Number of bytes written */ -static register8_t master_bytesRead; /*!< Number of bytes read */ -static register8_t master_sendStop; /*!< To send a stop at the end of the transaction or not */ -static register8_t master_trans_status; /*!< Status of transaction */ -static register8_t master_result; /*!< Result of transaction */ - -/* Slave variables */ -static uint8_t (*TWI_onSlaveTransmit)(void) __attribute__((unused)); -static void (*TWI_onSlaveReceive)(int) __attribute__((unused)); -static register8_t* slave_writeData; -static register8_t* slave_readData; -static register8_t slave_bytesToWrite; -static register8_t slave_bytesWritten; -static register8_t slave_bytesToRead; -static register8_t slave_bytesRead; -static register8_t slave_trans_status; -static register8_t slave_result; -static register8_t slave_callUserReceive; -static register8_t slave_callUserRequest; - -/* TWI module mode */ -static volatile TWI_MODE_t twi_mode; - -/*! \brief Initialize the TWI module as a master. - * - * TWI master initialization function. - * Enables master read and write interrupts. - * Remember to enable interrupts globally from the main application. - * - * \param frequency The required baud. - */ -void TWI_MasterInit(uint32_t frequency) -{ - if(twi_mode != TWI_MODE_UNKNOWN) return; - - // Enable pullups just in case, should have external ones though - //pinMode(PIN_WIRE_SDA, INPUT_PULLUP); - //pinMode(PIN_WIRE_SCL, INPUT_PULLUP); - - PORTMUX.TWISPIROUTEA |= TWI_MUX; - - twi_mode = TWI_MODE_MASTER; - - master_bytesRead = 0; - master_bytesWritten = 0; - master_trans_status = TWIM_STATUS_READY; - master_result = TWIM_RESULT_UNKNOWN; - - TWI0.MCTRLA = TWI_RIEN_bm | TWI_WIEN_bm | TWI_ENABLE_bm; - TWI_MasterSetBaud(frequency); - TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc; -} - -/*! \brief Initialize the TWI module as a slave. - * - * TWI slave initialization function. - * Enables slave address/stop and data interrupts. - * Assigns slave's own address. - * Remember to enable interrupts globally from the main application. - * - * \param address The TWI Slave's own address. - */ -void TWI_SlaveInit(uint8_t address) -{ - if(twi_mode != TWI_MODE_UNKNOWN) return; - - twi_mode = TWI_MODE_SLAVE; - - slave_bytesRead = 0; - slave_bytesWritten = 0; - slave_trans_status = TWIS_STATUS_READY; - slave_result = TWIS_RESULT_UNKNOWN; - slave_callUserRequest = 0; - slave_callUserReceive = 0; - - TWI0.SADDR = address << 1; - TWI0.SCTRLA = TWI_DIEN_bm | TWI_APIEN_bm | TWI_PIEN_bm | TWI_ENABLE_bm; - - /* Bus Error Detection circuitry needs Master enabled to work */ - TWI0.MCTRLA = TWI_ENABLE_bm; -} - -void TWI_Flush(void){ - TWI0.MCTRLB |= TWI_FLUSH_bm; -} - -/*! \brief Disable the TWI module. - * - * TWI module disable function. - * Disables both master and slave modes - * - * \param frequency The required baud. - */ -void TWI_Disable(void) -{ - TWI0.MCTRLA = 0x00; - TWI0.MBAUD = 0x00; - TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc; - TWI0.SADDR = 0x00; - TWI0.SCTRLA = 0x00; - - twi_mode = TWI_MODE_UNKNOWN; -} - -/*! \brief Returns the TWI bus state. - * - * Returns the TWI bus state (type defined in device headerfile), - * unknown, idle, owner or busy. - * - * \param twi The TWI_Master_t struct instance. - * - * \retval TWI_MASTER_BUSSTATE_UNKNOWN_gc Bus state is unknown. - * \retval TWI_MASTER_BUSSTATE_IDLE_gc Bus state is idle. - * \retval TWI_MASTER_BUSSTATE_OWNER_gc Bus state is owned by the master. - * \retval TWI_MASTER_BUSSTATE_BUSY_gc Bus state is busy. - */ -TWI_BUSSTATE_t TWI_MasterState(void) -{ - TWI_BUSSTATE_t twi_status; - twi_status = (TWI_BUSSTATE_t) (TWI0.MSTATUS & TWI_BUSSTATE_gm); - return twi_status; -} - - -/*! \brief Returns true if transaction is ready. - * - * This function returns a boolean whether the TWI Master is ready - * for a new transaction. - * - * \param twi The TWI_Master_t struct instance. - * - * \retval true If transaction could be started. - * \retval false If transaction could not be started. - */ -uint8_t TWI_MasterReady(void) -{ - uint8_t twi_status = (master_trans_status & TWIM_STATUS_READY); - return twi_status; -} - -/*! \brief Set the TWI baud rate. - * - * Sets the baud rate used by TWI Master. - * - * \param frequency The required baud. - */ -void TWI_MasterSetBaud(uint32_t frequency){ - -// Formula is: BAUD = ((F_CLKPER/frequency) - F_CLKPER*T_RISE - 10)/2; -// Where T_RISE varies depending on operating frequency... -// From 1617 DS: 1000ns @ 100kHz / 300ns @ 400kHz / 120ns @ 1MHz - - uint16_t t_rise; - - if(frequency < 200000){ - frequency = 100000; - t_rise = 1000; - - } else if (frequency < 800000){ - frequency = 400000; - t_rise = 300; - - } else if (frequency < 1200000){ - frequency = 1000000; - t_rise = 120; - - } else { - frequency = 100000; - t_rise = 1000; - } - - uint32_t baud = ((F_CPU_CORRECTED/frequency) - (((F_CPU_CORRECTED*t_rise)/1000)/1000)/1000 - 10)/2; - TWI0.MBAUD = (uint8_t)baud; - -} - -/*! \brief TWI write transaction. - * - * This function is TWI Master wrapper for a write-only transaction. - * - * \param twi The TWI_Master_t struct instance. - * \param address Slave address. - * \param writeData Pointer to data to write. - * \param bytesToWrite Number of data bytes to write. - * - * \retval true If transaction could be started. - * \retval false If transaction could not be started. - */ -uint8_t TWI_MasterWrite(uint8_t slave_address, - uint8_t *write_data, - uint8_t bytes_to_write, - uint8_t send_stop) -{ - return TWI_MasterWriteRead(slave_address, - write_data, - bytes_to_write, - 0, - send_stop); -} - - -/*! \brief TWI read transaction. - * - * This function is a TWI Master wrapper for read-only transaction. - * - * \param twi The TWI_Master_t struct instance. - * \param address The slave address. - * \param bytesToRead The number of bytes to read. - * - * \retval true If transaction could be started. - * \retval false If transaction could not be started. - */ -uint8_t TWI_MasterRead(uint8_t slave_address, - uint8_t* read_data, - uint8_t bytes_to_read, - uint8_t send_stop) -{ - master_readData = read_data; - - uint8_t bytes_read = TWI_MasterWriteRead(slave_address, - 0, - 0, - bytes_to_read, - send_stop); - return bytes_read; -} - - -/*! \brief TWI write and/or read transaction. - * - * This function is a TWI Master write and/or read transaction. The function - * can be used to both write and/or read bytes to/from the TWI Slave in one - * transaction. - * - * \param twi The TWI_Master_t struct instance. - * \param address The slave address. - * \param writeData Pointer to data to write. - * \param bytesToWrite Number of bytes to write. - * \param bytesToRead Number of bytes to read. - * - * \retval true If transaction could be started. - * \retval false If transaction could not be started. - */ -uint8_t TWI_MasterWriteRead(uint8_t slave_address, - uint8_t *write_data, - uint8_t bytes_to_write, - uint8_t bytes_to_read, - uint8_t send_stop) -{ - if(twi_mode != TWI_MODE_MASTER) return false; - - /*Initiate transaction if bus is ready. */ - if (master_trans_status == TWIM_STATUS_READY) { - - master_trans_status = TWIM_STATUS_BUSY; - master_result = TWIM_RESULT_UNKNOWN; - - master_writeData = write_data; - - master_bytesToWrite = bytes_to_write; - master_bytesToRead = bytes_to_read; - master_bytesWritten = 0; - master_bytesRead = 0; - master_sendStop = send_stop; - master_slaveAddress = slave_address<<1; - -trigger_action: - - /* If write command, send the START condition + Address + - * 'R/_W = 0' - */ - if (master_bytesToWrite > 0) { - twi_mode = TWI_MODE_MASTER_TRANSMIT; - uint8_t writeAddress = ADD_WRITE_BIT(master_slaveAddress); - TWI0.MADDR = writeAddress; - } - - /* If read command, send the START condition + Address + - * 'R/_W = 1' - */ - else if (master_bytesToRead > 0) { - twi_mode = TWI_MODE_MASTER_RECEIVE; - uint8_t readAddress = ADD_READ_BIT(master_slaveAddress); - TWI0.MADDR = readAddress; - } - - else if (master_bytesToWrite == 0 && master_bytesToRead == 0) { - twi_mode = TWI_MODE_MASTER_TRANSMIT; - uint8_t writeAddress = ADD_WRITE_BIT(master_slaveAddress); - TWI0.MADDR = writeAddress; - } - - /* Arduino requires blocking function */ - while(master_result == TWIM_RESULT_UNKNOWN) {} - - // in case of arbitration lost, retry sending - if (master_result == TWIM_RESULT_ARBITRATION_LOST) { - goto trigger_action; - } - - uint8_t ret = 0; - if (master_bytesToRead > 0) { - // return bytes really read - ret = master_bytesRead; - } else { - // return 0 if success, >0 otherwise - ret = (master_result == TWIM_RESULT_OK ? 0 : 1); - } - - return ret; - } else { - return 1; - } -} - - -/*! \brief Common TWI master interrupt service routine. - * - * Check current status and calls the appropriate handler. - * - */ -void TWI_MasterInterruptHandler() -{ - uint8_t currentStatus = TWI0.MSTATUS; - - /* If arbitration lost or bus error. */ - if ((currentStatus & TWI_ARBLOST_bm) || - (currentStatus & TWI_BUSERR_bm)) { - - TWI_MasterArbitrationLostBusErrorHandler(); - } - - /* If master write interrupt. */ - else if (currentStatus & TWI_WIF_bm) { - TWI_MasterWriteHandler(); - } - - /* If master read interrupt. */ - else if (currentStatus & TWI_RIF_bm) { - TWI_MasterReadHandler(); - } - - /* If unexpected state. */ - else { - TWI_MasterTransactionFinished(TWIM_RESULT_FAIL); - } -} - -/*! \brief TWI master arbitration lost and bus error interrupt handler. - * - * Handles TWI responses to lost arbitration and bus error. - * - */ -void TWI_MasterArbitrationLostBusErrorHandler() -{ - uint8_t currentStatus = TWI0.MSTATUS; - - /* If bus error. */ - if (currentStatus & TWI_BUSERR_bm) { - master_result = TWIM_RESULT_BUS_ERROR; - } - /* If arbitration lost. */ - else { - master_result = TWIM_RESULT_ARBITRATION_LOST; - } - - /* Clear all flags, abort operation */ - TWI0.MSTATUS = currentStatus; - - /* Wait for a new operation */ - twi_mode = TWI_MODE_MASTER; - master_trans_status = TWIM_STATUS_READY; -} - - -/*! \brief TWI master write interrupt handler. - * - * Handles TWI transactions (master write) and responses to (N)ACK. - * - */ -void TWI_MasterWriteHandler() -{ - /* Local variables used in if tests to avoid compiler warning. */ - uint8_t bytesToWrite = master_bytesToWrite; - uint8_t bytesToRead = master_bytesToRead; - - /* If NOT acknowledged (NACK) by slave cancel the transaction. */ - if (TWI0.MSTATUS & TWI_RXACK_bm) { - if(master_sendStop){ - TWI0.MCTRLB = TWI_MCMD_STOP_gc; - } else { - TWI0.MCTRLB = TWI_MCMD_REPSTART_gc; - - } - TWI_MasterTransactionFinished(TWIM_RESULT_NACK_RECEIVED); - } - - /* If more bytes to write, send data. */ - else if (master_bytesWritten < bytesToWrite) { - uint8_t data = master_writeData[master_bytesWritten]; - TWI0.MDATA = data; - master_bytesWritten++; - } - - /* If bytes to read, send START condition + Address + - * 'R/_W = 1' - */ - else if (master_bytesRead < bytesToRead) { - twi_mode = TWI_MODE_MASTER_RECEIVE; - uint8_t readAddress = ADD_READ_BIT(master_slaveAddress); - TWI0.MADDR = readAddress; - } - - /* If transaction finished, send ACK/STOP condition if instructed and set RESULT OK. */ - else { - if(master_sendStop){ - TWI0.MCTRLB = TWI_MCMD_STOP_gc; - } else { - TWI0.MCTRLB = TWI_MCMD_REPSTART_gc; - } - TWI_MasterTransactionFinished(TWIM_RESULT_OK); - } -} - - -/*! \brief TWI master read interrupt handler. - * - * This is the master read interrupt handler that takes care of - * reading bytes from the TWI slave. - * - * \param twi The TWI_Master_t struct instance. - */ -void TWI_MasterReadHandler() -{ - /* Fetch data if bytes to be read. */ - if (master_bytesRead < master_bytesToRead) { - uint8_t data = TWI0.MDATA; - master_readData[master_bytesRead] = data; - master_bytesRead++; - } - - /* If buffer overflow, issue NACK/STOP and BUFFER_OVERFLOW condition. */ - else { - if(master_sendStop){ - TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_STOP_gc; - } else { - TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_REPSTART_gc; - } - - TWI_MasterTransactionFinished(TWIM_RESULT_BUFFER_OVERFLOW); - master_bytesToRead = 0; - return; - } - - /* Local variable used in if test to avoid compiler warning. */ - uint8_t bytesToRead = master_bytesToRead; - - /* If more bytes to read, issue ACK and start a byte read. */ - if (master_bytesRead < bytesToRead) { - TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; - } - - /* If transaction finished, issue NACK and STOP condition if instructed. */ - else { - if(master_sendStop){ - TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_STOP_gc; - } else { - TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_REPSTART_gc; - } - - TWI_MasterTransactionFinished(TWIM_RESULT_OK); - } -} - - -/*! \brief TWI transaction finished handler. - * - * Prepares module for new transaction. - * - * \param result The result of the operation. - */ -void TWI_MasterTransactionFinished(uint8_t result) -{ - master_result = result; - master_trans_status = TWIM_STATUS_READY; - twi_mode = TWI_MODE_MASTER; -} - - -/*! \brief Common TWI slave interrupt service routine. - * - * Check current status and calls the appropriate handler. - * - */ -void TWI_SlaveInterruptHandler(){ - uint8_t currentStatus = TWI0.SSTATUS; - - /* If bus error */ - if(currentStatus & TWI_BUSERR_bm){ - slave_bytesRead = 0; - slave_bytesWritten = 0; - slave_bytesToWrite = 0; - TWI_SlaveTransactionFinished(TWIS_RESULT_BUS_ERROR); - } - - /* If Address or Stop */ - else if(currentStatus & TWI_APIF_bm){ - - /* Call user onReceive function if end of Master Write/Slave Read. - * This should be hit when there is a STOP or REPSTART - */ - if(slave_callUserReceive == 1){ - TWI_onSlaveReceive(slave_bytesRead); - slave_callUserReceive = 0; - } - - /* If address match */ - if(currentStatus & TWI_AP_bm){ - TWI_SlaveAddressMatchHandler(); - } - - /* If stop */ - else { - TWI_SlaveStopHandler(); - - /* If CLKHOLD is high, we have missed an address match - from a fast start after stop. - Because the flag is shared we need to handle this here. - */ - if(TWI0.SSTATUS & TWI_CLKHOLD_bm){ - - /* CLKHOLD will be cleared by servicing the address match */ - TWI_SlaveAddressMatchHandler(); - } - } - } - - /* If Data Interrupt */ - else if (currentStatus & TWI_DIF_bm){ - - /* If collision flag is raised, slave transmit unsuccessful */ - if (currentStatus & TWI_COLL_bm){ - slave_bytesRead = 0; - slave_bytesWritten = 0; - slave_bytesToWrite = 0; - TWI_SlaveTransactionFinished(TWIS_RESULT_TRANSMIT_COLLISION); - } - - /* Otherwise, normal data interrupt */ - else { - TWI_SlaveDataHandler(); - } - } - - /* If unexpected state */ - else { - TWI_SlaveTransactionFinished(TWIS_RESULT_FAIL); - } -} - -/*! \brief TWI slave address interrupt handler. - * - * This is the slave address match handler that takes care of responding to - * being addressed by a master - * - */ -void TWI_SlaveAddressMatchHandler(){ - slave_trans_status = TWIS_STATUS_BUSY; - slave_result = TWIS_RESULT_UNKNOWN; - - /* Send ACK, wait for data interrupt */ - TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; - - /* If Master Read/Slave Write */ - if(TWI0.SSTATUS & TWI_DIR_bm){ - slave_bytesWritten = 0; - /* Call user function */ - slave_bytesToWrite = TWI_onSlaveTransmit(); - twi_mode = TWI_MODE_SLAVE_TRANSMIT; - } - /* If Master Write/Slave Read */ - else { - slave_bytesRead = 0; - slave_callUserReceive = 1; - twi_mode = TWI_MODE_SLAVE_RECEIVE; - } - - /* Data interrupt to follow... */ -} - -/*! \brief TWI slave stop interrupt handler. - * - */ -void TWI_SlaveStopHandler(){ - - /* Clear APIF, don't ACK or NACK */ - TWI0.SSTATUS = TWI_APIF_bm; - - TWI_SlaveTransactionFinished(TWIS_RESULT_OK); - -} - -/*! \brief TWI slave data interrupt handler. - * - * This is the slave data handler that takes care of sending data to or - * receiving data from a master - * - */ -void TWI_SlaveDataHandler(){ - - /* Enable stop interrupt */ - TWI0.SCTRLA |= (TWI_APIEN_bm | TWI_PIEN_bm); - - /* If Master Read/Slave Write */ - if(TWI0.SSTATUS & TWI_DIR_bm){ - - TWI_SlaveWriteHandler(); - } - - /* If Master Write/Slave Read */ - else { - TWI_SlaveReadHandler(); - } - - -} - -/*! \brief TWI slave data write interrupt handler. - * - * This is the slave data handler that takes care of sending data to a master - * - */ -void TWI_SlaveWriteHandler(){ - - /* If NACK, slave write transaction finished */ - if((slave_bytesWritten > 0) && (TWI0.SSTATUS & TWI_RXACK_bm)){ - - TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; - TWI_SlaveTransactionFinished(TWIS_RESULT_OK); - } - - /* If ACK, master expects more data */ - else { - - if(slave_bytesWritten < slave_bytesToWrite){ - uint8_t data = slave_writeData[slave_bytesWritten]; - TWI0.SDATA = data; - slave_bytesWritten++; - - /* Send data, wait for data interrupt */ - TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; - - } - - /* If buffer overflow */ - else { - TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; - TWI_SlaveTransactionFinished(TWIS_RESULT_BUFFER_OVERFLOW); - - } - - - } -} - -/*! \brief TWI slave data read interrupt handler. - * - * This is the slave data handler that takes care of receiving data from a master - * - */ -void TWI_SlaveReadHandler(){ - - /* If free space in buffer */ - if(slave_bytesRead < slave_bytesToRead){ - - /* Fetch data */ - uint8_t data = TWI0.SDATA; - slave_readData[slave_bytesRead] = data; - slave_bytesRead++; - - /* Send ACK and wait for data interrupt */ - TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; - } - /* If buffer overflow, send NACK and wait for next START. - Set result buffer overflow */ - else { - TWI0.SCTRLB = TWI_ACKACT_bm | TWI_SCMD_COMPTRANS_gc; - TWI_SlaveTransactionFinished(TWIS_RESULT_BUFFER_OVERFLOW); - } -} - -/* - * Function twi_attachSlaveRxEvent - * Desc sets function called before a slave read operation - * Input function: callback function to use - * Output none - */ -void TWI_attachSlaveRxEvent( void (*function)(int), uint8_t *read_data, uint8_t bytes_to_read ){ - TWI_onSlaveReceive = function; - slave_readData = read_data; - slave_bytesToRead = bytes_to_read; -} - -/* - * Function twi_attachSlaveTxEvent - * Desc sets function called before a slave write operation - * Input function: callback function to use - * Output none - */ -void TWI_attachSlaveTxEvent( uint8_t (*function)(void), uint8_t* write_data ){ - TWI_onSlaveTransmit = function; - slave_writeData = write_data; -} - - -/*! \brief TWI slave transaction finished handler. - * - * Prepares module for new transaction. - * - * \param result The result of the operation. - */ -void TWI_SlaveTransactionFinished(uint8_t result) -{ - TWI0.SCTRLA |= (TWI_APIEN_bm | TWI_PIEN_bm); - twi_mode = TWI_MODE_SLAVE; - slave_result = result; - slave_trans_status = TWIM_STATUS_READY; -} - -ISR(TWI0_TWIM_vect){ - TWI_MasterInterruptHandler(); -} - -ISR(TWI0_TWIS_vect){ - TWI_SlaveInterruptHandler(); -} \ No newline at end of file +/****************************************************************************** +* (c) 2018 Microchip Technology Inc. and its subsidiaries. +* +* Subject to your compliance with these terms, you may use Microchip software +* and any derivatives exclusively with Microchip products. It is your +* responsibility to comply with third party license terms applicable to your +* use of third party software (including open source software) that may +* accompany Microchip software. +* +* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER +* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED +* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR +* PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, +* PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY +* KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP +* HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE +* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN +* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, +* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. +* + *****************************************************************************/ + +#include "twi.h" +#include "Arduino.h" + +/* Master variables */ +static register8_t master_slaveAddress; /*!< Slave address */ +static register8_t* master_writeData; /*!< Data to write */ +static register8_t* master_readData; /*!< Read data */ +static register8_t master_bytesToWrite; /*!< Number of bytes to write */ +static register8_t master_bytesToRead; /*!< Number of bytes to read */ +static register8_t master_bytesWritten; /*!< Number of bytes written */ +static register8_t master_bytesRead; /*!< Number of bytes read */ +static register8_t master_sendStop; /*!< To send a stop at the end of the transaction or not */ +static register8_t master_trans_status; /*!< Status of transaction */ +static register8_t master_result; /*!< Result of transaction */ + +/* Slave variables */ +static uint8_t (*TWI_onSlaveTransmit)(void) __attribute__((unused)); +static void (*TWI_onSlaveReceive)(int) __attribute__((unused)); +static register8_t* slave_writeData; +static register8_t* slave_readData; +static register8_t slave_bytesToWrite; +static register8_t slave_bytesWritten; +static register8_t slave_bytesToRead; +static register8_t slave_bytesRead; +static register8_t slave_trans_status; +static register8_t slave_result; +static register8_t slave_callUserReceive; +static register8_t slave_callUserRequest; + +/* TWI module mode */ +static volatile TWI_MODE_t twi_mode; + +/*! \brief Initialize the TWI module as a master. + * + * TWI master initialization function. + * Enables master read and write interrupts. + * Remember to enable interrupts globally from the main application. + * + * \param frequency The required baud. + */ +void TWI_MasterInit(uint32_t frequency) +{ + if (twi_mode != TWI_MODE_UNKNOWN) + return; + +// Enable input pullup for the default or pin swapped pin position + if ((PORTMUX.TWISPIROUTEA & 0x30) == TWI_MUX) + { + +// Disable pins hardwired to the default i2c pins (PA2 and PA3) +#if defined(NANO_EVERY_PINOUT) + PORTF_PIN2CTRL &= ~PORT_PULLUPEN_bm; // Disable PF2 pullup + PORTF_PIN3CTRL &= ~PORT_PULLUPEN_bm; // Disable PF3 pullup + PORTF_DIRCLR = PIN2_bm | PIN3_bm; // Set PF2 and PF3 as inputs +#endif + + pinMode(PIN_WIRE_SDA, INPUT_PULLUP); // Enable PA2 pullup + pinMode(PIN_WIRE_SCL, INPUT_PULLUP); // Enable PA3 pullup + } +#if defined(PIN_WIRE_SDA_PINSWAP_1) && defined(PIN_WIRE_SCL_PINSWAP_1) + else if ((PORTMUX.TWISPIROUTEA & 0x30) == TWI_MUX_PINSWAP) + { + pinMode(PIN_WIRE_SDA_PINSWAP_1, INPUT_PULLUP); // Enable PC2 pullup + pinMode(PIN_WIRE_SCL_PINSWAP_1, INPUT_PULLUP); // Enable PC3 pullup + } +#endif + + twi_mode = TWI_MODE_MASTER; + + master_bytesRead = 0; + master_bytesWritten = 0; + master_trans_status = TWIM_STATUS_READY; + master_result = TWIM_RESULT_UNKNOWN; + + TWI0.MCTRLA = TWI_RIEN_bm | TWI_WIEN_bm | TWI_ENABLE_bm; + TWI_MasterSetBaud(frequency); + TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc; +} + +/*! \brief Initialize the TWI module as a slave. + * + * TWI slave initialization function. + * Enables slave address/stop and data interrupts. + * Assigns slave's own address. + * Remember to enable interrupts globally from the main application. + * + * \param address The TWI Slave's own address. + */ +void TWI_SlaveInit(uint8_t address, uint8_t receive_broadcast, uint8_t second_address) +{ + if (twi_mode != TWI_MODE_UNKNOWN) + return; + + // Disable pins hardwired to the default i2c pins (PA2 and PA3) +#if defined(NANO_EVERY_PINOUT) + if ((PORTMUX.TWISPIROUTEA & 0x30) == TWI_MUX) + { + PORTF_PIN2CTRL &= ~PORT_PULLUPEN_bm; // Disable PF2 pullup + PORTF_PIN3CTRL &= ~PORT_PULLUPEN_bm; // Disable PF3 pullup + PORTF_DIRCLR = PIN2_bm | PIN3_bm; // Set PF2 and PF3 as inputs + } +#endif + + twi_mode = TWI_MODE_SLAVE; + + slave_bytesRead = 0; + slave_bytesWritten = 0; + slave_trans_status = TWIS_STATUS_READY; + slave_result = TWIS_RESULT_UNKNOWN; + slave_callUserRequest = 0; + slave_callUserReceive = 0; + + TWI0.SADDR = address << 1 | receive_broadcast; + TWI0.SADDRMASK = second_address; + TWI0.SCTRLA = TWI_DIEN_bm | TWI_APIEN_bm | TWI_PIEN_bm | TWI_ENABLE_bm; + + /* Bus Error Detection circuitry needs Master enabled to work */ + TWI0.MCTRLA = TWI_ENABLE_bm; +} + +void TWI_Flush(void) +{ + TWI0.MCTRLB |= TWI_FLUSH_bm; +} + +/*! \brief Disable the TWI module. + * + * TWI module disable function. + * Disables both master and slave modes + * + */ +void TWI_Disable(void) +{ + TWI0.MCTRLA = 0x00; + TWI0.MBAUD = 0x00; + TWI0.MSTATUS = TWI_BUSSTATE_IDLE_gc; + TWI0.SADDR = 0x00; + TWI0.SCTRLA = 0x00; + TWI0.SADDRMASK = 0; + twi_mode = TWI_MODE_UNKNOWN; +} + +/*! \brief Returns the TWI bus state. + * + * Returns the TWI bus state (type defined in device headerfile), + * unknown, idle, owner or busy. + * + * \param twi The TWI_Master_t struct instance. + * + * \retval TWI_MASTER_BUSSTATE_UNKNOWN_gc Bus state is unknown. + * \retval TWI_MASTER_BUSSTATE_IDLE_gc Bus state is idle. + * \retval TWI_MASTER_BUSSTATE_OWNER_gc Bus state is owned by the master. + * \retval TWI_MASTER_BUSSTATE_BUSY_gc Bus state is busy. + */ +TWI_BUSSTATE_t TWI_MasterState(void) +{ + TWI_BUSSTATE_t twi_status; + twi_status = (TWI_BUSSTATE_t)(TWI0.MSTATUS & TWI_BUSSTATE_gm); + return twi_status; +} + +/*! \brief Returns true if transaction is ready. + * + * This function returns a boolean whether the TWI Master is ready + * for a new transaction. + * + * \param twi The TWI_Master_t struct instance. + * + * \retval true If transaction could be started. + * \retval false If transaction could not be started. + */ +uint8_t TWI_MasterReady(void) +{ + uint8_t twi_status = (master_trans_status & TWIM_STATUS_READY); + return twi_status; +} + +/*! \brief Set the TWI baud rate. + * + * Sets the baud rate used by TWI Master. + * + * \param frequency The required baud. + */ +void TWI_MasterSetBaud(uint32_t frequency) +{ + // Formula is: BAUD = ((F_CLKPER/frequency) - F_CLKPER*T_RISE - 10)/2; + // Where T_RISE varies depending on operating frequency... + // From 1617 DS: 1000ns @ 100kHz / 300ns @ 400kHz / 120ns @ 1MHz + + uint16_t t_rise; + uint16_t freq_khz = frequency / 1000; + + if (freq_khz < 200) + { + freq_khz = 100; + t_rise = 1000; + } + else if (freq_khz < 800) + { + freq_khz = 400; + t_rise = 300; + } + else if (freq_khz < 1200) + { + freq_khz = 1000; + t_rise = 120; + } + else + { + freq_khz = 100; + t_rise = 1000; + } + + uint32_t baud = ((F_CPU / 1000 / freq_khz) - (((F_CPU * t_rise) / 1000) / 1000) / 1000 - 10) / 2; + TWI0.MBAUD = (uint8_t)baud; +} + +/*! \brief TWI write transaction. + * + * This function is TWI Master wrapper for a write-only transaction. + * + * \param twi The TWI_Master_t struct instance. + * \param address Slave address. + * \param writeData Pointer to data to write. + * \param bytesToWrite Number of data bytes to write. + * + * \retval true If transaction could be started. + * \retval false If transaction could not be started. + */ +uint8_t TWI_MasterWrite(uint8_t slave_address, + uint8_t* write_data, + uint8_t bytes_to_write, + uint8_t send_stop) +{ + return TWI_MasterWriteRead(slave_address, + write_data, + bytes_to_write, + 0, + send_stop); +} + +/*! \brief TWI read transaction. + * + * This function is a TWI Master wrapper for read-only transaction. + * + * \param twi The TWI_Master_t struct instance. + * \param address The slave address. + * \param bytesToRead The number of bytes to read. + * + * \retval true If transaction could be started. + * \retval false If transaction could not be started. + */ +uint8_t TWI_MasterRead(uint8_t slave_address, + uint8_t* read_data, + uint8_t bytes_to_read, + uint8_t send_stop) +{ + master_readData = read_data; + + uint8_t bytes_read = TWI_MasterWriteRead(slave_address, + 0, + 0, + bytes_to_read, + send_stop); + return bytes_read; +} + +/*! \brief TWI write and/or read transaction. + * + * This function is a TWI Master write and/or read transaction. The function + * can be used to both write and/or read bytes to/from the TWI Slave in one + * transaction. + * + * \param twi The TWI_Master_t struct instance. + * \param address The slave address. + * \param writeData Pointer to data to write. + * \param bytesToWrite Number of bytes to write. + * \param bytesToRead Number of bytes to read. + * + * \retval true If transaction could be started. + * \retval false If transaction could not be started. + */ +uint8_t TWI_MasterWriteRead(uint8_t slave_address, + uint8_t* write_data, + uint8_t bytes_to_write, + uint8_t bytes_to_read, + uint8_t send_stop) +{ + if (twi_mode != TWI_MODE_MASTER) + return false; + + /*Initiate transaction if bus is ready. */ + if (master_trans_status == TWIM_STATUS_READY) + { + master_trans_status = TWIM_STATUS_BUSY; + master_result = TWIM_RESULT_UNKNOWN; + + master_writeData = write_data; + + master_bytesToWrite = bytes_to_write; + master_bytesToRead = bytes_to_read; + master_bytesWritten = 0; + master_bytesRead = 0; + master_sendStop = send_stop; + master_slaveAddress = slave_address << 1; + + trigger_action: + + /* If write command, send the START condition + Address + + * 'R/_W = 0' + */ + if (master_bytesToWrite > 0) + { + twi_mode = TWI_MODE_MASTER_TRANSMIT; + uint8_t writeAddress = ADD_WRITE_BIT(master_slaveAddress); + TWI0.MADDR = writeAddress; + } + + /* If read command, send the START condition + Address + + * 'R/_W = 1' + */ + else if (master_bytesToRead > 0) + { + twi_mode = TWI_MODE_MASTER_RECEIVE; + uint8_t readAddress = ADD_READ_BIT(master_slaveAddress); + TWI0.MADDR = readAddress; + } + + else if (master_bytesToWrite == 0 && master_bytesToRead == 0) + { + twi_mode = TWI_MODE_MASTER_TRANSMIT; + uint8_t writeAddress = ADD_WRITE_BIT(master_slaveAddress); + TWI0.MADDR = writeAddress; + } + + /* Arduino requires blocking function */ + while (master_result == TWIM_RESULT_UNKNOWN) + { + } + + // in case of arbitration lost, retry sending + if (master_result == TWIM_RESULT_ARBITRATION_LOST) + { + goto trigger_action; + } + + uint8_t ret = 0; + if (master_bytesToRead > 0) + { + // return bytes really read + ret = master_bytesRead; + } + else + { + // return 0 if success, 1 otherwise + ret = (master_result == TWIM_RESULT_OK ? 0 : 1); + } + + return ret; + } + else + { + return 1; + } +} + +/*! \brief Common TWI master interrupt service routine. + * + * Check current status and calls the appropriate handler. + * + */ +void TWI_MasterInterruptHandler() +{ + uint8_t currentStatus = TWI0.MSTATUS; + + /* If arbitration lost or bus error. */ + if ((currentStatus & TWI_ARBLOST_bm) || + (currentStatus & TWI_BUSERR_bm)) + { + TWI_MasterArbitrationLostBusErrorHandler(); + } + + /* If master write interrupt. */ + else if (currentStatus & TWI_WIF_bm) + { + TWI_MasterWriteHandler(); + } + + /* If master read interrupt. */ + else if (currentStatus & TWI_RIF_bm) + { + TWI_MasterReadHandler(); + } + + /* If unexpected state. */ + else + { + TWI_MasterTransactionFinished(TWIM_RESULT_FAIL); + } +} + +/*! \brief TWI master arbitration lost and bus error interrupt handler. + * + * Handles TWI responses to lost arbitration and bus error. + * + */ +void TWI_MasterArbitrationLostBusErrorHandler() +{ + uint8_t currentStatus = TWI0.MSTATUS; + + /* If bus error. */ + if (currentStatus & TWI_BUSERR_bm) + { + master_result = TWIM_RESULT_BUS_ERROR; + } + /* If arbitration lost. */ + else + { + master_result = TWIM_RESULT_ARBITRATION_LOST; + } + + /* Clear all flags, abort operation */ + TWI0.MSTATUS = currentStatus; + + /* Wait for a new operation */ + twi_mode = TWI_MODE_MASTER; + master_trans_status = TWIM_STATUS_READY; +} + +/*! \brief TWI master write interrupt handler. + * + * Handles TWI transactions (master write) and responses to (N)ACK. + * + */ +void TWI_MasterWriteHandler() +{ + /* Local variables used in if tests to avoid compiler warning. */ + uint8_t bytesToWrite = master_bytesToWrite; + uint8_t bytesToRead = master_bytesToRead; + + /* If NOT acknowledged (NACK) by slave cancel the transaction. */ + if (TWI0.MSTATUS & TWI_RXACK_bm) + { + if (master_sendStop) + { + TWI0.MCTRLB = TWI_MCMD_STOP_gc; + } + else + { + TWI0.MCTRLB = TWI_MCMD_REPSTART_gc; + } + TWI_MasterTransactionFinished(TWIM_RESULT_NACK_RECEIVED); + } + + /* If more bytes to write, send data. */ + else if (master_bytesWritten < bytesToWrite) + { + uint8_t data = master_writeData[master_bytesWritten]; + TWI0.MDATA = data; + master_bytesWritten++; + } + + /* If bytes to read, send START condition + Address + + * 'R/_W = 1' + */ + else if (master_bytesRead < bytesToRead) + { + twi_mode = TWI_MODE_MASTER_RECEIVE; + uint8_t readAddress = ADD_READ_BIT(master_slaveAddress); + TWI0.MADDR = readAddress; + } + + /* If transaction finished, send ACK/STOP condition if instructed and set RESULT OK. */ + else + { + if (master_sendStop) + { + TWI0.MCTRLB = TWI_MCMD_STOP_gc; + } + else + { + TWI0.MCTRLB = TWI_MCMD_REPSTART_gc; + } + TWI_MasterTransactionFinished(TWIM_RESULT_OK); + } +} + +/*! \brief TWI master read interrupt handler. + * + * This is the master read interrupt handler that takes care of + * reading bytes from the TWI slave. + * + * \param twi The TWI_Master_t struct instance. + */ +void TWI_MasterReadHandler() +{ + /* Fetch data if bytes to be read. */ + if (master_bytesRead < master_bytesToRead) + { + uint8_t data = TWI0.MDATA; + master_readData[master_bytesRead] = data; + master_bytesRead++; + } + + /* If buffer overflow, issue NACK/STOP and BUFFER_OVERFLOW condition. */ + else + { + if (master_sendStop) + { + TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_STOP_gc; + } + else + { + TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_REPSTART_gc; + } + + TWI_MasterTransactionFinished(TWIM_RESULT_BUFFER_OVERFLOW); + master_bytesToRead = 0; + return; + } + + /* Local variable used in if test to avoid compiler warning. */ + uint8_t bytesToRead = master_bytesToRead; + + /* If more bytes to read, issue ACK and start a byte read. */ + if (master_bytesRead < bytesToRead) + { + TWI0.MCTRLB = TWI_MCMD_RECVTRANS_gc; + } + + /* If transaction finished, issue NACK and STOP condition if instructed. */ + else + { + if (master_sendStop) + { + TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_STOP_gc; + } + else + { + TWI0.MCTRLB = TWI_ACKACT_bm | TWI_MCMD_REPSTART_gc; + } + + TWI_MasterTransactionFinished(TWIM_RESULT_OK); + } +} + +/*! \brief TWI transaction finished handler. + * + * Prepares module for new transaction. + * + * \param result The result of the operation. + */ +void TWI_MasterTransactionFinished(uint8_t result) +{ + master_result = result; + master_trans_status = TWIM_STATUS_READY; + twi_mode = TWI_MODE_MASTER; +} + +/*! \brief Common TWI slave interrupt service routine. + * + * Check current status and calls the appropriate handler. + * + */ +void TWI_SlaveInterruptHandler() +{ + uint8_t currentStatus = TWI0.SSTATUS; + + /* If bus error */ + if (currentStatus & TWI_BUSERR_bm) + { + slave_bytesRead = 0; + slave_bytesWritten = 0; + slave_bytesToWrite = 0; + TWI_SlaveTransactionFinished(TWIS_RESULT_BUS_ERROR); + } + + /* If Address or Stop */ + else if (currentStatus & TWI_APIF_bm) + { + /* Call user onReceive function if end of Master Write/Slave Read. + * This should be hit when there is a STOP or REPSTART + */ + if (slave_callUserReceive == 1) + { + TWI_onSlaveReceive(slave_bytesRead); + slave_callUserReceive = 0; + } + + /* If address match */ + if (currentStatus & TWI_AP_bm) + { + TWI_SlaveAddressMatchHandler(); + } + + /* If stop */ + else + { + TWI_SlaveStopHandler(); + + /* If CLKHOLD is high, we have missed an address match + from a fast start after stop. + Because the flag is shared we need to handle this here. + */ + if (TWI0.SSTATUS & TWI_CLKHOLD_bm) + { + /* CLKHOLD will be cleared by servicing the address match */ + TWI_SlaveAddressMatchHandler(); + } + } + } + + /* If Data Interrupt */ + else if (currentStatus & TWI_DIF_bm) + { + /* If collision flag is raised, slave transmit unsuccessful */ + if (currentStatus & TWI_COLL_bm) + { + slave_bytesRead = 0; + slave_bytesWritten = 0; + slave_bytesToWrite = 0; + TWI_SlaveTransactionFinished(TWIS_RESULT_TRANSMIT_COLLISION); + } + + /* Otherwise, normal data interrupt */ + else + { + TWI_SlaveDataHandler(); + } + } + + /* If unexpected state */ + else + { + TWI_SlaveTransactionFinished(TWIS_RESULT_FAIL); + } +} + +/*! \brief TWI slave address interrupt handler. + * + * This is the slave address match handler that takes care of responding to + * being addressed by a master + * + */ +void TWI_SlaveAddressMatchHandler() +{ + slave_trans_status = TWIS_STATUS_BUSY; + slave_result = TWIS_RESULT_UNKNOWN; + + /* Send ACK, wait for data interrupt */ + TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; + + /* If Master Read/Slave Write */ + if (TWI0.SSTATUS & TWI_DIR_bm) + { + slave_bytesWritten = 0; + /* Call user function */ + slave_bytesToWrite = TWI_onSlaveTransmit(); + twi_mode = TWI_MODE_SLAVE_TRANSMIT; + } + /* If Master Write/Slave Read */ + else + { + slave_bytesRead = 0; + slave_callUserReceive = 1; + twi_mode = TWI_MODE_SLAVE_RECEIVE; + } + + /* Data interrupt to follow... */ +} + +/*! \brief TWI slave stop interrupt handler. + * + */ +void TWI_SlaveStopHandler() +{ + /* Clear APIF, don't ACK or NACK */ + TWI0.SSTATUS = TWI_APIF_bm; + + TWI_SlaveTransactionFinished(TWIS_RESULT_OK); +} + +/*! \brief TWI slave data interrupt handler. + * + * This is the slave data handler that takes care of sending data to or + * receiving data from a master + * + */ +void TWI_SlaveDataHandler() +{ + /* Enable stop interrupt */ + TWI0.SCTRLA |= (TWI_APIEN_bm | TWI_PIEN_bm); + + /* If Master Read/Slave Write */ + if (TWI0.SSTATUS & TWI_DIR_bm) + { + TWI_SlaveWriteHandler(); + } + + /* If Master Write/Slave Read */ + else + { + TWI_SlaveReadHandler(); + } +} + +/*! \brief TWI slave data write interrupt handler. + * + * This is the slave data handler that takes care of sending data to a master + * + */ +void TWI_SlaveWriteHandler() +{ + /* If NACK, slave write transaction finished */ + if ((slave_bytesWritten > 0) && (TWI0.SSTATUS & TWI_RXACK_bm)) + { + TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(TWIS_RESULT_OK); + } + + /* If ACK, master expects more data */ + else + { + if (slave_bytesWritten < slave_bytesToWrite) + { + uint8_t data = slave_writeData[slave_bytesWritten]; + TWI0.SDATA = data; + slave_bytesWritten++; + + /* Send data, wait for data interrupt */ + TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; + } + + /* If buffer overflow */ + else + { + TWI0.SCTRLB = TWI_SCMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(TWIS_RESULT_BUFFER_OVERFLOW); + } + } +} + +/*! \brief TWI slave data read interrupt handler. + * + * This is the slave data handler that takes care of receiving data from a master + * + */ +void TWI_SlaveReadHandler() +{ + /* If free space in buffer */ + if (slave_bytesRead < slave_bytesToRead) + { + /* Fetch data */ + uint8_t data = TWI0.SDATA; + slave_readData[slave_bytesRead] = data; + slave_bytesRead++; + + /* Send ACK and wait for data interrupt */ + TWI0.SCTRLB = TWI_SCMD_RESPONSE_gc; + } + /* If buffer overflow, send NACK and wait for next START. + Set result buffer overflow */ + else + { + TWI0.SCTRLB = TWI_ACKACT_bm | TWI_SCMD_COMPTRANS_gc; + TWI_SlaveTransactionFinished(TWIS_RESULT_BUFFER_OVERFLOW); + } +} + +/* + * Function twi_attachSlaveRxEvent + * Desc sets function called before a slave read operation + * Input function: callback function to use + * Output none + */ +void TWI_attachSlaveRxEvent(void (*function)(int), uint8_t* read_data, uint8_t bytes_to_read) +{ + TWI_onSlaveReceive = function; + slave_readData = read_data; + slave_bytesToRead = bytes_to_read; +} + +/* + * Function twi_attachSlaveTxEvent + * Desc sets function called before a slave write operation + * Input function: callback function to use + * Output none + */ +void TWI_attachSlaveTxEvent(uint8_t (*function)(void), uint8_t* write_data) +{ + TWI_onSlaveTransmit = function; + slave_writeData = write_data; +} + +/*! \brief TWI slave transaction finished handler. + * + * Prepares module for new transaction. + * + * \param result The result of the operation. + */ +void TWI_SlaveTransactionFinished(uint8_t result) +{ + TWI0.SCTRLA |= (TWI_APIEN_bm | TWI_PIEN_bm); + twi_mode = TWI_MODE_SLAVE; + slave_result = result; + slave_trans_status = TWIM_STATUS_READY; +} + +ISR(TWI0_TWIM_vect) +{ + TWI_MasterInterruptHandler(); +} + +ISR(TWI0_TWIS_vect) +{ + TWI_SlaveInterruptHandler(); +} diff --git a/megaavr/libraries/Wire/src/utility/twi.h b/megaavr/libraries/Wire/src/utility/twi.h index 9895ba7..9663c27 100644 --- a/megaavr/libraries/Wire/src/utility/twi.h +++ b/megaavr/libraries/Wire/src/utility/twi.h @@ -1,127 +1,129 @@ -/****************************************************************************** -* (c) 2018 Microchip Technology Inc. and its subsidiaries. -* -* Subject to your compliance with these terms, you may use Microchip software -* and any derivatives exclusively with Microchip products. It is your -* responsibility to comply with third party license terms applicable to your -* use of third party software (including open source software) that may -* accompany Microchip software. -* -* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER -* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED -* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR -* PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, -* PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY -* KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP -* HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE -* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN -* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, -* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. -* - *****************************************************************************/ - -#ifndef TWI_DRIVER_H -#define TWI_DRIVER_H - -#include "avr/io.h" - -/*! Transaction status defines. */ -#define TWIM_STATUS_READY 0 -#define TWIM_STATUS_BUSY 1 - -/* Transaction status defines.*/ -#define TWIS_STATUS_READY 0 -#define TWIS_STATUS_BUSY 1 - -/*! Transaction result enumeration. */ -typedef enum TWIM_RESULT_enum { - TWIM_RESULT_UNKNOWN = (0x00<<0), - TWIM_RESULT_OK = (0x01<<0), - TWIM_RESULT_BUFFER_OVERFLOW = (0x02<<0), - TWIM_RESULT_ARBITRATION_LOST = (0x03<<0), - TWIM_RESULT_BUS_ERROR = (0x04<<0), - TWIM_RESULT_NACK_RECEIVED = (0x05<<0), - TWIM_RESULT_FAIL = (0x06<<0), -} TWIM_RESULT_t; - -/* Transaction result enumeration */ -typedef enum TWIS_RESULT_enum { - TWIS_RESULT_UNKNOWN = (0x00<<0), - TWIS_RESULT_OK = (0x01<<0), - TWIS_RESULT_BUFFER_OVERFLOW = (0x02<<0), - TWIS_RESULT_TRANSMIT_COLLISION = (0x03<<0), - TWIS_RESULT_BUS_ERROR = (0x04<<0), - TWIS_RESULT_FAIL = (0x05<<0), - TWIS_RESULT_ABORTED = (0x06<<0), -} TWIS_RESULT_t; - -/*! TWI Modes */ -typedef enum TWI_MODE_enum { - TWI_MODE_UNKNOWN = 0, - TWI_MODE_MASTER = 1, - TWI_MODE_SLAVE = 2, - TWI_MODE_MASTER_TRANSMIT = 3, - TWI_MODE_MASTER_RECEIVE = 4, - TWI_MODE_SLAVE_TRANSMIT = 5, - TWI_MODE_SLAVE_RECEIVE = 6 -} TWI_MODE_t; - -/*! For adding R/_W bit to address */ -#define ADD_READ_BIT(address) (address | 0x01) -#define ADD_WRITE_BIT(address) (address & ~0x01) - -void TWI_MasterInit(uint32_t frequency); -void TWI_SlaveInit(uint8_t address); -void TWI_Flush(void); -void TWI_Disable(void); -TWI_BUSSTATE_t TWI_MasterState(void); -uint8_t TWI_MasterReady(void); -void TWI_MasterSetBaud(uint32_t frequency); -uint8_t TWI_MasterWrite(uint8_t slave_address, - uint8_t *write_data, - uint8_t bytes_to_write, - uint8_t send_stop); -uint8_t TWI_MasterRead(uint8_t slave_address, - uint8_t* read_data, - uint8_t bytes_to_read, - uint8_t send_stop); -uint8_t TWI_MasterWriteRead(uint8_t slave_address, - uint8_t *write_data, - uint8_t bytes_to_write, - uint8_t bytes_to_read, - uint8_t send_stop); -void TWI_MasterInterruptHandler(void); -void TWI_MasterArbitrationLostBusErrorHandler(void); -void TWI_MasterWriteHandler(void); -void TWI_MasterReadHandler(void); -void TWI_MasterTransactionFinished(uint8_t result); - -void TWI_SlaveInterruptHandler(void); -void TWI_SlaveAddressMatchHandler(void); -void TWI_SlaveStopHandler(void); -void TWI_SlaveDataHandler(void); -void TWI_SlaveWriteHandler(void); -void TWI_SlaveReadHandler(void); -void TWI_attachSlaveRxEvent( void (*function)(int), uint8_t *read_data, uint8_t bytes_to_read ); -void TWI_attachSlaveTxEvent( uint8_t (*function)(void), uint8_t *write_data ); -void TWI_SlaveTransactionFinished(uint8_t result); -/*! TWI master interrupt service routine. - * - * Interrupt service routine for the TWI master. Copy the needed vectors - * into your code. - * - - - ISR(TWI0_TWIM_vect){ - TWI_MasterInterruptHandler(); - } - - ISR(TWI0_TWIS_vect){ - TWI_SlaveInterruptHandler(); - } - - * - */ - - -#endif /* TWI_DRIVER_H */ +/****************************************************************************** +* (c) 2018 Microchip Technology Inc. and its subsidiaries. +* +* Subject to your compliance with these terms, you may use Microchip software +* and any derivatives exclusively with Microchip products. It is your +* responsibility to comply with third party license terms applicable to your +* use of third party software (including open source software) that may +* accompany Microchip software. +* +* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER +* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED +* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR +* PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, +* PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY +* KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP +* HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE +* FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN +* ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, +* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. +* + *****************************************************************************/ + +#ifndef TWI_DRIVER_H +#define TWI_DRIVER_H + +#include "avr/io.h" + +/*! Transaction status defines. */ +#define TWIM_STATUS_READY 0 +#define TWIM_STATUS_BUSY 1 + +/* Transaction status defines.*/ +#define TWIS_STATUS_READY 0 +#define TWIS_STATUS_BUSY 1 + +/*! Transaction result enumeration. */ +typedef enum __attribute__((packed)) TWIM_RESULT_enum +{ + TWIM_RESULT_UNKNOWN = (0x00 << 0), + TWIM_RESULT_OK = (0x01 << 0), + TWIM_RESULT_BUFFER_OVERFLOW = (0x02 << 0), + TWIM_RESULT_ARBITRATION_LOST = (0x03 << 0), + TWIM_RESULT_BUS_ERROR = (0x04 << 0), + TWIM_RESULT_NACK_RECEIVED = (0x05 << 0), + TWIM_RESULT_FAIL = (0x06 << 0), +} TWIM_RESULT_t; + +/* Transaction result enumeration */ +typedef enum __attribute__((packed)) TWIS_RESULT_enum +{ + TWIS_RESULT_UNKNOWN = (0x00 << 0), + TWIS_RESULT_OK = (0x01 << 0), + TWIS_RESULT_BUFFER_OVERFLOW = (0x02 << 0), + TWIS_RESULT_TRANSMIT_COLLISION = (0x03 << 0), + TWIS_RESULT_BUS_ERROR = (0x04 << 0), + TWIS_RESULT_FAIL = (0x05 << 0), + TWIS_RESULT_ABORTED = (0x06 << 0), +} TWIS_RESULT_t; + +/*! TWI Modes */ +typedef enum __attribute__((packed)) TWI_MODE_enum +{ + TWI_MODE_UNKNOWN = 0, + TWI_MODE_MASTER = 1, + TWI_MODE_SLAVE = 2, + TWI_MODE_MASTER_TRANSMIT = 3, + TWI_MODE_MASTER_RECEIVE = 4, + TWI_MODE_SLAVE_TRANSMIT = 5, + TWI_MODE_SLAVE_RECEIVE = 6 +} TWI_MODE_t; + +/*! For adding R/_W bit to address */ +#define ADD_READ_BIT(address) (address | 0x01) +#define ADD_WRITE_BIT(address) (address & ~0x01) + +void TWI_MasterInit(uint32_t frequency); +void TWI_SlaveInit(uint8_t address, uint8_t receive_broadcast, uint8_t second_address); +void TWI_Flush(void); +void TWI_Disable(void); +TWI_BUSSTATE_t TWI_MasterState(void); +uint8_t TWI_MasterReady(void); +void TWI_MasterSetBaud(uint32_t frequency); +uint8_t TWI_MasterWrite(uint8_t slave_address, + uint8_t *write_data, + uint8_t bytes_to_write, + uint8_t send_stop); +uint8_t TWI_MasterRead(uint8_t slave_address, + uint8_t *read_data, + uint8_t bytes_to_read, + uint8_t send_stop); +uint8_t TWI_MasterWriteRead(uint8_t slave_address, + uint8_t *write_data, + uint8_t bytes_to_write, + uint8_t bytes_to_read, + uint8_t send_stop); +void TWI_MasterInterruptHandler(void); +void TWI_MasterArbitrationLostBusErrorHandler(void); +void TWI_MasterWriteHandler(void); +void TWI_MasterReadHandler(void); +void TWI_MasterTransactionFinished(uint8_t result); + +void TWI_SlaveInterruptHandler(void); +void TWI_SlaveAddressMatchHandler(void); +void TWI_SlaveStopHandler(void); +void TWI_SlaveDataHandler(void); +void TWI_SlaveWriteHandler(void); +void TWI_SlaveReadHandler(void); +void TWI_attachSlaveRxEvent(void (*function)(int), uint8_t *read_data, uint8_t bytes_to_read); +void TWI_attachSlaveTxEvent(uint8_t (*function)(void), uint8_t *write_data); +void TWI_SlaveTransactionFinished(uint8_t result); +/*! TWI master interrupt service routine. + * + * Interrupt service routine for the TWI master. Copy the needed vectors + * into your code. + * + + + ISR(TWI0_TWIM_vect){ + TWI_MasterInterruptHandler(); + } + + ISR(TWI0_TWIS_vect){ + TWI_SlaveInterruptHandler(); + } + + * + */ + +#endif /* TWI_DRIVER_H */ diff --git a/megaavr/platform.txt b/megaavr/platform.txt index f26ec07..a727d82 100644 --- a/megaavr/platform.txt +++ b/megaavr/platform.txt @@ -6,7 +6,7 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification name=MegaCoreX -version=0.1.0 +version=1.1.5 # AVR compile variables # --------------------- @@ -18,19 +18,22 @@ compiler.warning_flags.more=-Wall compiler.warning_flags.all=-Wall -Wextra # Default "compiler.path" is correct, change only if you want to override the initial value -compiler.path={runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path}/bin/ +compiler.path={runtime.tools.avr-gcc.path}/bin/ compiler.c.cmd=avr-gcc -compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections +compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -mrelax +compiler.c.elf.flags={compiler.warning_flags} -Os -g -flto -fuse-linker-plugin -mrelax -Wl,--gc-sections -Wl,--section-start={build.text_section_start} compiler.c.elf.cmd=avr-gcc compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD compiler.cpp.cmd=avr-g++ -compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto +compiler.cpp.flags=-c -g -Os {compiler.warning_flags} -std=gnu++17 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mrelax compiler.ar.cmd=avr-gcc-ar compiler.ar.flags=rcs compiler.objcopy.cmd=avr-objcopy compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 +compiler.objdump.cmd=avr-objdump +compiler.objdump.flags=--disassemble --source --line-numbers --demangle --section=.text compiler.elf2hex.flags=-O ihex -R .eeprom +compiler.elf2hex.bin.flags=-O binary -R .eeprom compiler.elf2hex.cmd=avr-objcopy compiler.ldflags= compiler.size.cmd=avr-size @@ -71,13 +74,32 @@ recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.f recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" +## Save disassembler listing +# Dummy initial `echo.` command prevents unwanted stripping of quotes by `cmd /C` which would cause the command to fail for paths with spaces +recipe.hooks.objcopy.postobjcopy.1.pattern.windows=cmd /C echo. && "{compiler.path}{compiler.objdump.cmd}" {compiler.objdump.flags} "{build.path}/{build.project_name}.elf" > "{build.path}/{build.project_name}_{build.mcu}_{build.f_cpu}.lst" +recipe.hooks.objcopy.postobjcopy.1.pattern.linux=chmod +x "{runtime.platform.path}/scripts/create_disassembler_listing.sh" +recipe.hooks.objcopy.postobjcopy.1.pattern.macosx=chmod +x "{runtime.platform.path}/scripts/create_disassembler_listing.sh" +recipe.hooks.objcopy.postobjcopy.2.pattern.linux="{runtime.platform.path}/scripts/create_disassembler_listing.sh" "{compiler.path}{compiler.objdump.cmd}" "{compiler.objdump.flags}" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}_{build.mcu}_{build.f_cpu}.lst" +recipe.hooks.objcopy.postobjcopy.2.pattern.macosx="{runtime.platform.path}/scripts/create_disassembler_listing.sh" "{compiler.path}{compiler.objdump.cmd}" "{compiler.objdump.flags}" "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}_{build.mcu}_{build.f_cpu}.lst" + ## Save hex recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file={build.project_name}.{build.variant}.hex +recipe.output.save_file={build.project_name}_{build.mcu}_{build.f_cpu}.hex + +## Save hex +recipe.hooks.savehex.presavehex.1.pattern.windows="{runtime.platform.path}/scripts/delete_merged_output.bat" {build.export_merged_output} "{build.path}\{build.project_name}.with_bootloader.hex" +recipe.hooks.savehex.presavehex.2.pattern.windows=cmd /C copy "{build.path}\{build.project_name}_{build.mcu}_{build.f_cpu}.lst" "{sketch_path}" +recipe.hooks.savehex.presavehex.1.pattern.linux=chmod +x "{runtime.platform.path}/scripts/delete_merged_output.sh" +recipe.hooks.savehex.presavehex.2.pattern.linux="{runtime.platform.path}/scripts/delete_merged_output.sh" {build.export_merged_output} "{build.path}/{build.project_name}.with_bootloader.hex" +recipe.hooks.savehex.presavehex.3.pattern.linux=cp "{build.path}/{build.project_name}_{build.mcu}_{build.f_cpu}.lst" "{sketch_path}" +recipe.hooks.savehex.presavehex.1.pattern.macosx=chmod +x "{runtime.platform.path}/scripts/delete_merged_output.sh" +recipe.hooks.savehex.presavehex.2.pattern.macosx="{runtime.platform.path}/scripts/delete_merged_output.sh" {build.export_merged_output} "{build.path}/{build.project_name}.with_bootloader.hex" +recipe.hooks.savehex.presavehex.3.pattern.macosx=cp "{build.path}/{build.project_name}_{build.mcu}_{build.f_cpu}.lst" "{sketch_path}" + ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" -recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).* +recipe.size.regex=^(?:\.text|\.data|\.rodata|\.bootloader)\s+([0-9]+).* recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* @@ -91,9 +113,9 @@ recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} { # AVR Uploader/Programmers tools # ------------------------------ -tools.avrdude.path={runtime.tools.avrdude-6.3.0-arduino14.path} -tools.avrdude.cmd.path={path}/bin/avrdude -tools.avrdude.config.path={runtime.platform.path}/avrdude.conf +tools.avrdude.path={runtime.tools.avrdude.path} +tools.avrdude.cmd.path={runtime.tools.avrdude.path}/bin/avrdude +tools.avrdude.config.path={runtime.tools.avrdude.path}/etc/avrdude.conf tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA @@ -102,32 +124,29 @@ tools.avrdude.upload.params.quiet=-q -q # tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value tools.avrdude.upload.verify= tools.avrdude.upload.params.noverify=-V -tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} -Pusb -b{upload.speed} -e -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" {bootloader.fuse0} {bootloader.fuse1} {bootloader.fuse2} {bootloader.fuse4} {bootloader.fuse5} {bootloader.fuse6} {bootloader.fuse7} {bootloader.fuse8} {bootloader.lock} +tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" + +# Kind of a hacky way to implement support for the Nano every, where the IDE requires an upload sequence to perform 1200bps touch +tools.avrdude_nanoevery.upload.params.verbose=-v +tools.avrdude_nanoevery.upload.params.quiet=-q -q +tools.avrdude_nanoevery.upload.verify= +tools.avrdude_nanoevery.upload.params.noverify=-V +tools.avrdude_nanoevery.upload.pattern="{runtime.tools.avrdude.path}/bin/avrdude" "-C{runtime.tools.avrdude.path}/etc/avrdude.conf" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} {program.extra_params} -Ufuses:w:{bootloader.WDTCFG},{bootloader.BODCFG},{bootloader.OSCCFG},0xff,{bootloader.TCD0CFG},{bootloader.SYSCFG0},{bootloader.SYSCFG1},{bootloader.APPEND},{bootloader.BOOTEND}:m -Ulock:w:{bootloader.LOCKBIT}:m "-Uflash:w:{build.path}/{build.project_name}.hex:i" tools.avrdude.program.params.verbose=-v tools.avrdude.program.params.quiet=-q -q # tools.avrdude.program.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value tools.avrdude.program.verify= tools.avrdude.program.params.noverify=-V -tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" {bootloader.fuse0} {bootloader.fuse1} {bootloader.fuse2} {bootloader.fuse4} {bootloader.fuse5} {bootloader.fuse6} {bootloader.fuse7} {bootloader.fuse8} {bootloader.lock} +tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} -Ufuses:w:{bootloader.WDTCFG},{bootloader.BODCFG},{bootloader.OSCCFG},0xff,{bootloader.TCD0CFG},{bootloader.SYSCFG0},{bootloader.SYSCFG1},{bootloader.APPEND},{bootloader.BOOTEND}:m -Ulock:w:{bootloader.LOCKBIT}:m "-Uflash:w:{build.path}/{build.project_name}.with_bootloader.hex:i" tools.avrdude.erase.params.verbose=-v tools.avrdude.erase.params.quiet=-q -q -tools.avrdude.erase.pattern= - -tools.avrdude.bootloader.fuse0="-Ufuse0:w:{bootloader.WDTCFG}:m" -tools.avrdude.bootloader.fuse1="-Ufuse1:w:{bootloader.BODCFG}:m" -tools.avrdude.bootloader.fuse2="-Ufuse2:w:{bootloader.OSCCFG}:m" -tools.avrdude.bootloader.fuse4="-Ufuse4:w:{bootloader.TCD0CFG}:m" -tools.avrdude.bootloader.fuse5="-Ufuse5:w:{bootloader.SYSCFG0}:m" -tools.avrdude.bootloader.fuse6="-Ufuse6:w:{bootloader.SYSCFG1}:m" -tools.avrdude.bootloader.fuse7="-Ufuse7:w:{bootloader.APPEND}:m" -tools.avrdude.bootloader.fuse8="-Ufuse8:w:{bootloader.BOOTEND}:m" -tools.avrdude.bootloader.lock="-Ulock:w:{bootloader.LOCKBIT}:m" +tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" -p{build.mcu} -c{protocol} {program.extra_params} -e -Ufuses:w:{bootloader.WDTCFG},{bootloader.BODCFG},{bootloader.OSCCFG},0xff,{bootloader.TCD0CFG},{bootloader.SYSCFG0},{bootloader.SYSCFG1},{bootloader.APPEND},{bootloader.BOOTEND}:m -Ulock:w:{bootloader.LOCKBIT}:m tools.avrdude.bootloader.params.verbose=-v tools.avrdude.bootloader.params.quiet=-q -q -tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} {bootloader.fuse0} {bootloader.fuse1} {bootloader.fuse2} {bootloader.fuse4} {bootloader.fuse5} {bootloader.fuse6} {bootloader.fuse7} {bootloader.fuse8} {bootloader.lock} +tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} diff --git a/megaavr/programmers.txt b/megaavr/programmers.txt index f0c864d..cbc933e 100644 --- a/megaavr/programmers.txt +++ b/megaavr/programmers.txt @@ -1,20 +1,86 @@ -medbg.name=Atmel mEDBG (ATmega32u4) -medbg.communication=usb -medbg.protocol=xplainedmini_updi -medbg.program.protocol=xplainedmini_updi -medbg.program.tool=avrdude -medbg.program.extra_params=-Pusb - -nedbg.name=Atmel nEDBG (ATSAMD21E18) -nedbg.communication=usb -nedbg.protocol=curiosity_updi -nedbg.program.protocol=curiosity_updi -nedbg.program.tool=avrdude -nedbg.program.extra_params=-Pusb - -edbg.name=Atmel EDBG (AT32UC3A4256) -edbg.communication=usb -edbg.protocol=xplainedpro_updi -edbg.program.protocol=xplainedpro_updi -edbg.program.tool=avrdude -edbg.program.extra_params=-Pusb + +serialupdi_57600.name=SerialUPDI (57600 baud) +serialupdi_57600.communication=serial +serialupdi_57600.protocol=serialupdi +serialupdi_57600.program.tool=avrdude +serialupdi_57600.program.extra_params=-P{serial.port} -b57600 -xrtsdtr=high + +serialupdi_115200.name=SerialUPDI (115200 baud) +serialupdi_115200.communication=serial +serialupdi_115200.protocol=serialupdi +serialupdi_115200.program.tool=avrdude +serialupdi_115200.program.extra_params=-P{serial.port} -b115200 -xrtsdtr=high + +serialupdi_230400.name=SerialUPDI (230400 baud) +serialupdi_230400.communication=serial +serialupdi_230400.protocol=serialupdi +serialupdi_230400.program.tool=avrdude +serialupdi_230400.program.extra_params=-P{serial.port} -b230400 -xrtsdtr=high + +serialupdi_460800.name=SerialUPDI (460800 baud) +serialupdi_460800.communication=serial +serialupdi_460800.protocol=serialupdi +serialupdi_460800.program.tool=avrdude +serialupdi_460800.program.extra_params=-P{serial.port} -b460800 -xrtsdtr=high + +xplainedmini.name=microUPDI/Uno Wifi +xplainedmini.communication=usb +xplainedmini.protocol=xplainedmini_updi +xplainedmini.program.protocol=xplainedmini_updi +xplainedmini.program.tool=avrdude +xplainedmini.program.extra_params= + +jtag2updi.name=JTAG2UPDI +jtag2updi.communication=serial +jtag2updi.protocol=jtag2updi +jtag2updi.program.tool=avrdude +jtag2updi.program.extra_params=-P{serial.port} + +cusiositynano.name=Curiosity Nano +cusiositynano.communication=usb +cusiositynano.protocol=pkobn_updi +cusiositynano.program.protocol=pkobn_updi +cusiositynano.program.tool=avrdude +cusiositynano.program.extra_params= + +xplainedpro.name=Xplained Pro +xplainedpro.communication=usb +xplainedpro.protocol=xplainedpro_updi +xplainedpro.program.protocol=xplainedpro_updi +xplainedpro.program.tool=avrdude +xplainedpro.program.extra_params= + +pickit5_updi.name=PICkit5 UPDI +pickit5_updi.communication=usb +pickit5_updi.protocol=pickit5_updi +pickit5_updi.program.protocol=pickit5_updi +pickit5_updi.program.tool=avrdude +pickit5_updi.program.extra_params= + +pickit4_updi.name=PICkit4 UPDI +pickit4_updi.communication=usb +pickit4_updi.protocol=pickit4_updi +pickit4_updi.program.protocol=pickit4_updi +pickit4_updi.program.tool=avrdude +pickit4_updi.program.extra_params= + +snap_updi.name=MPLAB SNAP UPDI +snap_updi.communication=usb +snap_updi.protocol=snap_updi +snap_updi.program.protocol=snap_updi +snap_updi.program.tool=avrdude +snap_updi.program.extra_params= + +atmelice_updi.name=Atmel-ICE UPDI +atmelice_updi.communication=usb +atmelice_updi.protocol=atmelice_updi +atmelice_updi.program.protocol=atmelice_updi +atmelice_updi.program.tool=avrdude +atmelice_updi.program.extra_params= + +jtagice3_updi.name=JTAGICE3 UPDI +jtagice3_updi.communication=usb +jtagice3_updi.protocol=jtag3updi +jtagice3_updi.program.protocol=jtag3updi +jtagice3_updi.program.tool=avrdude +atmelice_updi.program.extra_params= \ No newline at end of file diff --git a/megaavr/scripts/create_disassembler_listing.sh b/megaavr/scripts/create_disassembler_listing.sh new file mode 100755 index 0000000..84e8b19 --- /dev/null +++ b/megaavr/scripts/create_disassembler_listing.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +objdumpCommand="$1" +options="$2" +objfile="$3" +outputFile="$4" + +"$objdumpCommand" $options "$objfile" > "$outputFile" diff --git a/megaavr/scripts/delete_merged_output.bat b/megaavr/scripts/delete_merged_output.bat new file mode 100644 index 0000000..c0af51a --- /dev/null +++ b/megaavr/scripts/delete_merged_output.bat @@ -0,0 +1,2 @@ +@echo off +if "%1" == "false" del "%2" diff --git a/megaavr/scripts/delete_merged_output.sh b/megaavr/scripts/delete_merged_output.sh new file mode 100755 index 0000000..c2cc493 --- /dev/null +++ b/megaavr/scripts/delete_merged_output.sh @@ -0,0 +1,4 @@ +#!/bin/bash +if [ "$1" == "false" ]; then + rm "$2" +fi diff --git a/megaavr/travis-ci/arduino-ci-script/.travis.yml b/megaavr/travis-ci/arduino-ci-script/.travis.yml new file mode 100644 index 0000000..8ecd7e5 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/.travis.yml @@ -0,0 +1,188 @@ +# This file is used to test the script with Travis CI + +# Although sudo is no longer required by arduino-ci-script since the 1.0.0 release, for some reason setting "sudo: false" causes the Travis CI build time to significantly increase so this setting is left as "sudo: required" +sudo: required + + +env: + global: + # The Arduino IDE will be installed at APPLICATION_FOLDER/arduino + - APPLICATION_FOLDER="${HOME}/arduino-ide" + - SKETCHBOOK_FOLDER="${HOME}/arduino-sketchbook" + + matrix: + # Test install_ide with no argument (using full version list). This would cause the Travis CI build to take much longer so I have it disabled + # - INSTALL_IDE_START_VERSION="" + # Test install_ide using full version list + - INSTALL_IDE_START_VERSION="all" VERBOSITY_LEVEL=0 VERBOSE_COMPILATION="false" + # Test install_ide using custom version list. Test the use of the special version names "oldest" and "newest" in a version list. Test use of "hourly" version name. + - INSTALL_IDE_START_VERSION='("oldest" "1.8.1" "1.8.2" "newest" "hourly")' VERBOSITY_LEVEL=1 VERBOSE_COMPILATION="true" + # Allowed to fail + # Test install_ide using single version + # test the failure behavior of install_package when a Boards Manager installation is attempted using an IDE version that doesn't support it. + - INSTALL_IDE_START_VERSION="1.6.3" VERBOSITY_LEVEL=2 VERBOSE_COMPILATION="false" + # Test install_ide using version range. Test the use of the special version names "oldest" and "newest" in a version range. + - INSTALL_IDE_START_VERSION="oldest" INSTALL_IDE_END_VERSION="newest" VERBOSITY_LEVEL=0 VERBOSE_COMPILATION="false" + + +matrix: + allow_failures: + # The expected behavior is failure because 1.6.3 doesn't support boards manager installation. + - env: INSTALL_IDE_START_VERSION="1.6.3" VERBOSITY_LEVEL=2 VERBOSE_COMPILATION="false" + + +addons: + apt: + sources: + - debian-sid + packages: + - shellcheck + + +before_install: + # Check for issues in the script + - bash -c 'shopt -s globstar; shellcheck arduino-ci-script.sh' + + # Check for trailing whitespace in all files in the repository + - "if grep --line-number --recursive --exclude-dir=.git '[[:blank:]]$' .; then echo 'Trailing whitespace found.'; false; fi" + # Check for tabs in all files in the repository + - "if grep --line-number --recursive --exclude-dir=.git $'\t' .; then echo 'Tab found.'; false; fi" + # Check if all files in the repository end in a newline (https://stackoverflow.com/a/25686825) + - find . -path ./.git -prune -o -type f -print0 | xargs -0 -L1 bash -c 'if test "$(tail --bytes=1 "$0")"; then echo "No new line at end of $0"; false; fi' + + - source "${TRAVIS_BUILD_DIR}/arduino-ci-script.sh" + + - set_script_verbosity "$VERBOSITY_LEVEL" + + - set_application_folder "$APPLICATION_FOLDER" + - set_sketchbook_folder "$SKETCHBOOK_FOLDER" + + # Check for board definition errors that don't affect compilation + - set_board_testing "true" + + # Check for library issues that don't affect compilation + - set_library_testing "true" + + - install_ide "$INSTALL_IDE_START_VERSION" "$INSTALL_IDE_END_VERSION" + + # Install hardware packages + # Test package install from this repository (can't do this because the repository isn't a hardware package) + # - install_package + # Test manual package install from compressed file download + - install_package "https://github.com/SpenceKonde/ATTinyCore/archive/master.zip" + # Test manual package install from Git repository clone + - install_package "https://github.com/MCUdude/MightyCore.git" + # Test manual package install from Git repository clone + - install_package "https://github.com/JChristensen/mighty-1284p.git" "v1.6.3" + + # Test library installation from repository (can't do this because there is no library in this repository) + # - install_library + # Test library install from .zip file. A non-GitHub library download must be used because GitHub appends -{branch name} or -{release version} to the .zip downloads and having a library folder installed whos name contains "-" causes arduino 1.5.6 or older to hang. + - install_library "https://bitbucket.org/teckel12/arduino-new-ping/downloads/NewPing_v1.8.zip" + # Test library install from .zip file with rename. If the rename doesn't work then any job verifying with Arduino IDE 1.5.6 or older will hang because GitHub changes the folder name to MPU9250-master, which is not a valid folder name on those IDE versions. + - install_library "https://github.com/brianc118/MPU9250/archive/master.zip" "MPU9250" + # Test library install from .zip file/folder that has a dot in the name + - install_library "https://github.com/arduino-libraries/CapacitiveSensor/archive/0.5.1.zip" + # Test library install from git repo + - install_library "https://github.com/sfrwmaker/WirelessOregonV2.git" + # Test library install from git repo with branch + - install_library "https://github.com/sde1000/NanodeUNIO.git" "master" + # Test library install from git repo with rename + - install_library "https://github.com/mikaelpatel/Arduino-Shell.git" "" "ArduinoShell" + # Test library install from git repo with branch and rename + - install_library "https://github.com/Avamander/max7456.git" "master" "max_7456" + # Test set_verbose_output_during_compilation. + - set_verbose_output_during_compilation "$VERBOSE_COMPILATION" + + # Boards Manager and Library Manager tests are done as late as possible to allow job 3 to do more thorough testing of script verbosity level 2 before the job fails + + # Test Boards Manager package install without URL. Test error handling of attempting to do a Boards Manager installation when the newest installed IDE version doesn't support it (should print a helpful error message and fail instead of hanging). + - install_package "arduino:sam" + # Test Boards Manager package install with URL + - install_package "MiniCore:avr" "https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json" + + # Test library install from Library Manager + - install_library "Pushetta:1.0.1" + + +script: + # Verify sketches: + # build_sketch arguments: sketch name, fqbn, IDE version, allow failure + # IDE version: Use "all" for IDE version argument to verify sketch with all versions of the Arduino IDE, use "newest" for IDE version argument to verify sketch with the newest version of the Arduino IDE + + # Installed package tests: + # Test board from hardware package installed via Boards Manager without URL + # Test build_sketch with "newest" special version name + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "arduino:sam:arduino_due_x_dbg" "false" "newest" + # Test board from hardware package installed with Boards Manager URL + # Test build_sketch with specific IDE version + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "MiniCore:avr:328:variant=modelP,BOD=2v7,LTO=Os,clock=16MHz_external" "false" "1.8.1" + # Test board from hardware package manually installed from compressed file download + # Test build_sketch with an IDE version list + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "ATTinyCore-master:avr:attinyx5:LTO=disable,TimerClockSource=default,chip=85,clock=8internal,bod=disable" "false" '("1.8.1" "1.8.2")' + # Test board from hardware package manually installed by cloning Git repository + # Test build_sketch with an IDE version range + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "MightyCore:avr:1284:pinout=standard,variant=modelP,BOD=2v7,LTO=Os,clock=16MHz_external" "false" "1.8.1" "1.8.2" + # Test board from hardware package manually installed by cloning Git repository with non-default branch + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "mighty-1284p:avr:avr_developers" "false" "newest" + + # Installed library tests: + # Test build_sketch without absolute path + # Test library installed from .zip with rename + - cd "${SKETCHBOOK_FOLDER}/libraries/MPU9250/examples/MPU9250/" + - build_sketch "MPU9250.ino" "arduino:avr:uno" "false" "newest" + # Test library installed from .zip with dot in the folder name + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/CapacitiveSensor-0.5.1/examples/CapacitiveSensorSketch/CapacitiveSensorSketch.pde" "arduino:avr:uno" "false" "newest" + # Test library installed from .zip + # Test build_sketch with "all" IDE version name + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/NewPing/examples/NewPingExample/NewPingExample.pde" "arduino:avr:uno" "false" "all" + # Test library installed from .git + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/WirelessOregonV2/examples/OregonReceiver/OregonReceiver.ino" "arduino:avr:uno" "false" "newest" + # Test library installed from .git with branch + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/NanodeUNIO/examples/NanodeUNIO_test/NanodeUNIO_test.pde" "arduino:avr:uno" "false" "newest" + # Test library installed from .git with rename + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/ArduinoShell/examples/ShellBlink/ShellBlink.ino" "arduino:avr:uno" "false" "newest" + # Test library installed from .git with branch and rename + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/max_7456/examples/HelloWorld/HelloWorld.ino" "arduino:avr:uno" "false" "newest" + # Test library installed from Library Manager + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/Pushetta/examples/simple_notification/simple_notification.ino" "arduino:avr:uno" "false" "newest" + + # build_sketch with version argument tests + # Test build_sketch with no IDE version argument (should use all installed IDE versions) + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "arduino:avr:uno" "false" + # Test build_sketch with "oldest" IDE version name + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "arduino:avr:uno" "false" "oldest" + # Test build_sketch allowed to fail (this will fail because WirelessOregonV2 is AVR specific) + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/WirelessOregonV2/examples/OregonReceiver/OregonReceiver.ino" "arduino:sam:arduino_due_x_dbg" "true" "newest" + + # build_sketch with folder argument tests: + # Test build_sketch with folder argument with specific IDE version + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" "1.8.1" + # Test build_sketch with folder argument with "oldest" IDE version name + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" "oldest" + # Test build_sketch with folder argument with "newest" IDE version name + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" "newest" + # Test build_sketch with folder argument with "all" IDE version name + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" "all" + # Test build_sketch with folder argument with no IDE version specified (should use all installed IDE versions) + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" + # Test build_sketch with folder argument with an IDE version list + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" '("1.8.1" "1.8.2")' + # Test build_sketch with folder argument with an IDE version range + - build_sketch "${APPLICATION_FOLDER}/arduino/examples/01.Basics" "arduino:avr:uno" "false" "1.8.1" "1.8.2" + # Test build_sketch with folder argument required to fail (this will fail because WirelessOregonV2 is AVR specific) + - build_sketch "${SKETCHBOOK_FOLDER}/libraries/WirelessOregonV2/examples" "arduino:sam:arduino_due_x_dbg" "require" "newest" + + - publish_report_to_gist "$REPORT_GITHUB_TOKEN" "$REPORT_GIST_URL" "true" + + - USER_NAME="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 1)" + - REPOSITORY_NAME="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 2)" + - publish_report_to_repository "$REPORT_GITHUB_TOKEN" "https://github.com/${USER_NAME}/CI-reports.git" "$REPOSITORY_NAME" "build_$(printf "%05d\n" "${TRAVIS_BUILD_NUMBER}")" "true" + + - display_report + + +notifications: + email: + on_success: always + on_failure: always diff --git a/megaavr/travis-ci/arduino-ci-script/LICENSE b/megaavr/travis-ci/arduino-ci-script/LICENSE new file mode 100755 index 0000000..56c77ec --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 per1234, Vitalii Tereshchuk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/megaavr/travis-ci/arduino-ci-script/README.md b/megaavr/travis-ci/arduino-ci-script/README.md new file mode 100755 index 0000000..09eb6db --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/README.md @@ -0,0 +1,266 @@ +arduino-ci-script +========== + +Bash script for continuous integration of [Arduino](http://www.arduino.cc/) projects. This is currently targeted for use with [Travis CI](http://travis-ci.org/) but it could be easily adapted to other purposes. + +[![Build Status](https://travis-ci.org/per1234/arduino-ci-script.svg?branch=master)](https://travis-ci.org/per1234/arduino-ci-script) + + +### Table of contents +- [Installation](#installation) +- [Usage](#usage) +- [Publishing job reports](#publishing-job-reports) +- [Troubleshooting](#troubleshooting) +- [Contributing](#contributing) + + +### Installation +The script can be used in multiple ways: + +#### Clone the latest release +Include the latest release of the script in your project by adding the following lines to your build configuration file: +```yaml + # Clone the script repository + - git clone --depth 1 https://github.com/per1234/arduino-ci-script.git "${HOME}/scripts" + - cd "${HOME}/scripts" + # Get new tags from the remote + - git fetch --tags + # Checkout the latest tag + - git checkout $(git describe --tags `git rev-list --tags --max-count=1`) + - source "${HOME}/scripts/arduino-ci-script.sh" +``` + +#### Local copy +If you're passing a token to the script's publish report functions then best security practices would be to use a static copy of the script so you can be sure of the commands the token is used with: +- Download the latest version of the script from https://github.com/per1234/arduino-ci-script/releases by clicking one of the **Source code** links. +- Unzip the downloaded file. +- Copy arduino-ci-script.sh to a convenient location. +- Include the script in your project by adding the following line to your build configuration file: +```yaml + - source arduino-ci-script.sh +``` +Be sure to check for new releases of the script so that you can benefit from the ongoing development work. You can receive notifications of releases by [watching the repository](https://github.com/per1234/arduino-ci-script/subscription). + + +### Usage +See https://github.com/per1234/WatchdogLog/blob/master/.travis.yml for an example of the script in use. + +Please configure your continuous integration system to make the minimum number of downloads and sketch verifications necessary to effectively test your code. This will prevent wasting Arduino and Travis CI's bandwidth and keep the build durations short. + +##### `set_script_verbosity SCRIPT_VERBOSITY_LEVEL` +Control the level of verbosity of the script's output in the Travis CI log. Verbose output can be helpful for debugging but in normal usage it makes the log hard to read and may cause the log to exceed Travis CI's maximum log size of 4 MB, which causes the job to be terminated. The default verbosity level is `0`. +- Parameter: **SCRIPT_VERBOSITY_LEVEL** - `0`, `1` or `2` (least to most verbosity). + +##### `set_application_folder APPLICATION_FOLDER` +- Parameter: **APPLICATION_FOLDER** - The folder to install the Arduino IDE (and Artistic Style if you use `check_code_formatting`) to. This should be set to `/usr/local/share` or a subfolder of that location. The folder will be created if it doesn't already exist. The Arduino IDE will be installed in the `arduino` subfolder. + +##### `set_sketchbook_folder SKETCHBOOK_FOLDER` +- Parameter: **SKETCHBOOK_FOLDER** - The folder to be set as the Arduino IDE's sketchbook folder. The folder will be created if it doesn't already exist. Libraries installed via `install_library` will be installed to the `libraries` subfolder. Non-Boards Manager hardware packages installed via `install_package` will be installed to the `hardware` subfolder. This setting is only supported by Arduino IDE 1.5.6 and newer. + +##### `set_board_testing BOARD_TESTING` +Turn on/off checking for problems with the board definition that generate a warning message during sketch verification but don't ordinarily cause it to fail, such as missing bootloader file. If this is turned on and a problem is detected the `build_sketch` command will return a non-zero exit status. This feature is off by default. +- Parameter: **BOARD_TESTING** - `true`/`false` + +##### `set_library_testing LIBRARY_TESTING` +Turn on/off checking for problems with libraries that generate a warning message during sketch verification but don't ordinarily cause it to fail, such as missing or invalid items in the library.properties file. If this is turned on and a problem is detected the `build_sketch` command will return a non-zero exit status. This feature is off by default. +- Parameter: **LIBRARY_TESTING** - `true`/`false` + +##### Special version names: + - `all`: Refers to all versions of the Arduino IDE (including the hourly build). In the context of `install_ide` this means all IDE versions compatible with the script (those that support the command line interface, 1.5.2 and newer). In the context of all other functions this means all IDE versions that were installed via `install_ide`. + - `oldest`: The oldest release version of the Arduino IDE. In the context of `install_ide` this is the oldest of the IDE versions compatible with the script (1.5.2, the first version to have a command line interface). In the context of build_sketch this means the oldest IDE version that was installed via `install_ide`. + - `newest`: In the context of `install_ide` this means the newest IDE release version. In the context of all other functions this means the newest IDE release version that was installed via `install_ide`. 'newest' will only match to the hourly build if that is the only version available. + - `hourly`: The hourly build of the Arduino IDE. Note that this IDE version is intended for beta testing only. + +##### `install_ide [IDEversionList]` +Install a list of Arduino IDE version(s). +- Parameter(optional): **IDEversionList** - A list of the versions of the Arduino IDE you want installed, in order from oldest to newest. e.g., `'("1.6.5-r5" "1.6.9" "1.8.2")'`. If no arguments are supplied all IDE versions will be installed. The script allows you to install all IDE versions with a command line interface (1.5.2 and newer) for the sake of being complete but I don't see a good reason for testing with the 1.5.x versions of the Arduino IDE. Please only install the IDE versions you actually need for your test to avoid wasting Arduino's bandwidth. This will also result in a shorter build duration. Installation of the IDE will be skipped if it's found to already be installed in the folder specified via the `set_application_folder` function so `install_ide` can also be used simply to inform the script which IDE versions are available. + +##### `install_ide startIDEversion [endIDEversion]` +Install a range of version(s) of the Arduino IDE. +- Parameter: **startIDEversion** - The oldest version of the Arduino IDE to install. +- Parameter(optional): **endIDEversion** - The newest version of the Arduino IDE to install. If this argument is omitted then only startIDEversion will be installed. + +##### `install_package` +"Manually" install the hardware package from the current repository. Packages are installed to `$SKETCHBOOK_FOLDER/hardware`. Assumes the hardware package is located in the root of the download or repository and has the correct folder structure. + +##### `install_package packageURL` +"Manually" install a hardware package downloaded as a compressed file. Packages are installed to `$SKETCHBOOK_FOLDER/hardware`. Assumes the hardware package is located in the root of the file and has the correct folder structure. +- Parameter: **packageURL** - The URL of the hardware package download. The scheme component of the URL (e.g., `http://`, `https://`) is required. + +##### `install_package packageURL [branchName]` +"Manually" install a hardware package by cloning from a Git repository. Packages are installed to `$SKETCHBOOK_FOLDER/hardware`. Assumes the hardware package is located in the root of the repository and has the correct folder structure. +- Parameter: **packageURL** - The URL of the Git repository. The scheme component of the URL (e.g., `http://`, `https://`) is required. The URL must end in `.git`. +- Parameter(optional): **branchName** - Branch of the repository to install. If this argument is not specified or is left blank the default branch will be used. + +##### `install_package packageID [packageURL]` +Install a hardware package using the Arduino IDE (Boards Manager). Only the **Arduino AVR Boards** package is included with the Arduino IDE installation. Packages are installed to `$HOME/.arduino15/packages`. You must call `install_ide` before this function. This feature is only available with Arduino IDE 1.6.4 and newer. +- Parameter: **packageID** - `package name:platform architecture[:version]`. If `version` is omitted the most recent version will be installed. e.g., `arduino:samd` will install the most recent version of **Arduino SAMD Boards**. +- Parameter(optional): **packageURL** - The URL of the Boards Manager JSON file for 3rd party hardware packages. This can be omitted for hardware packages that are included in the official Arduino JSON file (e.g., Arduino SAM Boards, Arduino SAMD Boards, Intel Curie Boards). + +##### `install_library` +Install the library from the current repository. Assumes the library is in the root of the repository. The library is installed to the `libraries` subfolder of the sketchbook folder. + +##### `install_library libraryName` +Install a library that is listed in the Arduino Library Manager index. The library is installed to the `libraries` subfolder of the sketchbook folder. You must call `install_ide` before this function. This feature is only available with Arduino IDE 1.6.4 and newer installed. +- Parameter: **libraryName** - The name of the library to install. You can specify a version separated from the name by a colon, e.g., "LiquidCrystal I2C:1.1.2". If no version is specified the most recent version will be installed. You can also specify comma-separated lists of library names. + +##### `install_library libraryURL [newFolderName]` +Download a library in a compressed file from a URL. The library is installed to the `libraries` subfolder of the sketchbook folder. +- Parameter: **libraryURL** - The URL of the library download or library name in the Arduino Library Manager. The scheme component of the URL (e.g., `http://`, `https://`) is required. The download file can be in any compressed file format. Assumes the library is located in the root of the file. +- Parameter(optional): **newFolderName** - Folder name to rename the installed library folder to. This can be useful if the default folder name of the downloaded file is problematic. The Arduino IDE gives include file preference when the filename matches the library folder name. GitHub's "Download ZIP" file is given the folder name `{repository name}-{branch name}`. Library folder names that contain `-` or `.` are not compatible with Arduino IDE 1.5.6 and older, arduino will hang if it's started with a library using an invalid folder name installed. + +##### `install_library libraryURL [branchName [newFolderName]]` +Install a library by cloning a Git repository. The library is installed to the `libraries` subfolder of the sketchbook folder. Assumes the library is located in the root of the repository. +- Parameter: **libraryURL** - The URL of the library download or library name in the Arduino Library Manager. The scheme component of the URL (e.g., `http://`, `https://`) is required. The URL must end in `.git`. +- Parameter(optional): **branchName** - Branch of the repository to install. If this argument is not specified or is left blank the default branch will be used. +- Parameter(optional): **newFolderName** - Folder name to rename the installed library folder to. This can be useful if the default folder name of the downloaded file is problematic. The Arduino IDE gives include file preference when the filename matches the library folder name. Library folder names that contain `-` or `.` are not compatible with Arduino IDE 1.5.6 and older, arduino will hang if it's started with a library using an invalid folder name installed. If the `newFolderName` argument is specified the `branchName` argument must also be specified. If you don't want to specify a branch then use `""` for the `branchName` argument. + +##### `set_verbose_output_during_compilation verboseOutputDuringCompilation` +Turn on/off `arduino` verbose output during compilation (same as the IDE's **File > Preferences > Show verbose output during: > compilation**). This will show all the commands `arduino` runs during the process rather than just the compiler output. This is usually not very useful output and only clutters up the log. This feature is off by default. +- Parameter: **verboseOutputDuringCompilation** - `true`/`false` + +##### `check_sketch_structure searchPath` +Check sketches to ensure they have the correct structure. +- Parameter: **searchPath** - Path containing sketches. The path will be searched recursively and all sketches found under it will be checked. + +##### `check_library_structure basePath [depth]` +Check libraries to ensure they have the correct structure. This will also run `check_sketch_structure` on all sketches bundled with the library. +- Parameter: **basePath** - Path containing a library. +- Parameter(optional): **depth** - Folder depth relative to `basePath` where the libraries are located. A depth of 0 will check the library located at `basePath`. The default value is 0. + +##### `check_library_properties searchPath [maximumSearchDepth]` +Check [library.properties](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format) library metadata files for errors. +- Parameter: **searchPath** - Path containing library.properties. +- Parameter(optional): **maximumSearchDepth** - The recursive search depth. A depth of 0 will only search `searchPath` and no subfolders. The default value is 0. + +##### `check_keywords_txt searchPath [maximumSearchDepth]` +Check [keywords.txt](https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords) files for errors. +- Parameter: **searchPath** - Path containing keywords.txt files. +- Parameter(optional): **maximumSearchDepth** - The recursive search depth. A depth of 0 will only search `searchPath` and no subfolders. The default value is 0. + +##### `check_library_manager_compliance libraryPath` +Make some additional checks for compliance with the requirements for adding a library to the [Library Manager index](https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ). This function should be used in combination with `check_library_structure` and `check_library_properties` to ensure full compliance with the requirements. +- Parameter: **libraryPath** - Path of the library to check. + +##### `check_code_formatting strictness excludedPathList targetPath` +Check code formatting for compliance with the Arduino code style. The [Artistic Style](http://astyle.sourceforge.net) formatter tool is used for this check. If it's not already installed, it will be installed to the `astyle` subfolder of the folder specified to `set_application_folder`. Note that in the Travis CI job logs, the `check_code_formatting` output is "folded" to make it easier to browse. You can click the triangle in the left margin of the command to unfold the output. +- Parameter: **strictness** - Determines how strict to be about code formatting compliance: 1 (least strict) - 3 (most strict). Each strictness level is based on the previous one, but with additional requirements. + - `1`: The Arduino IDE's auto format configuration. + - `2`: The configuration Arduino uses to format their example sketches. + - `3`: A custom configuration based on a study of the prevailing styles used in official Arduino code. +- Parameter: **excludedPathList** - A comma-separated list of paths to exclude from the check. +- Parameter: **targetPath** - The path to run the check on. All code files will be checked recursively. + +##### `build_sketch sketchPath boardID allowFail IDEversion` +##### `build_sketch sketchPath boardID allowFail [IDEversionList]` +##### `build_sketch sketchPath boardID allowFail startIDEversion endIDEversion` +Verify/compile sketch(es). `build_sketch` will echo the `arduino` exit status to the log, which is documented at https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#exit-status. Note that in the Travis CI job logs, the compilation output is "folded" to make it easier to browse. You can click the triangles in the left margin to unfold. +- Parameter: **sketchPath** - Path to a sketch or folder containing sketches. If a folder is specified it will be recursively searched and all sketches will be verified. +- Parameter: **boardID** - `package:arch:board[:parameters]` ID of the board to be compiled for. e.g., `arduino:avr:uno`. Board-specific parameters are only supported by Arduino IDE 1.5.5 and newer. +- Parameter: **allowFail** - `true`, `require`, or `false`. Allow the verification to fail without causing the CI build to fail. `require` will cause the build to fail if the sketch verification doesn't fail. +- Parameter: **IDEversion** - A single version of the Arduino IDE to use to verify the sketch. +- Parameter(optional): **IDEversionList** - A list of versions of the Arduino IDE to use to verify the sketch. e.g., `'("1.6.5-r5" "1.6.9" "1.8.2")'`. If no version list is provided all installed IDE versions will be used. +- Parameter: **startIDEversion** - The start (inclusive) of a range of versions of the Arduino IDE to use to verify the sketch. +- Parameter: **endIDEversion** - The end (inclusive) of a range of versions of the Arduino IDE to use to verify the sketch. + +##### `display_report` +Echo a tab separated report of all verification results to the log. The report is located in the `${HOME}/arduino-ci-script_report` folder and will be named according to the build number and job number. Note that Travis CI runs each build of the job in a separate virtual machine so if you have multiple jobs you will have multiple reports. The only way I have found to generate a single report for all tests is to run them as a single job. This means not setting multiple matrix environment variables in .travis.yml's `env` array. See: https://docs.travis-ci.com/user/environment-variables. The report consists of one line per verification: +- Build timestamp - Timestamp of the sketch verification in UTC. +- Build - The Travis CI build number. +- Job - Travis CI job number. +- Job URL - The URL of the Travis CI job log. +- Build Trigger - The cause of this Travis CI build. Possible values are `push`, `pull_request`, `api`, `cron`. +- Allow Job Failure - Whether the Travis CI configuration was set to allow the failure of this job without failing the build. See: https://docs.travis-ci.com/user/customizing-the-build/#Rows-that-are-Allowed-to-Fail. +- PR# - Pull request number (if build was triggered by a pull request). +- Branch - The branch of the repository that was built. +- Commit - Commit hash of the build. +- Commit range - The range of commits that were included in the push or pull request. +- Commit Message - First line of the commit message. +- Sketch filename +- Board ID +- IDE version +- Program Storage (bytes) - Program storage usage of the compiled sketch. +- Dynamic Memory (bytes) - Dynamic memory usage by global variables in the compiled sketch (not available for some boards). +- \# Warnings - Number of warnings reported by the compiler during the sketch compilation. +- Allow Failure - Whether the sketch verification was allowed to fail (set by the `allowFail` argument of `build_sketch`). +- Exit Status - Exit status returned by arduino after the sketch verification. +- \# Board Issues - The number of board issues detected. +- Board Issue - Short description of the last board issue detected. +- \# Library Issues - The number of library issues detected. Library issues are things that cause warnings in the sketch verification output that come from the IDE, rather than the compiler. +- Library Issue - Short description of the last library issue detected. + +##### `publish_report_to_repository REPORT_GITHUB_TOKEN repositoryURL reportBranch reportFolder doLinkComment` +Add the report to a repository. See the [instructions for publishing job reports](publishing-job-reports) for details. +- Parameter: **REPORT_GITHUB_TOKEN** - The hidden or encrypted environment variable containing the GitHub personal access token. +- Parameter: **repositoryURL** - The .git URL of the repository to publish the report to. This URL can be found by clicking the "Clone or download" button on the home page of the repository. The repository must already exist. +- Parameter: **reportBranch** - The branch to publish the report to. The branch must already exist. +- Parameter: **reportFolder** - The folder to publish the report to. The folder will be created if it doesn't exist. +- Parameter: **doLinkComment** - `true` or `false` Whether to comment on the GitHub thread of the commit that triggered the build with a link to the report. + +##### `publish_report_to_gist REPORT_GITHUB_TOKEN REPORT_GIST_URL doLinkComment` +Add the report to the report gist. See the [instructions for publishing job reports](publishing-job-reports) for details. +- Parameter: **REPORT_GITHUB_TOKEN** - The hidden or encrypted environment variable containing the GitHub personal access token. +- Parameter: **REPORT_GIST_URL** - The URL of the report gist. +- Parameter: **doLinkComment** - `true` or `false` Whether to comment on the GitHub thread of the commit that triggered the build with a link to the report. + + +### Publishing job reports +The script offers the option of publishing the job result reports to a repository or GitHub [gist](https://gist.github.com/) by using the `publish_report_to_repository` or `publish_report_to_gist` functions. This makes it easier to view the reports or to import them into a spreadsheet program. You also have the option of having the link to the reports automatically added in a comment to the commit that triggered the build. This requires some configuration, which is described in the instructions below. + +NOTE: For security reasons, reports for builds of pull requests from a fork of the repository can not be published. If the owner of that fork wants to publish reports they can create a GitHub token (and gist if using `publish_report_to_gist`) and configure the Travis CI settings for their fork of the repository following these instructions. + +#### Creating a GitHub personal access token +This is required for either publishing option. +1. Sign in to your GitHub account. +2. Click your avatar at the top right corner of GitHub > **Settings** > **Developer settings** > **Personal access tokens** > **Generate new token**. +3. Check the appropriate permissions for the token: + 1. If using `publish_report_to_gist` check **gist**. + 2. If using `publish_report_to_repository` or setting the `doLinkComment` argument of `publish_report_to_gist` check **public_repo** (for public repositories only) or **repo** (for private and public repositories). +5. Click the **Generate token** button. +6. When the generated token is displayed click the clipboard icon next to it to copy the token. +7. Open the settings page for your repository on the Travis CI website. +8. In the **Environment Variables** section enter `REPORT_GITHUB_TOKEN` in the **Name** field and the token in the **Value** field. Make sure the **Display value in build log** switch is in the off position. +9. Click the **Add** button. + +An alternative to using a Travis CI hidden environment variable as described above is to define the GitHub personal access token as an encrypted environment variable: https://docs.travis-ci.com/user/environment-variables/#Encrypting-environment-variables. + +#### Creating a gist +This is required for use of the `publish_report_to_gist` function. +1. Open https://gist.github.com/ +2. Sign in to your GitHub account. +3. Type an appropriate name in the **Filename including extension...** field. Gists sort files alphabetically so the filename should be something that will sort before the report filenames, which start at travis_ci_job_report_00001.001.tsv. +4. Add some text to the file contents box. +5. Click **Create secret gist** if you don't want the gist to be discoverable (it can still be read by anyone who knows the URL), or **Create public gist** to make it discoverable. +6. Copy the URL of the gist. +7. Open the settings page for your repository on the Travis CI website. +8. In the **Environment Variables** section enter `REPORT_GIST_URL` in the **Name** field and the URL of the gist in the **Value** field. You can turn the **Display value in build log** switch to the on position. The gist URL is not secret and this will provide more information in the log. +9. Click the **Add** button. + + +### Troubleshooting +##### Script hangs after an arduino command +The Arduino IDE will usually try to start the GUI whenever there is an error in the command. Since the Travis CI build environment does not support this it will just hang for ten minutes until Travis CI automatically cancels the job. This means you get no useful information on the cause of the problem. + +##### Verbose output +Verbose output results in a harder to read log so you should leave it off or minimized when possible but it can be useful for troubleshooting. Note that turning on verbose output for a large build may cause the log to exceed 4 MB, which causes Travis CI to terminate the job. +- Verbose script output - See [`set_script_verbosity` documentation](set_script_verbosity-script_verbosity_level) in the Usage section. +- Verbose output during compilation - See [`set_verbose_output_during_compilation` documentation](set_verbose_output_during_compilation-verboseoutputduringcompilation) in the Usage section. +- Verbose output for Travis CI - Add one or both of the following lines to your `.travis.yml` file to get more details of the Travis CI build process. + - Print shell input lines as they are read: + - `- set -o verbose` + - Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before they are executed. The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments. + - `- set -o xtrace` + +##### Problematic IDE versions +Some older versions of the Arduino IDE have bugs or limitations that may cause problems if used with this script: +- 1.5.1 and older - The command line interface was added in 1.5.2, thus no version older than that can be used. +- 1.5.4 and older - Do not support board-specific parameters, set by custom **Tools** menu items. +- 1.5.5 and older - Do not support setting preferences (`--pref`), thus `set_sketchbook_folder` can not be used if no newer IDE version has been installed. +- 1.5.5-r2 and older - Don't recognize libraries that have a library.properties` file that doesn't define a `core-dependencies` property. The file include is successful but compilation of sketches that use the library functions will fail. +- 1.5.6 and older - `-` or `.` are not allowed in sketch or library folder names. If any are present the Arduino IDE will hang indefinitely when it's executed. +- 1.6.2 - Moves its hardware packages to the .arduino15 folder, causing all other IDE versions to use those cores, some of which are not compatible. For this reason 1.6.2 is not installed when a version range containing, but not starting or ending in, 1.6.2 is passed to `install_ide`. 1.6.2 is installed if it is explicitly specified in a version list. +- 1.6.3 and older - Do not support installing boards (`--install-boards`), thus `install_package` can't be used if no newer IDE version has been installed. + + +### Contributing +Pull requests or issue reports are welcome! Please see the [contribution rules](https://github.com/per1234/arduino-ci-script/blob/master/.github/CONTRIBUTING.md) for instructions. diff --git a/megaavr/travis-ci/arduino-ci-script/arduino-ci-script.sh b/megaavr/travis-ci/arduino-ci-script/arduino-ci-script.sh new file mode 100755 index 0000000..d96e545 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/arduino-ci-script.sh @@ -0,0 +1,2500 @@ +#!/bin/bash +# This script is used to automate continuous integration tasks for Arduino projects +# https://github.com/per1234/arduino-ci-script + +# Based on https://github.com/adafruit/travis-ci-arduino/blob/eeaeaf8fa253465d18785c2bb589e14ea9893f9f/install.sh#L11 +# It seems that arrays can't been seen in other functions. So instead I'm setting $IDE_VERSIONS to a string that is the command to create the array +readonly ARDUINO_CI_SCRIPT_IDE_VERSION_LIST_ARRAY_DECLARATION="declare -a -r IDEversionListArray=" + +readonly ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER="${HOME}/temporary/arduino-ci-script" +readonly ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER="arduino" +readonly ARDUINO_CI_SCRIPT_VERIFICATION_OUTPUT_FILENAME="${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/verification_output.txt" +readonly ARDUINO_CI_SCRIPT_REPORT_FILENAME="travis_ci_job_report_$(printf '%05d\n' "${TRAVIS_BUILD_NUMBER}").$(printf '%03d\n' "$(echo "$TRAVIS_JOB_NUMBER" | cut -d'.' -f 2)").tsv" +readonly ARDUINO_CI_SCRIPT_REPORT_FOLDER="${HOME}/arduino-ci-script_report" +readonly ARDUINO_CI_SCRIPT_REPORT_FILE_PATH="${ARDUINO_CI_SCRIPT_REPORT_FOLDER}/${ARDUINO_CI_SCRIPT_REPORT_FILENAME}" +# The arduino manpage(https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#exit-status) documents a range of exit statuses. These exit statuses indicate success, invalid arduino command, or compilation failed due to legitimate code errors. arduino sometimes returns other exit statuses that may indicate problems that may go away after a retry. +readonly ARDUINO_CI_SCRIPT_HIGHEST_ACCEPTABLE_ARDUINO_EXIT_STATUS=4 +readonly ARDUINO_CI_SCRIPT_SKETCH_VERIFY_RETRIES=3 +readonly ARDUINO_CI_SCRIPT_REPORT_PUSH_RETRIES=10 + +readonly ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS=0 +readonly ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS=1 + +# Arduino IDE 1.8.2 and newer generates a ton of garbage output (appears to be something related to jmdns) that must be filtered for the log to be readable and to avoid exceeding the maximum log length +readonly ARDUINO_CI_SCRIPT_ARDUINO_OUTPUT_FILTER_REGEX='(^\[SocketListener\(travis-job-*|^ *[0-9][0-9]*: [0-9a-g][0-9a-g]*|^dns\[query,[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*:[0-9][0-9]*, length=[0-9][0-9]*, id=|^dns\[response,[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*:[0-9][0-9]*, length=[0-9][0-9]*, id=|^questions:$|\[DNSQuestion@|type: TYPE_IGNORE|^\.\]$|^\.\]\]$|^.\.\]$|^.\.\]\]$)' + +# Default value +ARDUINO_CI_SCRIPT_TOTAL_SKETCH_BUILD_FAILURE_COUNT=0 + +# Set the arduino command name according to OS (on Windows arduino_debug should be used) +if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]]; then + ARDUINO_CI_SCRIPT_ARDUINO_COMMAND="arduino_debug" +else + ARDUINO_CI_SCRIPT_ARDUINO_COMMAND="arduino" +fi + +# Create the folder if it doesn't exist +function create_folder() { + local -r folderName="$1" + if ! [[ -d "$folderName" ]]; then + # shellcheck disable=SC2086 + mkdir --parents $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "$folderName" + fi +} + +function set_script_verbosity() { + ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL="$1" + + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" == "true" ]]; then + ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL=1 + fi + + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -eq 1 ]]; then + ARDUINO_CI_SCRIPT_VERBOSITY_OPTION="--verbose" + ARDUINO_CI_SCRIPT_QUIET_OPTION="" + # Show stderr only + ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT="1>/dev/null" + elif [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -eq 2 ]]; then + ARDUINO_CI_SCRIPT_VERBOSITY_OPTION="--verbose" + ARDUINO_CI_SCRIPT_QUIET_OPTION="" + # Show stdout and stderr + ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT="" + else + ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL=0 + ARDUINO_CI_SCRIPT_VERBOSITY_OPTION="" + # cabextract only takes the short option name so this is more universally useful than --quiet + ARDUINO_CI_SCRIPT_QUIET_OPTION="-q" + # Don't show stderr or stdout + ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT="&>/dev/null" + fi + +} + +# Deprecated, use set_script_verbosity +function set_verbose_script_output() { + set_script_verbosity 1 +} + +# Deprecated, use set_script_verbosity +function set_more_verbose_script_output() { + set_script_verbosity 2 +} + +# Turn on verbosity based on the preferences set by set_script_verbosity +function enable_verbosity() { + # Store previous verbosity settings so they can be set back to their original values at the end of the function + shopt -q -o verbose + ARDUINO_CI_SCRIPT_PREVIOUS_VERBOSE_SETTING="$?" + + shopt -q -o xtrace + ARDUINO_CI_SCRIPT_PREVIOUS_XTRACE_SETTING="$?" + + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -gt 0 ]]; then + # "Print shell input lines as they are read." + # https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html + set -o verbose + fi + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -gt 1 ]]; then + # "Print a trace of simple commands, for commands, case commands, select commands, and arithmetic for commands and their arguments or associated word lists after they are expanded and before they are executed. The value of the PS4 variable is expanded and the resultant value is printed before the command and its expanded arguments." + # https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html + set -o xtrace + fi +} + +# Return verbosity settings to their previous values +function disable_verbosity() { + if [[ "$ARDUINO_CI_SCRIPT_PREVIOUS_VERBOSE_SETTING" == "0" ]]; then + set -o verbose + else + set +o verbose + fi + + if [[ "$ARDUINO_CI_SCRIPT_PREVIOUS_XTRACE_SETTING" == "0" ]]; then + set -o xtrace + else + set +o xtrace + fi +} + +# Verbosity and, in some cases, errexit must be disabled before an early return from a public function, this allows it to be done in a single line instead of two +function return_handler() { + local -r exitStatus="$1" + + # If exit status is success and errexit is enabled then it must be disabled before exiting the script because errexit must be disabled by default and only enabled in the functions that specifically require it. + # If exit status is not success then errexit should not be disabled, otherwise Travis CI won't fail the build even though the exit status was failure. + if [[ "$exitStatus" == "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]] && shopt -q -o errexit; then + set +o errexit + fi + + disable_verbosity + + return "$exitStatus" +} + +function set_application_folder() { + enable_verbosity + + ARDUINO_CI_SCRIPT_APPLICATION_FOLDER="$1" + + disable_verbosity +} + +function set_sketchbook_folder() { + enable_verbosity + + ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER="$1" + + # Create the sketchbook folder if it doesn't already exist + create_folder "$ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER" + + # Set sketchbook location preference if the IDE is already installed + if [[ "$INSTALLED_IDE_VERSION_LIST_ARRAY" != "" ]]; then + set_ide_preference "sketchbook.path=$ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER" + fi + + disable_verbosity +} + +# Deprecated +function set_parameters() { + set_application_folder "$1" + set_sketchbook_folder "$2" +} + +# Check for errors with the board definition that don't affect sketch verification +function set_board_testing() { + enable_verbosity + + ARDUINO_CI_SCRIPT_TEST_BOARD="$1" + + disable_verbosity +} + +# Check for errors with libraries that don't affect sketch verification +function set_library_testing() { + enable_verbosity + + ARDUINO_CI_SCRIPT_TEST_LIBRARY="$1" + + disable_verbosity +} + +# Install all specified versions of the Arduino IDE +function install_ide() { + enable_verbosity + + local -r startIDEversion="$1" + local -r endIDEversion="$2" + + # https://docs.travis-ci.com/user/customizing-the-build/#Implementing-Complex-Build-Steps + # set -o errexit will cause the script to exit as soon as any command returns a non-zero exit status. Without this the success of the function call is determined by the exit status of the last command in the function + set -o errexit + + if [[ "$ARDUINO_CI_SCRIPT_APPLICATION_FOLDER" == "" ]]; then + echo "ERROR: Application folder was not set. Please use the set_application_folder function to define the location of the application folder." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + # Generate an array declaration string containing a list all available Arduino IDE versions which support CLI + # Save the current folder + local -r previousFolder="$PWD" + cd "$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" + # Create empty local repo for the purpose of getting a list of tags in the arduino/Arduino repository + git init --quiet Arduino + cd Arduino + git remote add origin https://github.com/arduino/Arduino.git + if [[ "$startIDEversion" != "1.6.2" ]] && [[ "$startIDEversion" != "1.6.2" ]]; then + # See "Arduino IDE version blocklist" documentation below + local -r IDEversion162regex=--regex='refs/tags/1\.6\.2' + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -gt 0 ]]; then + echo "NOTE: Due to not playing nicely with other versions, Arduino IDE 1.6.2 will not be installed unless explicitly specified in the version arguments." + fi + fi + + # Arduino IDE tag blocklist: + # <1.5.2: no CLI (https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc#history) + # 1.5.4-r2: Not available for download + # 1.5.5-r2: Not available for download + # 1.5.7-macosx-java7: Not available for download + # 1.5.8-macosx-java7: Not available for download + # 1.6.2: has the nasty behavior of moving the included hardware cores to the .arduino15 folder, causing those versions to be used for all builds after Arduino IDE 1.6.2 is used. For that reason, 1.6.2 will only be installed if explicitly specified in the install_ide version arguments + # 1.6.5-r2: Not available for download + # 1.6.5-r3: Not available for download + # 1.6.5-r2: Not available for download + # 1.6.5-r3: Not available for download + # 1.8.11-ms-store-1: Not available for download + # 1.8.13-ms-store-1: Not available for download + local -r ARDUINO_CI_SCRIPT_FULL_IDE_VERSION_LIST_ARRAY="${ARDUINO_CI_SCRIPT_IDE_VERSION_LIST_ARRAY_DECLARATION}'(\"$(git ls-remote --quiet --tags --refs | grep --invert-match --regexp='refs/tags/1\.0' --regexp='refs/tags/1\.5$' --regexp='refs/tags/1\.5\.1$' --regexp='refs/tags/1\.5\.4-r2$' --regexp='refs/tags/1\.5\.5-r2$' --regexp='refs/tags/1\.5\.7-macosx-java7$' --regexp='refs/tags/1\.5\.8-macosx-java7$' ${IDEversion162regex} --regexp='refs/tags/1\.6\.5-r2$' --regexp='refs/tags/1\.6\.5-r3$' --regexp='refs/tags/.*-ms-store.*$' | grep --regexp='refs/tags/[0-9]\+\.[0-9]\+\.[0-9]\+\(\(-.*$\)\|$\)' | cut --delimiter='/' --fields=3 | sort --version-sort | sed ':a;N;$!ba;s/\n/\" \"/g')\")'" + cd .. + # Remove the temporary repo + rm Arduino --recursive --force + # Go back to the previous folder location + cd "$previousFolder" + + # Determine list of IDE versions to install + generate_ide_version_list_array "$ARDUINO_CI_SCRIPT_FULL_IDE_VERSION_LIST_ARRAY" "$startIDEversion" "$endIDEversion" + INSTALLED_IDE_VERSION_LIST_ARRAY="$ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY" + + # Set "$NEWEST_INSTALLED_IDE_VERSION" + determine_ide_version_extremes "$INSTALLED_IDE_VERSION_LIST_ARRAY" + NEWEST_INSTALLED_IDE_VERSION="$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" + + create_folder "$ARDUINO_CI_SCRIPT_APPLICATION_FOLDER" + + # This runs the command contained in the $INSTALLED_IDE_VERSION_LIST_ARRAY string, thus declaring the array locally as $IDEversionListArray. This must be done in any function that uses the array + # Dummy declaration to fix the "referenced but not assigned" warning. + local IDEversionListArray + eval "$INSTALLED_IDE_VERSION_LIST_ARRAY" + + # Determine whether any of the IDE versions to be installed require the creation of a virtual framebuffer (https://github.com/arduino/Arduino/blob/54264124b72eec40aaa22e327c16760f5e806c2a/build/shared/manpage.adoc#bugs) + # This is necessary in Arduino IDE 1.6.13 and older (https://github.com/arduino/Arduino/pull/5578) when running on a headless system + if [ -e /usr/bin/Xvfb ]; then + local -r virtualFramebufferRequiredRegex='^1\.[56]\.' + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + if [[ "$IDEversion" =~ $virtualFramebufferRequiredRegex ]]; then + # based on https://learn.adafruit.com/continuous-integration-arduino-and-you/testing-your-project + /sbin/start-stop-daemon --start $ARDUINO_CI_SCRIPT_QUIET_OPTION $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 + sleep 3 + export DISPLAY=:1.0 + break + fi + done + fi + + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + local IDEinstallFolder="$ARDUINO_CI_SCRIPT_APPLICATION_FOLDER/arduino-${IDEversion}" + + # Don't unnecessarily install the IDE + if ! [[ -d "$IDEinstallFolder" ]]; then + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -eq 0 ]]; then + # If the download/installation process is going slowly when installing a lot of IDE versions this function may cause the build to fail due to exceeding Travis CI's 10 minutes without log output timeout so it's necessary to periodically print something. + echo "Installing: $IDEversion" + fi + + # Determine download file extension + local tgzExtensionVersionsRegex="^1\.5\.[0-9]$" + if [[ "$IDEversion" =~ $tgzExtensionVersionsRegex ]]; then + # The download file extension prior to 1.6.0 is .tgz + local downloadFileExtension="tgz" + else + local downloadFileExtension="tar.xz" + fi + + if [[ "$IDEversion" == "hourly" ]]; then + # Deal with the inaccurate name given to the hourly build download + local downloadVersion="nightly" + else + local downloadVersion="$IDEversion" + fi + + wget --no-verbose $ARDUINO_CI_SCRIPT_QUIET_OPTION --directory-prefix="${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/" "http://downloads.arduino.cc/arduino-${downloadVersion}-linux64.${downloadFileExtension}" + tar --extract --directory="$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" --file="${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/arduino-${downloadVersion}-linux64.${downloadFileExtension}" + rm $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/arduino-${downloadVersion}-linux64.${downloadFileExtension}" + mv $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/arduino-${downloadVersion}" "$IDEinstallFolder" + fi + done + + set_ide_preference "compiler.warning_level=all" + + # If a sketchbook location has been defined then set the location in the Arduino IDE preferences + if [[ -d "$ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER" ]]; then + set_ide_preference "sketchbook.path=$ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER" + fi + + # Return errexit to the default state + set +o errexit + + disable_verbosity +} + +# Generate an array of Arduino IDE versions as a subset of the list provided in the base array defined by the start and end versions +# This function allows the same code to be shared by install_ide and build_sketch. The generated array is "returned" as a global named "$ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY" +function generate_ide_version_list_array() { + local -r baseIDEversionArray="$1" + local startIDEversion="$2" + local endIDEversion="$3" + + # Convert "oldest" or "newest" to actual version numbers + determine_ide_version_extremes "$baseIDEversionArray" + if [[ "$startIDEversion" == "oldest" ]]; then + startIDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION" + elif [[ "$startIDEversion" == "newest" ]]; then + startIDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" + fi + + if [[ "$endIDEversion" == "oldest" ]]; then + endIDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION" + elif [[ "$endIDEversion" == "newest" ]]; then + endIDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" + fi + + if [[ "$startIDEversion" == "" || "$startIDEversion" == "all" ]]; then + # Use the full base array + ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY="$baseIDEversionArray" + + else + local rawIDElist + local -r IDEversionListRegex='\(' + if [[ "$startIDEversion" =~ $IDEversionListRegex ]]; then + # IDE versions list was supplied + # Convert it to a temporary array + local -r suppliedIDEversionListArray="${ARDUINO_CI_SCRIPT_IDE_VERSION_LIST_ARRAY_DECLARATION}${startIDEversion}" + eval "$suppliedIDEversionListArray" + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + # Convert any use of "oldest" or "newest" special version names to the actual version number + if [[ "$IDEversion" == "oldest" ]]; then + IDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION" + elif [[ "$IDEversion" == "newest" ]]; then + IDEversion="$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" + fi + # Add the version to the array + rawIDElist="${rawIDElist} "'"'"$IDEversion"'"' + done + + elif [[ "$endIDEversion" == "" ]]; then + # Only a single version was specified + rawIDElist="$rawIDElist"'"'"$startIDEversion"'"' + + else + # A version range was specified + eval "$baseIDEversionArray" + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + if [[ "$IDEversion" == "$startIDEversion" ]]; then + # Start of the list reached, set a flag + local -r listIsStarted="true" + fi + + if [[ "$listIsStarted" == "true" ]]; then + # Add the version to the list + rawIDElist="${rawIDElist} "'"'"$IDEversion"'"' + fi + + if [[ "$IDEversion" == "$endIDEversion" ]]; then + # End of the list was reached, exit the loop + break + fi + done + fi + + # Turn the raw IDE version list into an array + declare -a -r rawIDElistArray="(${rawIDElist})" + + # Remove duplicates from list https://stackoverflow.com/a/13648438 + # shellcheck disable=SC2207 + readonly local uniqueIDElistArray=($(echo "${rawIDElistArray[@]}" | tr ' ' '\n' | sort --unique --version-sort | tr '\n' ' ')) + + # Generate ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY + ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY="$ARDUINO_CI_SCRIPT_IDE_VERSION_LIST_ARRAY_DECLARATION"'(' + for uniqueIDElistArrayIndex in "${!uniqueIDElistArray[@]}"; do + ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY="${ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY} "'"'"${uniqueIDElistArray[$uniqueIDElistArrayIndex]}"'"' + done + ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY="$ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY"')' + fi +} + +# Determine the oldest and newest (non-hourly unless hourly is the only version on the list) IDE version in the provided array +# The determined versions are "returned" by setting the global variables "$ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION" and "$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" +function determine_ide_version_extremes() { + local -r baseIDEversionArray="$1" + + # Reset the variables from any value they were assigned the last time the function was ran + ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION="" + ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION="" + + # Determine the oldest and newest (non-hourly) IDE version in the base array + eval "$baseIDEversionArray" + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + if [[ "$ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION" == "" ]]; then + ARDUINO_CI_SCRIPT_DETERMINED_OLDEST_IDE_VERSION="$IDEversion" + fi + if [[ "$ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION" == "" || "$IDEversion" != "hourly" ]]; then + ARDUINO_CI_SCRIPT_DETERMINED_NEWEST_IDE_VERSION="$IDEversion" + fi + done +} + +function set_ide_preference() { + local -r preferenceString="$1" + + # --pref option is only supported by Arduino IDE 1.5.6 and newer + local -r unsupportedPrefOptionVersionsRegex="^1\.5\.[0-5]$" + if ! [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedPrefOptionVersionsRegex ]]; then + install_ide_version "$NEWEST_INSTALLED_IDE_VERSION" + + # --save-prefs was added in Arduino IDE 1.5.8 + local -r unsupportedSavePrefsOptionVersionsRegex="^1\.5\.[6-7]$" + if ! [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedSavePrefsOptionVersionsRegex ]]; then + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --pref "$preferenceString" --save-prefs "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + else + # Arduino IDE 1.5.6 - 1.5.7 load the GUI if you only set preferences without doing a verify. So I am doing an unnecessary verification just to set the preferences in those versions. Definitely a hack but I prefer to keep the preferences setting code all here instead of cluttering build_sketch and this will pretty much never be used. + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --pref "$preferenceString" --verify "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/arduino/examples/01.Basics/BareMinimum/BareMinimum.ino" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + fi + fi +} + +function install_ide_version() { + local -r IDEversion="$1" + + # Create a symbolic link so that the Arduino IDE can always be referenced by the user from the same path no matter which version is being used. + if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]]; then + # git-bash's ln just does a copy instead of making a symlink, which takes forever and fails when the target folder exists (despite --force), which takes forever. + # Therefore, use the native Windows command mklink to create a directory junction instead. + # Using a directory junction instead of symlink because supposedly a symlink requires admin privileges. + + # Windows doesn't seem to provide any way to overwrite directory junctions + if [[ -d "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}" ]]; then + rm --recursive --force "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER:?}" + fi + # https://stackoverflow.com/a/25394801 + cmd <<<"mklink /J \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}\\${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}\" \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER//\//\\}\\arduino-${IDEversion}\"" >/dev/null + else + ln --symbolic --force --no-dereference $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/arduino-${IDEversion}" "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}" + fi +} + +# Install hardware packages +function install_package() { + enable_verbosity + + set -o errexit + + local -r URLregex="://" + if [[ "$1" =~ $URLregex ]]; then + # First argument is a URL, do a manual hardware package installation + # Note: Assumes the package is in the root of the download and has the correct folder structure (e.g. architecture folder added in Arduino IDE 1.5+) + + local -r packageURL="$1" + + # Create the hardware folder if it doesn't exist + create_folder "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware" + + if [[ "$packageURL" =~ \.git$ ]]; then + # Clone the repository + local -r branchName="$2" + + local -r previousFolder="$PWD" + cd "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware" + + if [[ "$branchName" == "" ]]; then + git clone --quiet "$packageURL" + else + git clone --quiet --branch "$branchName" "$packageURL" + fi + cd "$previousFolder" + else + local -r previousFolder="$PWD" + cd "$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" + + # Delete everything from the temporary folder + find ./ -mindepth 1 -delete + + # Download the package + wget --no-verbose $ARDUINO_CI_SCRIPT_QUIET_OPTION "$packageURL" + + # Uncompress the package + extract ./*.* + + # Delete all files from the temporary folder + find ./ -maxdepth 1 -type f -delete + + # Install the package + mv $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION ./* "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware/" + cd "$previousFolder" + fi + + elif [[ "$1" == "" ]]; then + # Install hardware package from this repository + # https://docs.travis-ci.com/user/environment-variables#Global-Variables + local packageName + packageName="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 2)" + mkdir --parents $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware/$packageName" + local -r previousFolder="$PWD" + cd "$TRAVIS_BUILD_DIR" + cp --recursive $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION ./* "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware/${packageName}" + # * doesn't copy .travis.yml but that file will be present in the user's installation so it should be there for the tests too + cp $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${TRAVIS_BUILD_DIR}/.travis.yml" "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/hardware/${packageName}" + cd "$previousFolder" + + else + # Install package via Boards Manager + + local -r packageID="$1" + local -r packageURL="$2" + + # Check if Arduino IDE is installed + if [[ "$INSTALLED_IDE_VERSION_LIST_ARRAY" == "" ]]; then + echo "ERROR: Installing a hardware package via Boards Manager requires the Arduino IDE to be installed. Please call install_ide before this command." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + # Check if the newest installed IDE version supports --install-boards + local -r unsupportedInstallBoardsOptionVersionsRange1regex="^1\.5\.[0-9]$" + local -r unsupportedInstallBoardsOptionVersionsRange2regex="^1\.6\.[0-3]$" + if [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedInstallBoardsOptionVersionsRange1regex ]] || [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedInstallBoardsOptionVersionsRange2regex ]]; then + echo "ERROR: --install-boards option is not supported by the newest version of the Arduino IDE you have installed. You must have Arduino IDE 1.6.4 or newer installed to use this function." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + else + # Temporarily install the latest IDE version to use for the package installation + install_ide_version "$NEWEST_INSTALLED_IDE_VERSION" + + # If defined add the boards manager URL to preferences + if [[ "$packageURL" != "" ]]; then + # Get the current Additional Boards Manager URLs preference value so it won't be overwritten when the new URL is added + local priorBoardsmanagerAdditionalURLs + local getPrefExitStatus + # arduino --get-pref returns 4 when the preference does not exist, which is an acceptable circumstance. So it's necessary to unset errexit + set +o errexit + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -eq 0 ]]; then + priorBoardsmanagerAdditionalURLs=$( + "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}" --get-pref boardsmanager.additional.urls 2>/dev/null | tail --lines=1 + exit "${PIPESTATUS[0]}" + ) + getPrefExitStatus="$?" + elif [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -eq 1 ]]; then + priorBoardsmanagerAdditionalURLs=$( + "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}" --get-pref boardsmanager.additional.urls | tail --lines=1 + exit "${PIPESTATUS[0]}" + ) + getPrefExitStatus="$?" + else + priorBoardsmanagerAdditionalURLs=$( + "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}" --get-pref boardsmanager.additional.urls | tee /dev/tty | tail --lines=1 + exit "${PIPESTATUS[0]}" + ) + getPrefExitStatus="$?" + fi + set -o errexit + + if [[ "$getPrefExitStatus" == "4" ]]; then + # No boardsmanager.additional.urls preference was set. This causes priorBoardsmanagerAdditionalURLs to have a garbage value with Arduino IDE 1.8.10 and newer. + priorBoardsmanagerAdditionalURLs="" + fi + + local -r blankregex="^[ ]*$" + if [[ "$priorBoardsmanagerAdditionalURLs" =~ $blankregex ]]; then + # There is no previous Additional Boards Manager URLs preference value + local boardsmanagerAdditionalURLs="$packageURL" + else + # There is a previous Additional Boards Manager URLs preference value so append the new one to the end of it + local boardsmanagerAdditionalURLs="${priorBoardsmanagerAdditionalURLs},${packageURL}" + fi + + # grep returns 1 when a line matches the regular expression so it's necessary to unset errexit + set +o errexit + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --pref boardsmanager.additional.urls="$boardsmanagerAdditionalURLs" --save-prefs "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" | tr --complement --delete '[:print:]\n\t' | tr --squeeze-repeats '\n' | grep --extended-regexp --invert-match "$ARDUINO_CI_SCRIPT_ARDUINO_OUTPUT_FILTER_REGEX" + local -r arduinoPreferenceSettingExitStatus="${PIPESTATUS[0]}" + set -o errexit + # this is required because otherwise the exit status of arduino is ignored + if [[ "$arduinoPreferenceSettingExitStatus" != "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]]; then + return_handler "$arduinoPreferenceSettingExitStatus" + fi + fi + + # Install the package + # grep returns 1 when a line matches the regular expression so it's necessary to unset errexit + set +o errexit + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --install-boards "$packageID" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" | tr --complement --delete '[:print:]\n\t' | tr --squeeze-repeats '\n' | grep --extended-regexp --invert-match "$ARDUINO_CI_SCRIPT_ARDUINO_OUTPUT_FILTER_REGEX" + local -r arduinoInstallPackageExitStatus="${PIPESTATUS[0]}" + set -o errexit + # this is required because otherwise the exit status of arduino is ignored + if [[ "$arduinoInstallPackageExitStatus" != "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]]; then + return_handler "$arduinoPreferenceSettingExitStatus" + fi + + fi + fi + + set +o errexit + + disable_verbosity +} + +function install_library() { + enable_verbosity + + set -o errexit + + local -r libraryIdentifier="$1" + + # Create the libraries folder if it doesn't already exist + create_folder "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries" + + local -r URLregex="://" + if [[ "$libraryIdentifier" =~ $URLregex ]]; then + # The argument is a URL + # Note: this assumes the library is in the root of the file + if [[ "$libraryIdentifier" =~ \.git$ ]]; then + # Clone the repository + local -r branchName="$2" + local -r newFolderName="$3" + + local -r previousFolder="$PWD" + cd "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries" + + if [[ "$branchName" == "" && "$newFolderName" == "" ]]; then + git clone --quiet "$libraryIdentifier" + elif [[ "$branchName" == "" ]]; then + git clone --quiet "$libraryIdentifier" "$newFolderName" + elif [[ "$newFolderName" == "" ]]; then + git clone --quiet --branch "$branchName" "$libraryIdentifier" + else + git clone --quiet --branch "$branchName" "$libraryIdentifier" "$newFolderName" + fi + cd "$previousFolder" + else + # Assume it's a compressed file + local -r newFolderName="$2" + # Download the file to the temporary folder + local -r previousFolder="$PWD" + cd "$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" + + # Delete everything from the temporary folder + find ./ -mindepth 1 -delete + + wget --no-verbose $ARDUINO_CI_SCRIPT_QUIET_OPTION "$libraryIdentifier" + + extract ./*.* + + # Delete all files from the temporary folder + find ./ -maxdepth 1 -type f -delete + + # Install the library + mv $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION ./* "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries/${newFolderName}" + cd "$previousFolder" + fi + + elif [[ "$libraryIdentifier" == "" ]]; then + # Install library from the repository + # https://docs.travis-ci.com/user/environment-variables#Global-Variables + local libraryName + libraryName="$(echo "$TRAVIS_REPO_SLUG" | cut -d'/' -f 2)" + mkdir --parents $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries/$libraryName" + local -r previousFolder="$PWD" + cd "$TRAVIS_BUILD_DIR" + cp --recursive $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION ./* "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries/${libraryName}" + # * doesn't copy .travis.yml but that file will be present in the user's installation so it should be there for the tests too + cp $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${TRAVIS_BUILD_DIR}/.travis.yml" "${ARDUINO_CI_SCRIPT_SKETCHBOOK_FOLDER}/libraries/${libraryName}" + cd "$previousFolder" + + else + # Install a library that is part of the Library Manager index + + # Check if Arduino IDE is installed + if [[ "$INSTALLED_IDE_VERSION_LIST_ARRAY" == "" ]]; then + echo "ERROR: Installing a library via Library Manager requires the Arduino IDE to be installed. Please call install_ide before this command." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + # Check if the newest installed IDE version supports --install-library + local -r unsupportedInstallLibraryOptionVersionsRange1regex="^1\.5\.[0-9]$" + local -r unsupportedInstallLibraryOptionVersionsRange2regex="^1\.6\.[0-3]$" + if [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedInstallLibraryOptionVersionsRange1regex ]] || [[ "$NEWEST_INSTALLED_IDE_VERSION" =~ $unsupportedInstallLibraryOptionVersionsRange2regex ]]; then + echo "ERROR: --install-library option is not supported by the newest version of the Arduino IDE you have installed. You must have Arduino IDE 1.6.4 or newer installed to use this function." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + else + local -r libraryName="$1" + + # Temporarily install the latest IDE version to use for the library installation + install_ide_version "$NEWEST_INSTALLED_IDE_VERSION" + + # Install the library + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --install-library "$libraryName" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + + fi + fi + + set +o errexit + + disable_verbosity +} + +# Extract common file formats +# https://github.com/xvoland/Extract +function extract() { + if [ -z "$1" ]; then + # display usage if no parameters given + echo "Usage: extract ." + echo " extract [path/file_name_2.ext] [path/file_name_3.ext]" + return "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + else + local filename + for filename in "$@"; do + if [ -f "$filename" ]; then + case "${filename%,}" in + *.tar.bz2 | *.tar.gz | *.tar.xz | *.tbz2 | *.tgz | *.txz | *.tar) + tar --extract --file="$filename" + ;; + *.lzma) + unlzma $ARDUINO_CI_SCRIPT_QUIET_OPTION ./"$filename" + ;; + *.bz2) + bunzip2 $ARDUINO_CI_SCRIPT_QUIET_OPTION ./"$filename" + ;; + *.rar) + eval unrar x -ad ./"$filename" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + ;; + *.gz) + gunzip ./"$filename" + ;; + *.zip) + unzip -qq ./"$filename" + ;; + *.z) + eval uncompress ./"$filename" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + ;; + *.7z | *.arj | *.cab | *.chm | *.deb | *.dmg | *.iso | *.lzh | *.msi | *.rpm | *.udf | *.wim | *.xar) + 7z x ./"$filename" + ;; + *.xz) + unxz $ARDUINO_CI_SCRIPT_QUIET_OPTION ./"$filename" + ;; + *.exe) + cabextract $ARDUINO_CI_SCRIPT_QUIET_OPTION ./"$filename" + ;; + *) + echo "extract: '$filename' - unknown archive method" + return "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + ;; + esac + else + echo "extract: '$filename' - file does not exist" + return "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + done + fi +} + +function set_verbose_output_during_compilation() { + enable_verbosity + + local -r verboseOutputDuringCompilation="$1" + if [[ "$verboseOutputDuringCompilation" == "true" ]]; then + ARDUINO_CI_SCRIPT_DETERMINED_VERBOSE_BUILD="--verbose" + else + ARDUINO_CI_SCRIPT_DETERMINED_VERBOSE_BUILD="" + fi + + disable_verbosity +} + +# Verify the sketch +function build_sketch() { + enable_verbosity + + local -r sketchPath="$1" + local -r boardID="$2" + local -r allowFail="$3" + local -r startIDEversion="$4" + local -r endIDEversion="$5" + + # Set default value for buildSketchExitStatus + local buildSketchExitStatus="$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" + + generate_ide_version_list_array "$INSTALLED_IDE_VERSION_LIST_ARRAY" "$startIDEversion" "$endIDEversion" + + if [[ "$ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY" == "$ARDUINO_CI_SCRIPT_IDE_VERSION_LIST_ARRAY_DECLARATION"'()' ]]; then + echo "ERROR: The IDE version(s) specified are not installed" + buildSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + else + eval "$ARDUINO_CI_SCRIPT_GENERATED_IDE_VERSION_LIST_ARRAY" + local IDEversion + for IDEversion in "${IDEversionListArray[@]}"; do + # Install the IDE + # This must be done before searching for sketches in case the path specified is in the Arduino IDE installation folder + install_ide_version "$IDEversion" + + # The package_index files installed by some versions of the IDE (1.6.5, 1.6.5) can cause compilation to fail for other versions (1.6.5-r4, 1.6.5-r5). Attempting to install a dummy package ensures that the correct version of those files will be installed before the sketch verification. + # Check if the newest installed IDE version supports --install-boards + local unsupportedInstallBoardsOptionVersionsRange1regex="^1\.5\.[0-9]$" + local unsupportedInstallBoardsOptionVersionsRange2regex="^1\.6\.[0-3]$" + if ! [[ "$IDEversion" =~ $unsupportedInstallBoardsOptionVersionsRange1regex ]] && ! [[ "$IDEversion" =~ $unsupportedInstallBoardsOptionVersionsRange2regex ]]; then + # shellcheck disable=SC2086 + eval \"${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}\" --install-boards arduino:dummy "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + if [[ "$ARDUINO_CI_SCRIPT_VERBOSITY_LEVEL" -gt 1 ]]; then + # The warning is printed to stdout + echo "NOTE: The warning above \"Selected board is not available\" is caused intentionally and does not indicate a problem." + fi + fi + + if [[ "$sketchPath" =~ \.ino$ ]] || [[ "$sketchPath" =~ \.pde$ ]]; then + # A sketch was specified + if ! [[ -f "$sketchPath" ]]; then + echo "ERROR: Specified sketch: $sketchPath doesn't exist" + buildSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + elif ! build_this_sketch "$sketchPath" "$boardID" "$IDEversion" "$allowFail"; then + # build_this_sketch returned a non-zero exit status + buildSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + else + # Search for all sketches in the path and put them in an array + local sketchFound="false" + # https://github.com/koalaman/shellcheck/wiki/SC2207 + declare -a sketches + mapfile -t sketches < <(find "$sketchPath" -name "*.pde" -o -name "*.ino") + local sketchName + for sketchName in "${sketches[@]}"; do + # Only verify the sketch that matches the name of the sketch folder, otherwise it will cause redundant verifications for sketches that have multiple .ino files + local sketchFolder + sketchFolder="$(echo "$sketchName" | rev | cut -d'/' -f 2 | rev)" + local sketchNameWithoutPathWithExtension + sketchNameWithoutPathWithExtension="$(echo "$sketchName" | rev | cut -d'/' -f 1 | rev)" + local sketchNameWithoutPathWithoutExtension + sketchNameWithoutPathWithoutExtension="${sketchNameWithoutPathWithExtension%.*}" + if [[ "$sketchFolder" == "$sketchNameWithoutPathWithoutExtension" ]]; then + sketchFound="true" + if ! build_this_sketch "$sketchName" "$boardID" "$IDEversion" "$allowFail"; then + # build_this_sketch returned a non-zero exit status + buildSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + fi + done + + if [[ "$sketchFound" == "false" ]]; then + echo "ERROR: No valid sketches were found in the specified path" + buildSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + fi + done + fi + + disable_verbosity + + return $buildSketchExitStatus +} + +function build_this_sketch() { + # Fold this section of output in the Travis CI build log to make it easier to read + echo -e "travis_fold:start:build_sketch" + + local -r sketchName="$1" + local -r boardID="$2" + local -r IDEversion="$3" + local -r allowFail="$4" + + # Produce a useful label for the fold in the Travis log for this function call + echo "build_sketch $sketchName $boardID $allowFail $IDEversion" + + # Arduino IDE 1.8.0 and 1.8.1 fail to verify a sketch if the absolute path to it is not specified + # http://stackoverflow.com/a/3915420/7059512 + local absoluteSketchName + absoluteSketchName="$( + cd "$(dirname "$1")" + pwd + )/$(basename "$1")" + + # Define a dummy value for arduinoExitStatus so that the while loop will run at least once + local arduinoExitStatus=255 + # Retry the verification if arduino returns an exit status that indicates there may have been a temporary error not caused by a bug in the sketch or the arduino command + while [[ $arduinoExitStatus -gt $ARDUINO_CI_SCRIPT_HIGHEST_ACCEPTABLE_ARDUINO_EXIT_STATUS && $verifyCount -le $ARDUINO_CI_SCRIPT_SKETCH_VERIFY_RETRIES ]]; do + # Verify the sketch + # shellcheck disable=SC2086 + "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/${ARDUINO_CI_SCRIPT_ARDUINO_COMMAND}" $ARDUINO_CI_SCRIPT_DETERMINED_VERBOSE_BUILD --verify "$absoluteSketchName" --board "$boardID" 2>&1 | tr --complement --delete '[:print:]\n\t' | tr --squeeze-repeats '\n' | grep --extended-regexp --invert-match "$ARDUINO_CI_SCRIPT_ARDUINO_OUTPUT_FILTER_REGEX" | tee "$ARDUINO_CI_SCRIPT_VERIFICATION_OUTPUT_FILENAME" + local arduinoExitStatus="${PIPESTATUS[0]}" + local verifyCount=$((verifyCount + 1)) + done + + if [[ "$arduinoExitStatus" != "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]]; then + # Sketch verification failed + local buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + else + # Sketch verification succeeded + local buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" + + # Parse through the output from the sketch verification to count warnings and determine the compile size + local warningCount=0 + local boardIssueCount=0 + local libraryIssueCount=0 + while read -r outputFileLine; do + # Determine program storage memory usage + local programStorageRegex="Sketch uses ([0-9,]+) *" + if [[ "$outputFileLine" =~ $programStorageRegex ]] >/dev/null; then + local -r programStorageWithComma=${BASH_REMATCH[1]} + fi + + # Determine dynamic memory usage + local dynamicMemoryRegex="Global variables use ([0-9,]+) *" + if [[ "$outputFileLine" =~ $dynamicMemoryRegex ]] >/dev/null; then + local -r dynamicMemoryWithComma=${BASH_REMATCH[1]} + fi + + # Increment warning count + local warningRegex="warning: " + if [[ "$outputFileLine" =~ $warningRegex ]] >/dev/null; then + warningCount=$((warningCount + 1)) + fi + + # Check for board issues + local bootloaderMissingRegex="Bootloader file specified but missing: " + if [[ "$outputFileLine" =~ $bootloaderMissingRegex ]] >/dev/null; then + local boardIssue="missing bootloader" + boardIssueCount=$((boardIssueCount + 1)) + fi + + local boardsDotTxtMissingRegex="Could not find boards.txt" + if [[ "$outputFileLine" =~ $boardsDotTxtMissingRegex ]] >/dev/null; then + local boardIssue="Could not find boards.txt" + boardIssueCount=$((boardIssueCount + 1)) + fi + + local buildDotBoardNotDefinedRegex="doesn't define a 'build.board' preference" + if [[ "$outputFileLine" =~ $buildDotBoardNotDefinedRegex ]] >/dev/null; then + local boardIssue="doesn't define a 'build.board' preference" + boardIssueCount=$((boardIssueCount + 1)) + fi + + # Check for library issues + # This is the generic "invalid library" warning that doesn't specify the reason + local invalidLibrarRegex1="Invalid library found in" + local invalidLibrarRegex2="from library$" + if [[ "$outputFileLine" =~ $invalidLibrarRegex1 ]] && ! [[ "$outputFileLine" =~ $invalidLibrarRegex2 ]] >/dev/null; then + local libraryIssue="Invalid library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingNameRegex="Invalid library found in .* Missing 'name' from library" + if [[ "$outputFileLine" =~ $missingNameRegex ]] >/dev/null; then + local libraryIssue="Missing 'name' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingVersionRegex="Invalid library found in .* Missing 'version' from library" + if [[ "$outputFileLine" =~ $missingVersionRegex ]] >/dev/null; then + local libraryIssue="Missing 'version' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingAuthorRegex="Invalid library found in .* Missing 'author' from library" + if [[ "$outputFileLine" =~ $missingAuthorRegex ]] >/dev/null; then + local libraryIssue="Missing 'author' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingMaintainerRegex="Invalid library found in .* Missing 'maintainer' from library" + if [[ "$outputFileLine" =~ $missingMaintainerRegex ]] >/dev/null; then + local libraryIssue="Missing 'maintainer' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingSentenceRegex="Invalid library found in .* Missing 'sentence' from library" + if [[ "$outputFileLine" =~ $missingSentenceRegex ]] >/dev/null; then + local libraryIssue="Missing 'sentence' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingParagraphRegex="Invalid library found in .* Missing 'paragraph' from library" + if [[ "$outputFileLine" =~ $missingParagraphRegex ]] >/dev/null; then + local libraryIssue="Missing 'paragraph' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local missingURLregex="Invalid library found in .* Missing 'url' from library" + if [[ "$outputFileLine" =~ $missingURLregex ]] >/dev/null; then + local libraryIssue="Missing 'url' from library" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local invalidVersionRegex="Invalid version found:" + if [[ "$outputFileLine" =~ $invalidVersionRegex ]] >/dev/null; then + local libraryIssue="Invalid version found:" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local invalidCategoryRegex="is not valid. Setting to 'Uncategorized'" + if [[ "$outputFileLine" =~ $invalidCategoryRegex ]] >/dev/null; then + local libraryIssue="Invalid category" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + local spuriousFolderRegex="WARNING: Spurious" + if [[ "$outputFileLine" =~ $spuriousFolderRegex ]] >/dev/null; then + local libraryIssue="Spurious folder" + libraryIssueCount=$((libraryIssueCount + 1)) + fi + + done <"$ARDUINO_CI_SCRIPT_VERIFICATION_OUTPUT_FILENAME" + + rm $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "$ARDUINO_CI_SCRIPT_VERIFICATION_OUTPUT_FILENAME" + + # Remove the stupid comma from the memory values if present + local -r programStorage=${programStorageWithComma//,/} + local -r dynamicMemory=${dynamicMemoryWithComma//,/} + + if [[ "$boardIssue" != "" && "$ARDUINO_CI_SCRIPT_TEST_BOARD" == "true" ]]; then + # There was a board issue and board testing is enabled so fail the build + local buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + if [[ "$libraryIssue" != "" && "$ARDUINO_CI_SCRIPT_TEST_LIBRARY" == "true" ]]; then + # There was a library issue and library testing is enabled so fail the build + local buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + fi + + # Add the build data to the report file + echo "$(date -u "+%Y-%m-%d %H:%M:%S")"$'\t'"$TRAVIS_BUILD_NUMBER"$'\t'"$TRAVIS_JOB_NUMBER"$'\t'"https://travis-ci.org/${TRAVIS_REPO_SLUG}/jobs/${TRAVIS_JOB_ID}"$'\t'"$TRAVIS_EVENT_TYPE"$'\t'"$TRAVIS_ALLOW_FAILURE"$'\t'"$TRAVIS_PULL_REQUEST"$'\t'"$TRAVIS_BRANCH"$'\t'"$TRAVIS_COMMIT"$'\t'"$TRAVIS_COMMIT_RANGE"$'\t'"${TRAVIS_COMMIT_MESSAGE%%$'\n'*}"$'\t'"$sketchName"$'\t'"$boardID"$'\t'"$IDEversion"$'\t'"$programStorage"$'\t'"$dynamicMemory"$'\t'"$warningCount"$'\t'"$allowFail"$'\t'"$arduinoExitStatus"$'\t'"$boardIssueCount"$'\t'"$boardIssue"$'\t'"$libraryIssueCount"$'\t'"$libraryIssue"$'\r' >>"$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" + + # Adjust the exit status according to the allowFail setting + if [[ "$buildThisSketchExitStatus" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" && ("$allowFail" == "true" || "$allowFail" == "require") ]]; then + buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" + elif [[ "$buildThisSketchExitStatus" == "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" && "$allowFail" == "require" ]]; then + buildThisSketchExitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + if [[ "$buildThisSketchExitStatus" != "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]]; then + ARDUINO_CI_SCRIPT_TOTAL_SKETCH_BUILD_FAILURE_COUNT=$((ARDUINO_CI_SCRIPT_TOTAL_SKETCH_BUILD_FAILURE_COUNT + 1)) + fi + ARDUINO_CI_SCRIPT_TOTAL_WARNING_COUNT=$((ARDUINO_CI_SCRIPT_TOTAL_WARNING_COUNT + warningCount + 0)) + ARDUINO_CI_SCRIPT_TOTAL_BOARD_ISSUE_COUNT=$((ARDUINO_CI_SCRIPT_TOTAL_BOARD_ISSUE_COUNT + boardIssueCount + 0)) + ARDUINO_CI_SCRIPT_TOTAL_LIBRARY_ISSUE_COUNT=$((ARDUINO_CI_SCRIPT_TOTAL_LIBRARY_ISSUE_COUNT + libraryIssueCount + 0)) + + # End the folded section of the Travis CI build log + echo -e "travis_fold:end:build_sketch" + # Add a useful message to the Travis CI build log + + echo "arduino Exit Status: ${arduinoExitStatus}, Allow Failure: ${allowFail}, # Warnings: ${warningCount}, # Board Issues: ${boardIssueCount}, # Library Issues: ${libraryIssueCount}" + + return $buildThisSketchExitStatus +} + +# Print the contents of the report file +function display_report() { + enable_verbosity + + if [ -e "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" ]; then + echo -e '\n\n\n**************Begin Report**************\n\n\n' + cat "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" + echo -e '\n\n' + echo "Total failed sketch builds: $ARDUINO_CI_SCRIPT_TOTAL_SKETCH_BUILD_FAILURE_COUNT" + echo "Total warnings: $ARDUINO_CI_SCRIPT_TOTAL_WARNING_COUNT" + echo "Total board issues: $ARDUINO_CI_SCRIPT_TOTAL_BOARD_ISSUE_COUNT" + echo "Total library issues: $ARDUINO_CI_SCRIPT_TOTAL_LIBRARY_ISSUE_COUNT" + echo -e '\n\n' + else + echo "No report file available for this job" + fi + + disable_verbosity +} + +# Add the report file to a Git repository +function publish_report_to_repository() { + enable_verbosity + + local -r token="$1" + local -r repositoryURL="$2" + local -r reportBranch="$3" + local -r reportFolder="$4" + local -r doLinkComment="$5" + + if [[ "$token" != "" ]] && [[ "$repositoryURL" != "" ]] && [[ "$reportBranch" != "" ]]; then + if [ -e "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" ]; then + # Location is a repository + if git clone --quiet --branch "$reportBranch" "$repositoryURL" "${HOME}/report-repository"; then + # Clone was successful + create_folder "${HOME}/report-repository/${reportFolder}" + cp $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" "${HOME}/report-repository/${reportFolder}" + local -r previousFolder="$PWD" + cd "${HOME}/report-repository" + git add $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "${HOME}/report-repository/${reportFolder}/${ARDUINO_CI_SCRIPT_REPORT_FILENAME}" + git config user.email "arduino-ci-script@nospam.me" + git config user.name "arduino-ci-script-bot" + # Only pushes the current branch to the corresponding remote branch that 'git pull' uses to update the current branch. + git config push.default simple + if [[ "$TRAVIS_TEST_RESULT" != "0" ]]; then + local -r jobSuccessMessage="FAILED" + else + local -r jobSuccessMessage="SUCCESSFUL" + fi + # Do a pull now in case another job has finished about the same time and pushed a report after the clone happened, which would otherwise cause the push to fail. This is the last chance to pull without having to deal with a merge or rebase. + git pull $ARDUINO_CI_SCRIPT_QUIET_OPTION + git commit $ARDUINO_CI_SCRIPT_QUIET_OPTION $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION --message="Add Travis CI job ${TRAVIS_JOB_NUMBER} report (${jobSuccessMessage})" --message="Total failed sketch builds: $ARDUINO_CI_SCRIPT_TOTAL_SKETCH_BUILD_FAILURE_COUNT" --message="Total warnings: $ARDUINO_CI_SCRIPT_TOTAL_WARNING_COUNT" --message="Total board issues: $ARDUINO_CI_SCRIPT_TOTAL_BOARD_ISSUE_COUNT" --message="Total library issues: $ARDUINO_CI_SCRIPT_TOTAL_LIBRARY_ISSUE_COUNT" --message="Job log: https://travis-ci.org/${TRAVIS_REPO_SLUG}/jobs/${TRAVIS_JOB_ID}" --message="Commit: https://github.com/${TRAVIS_REPO_SLUG}/commit/${TRAVIS_COMMIT}" --message="$TRAVIS_COMMIT_MESSAGE" --message="[skip ci]" + local gitPushExitStatus="1" + local pushCount=0 + while [[ "$gitPushExitStatus" != "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" && $pushCount -le $ARDUINO_CI_SCRIPT_REPORT_PUSH_RETRIES ]]; do + pushCount=$((pushCount + 1)) + # Do a pull now in case another job has finished about the same time and pushed a report since the last pull. This would require a merge or rebase. Rebase should be safe since the commits will be separate files. + git pull $ARDUINO_CI_SCRIPT_QUIET_OPTION --rebase + git push $ARDUINO_CI_SCRIPT_QUIET_OPTION $ARDUINO_CI_SCRIPT_VERBOSITY_OPTION "https://${token}@${repositoryURL#*//}" + gitPushExitStatus="$?" + done + cd "$previousFolder" + rm --recursive --force "${HOME}/report-repository" + if [[ "$gitPushExitStatus" == "$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" ]]; then + if [[ "$doLinkComment" == "true" ]]; then + # Only comment if it's job 1 + local -r firstJobRegex='\.1$' + if [[ "$TRAVIS_JOB_NUMBER" =~ $firstJobRegex ]]; then + local reportURL + reportURL="${repositoryURL%.*}/tree/${reportBranch}/${reportFolder}" + comment_report_link "$token" "$reportURL" + fi + fi + else + echo "ERROR: Failed to push to remote branch." + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + else + echo "ERROR: Failed to clone branch ${reportBranch} of repository URL ${repositoryURL}. Do they exist?" + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + else + echo "No report file available for this job" + fi + else + if [[ "$token" == "" ]]; then + echo "ERROR: GitHub token not specified. Failed to publish build report. See https://github.com/per1234/arduino-ci-script#publishing-job-reports for instructions." + fi + if [[ "$repositoryURL" == "" ]]; then + echo "ERROR: Repository URL not specified. Failed to publish build report." + fi + if [[ "$reportBranch" == "" ]]; then + echo "ERROR: Repository branch not specified. Failed to publish build report." + fi + return_handler "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + disable_verbosity +} + +# Add the report file to a gist +function publish_report_to_gist() { + enable_verbosity + + local -r token="$1" + local -r gistURL="$2" + local -r doLinkComment="$3" + + if [[ "$token" != "" ]] && [[ "$gistURL" != "" ]]; then + if [ -e "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" ]; then + # Get the gist ID from the gist URL + local gistID + gistID="$(echo "$gistURL" | rev | cut -d'/' -f 1 | rev)" + + # http://stackoverflow.com/a/33354920/7059512 + # Sanitize the report file content so it can be sent via a POST request without breaking the JSON + # Remove \r (from Windows end-of-lines), replace tabs by \t, replace " by \", replace EOL by \n + local reportContent + reportContent=$(sed -e 's/\r//' -e's/\t/\\t/g' -e 's/"/\\"/g' "$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" | awk '{ printf($0 "\\n") }') + + # Upload the report to the Gist. I have to use the here document to avoid the "Argument list too long" error from curl with long reports. Redirect output to dev/null because it dumps the whole gist to the log + eval curl --header "\"Authorization: token ${token}\"" --data @- "\"https://api.github.com/gists/${gistID}\"" "$ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" < Examples > INCOMPATIBLE." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_ARCHITECTURES_EMPTY_EXIT_STATUS) + else + # Check for invalid architectures + local validArchitecturesRegex='^((\*)|(ameba)|(arm)|(arc32)|(avr)|(efm32)|(esp32)|(esp8266)|(FP51)|(i586)|(i686)|(iot2000)|(mbed)|(megaavr)|(mraa)|(msp430)|(navspark)|(nRF5)|(nRF51822)|(nrf52)|(nRF52832)|(particle-photon)|(particle-electron)|(particle-core)|(pic)|(pic32)|(RFduino)|(sam)|(samd)|(samd_beta)|(Seeed_STM32F4)|(Simblee)|(solox)|(stm)|(STM32)|(stm32)|(STM32F1)|(STM32F2)|(STM32F3)|(STM32F4)|(stm32f4)|(STM32L1)|(STM32L4)|(teensy)|(win10)|(x86))$' + # Split string on , + IFS=',' + local validArchitectureFound=false + # Disable globbing, otherwise it fails when one of the architecture values is * + set -o noglob + # Check for * architecture. If this is found then the other architecture values don't matter + local wildcardArchitectureFound=false + for rawArchitecture in $architecturesValue; do + # The Arduino IDE ignores leading or trailing whitespace on architectures + # Strip leading whitespace + local architecture="${rawArchitecture#"${rawArchitecture%%[![:space:]]*}"}" + # Strip trailing whitespace + architecture="${architecture%"${architecture##*[![:space:]]}"}" + + if [[ "$architecture" == "*" ]]; then + wildcardArchitectureFound=true + validArchitectureFound=true + break + fi + done + if [[ "$wildcardArchitectureFound" == false ]]; then + for rawArchitecture in $architecturesValue; do + # The Arduino IDE ignores leading or trailing whitespace on architectures + # Strip leading whitespace + local architecture="${rawArchitecture#"${rawArchitecture%%[![:space:]]*}"}" + # Strip trailing whitespace + architecture="${architecture%"${architecture##*[![:space:]]}"}" + + if [[ "$architecture" =~ $validArchitecturesRegex ]]; then + validArchitectureFound=true + else + local aliasCheckPassed=true + # If an architecture alias is used then the correct architecture must also be present + check_architecture_alias "$architecture" '^((Avr)|(AVR)|([aA][tT][mM][eE][lL].?[aA][vV][rR]))$' "$architecturesValue" 'avr' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Sam)|(SAM))$' "$architecturesValue" 'sam' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Samd)|(SAMD)|(SamD)|((samD)|([aA][tT][mM][eE][lL].?[sS][aA][mM]))$' "$architecturesValue" 'samd' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Arc32)|(ARC32)|([aA][rR][cC].32)|([iI][nN][tT][eE][lL].?[aA][rR][cC]32))$' "$architecturesValue" 'arc32' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Esp8266)|(ESP8266)|([eE][sS][pP].8266)|(8266)|([eE][sS][pP])|([eE][sS][pP][rR][eE][sS][sS][iI][fF].?(8266)?))$' "$architecturesValue" 'esp8266' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Esp32)|(ESP32)|([eE][sS][pP].32)|(arduino-esp32)|([eE][sS][pP][rR][eE][sS][sS][iI][fF].?32))$' "$architecturesValue" 'esp32' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + check_architecture_alias "$architecture" '^((Teensy)|(TEENSY))$' "$architecturesValue" 'teensy' "$normalizedLibraryPropertiesPath" + if [[ "$?" == "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" ]]; then + aliasCheckPassed=false + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + + if [[ "$aliasCheckPassed" == true ]]; then + echo "WARNING: ${normalizedLibraryPropertiesPath}/library.properties: architectures field contains an unknown architecture: ${architecture}. Note: architecture values are case-sensitive." + fi + fi + done + fi + # Re-enable globbing + set +o noglob + # Set IFS back to default + unset IFS + + # At least one known architecture must be present + if [[ "$validArchitectureFound" == false ]]; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: architectures field (${architecturesValue}) doesn't contain any known architecture values." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_ARCHITECTURE_EXIT_STATUS) + fi + fi + fi + + # Check for invalid lines (anything other than property, comment, or blank line) + if grep --quiet --invert-match --extended-regexp --regexp='=' --regexp='^[[:space:]]*(#|$)' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Invalid line found. Installation of a library with invalid line will cause all compilations to fail. library.properties must only consist of property definitions, blank lines, and comments (#)." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INVALID_LINE_EXIT_STATUS) + fi + + # Check for incorrect includes field name case + if ! check_field_name_case "$libraryProperties" 'includes' "$normalizedLibraryPropertiesPath"; then + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INCLUDES_MISSPELLED_EXIT_STATUS) + fi + + # Check for misspelled includes field name + if grep --quiet --ignore-case --regexp='^[[:space:]]*include[[:space:]]*=' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Misspelled includes field name. It must be spelled exactly \"includes\". See https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_INCLUDES_MISSPELLED_EXIT_STATUS) + fi + + # Check for empty includes value + if grep --quiet --regexp='^[[:space:]]*includes[[:space:]]*=[[:space:]]*$' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Undefined includes field. Either define the field or remove it. See https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_EMPTY_INCLUDES_EXIT_STATUS) + fi + + # Check for incorrect dot_a_linkage field name case + if ! check_field_name_case "$libraryProperties" 'dot_a_linkage' "$normalizedLibraryPropertiesPath"; then + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_DOT_A_LINKAGE_MISSPELLED_EXIT_STATUS) + fi + + # Check for misspelled dot_a_linkage field name + if grep --quiet --ignore-case --extended-regexp --regexp='^[[:space:]]*((dot_a_linkages)|(dot-?a-?linkages?))[[:space:]]*=' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Misspelled dot_a_linkage field name. It must be spelled exactly \"dot_a_linkage\". See https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_DOT_A_LINKAGE_MISSPELLED_EXIT_STATUS) + fi + + # Check for incorrect precompiled field name case + if ! check_field_name_case "$libraryProperties" 'precompiled' "$normalizedLibraryPropertiesPath"; then + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_PRECOMPILED_MISSPELLED_EXIT_STATUS) + fi + + # Check for misspelled precompiled field name + if grep --quiet --ignore-case --extended-regexp --regexp='^[[:space:]]*((precompile)|(pre[-_]compiled?))[[:space:]]*=' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Misspelled precompiled field name. It must be spelled exactly \"precompiled\". See https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_PRECOMPILED_MISSPELLED_EXIT_STATUS) + fi + + # Check for incorrect ldflags field name case + if ! check_field_name_case "$libraryProperties" 'ldflags' "$normalizedLibraryPropertiesPath"; then + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_LDFLAGS_MISSPELLED_EXIT_STATUS) + fi + + # Check for misspelled ldflags field name + if grep --quiet --ignore-case --extended-regexp --regexp='^[[:space:]]*((ldflag)|(ld[-_]flags?))[[:space:]]*=' <<<"$libraryProperties"; then + echo "ERROR: ${normalizedLibraryPropertiesPath}/library.properties: Misspelled ldflags field name. It must be spelled exactly \"ldflags\". See https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_LDFLAGS_MISSPELLED_EXIT_STATUS) + fi + + done <<<"$(find "$normalizedLibraryPropertiesSearchPath" -maxdepth "$maximumSearchDepth" -type d | sort --dictionary-order)" + + return "$exitStatus" +} + +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keywords +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=1 +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCONSEQUENTIAL_MULTIPLE_TABS_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_LINE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCONSEQUENTIAL_LEADING_SPACE_ON_KEYWORD_TOKENTYPE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_MULTIPLE_TABS_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_LEADING_SPACE_ON_KEYWORD_TOKENTYPE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_FOLDER_DOESNT_EXIST_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_MISSPELLED_FILENAME_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCORRECT_FILENAME_CASE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_FIELD_SEPARATOR_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_BOM_CORRUPTED_KEYWORD_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_KEYWORD_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_KEYWORD_TOKENTYPE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_LEADING_SPACE_ON_RSYNTAXTEXTAREA_TOKENTYPE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_RSYNTAXTEXTAREA_TOKENTYPE_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_REFERENCE_LINK_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +function check_keywords_txt() { + local -r keywordsTxtSearchPath="$1" + local maximumSearchDepth="$2" + if [[ "$maximumSearchDepth" == "" ]]; then + # Set default search depth + maximumSearchDepth=0 + fi + + local exitStatus=$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS + + # Replace backslashes with slashes + local -r keywordsTxtSearchPathWithSlashes="${keywordsTxtSearchPath//\\//}" + local -r keywordsTxtRegex='[kK][eE][yY][wW][oO][rR][dD][sS]\.[tT][xX][tT]$' + if [[ ! -d "$keywordsTxtSearchPathWithSlashes" && "$keywordsTxtSearchPathWithSlashes" =~ $keywordsTxtRegex ]]; then + # Path contains the filename but we only want the folder + local -r keywordsTxtSearchPathWithoutFile="${keywordsTxtSearchPathWithSlashes::-12}" + else + local -r keywordsTxtSearchPathWithoutFile="$keywordsTxtSearchPathWithSlashes" + fi + # Remove trailing slash + local -r normalizedKeywordsTxtSearchPath="${keywordsTxtSearchPathWithoutFile%/}" + + # Check whether folder exists + if [[ ! -d "$normalizedKeywordsTxtSearchPath" ]]; then + echo "ERROR: ${normalizedKeywordsTxtSearchPath}: Folder doesn't exist." + return $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_FOLDER_DOESNT_EXIST_EXIT_STATUS + fi + + while read -r normalizedKeywordsTxtPath; do + # Check for misspelled keywords.txt filename + if [[ "$(find "$normalizedKeywordsTxtPath" -type f -iname 'keyword.txt')" || "$(find "$normalizedKeywordsTxtPath" -type f -iregex '.*/keywords?\.text')" || "$(find "$normalizedKeywordsTxtPath" -type f -iregex '.*/keywords?\.txt\.txt')" ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}: Incorrectly spelled keywords.txt file. It must be spelled exactly \"keywords.txt\"." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_MISSPELLED_FILENAME_EXIT_STATUS) + fi + + # Check for incorrect filename case + local keywordsTxtFound=false + while read -r foundKeywordsTxtPath; do + # The while loop always runs once, even if no file was found + if [[ "$foundKeywordsTxtPath" == "" ]]; then + continue + fi + + if [[ "${foundKeywordsTxtPath: -12}" == 'keywords.txt' ]]; then + keywordsTxtFound=true + else + echo "ERROR: ${foundKeywordsTxtPath}: Incorrect filename case, which causes it to not be recognized on a filename case-sensitive OS such as Linux. It must be exactly \"keywords.txt\"." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCORRECT_FILENAME_CASE_EXIT_STATUS) + fi + done <<<"$(find "$normalizedKeywordsTxtPath" -maxdepth 1 -type f -iname 'keywords.txt' | sort --dictionary-order)" + + # Check whether the folder contains a keywords.txt file + if [[ "$keywordsTxtFound" == false ]]; then + # no point in doing any more checks on this folder + continue + fi + + # Read the keywords.txt file line by line + # Split into lines by CR + while IFS='' read -d $'\r' -r keywordsTxtCRline || [[ -n "$keywordsTxtCRline" ]]; do + # Split into lines by LN + while IFS='' read -r keywordsTxtLine || [[ -n "$keywordsTxtLine" ]]; do + # Skip blank lines and comments + local blankLineRegex='^[[:space:]]*$' + local commentRegex='^[[:space:]]*#' + if [[ "$keywordsTxtLine" =~ $blankLineRegex ]] || [[ "$keywordsTxtLine" =~ $commentRegex ]]; then + continue + fi + + # Skip BOM corrupted blank lines and comments + if grep --quiet $'\xEF\xBB\xBF' <<<"$keywordsTxtLine"; then + local BOMcorruptedCommentRegex='^.[[:space:]]*#' + local BOMcorruptedBlankLineRegex='^.[[:space:]]*$' + if [[ "$keywordsTxtLine" =~ $BOMcorruptedCommentRegex ]] || [[ "$keywordsTxtLine" =~ $BOMcorruptedBlankLineRegex ]]; then + echo "WARNING: ${normalizedKeywordsTxtPath}/keywords.txt: BOM found. In this case it does not cause an issue but it's recommended to use UTF-8 encoding for keywords.txt." + continue + fi + fi + + local spacesSeparatorRegex='^[[:space:]]*[^[:space:]]+ +[^[:space:]]+' + # Check for invalid separator + if [[ "$keywordsTxtLine" =~ $spacesSeparatorRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Space(s) used as a field separator. Fields must be separated by a single true tab." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_FIELD_SEPARATOR_EXIT_STATUS) + # The rest of the checks will be borked by messed up field separators so continue to the next line + continue + fi + + # Check for multiple tabs used as separator where this causes unintended results + local consequentialMultipleSeparatorRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*'$'\t''+[[:space:]]*'$'\t''+[[:space:]]*((KEYWORD1)|(LITERAL1))' + if [[ "$keywordsTxtLine" =~ $consequentialMultipleSeparatorRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Multiple tabs used as field separator. It must be a single tab. This causes the default keyword highlighting (as used by KEYWORD2, KEYWORD3, LITERAL2) to be used rather than the intended highlighting." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_MULTIPLE_TABS_EXIT_STATUS) + # The rest of the checks will be borked by messed up field separators so continue to the next line + continue + fi + + # Check for multiple tabs used as separator where this causes no unintended results + local inconsequentialMultipleSeparatorRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*'$'\t''+[[:space:]]*'$'\t''+[[:space:]]*((KEYWORD2)|(KEYWORD3)|(LITERAL2))' + if [[ "$keywordsTxtLine" =~ $inconsequentialMultipleSeparatorRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Multiple tabs used as field separator. It must be a single tab. This causes the default keyword highlighting (as used by KEYWORD2, KEYWORD3, LITERAL2). In this case that doesn't cause the keywords to be colored other than intended but it's recommended to fully comply with the Arduino library specification." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCONSEQUENTIAL_MULTIPLE_TABS_EXIT_STATUS) + # The rest of the checks will be borked by messed up field separators so continue to the next line + continue + fi + + # Check for invalid line + local invalidLineRegex='^[[:space:]]*[^[:space:]]+[[:space:]]*$' + if [[ "$keywordsTxtLine" =~ $invalidLineRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Invalid line. If this was intended as a comment, it should use the correct # syntax." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_LINE_EXIT_STATUS) + # The rest of the checks are pointless so continue to the next line of keywords.txt + continue + fi + + # Get the field values + # Use a unique, non-whitespace field separator character + fieldSeparator=$'\a' + IFS=$fieldSeparator + # Strip leading whitespace. This is ignored by the Arduino IDE (even tabs) + local keywordsTxtLineFrontStripped="${keywordsTxtLine#"${keywordsTxtLine%%[![:space:]]*}"}" + # Change tabs to the field separator character for line splitting + # shellcheck disable=SC2206 + local keywordsTxtLineSwappedTabs=(${keywordsTxtLineFrontStripped//$'\t'/$fieldSeparator}) + + # KEYWORD is the 1st field + local keywordRaw=${keywordsTxtLineSwappedTabs[0]} + # Strip trailing spaces + local keyword="${keywordRaw%"${keywordRaw##*[! ]}"}" + + # KEYWORD_TOKENTYPE is the 2nd field + local keywordTokentypeRaw=${keywordsTxtLineSwappedTabs[1]} + # The Arduino IDE strips trailing spaces from KEYWORD_TOKENTYPE + # Strip trailing spaces + local keywordTokentype="${keywordTokentypeRaw%"${keywordTokentypeRaw##*[! ]}"}" + + # REFERENCE_LINK is the 3rd field + local referenceLinkRaw=${keywordsTxtLineSwappedTabs[2]} + # The Arduino IDE strips leading and trailing whitespace from REFERENCE_LINK + # Strip leading spaces + local referenceLinkFrontStripped="${referenceLinkRaw#"${referenceLinkRaw%%[! ]*}"}" + # Strip trailing spaces + local referenceLink="${referenceLinkFrontStripped%"${referenceLinkFrontStripped##*[! ]}"}" + + # RSYNTAXTEXTAREA_TOKENTYPE is the 4th field + local rsyntaxtextareaTokentypeRaw=${keywordsTxtLineSwappedTabs[3]} + # The Arduino IDE strips trailing spaces from RSYNTAXTEXTAREA_TOKENTYPE + # Strip trailing spaces + local rsyntaxtextareaTokentype="${rsyntaxtextareaTokentypeRaw%"${rsyntaxtextareaTokentypeRaw##*[! ]}"}" + + # Reset IFS to default + unset IFS + + allowedKeywordCharactersRegex='^[a-zA-Z0-9_]+$' + # Check for corruption of KEYWORD field caused by UTF-8 BOM file encoding + if grep --quiet $'\xEF\xBB\xBF' <<<"$keyword"; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: UTF-8 BOM file encoding has corrupted the first keyword definition. Please change the file encoding to standard UTF-8." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_BOM_CORRUPTED_KEYWORD_EXIT_STATUS) + elif ! [[ "$keyword" =~ $allowedKeywordCharactersRegex ]]; then + # Check for invalid characters in KEYWORD + # The Arduino IDE does recognize keywords that start with a number, even though these are not valid identifiers. + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Keyword: $keyword contains invalid character(s), which causes it to not be recognized by the Arduino IDE. Keywords may only contain the characters a-z, A-Z, 0-9, and _." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_KEYWORD_EXIT_STATUS) + fi + + # Check for invalid KEYWORD_TOKENTYPE + local validKeywordTokentypeRegex='^((KEYWORD1)|(KEYWORD2)|(KEYWORD3)|(LITERAL1)|(LITERAL2))$' + local validRsyntaxtextareaTokentypeRegex='^((RESERVED_WORD)|(RESERVED_WORD_2)|(DATA_TYPE)|(PREPROCESSOR)|(LITERAL_BOOLEAN))$' + if ! [[ "$keywordTokentype" =~ $validKeywordTokentypeRegex ]]; then + # Check if it's invalid only because of leading space + local keywordTokentypeWithoutLeadingSpace="${keywordTokentype#"${keywordTokentype%%[![:space:]]*}"}" + if [[ "$keywordTokentypeWithoutLeadingSpace" =~ $validKeywordTokentypeRegex ]]; then + # Check if the issue doesn't cause any change from the intended highlighting + local inconsequentialTokentypeRegex='((KEYWORD2)|(KEYWORD3)|(LITERAL2))' + if [[ "$keywordTokentypeWithoutLeadingSpace" =~ $inconsequentialTokentypeRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Leading space on the KEYWORD_TOKENTYPE field causes it to not be recognized, so the default keyword highlighting is used. In this case that doesn't cause the keywords to be colored other than intended but it's recommended to fully comply with the Arduino library specification." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INCONSEQUENTIAL_LEADING_SPACE_ON_KEYWORD_TOKENTYPE_EXIT_STATUS) + else + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Leading space on the KEYWORD_TOKENTYPE field causes it to not be recognized, so the default keyword highlighting is used." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_LEADING_SPACE_ON_KEYWORD_TOKENTYPE_EXIT_STATUS) + fi + elif ! [[ "$keywordTokentypeWithoutLeadingSpace" == "" && "$rsyntaxtextareaTokentype" =~ $validRsyntaxtextareaTokentypeRegex ]]; then + # It's reasonable to leave KEYWORD_TOKENTYPE blank if RSYNTAXTEXTAREA_TOKENTYPE is defined and valid. This will not be compatible with 1.6.4 and older but that's really no big deal. + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Invalid KEYWORD_TOKENTYPE: $keywordTokentype causes the default keyword highlighting to be used. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#keyword_tokentype" + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_KEYWORD_TOKENTYPE_EXIT_STATUS) + fi + fi + + # Check for invalid REFERENCE_LINK + if [[ "$referenceLink" != "" ]]; then + # The Arduino IDE must be installed to check if the reference page exists + if [[ "$NEWEST_INSTALLED_IDE_VERSION" == "" ]]; then + echo "WARNING: Arduino IDE is not installed so unable to check for invalid reference links. Please call install_ide before running check_keywords_txt." + else + install_ide_version "$NEWEST_INSTALLED_IDE_VERSION" + if [[ ! $(find "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/${ARDUINO_CI_SCRIPT_IDE_INSTALLATION_FOLDER}/reference/www.arduino.cc/en/Reference/" -type f -name "${referenceLink}.html") ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: REFERENCE_LINK value: $referenceLink is not a valid Arduino Language Reference page. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#reference_link" + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_REFERENCE_LINK_EXIT_STATUS) + fi + fi + fi + + # Check for invalid RSYNTAXTEXTAREA_TOKENTYPE + if [[ "$rsyntaxtextareaTokentype" != "" ]]; then + if ! [[ "$rsyntaxtextareaTokentype" =~ $validRsyntaxtextareaTokentypeRegex ]]; then + # Check if it's invalid only because of leading space + local rsyntaxtextareaTokentypeWithoutLeadingSpace="${rsyntaxtextareaTokentype#"${rsyntaxtextareaTokentype%%[![:space:]]*}"}" + if [[ "$rsyntaxtextareaTokentypeWithoutLeadingSpace" =~ $validRsyntaxtextareaTokentypeRegex ]]; then + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Leading space on the RSYNTAXTEXTAREA_TOKENTYPE field causes it to not be recognized, so the default keyword highlighting is used." + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_LEADING_SPACE_ON_RSYNTAXTEXTAREA_TOKENTYPE_EXIT_STATUS) + else + echo "ERROR: ${normalizedKeywordsTxtPath}/keywords.txt: Invalid RSYNTAXTEXTAREA_TOKENTYPE: $rsyntaxtextareaTokentype causes the default keyword highlighting to be used. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#rsyntaxtextarea_tokentype" + echo -e "\t$keywordsTxtLine" + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_KEYWORDS_TXT_INVALID_RSYNTAXTEXTAREA_TOKENTYPE_EXIT_STATUS) + fi + fi + fi + done <<<"$keywordsTxtCRline" + done <"${normalizedKeywordsTxtPath}/keywords.txt" + + done <<<"$(find "$normalizedKeywordsTxtSearchPath" -maxdepth "$maximumSearchDepth" -type d | sort --dictionary-order)" + + return "$exitStatus" +} + +# https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ#how-is-the-library-list-generated +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=1 +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_FOLDER_DOESNT_EXIST_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_EXE_FOUND_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_DOT_DEVELOPMENT_FOUND_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_SYMLINK_FOUND_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_CHECK_FOLDER_NAME_OFFSET=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_HAS_INVALID_FIRST_CHARACTER_EXIT_STATUS=$((ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_CHECK_FOLDER_NAME_OFFSET + ARDUINO_CI_SCRIPT_CHECK_FOLDER_NAME_INVALID_FIRST_CHARACTER_EXIT_STATUS)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_HAS_INVALID_CHARACTER_EXIT_STATUS=$((ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_CHECK_FOLDER_NAME_OFFSET + ARDUINO_CI_SCRIPT_CHECK_FOLDER_NAME_INVALID_CHARACTER_EXIT_STATUS)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_TOO_LONG_EXIT_STATUS=$((ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_CHECK_FOLDER_NAME_OFFSET + ARDUINO_CI_SCRIPT_CHECK_FOLDER_NAME_TOO_LONG_EXIT_STATUS)) +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_TOO_LONG_EXIT_STATUS + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_BLANK_URL_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER=$((ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER + 1)) +readonly ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_IS_RESERVED_EXIT_STATUS=$ARDUINO_CI_SCRIPT_EXIT_STATUS_COUNTER +function check_library_manager_compliance() { + local -r libraryPath="$1" + # Replace backslashes with slashes + local -r libraryPathWithSlashes="${libraryPath//\\//}" + # Remove trailing slash + local -r normalizedLibraryPath="${libraryPathWithSlashes%/}" + + local exitStatus=$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS + + # Check whether folder exists + if [[ ! -d "$normalizedLibraryPath" ]]; then + echo "ERROR: ${libraryPath}: Folder doesn't exist." + return $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_FOLDER_DOESNT_EXIST_EXIT_STATUS + fi + + # Check for .exe files + local -r exePath=$(find "$normalizedLibraryPath" -type f -name '*.exe') + if [[ "$exePath" != "" ]]; then + echo "ERROR: ${exePath}: .exe file found." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_EXE_FOUND_EXIT_STATUS) + fi + + # Check for .development file + local -r dotDevelopmentPath=$(find "$normalizedLibraryPath" -maxdepth 1 -type f -name '.development') + if [[ "$dotDevelopmentPath" != "" ]]; then + echo "ERROR: ${dotDevelopmentPath}: .development file found." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_DOT_DEVELOPMENT_FOUND_EXIT_STATUS) + fi + + # Check for symlink + local -r symlinkPath=$(find "$normalizedLibraryPath" -type l) + if [[ "$symlinkPath" != "" ]]; then + echo "ERROR: ${symlinkPath}: Symlink found." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_SYMLINK_FOUND_EXIT_STATUS) + fi + + # Check for problems with library.properties + if [[ -f "$normalizedLibraryPath/library.properties" ]]; then + # Get rid of the CRs + local libraryProperties + libraryProperties=$(tr "\r" "\n" <"$normalizedLibraryPath/library.properties") + local nameValue + nameValue="$(get_library_properties_field_value "$libraryProperties" 'name')" + + # Check if the library.properties name value meets the requirements of the Library Manager indexer + check_library_properties_name "$nameValue" + local -r checkLibraryPropertiesNameExitStatus=$? + if [[ $checkLibraryPropertiesNameExitStatus -ne $ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS ]]; then + if [[ "$checkLibraryPropertiesNameExitStatus" == "$ARDUINO_CI_SCRIPT_CHECK_LIBRARY_PROPERTIES_NAME_RESERVED_NAME_EXIT_STATUS" ]]; then + echo "ERROR: ${normalizedLibraryPath}/library.properties: name value: $nameValue starts with \"arduino\". These names are reserved for official Arduino libraries." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_NAME_IS_RESERVED_EXIT_STATUS) + else + echo "ERROR: ${normalizedLibraryPath}/library.properties: name value: $nameValue does not meet the requirements of the Arduino Library Manager indexer. See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5:-Library-specification#libraryproperties-file-format" + exitStatus=$(set_exit_status "$exitStatus" $((ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_CHECK_FOLDER_NAME_OFFSET + checkLibraryPropertiesNameExitStatus))) + fi + fi + + local urlValue + urlValue="$(get_library_properties_field_value "$libraryProperties" 'url')" + if [[ "$urlValue" == "" ]]; then + echo "ERROR: ${normalizedLibraryPath}/library.properties: Blank url value: You must define a URL." + exitStatus=$(set_exit_status "$exitStatus" $ARDUINO_CI_SCRIPT_CHECK_LIBRARY_MANAGER_COMPLIANCE_BLANK_URL_EXIT_STATUS) + fi + fi + + return "$exitStatus" +} + +function check_code_formatting() { + local -r strictness="$1" + local -r excludedPathList="$2" + local -r targetPath="$3" + + local -r astyleConfigurationFolder="etc/astyle-configurations" + local -r astyleConfigurationExtension=".conf" + + # Fold the output in the Travis CI log + echo -e -n 'travis_fold:start:check_code_formatting\r' + + if [[ $strictness -lt 1 ]] || [[ $strictness -gt 3 ]]; then + echo "ERROR: Invalid strictness parameter value. Valid values are 1 (least strict) - 3 (most strict)" + return "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + if ! [[ -d "$targetPath" ]]; then + echo "ERROR: targetPath doesn't exist" + return "$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + + local scriptFolder + # https://stackoverflow.com/a/246128 + local scriptSource="${BASH_SOURCE[0]}" + while [ -h "$scriptSource" ]; do # Resolve $scriptSource until the file is no longer a symlink + scriptFolder="$(cd -P "$(dirname "$scriptSource")" >/dev/null 2>&1 && pwd)" + scriptSource="$(readlink "$scriptSource")" + [[ $scriptSource != /* ]] && scriptSource="$scriptFolder/$scriptSource" # If $scriptSource was a relative symlink, we need to resolve it relative to the path where the symlink file was located + done + scriptFolder="$(cd -P "$(dirname "$scriptSource")" >/dev/null 2>&1 && pwd)" + + # Assemble the find options for the excluded paths from the list + for excludedPath in ${excludedPathList//,/ }; do + excludeOptions="$excludeOptions -path $excludedPath -prune -or" + done + + local astylePath + astylePath=$(command -v astyle) + if [[ ! -e "$astylePath" ]]; then + # Install astyle + # Save the current folder + local -r previousFolder="$PWD" + mkdir --parents "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/astyle" + wget --no-verbose $ARDUINO_CI_SCRIPT_QUIET_OPTION --output-document="${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/astyle.tar.gz" "https://iweb.dl.sourceforge.net/project/astyle/astyle/astyle%203.1/astyle_3.1_linux.tar.gz" + tar --extract --file="${ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER}/astyle.tar.gz" --directory="${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}" + cd "${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/astyle/build/gcc" + eval "make $ARDUINO_CI_SCRIPT_VERBOSITY_REDIRECT" + astylePath="${ARDUINO_CI_SCRIPT_APPLICATION_FOLDER}/astyle/build/gcc/bin/astyle" + # Return to the previous folder + cd "$previousFolder" + fi + + # Set default exit status + exitStatus="$ARDUINO_CI_SCRIPT_SUCCESS_EXIT_STATUS" + + while read -r filename; do + # Check if it's a file (find matches on pruned folders) + if [[ -f "$filename" ]]; then + if ! diff --strip-trailing-cr "$filename" <("${astylePath}" --options="${scriptFolder}/${astyleConfigurationFolder}/${strictness}${astyleConfigurationExtension}" --dry-run <"$filename"); then + echo "ERROR: Non-compliant code formatting in $filename" + # Make the function fail + exitStatus="$ARDUINO_CI_SCRIPT_FAILURE_EXIT_STATUS" + fi + fi + done <<<"$(eval "find $targetPath -regextype posix-extended $excludeOptions \( -iregex '.*\.((ino)|(h)|(hpp)|(hh)|(hxx)|(h\+\+)|(cpp)|(cc)|(cxx)|(c\+\+)|(cp)|(c)|(ipp)|(ii)|(ixx)|(inl)|(tpp)|(txx)|(tpl))$' -and -type f \)")" + + echo -e -n 'travis_fold:end:check_code_formatting\r' + return "$exitStatus" +} + +# Set default verbosity (must be called after the function definitions +set_script_verbosity 0 + +# Create the temporary folder +rm "$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" --recursive --force +create_folder "$ARDUINO_CI_SCRIPT_TEMPORARY_FOLDER" + +# Create the report folder +create_folder "$ARDUINO_CI_SCRIPT_REPORT_FOLDER" + +# Add column names to report +echo "Build Timestamp (UTC)"$'\t'"Build"$'\t'"Job"$'\t'"Job URL"$'\t'"Build Trigger"$'\t'"Allow Job Failure"$'\t'"PR#"$'\t'"Branch"$'\t'"Commit"$'\t'"Commit Range"$'\t'"Commit Message"$'\t'"Sketch Filename"$'\t'"Board ID"$'\t'"IDE Version"$'\t'"Program Storage (bytes)"$'\t'"Dynamic Memory (bytes)"$'\t'"# Warnings"$'\t'"Allow Failure"$'\t'"Exit Status"$'\t'"# Board Issues"$'\t'"Board Issue"$'\t'"# Library Issues"$'\t'"Library Issue"$'\r' >"$ARDUINO_CI_SCRIPT_REPORT_FILE_PATH" diff --git a/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/1.conf b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/1.conf new file mode 100755 index 0000000..fe9cf30 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/1.conf @@ -0,0 +1,33 @@ +# source: https://raw.githubusercontent.com/arduino/Arduino/1.8.9/build/shared/lib/formatter.conf + +# This configuration file contains a selection of the available options provided by the formatting tool "Artistic Style" +# http://astyle.sourceforge.net/astyle.html +# +# If you wish to change them, don't edit this file. +# Instead, copy it in the same folder of file "preferences.txt" and modify the copy. This way, you won't lose your custom formatter settings when upgrading the IDE +# If you don't know where file preferences.txt is stored, open the IDE, File -> Preferences and you'll find a link + +mode=c + +# 2 spaces indentation +indent=spaces=2 + +# also indent macros +indent-preprocessor + +# indent classes, switches (and cases), comments starting at column 1 +indent-classes +indent-switches +indent-cases +indent-col1-comments + +# put a space around operators +pad-oper + +# put a space after if/for/while +pad-header + +# if you like one-liners, keep them +keep-one-line-statements + +remove-comment-prefix diff --git a/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/2.conf b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/2.conf new file mode 100755 index 0000000..124f547 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/2.conf @@ -0,0 +1,46 @@ +# source: https://raw.githubusercontent.com/arduino/Arduino/1.8.9/build/shared/examples_formatter.conf + +# This configuration file contains a selection of the available options provided by the formatting tool "Artistic Style" +# http://astyle.sourceforge.net/astyle.html +# +# If you wish to change them, don't edit this file. +# Instead, copy it in the same folder of file "preferences.txt" and modify the copy. This way, you won't lose your custom formatter settings when upgrading the IDE +# If you don't know where file preferences.txt is stored, open the IDE, File -> Preferences and you'll find a link + +mode=c + +# 2 spaces indentation +indent=spaces=2 + +# also indent macros +indent-preprocessor + +# indent classes, switches (and cases), comments starting at column 1 +indent-classes +indent-switches +indent-cases +indent-col1-comments + +# put a space around operators +pad-oper + +# put a space after if/for/while +pad-header + +# if you like one-liners, keep them +keep-one-line-statements + +style=java +attach-namespaces +attach-classes +attach-inlines +attach-extern-c +indent-modifiers +indent-namespaces +indent-labels +indent-preproc-block +indent-preproc-define +indent-preproc-cond +unpad-paren +add-brackets +remove-comment-prefix diff --git a/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/3.conf b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/3.conf new file mode 100755 index 0000000..66613c2 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/etc/astyle-configurations/3.conf @@ -0,0 +1,125 @@ +# source: https://github.com/arduino/ArduinoCore-avr/issues/71#issuecomment-466763471 2019-06-09 + +# formatter.conf, examples_formatter.conf +mode=c + + +# examples_formatter.conf +# http://astyle.sourceforge.net/astyle.html#_style=java +# Considering changing this to the synonym "style=attach", which seems more descriptive +style=java + + +# examples_formatter.conf +attach-namespaces + +# examples_formatter.conf +attach-classes + +# examples_formatter.conf +attach-inlines + +# examples_formatter.conf +attach-extern-c + + +# formatter.conf, examples_formatter.conf +indent=spaces=2 + +# formatter.conf, examples_formatter.conf +indent-classes + +# formatter.conf, examples_formatter.conf +indent-switches + +# formatter.conf, examples_formatter.conf +indent-cases + +# formatter.conf, examples_formatter.conf +indent-col1-comments + +# examples_formatter.conf +indent-modifiers + +# examples_formatter.conf +indent-namespaces + +# examples_formatter.conf +indent-labels + +# examples_formatter.conf +indent-preproc-define + + +# formatter.conf, examples_formatter.conf +pad-header + +# formatter.conf, examples_formatter.conf +pad-oper + +# examples_formatter.conf +unpad-paren + + +# formatter.conf, examples_formatter.conf +remove-comment-prefix + +# formatter.conf, examples_formatter.conf +# http://astyle.sourceforge.net/astyle.html#_keep-one-line-statements +# "Don't break complex statements and multiple statements residing on a single line." +# I don't like one line complex statements, but I guess since it's in formatter.conf it must stay. +keep-one-line-statements + + + +# Options from examples_formatter.conf that I think should be removed: + +# http://astyle.sourceforge.net/astyle.html#_indent-preproc-block +# "Indent preprocessor blocks at brace level zero and immediately within a namespace. There are restrictions on what will be indented. Blocks within methods, classes, arrays, etc., will not be indented. Blocks containing braces or multi-line define statements will not be indented. Without this option the preprocessor block is not indented." +# This does indent for #ifdef, but not for #ifndef, so it's quite inconsistent +# Indentation of preprocessor directives as done by this option is not very common in Arduino AVR Boards core, and where it is used, it's typically done inconsistently throughout the file +indent-preproc-block + +# http://astyle.sourceforge.net/astyle.html#_indent-preproc-cond +# "Indent preprocessor conditional statements to the same level as the source code." +# Indentation of preprocessor directives as done by this option is very rare in Arduino AVR Boards core +indent-preproc-cond + + + +# Options I have not implemented from formatter.conf or examples_formatter.conf: + +# examples_formatter.conf +# Not a valid option in the latest version of AStyle. I think the correct option name is "add-braces", which I do use in my configuration +# add-brackets + +# formatter.conf, examples_formatter.conf +# Not a valid option in the latest version of AStyle. +# indent-preprocessor + + + +# Options I have added: + +# http://astyle.sourceforge.net/astyle.html#_add-braces +# "I believe this is the correct option name to use instead the "add-brackets" option used in examples_formatter.conf. "add-brackets" is not a valid option in the latest version of AStyle" +add-braces + +# http://astyle.sourceforge.net/astyle.html#_convert-tabs +# "Converts tabs into spaces in the non-indentation part of the line." +# AStyle is already configured to use spaces for indentation by indent=spaces=2. The Arduino IDE uses spaces instead of tabs by default. +convert-tabs + +# http://astyle.sourceforge.net/astyle.html#_attach-return-type +# "Attach the return type to the function name in function definitions." +attach-return-type + +# http://astyle.sourceforge.net/astyle.html#_attach-return-type +# "Attach the return type to the function name in function declarations." +attach-return-type-decl + +# http://astyle.sourceforge.net/astyle.html#_align-pointer +# "Attach a pointer or reference operator (*, &, or ^) to either the variable type (left) or variable name (right), or place it between the type and name (middle)." +# In Arduino AVR Boards core, name alignment of pointers is somewhat more common, though all possible styles are used +# I don't care which style is chosen (type, middle, name), but I do think one should be chosen and used. +align-pointer=name diff --git a/megaavr/travis-ci/arduino-ci-script/etc/autoformat.sh b/megaavr/travis-ci/arduino-ci-script/etc/autoformat.sh new file mode 100755 index 0000000..0ef37d9 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/etc/autoformat.sh @@ -0,0 +1 @@ +shfmt -i 2 -w ../arduino-ci-script.sh diff --git a/megaavr/travis-ci/arduino-ci-script/etc/codespell-ignore-words-list.txt b/megaavr/travis-ci/arduino-ci-script/etc/codespell-ignore-words-list.txt new file mode 100755 index 0000000..c74fb04 --- /dev/null +++ b/megaavr/travis-ci/arduino-ci-script/etc/codespell-ignore-words-list.txt @@ -0,0 +1,4 @@ +ba +propert +te +exampels diff --git a/megaavr/variants/28pin-standard/pins_arduino.h b/megaavr/variants/28pin-standard/pins_arduino.h index 743772e..7e53a4c 100644 --- a/megaavr/variants/28pin-standard/pins_arduino.h +++ b/megaavr/variants/28pin-standard/pins_arduino.h @@ -5,6 +5,8 @@ | COMPATIBLE WITH: | | ATmega4808 | | ATmega3208 | +| ATmega1608 | +| ATmega808 | | | | Note that PWM output pins are swapped by default | | | @@ -16,110 +18,188 @@ #include #include "timers.h" -#define DEFAULT_48PIN_PINOUT +#define MEGACOREX +#define MCUDUDE_MEGACOREX -#define NUM_DIGITAL_PINS 23 -#define NUM_ANALOG_INPUTS 8 -#define NUM_RESERVED_PINS 0 // With great power comes great responsibility -#define NUM_INTERNALLY_USED_PINS 0 -#define NUM_I2C_PINS 2 // (SDA / SCL) -#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) -#define NUM_TOTAL_FREE_PINS (NUM_DIGITAL_PINS) -#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS) -#define ANALOG_INPUT_OFFSET 0 -#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : (p) - 12) // The user will have to use A0 - A15, NOT 0 - 15 +#define MEGACOREX_DEFAULT_28PIN_PINOUT +#define __AVR_ATmegax08__ -#define MILLIS_USE_TIMERB0 // Use timerb0 for millis generation +// Arduino pin macros +#define PIN_PA0 0 +#define PIN_PA1 1 +#define PIN_PA2 2 +#define PIN_PA3 3 +#define PIN_PA4 4 +#define PIN_PA5 5 +#define PIN_PA6 6 +#define PIN_PA7 7 +#define PIN_PC0 8 +#define PIN_PC1 9 +#define PIN_PC2 10 +#define PIN_PC3 11 +#define PIN_PD0 12 +#define PIN_PD1 13 +#define PIN_PD2 14 +#define PIN_PD3 15 +#define PIN_PD4 16 +#define PIN_PD5 17 +#define PIN_PD6 18 +#define PIN_PD7 19 +#define PIN_PF0 20 +#define PIN_PF1 21 +#define PIN_PF6 22 -#define EXTERNAL_NUM_INTERRUPTS (NUM_TOTAL_PINS) +#define PINS_COUNT 23 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 8 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 +#define NUM_SPI_PINS 3 +#define NUM_TOTAL_FREE_PINS PINS_COUNT +#define NUM_TOTAL_PINS PINS_COUNT +#define ANALOG_INPUT_OFFSET 12 +#define LED_BUILTIN PIN_PA7 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : (p) - 12) +#define digitalOrAnalogPinToDigital(p) ((p < 8) ? ((p) + ANALOG_INPUT_OFFSET) : ((p) >= 12 && (p) <= 19) ? (p) : NOT_A_PIN) -#define digitalPinHasPWM(p) ((p) == 10 || (p) == 11) +// Timer to use for millis/micros +#if !defined(MILLIS_USE_TIMERB0) || !defined(MILLIS_USE_TIMERB1) || !defined(MILLIS_USE_TIMERB2) +#define MILLIS_USE_TIMERB2 // Use TCB2 if nothing else if defined +#endif + +// PWM pins +#if defined(MILLIS_USE_TIMERB0) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA3) || ((p) == PIN_PC0)) +#elif defined(MILLIS_USE_TIMERB1) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PC0)) +#else // default to MILLIS_USE_TIMERB2 + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PA3)) +#endif + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_UNTOUCHED = 0x80, +}; + +#endif + +// Timer pin mapping +#define TCA0_PINS PORTMUX_TCA0_PORTD_gc // TCA0 output on PD[0:5] +#define TCB0_PINS 0x00 // TCB0 output on PA2 instead of PF4 +#define TCB1_PINS 0x00 // TCB1 output on PA3 instead of PF5 +#define TCB2_PINS 0x00 // TCB2 output on PC0 instead of PB4 // SPI 0 // No pinswap by default // Pinswap 2 not available #define SPI_INTERFACES_COUNT 1 -#define SPI_MUX (PORTMUX_SPI0_DEFAULT_gc) -#define SPI_MUX_PINSWAP_1 (PORTMUX_SPI0_ALT1_gc) -#define SPI_MUX_PINSWAP_2 (PORTMUX_SPI0_DEFAULT_gc) -#define PIN_SPI_MISO (5) -#define PIN_SPI_SCK (6) -#define PIN_SPI_MOSI (4) -#define PIN_SPI_SS (7) -#define PIN_SPI_MISO_PINSWAP_1 (9) -#define PIN_SPI_SCK_PINSWAP_1 (10) -#define PIN_SPI_MOSI_PINSWAP_1 (8) -#define PIN_SPI_SS_PINSWAP_1 (11) -#define PIN_SPI_MISO_PINSWAP_2 (5) -#define PIN_SPI_SCK_PINSWAP_2 (6) -#define PIN_SPI_MOSI_PINSWAP_2 (4) -#define PIN_SPI_SS_PINSWAP_2 (7) -static const uint8_t SS = PIN_SPI_SS; -static const uint8_t MOSI = PIN_SPI_MOSI; -static const uint8_t MISO = PIN_SPI_MISO; -static const uint8_t SCK = PIN_SPI_SCK; - -// TWO 0 -// No pinswap enabled by default -#define TWI_MUX (PORTMUX_TWI0_DEFAULT_gc) -#define TWI_MUX_PINSWAP (PORTMUX_TWI0_ALT2_gc) -#define PIN_WIRE_SDA (2) -#define PIN_WIRE_SCL (3) -#define PIN_WIRE_SDA_PINSWAP_1 (10) -#define PIN_WIRE_SCL_PINSWAP_1 (11) -static const uint8_t SDA = PIN_WIRE_SDA; -static const uint8_t SCL = PIN_WIRE_SCL; +#define SPI_MUX PORTMUX_SPI0_DEFAULT_gc +#define SPI_MUX_PINSWAP_1 PORTMUX_SPI0_ALT1_gc +#define PIN_SPI_MISO PIN_PA5 +#define PIN_SPI_SCK PIN_PA6 +#define PIN_SPI_MOSI PIN_PA4 +#define PIN_SPI_SS PIN_PA7 +#define PIN_SPI_MISO_PINSWAP_1 PIN_PC1 +#define PIN_SPI_SCK_PINSWAP_1 PIN_PC2 +#define PIN_SPI_MOSI_PINSWAP_1 PIN_PC0 +#define PIN_SPI_SS_PINSWAP_1 PIN_PC3 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; -#define LED_BUILTIN 15 +// TWI 0 +// No pinswap enabled by default +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define TWI_MUX_PINSWAP PORTMUX_TWI0_ALT2_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +#define PIN_WIRE_SDA_PINSWAP_1 PIN_PC2 +#define PIN_WIRE_SCL_PINSWAP_1 PIN_PC3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; // USART 0 // No pinswap by default -#define HWSERIAL0 (&USART0) -#define HWSERIAL0_DRE_VECTOR (USART0_DRE_vect) -#define HWSERIAL0_DRE_VECTOR_NUM (USART0_DRE_vect_num) -#define HWSERIAL0_RXC_VECTOR (USART0_RXC_vect) -#define HWSERIAL0_MUX (PORTMUX_USART0_DEFAULT_gc) -#define HWSERIAL0_MUX_PINSWAP_1 (PORTMUX_USART0_ALT1_gc) -#define PIN_WIRE_HWSERIAL0_TX (0) -#define PIN_WIRE_HWSERIAL0_RX (1) -#define PIN_WIRE_HWSERIAL0_TX_PINSWAP_1 (4) -#define PIN_WIRE_HWSERIAL0_RX_PINSWAP_1 (5) +#define HWSERIAL0 &USART0 +#define HWSERIAL0_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL0_TX PIN_PA0 +#define PIN_HWSERIAL0_RX PIN_PA1 +#define PIN_HWSERIAL0_XCK PIN_PA2 +#define PIN_HWSERIAL0_XDIR PIN_PA3 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PA7 // USART1 // No pinswap available -#define HWSERIAL1 (&USART1) -#define HWSERIAL1_DRE_VECTOR (USART1_DRE_vect) -#define HWSERIAL1_DRE_VECTOR_NUM (USART1_DRE_vect_num) -#define HWSERIAL1_RXC_VECTOR (USART1_RXC_vect) -#define HWSERIAL1_MUX (PORTMUX_USART1_DEFAULT_gc) -#define HWSERIAL1_MUX_PINSWAP_1 (PORTMUX_USART1_DEFAULT_gc) -#define PIN_WIRE_HWSERIAL1_TX (8) -#define PIN_WIRE_HWSERIAL1_RX (9) -#define PIN_WIRE_HWSERIAL1_TX_PINSWAP_1 (8) -#define PIN_WIRE_HWSERIAL1_RX_PINSWAP_1 (9) +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_DEFAULT_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_DEFAULT_gc +#define PIN_HWSERIAL1_TX PIN_PC0 +#define PIN_HWSERIAL1_RX PIN_PC1 +#define PIN_HWSERIAL1_XCK PIN_PC2 +#define PIN_HWSERIAL1_XDIR PIN_PC3 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_HWSERIAL1_TX +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_HWSERIAL1_RX // USART 2 // No pinswap by default -#define HWSERIAL2 (&USART2) -#define HWSERIAL2_DRE_VECTOR (USART2_DRE_vect) -#define HWSERIAL2_DRE_VECTOR_NUM (USART2_DRE_vect_num) -#define HWSERIAL2_RXC_VECTOR (USART2_RXC_vect) -#define HWSERIAL2_MUX (PORTMUX_USART2_DEFAULT_gc) -#define HWSERIAL2_MUX_PINSWAP_1 (PORTMUX_USART2_ALT1_gc) -#define PIN_WIRE_HWSERIAL2_TX (20) -#define PIN_WIRE_HWSERIAL2_RX (21) -#define PIN_WIRE_HWSERIAL2_TX_PINSWAP_1 (24) -#define PIN_WIRE_HWSERIAL2_RX_PINSWAP_1 (25) - -#define PIN_A0 (12) -#define PIN_A1 (13) -#define PIN_A2 (14) -#define PIN_A3 (15) -#define PIN_A4 (16) -#define PIN_A5 (17) -#define PIN_A6 (18) -#define PIN_A7 (19) +#define HWSERIAL2 &USART2 +#define HWSERIAL2_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART2_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART2_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PF0 +#define PIN_HWSERIAL2_RX PIN_PF1 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_HWSERIAL2_TX +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_HWSERIAL2_RX +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PD4 +#define PIN_A5 PIN_PD5 +#define PIN_A6 PIN_PD6 +#define PIN_A7 PIN_PD7 static const uint8_t A0 = PIN_A0; static const uint8_t A1 = PIN_A1; static const uint8_t A2 = PIN_A2; @@ -129,11 +209,9 @@ static const uint8_t A5 = PIN_A5; static const uint8_t A6 = PIN_A6; static const uint8_t A7 = PIN_A7; -#define PINS_COUNT (27u) - #ifdef ARDUINO_MAIN -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PA, // 0 PA0/USART0_Tx/CLKIN PA, // 1 PA1/USART0_Rx PA, // 2 PA2/SDA @@ -141,15 +219,15 @@ const uint8_t PROGMEM digital_pin_to_port[] = { PA, // 4 PA4/MOSI PA, // 5 PA5/MISO PA, // 6 PA6/SCK - PA, // 7 PA7/SS/CLKOUT - PC, // 8 PC0/USART1_Tx - PC, // 9 PC1/USART1_Rx + PA, // 7 PA7/SS/CLKOUT/LED_BUILTIN + PC, // 8 PC0/USART1_Tx/TCA0 PWM + PC, // 9 PC1/USART1_Rx/TCA0 PWM PC, // 10 PC2/TCA0 PWM PC, // 11 PC3/TCA0 PWM PD, // 12 PD0/AIN0 PD, // 13 PD1/AIN1 PD, // 14 PD2/AIN2 - PD, // 15 PD3/AIN3/LED_BUILTIN + PD, // 15 PD3/AIN3 PD, // 16 PD4/AIN4 PD, // 17 PD5/AIN5 PD, // 18 PD6/AIN6 @@ -160,7 +238,7 @@ const uint8_t PROGMEM digital_pin_to_port[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN0_bp, // 0 PIN_bp0/USART0_Tx/CLKIN PIN1_bp, // 1 PA1/USART0_Rx PIN2_bp, // 2 PA2/SDA @@ -168,15 +246,15 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { PIN4_bp, // 4 PA4/MOSI PIN5_bp, // 5 PA5/MISO PIN6_bp, // 6 PA6/SCK - PIN7_bp, // 7 PA7/SS/CLKOUT + PIN7_bp, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bp, // 8 PC0/USART1_Tx PIN1_bp, // 9 PC1/USART1_Rx - PIN2_bp, // 10 PC2/TCA0 PWM - PIN3_bp, // 11 PC3/TCA0 PWM + PIN2_bp, // 10 PC2 + PIN3_bp, // 11 PC3 PIN0_bp, // 12 PD0/AIN0 PIN1_bp, // 13 PD1/AIN1 PIN2_bp, // 14 PD2/AIN2 - PIN3_bp, // 15 PD3/AIN3/LED_BUILTIN + PIN3_bp, // 15 PD3/AIN3 PIN4_bp, // 16 PD4/AIN4 PIN5_bp, // 17 PD5/AIN5 PIN6_bp, // 18 PD6/AIN6 @@ -187,23 +265,23 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { - PIN0_bm, // 0 PIN_bp0/USART0_Tx/CLKIN +const uint8_t digital_pin_to_bit_mask[] = { + PIN0_bm, // 0 PA0/USART0_Tx/CLKIN PIN1_bm, // 1 PA1/USART0_Rx PIN2_bm, // 2 PA2/SDA PIN3_bm, // 3 PA3/SCL PIN4_bm, // 4 PA4/MOSI PIN5_bm, // 5 PA5/MISO PIN6_bm, // 6 PA6/SCK - PIN7_bm, // 7 PA7/SS/CLKOUT + PIN7_bm, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bm, // 8 PC0/USART1_Tx PIN1_bm, // 9 PC1/USART1_Rx - PIN2_bm, // 10 PC2/TCA0 PWM - PIN3_bm, // 11 PC3/TCA0 PWM + PIN2_bm, // 10 PC2 + PIN3_bm, // 11 PC3 PIN0_bm, // 12 PD0/AIN0 PIN1_bm, // 13 PD1/AIN1 PIN2_bm, // 14 PD2/AIN2 - PIN3_bm, // 15 PD3/AIN3/LED_BUILTIN + PIN3_bm, // 15 PD3/AIN3 PIN4_bm, // 16 PD4/AIN4 PIN5_bm, // 17 PD5/AIN5 PIN6_bm, // 18 PD6/AIN6 @@ -213,25 +291,37 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN6_bm // 22 PF6 RESET }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PA0/USART0_Tx/CLKIN NOT_ON_TIMER, // 1 PA1/USART0_Rx +#if !defined(MILLIS_USE_TIMERB0) + TIMERB0, // 2 PA2/SDA +#else NOT_ON_TIMER, // 2 PA2/SDA +#endif +#if !defined(MILLIS_USE_TIMERB1) + TIMERB1, // 3 PA3/SCL +#else NOT_ON_TIMER, // 3 PA3/SCL +#endif NOT_ON_TIMER, // 4 PA4/MOSI NOT_ON_TIMER, // 5 PA5/MISO NOT_ON_TIMER, // 6 PA6/SCK - NOT_ON_TIMER, // 7 PA7/SS/CLKOUT + NOT_ON_TIMER, // 7 PA7/SS/CLKOUT/LED_BUILTIN +#if !defined(MILLIS_USE_TIMERB2) + TIMERB2, // 8 PC0/USART1_Tx +#else NOT_ON_TIMER, // 8 PC0/USART1_Tx +#endif NOT_ON_TIMER, // 9 PC1/USART1_Rx - TIMERA0, // 10 PC2/TCA0 PWM - TIMERA0, // 11 PC3/TCA0 PWM - NOT_ON_TIMER, // 12 PD0/AIN0 - NOT_ON_TIMER, // 13 PD1/AIN1 - NOT_ON_TIMER, // 14 PD2/AIN2 - NOT_ON_TIMER, // 15 PD3/AIN3/LED_BUILTIN - NOT_ON_TIMER, // 16 PD4/AIN4 - NOT_ON_TIMER, // 17 PD5/AIN5 + NOT_ON_TIMER, // 10 PC2 + NOT_ON_TIMER, // 11 PC3 + TIMERA0, // 12 PD0/AIN0 + TIMERA0, // 13 PD1/AIN1 + TIMERA0, // 14 PD2/AIN2 + TIMERA0, // 15 PD3/AIN3 + TIMERA0, // 16 PD4/AIN4 + TIMERA0, // 17 PD5/AIN5 NOT_ON_TIMER, // 18 PD6/AIN6 NOT_ON_TIMER, // 19 PD7/AIN7/AREF NOT_ON_TIMER, // 20 PF0/USART2_Tx/TOSC1 @@ -239,7 +329,28 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { NOT_ON_TIMER // 22 PF6 RESET }; - #endif +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial2 + +void initVariant() __attribute__((weak)); +void initVariant() { } + #endif diff --git a/megaavr/variants/28pin-standard/timers.h b/megaavr/variants/28pin-standard/timers.h deleted file mode 100644 index 438e79f..0000000 --- a/megaavr/variants/28pin-standard/timers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __TIMERS_H__ -#define __TIMERS_H__ - -#define TIME_TRACKING_TIMER_PERIOD 0xFF -#define TIME_TRACKING_TICKS_PER_OVF (TIME_TRACKING_TIMER_PERIOD + 1) // Timer ticks per overflow of TCB3 -#define TIME_TRACKING_TIMER_DIVIDER 64 // Clock divider for TCB0 -#define TIME_TRACKING_CYCLES_PER_OVF (TIME_TRACKING_TICKS_PER_OVF * TIME_TRACKING_TIMER_DIVIDER) - -#define PWM_TIMER_PERIOD 0xFF // For frequency -#define PWM_TIMER_COMPARE 0x80 // For duty cycle - -#endif \ No newline at end of file diff --git a/megaavr/variants/28pin-standard/variant.c b/megaavr/variants/28pin-standard/variant.c deleted file mode 100644 index e54d4d4..0000000 --- a/megaavr/variants/28pin-standard/variant.c +++ /dev/null @@ -1,118 +0,0 @@ -#include - -#include "pins_arduino.h" -#include "api/Common.h" - -#define FORCE_INLINE __attribute__((always_inline)) inline - -void setup_timers() { - - // TYPE A TIMER - - // PORTMUX setting for TCA -> outputs [2:3] point to PORTC pins [2:3] - PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTC_gc; - - // Setup timers for single slope PWM, but do not enable, will do in analogWrite() - TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; - - // Period setting, 16 bit register but val resolution is 8 bit - TCA0.SINGLE.PER = PWM_TIMER_PERIOD; - - // Default duty 50%, will re-assign in analogWrite() - TCA0.SINGLE.CMP0BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP1BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP2BUF = PWM_TIMER_COMPARE; - - // Use DIV64 prescaler (giving 250kHz clock), enable TCA timer - TCA0.SINGLE.CTRLA = (TCA_SINGLE_CLKSEL_DIV64_gc) | (TCA_SINGLE_ENABLE_bm); - - // TYPE B TIMERS - - // Setup TCB0 routing - #if defined(TCB0) - PORTMUX.TCBROUTEA |= PORTMUX_TCB0_bm; // Route signal to PF4 - #endif - - // Setup TCB1 routing - #if defined(TCB1) - PORTMUX.TCBROUTEA |= PORTMUX_TCB1_bm; // Route signal to PF5 - #endif - - // Start with TCB0 - TCB_t *timer_B = (TCB_t *)&TCB0; - - // Find end timer - #if defined(TCB3) - TCB_t *timer_B_end = (TCB_t *)&TCB3; - #elif defined(TCB2) - TCB_t *timer_B_end = (TCB_t *)&TCB2; - #elif defined(TCB1) - TCB_t *timer_B_end = (TCB_t *)&TCB1; - #else - TCB_t *timer_B_end = (TCB_t *)&TCB0; - #endif - - // Timer B Setup loop for TCB[0:end] - do - { - // 8 bit PWM mode, but do not enable output yet, will do in analogWrite() - timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc); - - // Assign 8-bit period - timer_B->CCMPL = PWM_TIMER_PERIOD; - - // default duty 50%, set when output enabled - timer_B->CCMPH = PWM_TIMER_COMPARE; - - // Use TCA clock (250kHz) and enable - // (sync update commented out, might try to synchronize later - timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) - //|(TCB_SYNCUPD_bm) - |(TCB_ENABLE_bm); - - // Increment pointer to next TCB instance - timer_B++; - - // Stop when pointing to TCB3 - } while (timer_B <= timer_B_end); - - // Stuff for synchronizing PWM timers -// // Restart TCA to sync TCBs -// // should not be needed -// TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESTART_gc; -// TCA0.SINGLE.CTRLECLR = TCA_SINGLE_CMD_RESTART_gc; -// -// timer_B = (TCB_t *)&TCB0; -// -// // TCB are sync to TCA, remove setting -// for (uint8_t digitial_pin_timer = (TIMERB0 - TIMERB0); -// digitial_pin_timer < (TIMERB3 - TIMERB0); -// digitial_pin_timer++) -// { -// // disable sync with tca -// timer_B->CTRLA &= ~ (TCB_SYNCUPD_bm); -// -// // Add offset to register -// timer_B++; -// -// } -} - -FORCE_INLINE bool isDoubleBondedActive(uint8_t pin) { - (void)pin; - - /* Check if TWI is operating on double bonded pin (Master Enable is high - in both Master and Slave mode for bus error detection, so this can - indicate an active state for Wire) */ - //if(((pin == PIN_A4) || (pin == PIN_A5)) && (TWI0.MCTRLA & TWI_ENABLE_bm)) return true; - - /* Special check for SPI_SS double bonded pin -- no action if SPI is active - (Using SPI Enable bit as indicator of SPI activity) */ - //if((pin == 10) && (SPI0.CTRLA & SPI_ENABLE_bm)) return true; - - return false; -} - -void initVariant() { -// Not used -} diff --git a/megaavr/variants/32pin-standard/pins_arduino.h b/megaavr/variants/32pin-standard/pins_arduino.h index 45b95df..8291fe6 100644 --- a/megaavr/variants/32pin-standard/pins_arduino.h +++ b/megaavr/variants/32pin-standard/pins_arduino.h @@ -5,6 +5,8 @@ | COMPATIBLE WITH: | | ATmega4808 | | ATmega3208 | +| ATmega1608 | +| ATmega808 | | | | Note that PWM output pins are swapped by default | | | @@ -16,114 +18,201 @@ #include #include "timers.h" -#define DEFAULT_48PIN_PINOUT +#define MEGACOREX +#define MCUDUDE_MEGACOREX -#define NUM_DIGITAL_PINS 27 -#define NUM_ANALOG_INPUTS 12 -#define NUM_RESERVED_PINS 0 // With great power comes great responsibility -#define NUM_INTERNALLY_USED_PINS 0 -#define NUM_I2C_PINS 2 // (SDA / SCL) -#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) -#define NUM_TOTAL_FREE_PINS (NUM_DIGITAL_PINS) -#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS) -#define ANALOG_INPUT_OFFSET 0 -#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : (p) - 12) // The user will have to use A0 - A15, NOT 0 - 15 +#define MEGACOREX_DEFAULT_32PIN_PINOUT +#define __AVR_ATmegax08__ -#define MILLIS_USE_TIMERB0 // Use timerb0 for millis generation +// Arduino pin macros +#define PIN_PA0 0 +#define PIN_PA1 1 +#define PIN_PA2 2 +#define PIN_PA3 3 +#define PIN_PA4 4 +#define PIN_PA5 5 +#define PIN_PA6 6 +#define PIN_PA7 7 +#define PIN_PC0 8 +#define PIN_PC1 9 +#define PIN_PC2 10 +#define PIN_PC3 11 +#define PIN_PD0 12 +#define PIN_PD1 13 +#define PIN_PD2 14 +#define PIN_PD3 15 +#define PIN_PD4 16 +#define PIN_PD5 17 +#define PIN_PD6 18 +#define PIN_PD7 19 +#define PIN_PF0 20 +#define PIN_PF1 21 +#define PIN_PF2 22 +#define PIN_PF3 23 +#define PIN_PF4 24 +#define PIN_PF5 25 +#define PIN_PF6 26 -#define EXTERNAL_NUM_INTERRUPTS (NUM_TOTAL_PINS) +#define PINS_COUNT 27 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 12 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 +#define NUM_SPI_PINS 3 +#define NUM_TOTAL_FREE_PINS PINS_COUNT +#define NUM_TOTAL_PINS PINS_COUNT +#define ANALOG_INPUT_OFFSET 12 +#define LED_BUILTIN PIN_PA7 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) ((p < 8) ? (p) : ((p) < 12) ? ((p) + 4) : ((p) < 20) ? ((p) - 12) : ((p) >= 22 && (p) <=25) ? ((p) - 10) : NOT_A_PIN) +#define digitalOrAnalogPinToDigital(p) ((p < 8) ? ((p) + ANALOG_INPUT_OFFSET) : ((p) >= 8 && (p) <= 11) ? ((p) + ANALOG_INPUT_OFFSET + 2) : (((p) >= 12 && (p) <= 19) || ((p) >= 22 && (p) <= 25)) ? (p) : NOT_A_PIN) -#define digitalPinHasPWM(p) ((p) == 10 || (p) == 11 || (p) == 24 || (p) == 25) +#if !defined(MILLIS_USE_TIMERB0) || !defined(MILLIS_USE_TIMERB1) || !defined(MILLIS_USE_TIMERB2) +#define MILLIS_USE_TIMERB2 // Use TCB2 if nothing else if defined +#endif + +// PWM pins +#if defined(MILLIS_USE_TIMERB0) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA3) || ((p) == PIN_PC0)) +#elif defined(MILLIS_USE_TIMERB1) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PC0)) +#else // default to MILLIS_USE_TIMERB2 + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PA3)) +#endif + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_UNTOUCHED = 0x80, +}; +#endif + +// Timer pin mapping +#define TCA0_PINS PORTMUX_TCA0_PORTD_gc // TCA0 output on PD[0:5] +#define TCB0_PINS 0x00 // TCB0 output on PA2 instead of PF4 +#define TCB1_PINS 0x00 // TCB1 output on PA3 instead of PF5 +#define TCB2_PINS 0x00 // TCB2 output on PC0 instead of PB4 // SPI 0 // No pinswap enabled by default // Pinswap 2 not available #define SPI_INTERFACES_COUNT 1 -#define SPI_MUX (PORTMUX_SPI0_DEFAULT_gc) -#define SPI_MUX_PINSWAP_1 (PORTMUX_SPI0_ALT1_gc) -#define SPI_MUX_PINSWAP_2 (PORTMUX_SPI0_DEFAULT_gc) -#define PIN_SPI_MISO (5) -#define PIN_SPI_SCK (6) -#define PIN_SPI_MOSI (4) -#define PIN_SPI_SS (7) -#define PIN_SPI_MISO_PINSWAP_1 (9) -#define PIN_SPI_SCK_PINSWAP_1 (10) -#define PIN_SPI_MOSI_PINSWAP_1 (8) -#define PIN_SPI_SS_PINSWAP_1 (11) -#define PIN_SPI_MISO_PINSWAP_2 (5) -#define PIN_SPI_SCK_PINSWAP_2 (6) -#define PIN_SPI_MOSI_PINSWAP_2 (4) -#define PIN_SPI_SS_PINSWAP_2 (7) -static const uint8_t SS = PIN_SPI_SS; -static const uint8_t MOSI = PIN_SPI_MOSI; -static const uint8_t MISO = PIN_SPI_MISO; -static const uint8_t SCK = PIN_SPI_SCK; +#define SPI_MUX PORTMUX_SPI0_DEFAULT_gc +#define SPI_MUX_PINSWAP_1 PORTMUX_SPI0_ALT1_gc +#define PIN_SPI_MISO PIN_PA5 +#define PIN_SPI_SCK PIN_PA6 +#define PIN_SPI_MOSI PIN_PA4 +#define PIN_SPI_SS PIN_PA7 +#define PIN_SPI_MISO_PINSWAP_1 PIN_PC1 +#define PIN_SPI_SCK_PINSWAP_1 PIN_PC2 +#define PIN_SPI_MOSI_PINSWAP_1 PIN_PC0 +#define PIN_SPI_SS_PINSWAP_1 PIN_PC3 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; // TWI 0 // No pinswap enabled by default -#define TWI_MUX (PORTMUX_TWI0_DEFAULT_gc) -#define TWI_MUX_PINSWAP (PORTMUX_TWI0_ALT2_gc) -#define PIN_WIRE_SDA (2) -#define PIN_WIRE_SCL (3) -#define PIN_WIRE_SDA_PINSWAP_1 (10) -#define PIN_WIRE_SCL_PINSWAP_1 (11) -static const uint8_t SDA = PIN_WIRE_SDA; -static const uint8_t SCL = PIN_WIRE_SCL; - -#define LED_BUILTIN 15 +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define TWI_MUX_PINSWAP PORTMUX_TWI0_ALT2_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +#define PIN_WIRE_SDA_PINSWAP_1 PIN_PC2 +#define PIN_WIRE_SCL_PINSWAP_1 PIN_PC3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; // USART 0 // No pinswap enabled by default -#define HWSERIAL0 (&USART0) -#define HWSERIAL0_DRE_VECTOR (USART0_DRE_vect) -#define HWSERIAL0_DRE_VECTOR_NUM (USART0_DRE_vect_num) -#define HWSERIAL0_RXC_VECTOR (USART0_RXC_vect) -#define HWSERIAL0_MUX (PORTMUX_USART0_DEFAULT_gc) -#define HWSERIAL0_MUX_PINSWAP_1 (PORTMUX_USART0_ALT1_gc) -#define PIN_WIRE_HWSERIAL0_TX (0) -#define PIN_WIRE_HWSERIAL0_RX (1) -#define PIN_WIRE_HWSERIAL0_TX_PINSWAP_1 (4) -#define PIN_WIRE_HWSERIAL0_RX_PINSWAP_1 (5) +#define HWSERIAL0 &USART0 +#define HWSERIAL0_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL0_TX PIN_PA0 +#define PIN_HWSERIAL0_RX PIN_PA1 +#define PIN_HWSERIAL0_XCK PIN_PA2 +#define PIN_HWSERIAL0_XDIR PIN_PA3 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PA7 // USART1 // No pinswap available -#define HWSERIAL1 (&USART1) -#define HWSERIAL1_DRE_VECTOR (USART1_DRE_vect) -#define HWSERIAL1_DRE_VECTOR_NUM (USART1_DRE_vect_num) -#define HWSERIAL1_RXC_VECTOR (USART1_RXC_vect) -#define HWSERIAL1_MUX (PORTMUX_USART1_DEFAULT_gc) -#define HWSERIAL1_MUX_PINSWAP_1 (PORTMUX_USART1_DEFAULT_gc) -#define PIN_WIRE_HWSERIAL1_TX (8) -#define PIN_WIRE_HWSERIAL1_RX (9) -#define PIN_WIRE_HWSERIAL1_TX_PINSWAP_1 (8) -#define PIN_WIRE_HWSERIAL1_RX_PINSWAP_1 (9) +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_DEFAULT_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_DEFAULT_gc +#define PIN_HWSERIAL1_TX PIN_PC0 +#define PIN_HWSERIAL1_RX PIN_PC1 +#define PIN_HWSERIAL1_XCK PIN_PC2 +#define PIN_HWSERIAL1_XDIR PIN_PC3 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_HWSERIAL1_TX +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_HWSERIAL1_RX // USART 2 // No pinswap enabled by default -#define HWSERIAL2 (&USART2) -#define HWSERIAL2_DRE_VECTOR (USART2_DRE_vect) -#define HWSERIAL2_DRE_VECTOR_NUM (USART2_DRE_vect_num) -#define HWSERIAL2_RXC_VECTOR (USART2_RXC_vect) -#define HWSERIAL2_MUX (PORTMUX_USART2_DEFAULT_gc) -#define HWSERIAL2_MUX_PINSWAP_1 (PORTMUX_USART2_ALT1_gc) -#define PIN_WIRE_HWSERIAL2_TX (20) -#define PIN_WIRE_HWSERIAL2_RX (21) -#define PIN_WIRE_HWSERIAL2_TX_PINSWAP_1 (24) -#define PIN_WIRE_HWSERIAL2_RX_PINSWAP_1 (25) - -#define PIN_A0 (12) -#define PIN_A1 (13) -#define PIN_A2 (14) -#define PIN_A3 (15) -#define PIN_A4 (16) -#define PIN_A5 (17) -#define PIN_A6 (18) -#define PIN_A7 (19) -#define PIN_A12 (22) -#define PIN_A13 (23) -#define PIN_A14 (24) -#define PIN_A15 (25) +#define HWSERIAL2 &USART2 +#define HWSERIAL2_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART2_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART2_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PF0 +#define PIN_HWSERIAL2_RX PIN_PF1 +#define PIN_HWSERIAL2_XCK PIN_PF2 +#define PIN_HWSERIAL2_XDIR PIN_PF3 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PF4 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PF5 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PF6 +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PD4 +#define PIN_A5 PIN_PD5 +#define PIN_A6 PIN_PD6 +#define PIN_A7 PIN_PD7 +#define PIN_A8 PIN_PF2 +#define PIN_A9 PIN_PF3 +#define PIN_A10 PIN_PF4 +#define PIN_A11 PIN_PF5 +#define PIN_A12 PIN_PF2 +#define PIN_A13 PIN_PF3 +#define PIN_A14 PIN_PF4 +#define PIN_A15 PIN_PF5 static const uint8_t A0 = PIN_A0; static const uint8_t A1 = PIN_A1; static const uint8_t A2 = PIN_A2; @@ -132,16 +221,18 @@ static const uint8_t A4 = PIN_A4; static const uint8_t A5 = PIN_A5; static const uint8_t A6 = PIN_A6; static const uint8_t A7 = PIN_A7; +static const uint8_t A8 = PIN_A8; +static const uint8_t A9 = PIN_A9; +static const uint8_t A10 = PIN_A10; +static const uint8_t A11 = PIN_A11; static const uint8_t A12 = PIN_A12; static const uint8_t A13 = PIN_A13; static const uint8_t A14 = PIN_A14; static const uint8_t A15 = PIN_A15; -#define PINS_COUNT (27u) - #ifdef ARDUINO_MAIN -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PA, // 0 PA0/USART0_Tx/CLKIN PA, // 1 PA1/USART0_Rx PA, // 2 PA2/SDA @@ -149,15 +240,15 @@ const uint8_t PROGMEM digital_pin_to_port[] = { PA, // 4 PA4/MOSI PA, // 5 PA5/MISO PA, // 6 PA6/SCK - PA, // 7 PA7/SS/CLKOUT + PA, // 7 PA7/SS/CLKOUT/LED_BUILTIN PC, // 8 PC0/USART1_Tx PC, // 9 PC1/USART1_Rx - PC, // 10 PC2/TCA0 PWM - PC, // 11 PC3/TCA0 PWM + PC, // 10 PC2 + PC, // 11 PC3 PD, // 12 PD0/AIN0 PD, // 13 PD1/AIN1 PD, // 14 PD2/AIN2 - PD, // 15 PD3/AIN3/LED_BUILTIN + PD, // 15 PD3/AIN3 PD, // 16 PD4/AIN4 PD, // 17 PD5/AIN5 PD, // 18 PD6/AIN6 @@ -172,7 +263,7 @@ const uint8_t PROGMEM digital_pin_to_port[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN0_bp, // 0 PIN_bp0/USART0_Tx/CLKIN PIN1_bp, // 1 PA1/USART0_Rx PIN2_bp, // 2 PA2/SDA @@ -180,15 +271,15 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { PIN4_bp, // 4 PA4/MOSI PIN5_bp, // 5 PA5/MISO PIN6_bp, // 6 PA6/SCK - PIN7_bp, // 7 PA7/SS/CLKOUT + PIN7_bp, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bp, // 8 PC0/USART1_Tx PIN1_bp, // 9 PC1/USART1_Rx - PIN2_bp, // 10 PC2/TCA0 PWM - PIN3_bp, // 11 PC3/TCA0 PWM + PIN2_bp, // 10 PC2 + PIN3_bp, // 11 PC3 PIN0_bp, // 12 PD0/AIN0 PIN1_bp, // 13 PD1/AIN1 PIN2_bp, // 14 PD2/AIN2 - PIN3_bp, // 15 PD3/AIN3/LED_BUILTIN + PIN3_bp, // 15 PD3/AIN3 PIN4_bp, // 16 PD4/AIN4 PIN5_bp, // 17 PD5/AIN5 PIN6_bp, // 18 PD6/AIN6 @@ -203,23 +294,23 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { - PIN0_bm, // 0 PIN_bp0/USART0_Tx/CLKIN +const uint8_t digital_pin_to_bit_mask[] = { + PIN0_bm, // 0 PA0/USART0_Tx/CLKIN PIN1_bm, // 1 PA1/USART0_Rx PIN2_bm, // 2 PA2/SDA PIN3_bm, // 3 PA3/SCL PIN4_bm, // 4 PA4/MOSI PIN5_bm, // 5 PA5/MISO PIN6_bm, // 6 PA6/SCK - PIN7_bm, // 7 PA7/SS/CLKOUT + PIN7_bm, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bm, // 8 PC0/USART1_Tx PIN1_bm, // 9 PC1/USART1_Rx - PIN2_bm, // 10 PC2/TCA0 PWM - PIN3_bm, // 11 PC3/TCA0 PWM + PIN2_bm, // 10 PC2 + PIN3_bm, // 11 PC3 PIN0_bm, // 12 PD0/AIN0 PIN1_bm, // 13 PD1/AIN1 PIN2_bm, // 14 PD2/AIN2 - PIN3_bm, // 15 PD3/AIN3/LED_BUILTIN + PIN3_bm, // 15 PD3/AIN3 PIN4_bm, // 16 PD4/AIN4 PIN5_bm, // 17 PD5/AIN5 PIN6_bm, // 18 PD6/AIN6 @@ -233,37 +324,70 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN6_bm // 26 PF6 RESET }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PA0/USART0_Tx/CLKIN NOT_ON_TIMER, // 1 PA1/USART0_Rx +#if !defined(MILLIS_USE_TIMERB0) + TIMERB0, // 2 PA2/SDA +#else NOT_ON_TIMER, // 2 PA2/SDA +#endif +#if !defined(MILLIS_USE_TIMERB1) + TIMERB1, // 3 PA3/SCL +#else NOT_ON_TIMER, // 3 PA3/SCL +#endif NOT_ON_TIMER, // 4 PA4/MOSI NOT_ON_TIMER, // 5 PA5/MISO NOT_ON_TIMER, // 6 PA6/SCK - NOT_ON_TIMER, // 7 PA7/SS/CLKOUT + NOT_ON_TIMER, // 7 PA7/SS/CLKOUT/LED_BUILTIN +#if !defined(MILLIS_USE_TIMERB2) + TIMERB2, // 8 PC0/USART1_Tx +#else NOT_ON_TIMER, // 8 PC0/USART1_Tx +#endif NOT_ON_TIMER, // 9 PC1/USART1_Rx - TIMERA0, // 10 PC2/TCA0 PWM - TIMERA0, // 11 PC3/TCA0 PWM - NOT_ON_TIMER, // 12 PD0/AIN0 - NOT_ON_TIMER, // 13 PD1/AIN1 - NOT_ON_TIMER, // 14 PD2/AIN2 - NOT_ON_TIMER, // 15 PD3/AIN3/LED_BUILTIN - NOT_ON_TIMER, // 16 PD4/AIN4 - NOT_ON_TIMER, // 17 PD5/AIN5 + NOT_ON_TIMER, // 10 PC2/ + NOT_ON_TIMER, // 11 PC3/ + TIMERA0, // 12 PD0/AIN0 + TIMERA0, // 13 PD1/AIN1 + TIMERA0, // 14 PD2/AIN2 + TIMERA0, // 15 PD3/AIN3 + TIMERA0, // 16 PD4/AIN4 + TIMERA0, // 17 PD5/AIN5 NOT_ON_TIMER, // 18 PD6/AIN6 NOT_ON_TIMER, // 19 PD7/AIN7/AREF NOT_ON_TIMER, // 20 PF0/USART2_Tx/TOSC1 NOT_ON_TIMER, // 21 PF1/USART2_Rx/TOSC2 NOT_ON_TIMER, // 22 PF2/AIN12 NOT_ON_TIMER, // 23 PF3/AIN13 - TIMERB0, // 24 PF4/AIN14/TCB0 PWM - TIMERB1, // 25 PF5/AIN15/TCB1 PWM + NOT_ON_TIMER, // 24 PF4/AIN14 + NOT_ON_TIMER, // 25 PF5/AIN15 NOT_ON_TIMER // 26 PF6 RESET }; - #endif +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial2 + +void initVariant() __attribute__((weak)); +void initVariant() { } + #endif diff --git a/megaavr/variants/32pin-standard/timers.h b/megaavr/variants/32pin-standard/timers.h deleted file mode 100644 index 438e79f..0000000 --- a/megaavr/variants/32pin-standard/timers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __TIMERS_H__ -#define __TIMERS_H__ - -#define TIME_TRACKING_TIMER_PERIOD 0xFF -#define TIME_TRACKING_TICKS_PER_OVF (TIME_TRACKING_TIMER_PERIOD + 1) // Timer ticks per overflow of TCB3 -#define TIME_TRACKING_TIMER_DIVIDER 64 // Clock divider for TCB0 -#define TIME_TRACKING_CYCLES_PER_OVF (TIME_TRACKING_TICKS_PER_OVF * TIME_TRACKING_TIMER_DIVIDER) - -#define PWM_TIMER_PERIOD 0xFF // For frequency -#define PWM_TIMER_COMPARE 0x80 // For duty cycle - -#endif \ No newline at end of file diff --git a/megaavr/variants/32pin-standard/variant.c b/megaavr/variants/32pin-standard/variant.c deleted file mode 100644 index e54d4d4..0000000 --- a/megaavr/variants/32pin-standard/variant.c +++ /dev/null @@ -1,118 +0,0 @@ -#include - -#include "pins_arduino.h" -#include "api/Common.h" - -#define FORCE_INLINE __attribute__((always_inline)) inline - -void setup_timers() { - - // TYPE A TIMER - - // PORTMUX setting for TCA -> outputs [2:3] point to PORTC pins [2:3] - PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTC_gc; - - // Setup timers for single slope PWM, but do not enable, will do in analogWrite() - TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; - - // Period setting, 16 bit register but val resolution is 8 bit - TCA0.SINGLE.PER = PWM_TIMER_PERIOD; - - // Default duty 50%, will re-assign in analogWrite() - TCA0.SINGLE.CMP0BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP1BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP2BUF = PWM_TIMER_COMPARE; - - // Use DIV64 prescaler (giving 250kHz clock), enable TCA timer - TCA0.SINGLE.CTRLA = (TCA_SINGLE_CLKSEL_DIV64_gc) | (TCA_SINGLE_ENABLE_bm); - - // TYPE B TIMERS - - // Setup TCB0 routing - #if defined(TCB0) - PORTMUX.TCBROUTEA |= PORTMUX_TCB0_bm; // Route signal to PF4 - #endif - - // Setup TCB1 routing - #if defined(TCB1) - PORTMUX.TCBROUTEA |= PORTMUX_TCB1_bm; // Route signal to PF5 - #endif - - // Start with TCB0 - TCB_t *timer_B = (TCB_t *)&TCB0; - - // Find end timer - #if defined(TCB3) - TCB_t *timer_B_end = (TCB_t *)&TCB3; - #elif defined(TCB2) - TCB_t *timer_B_end = (TCB_t *)&TCB2; - #elif defined(TCB1) - TCB_t *timer_B_end = (TCB_t *)&TCB1; - #else - TCB_t *timer_B_end = (TCB_t *)&TCB0; - #endif - - // Timer B Setup loop for TCB[0:end] - do - { - // 8 bit PWM mode, but do not enable output yet, will do in analogWrite() - timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc); - - // Assign 8-bit period - timer_B->CCMPL = PWM_TIMER_PERIOD; - - // default duty 50%, set when output enabled - timer_B->CCMPH = PWM_TIMER_COMPARE; - - // Use TCA clock (250kHz) and enable - // (sync update commented out, might try to synchronize later - timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) - //|(TCB_SYNCUPD_bm) - |(TCB_ENABLE_bm); - - // Increment pointer to next TCB instance - timer_B++; - - // Stop when pointing to TCB3 - } while (timer_B <= timer_B_end); - - // Stuff for synchronizing PWM timers -// // Restart TCA to sync TCBs -// // should not be needed -// TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESTART_gc; -// TCA0.SINGLE.CTRLECLR = TCA_SINGLE_CMD_RESTART_gc; -// -// timer_B = (TCB_t *)&TCB0; -// -// // TCB are sync to TCA, remove setting -// for (uint8_t digitial_pin_timer = (TIMERB0 - TIMERB0); -// digitial_pin_timer < (TIMERB3 - TIMERB0); -// digitial_pin_timer++) -// { -// // disable sync with tca -// timer_B->CTRLA &= ~ (TCB_SYNCUPD_bm); -// -// // Add offset to register -// timer_B++; -// -// } -} - -FORCE_INLINE bool isDoubleBondedActive(uint8_t pin) { - (void)pin; - - /* Check if TWI is operating on double bonded pin (Master Enable is high - in both Master and Slave mode for bus error detection, so this can - indicate an active state for Wire) */ - //if(((pin == PIN_A4) || (pin == PIN_A5)) && (TWI0.MCTRLA & TWI_ENABLE_bm)) return true; - - /* Special check for SPI_SS double bonded pin -- no action if SPI is active - (Using SPI Enable bit as indicator of SPI activity) */ - //if((pin == 10) && (SPI0.CTRLA & SPI_ENABLE_bm)) return true; - - return false; -} - -void initVariant() { -// Not used -} diff --git a/megaavr/variants/40pin-standard/pins_arduino.h b/megaavr/variants/40pin-standard/pins_arduino.h new file mode 100644 index 0000000..f3a2058 --- /dev/null +++ b/megaavr/variants/40pin-standard/pins_arduino.h @@ -0,0 +1,447 @@ +/****************************************************| +| 40-PIN STANDARD PINOUT | +| https://github.com/MCUdude/MegaCoreX | +| | +| COMPATIBLE WITH: | +| ATmega4809 | +| | +| Note that this pinout is not directly compatible | +| with the UNO Wifi Rev2 hardware without performing | +| pinswaps. This pinout is supposed to be as close | +| to the metal as possible. The only peripherals | +| that are swapped to other pins by default are the | +| PWM outputs. | +| | +|****************************************************/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "timers.h" + +#define MEGACOREX +#define MCUDUDE_MEGACOREX + +#define MEGACOREX_DEFAULT_40PIN_PINOUT +#define __AVR_ATmegax09__ + +// Pin macros +#define PIN_PA0 0 +#define PIN_PA1 1 +#define PIN_PA2 2 +#define PIN_PA3 3 +#define PIN_PA4 4 +#define PIN_PA5 5 +#define PIN_PA6 6 +#define PIN_PA7 7 +#define PIN_PC0 8 +#define PIN_PC1 9 +#define PIN_PC2 10 +#define PIN_PC3 11 +#define PIN_PC4 12 +#define PIN_PC5 13 +#define PIN_PD0 14 +#define PIN_PD1 15 +#define PIN_PD2 16 +#define PIN_PD3 17 +#define PIN_PD4 18 +#define PIN_PD5 19 +#define PIN_PD6 20 +#define PIN_PD7 21 +#define PIN_PE0 22 +#define PIN_PE1 23 +#define PIN_PE2 24 +#define PIN_PE3 25 +#define PIN_PF0 26 +#define PIN_PF1 27 +#define PIN_PF2 28 +#define PIN_PF3 29 +#define PIN_PF4 30 +#define PIN_PF5 31 +#define PIN_PF6 32 + +#define PINS_COUNT 33 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 16 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 +#define NUM_SPI_PINS 3 +#define NUM_TOTAL_FREE_PINS PINS_COUNT +#define NUM_TOTAL_PINS PINS_COUNT +#define ANALOG_INPUT_OFFSET 14 +#define LED_BUILTIN PIN_PA7 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) ((p < 14) ? (p) : ((p) >= PIN_PD0 && (p) <= PIN_PE3) ? ((p) - ANALOG_INPUT_OFFSET) : ((p) >= PIN_PF2 && (p) <= PIN_PF5) ? ((p) - 2 - ANALOG_INPUT_OFFSET) : NOT_A_PIN) +#define digitalOrAnalogPinToDigital(p) ((p <= 11) ? ((p) + ANALOG_INPUT_OFFSET) : ((p) <= 15) ? ((p) + ANALOG_INPUT_OFFSET + 2) : (((p) >= 26 && (p) <= 31)) ? (p) : NOT_A_PIN) + +// Timer to use for millis/micros +#if !defined(MILLIS_USE_TIMERB0) || !defined(MILLIS_USE_TIMERB1) || !defined(MILLIS_USE_TIMERB2) || !defined(MILLIS_USE_TIMERB3) +#define MILLIS_USE_TIMERB2 // Use TCB2 for millis generation +#endif + +// PWM pins +#if defined(MILLIS_USE_TIMERB0) + #define digitalPinHasPWM(p) (((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF5)) +#elif defined(MILLIS_USE_TIMERB1) + #define digitalPinHasPWM(p) (((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4)) +#elif defined(MILLIS_USE_TIMERB2) + #define digitalPinHasPWM(p) (((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4) || ((p) == PIN_PF5)) +#else // default to MILLIS_USE_TIMERB3 + #define digitalPinHasPWM(p) (((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4) || ((p) == PIN_PF5)) +#endif + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, + TCB_3 = 9, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTE = 0x44, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_TCB3_PC1 = 0x31, + ROUTE_UNTOUCHED = 0x80, +}; + +#endif + +// Timer pin swaps +#define TCA0_PINS PORTMUX_TCA0_PORTC_gc // TCA0 output on PC[0:5] +#define TCB0_PINS PORTMUX_TCB0_bm // TCB0 output on PF4 instead of PA2 +#define TCB1_PINS PORTMUX_TCB1_bm // TCB1 output on PF5 instead of PA3 +#define TCB2_PINS PORTMUX_TCB2_bm // TCB2 output on PB4 instead of PC0 +#define TCB3_PINS 0x00 // TCB3 output on PB5 instead of PC1 + +// SPI 0 +// No pinswap enabled by default +// Pinswap 2 not available +#define SPI_INTERFACES_COUNT 1 +#define SPI_MUX PORTMUX_SPI0_DEFAULT_gc +#define SPI_MUX_PINSWAP_1 PORTMUX_SPI0_ALT1_gc +#define SPI_MUX_PINSWAP_2 PORTMUX_SPI0_ALT2_gc +#define PIN_SPI_MISO PIN_PA5 +#define PIN_SPI_SCK PIN_PA6 +#define PIN_SPI_MOSI PIN_PA4 +#define PIN_SPI_SS PIN_PA7 +#define PIN_SPI_MISO_PINSWAP_1 PIN_PC1 +#define PIN_SPI_SCK_PINSWAP_1 PIN_PC2 +#define PIN_SPI_MOSI_PINSWAP_1 PIN_PC0 +#define PIN_SPI_SS_PINSWAP_1 PIN_PC3 +#define PIN_SPI_MISO_PINSWAP_2 PIN_PE1 +#define PIN_SPI_SCK_PINSWAP_2 PIN_PE2 +#define PIN_SPI_MOSI_PINSWAP_2 PIN_PE0 +#define PIN_SPI_SS_PINSWAP_2 PIN_PE3 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// TWI 0 +// No pinswap enabled by default +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define TWI_MUX_PINSWAP PORTMUX_TWI0_ALT2_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +#define PIN_WIRE_SDA_PINSWAP_1 PIN_PC2 +#define PIN_WIRE_SCL_PINSWAP_1 PIN_PC3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// USART 0 +// No pinswap by default +#define HWSERIAL0 &USART0 +#define HWSERIAL0_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL0_TX PIN_PA0 +#define PIN_HWSERIAL0_RX PIN_PA1 +#define PIN_HWSERIAL0_XCK PIN_PA2 +#define PIN_HWSERIAL0_XDIR PIN_PA3 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PA7 + +// USART1 +// No pinswap by default +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_DEFAULT_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_ALT1_gc +#define PIN_HWSERIAL1_TX PIN_PC0 +#define PIN_HWSERIAL1_RX PIN_PC1 +#define PIN_HWSERIAL1_XCK PIN_PC2 +#define PIN_HWSERIAL1_XDIR PIN_PC3 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_PC4 +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_PC5 + +// USART 2 +// No pinswap by default +#define HWSERIAL2 &USART2 +#define HWSERIAL2_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART2_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART2_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PF0 +#define PIN_HWSERIAL2_RX PIN_PF1 +#define PIN_HWSERIAL2_XCK PIN_PF2 +#define PIN_HWSERIAL2_XDIR PIN_PF3 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PF4 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PF5 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PF6 + +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PD4 +#define PIN_A5 PIN_PD5 +#define PIN_A6 PIN_PD6 +#define PIN_A7 PIN_PD7 +#define PIN_A8 PIN_PE0 +#define PIN_A9 PIN_PE1 +#define PIN_A10 PIN_PE2 +#define PIN_A11 PIN_PE3 +#define PIN_A12 PIN_PF2 +#define PIN_A13 PIN_PF3 +#define PIN_A14 PIN_PF4 +#define PIN_A15 PIN_PF5 +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; +static const uint8_t A8 = PIN_A8; +static const uint8_t A9 = PIN_A9; +static const uint8_t A10 = PIN_A10; +static const uint8_t A11 = PIN_A11; +static const uint8_t A12 = PIN_A12; +static const uint8_t A13 = PIN_A13; +static const uint8_t A14 = PIN_A14; +static const uint8_t A15 = PIN_A15; + +#ifdef ARDUINO_MAIN + +const uint8_t digital_pin_to_port[] = { + PA, // 0 PA0/USART0_Tx/CLKIN + PA, // 1 PA1/USART0_Rx + PA, // 2 PA2/SDA + PA, // 3 PA3/SCL + PA, // 4 PA4/MOSI + PA, // 5 PA5/MISO + PA, // 6 PA6/SCK + PA, // 7 PA7/SS/CLKOUT/LED_BUILTIN + PC, // 8 PC0/USART1_Tx + PC, // 9 PC1/USART1_Rx + PC, // 10 PC2 + PC, // 11 PC3 + PC, // 12 PC4 + PC, // 13 PC5 + PD, // 14 PD0/AIN0 + PD, // 15 PD1/AIN1 + PD, // 16 PD2/AIN2 + PD, // 17 PD3/AIN3 + PD, // 18 PD4/AIN4 + PD, // 19 PD5/AIN5 + PD, // 20 PD6/AIN6 + PD, // 21 PD7/AIN7/AREF + PE, // 22 PE0/AIN8 + PE, // 23 PE1/AIN9 + PE, // 24 PE2/AIN10 + PE, // 25 PE3/AIN11 + PF, // 26 PF0/USART2_Tx/TOSC1 + PF, // 27 PF1/USART2_Rx/TOSC2 + PF, // 28 PF2/AIN12 + PF, // 29 PF3/AIN13 + PF, // 30 PF4/AIN14 + PF, // 31 PF5/AIN15 + PF // 32 PF6 RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_position[] = { + PIN0_bp, // 0 PIN_bp0/USART0_Tx/CLKIN + PIN1_bp, // 1 PA1/USART0_Rx + PIN2_bp, // 2 PA2/SDA + PIN3_bp, // 3 PA3/SCL + PIN4_bp, // 4 PA4/MOSI + PIN5_bp, // 5 PA5/MISO + PIN6_bp, // 6 PA6/SCK + PIN7_bp, // 7 PA7/SS/CLKOUT/LED_BUILTIN + PIN0_bp, // 8 PC0/USART1_Tx + PIN1_bp, // 9 PC1/USART1_Rx + PIN2_bp, // 10 PC2 + PIN3_bp, // 11 PC3 + PIN4_bp, // 12 PC4 + PIN5_bp, // 13 PC5 + PIN0_bp, // 14 PD0/AIN0 + PIN1_bp, // 15 PD1/AIN1 + PIN2_bp, // 16 PD2/AIN2 + PIN3_bp, // 17 PD3/AIN3 + PIN4_bp, // 18 PD4/AIN4 + PIN5_bp, // 19 PD5/AIN5 + PIN6_bp, // 20 PD6/AIN6 + PIN7_bp, // 21 PD7/AIN7/AREF + PIN0_bp, // 22 PE0/AIN8 + PIN1_bp, // 23 PE1/AIN9 + PIN2_bp, // 24 PE2/AIN10 + PIN3_bp, // 25 PE3/AIN11 + PIN0_bp, // 26 PF0/USART2_Tx/TOSC1 + PIN1_bp, // 27 PF1/USART2_Rx/TOSC2 + PIN2_bp, // 28 PF2/AIN12 + PIN3_bp, // 29 PF3/AIN13 + PIN4_bp, // 30 PF4/AIN14 + PIN5_bp, // 31 PF5/AIN15 + PIN6_bp // 42 PF6 RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_mask[] = { + PIN0_bm, // 0 PIN_bp0/USART0_Tx/CLKIN + PIN1_bm, // 1 PA1/USART0_Rx + PIN2_bm, // 2 PA2/SDA + PIN3_bm, // 3 PA3/SCL + PIN4_bm, // 4 PA4/MOSI + PIN5_bm, // 5 PA5/MISO + PIN6_bm, // 6 PA6/SCK + PIN7_bm, // 7 PA7/SS/CLKOUT/LED_BUILTIN + PIN0_bm, // 8 PC0/USART1_Tx + PIN1_bm, // 9 PC1/USART1_Rx + PIN2_bm, // 10 PC2 + PIN3_bm, // 11 PC3 + PIN4_bm, // 12 PC4 + PIN5_bm, // 13 PC5 + PIN0_bm, // 14 PD0/AIN0 + PIN1_bm, // 15 PD1/AIN1 + PIN2_bm, // 16 PD2/AIN2 + PIN3_bm, // 17 PD3/AIN3 + PIN4_bm, // 18 PD4/AIN4 + PIN5_bm, // 19 PD5/AIN5 + PIN6_bm, // 20 PD6/AIN6 + PIN7_bm, // 21 PD7/AIN7/AREF + PIN0_bm, // 22 PE0/AIN8 + PIN1_bm, // 23 PE1/AIN9 + PIN2_bm, // 24 PE2/AIN10 + PIN3_bm, // 25 PE3/AIN11 + PIN0_bm, // 26 PF0/USART2_Tx/TOSC1 + PIN1_bm, // 27 PF1/USART2_Rx/TOSC2 + PIN2_bm, // 28 PF2/AIN12 + PIN3_bm, // 29 PF3/AIN13 + PIN4_bm, // 30 PF4/AIN14 + PIN5_bm, // 31 PF5/AIN15 + PIN6_bm // 32 PF6 RESET +}; + +const uint8_t digital_pin_to_timer[] = { + NOT_ON_TIMER, // 0 PA0/USART0_Tx/CLKIN + NOT_ON_TIMER, // 1 PA1/USART0_Rx + NOT_ON_TIMER, // 2 PA2/SDA + NOT_ON_TIMER, // 3 PA3/SCL + NOT_ON_TIMER, // 4 PA4/MOSI + NOT_ON_TIMER, // 5 PA5/MISO + NOT_ON_TIMER, // 6 PA6/SCK + NOT_ON_TIMER, // 7 PA7/SS/CLKOUT/LED_BUILTIN + TIMERA0, // 8 PC0/USART1_Tx + TIMERA0, // 9 PC1/USART1_Rx + TIMERA0, // 10 PC2 + TIMERA0, // 11 PC3 + TIMERA0, // 12 PC4 + TIMERA0, // 13 PC5 + NOT_ON_TIMER, // 14 PD0/AIN0 + NOT_ON_TIMER, // 15 PD1/AIN1 + NOT_ON_TIMER, // 16 PD2/AIN2 + NOT_ON_TIMER, // 17 PD3/AIN3 + NOT_ON_TIMER, // 18 PD4/AIN4 + NOT_ON_TIMER, // 19 PD5/AIN5 + NOT_ON_TIMER, // 20 PD6/AIN6 + NOT_ON_TIMER, // 21 PD7/AIN7/AREF + NOT_ON_TIMER, // 22 PE0/AIN8 + NOT_ON_TIMER, // 23 PE1/AIN9 + NOT_ON_TIMER, // 24 PE2/AIN10 + NOT_ON_TIMER, // 25 PE3/AIN11 + NOT_ON_TIMER, // 26 PF0/USART2_Tx/TOSC1 + NOT_ON_TIMER, // 27 PF1/USART2_Rx/TOSC2 + NOT_ON_TIMER, // 28 PF2/AIN12 + NOT_ON_TIMER, // 29 PF3/AIN13 +#ifdef MILLIS_USE_TIMERB0 + NOT_ON_TIMER, // 30 PF4/AIN14 +#else + TIMERB0, // 30 PF4/AIN14 +#endif +#ifdef MILLIS_USE_TIMERB1 + NOT_ON_TIMER, // 31 PF5/AIN15 +#else + TIMERB1, // 31 PF5/AIN15 +#endif + NOT_ON_TIMER // 32 PF6 RESET +}; + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial2 + + +void initVariant() __attribute__((weak)); +void initVariant() +{ + // Disable unavailable pins on the 40 pin package + PORTB.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTB.PIN1CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTB.PIN2CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTB.PIN3CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTB.PIN4CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTB.PIN5CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTC.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; + PORTC.PIN6CTRL = PORT_ISC_INPUT_DISABLE_gc; +} + +#endif diff --git a/megaavr/variants/48pin-standard/pins_arduino.h b/megaavr/variants/48pin-standard/pins_arduino.h index 8067c79..4c1e864 100644 --- a/megaavr/variants/48pin-standard/pins_arduino.h +++ b/megaavr/variants/48pin-standard/pins_arduino.h @@ -5,12 +5,14 @@ | COMPATIBLE WITH: | | ATmega4809 | | ATmega3209 | +| ATmega1609 | +| ATmega809 | | | | Note that this pinout is not directly compatible | -| with the UNO Wifi Rev2 hardware without preforming | +| with the UNO Wifi Rev2 hardware without performing | | pinswaps. This pinout is supposed to be as close | | to the metal as possible. The only peripherals | -| that is swapped to other pins by default are the | +| that are swapped to other pins by default are the | | PWM outputs. | | | |****************************************************/ @@ -21,131 +23,247 @@ #include #include "timers.h" -#define DEFAULT_48PIN_PINOUT +#define MEGACOREX +#define MCUDUDE_MEGACOREX -#define NUM_DIGITAL_PINS 41 -#define NUM_ANALOG_INPUTS 16 -#define NUM_RESERVED_PINS 0 // With great power comes great responsibility -#define NUM_INTERNALLY_USED_PINS 0 // (2 x Chip select + 2 x UART + 4 x IO + LED_BUILTIN + 1 unused pin) -#define NUM_I2C_PINS 2 // (SDA / SCL) -#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) -#define NUM_TOTAL_FREE_PINS (NUM_DIGITAL_PINS) -#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS) -#define ANALOG_INPUT_OFFSET 0 -#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : (p) - 22) // The user will have to use A0 - A15, NOT 0 - 15 +#define MEGACOREX_DEFAULT_48PIN_PINOUT +#define __AVR_ATmegax09__ -#define MILLIS_USE_TIMERB0 // Use timerb0 for millis generation +// Arduino pin macros +#define PIN_PA0 0 +#define PIN_PA1 1 +#define PIN_PA2 2 +#define PIN_PA3 3 +#define PIN_PA4 4 +#define PIN_PA5 5 +#define PIN_PA6 6 +#define PIN_PA7 7 +#define PIN_PB0 8 +#define PIN_PB1 9 +#define PIN_PB2 10 +#define PIN_PB3 11 +#define PIN_PB4 12 +#define PIN_PB5 13 +#define PIN_PC0 14 +#define PIN_PC1 15 +#define PIN_PC2 16 +#define PIN_PC3 17 +#define PIN_PC4 18 +#define PIN_PC5 19 +#define PIN_PC6 20 +#define PIN_PC7 21 +#define PIN_PD0 22 +#define PIN_PD1 23 +#define PIN_PD2 24 +#define PIN_PD3 25 +#define PIN_PD4 26 +#define PIN_PD5 27 +#define PIN_PD6 28 +#define PIN_PD7 29 +#define PIN_PE0 30 +#define PIN_PE1 31 +#define PIN_PE2 32 +#define PIN_PE3 33 +#define PIN_PF0 34 +#define PIN_PF1 35 +#define PIN_PF2 36 +#define PIN_PF3 37 +#define PIN_PF4 38 +#define PIN_PF5 39 +#define PIN_PF6 40 -#define EXTERNAL_NUM_INTERRUPTS (NUM_TOTAL_PINS) +#define PINS_COUNT 41 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 16 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 +#define NUM_SPI_PINS 3 +#define NUM_TOTAL_FREE_PINS NUM_DIGITAL_PINS +#define NUM_TOTAL_PINS NUM_DIGITAL_PINS +#define ANALOG_INPUT_OFFSET 22 +#define LED_BUILTIN PIN_PA7 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : ((p) >= 22 && (p) <= 33) ? ((p) - ANALOG_INPUT_OFFSET) : ((p) >= 36 && (p) <=39) ? ((p) - 2 - ANALOG_INPUT_OFFSET) : NOT_A_PIN) +#define digitalOrAnalogPinToDigital(p) ((p <= 11) ? ((p) + ANALOG_INPUT_OFFSET) : ((p) <= 15) ? ((p) + ANALOG_INPUT_OFFSET + 2) : (((p) >= 22 && (p) <= 33) || ((p) >= 36 && (p) <= 39)) ? (p) : NOT_A_PIN) -#define digitalPinHasPWM(p) ((p) == 16 || (p) == 17 || (p) == 18 || (p) == 19 || (p) == 38 || (p) == 39) +// Timer to use for millis/micros +#if !defined(MILLIS_USE_TIMERB0) || !defined(MILLIS_USE_TIMERB1) || !defined(MILLIS_USE_TIMERB2) || !defined(MILLIS_USE_TIMERB3) +#define MILLIS_USE_TIMERB2 // Use TCB2 if nothing else if defined +#endif + +// PWM pins +#if defined(MILLIS_USE_TIMERB0) + #define digitalPinHasPWM(p) (((p) == PIN_PB4) || ((p) == PIN_PB5) || ((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || \ + ((p) == PIN_PC3) || ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF5)) +#elif defined(MILLIS_USE_TIMERB1) + #define digitalPinHasPWM(p) (((p) == PIN_PB4) || ((p) == PIN_PB5) || ((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || \ + ((p) == PIN_PC3) || ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4)) +#elif defined(MILLIS_USE_TIMERB2) + #define digitalPinHasPWM(p) (((p) == PIN_PB5) || ((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4) || ((p) == PIN_PF5)) +#else // default to MILLIS_USE_TIMERB3 + #define digitalPinHasPWM(p) (((p) == PIN_PB4) || ((p) == PIN_PC0) || ((p) == PIN_PC1) || ((p) == PIN_PC2) || ((p) == PIN_PC3) || \ + ((p) == PIN_PC4) || ((p) == PIN_PC5) || ((p) == PIN_PF4) || ((p) == PIN_PF5)) +#endif + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, + TCB_3 = 9, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTB = 0x41, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTE = 0x44, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_TCB2_PB4 = 0x21, + ROUTE_TCB3_PB5 = 0x30, + ROUTE_TCB3_PC1 = 0x31, + ROUTE_UNTOUCHED = 0x80, +}; +#endif + +// Timer pin swaps +#define TCA0_PINS PORTMUX_TCA0_PORTC_gc // TCA0 output on PC[0:5] +#define TCB0_PINS PORTMUX_TCB0_bm // TCB0 output on PF4 instead of PA2 +#define TCB1_PINS PORTMUX_TCB1_bm // TCB1 output on PF5 instead of PA3 +#define TCB2_PINS PORTMUX_TCB2_bm // TCB2 output on PB4 instead of PC0 +#define TCB3_PINS 0x00 // TCB3 output on PB5 instead of PC1 // SPI 0 // No pinswap enabled by default -// Pinswap 2 not available #define SPI_INTERFACES_COUNT 1 -#define SPI_MUX (PORTMUX_SPI0_DEFAULT_gc) -#define SPI_MUX_PINSWAP_1 (PORTMUX_SPI0_ALT1_gc) -#define SPI_MUX_PINSWAP_2 (PORTMUX_SPI0_ALT2_gc) -#define PIN_SPI_MISO (5) -#define PIN_SPI_SCK (6) -#define PIN_SPI_MOSI (4) -#define PIN_SPI_SS (7) -#define PIN_SPI_MISO_PINSWAP_1 (15) -#define PIN_SPI_SCK_PINSWAP_1 (16) -#define PIN_SPI_MOSI_PINSWAP_1 (14) -#define PIN_SPI_SS_PINSWAP_1 (17) -#define PIN_SPI_MISO_PINSWAP_2 (31) -#define PIN_SPI_SCK_PINSWAP_2 (32) -#define PIN_SPI_MOSI_PINSWAP_2 (30) -#define PIN_SPI_SS_PINSWAP_2 (33) -static const uint8_t SS = PIN_SPI_SS; -static const uint8_t MOSI = PIN_SPI_MOSI; -static const uint8_t MISO = PIN_SPI_MISO; -static const uint8_t SCK = PIN_SPI_SCK; +#define SPI_MUX PORTMUX_SPI0_DEFAULT_gc +#define SPI_MUX_PINSWAP_1 PORTMUX_SPI0_ALT1_gc +#define SPI_MUX_PINSWAP_2 PORTMUX_SPI0_ALT2_gc +#define PIN_SPI_MISO PIN_PA5 +#define PIN_SPI_SCK PIN_PA6 +#define PIN_SPI_MOSI PIN_PA4 +#define PIN_SPI_SS PIN_PA7 +#define PIN_SPI_MISO_PINSWAP_1 PIN_PC1 +#define PIN_SPI_SCK_PINSWAP_1 PIN_PC2 +#define PIN_SPI_MOSI_PINSWAP_1 PIN_PC0 +#define PIN_SPI_SS_PINSWAP_1 PIN_PC3 +#define PIN_SPI_MISO_PINSWAP_2 PIN_PE1 +#define PIN_SPI_SCK_PINSWAP_2 PIN_PE2 +#define PIN_SPI_MOSI_PINSWAP_2 PIN_PE0 +#define PIN_SPI_SS_PINSWAP_2 PIN_PE3 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; // TWI 0 // No pinswap enabled by default -#define TWI_MUX (PORTMUX_TWI0_DEFAULT_gc) -#define TWI_MUX_PINSWAP (PORTMUX_TWI0_ALT2_gc) -#define PIN_WIRE_SDA (2) -#define PIN_WIRE_SCL (3) -#define PIN_WIRE_SDA_PINSWAP_1 (16) -#define PIN_WIRE_SCL_PINSWAP_1 (17) -static const uint8_t SDA = PIN_WIRE_SDA; -static const uint8_t SCL = PIN_WIRE_SCL; - -#define LED_BUILTIN 39 +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define TWI_MUX_PINSWAP PORTMUX_TWI0_ALT2_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +#define PIN_WIRE_SDA_PINSWAP_1 PIN_PC2 +#define PIN_WIRE_SCL_PINSWAP_1 PIN_PC3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; // USART 0 // No pinswap by default -#define HWSERIAL0 (&USART0) -#define HWSERIAL0_DRE_VECTOR (USART0_DRE_vect) -#define HWSERIAL0_DRE_VECTOR_NUM (USART0_DRE_vect_num) -#define HWSERIAL0_RXC_VECTOR (USART0_RXC_vect) -#define HWSERIAL0_MUX (PORTMUX_USART0_DEFAULT_gc) -#define HWSERIAL0_MUX_PINSWAP_1 (PORTMUX_USART0_ALT1_gc) -#define PIN_WIRE_HWSERIAL0_TX (0) -#define PIN_WIRE_HWSERIAL0_RX (1) -#define PIN_WIRE_HWSERIAL0_TX_PINSWAP_1 (4) -#define PIN_WIRE_HWSERIAL0_RX_PINSWAP_1 (5) +#define HWSERIAL0 &USART0 +#define HWSERIAL0_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL0_TX PIN_PA0 +#define PIN_HWSERIAL0_RX PIN_PA1 +#define PIN_HWSERIAL0_XCK PIN_PA2 +#define PIN_HWSERIAL0_XDIR PIN_PA3 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PA7 // USART1 // No pinswap by default -#define HWSERIAL1 (&USART1) -#define HWSERIAL1_DRE_VECTOR (USART1_DRE_vect) -#define HWSERIAL1_DRE_VECTOR_NUM (USART1_DRE_vect_num) -#define HWSERIAL1_RXC_VECTOR (USART1_RXC_vect) -#define HWSERIAL1_MUX (PORTMUX_USART1_DEFAULT_gc) -#define HWSERIAL1_MUX_PINSWAP_1 (PORTMUX_USART1_ALT1_gc) -#define PIN_WIRE_HWSERIAL1_TX (12) -#define PIN_WIRE_HWSERIAL1_RX (13) -#define PIN_WIRE_HWSERIAL1_TX_PINSWAP_1 (14) -#define PIN_WIRE_HWSERIAL1_RX_PINSWAP_1 (15) +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_DEFAULT_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_ALT1_gc +#define PIN_HWSERIAL1_TX PIN_PC0 +#define PIN_HWSERIAL1_RX PIN_PC1 +#define PIN_HWSERIAL1_XCK PIN_PC2 +#define PIN_HWSERIAL1_XDIR PIN_PC3 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_PC4 +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_PC5 +#define PIN_HWSERIAL1_XCK_PINSWAP_1 PIN_PC6 +#define PIN_HWSERIAL1_XDIR_PINSWAP_1 PIN_PC7 // USART 2 // No pinswap by default -#define HWSERIAL2 (&USART2) -#define HWSERIAL2_DRE_VECTOR (USART2_DRE_vect) -#define HWSERIAL2_DRE_VECTOR_NUM (USART2_DRE_vect_num) -#define HWSERIAL2_RXC_VECTOR (USART2_RXC_vect) -#define HWSERIAL2_MUX (PORTMUX_USART2_DEFAULT_gc) -#define HWSERIAL2_MUX_PINSWAP_1 (PORTMUX_USART2_ALT1_gc) -#define PIN_WIRE_HWSERIAL2_TX (34) -#define PIN_WIRE_HWSERIAL2_RX (35) -#define PIN_WIRE_HWSERIAL2_TX_PINSWAP_1 (38) -#define PIN_WIRE_HWSERIAL2_RX_PINSWAP_1 (39) +#define HWSERIAL2 &USART2 +#define HWSERIAL2_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART2_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART2_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PF0 +#define PIN_HWSERIAL2_RX PIN_PF1 +#define PIN_HWSERIAL2_XCK PIN_PF2 +#define PIN_HWSERIAL2_XDIR PIN_PF3 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PF4 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PF5 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PF6 // USART 3 // No pinswap by default -#define HWSERIAL3 (&USART3) -#define HWSERIAL3_DRE_VECTOR (USART3_DRE_vect) -#define HWSERIAL3_DRE_VECTOR_NUM (USART3_DRE_vect_num) -#define HWSERIAL3_RXC_VECTOR (USART3_RXC_vect) -#define HWSERIAL3_MUX (PORTMUX_USART3_DEFAULT_gc) -#define HWSERIAL3_MUX_PINSWAP_1 (PORTMUX_USART3_ALT1_gc) -#define PIN_WIRE_HWSERIAL3_TX (8) -#define PIN_WIRE_HWSERIAL3_RX (9) -#define PIN_WIRE_HWSERIAL3_TX_PINSWAP_1 (12) -#define PIN_WIRE_HWSERIAL3_RX_PINSWAP_1 (13) - -#define PIN_A0 (22) -#define PIN_A1 (23) -#define PIN_A2 (24) -#define PIN_A3 (25) -#define PIN_A4 (26) -#define PIN_A5 (27) -#define PIN_A6 (28) -#define PIN_A7 (29) -#define PIN_A8 (30) -#define PIN_A9 (31) -#define PIN_A10 (32) -#define PIN_A11 (33) -#define PIN_A12 (36) -#define PIN_A13 (37) -#define PIN_A14 (38) -#define PIN_A15 (39) +#define HWSERIAL3 &USART3 +#define HWSERIAL3_DRE_VECTOR USART3_DRE_vect +#define HWSERIAL3_DRE_VECTOR_NUM USART3_DRE_vect_num +#define HWSERIAL3_RXC_VECTOR USART3_RXC_vect +#define HWSERIAL3_MUX PORTMUX_USART3_DEFAULT_gc +#define HWSERIAL3_MUX_PINSWAP_1 PORTMUX_USART3_ALT1_gc +#define PIN_HWSERIAL3_TX PIN_PB0 +#define PIN_HWSERIAL3_RX PIN_PB1 +#define PIN_HWSERIAL3_XCK PIN_PB2 +#define PIN_HWSERIAL3_XDIR PIN_PB3 +#define PIN_HWSERIAL3_TX_PINSWAP_1 PIN_PB4 +#define PIN_HWSERIAL3_RX_PINSWAP_1 PIN_PB5 +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PD4 +#define PIN_A5 PIN_PD5 +#define PIN_A6 PIN_PD6 +#define PIN_A7 PIN_PD7 +#define PIN_A8 PIN_PE0 +#define PIN_A9 PIN_PE1 +#define PIN_A10 PIN_PE2 +#define PIN_A11 PIN_PE3 +#define PIN_A12 PIN_PF2 +#define PIN_A13 PIN_PF3 +#define PIN_A14 PIN_PF4 +#define PIN_A15 PIN_PF5 static const uint8_t A0 = PIN_A0; static const uint8_t A1 = PIN_A1; static const uint8_t A2 = PIN_A2; @@ -163,12 +281,9 @@ static const uint8_t A13 = PIN_A13; static const uint8_t A14 = PIN_A14; static const uint8_t A15 = PIN_A15; -#define PINS_COUNT (41u) - - #ifdef ARDUINO_MAIN -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PA, // 0 PA0/USART0_Tx/CLKIN PA, // 1 PA1/USART0_Rx PA, // 2 PA2/SDA @@ -176,19 +291,19 @@ const uint8_t PROGMEM digital_pin_to_port[] = { PA, // 4 PA4/MOSI PA, // 5 PA5/MISO PA, // 6 PA6/SCK - PA, // 7 PA7/SS/CLKOUT + PA, // 7 PA7/SS/CLKOUT/LED_BUILTIN PB, // 8 PB0/USART3_Tx PB, // 9 PB1/USART3_Rx PB, // 10 PB2 PB, // 11 PB3 - PB, // 12 PB4 + PB, // 12 PB4/(TCB2 PWM) PB, // 13 PB5 PC, // 14 PC0/USART1_Tx PC, // 15 PC1/USART1_Rx - PC, // 16 PC2/TCA0 PWM - PC, // 17 PC3/TCA0 PWM - PC, // 18 PC4/TCA0 PWM - PC, // 19 PC5/TCA0 PWM + PC, // 16 PC2 + PC, // 17 PC3 + PC, // 18 PC4 + PC, // 19 PC5 PC, // 20 PC6 PC, // 21 PC7 PD, // 22 PD0/AIN0 @@ -207,13 +322,13 @@ const uint8_t PROGMEM digital_pin_to_port[] = { PF, // 35 PF1/USART2_Rx/TOSC2 PF, // 36 PF2/AIN12 PF, // 37 PF3/AIN13 - PF, // 38 PF4/AIN14/TCB0 PWM - PF, // 39 PF5/AIN15/TCB1 PWM/LED_BUILTIN + PF, // 38 PF4/AIN14 + PF, // 39 PF5/AIN15 PF // 40 PF6 RESET }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN0_bp, // 0 PIN_bp0/USART0_Tx/CLKIN PIN1_bp, // 1 PA1/USART0_Rx PIN2_bp, // 2 PA2/SDA @@ -221,19 +336,19 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { PIN4_bp, // 4 PA4/MOSI PIN5_bp, // 5 PA5/MISO PIN6_bp, // 6 PA6/SCK - PIN7_bp, // 7 PA7/SS/CLKOUT + PIN7_bp, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bp, // 8 PB0/USART3_Tx PIN1_bp, // 9 PB1/USART3_Rx PIN2_bp, // 10 PB2 PIN3_bp, // 11 PB3 - PIN4_bp, // 12 PB4 + PIN4_bp, // 12 PB4/(TCB2 PWM) PIN5_bp, // 13 PB5 PIN0_bp, // 14 PC0/USART1_Tx PIN1_bp, // 15 PC1/USART1_Rx - PIN2_bp, // 16 PC2/TCA0 PWM - PIN3_bp, // 17 PC3/TCA0 PWM - PIN4_bp, // 18 PC4/TCA0 PWM - PIN5_bp, // 19 PC5/TCA0 PWM + PIN2_bp, // 16 PC2 + PIN3_bp, // 17 PC3 + PIN4_bp, // 18 PC4 + PIN5_bp, // 19 PC5 PIN6_bp, // 20 PC6 PIN7_bp, // 21 PC7 PIN0_bp, // 22 PD0/AIN0 @@ -252,13 +367,13 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { PIN1_bp, // 35 PF1/USART2_Rx/TOSC2 PIN2_bp, // 36 PF2/AIN12 PIN3_bp, // 37 PF3/AIN13 - PIN4_bp, // 38 PF4/AIN14/TCB0 PWM - PIN5_bp, // 39 PF5/AIN15/TCB1 PWM/LED_BUILTIN + PIN4_bp, // 38 PF4/AIN14 + PIN5_bp, // 39 PF5/AIN15 PIN6_bp // 40 PF6 RESET }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { +const uint8_t digital_pin_to_bit_mask[] = { PIN0_bm, // 0 PIN_bp0/USART0_Tx/CLKIN PIN1_bm, // 1 PA1/USART0_Rx PIN2_bm, // 2 PA2/SDA @@ -266,19 +381,19 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN4_bm, // 4 PA4/MOSI PIN5_bm, // 5 PA5/MISO PIN6_bm, // 6 PA6/SCK - PIN7_bm, // 7 PA7/SS/CLKOUT + PIN7_bm, // 7 PA7/SS/CLKOUT/LED_BUILTIN PIN0_bm, // 8 PB0/USART3_Tx PIN1_bm, // 9 PB1/USART3_Rx PIN2_bm, // 10 PB2 PIN3_bm, // 11 PB3 - PIN4_bm, // 12 PB4 + PIN4_bm, // 12 PB4/(TCB2 PWM) PIN5_bm, // 13 PB5 PIN0_bm, // 14 PC0/USART1_Tx PIN1_bm, // 15 PC1/USART1_Rx - PIN2_bm, // 16 PC2/TCA0 PWM - PIN3_bm, // 17 PC3/TCA0 PWM - PIN4_bm, // 18 PC4/TCA0 PWM - PIN5_bm, // 19 PC5/TCA0 PWM + PIN2_bm, // 16 PC2 + PIN3_bm, // 17 PC3 + PIN4_bm, // 18 PC4 + PIN5_bm, // 19 PC5 PIN6_bm, // 20 PC6 PIN7_bm, // 21 PC7 PIN0_bm, // 22 PD0/AIN0 @@ -297,12 +412,12 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN1_bm, // 35 PF1/USART2_Rx/TOSC2 PIN2_bm, // 36 PF2/AIN12 PIN3_bm, // 37 PF3/AIN13 - PIN4_bm, // 38 PF4/AIN14/TCB0 PWM - PIN5_bm, // 39 PF5/AIN15/TCB1 PWM/LED_BUILTIN + PIN4_bm, // 38 PF4/AIN14 + PIN5_bm, // 39 PF5/AIN15 PIN6_bm // 40 PF6 RESET }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PA0/USART0_Tx/CLKIN NOT_ON_TIMER, // 1 PA1/USART0_Rx NOT_ON_TIMER, // 2 PA2/SDA @@ -310,19 +425,27 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { NOT_ON_TIMER, // 4 PA4/MOSI NOT_ON_TIMER, // 5 PA5/MISO NOT_ON_TIMER, // 6 PA6/SCK - NOT_ON_TIMER, // 7 PA7/SS/CLKOUT + NOT_ON_TIMER, // 7 PA7/SS/CLKOUT/LED_BUILTIN NOT_ON_TIMER, // 8 PB0/USART3_Tx NOT_ON_TIMER, // 9 PB1/USART3_Rx NOT_ON_TIMER, // 10 PB2 NOT_ON_TIMER, // 11 PB3 +#if !defined(MILLIS_USE_TIMERB2) + TIMERB2, // 12 PB4 +#else NOT_ON_TIMER, // 12 PB4 +#endif +#if !defined(MILLIS_USE_TIMERB3) + TIMERB3, // 13 PB5 +#else NOT_ON_TIMER, // 13 PB5 - NOT_ON_TIMER, // 14 PC0/USART1_Tx - NOT_ON_TIMER, // 15 PC1/USART1_Rx - TIMERA0, // 16 PC2/TCA0 PWM - TIMERA0, // 17 PC3/TCA0 PWM - TIMERA0, // 18 PC4/TCA0 PWM - TIMERA0, // 19 PC5/TCA0 PWM +#endif + TIMERA0, // 14 PC0/USART1_Tx + TIMERA0, // 15 PC1/USART1_Rx + TIMERA0, // 16 PC2 + TIMERA0, // 17 PC3 + TIMERA0, // 18 PC4 + TIMERA0, // 19 PC5 NOT_ON_TIMER, // 20 PC6 NOT_ON_TIMER, // 21 PC7 NOT_ON_TIMER, // 22 PD0/AIN0 @@ -341,12 +464,42 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { NOT_ON_TIMER, // 35 PF1/USART2_Rx/TOSC2 NOT_ON_TIMER, // 36 PF2/AIN12 NOT_ON_TIMER, // 37 PF3/AIN13 - TIMERB0, // 38 PF4/AIN14/TCB0 PWM - TIMERB1, // 39 PF5/AIN15/TCB1 PWM/LED_BUILTIN +#if !defined(MILLIS_USE_TIMERB0) + TIMERB0, // 38 PF4/AIN14 +#else + NOT_ON_TIMER, // 38 PF4/AIN14 +#endif +#if !defined(MILLIS_USE_TIMERB1) + TIMERB1, // 39 PF5/AIN15 +#else + NOT_ON_TIMER, // 39 PF5/AIN15 +#endif NOT_ON_TIMER // 40 PF6 RESET }; - #endif +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial2 +#define SERIAL_PORT_HARDWARE_OPEN2 Serial3 + +void initVariant() __attribute__((weak)); +void initVariant() { } + #endif diff --git a/megaavr/variants/48pin-standard/timers.h b/megaavr/variants/48pin-standard/timers.h deleted file mode 100644 index 438e79f..0000000 --- a/megaavr/variants/48pin-standard/timers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __TIMERS_H__ -#define __TIMERS_H__ - -#define TIME_TRACKING_TIMER_PERIOD 0xFF -#define TIME_TRACKING_TICKS_PER_OVF (TIME_TRACKING_TIMER_PERIOD + 1) // Timer ticks per overflow of TCB3 -#define TIME_TRACKING_TIMER_DIVIDER 64 // Clock divider for TCB0 -#define TIME_TRACKING_CYCLES_PER_OVF (TIME_TRACKING_TICKS_PER_OVF * TIME_TRACKING_TIMER_DIVIDER) - -#define PWM_TIMER_PERIOD 0xFF // For frequency -#define PWM_TIMER_COMPARE 0x80 // For duty cycle - -#endif \ No newline at end of file diff --git a/megaavr/variants/48pin-standard/variant.c b/megaavr/variants/48pin-standard/variant.c deleted file mode 100644 index 0951a66..0000000 --- a/megaavr/variants/48pin-standard/variant.c +++ /dev/null @@ -1,118 +0,0 @@ -#include - -#include "pins_arduino.h" -#include "api/Common.h" - -#define FORCE_INLINE __attribute__((always_inline)) inline - -void setup_timers() { - - // TYPE A TIMER - - // PORTMUX setting for TCA -> outputs [2:5] point to PORTC pins [2:5] - PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTC_gc; - - // Setup timers for single slope PWM, but do not enable, will do in analogWrite() - TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; - - // Period setting, 16 bit register but val resolution is 8 bit - TCA0.SINGLE.PER = PWM_TIMER_PERIOD; - - // Default duty 50%, will re-assign in analogWrite() - TCA0.SINGLE.CMP0BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP1BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP2BUF = PWM_TIMER_COMPARE; - - // Use DIV64 prescaler (giving 250kHz clock), enable TCA timer - TCA0.SINGLE.CTRLA = (TCA_SINGLE_CLKSEL_DIV64_gc) | (TCA_SINGLE_ENABLE_bm); - - // TYPE B TIMERS - - // Setup TCB0 routing - #if defined(TCB0) - PORTMUX.TCBROUTEA |= PORTMUX_TCB0_bm; // Route signal to PF4 - #endif - - // Setup TCB1 routing - #if defined(TCB1) - PORTMUX.TCBROUTEA |= PORTMUX_TCB1_bm; // Route signal to PF5 - #endif - - // Start with TCB0 - TCB_t *timer_B = (TCB_t *)&TCB0; - - // Find end timer - #if defined(TCB3) - TCB_t *timer_B_end = (TCB_t *)&TCB3; - #elif defined(TCB2) - TCB_t *timer_B_end = (TCB_t *)&TCB2; - #elif defined(TCB1) - TCB_t *timer_B_end = (TCB_t *)&TCB1; - #else - TCB_t *timer_B_end = (TCB_t *)&TCB0; - #endif - - // Timer B Setup loop for TCB[0:end] - do - { - // 8 bit PWM mode, but do not enable output yet, will do in analogWrite() - timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc); - - // Assign 8-bit period - timer_B->CCMPL = PWM_TIMER_PERIOD; - - // default duty 50%, set when output enabled - timer_B->CCMPH = PWM_TIMER_COMPARE; - - // Use TCA clock (250kHz) and enable - // (sync update commented out, might try to synchronize later - timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) - //|(TCB_SYNCUPD_bm) - |(TCB_ENABLE_bm); - - // Increment pointer to next TCB instance - timer_B++; - - // Stop when pointing to TCB3 - } while (timer_B <= timer_B_end); - - // Stuff for synchronizing PWM timers -// // Restart TCA to sync TCBs -// // should not be needed -// TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESTART_gc; -// TCA0.SINGLE.CTRLECLR = TCA_SINGLE_CMD_RESTART_gc; -// -// timer_B = (TCB_t *)&TCB0; -// -// // TCB are sync to TCA, remove setting -// for (uint8_t digitial_pin_timer = (TIMERB0 - TIMERB0); -// digitial_pin_timer < (TIMERB3 - TIMERB0); -// digitial_pin_timer++) -// { -// // disable sync with tca -// timer_B->CTRLA &= ~ (TCB_SYNCUPD_bm); -// -// // Add offset to register -// timer_B++; -// -// } -} - -FORCE_INLINE bool isDoubleBondedActive(uint8_t pin) { - (void)pin; - - /* Check if TWI is operating on double bonded pin (Master Enable is high - in both Master and Slave mode for bus error detection, so this can - indicate an active state for Wire) */ - //if(((pin == PIN_A4) || (pin == PIN_A5)) && (TWI0.MCTRLA & TWI_ENABLE_bm)) return true; - - /* Special check for SPI_SS double bonded pin -- no action if SPI is active - (Using SPI Enable bit as indicator of SPI activity) */ - //if((pin == 10) && (SPI0.CTRLA & SPI_ENABLE_bm)) return true; - - return false; -} - -void initVariant() { -// Not used -} diff --git a/megaavr/variants/nano-4808/pins_arduino.h b/megaavr/variants/nano-4808/pins_arduino.h new file mode 100644 index 0000000..5c6ce86 --- /dev/null +++ b/megaavr/variants/nano-4808/pins_arduino.h @@ -0,0 +1,400 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + 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., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "timers.h" + +#define MEGACOREX +#define MCUDUDE_MEGACOREX + +#define NANO_4808_PINOUT +#define NONA4808_PINOUT +#define __AVR_ATmegax08__ + +// Arduino pin macros +#define PIN_PF0 0 +#define PIN_PF1 1 +#define PIN_PA0 2 +#define PIN_PA1 3 +#define PIN_PA2 4 +#define PIN_PA3 5 +#define PIN_PA4 6 +#define PIN_PA5 7 +#define PIN_PA6 8 +#define PIN_PA7 9 +#define PIN_PC3 10 +#define PIN_PC0 11 +#define PIN_PC1 12 +#define PIN_PC2 13 +#define PIN_PD0 14 +#define PIN_PD1 15 +#define PIN_PD2 16 +#define PIN_PD3 17 +#define PIN_PF2 18 +#define PIN_PF3 19 +#define PIN_PF4 20 +#define PIN_PF5 21 +#define PIN_PD4 22 +#define PIN_PD5 23 +#define PIN_PD6 24 +#define PIN_PD7 25 +#define PIN_PF6 26 + +#define PINS_COUNT 27 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 12 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 +#define NUM_SPI_PINS 3 +#define NUM_TOTAL_FREE_PINS PINS_COUNT +#define NUM_TOTAL_PINS PINS_COUNT +#define ANALOG_INPUT_OFFSET 14 +#define LED_BUILTIN PIN_PC2 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalOrAnalogPinToDigital(p) (((p) <= 26) ? (p) : NOT_A_PIN) +#define digitalPinToAnalogInput(p) (((p) <= 3) ? (p) : \ + ((p) <= 7) ? ((p) + 8) : \ + ((p) <= 11) ? ((p) - 4) : \ + ((p) >= 14 && (p) <= 17) ? ((p) - 14) : \ + ((p) >= 22 && (p) <= 25) ? ((p) - 18) : \ + ((p) >= 18 && (p) <= 21) ? ((p) - 6) : NOT_A_PIN) + +// Timer to use for millis/micros +#if !defined(MILLIS_USE_TIMERB0) || !defined(MILLIS_USE_TIMERB1) || !defined(MILLIS_USE_TIMERB2) +#define MILLIS_USE_TIMERB2 // Use TCB2 if nothing else if defined +#endif + +// PWM pins +#if defined(MILLIS_USE_TIMERB0) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA3) || ((p) == PIN_PC0)) +#elif defined(MILLIS_USE_TIMERB1) + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PC0)) +#else // default to MILLIS_USE_TIMERB2 + #define digitalPinHasPWM(p) (((p) == PIN_PD0) || ((p) == PIN_PD1) || ((p) == PIN_PD2) || ((p) == PIN_PD3) || \ + ((p) == PIN_PD4) || ((p) == PIN_PD5) || ((p) == PIN_PA2) || ((p) == PIN_PA3)) +#endif + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_UNTOUCHED = 0x80, +}; +#endif + +// Timer pin mapping +#define TCA0_PINS PORTMUX_TCA0_PORTD_gc // TCA0 output on PD[0:5] +#define TCB0_PINS 0x00 // TCB0 output on PA2 instead of PF4 +#define TCB1_PINS 0x00 // TCB1 output on PA3 instead of PF5 +#define TCB2_PINS 0x00 // TCB2 output on PC0 instead of PB4 + +// SPI 0 +// Pinswapped by default +// Pinswap 2 not available +#define SPI_INTERFACES_COUNT 1 +#define SPI_MUX PORTMUX_SPI0_ALT1_gc +#define SPI_MUX_PINSWAP_1 PORTMUX_SPI0_DEFAULT_gc +#define PIN_SPI_MISO PIN_PC1 +#define PIN_SPI_SCK PIN_PC2 +#define PIN_SPI_MOSI PIN_PC0 +#define PIN_SPI_SS PIN_PC3 +#define PIN_SPI_MISO_PINSWAP_1 PIN_PA5 +#define PIN_SPI_SCK_PINSWAP_1 PIN_PA6 +#define PIN_SPI_MOSI_PINSWAP_1 PIN_PA4 +#define PIN_SPI_SS_PINSWAP_1 PIN_PA7 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// TWI 0 +// No pinswap enabled by default +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define TWI_MUX_PINSWAP PORTMUX_TWI0_ALT2_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +#define PIN_WIRE_SDA_PINSWAP_1 PIN_PC2 +#define PIN_WIRE_SCL_PINSWAP_1 PIN_PC3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// USART 0 +// No pinswap enabled by default +#define HWSERIAL0 &USART2 +#define HWSERIAL0_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART2_DEFAULT_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART2_ALT1_gc +#define PIN_HWSERIAL0_TX PIN_PF0 +#define PIN_HWSERIAL0_RX PIN_PF1 +#define PIN_HWSERIAL0_XCK PIN_PF2 +#define PIN_HWSERIAL0_XDIR PIN_PF3 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PF4 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PF5 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PF6 + +// USART1 +// No pinswap available +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_DEFAULT_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_DEFAULT_gc +#define PIN_HWSERIAL1_TX PIN_PC0 +#define PIN_HWSERIAL1_RX PIN_PC1 +#define PIN_HWSERIAL1_XCK PIN_PC2 +#define PIN_HWSERIAL1_XDIR PIN_PC3 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_HWSERIAL1_TX +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_HWSERIAL1_RX + +// USART 2 +// No pinswap enabled by default +#define HWSERIAL2 &USART0 +#define HWSERIAL2_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PA0 +#define PIN_HWSERIAL2_RX PIN_PA1 +#define PIN_HWSERIAL2_XCK PIN_PA2 +#define PIN_HWSERIAL2_XDIR PIN_PA3 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL2_XDIR_PINSWAP_1 PIN_PA7 + +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PF2 +#define PIN_A5 PIN_PF3 +#define PIN_A6 PIN_PF4 +#define PIN_A7 PIN_PF5 +#define PIN_A8 PIN_PD4 +#define PIN_A9 PIN_PD5 +#define PIN_A10 PIN_PD6 +#define PIN_A11 PIN_PD7 +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; +static const uint8_t A8 = PIN_A8; +static const uint8_t A9 = PIN_A9; +static const uint8_t A10 = PIN_A10; +static const uint8_t A11 = PIN_A11; + +#ifdef ARDUINO_MAIN + +const uint8_t digital_pin_to_port[] = { + PF, // 0 PF0/USART2_Tx/TOSC1 + PF, // 1 PF1/USART2_Rx/TOSC2 + PA, // 2 PA0/USART0_Tx/CLKIN + PA, // 3 PA1/USART0_Rx + PA, // 4 PA2/SDA + PA, // 5 PA3/SCL + PA, // 6 PA4/MOSI + PA, // 7 PA5/MISO + PA, // 8 PA6/SCK + PA, // 9 PA7/SS/CLKOUT/LED_BUILTIN + PC, // 10 PC3 + PC, // 11 PC0/USART1_Tx + PC, // 12 PC1/USART1_Rx + PC, // 13 PC2 + PD, // 14 PD0/AIN0 + PD, // 15 PD1/AIN1 + PD, // 16 PD2/AIN2 + PD, // 17 PD3/AIN3 + PF, // 18 PF2/AIN12 + PF, // 19 PF3/AIN13 + PF, // 20 PF4/AIN14/TCB0 PWM + PF, // 21 PF5/AIN15/TCB1 PWM + PD, // 22 PD4/AIN4 + PD, // 23 PD5/AIN5 + PD, // 24 PD6/AIN6 + PD, // 25 PD7/AIN7/AREF + PF // 26 PF6 RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_position[] = { + PIN0_bp, // 0 PF0/USART2_Tx/TOSC1 + PIN1_bp, // 1 PF1/USART2_Rx/TOSC2 + PIN0_bp, // 2 PA0/USART0_Tx/CLKIN + PIN1_bp, // 3 PA1/USART0_Rx + PIN2_bp, // 4 PA2/SDA + PIN3_bp, // 5 PA3/SCL + PIN4_bp, // 6 PA4/MOSI + PIN5_bp, // 7 PA5/MISO + PIN6_bp, // 8 PA6/SCK + PIN7_bp, // 9 PA7/SS/CLKOUT/LED_BUILTIN + PIN3_bp, // 10 PC3 + PIN0_bp, // 11 PC0/USART1_Tx + PIN1_bp, // 12 PC1/USART1_Rx + PIN2_bp, // 13 PC2 + PIN0_bp, // 14 PD0/AIN0 + PIN1_bp, // 15 PD1/AIN1 + PIN2_bp, // 16 PD2/AIN2 + PIN3_bp, // 17 PD3/AIN3 + PIN2_bp, // 18 PF2/AIN12 + PIN3_bp, // 19 PF3/AIN13 + PIN4_bp, // 20 PF4/AIN14/TCB0 PWM + PIN5_bp, // 21 PF5/AIN15/TCB1 PWM + PIN4_bp, // 22 PD4/AIN4 + PIN5_bp, // 23 PD5/AIN5 + PIN6_bp, // 24 PD6/AIN6 + PIN7_bp, // 25 PD7/AIN7/AREF + PIN6_bp // 26 PF6 RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_mask[] = { + PIN0_bm, // 0 PF0/USART2_Tx/TOSC1 + PIN1_bm, // 1 PF1/USART2_Rx/TOSC2 + PIN0_bm, // 2 PA0/USART0_Tx/CLKIN + PIN1_bm, // 3 PA1/USART0_Rx + PIN2_bm, // 4 PA2/SDA + PIN3_bm, // 5 PA3/SCL + PIN4_bm, // 6 PA4/MOSI + PIN5_bm, // 7 PA5/MISO + PIN6_bm, // 8 PA6/SCK + PIN7_bm, // 9 PA7/SS/CLKOUT/LED_BUILTIN + PIN3_bm, // 10 PC3 + PIN0_bm, // 11 PC0/USART1_Tx + PIN1_bm, // 12 PC1/USART1_Rx + PIN2_bm, // 13 PC2 + PIN0_bm, // 14 PD0/AIN0 + PIN1_bm, // 15 PD1/AIN1 + PIN2_bm, // 16 PD2/AIN2 + PIN3_bm, // 17 PD3/AIN3 + PIN2_bm, // 18 PF2/AIN12 + PIN3_bm, // 19 PF3/AIN13 + PIN4_bm, // 20 PF4/AIN14/TCB0 PWM + PIN5_bm, // 21 PF5/AIN15/TCB1 PWM + PIN4_bm, // 22 PD4/AIN4 + PIN5_bm, // 23 PD5/AIN5 + PIN6_bm, // 24 PD6/AIN6 + PIN7_bm, // 25 PD7/AIN7/AREF + PIN6_bm // 26 PF6 RESET +}; + +const uint8_t digital_pin_to_timer[] = { + NOT_ON_TIMER, // 0 PF0/USART2_Tx/TOSC1 + NOT_ON_TIMER, // 1 PF1/USART2_Rx/TOSC2 + NOT_ON_TIMER, // 2 PA0/USART0_Tx/CLKIN + NOT_ON_TIMER, // 3 PA1/USART0_Rx +#if !defined(MILLIS_USE_TIMERB0) + TIMERB0, // 4 PA2/SDA +#else + NOT_ON_TIMER, // 4 PA2/SDA +#endif +#if !defined(MILLIS_USE_TIMERB1) + TIMERB1, // 5 PA3/SCL +#else + NOT_ON_TIMER, // 5 PA3/SCL +#endif + NOT_ON_TIMER, // 6 PA4/MOSI + NOT_ON_TIMER, // 7 PA5/MISO + NOT_ON_TIMER, // 8 PA6/SCK + NOT_ON_TIMER, // 9 PA7/SS/CLKOUT/LED_BUILTIN + NOT_ON_TIMER, // 10 PC3 +#if !defined(MILLIS_USE_TIMERB2) + TIMERB2, // 11 PC0/USART1_Tx +#else + NOT_ON_TIMER, // 11 PC0/USART1_Tx +#endif + NOT_ON_TIMER, // 12 PC1/USART1_Rx + NOT_ON_TIMER, // 13 PC2 + TIMERA0, // 14 PD0/AIN0 + TIMERA0, // 15 PD1/AIN1 + TIMERA0, // 16 PD2/AIN2 + TIMERA0, // 17 PD3/AIN3 + NOT_ON_TIMER, // 18 PF2/AIN12 + NOT_ON_TIMER, // 19 PF3/AIN13 + NOT_ON_TIMER, // 20 PF4/AIN14 + NOT_ON_TIMER, // 21 PF5/AIN15 + TIMERA0, // 22 PD4/AIN4 + TIMERA0, // 23 PD5/AIN5 + NOT_ON_TIMER, // 24 PD6/AIN6 + NOT_ON_TIMER, // 25 PD7/AIN7/AREF + NOT_ON_TIMER // 26 PF6 RESET +}; + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_USBVIRTUAL Serial + +void initVariant() __attribute__((weak)); +void initVariant() { } + +#endif diff --git a/megaavr/variants/nano-every/pins_arduino.h b/megaavr/variants/nano-every/pins_arduino.h new file mode 100644 index 0000000..15fab7a --- /dev/null +++ b/megaavr/variants/nano-every/pins_arduino.h @@ -0,0 +1,475 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + 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., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include "timers.h" + +#define MEGACOREX +#define MCUDUDE_MEGACOREX + +#define NANO_EVERY_PINOUT +#define NONA4809_PINOUT +#define __AVR_ATmegax09__ + +// Arduino pin macros +#define PIN_PC5 0 +#define PIN_PC4 1 +#define PIN_PA0 2 +#define PIN_PF5 3 +#define PIN_PC6 4 +#define PIN_PB2 5 +#define PIN_PF4 6 +#define PIN_PA1 7 +#define PIN_PE3 8 +#define PIN_PB0 9 +#define PIN_PB1 10 +#define PIN_PE0 11 +#define PIN_PE1 12 +#define PIN_PE2 13 +#define PIN_PD3 14 +#define PIN_PD2 15 +#define PIN_PD1 16 +#define PIN_PD0 17 +#define PIN_PF2 18 +#define PIN_PF3 19 +#define PIN_PD4 20 +#define PIN_PD5 21 +#define PIN_PA2 22 +#define PIN_PA3 23 +#define PIN_PB5 24 +#define PIN_PB4 25 +#define PIN_PC3 26 +#define PIN_PA5 27 +#define PIN_PA4 28 +#define PIN_PD6 29 +#define PIN_PA6 30 +#define PIN_PA7 31 +#define PIN_PB3 32 +#define PIN_PC7 33 +#define PIN_PC0 34 +#define PIN_PC1 35 +#define PIN_PC2 36 +#define PIN_PF0 37 +#define PIN_PF1 38 +#define PIN_PD7 39 +#define PIN_PF6 40 + +#define PINS_COUNT 41 +#define NUM_DIGITAL_PINS PINS_COUNT +#define NUM_ANALOG_INPUTS 16 +#define NUM_RESERVED_PINS 0 +#define NUM_INTERNALLY_USED_PINS 0 +#define NUM_I2C_PINS 2 // (SDA / SCL) +#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) +#define NUM_TOTAL_FREE_PINS NUM_DIGITAL_PINS +#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS + NUM_RESERVED_PINS + NUM_INTERNALLY_USED_PINS + NUM_I2C_PINS + NUM_SPI_PINS) +#define ANALOG_INPUT_OFFSET 14 +#define LED_BUILTIN 13 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) (((p) == A0) ? (3) : ((p) == A1) ? (2) : ((p) == A2) ? (1): ((p) == A3) ? (0): ((p) == A4) ? (12): ((p) == A5) ? (13): ((p) == A6) ? (4): ((p) == A7) ? (5): ((p) == A8) ? (7): ((p) == A9) ? (10) : ((p) == A10) ? (9): ((p) == A11) ? (8): ((p) == A12) ? (11): ((p) == A13) ? (14): ((p) == A14) ? (15) :((p) == A15) ? (29) : NOT_A_PIN) +#define digitalOrAnalogPinToDigital(p) (((p) <= 40) ? (p) : NOT_A_PIN) + +// Timer to use for millis/micros +#define MILLIS_USE_TIMERB3 + +// PWM pins +#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 27) + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, + TCB_3 = 9, +}; + +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTB = 0x41, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTE = 0x44, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_TCB2_PB4 = 0x21, + ROUTE_TCB3_PB5 = 0x30, + ROUTE_TCB3_PC1 = 0x31, + ROUTE_UNTOUCHED = 0x80, +}; +#endif + +// Timer pin mapping +#define TCA0_PINS PORTMUX_TCA0_PORTB_gc +#define TCB0_PINS PORTMUX_TCB0_bm +#define TCB1_PINS PORTMUX_TCB1_bm +#define TCB2_PINS 0x00 +#define TCB3_PINS 0x00 + +// SPI 0 +// Pinswap enabled by default and no alternative available +#define SPI_INTERFACES_COUNT 1 +#define SPI_MUX PORTMUX_SPI0_ALT2_gc +#define PIN_SPI_MISO PIN_PE1 +#define PIN_SPI_SCK PIN_PE2 +#define PIN_SPI_MOSI PIN_PE0 +#define PIN_SPI_SS PIN_PE3 +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; + +// TWI 0 +// No pinswap enabled by default, and no alternative available +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; + +// Nano Every debug USART (Serial) +// USART3 on mega4809 +// Maps to alternative pins by default +// Mapped to HWSERIAL0 in Serial library +#define HWSERIAL0 &USART3 +#define HWSERIAL0_DRE_VECTOR USART3_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART3_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART3_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART3_ALT1_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART3_DEFAULT_gc +#define PIN_HWSERIAL0_TX PIN_PB4 +#define PIN_HWSERIAL0_RX PIN_PB5 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PB0 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PB1 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PB2 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PB3 + +// Nano every USART (Serial1) +// USART1 on mega4809 +// Maps to alternative pins by default +// Mapped to HWSERIAL1 in Serial library +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_ALT1_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_DEFAULT_gc +#define PIN_HWSERIAL1_TX PIN_PC4 +#define PIN_HWSERIAL1_RX PIN_PC5 +#define PIN_HWSERIAL1_XCK PIN_PC6 +#define PIN_HWSERIAL1_XDIR PIN_PC7 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_PC0 +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_PC1 +#define PIN_HWSERIAL1_XCK_PINSWAP_1 PIN_PC2 +#define PIN_HWSERIAL1_XDIR_PINSWAP_1 PIN_PC3 + +// Nano Every USART (Serial2) +// USART0 on mega4809 +// Maps to default pins by default +// Mapped to HWSERIAL2 in Serial library +#define HWSERIAL2 &USART0 +#define HWSERIAL2_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART0_DEFAULT_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART0_ALT1_gc +#define PIN_HWSERIAL2_TX PIN_PA0 +#define PIN_HWSERIAL2_RX PIN_PA1 +#define PIN_HWSERIAL2_XCK PIN_PA2 +#define PIN_HWSERIAL2_XDIR PIN_PA3 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PA4 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PA5 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PA6 +#define PIN_HWSERIAL2_XDIR_PINSWAP_1 PIN_PA7 + +// Nano Every USART (Serial3) +// USART2 on mega4809 +// Maps to alternative pins by default +// Mapped to HWSERIAL3 in Serial library +#define HWSERIAL3 &USART2 +#define HWSERIAL3_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL3_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL3_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL3_MUX PORTMUX_USART2_ALT1_gc +#define HWSERIAL3_MUX_PINSWAP_1 PORTMUX_USART2_DEFAULT_gc +#define PIN_HWSERIAL3_TX PIN_PF4 +#define PIN_HWSERIAL3_RX PIN_PF5 +#define PIN_HWSERIAL3_XCK PIN_PF6 +#define PIN_HWSERIAL3_TX_PINSWAP_1 PIN_PF0 +#define PIN_HWSERIAL3_RX_PINSWAP_1 PIN_PF1 +#define PIN_HWSERIAL3_XCK_PINSWAP_1 PIN_PF2 +#define PIN_HWSERIAL3_XDIR_PINSWAP_1 PIN_PF3 + +// Analog pins +#define PIN_A0 PIN_PD3 // AIN3 +#define PIN_A1 PIN_PD2 // AIN2 +#define PIN_A2 PIN_PD1 // AIN1 +#define PIN_A3 PIN_PD0 // AIN0 +#define PIN_A4 PIN_PF2 // AIN12 +#define PIN_A5 PIN_PF3 // AIN13 +#define PIN_A6 PIN_PD4 // AIN4 +#define PIN_A7 PIN_PD5 // AIN5 +#define PIN_A8 PIN_PD7 // AIN7 +#define PIN_A9 PIN_PE2 // AIN10 +#define PIN_A10 PIN_PE1 // AIN9 +#define PIN_A11 PIN_PE0 // AIN8 +#define PIN_A12 PIN_PE3 // AIN11 +#define PIN_A13 PIN_PF4 // AIN14 +#define PIN_A14 PIN_PF5 // AIN15 +#define PIN_A15 PIN_PD6 // AIN6 +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; +static const uint8_t A8 = PIN_A8; +static const uint8_t A9 = PIN_A9; +static const uint8_t A10 = PIN_A10; +static const uint8_t A11 = PIN_A11; +static const uint8_t A12 = PIN_A12; +static const uint8_t A13 = PIN_A13; +static const uint8_t A14 = PIN_A14; +static const uint8_t A15 = PIN_A15; + +#ifdef ARDUINO_MAIN + +const uint8_t digital_pin_to_port[] = { + PC, // 0 PC5/USART1_Rx_alt + PC, // 1 PC4/USART1_Tx_alt + PA, // 2 PA0/USART0_Tx + PF, // 3 PF5/USART2_Rx_alt/AIN6 + PC, // 4 PC6 + PB, // 5 PB2 + PF, // 6 PF4/USART2_Tx_alt/AIN14 + PA, // 7 PA1/USART0_Rx + PE, // 8 PE3/AIN11 + PB, // 9 PB0/USART3_Tx + PB, // 10 PB1/USART3_Rx + PE, // 11 PE0/AIN8 + PE, // 12 PE1/AIN9 + PE, // 13 PE2/AIN10/LED_BUILTIN + PD, // 14 PD3/AIN3 + PD, // 15 PD2/AIN2 + PD, // 16 PD1/AIN1 + PD, // 17 PD0/AIN0 + PF, // 18 PF2/AIN12 + PF, // 19 PF3/AIN13 + PD, // 20 PD4/AIN4 + PD, // 21 PD5/AIN5 + PA, // 22 PA2/TWI_SDA + PA, // 23 PA3/TWI_SCL + PB, // 24 PB5/USART3_Rx_alt + PB, // 25 PB4/USART3_Tx_alt + PC, // 26 PC3 + PA, // 27 PA5/USART0_Rx_alt + PA, // 28 PA4/USART0_Tx_alt + PD, // 29 PD6/AIN6 + PA, // 30 PA6 + PA, // 31 PA7 + PB, // 32 PB3 + PC, // 33 PC7 + PC, // 34 PC0/USART1_Tx + PC, // 35 PC1/USART1_Rx + PC, // 36 PC2 + PF, // 37 PF0/USART2_Tx + PF, // 38 PF1/USART2_Rx + PD, // 39 PD7/VREF/AIN7 + PF // 40 PF6/RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_position[] = { + PIN5_bp, // 0 PC5/USART1_Rx_alt + PIN4_bp, // 1 PC4/USART1_Tx_alt + PIN0_bp, // 2 PA0/USART0_Tx + PIN5_bp, // 3 PF5/USART2_Rx_alt/AIN15 + PIN6_bp, // 4 PC6 + PIN2_bp, // 5 PB2 + PIN4_bp, // 6 PF4/USART2_Tx_alt/AIN15 + PIN1_bp, // 7 PA1/USART0_Rx + PIN3_bp, // 8 PE3/AIN11 + PIN0_bp, // 9 PB0/USART3_Tx + PIN1_bp, // 10 PB1/USART3_Rx + PIN0_bp, // 11 PE0/AIN8 + PIN1_bp, // 12 PE1/AIN9 + PIN2_bp, // 13 PE2/AIN10/LED_BUILTIN + PIN3_bp, // 14 PD3/AIN3 + PIN2_bp, // 15 PD2/AIN2 + PIN1_bp, // 16 PD1/AIN1 + PIN0_bp, // 17 PD0/AIN0 + PIN2_bp, // 18 PF2/AIN12 + PIN3_bp, // 19 PF3/AIN13 + PIN4_bp, // 20 PD4/AIN4 + PIN5_bp, // 21 PD5/AIN5 + PIN2_bp, // 22 PA2/TWI_SDA + PIN3_bp, // 23 PA3/TWI_SCL + PIN5_bp, // 24 PB5/USART3_Rx_alt + PIN4_bp, // 25 PB4/USART3_Tx_alt + PIN3_bp, // 26 PC3 + PIN5_bp, // 27 PA5/USART0_Rx_alt + PIN4_bp, // 28 PA4/USART0_Tx_alt + PIN6_bp, // 29 PD6/AIN6 + PIN6_bp, // 30 PA6 + PIN7_bp, // 31 PA7 + PIN3_bp, // 32 PB3 + PIN7_bp, // 33 PC7 + PIN0_bp, // 34 PC0/USART1_Tx + PIN1_bp, // 35 PC1/USART1_Rx + PIN2_bp, // 36 PC2 + PIN0_bp, // 37 PF0/USART2_Tx + PIN1_bp, // 38 PF1/USART2_Rx + PIN7_bp, // 39 PD7/VREF/AIN7 + PIN6_bp, // 40 PF6/RESET +}; + +/* Use this for accessing PINnCTRL register */ +const uint8_t digital_pin_to_bit_mask[] = { + PIN5_bm, // 0 PC5/USART1_Rx_alt + PIN4_bm, // 1 PC4/USART1_Tx_alt + PIN0_bm, // 2 PA0/USART0_Tx + PIN5_bm, // 3 PF5/USART2_Rx_alt/AIN15 + PIN6_bm, // 4 PC6 + PIN2_bm, // 5 PB2 + PIN4_bm, // 6 PF4/USART2_Tx_alt/AIN14 + PIN1_bm, // 7 PA1/USART0_Rx + PIN3_bm, // 8 PE3/AIN11 + PIN0_bm, // 9 PB0/USART3_Tx + PIN1_bm, // 10 PB1/USART3_Rx + PIN0_bm, // 11 PE0/AIN8 + PIN1_bm, // 12 PE1/AIN9 + PIN2_bm, // 13 PE2/AIN10/LED_BUILTIN + PIN3_bm, // 14 PD3/AIN3 + PIN2_bm, // 15 PD2/AIN2 + PIN1_bm, // 16 PD1/AIN1 + PIN0_bm, // 17 PD0/AIN0 + PIN2_bm, // 18 PF2/AIN12 + PIN3_bm, // 19 PF3/AIN13 + PIN4_bm, // 20 PD4/AIN4 + PIN5_bm, // 21 PD5/AIN5 + PIN2_bm, // 22 PA2/TWI_SDA + PIN3_bm, // 23 PA3/TWI_SCL + PIN5_bm, // 24 PB5/USART3_Rx_alt + PIN4_bm, // 25 PB4/USART3_Tx_alt + PIN3_bm, // 26 PC3 + PIN5_bm, // 27 PA5/USART0_Rx_alt + PIN4_bm, // 28 PA4/USART0_Tx_alt + PIN6_bm, // 29 PD6/AIN6 + PIN6_bm, // 30 PA6 + PIN7_bm, // 31 PA7 + PIN3_bm, // 32 PB3 + PIN7_bm, // 33 PC7 + PIN0_bm, // 34 PC0/USART1_Tx + PIN1_bm, // 35 PC1/USART1_Rx + PIN2_bm, // 36 PC2 + PIN0_bm, // 37 PF0/USART2_Tx + PIN1_bm, // 38 PF1/USART2_Rx + PIN7_bm, // 39 PD7/VREF/AIN7 + PIN6_bm, // 40 PF6/RESET +}; + +const uint8_t digital_pin_to_timer[] = { + NOT_ON_TIMER, // 0 PC5/USART1_Rx_alt + NOT_ON_TIMER, // 1 PC4/USART1_Tx_alt + NOT_ON_TIMER, // 2 PA0/USART0_Tx + TIMERB1, // 3 PF5/USART2_Rx_alt/AIN15 + NOT_ON_TIMER, // 4 PC6 + TIMERA0, // 5 PB2 + TIMERB0, // 6 PF4/USART2_Tx_alt/AIN14 + NOT_ON_TIMER, // 7 PA1/USART0_Rx + NOT_ON_TIMER, // 8 PE3/AIN11 + TIMERA0, // 9 PB0/USART3_Tx + TIMERA0, // 10 PB1/USART3_Rx + NOT_ON_TIMER, // 11 PE0/AIN8 + NOT_ON_TIMER, // 12 PE1/AIN9 + NOT_ON_TIMER, // 13 PE2/AIN10/LED_BUILTIN + NOT_ON_TIMER, // 14 PD3/AIN3 + NOT_ON_TIMER, // 15 PD2/AIN2 + NOT_ON_TIMER, // 16 PD1/AIN1 + NOT_ON_TIMER, // 17 PD0/AIN0 + NOT_ON_TIMER, // 18 PF2/AIN12 + NOT_ON_TIMER, // 19 PF3/AIN13 + NOT_ON_TIMER, // 20 PD4/AIN4 + NOT_ON_TIMER, // 21 PD5/AIN5 + NOT_ON_TIMER, // 22 PA2/TWI_SDA + NOT_ON_TIMER, // 23 PA3/TWI_SCL + NOT_ON_TIMER, // 24 PB5/USART3_Rx + NOT_ON_TIMER, // 25 PB4/USART3_Tx + NOT_ON_TIMER, // 26 PC3 + NOT_ON_TIMER, // 27 PA5/USART0_Rx_alt + NOT_ON_TIMER, // 28 PA4/USART0_Tx_alt + NOT_ON_TIMER, // 29 PD6/AIN6 + NOT_ON_TIMER, // 30 PA6 + NOT_ON_TIMER, // 31 PA7 + NOT_ON_TIMER, // 32 PB3 + NOT_ON_TIMER, // 33 PC7 + NOT_ON_TIMER, // 34 PC0/USART1_Tx + NOT_ON_TIMER, // 35 PC1/USART1_Rx + NOT_ON_TIMER, // 36 PC2 + NOT_ON_TIMER, // 37 PF0/USART2_Tx + NOT_ON_TIMER, // 38 PF1/USART2_Rx + NOT_ON_TIMER, // 39 PD7/VREF/AIN7 + NOT_ON_TIMER, // 40 PF6/RESET +}; + +//const uint8_t analog_pin_to_channel[] = { 3, 2, 1, 0, 12, 13, 4, 5 , 7, 10, 9, 8, 11, 14, 15}; + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_MONITOR Serial +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_USBVIRTUAL Serial + +void initVariant() __attribute__((weak)); +void initVariant() { } + +#endif diff --git a/megaavr/variants/uno-wifi/pins_arduino.h b/megaavr/variants/uno-wifi/pins_arduino.h index fbdb9d9..ed0c177 100644 --- a/megaavr/variants/uno-wifi/pins_arduino.h +++ b/megaavr/variants/uno-wifi/pins_arduino.h @@ -23,128 +23,263 @@ #ifndef Pins_Arduino_h #define Pins_Arduino_h +#include #include #include "timers.h" +#define MEGACOREX +#define MCUDUDE_MEGACOREX + #define UNO_WIFI_REV2_PINOUT #define UNO2018_PINOUT +#define __AVR_ATmegax09__ + +// Arduino pin macros +#define PIN_PC5 0 +#define PIN_PC4 1 +#define PIN_PA0 2 +#define PIN_PF5 3 +#define PIN_PC6 4 +#define PIN_PB2 5 +#define PIN_PF4 6 +#define PIN_PA1 7 +#define PIN_PE3 8 +#define PIN_PB0 9 +#define PIN_PB1 10 +#define PIN_PE0 11 +#define PIN_PE1 12 +#define PIN_PE2 13 +#define PIN_PD0 14 +#define PIN_PD1 15 +#define PIN_PD2 16 +#define PIN_PD3 17 +#define PIN_PD4 18 +#define PIN_PD5 19 +#define PIN_PA2 20 +#define PIN_PA3 21 +#define PIN_PC3 22 +#define PIN_PA5 23 +#define PIN_PA4 24 +#define PIN_PD6 25 +#define PIN_PB5 26 +#define PIN_PB4 27 +#define PIN_PA6 28 +#define PIN_PA7 29 +#define PIN_PB3 30 +#define PIN_PC7 31 +#define PIN_PC0 32 +#define PIN_PC1 33 +#define PIN_PC2 34 +#define PIN_PF2 35 +#define PIN_PF3 36 +#define PIN_PF0 37 +#define PIN_PF1 38 +#define PIN_PD7 39 +#define PIN_PF6 40 + +#define PINS_COUNT 41 +#define NUM_DIGITAL_PINS 20 // (14 on digital headers + 6 on analog headers) +#define NUM_ANALOG_INPUTS 16 +#define NUM_RESERVED_PINS 6 // (TOSC1/2, VREF, RESET, DEBUG USART Rx/Tx) +#define NUM_INTERNALLY_USED_PINS 10 // (2 x Chip select + 2 x UART + 4 x IO + LED_BUILTIN + 1 unused pin) +#define NUM_I2C_PINS 2 // (SDA / SCL) +#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) +#define NUM_TOTAL_FREE_PINS NUM_DIGITAL_PINS +#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS + NUM_RESERVED_PINS + NUM_INTERNALLY_USED_PINS + NUM_I2C_PINS + NUM_SPI_PINS) +#define ANALOG_INPUT_OFFSET 14 +#define LED_BUILTIN PIN_PD6 +#define EXTERNAL_NUM_INTERRUPTS 47 +#define digitalPinToAnalogInput(p) (((p) <= 5 && (p) != 3) ? (p) : ((p) >= 14 && (p) <= 19) ? ((p) - 14) : ((p) == 25) ? ((p) - 19) : ((p) == 39) ? ((p) - 32) : ((p) >= 11 && (p) <= 13) ? ((p) - 3) : ((p) == 8) ? ((p) + 3) : ((p) >= 35 && (p) <= 36) ? ((p) - 23) : ((p) == 6) ? ((p) + 8) : ((p) == 3) ? ((p) + 12) : NOT_A_PIN) +#define digitalOrAnalogPinToDigital(p) (((p) <= 40) ? (p) : NOT_A_PIN) + +// Timer to use for millis/micros +#define MILLIS_USE_TIMERB3 // Use TCB3 for millis generation + +// PWM pins +#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 27) + +// Timer enums +#ifdef __cplusplus +enum pwm_timers_t : uint8_t { + TCA0_0 = 0, + TCA0_1 = 1, + TCA0_2 = 2, + TCA0_3 = 3, + TCA0_4 = 4, + TCA0_5 = 5, + TCB_0 = 6, + TCB_1 = 7, + TCB_2 = 8, + TCB_3 = 9, +}; -#define NUM_DIGITAL_PINS 20 // (14 on digital headers + 6 on analog headers) -#define NUM_ANALOG_INPUTS 6 -#define NUM_RESERVED_PINS 6 // (TOSC1/2, VREF, RESET, DEBUG USART Rx/Tx) -#define NUM_INTERNALLY_USED_PINS 10 // (2 x Chip select + 2 x UART + 4 x IO + LED_BUILTIN + 1 unused pin) -#define NUM_I2C_PINS 2 // (SDA / SCL) -#define NUM_SPI_PINS 3 // (MISO / MOSI / SCK) -#define NUM_TOTAL_FREE_PINS (NUM_DIGITAL_PINS) -#define NUM_TOTAL_PINS (NUM_DIGITAL_PINS + NUM_RESERVED_PINS + NUM_INTERNALLY_USED_PINS + NUM_I2C_PINS + NUM_SPI_PINS) -#define ANALOG_INPUT_OFFSET 14 -#define digitalPinToAnalogInput(p) ((p < NUM_ANALOG_INPUTS) ? (p) : (p) - ANALOG_INPUT_OFFSET) - -#define MILLIS_USE_TIMERB3 // Use timerb3 for millis generation - -#define EXTERNAL_NUM_INTERRUPTS (NUM_TOTAL_PINS) - -#define digitalPinHasPWM(p) ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10) - -#define SPI_MUX (PORTMUX_SPI0_ALT1_gc) -#define SPI_MUX_PINSWAP_1 (PORTMUX_SPI0_ALT2_gc) -#define SPI_MUX_PINSWAP_2 (PORTMUX_SPI0_DEFAULT_gc) -#define PIN_SPI_MISO (33) -#define PIN_SPI_SCK (34) -#define PIN_SPI_MOSI (32) -#define PIN_SPI_SS (10) +enum timers_route_t : uint8_t { + ROUTE_TCA0_PORTA = 0x40, + ROUTE_TCA0_PORTB = 0x41, + ROUTE_TCA0_PORTC = 0x42, + ROUTE_TCA0_PORTD = 0x43, + ROUTE_TCA0_PORTE = 0x44, + ROUTE_TCA0_PORTF = 0x45, + ROUTE_TCB0_PA2 = 0x00, + ROUTE_TCB0_PF4 = 0x01, + ROUTE_TCB1_PA3 = 0x10, + ROUTE_TCB1_PF5 = 0x11, + ROUTE_TCB2_PC0 = 0x20, + ROUTE_TCB2_PB4 = 0x21, + ROUTE_TCB3_PB5 = 0x30, + ROUTE_TCB3_PC1 = 0x31, + ROUTE_UNTOUCHED = 0x80, +}; +#endif +// Timer pin mapping +#define TCA0_PINS PORTMUX_TCA0_PORTB_gc +#define TCB0_PINS PORTMUX_TCB0_bm +#define TCB1_PINS PORTMUX_TCB1_bm +#define TCB2_PINS PORTMUX_TCB2_bm +#define TCB3_PINS 0x00 + +// Wiring to Wifi NINA module +#define NINA_GPIO0 PIN_PA6 +#define NINA_RESETN PIN_PA7 +#define NINA_ACK PIN_PF3 +#define NINA_CTS NINA_ACK +#define NINA_RTS NINA_GPIO0 +#define SPIWIFI_SS PIN_PF2 +#define SPIWIFI_ACK NINA_ACK +#define SPIWIFI_RESET ~NINA_RESETN + +// Wiring to IMU +#define SPIIMU_SS PIN_PB3 +#define SPIIMU_INT PIN_PC7 + +// SPI 0 +// Pinswap enabled by default and no alternative available +#define SPI_INTERFACES_COUNT 1 +#define SPI_MUX PORTMUX_SPI0_ALT1_gc +#define PIN_SPI_MISO PIN_PC1 +#define PIN_SPI_SCK PIN_PC2 +#define PIN_SPI_MOSI PIN_PC0 +#define PIN_SPI_SS PIN_PB1 static const uint8_t SS = PIN_SPI_SS; static const uint8_t MOSI = PIN_SPI_MOSI; static const uint8_t MISO = PIN_SPI_MISO; static const uint8_t SCK = PIN_SPI_SCK; -#define PIN_WIRE_SDA (20) -#define PIN_WIRE_SCL (21) - +// TWI 0 +// No pinswap enabled by default, and no alternative available +#define TWI_MUX PORTMUX_TWI0_DEFAULT_gc +#define PIN_WIRE_SDA PIN_PA2 +#define PIN_WIRE_SCL PIN_PA3 static const uint8_t SDA = PIN_WIRE_SDA; static const uint8_t SCL = PIN_WIRE_SCL; -// Uno2 Main USART available on Arduino header pins -// USART1 on mega4809 (alternative pins) +// Uno Wifi Rev2 debug USART (Serial) +// USART3 on mega4809 +// Maps to alternative pins by default // Mapped to HWSERIAL0 in Serial library -#define HWSERIAL1 (&USART1) -#define HWSERIAL1_DRE_VECTOR (USART1_DRE_vect) -#define HWSERIAL1_DRE_VECTOR_NUM (USART1_DRE_vect_num) -#define HWSERIAL1_RXC_VECTOR (USART1_RXC_vect) -#define HWSERIAL1_MUX (PORTMUX_USART1_ALT1_gc) -#define HWSERIAL1_MUX_PINSWAP_1 (PORTMUX_USART1_DEFAULT_gc) -#define PIN_WIRE_HWSERIAL1_RX (0) -#define PIN_WIRE_HWSERIAL1_TX (1) -#define PIN_WIRE_HWSERIAL1_RX_PINSWAP_1 (33) -#define PIN_WIRE_HWSERIAL1_TX_PINSWAP_1 (32) - -// Uno2 Debug USART (not available on headers, only via the EDGB virtual COM port) -// USART3 on mega4809 (alternative pins) +#define HWSERIAL0 &USART3 +#define HWSERIAL0_DRE_VECTOR USART3_DRE_vect +#define HWSERIAL0_DRE_VECTOR_NUM USART3_DRE_vect_num +#define HWSERIAL0_RXC_VECTOR USART3_RXC_vect +#define HWSERIAL0_MUX PORTMUX_USART3_ALT1_gc +#define HWSERIAL0_MUX_PINSWAP_1 PORTMUX_USART3_DEFAULT_gc +#define PIN_HWSERIAL0_TX PIN_PB4 +#define PIN_HWSERIAL0_RX PIN_PB5 +#define PIN_HWSERIAL0_TX_PINSWAP_1 PIN_PB0 +#define PIN_HWSERIAL0_RX_PINSWAP_1 PIN_PB1 +#define PIN_HWSERIAL0_XCK_PINSWAP_1 PIN_PB2 +#define PIN_HWSERIAL0_XDIR_PINSWAP_1 PIN_PB3 + +// Uno Wifi Rev2 USART (Serial1) +// USART1 on mega4809 +// Maps to alternative pins by default // Mapped to HWSERIAL1 in Serial library -#define HWSERIAL0 (&USART3) -#define HWSERIAL0_DRE_VECTOR (USART3_DRE_vect) -#define HWSERIAL0_DRE_VECTOR_NUM (USART3_DRE_vect_num) -#define HWSERIAL0_RXC_VECTOR (USART3_RXC_vect) -#define HWSERIAL0_MUX (PORTMUX_USART3_ALT1_gc) -#define HWSERIAL0_MUX_PINSWAP_1 (PORTMUX_USART3_DEFAULT_gc) -#define PIN_WIRE_HWSERIAL0_RX (26) -#define PIN_WIRE_HWSERIAL0_TX (27) -#define PIN_WIRE_HWSERIAL0_RX_PINSWAP_1 (10) -#define PIN_WIRE_HWSERIAL0_TX_PINSWAP_1 (9) - -// Uno2 Spare USART available on testpoints -// USART0 on mega4809 (alternative pins) +#define HWSERIAL1 &USART1 +#define HWSERIAL1_DRE_VECTOR USART1_DRE_vect +#define HWSERIAL1_DRE_VECTOR_NUM USART1_DRE_vect_num +#define HWSERIAL1_RXC_VECTOR USART1_RXC_vect +#define HWSERIAL1_MUX PORTMUX_USART1_ALT1_gc +#define HWSERIAL1_MUX_PINSWAP_1 PORTMUX_USART1_DEFAULT_gc +#define PIN_HWSERIAL1_TX PIN_PC4 +#define PIN_HWSERIAL1_RX PIN_PC5 +#define PIN_HWSERIAL1_XCK PIN_PC6 +#define PIN_HWSERIAL1_XDIR PIN_PC7 +#define PIN_HWSERIAL1_TX_PINSWAP_1 PIN_PC0 +#define PIN_HWSERIAL1_RX_PINSWAP_1 PIN_PC1 +#define PIN_HWSERIAL1_XCK_PINSWAP_1 PIN_PC2 +#define PIN_HWSERIAL1_XDIR_PINSWAP_1 PIN_PC3 + +// Uno Wifi Rev2 USART for communicating with Wifi NINA (Serial2) +// USART0 on mega4809 +// Maps to alternative pins by default // Mapped to HWSERIAL2 in Serial library -#define HWSERIAL2 (&USART0) -#define HWSERIAL2_DRE_VECTOR (USART0_DRE_vect) -#define HWSERIAL2_DRE_VECTOR_NUM (USART0_DRE_vect_num) -#define HWSERIAL2_RXC_VECTOR (USART0_RXC_vect) -#define HWSERIAL2_MUX (PORTMUX_USART0_ALT1_gc) -#define HWSERIAL2_MUX_PINSWAP_1 (PORTMUX_USART0_DEFAULT_gc) -#define PIN_WIRE_HWSERIAL2_RX (23) -#define PIN_WIRE_HWSERIAL2_TX (24) -#define PIN_WIRE_HWSERIAL2_RX_PINSWAP_1 (7) -#define PIN_WIRE_HWSERIAL2_TX_PINSWAP_1 (2) - -#define HWSERIAL3_MUX (PORTMUX_USART2_NONE_gc) -#define TWI_MUX (PORTMUX_TWI0_DEFAULT_gc) //PORTMUX_TWI0_ALT1_gc - -#define MUX_SPI (SPI_MUX) -#define SPI_INTERFACES_COUNT 1 - -#define LED_BUILTIN 25 - -#define PIN_A0 (14) -#define PIN_A1 (15) -#define PIN_A2 (16) -#define PIN_A3 (17) -#define PIN_A4 (18) -#define PIN_A5 (19) - -static const uint8_t A0 = PIN_A0; -static const uint8_t A1 = PIN_A1; -static const uint8_t A2 = PIN_A2; -static const uint8_t A3 = PIN_A3; -static const uint8_t A4 = PIN_A4; -static const uint8_t A5 = PIN_A5; - -#define PINS_COUNT (40u) - -//NINA -#define NINA_GPIO0 (28u) -#define NINA_RESETN (29u) -#define NINA_ACK (36u) -#define NINA_CTS NINA_ACK -#define NINA_RTS NINA_GPIO0 - -#define SPIWIFI_SS (35u) -#define SPIWIFI_ACK NINA_ACK -#define SPIWIFI_RESET (~NINA_RESETN) - -//IMU -#define SPIIMU_SS (30u) -#define SPIIMU_INT (31u) +#define HWSERIAL2 &USART0 +#define HWSERIAL2_DRE_VECTOR USART0_DRE_vect +#define HWSERIAL2_DRE_VECTOR_NUM USART0_DRE_vect_num +#define HWSERIAL2_RXC_VECTOR USART0_RXC_vect +#define HWSERIAL2_MUX PORTMUX_USART0_ALT1_gc +#define HWSERIAL2_MUX_PINSWAP_1 PORTMUX_USART0_DEFAULT_gc +#define PIN_HWSERIAL2_TX PIN_PA4 +#define PIN_HWSERIAL2_RX PIN_PA5 +#define PIN_HWSERIAL2_XCK PIN_PA6 +#define PIN_HWSERIAL2_XDIR PIN_PA7 +#define PIN_HWSERIAL2_TX_PINSWAP_1 PIN_PA0 +#define PIN_HWSERIAL2_RX_PINSWAP_1 PIN_PA1 +#define PIN_HWSERIAL2_XCK_PINSWAP_1 PIN_PA2 +#define PIN_HWSERIAL2_XDIR_PINSWAP_1 PIN_PA3 + +// Uno Wifi Rev2 USART (Serial3) +// USART2 on mega4809 +// Maps to alternative pins by default +// Mapped to HWSERIAL3 in Serial library +#define HWSERIAL3 &USART2 +#define HWSERIAL3_DRE_VECTOR USART2_DRE_vect +#define HWSERIAL3_DRE_VECTOR_NUM USART2_DRE_vect_num +#define HWSERIAL3_RXC_VECTOR USART2_RXC_vect +#define HWSERIAL3_MUX PORTMUX_USART2_ALT1_gc +#define HWSERIAL3_MUX_PINSWAP_1 PORTMUX_USART2_DEFAULT_gc +#define PIN_HWSERIAL3_TX PIN_PF4 +#define PIN_HWSERIAL3_RX PIN_PF5 +#define PIN_HWSERIAL3_XCK PIN_PF6 +#define PIN_HWSERIAL3_TX_PINSWAP_1 PIN_PF0 +#define PIN_HWSERIAL3_RX_PINSWAP_1 PIN_PF1 +#define PIN_HWSERIAL3_XCK_PINSWAP_1 PIN_PF2 +#define PIN_HWSERIAL3_XDIR_PINSWAP_1 PIN_PF3 + +// Analog pins +#define PIN_A0 PIN_PD0 +#define PIN_A1 PIN_PD1 +#define PIN_A2 PIN_PD2 +#define PIN_A3 PIN_PD3 +#define PIN_A4 PIN_PD4 +#define PIN_A5 PIN_PD5 +#define PIN_A6 PIN_PD6 +#define PIN_A7 PIN_PD7 +#define PIN_A8 PIN_PE0 +#define PIN_A9 PIN_PE1 +#define PIN_A10 PIN_PE2 +#define PIN_A11 PIN_PE3 +#define PIN_A12 PIN_PF2 +#define PIN_A13 PIN_PF3 +#define PIN_A14 PIN_PF4 +#define PIN_A15 PIN_PF5 +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; +static const uint8_t A8 = PIN_A8; +static const uint8_t A9 = PIN_A9; +static const uint8_t A10 = PIN_A10; +static const uint8_t A11 = PIN_A11; +static const uint8_t A12 = PIN_A12; +static const uint8_t A13 = PIN_A13; +static const uint8_t A14 = PIN_A14; +static const uint8_t A15 = PIN_A15; #ifdef ARDUINO_MAIN @@ -179,7 +314,7 @@ static const uint8_t A5 = PIN_A5; // -const uint8_t PROGMEM digital_pin_to_port[] = { +const uint8_t digital_pin_to_port[] = { PC, // 0 PC5/USART1_Rx PC, // 1 PC4/USART1_Tx PA, // 2 PA0 @@ -224,7 +359,7 @@ const uint8_t PROGMEM digital_pin_to_port[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_position[] = { +const uint8_t digital_pin_to_bit_position[] = { PIN5_bp, // 0 PC5/USART1_Rx PIN4_bp, // 1 PC4/USART1_Tx PIN0_bp, // 2 PA0 @@ -269,7 +404,7 @@ const uint8_t PROGMEM digital_pin_to_bit_position[] = { }; /* Use this for accessing PINnCTRL register */ -const uint8_t PROGMEM digital_pin_to_bit_mask[] = { +const uint8_t digital_pin_to_bit_mask[] = { PIN5_bm, // 0 PC5/USART1_Rx PIN4_bm, // 1 PC4/USART1_Tx PIN0_bm, // 2 PA0 @@ -285,7 +420,7 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN1_bm, // 12 PE1 PIN2_bm, // 13 PE2 PIN0_bm, // 14 PD0/AI0 - PIN1_bm, // 15 PD1AI1 + PIN1_bm, // 15 PD1/AI1 PIN2_bm, // 16 PD2/AI2 PIN3_bm, // 17 PD3/AI3 PIN4_bm, // 18 PD4/AI4 @@ -313,7 +448,7 @@ const uint8_t PROGMEM digital_pin_to_bit_mask[] = { PIN6_bm // 40 PF6 RESET }; -const uint8_t PROGMEM digital_pin_to_timer[] = { +const uint8_t digital_pin_to_timer[] = { NOT_ON_TIMER, // 0 PC5/USART1_Rx NOT_ON_TIMER, // 1 PC4/USART1_Tx NOT_ON_TIMER, // 2 PA0 @@ -341,7 +476,11 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { NOT_ON_TIMER, // 24 PA4/NINA RX NOT_ON_TIMER, // 25 PD6/LED_BUILTIN NOT_ON_TIMER, // 26 PB5/USART3_Rx +#ifdef MILLIS_USE_TIMERB2 NOT_ON_TIMER, // 27 PB4/USART3_Tx +#else + TIMERB2, // 27 PB4/USART3_Tx/TCB2 PWM +#endif NOT_ON_TIMER, // 28 PA6/NINA GPIO0 NOT_ON_TIMER, // 29 PA7/NINA RST NOT_ON_TIMER, // 30 PB3/IMU CS @@ -381,4 +520,23 @@ const uint8_t PROGMEM digital_pin_to_timer[] = { #define SERIAL_PORT_HARDWARE_OPEN Serial2 #define SerialNina Serial2 +void initVariant() __attribute__((weak)); +void initVariant() { + // NINA - SPI boot + pinMode(NINA_GPIO0, OUTPUT); + digitalWrite(NINA_GPIO0, HIGH); + + // disable the NINA + pinMode(NINA_RESETN, OUTPUT); + digitalWrite(NINA_RESETN, HIGH); + + // NINA SS HIGH by default + pinMode(SPIWIFI_SS, OUTPUT); + digitalWrite(SPIWIFI_SS, HIGH); + + // IMU SS HIGH by default + pinMode(SPIIMU_SS, OUTPUT); + digitalWrite(SPIIMU_SS, HIGH); +} + #endif diff --git a/megaavr/variants/uno-wifi/timers.h b/megaavr/variants/uno-wifi/timers.h deleted file mode 100644 index 438e79f..0000000 --- a/megaavr/variants/uno-wifi/timers.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __TIMERS_H__ -#define __TIMERS_H__ - -#define TIME_TRACKING_TIMER_PERIOD 0xFF -#define TIME_TRACKING_TICKS_PER_OVF (TIME_TRACKING_TIMER_PERIOD + 1) // Timer ticks per overflow of TCB3 -#define TIME_TRACKING_TIMER_DIVIDER 64 // Clock divider for TCB0 -#define TIME_TRACKING_CYCLES_PER_OVF (TIME_TRACKING_TICKS_PER_OVF * TIME_TRACKING_TIMER_DIVIDER) - -#define PWM_TIMER_PERIOD 0xFF // For frequency -#define PWM_TIMER_COMPARE 0x80 // For duty cycle - -#endif \ No newline at end of file diff --git a/megaavr/variants/uno-wifi/variant.c b/megaavr/variants/uno-wifi/variant.c deleted file mode 100644 index 4190726..0000000 --- a/megaavr/variants/uno-wifi/variant.c +++ /dev/null @@ -1,132 +0,0 @@ -#include - -#include "pins_arduino.h" -#include "api/Common.h" - -#define FORCE_INLINE __attribute__((always_inline)) inline - -void setup_timers() { - - // TYPE A TIMER - - // PORTMUX setting for TCA -> all outputs [0:2] point to PORTB pins [0:2] - PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTB_gc; - - // Setup timers for single slope PWM, but do not enable, will do in analogWrite() - TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc; - - // Period setting, 16 bit register but val resolution is 8 bit - TCA0.SINGLE.PER = PWM_TIMER_PERIOD; - - // Default duty 50%, will re-assign in analogWrite() - TCA0.SINGLE.CMP0BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP1BUF = PWM_TIMER_COMPARE; - TCA0.SINGLE.CMP2BUF = PWM_TIMER_COMPARE; - - // Use DIV64 prescaler (giving 250kHz clock), enable TCA timer - TCA0.SINGLE.CTRLA = (TCA_SINGLE_CLKSEL_DIV64_gc) | (TCA_SINGLE_ENABLE_bm); - - // TYPE B TIMERS - - // Setup TCB0 routing - #if defined(TCB0) - PORTMUX.TCBROUTEA |= PORTMUX_TCB0_bm; // Route signal to PF4 - #endif - - // Setup TCB1 routing - #if defined(TCB1) - PORTMUX.TCBROUTEA |= PORTMUX_TCB1_bm; // Route signal to PF5 - #endif - - // Start with TCB0 - TCB_t *timer_B = (TCB_t *)&TCB0; - - // Find end timer - #if defined(TCB3) - TCB_t *timer_B_end = (TCB_t *)&TCB3; - #elif defined(TCB2) - TCB_t *timer_B_end = (TCB_t *)&TCB2; - #elif defined(TCB1) - TCB_t *timer_B_end = (TCB_t *)&TCB1; - #else - TCB_t *timer_B_end = (TCB_t *)&TCB0; - #endif - - // Timer B Setup loop for TCB[0:3] - do - { - // 8 bit PWM mode, but do not enable output yet, will do in analogWrite() - timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc); - - // Assign 8-bit period - timer_B->CCMPL = PWM_TIMER_PERIOD; - - // default duty 50%, set when output enabled - timer_B->CCMPH = PWM_TIMER_COMPARE; - - // Use TCA clock (250kHz) and enable - // (sync update commented out, might try to synchronize later - timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) - //|(TCB_SYNCUPD_bm) - |(TCB_ENABLE_bm); - - // Increment pointer to next TCB instance - timer_B++; - - // Stop when pointing to TCB3 - } while (timer_B <= timer_B_end); - - // Stuff for synchronizing PWM timers -// // Restart TCA to sync TCBs -// // should not be needed -// TCA0.SINGLE.CTRLESET = TCA_SINGLE_CMD_RESTART_gc; -// TCA0.SINGLE.CTRLECLR = TCA_SINGLE_CMD_RESTART_gc; -// -// timer_B = (TCB_t *)&TCB0; -// -// // TCB are sync to TCA, remove setting -// for (uint8_t digitial_pin_timer = (TIMERB0 - TIMERB0); -// digitial_pin_timer < (TIMERB3 - TIMERB0); -// digitial_pin_timer++) -// { -// // disable sync with tca -// timer_B->CTRLA &= ~ (TCB_SYNCUPD_bm); -// -// // Add offset to register -// timer_B++; -// -// } -} - -FORCE_INLINE bool isDoubleBondedActive(uint8_t pin) { - (void)pin; - - /* Check if TWI is operating on double bonded pin (Master Enable is high - in both Master and Slave mode for bus error detection, so this can - indicate an active state for Wire) */ - //if(((pin == PIN_A4) || (pin == PIN_A5)) && (TWI0.MCTRLA & TWI_ENABLE_bm)) return true; - - /* Special check for SPI_SS double bonded pin -- no action if SPI is active - (Using SPI Enable bit as indicator of SPI activity) */ - //if((pin == 10) && (SPI0.CTRLA & SPI_ENABLE_bm)) return true; - - return false; -} - -void initVariant() { - // NINA - SPI boot - pinMode(NINA_GPIO0, OUTPUT); - digitalWrite(NINA_GPIO0, HIGH); - - // disable the NINA - pinMode(NINA_RESETN, OUTPUT); - digitalWrite(NINA_RESETN, HIGH); - - // NINA SS HIGH by default - pinMode(SPIWIFI_SS, OUTPUT); - digitalWrite(SPIWIFI_SS, HIGH); - - // IMU SS HIGH by default - pinMode(SPIIMU_SS, OUTPUT); - digitalWrite(SPIIMU_SS, HIGH); -}