From 41c542e53f9272f332600cf626eae5ffd1b66db2 Mon Sep 17 00:00:00 2001 From: Ben Lye Date: Tue, 19 Dec 2017 09:22:38 +0000 Subject: [PATCH] More fixes to consolidate OrangeRX and Atmega --- .../avrdude.conf => avr/avrdude_xmega.conf} | 0 BootLoaders/Boards/avr/boards.txt | 29 +- BootLoaders/Boards/avr/platform.local.txt | 22 +- BootLoaders/Boards/avr/platform.txt | 28 +- .../Boards/avr/tools/win/do_version.bat | 6 +- BootLoaders/Boards/orangerx/boards.txt | 19 - .../Boards/orangerx/cores/xmega/Arduino.h | 450 -- .../Boards/orangerx/cores/xmega/CDC.cpp | 541 --- .../Boards/orangerx/cores/xmega/Client.h | 45 - .../Boards/orangerx/cores/xmega/HID.cpp | 593 --- .../orangerx/cores/xmega/HardwareSerial.cpp | 1869 -------- .../orangerx/cores/xmega/HardwareSerial.h | 143 - .../Boards/orangerx/cores/xmega/IPAddress.cpp | 74 - .../Boards/orangerx/cores/xmega/IPAddress.h | 82 - .../Boards/orangerx/cores/xmega/Platform.h | 27 - .../Boards/orangerx/cores/xmega/Print.cpp | 381 -- .../Boards/orangerx/cores/xmega/Print.h | 97 - .../Boards/orangerx/cores/xmega/Printable.h | 40 - .../Boards/orangerx/cores/xmega/Server.h | 28 - .../Boards/orangerx/cores/xmega/Stream.cpp | 362 -- .../Boards/orangerx/cores/xmega/Stream.h | 96 - .../Boards/orangerx/cores/xmega/Tone.cpp | 960 ----- .../Boards/orangerx/cores/xmega/USBAPI.h | 275 -- .../Boards/orangerx/cores/xmega/USBCore.cpp | 3745 ----------------- .../Boards/orangerx/cores/xmega/USBCore.h | 442 -- .../Boards/orangerx/cores/xmega/USBDesc.h | 83 - BootLoaders/Boards/orangerx/cores/xmega/Udp.h | 88 - .../Boards/orangerx/cores/xmega/WCharacter.h | 168 - .../Boards/orangerx/cores/xmega/WInterrupts.c | 808 ---- .../Boards/orangerx/cores/xmega/WMath.cpp | 60 - .../Boards/orangerx/cores/xmega/WString.cpp | 744 ---- .../Boards/orangerx/cores/xmega/WString.h | 224 - .../orangerx/cores/xmega/avr-libc/malloc.c | 267 -- .../orangerx/cores/xmega/avr-libc/realloc.c | 150 - .../cores/xmega/avr-libc/sectionname.h | 49 - .../cores/xmega/avr-libc/stdlib_private.h | 58 - .../Boards/orangerx/cores/xmega/binary.h | 534 --- .../Boards/orangerx/cores/xmega/main.cpp | 68 - .../Boards/orangerx/cores/xmega/new.cpp | 28 - BootLoaders/Boards/orangerx/cores/xmega/new.h | 24 - .../Boards/orangerx/cores/xmega/wiring.c | 1088 ----- .../orangerx/cores/xmega/wiring_analog.c | 859 ---- .../orangerx/cores/xmega/wiring_digital.c | 428 -- .../orangerx/cores/xmega/wiring_private.h | 125 - .../orangerx/cores/xmega/wiring_pulse.c | 69 - .../orangerx/cores/xmega/wiring_shift.c | 55 - .../Boards/orangerx/platform.local.txt | 25 - BootLoaders/Boards/orangerx/platform.txt | 124 - .../Boards/orangerx/tools/linux/do_version | 47 - .../Boards/orangerx/tools/linux64/do_version | 47 - .../Boards/orangerx/tools/macosx/do_version | 47 - .../Boards/orangerx/tools/win/do_version.bat | 67 - .../variants/xmega32d4/pins_arduino.h | 702 --- .../Boards/stm32/tools/win/do_version.bat | 6 +- 54 files changed, 53 insertions(+), 17343 deletions(-) rename BootLoaders/Boards/{orangerx/avrdude.conf => avr/avrdude_xmega.conf} (100%) delete mode 100644 BootLoaders/Boards/orangerx/boards.txt delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Arduino.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Client.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/HID.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Platform.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Print.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Print.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Printable.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Server.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Stream.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/USBCore.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/Udp.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/WString.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/WString.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/avr-libc/sectionname.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/avr-libc/stdlib_private.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/binary.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/main.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/new.cpp delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/new.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c delete mode 100644 BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c delete mode 100644 BootLoaders/Boards/orangerx/platform.local.txt delete mode 100644 BootLoaders/Boards/orangerx/platform.txt delete mode 100755 BootLoaders/Boards/orangerx/tools/linux/do_version delete mode 100755 BootLoaders/Boards/orangerx/tools/linux64/do_version delete mode 100755 BootLoaders/Boards/orangerx/tools/macosx/do_version delete mode 100644 BootLoaders/Boards/orangerx/tools/win/do_version.bat delete mode 100644 BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h diff --git a/BootLoaders/Boards/orangerx/avrdude.conf b/BootLoaders/Boards/avr/avrdude_xmega.conf similarity index 100% rename from BootLoaders/Boards/orangerx/avrdude.conf rename to BootLoaders/Boards/avr/avrdude_xmega.conf diff --git a/BootLoaders/Boards/avr/boards.txt b/BootLoaders/Boards/avr/boards.txt index 3beedb6..8c65e09 100644 --- a/BootLoaders/Boards/avr/boards.txt +++ b/BootLoaders/Boards/avr/boards.txt @@ -22,13 +22,13 @@ multiatmega328p.build.variant=arduino:eightanaloginputs multiatmega328p.build.extra_flags=-Wl,--relax multiatmega328p.build.board=MULTI_AVR -multiatmega328p.build.compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects -multiatmega328p.compiler.c.elf.flags=-Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -multiatmega328p.compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD - -multiatmega328p.tools.avrdude.config.path={path}/etc/avrdude.conf -multiatmega328p.tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m -multiatmega328p.tools.avrdude.bootloader.pattern= +multiatmega328p.board.compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -fno-fat-lto-objects +multiatmega328p.board.compiler.c.elf.flags=-Os -g -flto -fuse-linker-plugin -Wl,--gc-sections +multiatmega328p.board.compiler.S.flags=-c -g -x assembler-with-cpp -flto -MMD +multiatmega328p.board.recipe.output.save_file=multi-avr.hex +multiatmega328p.board.tools.avrdude.config.path={path}/etc/avrdude.conf +multiatmega328p.board.tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m +multiatmega328p.board.tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m multiatmega328p.bootloader.tool=arduino:avrdude multiatmega328p.bootloader.low_fuses=0xFF @@ -63,19 +63,20 @@ multixmega32d4.build.f_cpu=32000000L multixmega32d4.build.core=xmega multixmega32d4.build.variant=xmega32d4 -multixmega32d4.upload.tool=avrdude +multixmega32d4.upload.tool=arduino:avrdude multixmega32d4.upload.protocol=avrispmkii multixmega32d4.upload.maximum_size=32768 multixmega32d4.upload.speed=57600 multixmega32d4.bootloader.tool=arduino:avrdude -multixmega32d4.build.compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -multixmega32d4.compiler.c.elf.flags=-Os -flto -Wl,--gc-sections -multixmega32d4.compiler.S.flags=-c -g -x assembler-with-cpp -flto +multixmega32d4.board.compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto +multixmega32d4.board.compiler.c.elf.flags=-Os -flto -Wl,--gc-sections +multixmega32d4.board.compiler.S.flags=-c -g -x assembler-with-cpp -flto +multixmega32d4.board.recipe.output.save_file=multi-orx.hex -multixmega32d4.tools.avrdude.config.path={runtime.platform.path}/avrdude.conf -multixmega32d4.tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Ufuse1:w:{bootloader.fuse1}:m -Ufuse2:w:{bootloader.fuse2}:m -Ufuse4:w:{bootloader.fuse4}:m -Ufuse5:w:{bootloader.fuse5}:m -multixmega32d4.tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uboot:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m +multixmega32d4.board.tools.avrdude.config.path={runtime.platform.path}/avrdude_xmega.conf +multixmega32d4.board.tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Ufuse1:w:{bootloader.fuse1}:m -Ufuse2:w:{bootloader.fuse2}:m -Ufuse4:w:{bootloader.fuse4}:m -Ufuse5:w:{bootloader.fuse5}:m +multixmega32d4.board.tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uboot:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m ############################################################## diff --git a/BootLoaders/Boards/avr/platform.local.txt b/BootLoaders/Boards/avr/platform.local.txt index 65ae6a9..2b786ce 100644 --- a/BootLoaders/Boards/avr/platform.local.txt +++ b/BootLoaders/Boards/avr/platform.local.txt @@ -1,16 +1,8 @@ -## Save hex -recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file=multi-avr.hex +## Override some platform.txt settings to create a .bin instead of a .hex file +## The two lines below can be uncommented to have the compiler create a .bin file instead of a .hex file +#compiler.elf2hex.flags=-O binary -R .eeprom +#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}.bin" -## Copy hex -# Make a copy of the compiled binary with the version number in the file name -recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} - -# If we're exporting the hex file, rename it with the version number -recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT +## Make a .bin version of the .hex file +## The line below can be uncommented to have a .bin file made as well as the .hex file +#recipe.hooks.objcopy.postobjcopy.00.pattern.windows="{compiler.path}{compiler.objcopy.cmd}" -I ihex "{build.path}/{build.project_name}.hex" -O binary "{build.path}/{build.project_name}.bin" diff --git a/BootLoaders/Boards/avr/platform.txt b/BootLoaders/Boards/avr/platform.txt index d9d7361..bf03cca 100644 --- a/BootLoaders/Boards/avr/platform.txt +++ b/BootLoaders/Boards/avr/platform.txt @@ -17,10 +17,10 @@ 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.path}/bin/ compiler.c.cmd=avr-gcc -compiler.c.flags={build.compiler.c.flags} -compiler.c.elf.flags={compiler.warning_flags} {build.compiler.c.elf.flags} +compiler.c.flags={board.compiler.c.flags} +compiler.c.elf.flags={compiler.warning_flags} {board.compiler.c.elf.flags} compiler.c.elf.cmd=avr-gcc -compiler.S.flags={build.compiler.S.flags} +compiler.S.flags={board.compiler.S.flags} 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 -MMD -flto compiler.ar.cmd=avr-gcc-ar @@ -70,7 +70,7 @@ recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf ## Save hex recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file={build.project_name}.{build.variant}.hex +recipe.output.save_file={board.recipe.output.save_file} ## Compute size recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" @@ -85,12 +85,26 @@ recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} preproc.macros.flags=-w -x c++ -E -CC recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" +## Post objcopy recipes +# Make a copy of the compiled binary with the version number in the file name +recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} +recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} +recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} +recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} + +## Post savehex (export compiled binary) recipes +# If we're exporting the hex file, rename it with the version number +recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT +recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT +recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT +recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT + # AVR Uploader/Programmers tools # ------------------------------ tools.avrdude.path={runtime.tools.avrdude.path} tools.avrdude.cmd.path={path}/bin/avrdude -tools.avrdude.config.path={tools.avrdude.config.path} +tools.avrdude.config.path={board.tools.avrdude.config.path} tools.avrdude.upload.params.verbose=-v tools.avrdude.upload.params.quiet=-q -q @@ -108,11 +122,11 @@ tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" {program.verbose} { tools.avrdude.erase.params.verbose=-v tools.avrdude.erase.params.quiet=-q -q -tools.avrdude.erase.pattern={tools.avrdude.erase.pattern} +tools.avrdude.erase.pattern={board.tools.avrdude.erase.pattern} tools.avrdude.bootloader.params.verbose=-v tools.avrdude.bootloader.params.quiet=-q -q -tools.avrdude.bootloader.pattern={tools.avrdude.bootloader.pattern} +tools.avrdude.bootloader.pattern={board.tools.avrdude.bootloader.pattern} tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} diff --git a/BootLoaders/Boards/avr/tools/win/do_version.bat b/BootLoaders/Boards/avr/tools/win/do_version.bat index f8dd9ad..f124cc0 100644 --- a/BootLoaders/Boards/avr/tools/win/do_version.bat +++ b/BootLoaders/Boards/avr/tools/win/do_version.bat @@ -18,7 +18,11 @@ IF DEFINED DEBUG ( ECHO Multi board: %MULTI_BOARD% ) -SET MULTI_TYPE=avr +IF %MULTI_BOARD%==MULTI_NO_BOOT SET MULTI_TYPE=avr +IF %MULTI_BOARD%==MULTI_FLASH_FROM_TX SET MULTI_TYPE=avr +IF %MULTI_BOARD%==MULTI_STM32_NO_BOOT SET MULTI_TYPE=stm +IF %MULTI_BOARD%==MULTI_STM32_FLASH_FROM_TX SET MULTI_TYPE=stm +IF %MULTI_BOARD%==MULTI_ORANGERX SET MULTI_TYPE=orx IF EXIST "%BUILD_PATH%\sketch\Multiprotocol.h" ( IF DEFINED DEBUG ECHO Getting Multi-MODULE firmware version from "%BUILD_PATH%\sketch\Multiprotocol.h" diff --git a/BootLoaders/Boards/orangerx/boards.txt b/BootLoaders/Boards/orangerx/boards.txt deleted file mode 100644 index 6857042..0000000 --- a/BootLoaders/Boards/orangerx/boards.txt +++ /dev/null @@ -1,19 +0,0 @@ -# See: https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification -# See: http://code.google.com/p/arduino/wiki/Platforms - -############################################################## - -############################################################## -## Multi 4-in-1 (OrangeRX) -## -------------------------------------------------- -multixmega32d4.name=Multi 4-in-1 (OrangeRX) -multixmega32d4.build.board=MULTI_ORANGERX=103 -multixmega32d4.upload.protocol=arduino -multixmega32d4.upload.maximum_size=32768 -multixmega32d4.upload.speed=115200 -multixmega32d4.build.mcu=atxmega32d4 -multixmega32d4.build.f_cpu=32000000L -multixmega32d4.build.core=xmega -multixmega32d4.build.variant=xmega32d4 - -############################################################## diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Arduino.h b/BootLoaders/Boards/orangerx/cores/xmega/Arduino.h deleted file mode 100644 index 0ee9cd8..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Arduino.h +++ /dev/null @@ -1,450 +0,0 @@ -/* - Arduino.h - standard definitions for Arduino build environment - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2007 David A. Mellis [duplicated from pins_arduino.h, not present in original] - - 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 - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - for the XMegaForArduino project - http://github.com/XMegaForArduino - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - - -#ifndef Arduino_h -#define Arduino_h - -#include -#include -#include - -#include -#include -#include - -#include "binary.h" - -#ifdef __cplusplus -extern "C"{ -#endif // __cplusplus - -#define HIGH 0x1 -#define LOW 0x0 - -#define INPUT 0x0 /* totem poll, input */ -#define OUTPUT 0x1 /* totem poll, output */ -#define INPUT_BUS_KEEPER 0x2 /* weak pull up/down to maintain state when switched to or in input mode */ -#define INPUT_PULLUP 0x3 /* pullup resistor on input */ -#define INPUT_PULLDOWN 0x4 /* pulldown resistor on input */ -#define OUTPUT_OR 0x5 /* output open drain 'or', no pulldown */ -#define OUTPUT_AND 0x6 /* output open drain 'and', no pullup */ -#define INPUT_OR_PULLDOWN 0x7 /* output open drain 'or' with pulldown */ -#define INPUT_AND_PULLUP 0x8 /* output open drain 'and' with pullup */ -#define OUTPUT_OR_PULLDOWN 0x9 /* output open drain 'or' with pulldown */ -#define OUTPUT_AND_PULLUP 0xa /* output open drain 'and' with pullup */ -#define INPUT_OUTPUT_MASK 0xf /* mask for INPUT/OUTPUT flags */ -#define INPUT_SENSE_DEFAULT 0 /* input sense default - currently 'BOTH' */ -#define INPUT_SENSE_RISING 0x10 /* just rising */ -#define INPUT_SENSE_FALLING 0x20 /* just falling */ -#define INPUT_SENSE_BOTH 0x30 /* rising AND falling */ -#define INPUT_SENSE_LEVEL 0x40 /* high level (or low if I invert it) */ -#define INPUT_SENSE_DISABLED 0x50 /* buffered input disabled (most pins won't be able to use 'IN' if you do this) */ -#define INPUT_SENSE_MASK 0x70 /* mask for 'input sense' bits */ -#define INPUT_OUTPUT_INVERT 0x80 /* bit for 'inverted' I/O - note that digitalRead and digitalWrite will re-invert to maintain consistency */ - -// NOTE: 'INPUT_OUTPUT_INVER' is primarily there to support LOW LEVEL interrupts. if you specify this flag for normal -// digital I/O, there will be no 'visible effect' since digitalRead and digitalWrite will "re-invert" the bit value -// and act as if the invert flag weren't set. That way, if you select 'LOW LEVEL' interrupt, you will read the -// low level as a '0' (as it should be) via digitalRead, even though the value MUST be inverted for this to work. - -// NOTE: the values of 'true' and 'false' should be defined by C++ already -#define true /*0x1*/(!0) /* rather than '1' true is defined as '!0' - it's logically accurate */ -#define false 0x0 - -#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 - -/* I do not know what these next 4 #defines do, but all 4 seem to be WRONG - bf */ -#define SERIAL 0x0 -#define DISPLAY 0x1 - -#define LSBFIRST 0 -#define MSBFIRST 1 - -// INTERRUPT TYPE - LOW, HIGH, CHANGE, FALLING, RISING (compatibility with DUE etc.) -// 'LOW' is defined as '0' already -// 'HIGH' is defined as '1' already -#define CHANGE 2 -#define FALLING 3 -#define RISING 4 - -// definitions for atmega328 etc. carried forward - not sure what this is for -#define INTERNAL 3 -#define DEFAULT 1 -#define EXTERNAL 0 - -// undefine stdlib's abs if encountered (from 'arduino' version) -#ifdef abs -#undef abs -#endif - -#define min(a,b) ((a)<(b)?(a):(b)) -#define max(a,b) ((a)>(b)?(a):(b)) -#define abs(x) ((x)>0?(x):-(x)) -#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) -#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) -#define radians(deg) ((deg)*DEG_TO_RAD) -#define degrees(rad) ((rad)*RAD_TO_DEG) -#define sq(x) ((x)*(x)) - -#define interrupts() sei() -#define noInterrupts() cli() - -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) -#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) - -#define lowByte(w) ((uint8_t) ((w) & 0xff)) -#define highByte(w) ((uint8_t) ((w) >> 8)) - -#define bitRead(value, bit) (((value) >> (bit)) & 0x01) -#define bitSet(value, bit) ((value) |= (1UL << (bit))) -#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) -#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) - - -typedef unsigned int word; - -#define bit(b) (1UL << (b)) - -typedef uint8_t boolean; -typedef uint8_t byte; - -void init(void); -void initVariant(void); - -int atexit(void (*func)()) __attribute__((weak)); - -void adc_setup(void); // implemented in wiring_analog.c - configures ADC for analogRead() -// adc_setup must be called whenever exiting SLEEP MODE or ADC will malfunction -// It is automatically called from 'init()' but sleep mode typically resets the controller - -void pinMode(uint8_t, uint8_t); -void digitalWrite(uint8_t, uint8_t); -int digitalRead(uint8_t); -int analogRead(uint8_t); -void analogReference(uint8_t mode); // somewhat different for xmega (default is Vcc/2) - see 'enum _analogReference_', below - // pass only one of THOSE values as 'mode' -void analogWrite(uint8_t, int); - -// special XMEGA-specific functions for the analog inputs - -int analogReadDeltaWithGain(uint8_t pin, uint8_t negpin, uint8_t gain); -// typically 'pin' can be A0 through An, 'negpin' may be restricted but typically A4-A7 or 'ANALOG_READ_DELTA_USE_GND' to use GND -// NOTE: On the A-series processors it is NOT possible to use 'diff input with gain' on MORE than A0-A7 -// On later processors (like D series) it _IS_ possible. - - -#define ANALOG_READ_DELTA_USE_GND 0xff - -// there is a bug in several headers for ADC_REFSEL_gm - should be 0x70, not 0x30 (and it gets re-defined, too) -#ifdef ADC_REFSEL_gm -#undef ADC_REFSEL_gm -#endif // ADC_REFSEL_gm -#define ADC_REFSEL_gm 0x70 - -enum _analogReference_ // pass to 'analogReference' function - see D manual section 22.14.3, or 28.16.3 in 'AU' manual -{ - analogReference_INT1V = (ADC_REFSEL_INT1V_gc), - analogReference_PORTA0 = (ADC_REFSEL_AREFA_gc), // PORT A pin 0 is the AREF - -#if !defined (__AVR_ATxmega8E5__) && !defined (__AVR_ATxmega16E5__) && !defined (__AVR_ATxmega32E5__) - // these 2 aren't valid for 'E' series - analogReference_PORTB0 = (ADC_REFSEL_AREFB_gc), // PORT B pin 0 is the AREF - - analogReference_VCC = (ADC_REFSEL0_bm) /* (ADC_REFSEL_VCC_gc)*/, // VCC / 10, actually - // NOTE: 'ADC_REFSEL_VCC_gc' exists for some headers, and others 'ADC_REFSEL_INTVCC_gc' - // to avoid compile problems I use the bitmask instead. -#endif // E series - -#if defined(__AVR_ATxmega64d4__) || defined(__AVR_ATxmega64a1u__) || defined(__AVR_ATxmega128a1u__) - analogReference_VCCDIV2 = (ADC_REFSEL_VCCDIV2_gc) // using THIS forces gain to 1/2, so it's rail-rail -#else - analogReference_VCCDIV2 = (0x04<<4) // (ADC_REFSEL_VCCDIV2_gc) - // NOTE that for some processor headers, ADC_REFSEL_VCCDIV2_gc is not properly defined - // this definition '(0x04<<4)' is taken from the 64d4 header. it's also THE DEFAULT for max compatibility -#endif // processors that define ADC_REFSEL_VCCDIV2_gc correctly -}; - -// NOTE: this constant isn't always defined, either -#ifndef ADC_CH_GAIN_gm -#define ADC_CH_GAIN_gm 0x1C /* Gain Factor group mask. */ -#endif // ADC_CH_GAIN_gm - - -unsigned long millis(void); -unsigned long micros(void); -void delay(unsigned long); -void delayMicroseconds(unsigned int us); -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); - -void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); -uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); - -// XMEGA specific -void wait_for_interrupt(void); // uses 'IDLE' sleep mode to wait for an interrupt, then returns -void low_power_delay(unsigned long ms); // similar to 'delay' but goes into low power 'IDLE sleep' state - - -// X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A -// -// NOTE: for 'attachInterrupt' the 'mode' parameter indicates non-default input pins -// and the interrupt mode, as well as the interrupt priority. If the interrupt -// priority is INT_MODE_PRI_DEFAULT (0), it will be assigned a 'default' value. -// Default interrupt pin is pin 2 except for PORTR (since it doesn't have a pin 2) -// when it has not been specified. -// -// usage: -// attachInterrupt(PORTD_INT0, the specific interrupt vector - see pins_arduino.h -// my_callback, user-defined callback function -// RISING interrupt mode (can be LOW, HIGH, RISING, FALLING, CHANGE) -// | INT_MODE_PIN_DEFAULT the pin(s) to assign to this interrupt, or default pin 2 (optional) -// | INT_MODE_PRI_DEFAULT); interrupt priority, default is 'high' (optional) -// -// Additional note, the 'pin' constants (see below) refer to the port's pin number, and -// NOT the 'digital I/O pin' number. See 'pins_arduino.h' for more on this. -// -// for compatibility with newer arduino environment, attachInterrupt 'interruptNum' parameter -// can use the return value from 'digitalPinToInterrupt(pin)' -// -// X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A - -#ifdef __cplusplus -void attachInterrupt(uint8_t interruptNum, void (*)(void), int mode = 0); // default 'mode' param is: LOW | INT_MODE_PRI_DEFAULT | INT_MODE_PIN_DEFAULT -#else // not __cplusplus -void attachInterrupt(uint8_t interruptNum, void (*)(void), int mode); -#endif // __cplusplus - -void detachInterrupt(uint8_t interruptNum); // NOTE: detaches ALL interrupts for that port (special exceptions for serial flow control) - - -// this next function reads data from the calibration row, including the serial # info. -// This is often referred to as the 'PRODUCT SIGNATURE ROW'. It is xmega-specific. -uint8_t readCalibrationData(uint16_t iIndex); - - -// INTERRUPT MODE FLAGS - for attachInterrupt 'mode' parameter - -#define INT_MODE_MODE_MASK 0x003f -#define INT_MODE_PRI_MASK 0x00c0 -#define INT_MODE_PRI_DEFAULT 0 -#define INT_MODE_PRI_LOW 0x0040 -#define INT_MODE_PRI_MED 0x0080 -#define INT_MODE_PRI_HIGH 0x00c0 -#define INT_MODE_PRI_SHIFT 6 /* shift right 6 bits to get a 0, 1, 2 or 3 for priority (0 is 'default') */ -#define INT_MODE_PIN_MASK 0xff00 -#define INT_MODE_PIN0 0x0100 -#define INT_MODE_PIN1 0x0200 -#define INT_MODE_PIN2 0x0400 -#define INT_MODE_PIN3 0x0800 -#define INT_MODE_PIN4 0x1000 -#define INT_MODE_PIN5 0x2000 -#define INT_MODE_PIN6 0x4000 -#define INT_MODE_PIN7 0x8000 -#define INT_MODE_PIN_DEFAULT 0 /* no 'pin bits' set implies 'default' which is pin 2 on each capable port */ -#define INT_MODE_PIN_SHIFT 8 /* shift right 8 bits to get the pin bits in a single byte */ - -// NOTE: the 'pin' constants refer to the port's pin number, and not the digital I/O pin -// The default 'pin 2' refers to the port's pin 2. See 'pins_arduino.h' for more on this. -// Multiple pins may be specified, so it is a bit mask. If a pin is specified by using -// digitalPinToInterrupt() and you also specify pins using the 'INT_MODE_PINx' flags, the -// pin specified in the 'interruptNum' parameter will be 'or'd with the pins specified in -// 'mode'. This can result in some unpredictable outcomes, so you should either use -// 'digitalPinToInterrupt' for 'interruptNum', or specify the port as 'interruptNum' and -// then specfify the pin info in 'mode'. - - -#define NOT_AN_INTERRUPT (-1) /* a placeholder for various arrays, etc. */ - - - - -// SETUP and LOOP (no changes from Arduino classic) - -void setup(void); -void loop(void); - - -// hardware flow control 'helpers' -void serial_0_cts_callback(void); -void serial_1_cts_callback(void); -void InitSerialFlowControlInterrupts(void); - - -// On the xmega, the addresses of the port registers are -// greater than 255, so we can't store them in uint8_t's. -extern const uint16_t PROGMEM port_to_mode_PGM[]; -extern const uint16_t PROGMEM port_to_input_PGM[]; -extern const uint16_t PROGMEM port_to_output_PGM[]; -extern const uint16_t PROGMEM digital_pin_to_control_PGM[]; - -// these contain index values so they CAN be uint8_t's -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; -// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; not used on xmega -extern const uint16_t PROGMEM port_to_input_PGM[]; - -// 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. -// -// These perform slightly better as macros compared to inline functions -// -#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) -#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) -#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) -// note pins_arduino.h may need to override this next one, depending -#define analogInPinToBit(P) ((P) & 7) /* analog pin 0 = 0 (PORTA), analog pin 8 = 0 (PORTB) */ -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) -#define pinControlRegister(P) ( (volatile uint8_t *)( pgm_read_word( digital_pin_to_control_PGM + (P))) ) - -// use THIS macro to convert a _BV(n) value into 'n' -#define pinBitValueToIndex(B) ( (B)==_BV(0) ? 0 : (B)==_BV(1) ? 1 : (B)==_BV(2) ? 2 : (B)==_BV(3) ? 3 : \ - (B)==_BV(4) ? 4 : (B)==_BV(5) ? 5 : (B)==_BV(6) ? 6 : (B)==_BV(7) ? 7 : 0 ) - -#define NOT_A_PIN 0 -#define NOT_A_PORT 0 - -#ifdef ARDUINO_MAIN -// use of '_' prefix to prevent collisions with iox64d#.h and for consistency -#define _PA 1 -#define _PB 2 -#define _PC 3 -#define _PD 4 -#define _PE 5 -#define _PR 6 /* was PF */ -#define _PF 7 -#define _PH 8 -#define _PJ 9 -#define _PK 10 -#define _PQ 11 -#endif - -// modified timer definitions for xmega -// TCD2 --> TIMERD2 -// TCC2 --> TIMERC2 -// TCE0 --> TIMERE0 - 'D' series which has only 4 pins on PORTE */ -// TCE2 --> TIMERE2 - A series and others that use all 8 pins for port E -// TCF2 --> TIMERF2 - A series and others that have PORT F -#define NOT_ON_TIMER 0 -#define TIMERD2 1 -#define TIMERC2 2 -#define TIMERE0 3 -#define TIMERE2 4 -#define TIMERF2 5 -#define TIMERC4 6 -#define TIMERD5 7 -// not using TCD0,1 nor TCC0,1 -// The first 16 IO pins (PD0-PD7, PC0-PC7) will be PWM capable, as are PE0-PE3 (or PE0-PE7) and PF0-PF7 (when there) - - -#ifdef __cplusplus -} // extern "C" -#endif // __cplusplus - -#ifdef __cplusplus -#include "WCharacter.h" -#include "WString.h" -#include "HardwareSerial.h" - -uint16_t makeWord(uint16_t w); -uint16_t makeWord(byte h, byte l); - -#define word(...) makeWord(__VA_ARGS__) - -#if 0 -// these are not currently implemented - TODO implement them - -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); -#endif // 0 - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); -void noTone(uint8_t _pin); - - -// WMath prototypes -long random(long); -long random(long, long); -void randomSeed(unsigned int); -long map(long, long, long, long, long); - -#endif // __cplusplus - -// at this point we include the pin definitions from 'pins_arduino.h' -// you can customize 'pins_arduino.h' for your specific hardware - -#include "pins_arduino.h" - -// The default SPI interface is SPIC if not already defined -#ifndef DEFAULT_SPI -#define DEFAULT_SPI SPIC -#endif // DEFAULT_SPI - -// the default TWI interface is TWIC if not already defined -#ifndef DEFAULT_TWI -#define DEFAULT_TWI TWIC -#endif // DEFAULT_TWI - - -// added support for hardware serial flow control - spans multiple files - -#if defined(SERIAL_0_RTS_PORT_NAME) && defined(SERIAL_0_RTS_PIN_INDEX) -#define SERIAL_0_RTS_ENABLED -#define SERIAL_0_RTS_PORT (&SERIAL_0_RTS_PORT_NAME) -#define SERIAL_0_RTS_PIN _BV(SERIAL_0_RTS_PIN_INDEX) -#endif // defined(SERIAL_0_RTS_PORT) && defined(SERIAL_0_RTS_PIN) - -#if defined(SERIAL_1_RTS_PORT_NAME) && defined(SERIAL_1_RTS_PIN_INDEX) -#define SERIAL_1_RTS_ENABLED -#define SERIAL_1_RTS_PORT (&SERIAL_1_RTS_PORT_NAME) -#define SERIAL_1_RTS_PIN _BV(SERIAL_1_RTS_PIN_INDEX) -#endif // defined(SERIAL_1_RTS_PORT) && defined(SERIAL_1_RTS_PIN) - -#if defined(SERIAL_0_CTS_PORT_NAME) && defined(SERIAL_0_CTS_PIN_INDEX) -#define SERIAL_0_CTS_ENABLED -#define SERIAL_0_CTS_PORT (&SERIAL_0_CTS_PORT_NAME) -#define SERIAL_0_CTS_PIN _BV(SERIAL_0_CTS_PIN_INDEX) -#endif // defined(SERIAL_0_CTS_PORT) && defined(SERIAL_0_CTS_PIN) - -#if defined(SERIAL_1_CTS_PORT_NAME) && defined(SERIAL_1_CTS_PIN_INDEX) -#define SERIAL_1_CTS_ENABLED -#define SERIAL_1_CTS_PORT (&SERIAL_1_CTS_PORT_NAME) -#define SERIAL_1_CTS_PIN _BV(SERIAL_1_CTS_PIN_INDEX) -#endif // defined(SERIAL_1_CTS_PORT) && defined(SERIAL_1_CTS_PIN) - - -#endif // Arduino_h - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp b/BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp deleted file mode 100644 index e07a17d..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp +++ /dev/null @@ -1,541 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// ____ ____ ____ // -// / ___|| _ \ / ___| ___ _ __ _ __ // -// | | | | | || | / __|| '_ \ | '_ \ // -// | |___ | |_| || |___ _| (__ | |_) || |_) | // -// \____||____/ \____|(_)\___|| .__/ | .__/ // -// |_| |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -/* 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. -*/ - -// Updated for the XMegaForArduino project by Bob Frazier, S.F.T. Inc. - -///////////////////////////////////////////////////////////////////////////////// -// XMEGA NOTES: -// -// a) major re-factoring, including API functions -// b) K&R style is hard to read. I won't use it. Hard tabs are evil. Same. -// -///////////////////////////////////////////////////////////////////////////////// - - - -#include "Platform.h" -#include "USBAPI.h" -#include - -#if defined(USBCON) -#ifdef CDC_ENABLED - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#define PROGMEM_ORIG PROGMEM -#else // PROGMEM workaround - -// to avoid the bogus "initialized variables" warning -#ifdef PROGMEM -#undef PROGMEM -#endif // PROGMEM re-define - -#define PROGMEM __attribute__((section(".progmem.cdc"))) -#define PROGMEM_ORIG __attribute__((__progmem__)) - -#endif // check for GNUC >= or < 4.6 - - -typedef struct -{ - u32 dwDTERate; // little-endian line rate - u8 bCharFormat; // stop bits = one, one-and-a-half, two (0, 1, 2 respectively) - u8 bParityType; // none, odd, even, mark, space (0 through 4) - u8 bDataBits; // char bits 5, 6, 7, 8 -} __attribute__((aligned(1))) LineInfo; - -static volatile LineInfo _usbLineInfo; // for initialization, see CDC_Reset -static u8 _cdcLineState; -static u16 _cdcSerialState; -static uint16_t wInterval; - -#define WEAK __attribute__ ((weak)) - -extern const DeviceDescriptor _cdcDeviceDescriptor PROGMEM; -extern const IADDescriptor _cdcIADDesc PROGMEM; -extern const CDCDescriptor _cdcInterface PROGMEM; - - -// CDC DEVICE DESCRIPTOR (for CDC device) - sent by CDC_SendDeviceDescriptor() - -const DeviceDescriptor _cdcDeviceDescriptor PROGMEM = - D_DEVICE(USB_DEVICE_CLASS_COMMUNICATIONS, // device class (COMM) - CDC_COMMUNICATION_INTERFACE_CLASS, // device sub-class (CDC COMM) - CDC_ABSTRACT_CONTROL_MODEL, // device protocol (ACM) - 64, // packet size (64) - USB_VID, // vendor ID for the USB device - USB_PID, // product ID for the USB device - 0x100, // device release version as BCD (1.00) - USB_STRING_INDEX_MANUFACTURER, // string index for mfg - USB_STRING_INDEX_PRODUCT, // string index for product name - USB_STRING_INDEX_SERIAL, // string index for serial number (0 for 'none') - 1); // number of configurations (1) - - -// IAD descriptor - REQUIRED for composite interfaces, sent via CDC_SendIAD() - -const IADDescriptor _cdcIADDesc = D_IAD(0, // first interface - 2, // count (interfaces, not endpoints) - CDC_COMMUNICATION_INTERFACE_CLASS, // interface class - CDC_ABSTRACT_CONTROL_MODEL, // interface sub-class - 1); // protocol - -// CDC interface descriptor - sent by CDC_SendInterfaceData() - -const CDCDescriptor _cdcInterface = // needs to be no more than 55 bytes in length -{ - // FIRST INTERFACE - // CDC communication interface (endpoint 0) - D_INTERFACE(CDC_ACM_INTERFACE, // 'n' - 1, // number of endpoints - CDC_COMMUNICATION_INTERFACE_CLASS, // interface class - CDC_ABSTRACT_CONTROL_MODEL, // interface sub-class - 0), // protocol - - // these headers describe the supported interfaces - D_CDCCS(CDC_HEADER,0x10,0x01), // CDCCS InterfaceDescriptor Header (1.10 bcd) - version 1.10? -// D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management (seems to be optional) - 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), // IN endpoint for CDC_ENDPOINT_ACM - USB_ENDPOINT_TYPE_INTERRUPT, // INTERRUPT type - 0x10, // max packet size 16 - 0x40), // interval 64 frames i.e. 64 msec (see USB spec table 9-13) - - // SECOND INTERFACE - // CDC data interface (endpoints 1, 2) - D_INTERFACE(CDC_DATA_INTERFACE, // 'n' - 2, // number of endpoints - CDC_DATA_INTERFACE_CLASS, // interface class - 0, // interface sub-class - 0), // protocol - - D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT), // OUT endpoint, index 'CDC_ENDPOINT_OUT' - USB_ENDPOINT_TYPE_BULK, // BULK data transfers - 0x40, // max packet size 64 - 1), // interval 1 (was 0) - - D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN), // IN endpoint, index 'CDC_ENDPOINT_IN' - USB_ENDPOINT_TYPE_BULK, // BULK data transfers - 0x40, // max packet size 64 - 0) // interval 0 (apparently not needed) -}; - -void WEAK CDC_Reset(void) -{ - _usbLineInfo.dwDTERate = 115200; - - _usbLineInfo.bCharFormat - = _usbLineInfo.bParityType - = _usbLineInfo.bDataBits - = 0; // says I'm not initialized, basically - - _cdcLineState = 0; - _cdcSerialState = 0; - - wInterval = 0; -} - -bool WEAK CDC_SendIAD(void) -{ - return USB_SendControl(TRANSFER_PGM, &_cdcIADDesc, sizeof(_cdcIADDesc)) - != 0; -} - -int WEAK CDC_GetNumInterfaces(void) -{ - return 2; // always 2 -} - -int WEAK CDC_GetInterfaceDataLength(void) -{ - return sizeof(_cdcInterface); -} - -int WEAK CDC_SendInterfaceData(void) -{ - return USB_SendControl(TRANSFER_PGM, &_cdcInterface, sizeof(_cdcInterface)); -} - -bool WEAK CDC_SendDeviceDescriptor(void) -{ - return 0 != USB_SendControl(TRANSFER_PGM, &_cdcDeviceDescriptor, sizeof(_cdcDeviceDescriptor)); -} - -bool WEAK CDC_Setup(Setup& setup) -{ - u8 r = setup.bRequest; - u8 requestType = setup.bmRequestType; - - if(REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) - { - if (CDC_GET_LINE_CODING == r) - { - error_printP(F("Get Line Coding")); - -#if 1 - USB_SendControl(0,(void*)&_usbLineInfo, sizeof(_usbLineInfo)/*7*/); -#endif // 0 - - return true; - } - } - else if(REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) - { - if(CDC_SET_LINE_CODING == r) - { - error_printP_(F("CDC_SET_LINE_CODING")); - - // setup packet is followed by data? - memcpy((void *)&_usbLineInfo, (char *)&(setup) + sizeof(Setup), sizeof(_usbLineInfo)); - - error_printP_(F(" rate:")); - error_printL_(_usbLineInfo.dwDTERate); - error_printP_(F(" fmt:")); - error_printL_(_usbLineInfo.bCharFormat); - error_printP_(F(" par:")); - error_printL_(_usbLineInfo.bParityType); - error_printP_(F(" bit:")); - error_printL(_usbLineInfo.bDataBits); - - USB_SendControl(0, NULL, 0); // send a ZLP - - _cdcLineState = CONTROL_LINE_STATE_DTR; // for now... assume "this" - - // now set up the ACM interrupt info in '_cdcSerialState' and send it back - - _cdcSerialState = SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data" (always) - - return true; - } - else if(CDC_SET_CONTROL_LINE_STATE == r) - { - error_printP_(F("Set Control Line State: ")); - error_printL(setup.wValueL); - - _cdcLineState = setup.wValueL; - - // NOTE: this next part is for the 'caterina' CDC bootloader, arduino/bootloaders/caterina/Caterina.c - // it has some "special" code in it, like using 0x0800 in RAM as an address for a 'key' (7777H) - // to indicate it was soft-booted. XMEGA has better ways of handling this, like a CPU flag that - // indicates "I was soft-booted" as one example, and a 'WDT' timeout flag on top of that. - - // 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 - - if (1200 == _usbLineInfo.dwDTERate) - { - // We check DTR state to determine if host port is open (bit 0 of _cdcLineState). - if ((_cdcLineState & 0x01) == 0) - { -// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently) -// -// *(uint16_t *)0x0800 = 0x7777; note that on XMEGA this is a VERY bad thing -// wdt_enable(WDTO_120MS); -// -// on the atmega, address 800H is the start of the final 256-byte page in RAM space for 2k RAM -// -// atmega328(p) RAM goes from 0x100 through 0x8ff - see datasheet for atmega 328 [etc.] section 8.3 -// 32U4 RAM goes through 0xaff - see datasheet for U4 processors, section 5.2 -// 8/16/32U2 RAM goes through 4FFH so this won't even work - see datasheet for U2 processors, section 7.2 -// basically it's a 'hack' and needs to be re-evaluated - - // TODO: would it be safe to enable interrupts, NOT return from this function, - // and simply wait until the appropriate time has elapsed? Or, as is - // handled in the section below, this 'wait period' is canceled - - // TODO: if I use a function that's part of the USB driver to trigger a soft boot, I can detect - // that a soft boot has taken place using the bits in the 'RESET' status register. If all - // I have to do is detect this, it's not a problem, and I won't need "magic memory locations" - -// TODO: timeout-based reboot - } - else - { - // 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 250ms and eventually - // cancel if DTR goes back high. - -// This section of code is support for the 'caterina' bootloader, which allows USB flashing (apparently) -// -// TODO: reset whatever boot timeout I did -// wdt_disable(); -// wdt_reset(); -// *(uint16_t *)0x0800 = 0x0; note that on XMEGA this is a VERY bad thing - } - } - - USB_SendControl(0, NULL, 0); // send a ZLP - - return true; - } - } - - // unrecognized request - report it - - error_printP_(F("CDC request: type=")); - error_printL_(requestType); - error_printP_(F(" request=")); - error_printL(r); - return false; -} - -// 'frame received' callback - notification that a 'Start Of Frame' took place - -void CDC_FrameReceived(void) -{ -bool bSend = false; - - // NOTE: if I haven't configured the baud/bits yet, or the DTR bit is cleared, - // do NOT send anything nor muck with the flags. Wait until the device - // is actually RUNNING, first. - - if(!_usbLineInfo.bDataBits || !(_cdcLineState & CONTROL_LINE_STATE_DTR)) - { - return; // don't do anything if I haven't properly set up the data bits yet - } - - if(USB_Available(CDC_RX) >= 64) // allow ~64 buffered bytes - { - if(_cdcSerialState & SERIAL_STATE_RX_CARRIER_DCD) // was on? - { - _cdcSerialState &= ~SERIAL_STATE_RX_CARRIER_DCD; - - bSend = true; - } - } - else - { - if(!(_cdcSerialState & SERIAL_STATE_RX_CARRIER_DCD)) // was off? - { - _cdcSerialState |= SERIAL_STATE_RX_CARRIER_DCD; - - bSend = true; - } - } - -// if(USB_SendQLength(CDC_TX) > 0) // anything to send?? -// { -// if(!(_cdcSerialState & SERIAL_STATE_TX_CARRIER_DSR)) -// { -// _cdcSerialState |= SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data" -// -// bSend = true; -// } -// } -// else -// { -// if(_cdcSerialState & SERIAL_STATE_TX_CARRIER_DSR) -// { -// _cdcSerialState &= ~SERIAL_STATE_TX_CARRIER_DSR; // to tell host "I have data" -// -// bSend = true; -// } -// } - - if((bSend || wInterval >= 64) // will send every 64 'bus cycles' or when there's a change - && !USB_SendQLength(CDC_ACM)) - { - CDC_SendACM(); - - wInterval = 0; - } - else if(wInterval < 64) - { - wInterval++; - } -} - -void CDC_SendACM(void) -{ - USB_Send(CDC_ACM, &_cdcSerialState, sizeof(_cdcSerialState), 1); -} - -void Serial_::begin(unsigned long baud_count) -{ - peek_buffer = -1; -} - -void Serial_::begin(unsigned long baud_count, byte config) -{ - peek_buffer = -1; -} - -void Serial_::end(void) -{ -} - -int Serial_::available(void) -{ - if (peek_buffer >= 0) - { - return 1 + USB_Available(CDC_RX); - } - - return USB_Available(CDC_RX); -} - -int Serial_::peek(void) -{ - if (peek_buffer < 0) - { - if(USBDevice.configured()) - { - 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; - } - - if(USBDevice.configured()) - { - return USB_Recv(CDC_RX); - } - - return -1; -} - -void Serial_::flush(void) -{ - if(USBDevice.configured()) - { - USB_Flush(CDC_TX); - } -} - -size_t Serial_::write(uint8_t c) -{ - 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 _cdcLineState when the port - is opened and clear _cdcLineState 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. */ - - // NOTE: if my outgoing buffer is too full, stop sending - - // 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(USBDevice.configured() && // make sure I'm running -// !USB_IsStalled(CDC_TX) && // make sure I'm not stalled - !USB_IsSendQFull(CDC_TX)) // make sure I'm not flooding the queue - { - if(_cdcLineState & CONTROL_LINE_STATE_DTR) // make sure DTR is set - { - if(size > 128) - { - size = 128; // adjust size DOWN to limit output buffer size - } - - int r = USB_Send(CDC_TX, buffer, size, 1); - - // TODO: check for partial sends and retry?? - - if(r > 0) - { - CDC_FrameReceived(); // inform the host of my data send/receive state - - return r; - } - } - } - - // TODO: block? - - 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 -// setup() before printing to ensure that an application on the host is -// actually ready to receive and display the data. - -Serial_::operator bool() -{ - bool result = false; - if(USBDevice.configured() - && (_cdcLineState & CONTROL_LINE_STATE_DTR) - && !USB_IsSendQFull(CDC_TX) -// && !USB_IsStalled(CDC_TX) - ) - { - result = true; - } - -// We add a short delay before returning to fix a bug observed by Federico -// where the port is configured (_cdcLineState != 0) but not quite opened. -// delay(10); - - if(!result) - { - if(!USBDevice.configured()) - { - error_printP(F("USB device not configured")); - } - else if(!(_cdcLineState & CONTROL_LINE_STATE_DTR)) - { - error_printP(F("DTR is off")); - } - else if(USB_IsSendQFull(CDC_TX)) - { - error_printP(F("Send Queue FULL")); - } -// else if(USB_IsStalled(CDC_TX)) -// { -// error_printP(F("USB is stalled")); -// } - } - - return result; -} - -Serial_ Serial; - -#endif -#endif /* if defined(USBCON) */ - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Client.h b/BootLoaders/Boards/orangerx/cores/xmega/Client.h deleted file mode 100644 index b8e5d93..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Client.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - Client.h - Base class that provides Client - Copyright (c) 2011 Adrian McEwen. 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 -*/ - -#ifndef client_h -#define client_h -#include "Print.h" -#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; - virtual int available() = 0; - virtual int read() = 0; - virtual int read(uint8_t *buf, size_t size) = 0; - virtual int peek() = 0; - virtual void flush() = 0; - virtual void stop() = 0; - virtual uint8_t connected() = 0; - virtual operator bool() = 0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/HID.cpp b/BootLoaders/Boards/orangerx/cores/xmega/HID.cpp deleted file mode 100644 index 53fd4b5..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/HID.cpp +++ /dev/null @@ -1,593 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ___ ____ // -// | | | ||_ _|| _ \ ___ _ __ _ __ // -// | |_| | | | | | | | / __|| '_ \ | '_ \ // -// | _ | | | | |_| |_| (__ | |_) || |_) | // -// |_| |_||___||____/(_)\___|| .__/ | .__/ // -// |_| |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -/* 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. -*/ - -///////////////////////////////////////////////////////////////////////////////// -// XMEGA NOTES: -// -// a) it appears that, at one time at least, this was intended to be overridden -// by user code, hence the use of 'WEAK' all over the place; -// b) This API is *VERY* 'tricky' in that it's tied in heavily with the atmega -// USB implementation and (in some cases) does 'magic things' that are not -// apparently obvious to someone trying to port it to another processor -// (for an example see original use of CDC_GetInterface - lame!) -// c) Given the fact that it's (in my view) POORLY WRITTEN, it deserves a makeover. -// d) K&R style is hard to read. I won't use it. Hard tabs are evil. Same. -// -///////////////////////////////////////////////////////////////////////////////// - -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -#if defined(USBCON) -#ifdef HID_ENABLED - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#define PROGMEM_ORIG PROGMEM -#else // PROGMEM workaround - -// to avoid the bogus "initialized variables" warning -#ifdef PROGMEM -#undef PROGMEM -#endif // PROGMEM re-define - -#define PROGMEM __attribute__((section(".progmem.hid"))) -#define PROGMEM_ORIG __attribute__((__progmem__)) - -#endif // check for GNUC >= or < 4.6 - - -//#define RAWHID_ENABLED - -// Singletons for mouse and keyboard - -Mouse_ Mouse; -Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ - -// HID report descriptor - -#define LSB(_x) ((_x) & 0xFF) -#define MSB(_x) ((_x) >> 8) - -#define RAWHID_USAGE_PAGE 0xFFC0 -#define RAWHID_USAGE 0x0C00 -#define RAWHID_TX_SIZE 64 -#define RAWHID_RX_SIZE 64 - -const u8 _hidReportDescriptor[] PROGMEM = -{ - // Mouse - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 - 0x09, 0x02, // USAGE (Mouse) - 0xa1, 0x01, // COLLECTION (Application) - 0x09, 0x01, // USAGE (Pointer) - 0xa1, 0x00, // COLLECTION (Physical) - 0x85, 0x01, // REPORT_ID (1) - 0x05, 0x09, // USAGE_PAGE (Button) - 0x19, 0x01, // USAGE_MINIMUM (Button 1) - 0x29, 0x03, // USAGE_MAXIMUM (Button 3) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x95, 0x03, // REPORT_COUNT (3) - 0x75, 0x01, // REPORT_SIZE (1) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x05, // REPORT_SIZE (5) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) - 0x09, 0x30, // USAGE (X) - 0x09, 0x31, // USAGE (Y) - 0x09, 0x38, // USAGE (Wheel) - 0x15, 0x81, // LOGICAL_MINIMUM (-127) - 0x25, 0x7f, // LOGICAL_MAXIMUM (127) - 0x75, 0x08, // REPORT_SIZE (8) - 0x95, 0x03, // REPORT_COUNT (3) - 0x81, 0x06, // INPUT (Data,Var,Rel) - 0xc0, // END_COLLECTION - 0xc0, // END_COLLECTION - - // Keyboard - 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47 - 0x09, 0x06, // USAGE (Keyboard) - 0xa1, 0x01, // COLLECTION (Application) - 0x85, 0x02, // REPORT_ID (2) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl) - 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - - 0x95, 0x08, // REPORT_COUNT (8) - 0x81, 0x02, // INPUT (Data,Var,Abs) - 0x95, 0x01, // REPORT_COUNT (1) - 0x75, 0x08, // REPORT_SIZE (8) - 0x81, 0x03, // INPUT (Cnst,Var,Abs) - - 0x95, 0x06, // REPORT_COUNT (6) - 0x75, 0x08, // REPORT_SIZE (8) - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x65, // LOGICAL_MAXIMUM (101) - 0x05, 0x07, // USAGE_PAGE (Keyboard) - - 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated)) - 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application) - 0x81, 0x00, // INPUT (Data,Ary,Abs) - 0xc0, // END_COLLECTION - -#ifdef RAWHID_ENABLED - // RAW HID - 0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30 - 0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), - - 0xA1, 0x01, // Collection 0x01 - 0x85, 0x03, // REPORT_ID (3) - 0x75, 0x08, // report size = 8 bits - 0x15, 0x00, // logical minimum = 0 - 0x26, 0xFF, 0x00, // logical maximum = 255 - - 0x95, 64, // report count TX - 0x09, 0x01, // usage - 0x81, 0x02, // Input (array) - - 0x95, 64, // report count RX - 0x09, 0x02, // usage - 0x91, 0x02, // Output (array) - 0xC0 // end collection -#endif -}; - - -const HIDDescriptor _hidInterface PROGMEM = -{ - D_INTERFACE(HID_INTERFACE,1,3,0,0), - D_HIDREPORT(sizeof(_hidReportDescriptor)), - D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01) -}; - -//================================================================================ -//================================================================================ -// Driver - -u8 _hid_protocol = 1; -u8 _hid_idle = 1; - -#define WEAK __attribute__ ((weak)) - -int WEAK HID_GetNumInterfaces(void) -{ - return 1; // always 1 -} - -int WEAK HID_GetInterfaceDataLength(void) -{ - return sizeof(_hidInterface); -} - -int WEAK HID_SendInterfaceData(void) -{ - return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface)); -} - -int WEAK HID_GetDescriptor(int i) -{ - // NOTE: 'i' is the max size for the request. Should I pay attention to it? - - return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); -} - -void WEAK HID_SendReport(u8 id, const void* data, int len) -{ - USB_Send(HID_TX, &id, 1, 0); - USB_Send(HID_TX,data,len, 1); -} - -bool WEAK HID_Setup(Setup& setup) -{ - u8 r = setup.bRequest; - u8 requestType = setup.bmRequestType; - - if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) - { - if (HID_GET_REPORT == r) - { - //HID_GetReport(); - return true; - } - if (HID_GET_PROTOCOL == r) - { - //Send8(_hid_protocol); // TODO - return true; - } - } - - if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) - { - if (HID_SET_PROTOCOL == r) - { - _hid_protocol = setup.wValueL; - return true; - } - - if (HID_SET_IDLE == r) - { - _hid_idle = setup.wValueL; - return true; - } - } - return false; -} - -//================================================================================ -//================================================================================ -// Mouse - -Mouse_::Mouse_(void) : _buttons(0) -{ -} - -void Mouse_::begin(void) -{ -} - -void Mouse_::end(void) -{ -} - -void Mouse_::click(uint8_t b) -{ - _buttons = b; - move(0,0,0); - _buttons = 0; - move(0,0,0); -} - -void Mouse_::move(signed char x, signed char y, signed char wheel) -{ - u8 m[4]; - m[0] = _buttons; - m[1] = x; - m[2] = y; - m[3] = wheel; - HID_SendReport(1,m,4); -} - -void Mouse_::buttons(uint8_t b) -{ - if (b != _buttons) - { - _buttons = b; - move(0,0,0); - } -} - -void Mouse_::press(uint8_t b) -{ - buttons(_buttons | b); -} - -void Mouse_::release(uint8_t b) -{ - buttons(_buttons & ~b); -} - -bool Mouse_::isPressed(uint8_t b) -{ - if ((b & _buttons) > 0) - { - return true; - } - - return false; -} - -//================================================================================ -//================================================================================ -// Keyboard - -Keyboard_::Keyboard_(void) -{ -} - -void Keyboard_::begin(void) -{ -} - -void Keyboard_::end(void) -{ -} - -void Keyboard_::sendReport(KeyReport* keys) -{ - HID_SendReport(2,keys,sizeof(KeyReport)); -} - -extern -const uint8_t _asciimap[128] PROGMEM; - -#define SHIFT 0x80 -const uint8_t _asciimap[128] = -{ - 0x00, // NUL - 0x00, // SOH - 0x00, // STX - 0x00, // ETX - 0x00, // EOT - 0x00, // ENQ - 0x00, // ACK - 0x00, // BEL - 0x2a, // BS Backspace - 0x2b, // TAB Tab - 0x28, // LF Enter - 0x00, // VT - 0x00, // FF - 0x00, // CR - 0x00, // SO - 0x00, // SI - 0x00, // DEL - 0x00, // DC1 - 0x00, // DC2 - 0x00, // DC3 - 0x00, // DC4 - 0x00, // NAK - 0x00, // SYN - 0x00, // ETB - 0x00, // CAN - 0x00, // EM - 0x00, // SUB - 0x00, // ESC - 0x00, // FS - 0x00, // GS - 0x00, // RS - 0x00, // US - - 0x2c, // ' ' - 0x1e|SHIFT, // ! - 0x34|SHIFT, // " - 0x20|SHIFT, // # - 0x21|SHIFT, // $ - 0x22|SHIFT, // % - 0x24|SHIFT, // & - 0x34, // ' - 0x26|SHIFT, // ( - 0x27|SHIFT, // ) - 0x25|SHIFT, // * - 0x2e|SHIFT, // + - 0x36, // , - 0x2d, // - - 0x37, // . - 0x38, // / - 0x27, // 0 - 0x1e, // 1 - 0x1f, // 2 - 0x20, // 3 - 0x21, // 4 - 0x22, // 5 - 0x23, // 6 - 0x24, // 7 - 0x25, // 8 - 0x26, // 9 - 0x33|SHIFT, // : - 0x33, // ; - 0x36|SHIFT, // < - 0x2e, // = - 0x37|SHIFT, // > - 0x38|SHIFT, // ? - 0x1f|SHIFT, // @ - 0x04|SHIFT, // A - 0x05|SHIFT, // B - 0x06|SHIFT, // C - 0x07|SHIFT, // D - 0x08|SHIFT, // E - 0x09|SHIFT, // F - 0x0a|SHIFT, // G - 0x0b|SHIFT, // H - 0x0c|SHIFT, // I - 0x0d|SHIFT, // J - 0x0e|SHIFT, // K - 0x0f|SHIFT, // L - 0x10|SHIFT, // M - 0x11|SHIFT, // N - 0x12|SHIFT, // O - 0x13|SHIFT, // P - 0x14|SHIFT, // Q - 0x15|SHIFT, // R - 0x16|SHIFT, // S - 0x17|SHIFT, // T - 0x18|SHIFT, // U - 0x19|SHIFT, // V - 0x1a|SHIFT, // W - 0x1b|SHIFT, // X - 0x1c|SHIFT, // Y - 0x1d|SHIFT, // Z - 0x2f, // [ - 0x31, // bslash - 0x30, // ] - 0x23|SHIFT, // ^ - 0x2d|SHIFT, // _ - 0x35, // ` - 0x04, // a - 0x05, // b - 0x06, // c - 0x07, // d - 0x08, // e - 0x09, // f - 0x0a, // g - 0x0b, // h - 0x0c, // i - 0x0d, // j - 0x0e, // k - 0x0f, // l - 0x10, // m - 0x11, // n - 0x12, // o - 0x13, // p - 0x14, // q - 0x15, // r - 0x16, // s - 0x17, // t - 0x18, // u - 0x19, // v - 0x1a, // w - 0x1b, // x - 0x1c, // y - 0x1d, // z - 0x2f|SHIFT, // - 0x31|SHIFT, // | - 0x30|SHIFT, // } - 0x35|SHIFT, // ~ - 0 // DEL -}; - -uint8_t USBPutChar(uint8_t c); - -// press() adds the specified key (printing, non-printing, or modifier) -// to the persistent key report and sends the report. Because of the way -// USB HID works, the host acts like the key remains pressed until we -// call release(), releaseAll(), or otherwise clear the report and resend. -size_t Keyboard_::press(uint8_t k) -{ - uint8_t i; - if (k >= 136) // it's a non-printing key (not a modifier) - { - k = k - 136; - } - else if (k >= 128) - { // it's a modifier key - _keyReport.modifiers |= (1<<(k-128)); - k = 0; - } - else // it's a printing key - { - k = pgm_read_byte(_asciimap + k); - if (!k) - { - setWriteError(); - return 0; - } - if (k & 0x80) // it's a capital letter or other character reached with shift - { - _keyReport.modifiers |= 0x02; // the left shift modifier - k &= 0x7F; - } - } - - // Add k to the key report only if it's not already present - // and if there is an empty slot. - if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && - _keyReport.keys[2] != k && _keyReport.keys[3] != k && - _keyReport.keys[4] != k && _keyReport.keys[5] != k) - { - for (i=0; i<6; i++) - { - if (_keyReport.keys[i] == 0x00) - { - _keyReport.keys[i] = k; - break; - } - } - if (i == 6) - { - setWriteError(); - return 0; - } - } - - sendReport(&_keyReport); - return 1; -} - -// release() takes the specified key out of the persistent key report and -// sends the report. This tells the OS the key is no longer pressed and that -// it shouldn't be repeated any more. -size_t Keyboard_::release(uint8_t k) -{ - uint8_t i; - if (k >= 136) - { // it's a non-printing key (not a modifier) - k = k - 136; - } - else if (k >= 128) - { // it's a modifier key - _keyReport.modifiers &= ~(1<<(k-128)); - k = 0; - } - else - { // it's a printing key - k = pgm_read_byte(_asciimap + k); - if (!k) - { - return 0; - } - if (k & 0x80) - { // it's a capital letter or other character reached with shift - _keyReport.modifiers &= ~(0x02); // the left shift modifier - k &= 0x7F; - } - } - - // Test the key report to see if k is present. Clear it if it exists. - // Check all positions in case the key is present more than once (which it shouldn't be) - for (i=0; i<6; i++) - { - if (0 != k && _keyReport.keys[i] == k) - { - _keyReport.keys[i] = 0x00; - } - } - - sendReport(&_keyReport); - return 1; -} - -void Keyboard_::releaseAll(void) -{ - _keyReport.keys[0] = 0; - _keyReport.keys[1] = 0; - _keyReport.keys[2] = 0; - _keyReport.keys[3] = 0; - _keyReport.keys[4] = 0; - _keyReport.keys[5] = 0; - _keyReport.modifiers = 0; - sendReport(&_keyReport); -} - -size_t Keyboard_::write(uint8_t c) -{ - uint8_t p = press(c); // Keydown - /*uint8_t r =*/ release(c); // Keyup - return (p); // just return the result of press() since release() almost always returns 1 -} - -#endif - -#endif /* if defined(USBCON) */ - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp b/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp deleted file mode 100644 index de5cfb5..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp +++ /dev/null @@ -1,1869 +0,0 @@ -/* - HardwareSerial.cpp - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. 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 - - Modified 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul - Modified 14 August 2012 by Alarus - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#include -#include -#include -#include -#include "Arduino.h" -#include "pins_arduino.h" -#include "wiring_private.h" -#include "HardwareSerial.h" - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#define PROGMEM_ORIG PROGMEM -#else // PROGMEM workaround - -// to avoid the bogus "initialized variables" warning -#ifdef PROGMEM -#undef PROGMEM -#endif // PROGMEM re-define - -#define PROGMEM __attribute__((section(".progmem.hardwareserial"))) -#define PROGMEM_ORIG __attribute__((__progmem__)) - -#endif // check for GNUC >= or < 4.6 - - -#ifndef SERIAL_0_PORT_NAME -#define SERIAL_0_PORT_NAME PORTD -#define SERIAL_0_USART_NAME USARTD0 -#define SERIAL_0_USART_DATA USARTD0_DATA -#define SERIAL_0_RXC_ISR ISR(USARTD0_RXC_vect) -#define SERIAL_0_DRE_ISR ISR(USARTD0_DRE_vect) -#define USARTD0_VECTOR_EXISTS -#define SERIAL_0_RX_PIN_INDEX 2 -#define SERIAL_0_TX_PIN_INDEX 3 -#else // check for new defs - -#if !defined(USARTC0_VECTOR_EXISTS) && !defined(USARTD0_VECTOR_EXISTS) && !defined(USARTE0_VECTOR_EXISTS) && !defined(USARTF0_VECTOR_EXISTS) && !defined(USARTC1_VECTOR_EXISTS) && !defined(USARTD1_VECTOR_EXISTS) && !defined(USARTE1_VECTOR_EXISTS) && !defined(USARTF1_VECTOR_EXISTS) -#error you must define the 'USARTxx_VECTOR_EXISTS' macro for each serial port as of 1/14/2015 modifications -#endif // defined 'all that' - -#endif // SERIAL_0_PORT_NAME - -#ifndef SERIAL_1_PORT_NAME -#define SERIAL_1_PORT_NAME PORTC -#define SERIAL_1_USART_NAME USARTC0 -#define SERIAL_1_USART_DATA USARTC0_DATA -#define SERIAL_1_RXC_ISR ISR(USARTC0_RXC_vect) -#define SERIAL_1_DRE_ISR ISR(USARTC0_DRE_vect) -#define USARTC0_VECTOR_EXISTS -#define SERIAL_1_RX_PIN_INDEX 2 -#define SERIAL_1_TX_PIN_INDEX 3 -#else // check for new defs - -#if !defined(USARTC0_VECTOR_EXISTS) && !defined(USARTD0_VECTOR_EXISTS) && !defined(USARTE0_VECTOR_EXISTS) && !defined(USARTF0_VECTOR_EXISTS) && !defined(USARTC1_VECTOR_EXISTS) && !defined(USARTD1_VECTOR_EXISTS) && !defined(USARTE1_VECTOR_EXISTS) && !defined(USARTF1_VECTOR_EXISTS) -#error you must define the 'USARTxx_VECTOR_EXISTS' macro for each serial port as of 1/14/2015 modifications -#endif // defined 'all that' - -#endif // SERIAL_1_PORT_NAME - - -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer, in which 'head' is the index of the location to -// which to write the next incoming character and 'tail' is the index of the -// location from which to read. - - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// // -// ____ _____ ____ ___ _ _ ____ _ _ _____ _____ _____ ____ ____ ___ _____ _____ // -// / ___| | ____|| _ \ |_ _| / \ | | | __ ) | | | || ___|| ___|| ____|| _ \ / ___||_ _||__ /| ____| // -// \___ \ | _| | |_) | | | / _ \ | | | _ \ | | | || |_ | |_ | _| | |_) | \___ \ | | / / | _| // -// ___) || |___ | _ < | | / ___ \ | |___ | |_) || |_| || _| | _| | |___ | _ < ___) || | / /_ | |___ // -// |____/ |_____||_| \_\|___|/_/ \_\|_____|_____|____/ \___/ |_| |_| |_____||_| \_\_____|____/|___|/____||_____| // -// |_____| |_____| // -// // -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// NOTE: in some cases I might want to override this. It's now "overrideable" in 'pins_arduino.h' -// TODO: support var length buffers from a pre-allocated linked list? as an option? -#ifndef SERIAL_BUFFER_SIZE - -#if !defined(SERIAL_2_PORT_NAME) && !defined(SERIAL_3_PORT_NAME) && !defined(SERIAL_4_PORT_NAME) && !defined(SERIAL_5_PORT_NAME) && !defined(SERIAL_6_PORT_NAME) && !defined(SERIAL_7_PORT_NAME) - -// only 2 serial ports, use larger buffer because I can - this can be overridden in 'pins_arduino.h' -#define SERIAL_BUFFER_SIZE 128 /* I like... big... BUFFERS! */ - -#else // more than 2 serial ports - -#define SERIAL_BUFFER_SIZE 64 /* reduce buffer size with *many* serial ports */ - -#endif // more than 2 serial ports? - -#endif // SERIAL_BUFFER_SIZE - -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ __ __ // -// _ __ (_) _ __ __ _ | |__ _ _ / _| / _| ___ _ __ ___ // -// | '__|| || '_ \ / _` | | '_ \ | | | || |_ | |_ / _ \| '__|/ __| // -// | | | || | | || (_| | | |_) || |_| || _|| _|| __/| | \__ \ // -// |_| |_||_| |_| \__, | |_.__/ \__,_||_| |_| \___||_| |___/ // -// |___/ // -// // -////////////////////////////////////////////////////////////////////////////// - -struct ring_buffer -{ - unsigned char buffer[SERIAL_BUFFER_SIZE]; -#if SERIAL_BUFFER_SIZE < 256 - // when buffer size is less than 256 bytes, use an unsigned char (it's faster, smaller) - volatile uint8_t/*unsigned int*/ head; - volatile uint8_t/*unsigned int*/ tail; -#else // SERIAL_BUFFER_SIZE >= 256 - volatile unsigned int head; - volatile unsigned int tail; -#endif // SERIAL_BUFFER_SIZE -}; - -// ring buffers for serial ports 1 and 2 (must zero head/tail before use) -// NOTE: there are ALWAYS at LEAST 2 serial ports: -// these are USARTD0 and USARTC0 (on pins 2,3) by default. - -ring_buffer rx_buffer; // = { { 0 }, 0, 0 }; // SERIAL_0 -ring_buffer tx_buffer; // = { { 0 }, 0, 0 }; -ring_buffer rx_buffer2; // = { { 0 }, 0, 0 }; // SERIAL_1 -ring_buffer tx_buffer2; // = { { 0 }, 0, 0 }; - -#ifdef SERIAL_2_PORT_NAME -ring_buffer rx_buffer3; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer3; // = { { 0 }, 0, 0 }; -#endif // SERIAL_2_PORT_NAME - -#ifdef SERIAL_3_PORT_NAME -ring_buffer rx_buffer4; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer4; // = { { 0 }, 0, 0 }; -#endif // SERIAL_3_PORT_NAME - -#ifdef SERIAL_4_PORT_NAME -ring_buffer rx_buffer5; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer5; // = { { 0 }, 0, 0 }; -#endif // SERIAL_4_PORT_NAME - -#ifdef SERIAL_5_PORT_NAME -ring_buffer rx_buffer6; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer6; // = { { 0 }, 0, 0 }; -#endif // SERIAL_5_PORT_NAME - -#ifdef SERIAL_6_PORT_NAME -ring_buffer rx_buffer7; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer7; // = { { 0 }, 0, 0 }; -#endif // SERIAL_6_PORT_NAME - -#ifdef SERIAL_7_PORT_NAME -ring_buffer rx_buffer8; // = { { 0 }, 0, 0 }; -ring_buffer tx_buffer8; // = { { 0 }, 0, 0 }; -#endif // SERIAL_7_PORT_NAME - - -////////////////////////////////////////////////////////////////////////////// -// // -// _____ _ ____ _ _ // -// | ___|| | ___ __ __ / ___| ___ _ __ | |_ _ __ ___ | | // -// | |_ | | / _ \\ \ /\ / / | | / _ \ | '_ \ | __|| '__|/ _ \ | | // -// | _| | || (_) |\ V V / | |___| (_) || | | || |_ | | | (_) || | // -// |_| |_| \___/ \_/\_/ \____|\___/ |_| |_| \__||_| \___/ |_| // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -//#ifdef SERIAL_0_CTS_ENABLED -//static char bWasCTS0; -//#endif // SERIAL_0_CTS_ENABLED -//#ifdef SERIAL_1_CTS_ENABLED -//static char bWasCTS1; -//#endif // SERIAL_1_CTS_ENABLED - - -// TODO: _SOFT_ flow control enable/disable, arbitrary pin assignments for CTS/DTR - -#if defined(SERIAL_0_CTS_ENABLED) -void InitSerialFlowControlInterrupt0(void) -{ -register8_t *pCTRL; -uint8_t oldSREG; - - - pCTRL = &(SERIAL_0_CTS_PORT->PIN0CTRL) + SERIAL_0_CTS_PIN_INDEX; - - SERIAL_0_CTS_PORT->DIR &= ~SERIAL_0_CTS_PIN; // it's an input - - *pCTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; //PORT_ISC_FALLING_gc; // interrupt on falling, pulldown resistor - - // this next section enables actual interrupts - - oldSREG = SREG; // store the interrupt flag basically - - cli(); // disable interrupts for a bit - - SERIAL_0_CTS_PORT->INT1MASK &= ~SERIAL_0_CTS_PIN; - // TODO: 'E' series doesn't have 'INT1' -// SERIAL_0_CTS_PORT->INTCTRL &= ~PORT_INT1LVL_gm; // interrupt initially off - - SREG = oldSREG; // restore -} -#endif // defined(SERIAL_0_CTS_ENABLED) - - -#if defined(SERIAL_1_CTS_ENABLED) -static void InitSerialFlowControlInterrupt1(void) -{ -register8_t *pCTRL; -uint8_t oldSREG; - - pCTRL = &(SERIAL_1_CTS_PORT->PIN0CTRL) + SERIAL_1_CTS_PIN_INDEX; - - SERIAL_1_CTS_PORT->DIR &= ~SERIAL_1_CTS_PIN; // it's an input - - *pCTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; //PORT_ISC_FALLING_gc; // interrupt on falling, pulldown resistor - - // this next section enables actual interrupts - - oldSREG = SREG; // store the interrupt flag basically - - cli(); // disable interrupts for a bit - - SERIAL_1_CTS_PORT->INT1MASK &= ~SERIAL_1_CTS_PIN; // interrupt off (for now) - // TODO: 'E' series doesn't have 'INT1' -// SERIAL_1_CTS_PORT->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this - - SREG = oldSREG; // restore -} -#endif // defined(SERIAL_1_CTS_ENABLED) - - -void InitSerialFlowControlInterrupts(void) -{ -uint8_t oldSREG=SREG; - - cli(); // disable interrupts for a bit - -#if defined(SERIAL_0_CTS_ENABLED) - InitSerialFlowControlInterrupt0(); -#endif // defined(SERIAL_0_CTS_ENABLED) - -#if defined(SERIAL_1_CTS_ENABLED) - InitSerialFlowControlInterrupt1(); -#endif // defined(SERIAL_1_CTS_ENABLED) - - SREG = oldSREG; // restore -} - - -// helpers for hardware flow control -// these will send the 'next character' _NOW_ if one is available by -// restoring the 'DRE' interrupt. - -void serial_0_cts_callback(void) -{ -uint8_t oldSREG = SREG; // get this FIRST -#ifdef SERIAL_0_CTS_ENABLED -char bCTS = SERIAL_0_CTS_PORT->IN & SERIAL_0_CTS_PIN; -#endif // SERIAL_0_CTS_ENABLED - - - cli(); // in case I'm currently doing somethign ELSE that affects tx_buffer - -#ifdef SERIAL_0_CTS_ENABLED - if(!bCTS) // it's cleared - turn off the interrupt - { - SERIAL_0_CTS_PORT->INT1MASK &= ~SERIAL_0_CTS_PIN; - // TODO: 'E' series doesn't have 'INT1' -// SERIAL_0_CTS_PORT->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this - } -#endif // SERIAL_0_CTS_ENABLED - - if(tx_buffer.head != tx_buffer.tail) // only when there's something to send - { - // re-enable the DRE interrupt - this will cause transmission to - // occur again without code duplication. see HardwareSerial::write() - - (&(SERIAL_0_USART_NAME))->CTRLA /*USARTD0_CTRLA*/ - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp) - | _BV(USART_DREINTLVL1_bp) | _BV(USART_DREINTLVL0_bp); // set int bits for rx and dre (sect 19.14.3) - } - - SREG=oldSREG; // interrupts re-enabled -} - -void serial_1_cts_callback(void) -{ -uint8_t oldSREG = SREG; // get this FIRST -#ifdef SERIAL_1_CTS_ENABLED -char bCTS = SERIAL_1_CTS_PORT->IN & SERIAL_1_CTS_PIN; -#endif // SERIAL_1_CTS_ENABLED - - - cli(); // in case I'm currently doing somethign ELSE that affects tx_buffer - -#ifdef SERIAL_1_CTS_ENABLED - if(!bCTS) // it's cleared - turn off the interrupt - { - SERIAL_1_CTS_PORT->INT1MASK &= ~SERIAL_1_CTS_PIN; - // TODO: 'E' series doesn't have 'INT1' -// SERIAL_1_CTS_PORT->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this - } -#endif // SERIAL_1_CTS_ENABLED - - if (tx_buffer2.head != tx_buffer2.tail) // only when there's something to send - { - // re-enable the DRE interrupt - this will cause transmission to - // occur again without code duplication. see HardwareSerial::write() - - USARTC0_CTRLA = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp) - | _BV(USART_DREINTLVL1_bp) | _BV(USART_DREINTLVL0_bp); // set int bits for rx and dre (sect 19.14.3) - } - - SREG=oldSREG; // interrupts re-enabled -} - - - -////////////////////////////////////////////////////////////////////////////////////////// -// // -// _ _ _ __ _ _ // -// (_) _ __ | |(_) _ __ ___ / _| _ _ _ __ ___ | |_ (_) ___ _ __ ___ // -// | || '_ \ | || || '_ \ / _ \ | |_ | | | || '_ \ / __|| __|| | / _ \ | '_ \ / __| // -// | || | | || || || | | || __/ | _|| |_| || | | || (__ | |_ | || (_) || | | |\__ \ // -// |_||_| |_||_||_||_| |_| \___| |_| \__,_||_| |_| \___| \__||_| \___/ |_| |_||___/ // -// // -// // -////////////////////////////////////////////////////////////////////////////////////////// - -inline void store_char(unsigned char c, ring_buffer *buffer) -{ - unsigned int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; - - // 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 != buffer->tail) - { - buffer->buffer[buffer->head] = c; - buffer->head = i; - } -} - -inline char set_not_rts(ring_buffer *buffer) -{ - unsigned int i1 = (unsigned int)(buffer->head + 3) % SERIAL_BUFFER_SIZE; - unsigned int i2 = (unsigned int)(buffer->head + 2) % SERIAL_BUFFER_SIZE; - unsigned int i3 = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE; - - // 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. - return i1 == buffer->tail || i2 == buffer->tail || i3 == buffer->tail; -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// // -// ___ _ _ _ _ _ _ // -// |_ _| _ __ | |_ ___ _ __ _ __ _ _ _ __ | |_ | | | | __ _ _ __ __| || | ___ _ __ ___ // -// | | | '_ \ | __|/ _ \| '__|| '__|| | | || '_ \ | __| | |_| | / _` || '_ \ / _` || | / _ \| '__|/ __| // -// | | | | | || |_| __/| | | | | |_| || |_) || |_ | _ || (_| || | | || (_| || || __/| | \__ \ // -// |___||_| |_| \__|\___||_| |_| \__,_|| .__/ \__| |_| |_| \__,_||_| |_| \__,_||_| \___||_| |___/ // -// |_| // -// // -////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// TODO: consider re-doing these to use a single ISR, via an ISR macro similar -// to the following: -// -// ISR(USARTC0_RXC_vect) -// { -// ... -// } -// -// ISR(USARTD0_RXC_vect, ISR_ALIASOF(USARTC0_RXC_vect)); -// -// etc. -// -// then the ISR would figure out 'whatever' for registers, etc. by checking flags -// to see who triggered the interrupt. such common code could more easily allow -// for ISR call as currently done via 'call_isr()'. downside, might run a bit -// slower, but probably smaller code. Alternative to single utility function being -// passed the address of the serial port register block in each ISR. -// -// see http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html -// - -SERIAL_0_RXC_ISR // ISR(USARTD0_RXC_vect) -{ -unsigned char c; - -#ifdef SERIAL_0_RTS_ENABLED - if(set_not_rts(&rx_buffer)) // do I need to turn off RTS ? - { - SERIAL_0_RTS_PORT->OUT |= SERIAL_0_RTS_PIN; // set to '1' - SERIAL_0_RTS_PORT->DIR |= SERIAL_0_RTS_PIN; // make sure it's an output - } -#endif // SERIAL_0_RTS_ENABLED - - if((&(SERIAL_0_USART_NAME))->STATUS /*USARTD0_STATUS*/ & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_0_USART_DATA; //USARTD0_DATA; - store_char(c, &rx_buffer); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_0_USART_DATA; //USARTD0_DATA; - } -} - -SERIAL_1_RXC_ISR // ISR(USARTC0_RXC_vect) -{ -unsigned char c; - -#ifdef SERIAL_1_RTS_ENABLED - if(set_not_rts(&rx_buffer2)) // do I need to turn off RTS ? - { - SERIAL_1_RTS_PORT->OUT |= SERIAL_1_RTS_PIN; // set to '1' - SERIAL_1_RTS_PORT->DIR |= SERIAL_1_RTS_PIN; // make sure it's an output - } -#endif // SERIAL_0_RTS_ENABLED - - if((&(SERIAL_1_USART_NAME))->STATUS /*USARTC0_STATUS*/ & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_1_USART_DATA; //USARTC0_DATA; - store_char(c, &rx_buffer2); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_1_USART_DATA; //USARTC0_DATA; - } -} - -#ifdef SERIAL_2_PORT_NAME -SERIAL_2_RXC_ISR // ISR(USARTE0_RXC_vect) -{ -unsigned char c; - - if((&(SERIAL_2_USART_NAME))->STATUS /*USARTE0_STATUS*/ & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_2_USART_DATA; //USARTE0_DATA; - store_char(c, &rx_buffer3); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_2_USART_DATA; //USARTE0_DATA; - } -} -#endif // SERIAL_2_PORT_NAME - -#ifdef SERIAL_3_PORT_NAME -SERIAL_3_RXC_ISR // ISR(USARTF0_RXC_vect) -{ -unsigned char c; - - if((&(SERIAL_3_USART_NAME))->STATUS /*USARTF0_STATUS*/ & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_3_USART_DATA; //USARTF0_DATA; - store_char(c, &rx_buffer4); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_3_USART_DATA; //USARTF0_DATA; - } -} -#endif // SERIAL_3_PORT_NAME - -#ifdef SERIAL_4_PORT_NAME -SERIAL_4_RXC_ISR -{ -unsigned char c; - - if((&(SERIAL_4_USART_NAME))->STATUS & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_4_USART_DATA; - store_char(c, &rx_buffer4); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_4_USART_DATA; - } -} -#endif // SERIAL_4_PORT_NAME - -#ifdef SERIAL_5_PORT_NAME -SERIAL_5_RXC_ISR -{ -unsigned char c; - - if((&(SERIAL_5_USART_NAME))->STATUS & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_5_USART_DATA; - store_char(c, &rx_buffer4); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_5_USART_DATA; - } -} -#endif // SERIAL_5_PORT_NAME - -#ifdef SERIAL_6_PORT_NAME -SERIAL_6_RXC_ISR -{ -unsigned char c; - - if((&(SERIAL_6_USART_NAME))->STATUS & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_6_USART_DATA; - store_char(c, &rx_buffer4); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_6_USART_DATA; - } -} -#endif // SERIAL_6_PORT_NAME - -#ifdef SERIAL_7_PORT_NAME -SERIAL_7_RXC_ISR -{ -unsigned char c; - - if((&(SERIAL_7_USART_NAME))->STATUS & _BV(USART_RXCIF_bp)) // if there is data available - { - c = SERIAL_7_USART_DATA; - store_char(c, &rx_buffer4); - } - else // I got an interrupt for some reason, just eat data from data reg - { - c = SERIAL_7_USART_DATA; - } -} -#endif // SERIAL_7_PORT_NAME - - -SERIAL_0_DRE_ISR // ISR(USARTD0_DRE_vect) -{ -#ifdef SERIAL_0_CTS_ENABLED -uint8_t oldSREG; -char bCTS = SERIAL_0_CTS_PORT->IN & SERIAL_0_CTS_PIN; -#endif // SERIAL_0_CTS_ENABLED - - - if ( -#ifdef SERIAL_0_CTS_ENABLED - bCTS || -#endif // SERIAL_0_CTS_ENABLED - tx_buffer.head == tx_buffer.tail) - { -#ifdef SERIAL_0_CTS_ENABLED - if(bCTS) - { - oldSREG = SREG; // store the interrupt flag basically - - cli(); // disable interrupts for a bit (in case they were enabled) - -// bWasCTS0 = 1; // to mark that I set the interrupt - - SERIAL_0_CTS_PORT->INT1MASK |= SERIAL_0_CTS_PIN; - // TODO: 'E' series doesn't have 'INT1' - SERIAL_0_CTS_PORT->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this - - SREG = oldSREG; // restore - } -#endif // SERIAL_0_CTS_ENABLED - - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_0_USART_NAME))->CTRLA /*USARTD0_CTRLA*/ - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer.buffer[tx_buffer.tail]; - tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_0_USART_DATA = c; //USARTD0_DATA = c; - } -} - -SERIAL_1_DRE_ISR // ISR(USARTC0_DRE_vect) -{ -#ifdef SERIAL_1_CTS_ENABLED -uint8_t oldSREG; -char bCTS = SERIAL_1_CTS_PORT->IN & SERIAL_1_CTS_PIN; -#endif // SERIAL_1_CTS_ENABLED - - - if ( -#ifdef SERIAL_1_CTS_ENABLED - bCTS || -#endif // SERIAL_1_CTS_ENABLED - tx_buffer2.head == tx_buffer2.tail) - - { -#ifdef SERIAL_1_CTS_ENABLED - if(bCTS) - { - oldSREG = SREG; // store the interrupt flag basically - - cli(); // disable interrupts for a bit - -// bWasCTS1 = 1; // to mark that I set the interrupt - - SERIAL_1_CTS_PORT->INT1MASK |= SERIAL_1_CTS_PIN; - // TODO: 'E' series doesn't have 'INT1' - SERIAL_1_CTS_PORT->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this - - SREG = oldSREG; // restore - } -#endif // SERIAL_1_CTS_ENABLED - - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_1_USART_NAME))->CTRLA /*USARTC0_CTRLA*/ - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer2.buffer[tx_buffer2.tail]; - tx_buffer2.tail = (tx_buffer2.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_1_USART_DATA = c; //USARTC0_DATA = c; - } -} - -#ifdef SERIAL_2_PORT_NAME -SERIAL_2_DRE_ISR // ISR(USARTE0_DRE_vect) -{ - if (tx_buffer3.head == tx_buffer3.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_2_USART_NAME))->CTRLA /*USARTE0_CTRLA*/ - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer3.buffer[tx_buffer3.tail]; - tx_buffer3.tail = (tx_buffer3.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_2_USART_DATA = c; //USARTE0_DATA = c; - } -} -#endif // SERIAL_2_PORT_NAME - -#ifdef SERIAL_3_PORT_NAME -SERIAL_3_DRE_ISR // ISR(USARTF0_DRE_vect) -{ - if (tx_buffer4.head == tx_buffer4.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_3_USART_NAME))->CTRLA /*USARTF0_CTRLA*/ - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer4.buffer[tx_buffer4.tail]; - tx_buffer4.tail = (tx_buffer4.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_3_USART_DATA = c; //USARTE0_DATA = c; - } -} -#endif // SERIAL_3_PORT_NAME - -#ifdef SERIAL_4_PORT_NAME -SERIAL_4_DRE_ISR -{ - if (tx_buffer4.head == tx_buffer4.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_4_USART_NAME))->CTRLA - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer4.buffer[tx_buffer4.tail]; - tx_buffer4.tail = (tx_buffer4.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_4_USART_DATA = c; - } -} -#endif // SERIAL_4_PORT_NAME - -#ifdef SERIAL_5_PORT_NAME -SERIAL_5_DRE_ISR -{ - if (tx_buffer4.head == tx_buffer4.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_5_USART_NAME))->CTRLA - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer4.buffer[tx_buffer4.tail]; - tx_buffer4.tail = (tx_buffer4.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_5_USART_DATA = c; - } -} -#endif // SERIAL_5_PORT_NAME - -#ifdef SERIAL_6_PORT_NAME -SERIAL_6_DRE_ISR -{ - if (tx_buffer4.head == tx_buffer4.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_6_USART_NAME))->CTRLA - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer4.buffer[tx_buffer4.tail]; - tx_buffer4.tail = (tx_buffer4.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_6_USART_DATA = c; - } -} -#endif // SERIAL_6_PORT_NAME - -#ifdef SERIAL_7_PORT_NAME -SERIAL_7_DRE_ISR -{ - if (tx_buffer4.head == tx_buffer4.tail) - { - // Buffer empty, so disable interrupts - // section 19.14.3 - the CTRLA register (interrupt stuff) - (&(SERIAL_7_USART_NAME))->CTRLA - = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); // only set these 2 (the DRE int is now OFF) - } - else - { - // There is more data in the output buffer. Send the next byte - register unsigned char c = tx_buffer4.buffer[tx_buffer4.tail]; - tx_buffer4.tail = (tx_buffer4.tail + 1) % SERIAL_BUFFER_SIZE; - - SERIAL_7_USART_DATA = c; - } -} -#endif // SERIAL_7_PORT_NAME - - -// this helper function calls the ISR directly whenever the status reg has the appropriate bit set, then clears the bit -// call this function when you're waiting for I/O, whenever interrupts are disabled. -void call_isr(volatile USART_t *pPort) -{ - if(pPort->STATUS & _BV(USART_RXCIF_bp)) - { - if(0) - { - // so I can use 'else if' for everything else - } -#ifdef USARTD0_VECTOR_EXISTS - else if(pPort == &(USARTD0)) - { - USARTD0_RXC_vect(); - } -#endif // USARTD0_VECTOR_EXISTS -#ifdef USARTD1_VECTOR_EXISTS - else if(pPort == &USARTD1) - { - USARTD1_RXC_vect(); - } -#endif // USARTD1_VECTOR_EXISTS -#ifdef USARTC0_VECTOR_EXISTS - else if(pPort == &USARTC0) - { - USARTC0_RXC_vect(); - } -#endif // USARTC0_VECTOR_EXISTS -#ifdef USARTC1_VECTOR_EXISTS - else if(pPort == &USARTC1) - { - USARTC1_RXC_vect(); - } -#endif // USARTC1_VECTOR_EXISTS -#ifdef USARTE0_VECTOR_EXISTS - else if(pPort == &USARTE0) - { - USARTE0_RXC_vect(); - } -#endif // USARTE0_VECTOR_EXISTS -#ifdef USARTE1_VECTOR_EXISTS - else if(pPort == &USARTE1) - { - USARTE1_RXC_vect(); - } -#endif // USARTE1_VECTOR_EXISTS -#ifdef USARTF0_VECTOR_EXISTS - else if(pPort == &USARTF0) - { - USARTF0_RXC_vect(); - } -#endif // USARTF0_VECTOR_EXISTS -#ifdef USARTF1_VECTOR_EXISTS - else if(pPort == &USARTF1) - { - USARTF1_RXC_vect(); - } -#endif // USARTF1_VECTOR_EXISTS - - pPort->STATUS = _BV(USART_RXCIF_bp); // clear THIS one. other bits must be written as zero - } - - if(pPort->STATUS & _BV(USART_DREIF_bp)) - { - if(0) - { - // so I can use 'else if' below - } -#ifdef USARTD0_VECTOR_EXISTS - else if(pPort == &USARTD0) - { - USARTD0_DRE_vect(); - } -#endif // USARTD0_VECTOR_EXISTS -#ifdef USARTD1_VECTOR_EXISTS - else if(pPort == &USARTD1) - { - USARTD1_DRE_vect(); - } -#endif // USARTD1_VECTOR_EXISTS -#ifdef USARTC0_VECTOR_EXISTS - else if(pPort == &USARTC0) - { - USARTC0_DRE_vect(); - } -#endif // USARTC0_VECTOR_EXISTS -#ifdef USARTC1_VECTOR_EXISTS - else if(pPort == &USARTC1) - { - USARTC1_DRE_vect(); - } -#endif // USARTC1_VECTOR_EXISTS -#ifdef USARTE0_VECTOR_EXISTS - else if(pPort == &USARTE0) - { - USARTE0_DRE_vect(); - } -#endif // USARTE0_VECTOR_EXISTS -#ifdef USARTE1_VECTOR_EXISTS - else if(pPort == &USARTE1) - { - USARTE1_DRE_vect(); - } -#endif // USARTE1_VECTOR_EXISTS -#ifdef USARTF0_VECTOR_EXISTS - else if(pPort == &USARTF0) - { - USARTF0_DRE_vect(); - } -#endif // USARTF0_VECTOR_EXISTS -#ifdef USARTF1_VECTOR_EXISTS - else if(pPort == &USARTF1) - { - USARTF1_DRE_vect(); - } -#endif // USARTF1_VECTOR_EXISTS - - pPort->STATUS = _BV(USART_DREIF_bp); // clear THIS one. other bits must be written as zero - } -} - - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ _ _____ _ // -// / ___| ___ _ __ (_) __ _ | | | ____|__ __ ___ _ __ | |_ ___ // -// \___ \ / _ \| '__|| | / _` || | | _| \ \ / // _ \| '_ \ | __|/ __| // -// ___) || __/| | | || (_| || | | |___ \ V /| __/| | | || |_ \__ \ // -// |____/ \___||_| |_| \__,_||_| |_____| \_/ \___||_| |_| \__||___/ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -void serialEvent() __attribute__((weak)); -void serialEvent() {} -#define serialEvent_implemented - -void serialEvent2() __attribute__((weak)); -void serialEvent2() {} -#define serialEvent2_implemented - -#ifdef SERIAL_2_PORT_NAME -void serialEvent3() __attribute__((weak)); -void serialEvent3() {} -#define serialEvent3_implemented -#endif // SERIAL_2_PORT_NAME - -#ifdef SERIAL_3_PORT_NAME -void serialEvent4() __attribute__((weak)); -void serialEvent4() {} -#define serialEvent4_implemented -#endif // SERIAL_3_PORT_NAME - -#ifdef SERIAL_4_PORT_NAME -void serialEvent5() __attribute__((weak)); -void serialEvent5() {} -#define serialEvent5_implemented -#endif // SERIAL_4_PORT_NAME - -#ifdef SERIAL_5_PORT_NAME -void serialEvent6() __attribute__((weak)); -void serialEvent6() {} -#define serialEvent6_implemented -#endif // SERIAL_5_PORT_NAME - -#ifdef SERIAL_6_PORT_NAME -void serialEvent7() __attribute__((weak)); -void serialEvent7() {} -#define serialEvent7_implemented -#endif // SERIAL_6_PORT_NAME - -#ifdef SERIAL_7_PORT_NAME -void serialEvent8() __attribute__((weak)); -void serialEvent8() {} -#define serialEvent8_implemented -#endif // SERIAL_7_PORT_NAME - -void serialEventRun(void) -{ -// TODO: support this - -#ifdef serialEvent_implemented -#ifdef USBCON - if (Serial1.available()) -#else // normal - if (Serial.available()) -#endif // USBCON, normal - { - serialEvent(); - } -#endif // serialEvent_implemented - -#ifdef serialEvent2_implemented - if (Serial2.available()) - { - serialEvent2(); - } -#endif // serialEvent2_implemented - -#ifdef serialEvent3_implemented - if (Serial3.available()) - { - serialEvent3(); - } -#endif // serialEvent3_implemented - -#ifdef serialEvent4_implemented - if (Serial4.available()) - { - serialEvent4(); - } -#endif // serialEvent4_implemented - -#ifdef serialEvent5_implemented - if (Serial5.available()) - { - serialEvent5(); - } -#endif // serialEvent5_implemented - -#ifdef serialEvent6_implemented - if (Serial6.available()) - { - serialEvent6(); - } -#endif // serialEvent6_implemented - -#ifdef serialEvent7_implemented - if (Serial7.available()) - { - serialEvent7(); - } -#endif // serialEvent7_implemented - -} - - -/////////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ ____ _ ____ _ // -// | __ ) __ _ _ _ __| | | _ \ __ _ | |_ ___ / ___| __ _ | | ___ // -// | _ \ / _` || | | | / _` | | |_) |/ _` || __|/ _ \ | | / _` || | / __| // -// | |_) || (_| || |_| || (_| | | _ <| (_| || |_| __/ | |___| (_| || || (__ // -// |____/ \__,_| \__,_| \__,_| |_| \_\\__,_| \__|\___| \____|\__,_||_| \___| // -// // -// // -/////////////////////////////////////////////////////////////////////////////////// - -// this function that uses 'canned' baud rate values is 'temporary'. A proper one that -// calculates the baud rate values will appear at some point in the future, once I have -// a nice bullet-proof algorithm for it. -// -// Note that THESE values assume F_CPU==32000000 - -// baud <= F_CPU / 16 for 1x, F_CPU / 8 for 2x - above that gives you a value of '1' -// -// X = clk_2x ? 8 : 16 bscale >= 0: bsel = F_CPU / ( (2 ^ bscale) * X * baud) - 1 -// baud = F_CPU / ( (2 ^ bscale) * X * (bsel + 1) ) -// bscale < 0: bsel = (1 / (2 ^ (bscale))) * (F_CPU / (X * baud) - 1) -// baud = F_CPU / ( X * (((2 ^ bscale) * bsel) + 1) ) -// -// NOTE: if bsel is zero for a given bscale, then use bscale=0 and bsel=2^(bscale - 1) -// see section 19.3.1 -// -// find 'best fit baud' by calculating the best 'bscale' and 'bsel' for a given baud -// bscale is -7 through +7 so this can be done in a simple loop -// -// Note that I have managed to "nuke out" some accurate integer math to make this work -// although the converging solutions tend to take up some time. It's still fast, though -// and you won't be calling this very often, now will ya? - -// calculating BSEL and BAUD correctly - this lets me select _ANY_ baud rate - - -#if 1 // use NEW get_baud - it's about 810 bytes bigger, though - -// GetBSEL returns the BSEL value given the baud and BSCALE -// this is more of an estimate. to get the right answer, this is -// merely a starting point. you have to converge on the solution -// by using a loop and picking the best 'nearby' value, up to '4' away -static int GetBSEL(unsigned long lBaud, int nBSCALE, int b2X) -{ -long l1, l3; -unsigned char nFactor; - - - if(b2X) - { - nFactor = 8; - } - else - { - nFactor = 16; - } - - if(nBSCALE >= 0) - { - l1 = nFactor * lBaud; - - if(nBSCALE) - { - l1 = l1 << nBSCALE; - } - - if(!l1) - { - return 0; - } - - if((((long)F_CPU) % l1) < (l1 >> 1)) - { - l1 = (((long)F_CPU) / l1) - 1; - } - else - { - l1 = (((long)F_CPU) / l1); // rounded off - } - } - else // nBSCALE < 0 - { - l1 = nFactor * lBaud; - - l3 = F_CPU; - - if(nBSCALE > -4) // might overload if I use 32-bit integers and 32Mhz - { - l3 = l3 << (-nBSCALE); - } - else - { - l3 = l3 << 3; - l1 = l1 >> -(3 + nBSCALE); - } - - if(l3 % l1 < (l1 >> 1)) - { - l1 = l3 / l1 - 1; - } - else - { - l1 = l3 / l1; // round up - } - } - - return (int)l1; -} - -// GetBAUD calculates the actual baud rate based on nBSCALE and nBSEL -// it is actually pretty accurate, matching what you seen in the manual -static long GetBAUD(int nBSCALE, int nBSEL, int b2X) -{ -long l1, l3; -unsigned char nFactor; -#define GET_BAUD_SCALE_FACTOR 4096 /* scaling the math so I can improve accuracy */ - - if(b2X) - { - nFactor = 8; - } - else - { - nFactor = 16; - } - - if(nBSCALE >= 0) - { - l1 = (long)nFactor * (nBSEL + 1); // nBSEL can be 1-4095; 16 * 4k is ~64k; then it gets shifted. - - if(nBSCALE) - { - l1 = l1 << nBSCALE; - } - - if(!l1) - { - return 0; - } - - return ((long)F_CPU) / l1; // TODO: roundoff correction? - } - - // nBSCALE < 0 - - l3 = (long)nFactor * GET_BAUD_SCALE_FACTOR; // scale factor improves precision - - l1 = l3 * nBSEL; - - if(nBSCALE) - { - l1 = l1 >> (-nBSCALE); - } - - l1 += l3; // the '+ 1' multiplied by nFactor * GET_BAUD_SCALE_SCALE_FACTOR - - if(!l1) // unlikely - { - return 0; - } - - l3 = F_CPU % l1; // the remainder - this gives me better rounding with int math - - return GET_BAUD_SCALE_FACTOR * (F_CPU / l1) // integer division, then mult by the scale - + (GET_BAUD_SCALE_FACTOR * l3) / l1; // the fractional remainder [scaled] -} - -// 'get_baud' - the official baud rate number thingy -// this returns (BSCALE << 12) | (BSEL & 0x3fff) for all practical purposes -uint16_t get_baud(unsigned long baud, uint8_t use_u2x) -{ -int i1; -char i2; -char iBSCALE, iBSCALERange; -int iBSEL, iTemp; -int iMinErr, iErr; - - - - // NOTE: 2^ABS(BSCALE) must at most be one half of the minimum number - // of clock cycles a frame requires - - iBSCALERange = 7; // my initial maximum range - - if(baud > (F_CPU / 1310720)) // so that the result fits in an integer - { - iTemp = (int)((F_CPU / 2) * 11L / baud); // half the # of clock cycles needed per 11-bits - - while(iBSCALERange && (1 << iBSCALERange) >= iTemp) - { - iBSCALERange --; - } - } - - iBSEL = 0; // initially zero for 'not found' - iBSCALE = 0; - iMinErr = 0x7fff; // grossly over expected value of error - - for(i2=-iBSCALERange; i2 <= iBSCALERange; i2++) - { - iTemp = GetBSEL(baud, i2, use_u2x); - - if(!iTemp || iTemp >= 2048) // out of range? - note actual max is 4095 - { - continue; // don't even look at an invalid value - } - - // derived experimentally, loop on range of iTemp - 4 to iTemp + 1 - for(i1=iTemp > 4 ? iTemp - 4 : 0; i1 <= iTemp + 1; i1++) - { - iErr = (int)(GetBAUD(iBSCALE, i1, use_u2x) - baud); // my delta - - if(iErr < 0) // smaller than call to 'abs()' - { - iErr = -iErr; - } - - if(iErr < iMinErr) - { - // I shall keep the first one I find that is below the current min error - // and the first 'lowest' error is the one I return. This favors lower - // values of BSCALE which I understand helps the baud rate generator - // work better overall. - - iBSEL = i1; - iBSCALE = i2; - iMinErr = iErr; // new error to stay below, now - } - } - } - - if(!iBSEL) - { - return 1; // highest possible baud rate - } - - return ((uint16_t)((int)iBSCALE << 12)) | (uint16_t)(iBSEL & 0x3fff); -} - -#else // OLD get_baud - -// the OLD version used baud rate values from a lookup table -uint16_t get_baud(unsigned long baud, uint8_t use_u2x) -{ -uint16_t i1; -static const unsigned long aBaud[] PROGMEM = // standard baud rates -{ - 2400, 4800, 9600, 14400, 19200, 28800, 31250, - 38400, 57600, 76800, 115200, 230400, 460800, 921600 -}; - -static const uint16_t a2x[] PROGMEM = // 2x constants for standard baud rates -{ - (7 << 12) | 12, // 2400 - (6 << 12) | 12, // 4800 - (5 << 12) | 12, // 9600 - (1 << 12) | 138, // 14400 - (4 << 12) | 12, // 19200 - 138, // 28800 - (2 << 12) | 31, // 31250 - MIDI baud rate - (3 << 12) | 12, // 38400 - (uint16_t)(-1 << 12) | 137, // 57600 - (2 << 12) | 12, // 76800 - (uint16_t)(-2 << 12) | 135, // 115200 - (uint16_t)(-3 << 12) | 131, // 230400 - (uint16_t)(-4 << 12) | 123, // 460800 - (uint16_t)(-5 << 12) | 107 // 921600 -}; - -static const uint16_t a1x[] PROGMEM = // 1x constants for standard baud rates -{ - (6 << 12) | 12, // 2400 - (5 << 12) | 12, // 4800 - (4 << 12) | 12, // 9600 - 138, // 14400 - (3 << 12) | 12, // 19200 - (uint16_t)(-1 << 12) | 137, // 28800 - (1 << 12) | 31, // 31250 - MIDI baud rate - (2 << 12) | 12, // 38400 - (uint16_t)(-2 << 12) | 135, // 57600 - (1 << 12) | 12, // 76800 - (uint16_t)(-3 << 12) | 131, // 115200 - (uint16_t)(-4 << 12) | 123, // 230400 - (uint16_t)(-5 << 12) | 107, // 460800 - (uint16_t)(-6 << 12) | 75 // 921600 -}; - - // TODO: binary search is faster, but uses more code - - for(i1=0; i1 < sizeof(aBaud)/sizeof(aBaud[0]); i1++) - { - unsigned long dw1 = pgm_read_dword(&aBaud[i1]); - if(baud == dw1) - { - if(use_u2x) - { - return pgm_read_word(&a2x[i1]); - } - else - { - return pgm_read_word(&a1x[i1]); - } - } - } - - return 1; // for now [half the maximum baud rate] -} - -#endif // 0,1 - - -///////////////////////////////////////////////////////////////////////////////////////////// -// // -// _ _ _ ____ _ _ // -// | | | | __ _ _ __ __| |__ __ __ _ _ __ ___ / ___| ___ _ __ (_) __ _ | | // -// | |_| | / _` || '__|/ _` |\ \ /\ / // _` || '__|/ _ \\___ \ / _ \| '__|| | / _` || | // -// | _ || (_| || | | (_| | \ V V /| (_| || | | __/ ___) || __/| | | || (_| || | // -// |_| |_| \__,_||_| \__,_| \_/\_/ \__,_||_| \___||____/ \___||_| |_| \__,_||_| // -// // -// // -///////////////////////////////////////////////////////////////////////////////////////////// - -// Constructors //////////////////////////////////////////////////////////////// - -void HardwareSerial::init(ring_buffer *rx_buffer0, ring_buffer *tx_buffer0, - uint16_t usart0) -{ -register ring_buffer *pR = rx_buffer0; -register ring_buffer *pT = tx_buffer0; - - _rx_buffer = pR;//rx_buffer0; - _tx_buffer = pT;//tx_buffer0; - _usart = (volatile USART_t *)usart0; - - pR->head = 0; - pR->tail = 0; - pT->head = 0; - pT->tail = 0; -// memset(rx_buffer0, 0, sizeof(*rx_buffer0)); -// memset(tx_buffer0, 0, sizeof(*tx_buffer0)); -} - -HardwareSerial::HardwareSerial(ring_buffer *rx_buffer0, ring_buffer *tx_buffer0, - uint16_t usart0) /*__attribute__ ((noinline))*/ -{ -register ring_buffer *pR = rx_buffer0; -register ring_buffer *pT = tx_buffer0; - -// init(rx_buffer0, tx_buffer0, usart0); this is larger code, left for reference - - _rx_buffer = pR;//rx_buffer0; - _tx_buffer = pT;//tx_buffer0; - _usart = (volatile USART_t *)usart0; - - pR->head = 0; - pR->tail = 0; - pT->head = 0; - pT->tail = 0; -// memset(rx_buffer0, 0, sizeof(*rx_buffer0)); -// memset(tx_buffer0, 0, sizeof(*tx_buffer0)); -} - -// Public Methods ////////////////////////////////////////////////////////////// - -// 'D' manual, section 19.5 -// USART Initialization -// USART initialization should use the following sequence: -// 1. Set the TxD pin value high, and optionally set the XCK pin low. -// 2. Set the TxD and optionally the XCK pin as output. -// 3. Set the baud rate and frame format. -// 4. Set the mode of operation (enables XCK pin output in synchronous mode). -// 5. Enable the transmitter or the receiver, depending on the usage. -// For interrupt-driven USART operation, global interrupts should be disabled during the initialization. -// Before doing a re-initialization with a changed baud rate or frame format, be sure that there are no ongoing transmissions -// while the registers are changed. - -void HardwareSerial::begin(unsigned long baud) -{ - begin(baud, SERIAL_8N1); // eliminated replicated code (12/9/2014) -} - -void HardwareSerial::begin(unsigned long baud, byte config) -{ - uint16_t baud_setting; - uint8_t use_u2x; - uint8_t bit, bitTX=3, bitRX=2; // defaults - volatile uint8_t *reg; - volatile uint8_t *out; - volatile uint8_t *ctrlT; - volatile uint8_t *ctrlR; - uint8_t oldSREG; - - - if (baud <= 57600) - { - use_u2x = 0; - } - else - { - use_u2x = _BV(USART_CLK2X_bp); // enable CLK2X - bit 2 in the CTRLB register (section 19.14.4) - } - - transmitting = false; // pre-assign - - // baud rate calc - page 220 table 19-5 [for standard values] - // table 19-1 (page 211) for calculation formulae - // (also see theory discussion on page 219) - baud_setting = get_baud(baud, use_u2x); - - // NOTE: I had some difficulty getting 300 baud to work. 600 baud worked ok though - // to get 300 baud to work, you might have to change things around a bit - - oldSREG = SREG; // save old to restore interrupts as they were - cli(); // clear interrupt flag until I'm done assigning pin stuff - - // pin re-mapping register and port/pin assignments - - if(_usart == &SERIAL_0_USART_NAME) - { - bitTX = (SERIAL_0_TX_PIN_INDEX); - bitRX = (SERIAL_0_RX_PIN_INDEX); -#ifdef SERIAL_0_REMAP - SERIAL_0_REMAP |= SERIAL_0_REMAP_BIT; // enable re-mapping for this port -#endif // SERIAL_0_REMAP - } - else if(_usart == &SERIAL_1_USART_NAME) - { - bitTX = (SERIAL_1_TX_PIN_INDEX); - bitRX = (SERIAL_1_RX_PIN_INDEX); -#ifdef SERIAL_1_REMAP - SERIAL_1_REMAP |= SERIAL_1_REMAP_BIT; // enable re-mapping for this port -#endif // SERIAL_0_REMAP - } -#ifdef SERIAL_2_PORT_NAME - else if(_usart == &SERIAL_2_USART_NAME) - { - bitTX = (SERIAL_2_TX_PIN_INDEX); - bitRX = (SERIAL_2_RX_PIN_INDEX); -#ifdef SERIAL_2_REMAP - SERIAL_2_REMAP |= SERIAL_2_REMAP_BIT; // enable re-mapping for this port -#endif // SERIAL_2_REMAP - } -#endif // SERIAL_2_PORT_NAME -#ifdef SERIAL_3_PORT_NAME - else if(_usart == &SERIAL_3_USART_NAME) - { - bitTX = (SERIAL_3_TX_PIN_INDEX); - bitRX = (SERIAL_3_RX_PIN_INDEX); -#ifdef SERIAL_3_REMAP - SERIAL_3_REMAP |= SERIAL_3_REMAP_BIT; // enable re-mapping for this port -#endif // SERIAL_3_REMAP - } -#endif // SERIAL_3_PORT_NAME -#ifdef SERIAL_4_PORT_NAME - else if(_usart == &SERIAL_4_USART_NAME) - { - bitTX = (SERIAL_4_TX_PIN_INDEX); - bitRX = (SERIAL_4_RX_PIN_INDEX); - -#ifdef SERIAL_4_REMAP - // NOTE: no remap for serial 4 through Serial 7 -#warning pin remap not supported for 'SERIAL_4' -#endif // SERIAL_4_REMAP - } -#endif // SERIAL_4_PORT_NAME -#ifdef SERIAL_5_PORT_NAME - else if(_usart == &SERIAL_5_USART_NAME) - { - bitTX = (SERIAL_5_TX_PIN_INDEX); - bitRX = (SERIAL_5_RX_PIN_INDEX); - -#ifdef SERIAL_5_REMAP - // NOTE: no remap for serial 4 through Serial 7 -#warning pin remap not supported for 'SERIAL_5' -#endif // SERIAL_5_REMAP - } -#endif // SERIAL_5_PORT_NAME -#ifdef SERIAL_6_PORT_NAME - else if(_usart == &SERIAL_6_USART_NAME) - { - bitTX = (SERIAL_6_TX_PIN_INDEX); - bitRX = (SERIAL_6_RX_PIN_INDEX); - -#ifdef SERIAL_6_REMAP - // NOTE: no remap for serial 4 through Serial 7 -#warning pin remap not supported for 'SERIAL_6' -#endif // SERIAL_6_REMAP - } -#endif // SERIAL_6_PORT_NAME -#ifdef SERIAL_7_PORT_NAME - else if(_usart == &SERIAL_7_USART_NAME) - { - bitTX = (SERIAL_7_TX_PIN_INDEX); - bitRX = (SERIAL_7_RX_PIN_INDEX); - -#ifdef SERIAL_7_REMAP - // NOTE: no remap for serial 4 through Serial 7 -#warning pin remap not supported for 'SERIAL_7' -#endif // SERIAL_7_REMAP - } -#endif // SERIAL_7_PORT_NAME - else - { - goto exit_point; // not valid (bail) - } - - // USART setup - for existing ports only (otherwise we just return) - - if(_usart == &USARTD0 -#ifdef USARTD1 - || _usart == &USARTD1 -#endif // USARTD1 - ) - { - reg = &PORTD_DIR; - out = &PORTD_OUT; - ctrlT = &PORTD_PIN0CTRL + bitTX; - ctrlR = &PORTD_PIN0CTRL + bitRX; - } - else if(_usart == &USARTC0 -#ifdef USARTC1 - || _usart == &USARTC1 -#endif // USARTC1 - ) - { - reg = &PORTC_DIR; - out = &PORTC_OUT; - ctrlT = &PORTC_PIN0CTRL + bitTX; - ctrlR = &PORTC_PIN0CTRL + bitRX; // note bitTX and bitRX must be correct - } -#ifdef USARTE0 - else if(_usart == &USARTE0 -#ifdef USARTE1 - || _usart == &USARTE1 -#endif // USARTE1 - ) - { - reg = &PORTE_DIR; - out = &PORTE_OUT; - ctrlT = &PORTE_PIN0CTRL + bitTX; - ctrlR = &PORTE_PIN0CTRL + bitRX; - } -#endif // USARTE0 -#ifdef USARTF0 - else if(_usart == &USARTF0 -#ifdef USARTE1 - || _usart == &USARTF1 -#endif // USARTE1 - ) - { - reg = &PORTF_DIR; - out = &PORTF_OUT; - ctrlT = &PORTF_PIN0CTRL + bitTX; - ctrlR = &PORTF_PIN0CTRL + bitRX; - } -#endif // USARTF0 - else - { - goto exit_point; // not valid (bail) - } - - // port config, transmit bit - bit = 1 << bitTX; - *ctrlT = 0; // trigger on BOTH, totem, no pullup - *out |= bit; // set to 'HIGH' - *reg |= bit; // set as output - - // port config, receive bit - bit = 1 << bitRX; - *ctrlR = 0; // triger on BOTH, no pullup - *out &= ~bit; // off - *reg &= ~bit; // set as input - - - // section 19.4.4 - _usart->CTRLB = use_u2x; // enable clock 2x when set (everything else disabled) - - - // section 19.14.5 - USART mode, parity, bits - // CMODE 7:6 00 [async] - // PMODE 5:4 00=none 10=even 11=odd - // SBMODE 3 0=1 stop 1=2 stop - // CHSIZE 2:0 000=5 bit 001=6 bit 010=7 bit 011=8 bit 111=9 bit - _usart->CTRLC = config & ~(_BV(USART_CMODE1_bp)|_BV(USART_CMODE0_bp)); // make sure bits 6 and 7 are cleared -#ifdef USARTD0_CTRLD - _usart->CTRLD = 0; // E5 has this register, must assign to zero -#endif // USARTD0_CTRLD - - // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register) - - _usart->BAUDCTRLA = (uint8_t)(baud_setting & 0xff); - _usart->BAUDCTRLB = (uint8_t)(baud_setting >> 8); - - // section 19.4.4 - - // enable RX, enable TX. Bit 2 will be 1 or 0 based on clock 2x/1x. multi-processor disabled. bit 9 = 0 - _usart->CTRLB = use_u2x | _BV(USART_RXEN_bp) | _BV(USART_TXEN_bp); - - // priority 3 for RX interrupts. DRE and TX interrupts OFF (for now). - _usart->CTRLA = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp); - -exit_point: - SREG = oldSREG; // restore interrupt flag (now that I'm done assigning things) -} - -void HardwareSerial::end() -{ - // wait for transmission of outgoing data - // TODO: check for 'in an ISR' or stalled? - - if(SREG & CPU_I_bm) // interrupts are enabled - { - // if ints not disabled it's safe to do this - wait for tx_buffer to empty - - while (_tx_buffer->head != _tx_buffer->tail) { } - } - - _usart->CTRLB = 0; // disable RX, TX - _usart->CTRLA = 0; // disable interrupts - - // clear any received data - _rx_buffer->head = _rx_buffer->tail; -} - -int HardwareSerial::available(void) -{ - register int iRval; - register uint8_t oldSREG = SREG; // save old to restore interrupts as they were - - cli(); // clear interrupt flag to prevent inconsistency - - iRval = (int)((unsigned int)(SERIAL_BUFFER_SIZE + (unsigned int)_rx_buffer->head - (unsigned int)_rx_buffer->tail) - % SERIAL_BUFFER_SIZE); - - SREG = oldSREG; // restore interrupt flag - - return iRval; -} - -int HardwareSerial::peek(void) -{ - register int iRval; - register uint8_t oldSREG = SREG; // save old to restore interrupts as they were - - cli(); // clear interrupt flag to prevent inconsistency - - if (_rx_buffer->head == _rx_buffer->tail) - { - iRval = -1; - } - else - { - iRval = _rx_buffer->buffer[_rx_buffer->tail]; - } - - SREG = oldSREG; // restore interrupt flag - - return iRval; -} - -int HardwareSerial::read(void) -{ - register int iRval; - uint8_t oldSREG = SREG; - - cli(); // clear interrupt flag for consistency - - // each time I'm ready to read a byte, double-check that the RTS (when enabled) - // needs to be set to a 0 value [which enables things to be sent to me]. As - // I deplete the buffer, RTS will enable, and as I fill it, RTS will disable. - - // This section is the 'deplete' part. So I'll set RTS to 'LOW' which is 'ok to send' - // if the buffer is _NOT_ too full (the set_not_rts() function determines that) - -#ifdef SERIAL_0_RTS_ENABLED - if(_rx_buffer == &rx_buffer && // it's serial #0 - !set_not_rts(&rx_buffer)) // do I need to turn off RTS ? - { - SERIAL_0_RTS_PORT->OUT &= ~SERIAL_0_RTS_PIN; // set to '0' - SERIAL_0_RTS_PORT->DIR |= SERIAL_0_RTS_PIN; // make sure it's an output - } -#endif // SERIAL_0_RTS_ENABLED - -#ifdef SERIAL_1_RTS_ENABLED - if(_rx_buffer == &rx_buffer2 && // it's serial #1 - !set_not_rts(&rx_buffer2)) // do I need to turn off RTS ? - { - SERIAL_1_RTS_PORT->OUT &= ~SERIAL_1_RTS_PIN; // set to '0' - SERIAL_1_RTS_PORT->DIR |= SERIAL_1_RTS_PIN; // make sure it's an output - } -#endif // SERIAL_1_RTS_ENABLED - - // back to regular serial I/O handling - - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer->head == _rx_buffer->tail) - { - iRval = -1; - } - else - { - iRval = (int)(_rx_buffer->buffer[_rx_buffer->tail]); - - _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % SERIAL_BUFFER_SIZE; - } - - SREG = oldSREG; // restore interrupt flag - - return iRval; -} - -void HardwareSerial::flush() -{ - // TODO: force an 'sei' here? - - // DATA is kept full while the buffer is not empty, so TXCIF triggers when EMPTY && SENT - while (transmitting && !(_usart->STATUS & _BV(USART_TXCIF_bp))) // TXCIF bit 6 indicates transmit complete - ; - - transmitting = false; -} - -size_t HardwareSerial::write(uint8_t c) -{ -register unsigned int i1; -uint8_t oldSREG; - - - oldSREG = SREG; // get this FIRST - cli(); // in case I'm currently doing somethign ELSE that affects the _tx_buffer - - i1 = (unsigned int)((_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE); // next head after this char - - // If the output buffer is full, there's nothing for it other than to - // wait for the interrupt handler to empty it a bit - - if (i1 == _tx_buffer->tail) // the buffer is still 'full'? - { - // if the interrupt flag is cleared in 'oldSREG' we must call the ISR directly - // otherwise we can set the int flag and wait for it - - if(oldSREG & CPU_I_bm) // interrupts were enabled - { - // make sure that the USART's RXC and DRE interupts are enabled - _usart->CTRLA = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp) - | _BV(USART_DREINTLVL1_bp) | _BV(USART_DREINTLVL0_bp); // set int bits for rx and dre (sect 19.14.3) - } - - do - { - if(oldSREG & CPU_I_bm) // interrupts were enabled - { - sei(); // re-enable interrupts - __builtin_avr_delay_cycles((F_CPU / 2000000) + 1); // delay ~17 cycles, enough time to allow for an interrupt to happen - } - else - { - call_isr(_usart); // this will block until there is a serial interrupt condition, but in an ISR-safe manner - } - - i1 = (unsigned int)((_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE); // next head after this char - - cli(); // do this regardless (smaller than another 'if' block, no harm if already clear) - - } while (i1 == _tx_buffer->tail); // while the buffer is still 'full' - } - - // if I didn't have to wait for buffer space, I'm already covered - - _tx_buffer->buffer[_tx_buffer->head] = c; - _tx_buffer->head = i1; // I already incremented it earlier, assume nobody ELSE modifies this - - // NOTE: this messes with flow control. it will still work, however -// _usart->CTRLA |= _BV(1) | _BV(0); // make sure I (re)enable the DRE interrupt (sect 19.14.3) - _usart->CTRLA = _BV(USART_RXCINTLVL1_bp) | _BV(USART_RXCINTLVL0_bp) - | _BV(USART_DREINTLVL1_bp) | _BV(USART_DREINTLVL0_bp); // set int bits for rx and dre (sect 19.14.3) - - transmitting = true; -// sbi(_usart->STATUS,6); // clear the TXCIF bit by writing a 1 to its location (sect 19.14.2) - _usart->STATUS = _BV(USART_TXCIF_bp); // other bits must be written as zero - - SREG=oldSREG; // interrupts re-enabled - - return 1; -} - -HardwareSerial::operator bool() -{ - return true; -} - - -////////////////////////////////////////////////////////////////////////////////////////////// -// // -// ___ _ _ _ ___ _ // -// / _ \ | |__ (_) ___ ___ | |_ |_ _| _ __ ___ | |_ __ _ _ __ ___ ___ ___ // -// | | | || '_ \ | | / _ \ / __|| __| | | | '_ \ / __|| __|/ _` || '_ \ / __|/ _ \/ __| // -// | |_| || |_) || || __/| (__ | |_ | | | | | |\__ \| |_| (_| || | | || (__| __/\__ \ // -// \___/ |_.__/_/ | \___| \___| \__| |___||_| |_||___/ \__|\__,_||_| |_| \___|\___||___/ // -// |__/ // -// // -////////////////////////////////////////////////////////////////////////////////////////////// - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -// NOTE: object naming in 'approximate' accordance with the way it's being done with Arduino -// except that 'Serial1' is *special*, and only defined when USB becomes 'Serial' -// and 'Serial2' will always be the '2nd' serial port ('Serial1' *could* become an alias) - -#ifdef USBCON -HardwareSerial Serial1(&rx_buffer, &tx_buffer, (uint16_t)&(SERIAL_0_USART_NAME)); // name changes to 'Serial1' when USB present -#else // normal -HardwareSerial Serial(&rx_buffer, &tx_buffer, (uint16_t)&(SERIAL_0_USART_NAME)); -#endif // USBCON or normal - -HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, (uint16_t)&(SERIAL_1_USART_NAME)); - -#ifdef SERIAL_2_PORT_NAME /* note these names are off by 1 with the 'Serial_N_' objects */ -HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, (uint16_t)&(SERIAL_2_USART_NAME)); -#endif // SERIAL_2_PORT_NAME - -#ifdef SERIAL_3_PORT_NAME -HardwareSerial Serial4(&rx_buffer4, &tx_buffer4, (uint16_t)&(SERIAL_3_USART_NAME)); -#endif // SERIAL_3_PORT_NAME - -#ifdef SERIAL_4_PORT_NAME -HardwareSerial Serial5(&rx_buffer5, &tx_buffer5, (uint16_t)&(SERIAL_3_USART_NAME)); -#endif // SERIAL_4_PORT_NAME - -#ifdef SERIAL_5_PORT_NAME -HardwareSerial Serial6(&rx_buffer6, &tx_buffer6, (uint16_t)&(SERIAL_3_USART_NAME)); -#endif // SERIAL_5_PORT_NAME - -#ifdef SERIAL_6_PORT_NAME -HardwareSerial Serial7(&rx_buffer7, &tx_buffer7, (uint16_t)&(SERIAL_3_USART_NAME)); -#endif // SERIAL_6_PORT_NAME - -#ifdef SERIAL_7_PORT_NAME -HardwareSerial Serial8(&rx_buffer8, &tx_buffer8, (uint16_t)&(SERIAL_3_USART_NAME)); -#endif // SERIAL_7_PORT_NAME - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h b/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h deleted file mode 100644 index fab2201..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - HardwareSerial.h - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. 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 - - Modified 28 September 2010 by Mark Sproul - Modified 14 August 2012 by Alarus - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#ifndef HardwareSerial_h -#define HardwareSerial_h - -#include - -#include "Stream.h" - -struct ring_buffer; - -class HardwareSerial : public Stream -{ - protected: // NEVER 'private' - // NOTE: xmega uses a structure pointer rather than individual pointers - // and the bit flags are consistent for all USART devices - ring_buffer *_rx_buffer; - ring_buffer *_tx_buffer; - volatile USART_t *_usart; - bool transmitting; - public: - HardwareSerial(ring_buffer *rx_buffer, ring_buffer *tx_buffer, uint16_t usart) __attribute__ ((noinline)); - void init(ring_buffer *rx_buffer, ring_buffer *tx_buffer, uint16_t usart) __attribute__ ((noinline)); - void begin(unsigned long); - void begin(unsigned long, uint8_t); - void end(); - virtual int available(void); - virtual int peek(void); - virtual int read(void); - virtual void flush(void); - virtual size_t write(uint8_t); - 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); } - using Print::write; // pull in write(str) and write(buf, size) from Print - operator bool(); -}; - -// Define config for Serial.begin(baud, config); -// PMODE 5:4 00=none 10=even 11=odd -// SBMODE 3 0=1 stop 1=2 stop -// CHSIZE 2:0 000=5 bit 001=6 bit 010=7 bit 011=8 bit 111=9 bit - -#define SERIAL_TWO_STOP _BV(USART_SBMODE_bp) -#define SERIAL_EVEN_PARITY _BV(USART_PMODE1_bp) -#define SERIAL_ODD_PARITY (_BV(USART_PMODE1_bp) | _BV(USART_PMODE0_bp)) - -#define SERIAL_5N1 0x00 -#define SERIAL_6N1 0x01 -#define SERIAL_7N1 0x02 -#define SERIAL_8N1 0x03 -#define SERIAL_5N2 (SERIAL_5N1 | SERIAL_TWO_STOP) -#define SERIAL_6N2 (SERIAL_6N1 | SERIAL_TWO_STOP) -#define SERIAL_7N2 (SERIAL_7N1 | SERIAL_TWO_STOP) -#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_TWO_STOP) -#define SERIAL_5E1 (SERIAL_5N1 | SERIAL_EVEN_PARITY) -#define SERIAL_6E1 (SERIAL_6N1 | SERIAL_EVEN_PARITY) -#define SERIAL_7E1 (SERIAL_7N1 | SERIAL_EVEN_PARITY) -#define SERIAL_8E1 (SERIAL_8N1 | SERIAL_EVEN_PARITY) -#define SERIAL_5E2 (SERIAL_5N2 | SERIAL_EVEN_PARITY) -#define SERIAL_6E2 (SERIAL_6N2 | SERIAL_EVEN_PARITY) -#define SERIAL_7E2 (SERIAL_7N2 | SERIAL_EVEN_PARITY) -#define SERIAL_8E2 (SERIAL_8N2 | SERIAL_EVEN_PARITY) -#define SERIAL_5O1 (SERIAL_5N1 | SERIAL_ODD_PARITY) -#define SERIAL_6O1 (SERIAL_6N1 | SERIAL_ODD_PARITY) -#define SERIAL_7O1 (SERIAL_7N1 | SERIAL_ODD_PARITY) -#define SERIAL_8O1 (SERIAL_8N1 | SERIAL_ODD_PARITY) -#define SERIAL_5O2 (SERIAL_5N2 | SERIAL_ODD_PARITY) -#define SERIAL_6O2 (SERIAL_6N2 | SERIAL_ODD_PARITY) -#define SERIAL_7O2 (SERIAL_7N2 | SERIAL_ODD_PARITY) -#define SERIAL_8O2 (SERIAL_8N2 | SERIAL_ODD_PARITY) - - -// this is where I must include 'pins_arduino.h' to get the 'USBCON' definition -#include "pins_arduino.h" - -// DEFAULT SERIAL or 'SERIAL 1' -#if defined(USBCON) - // NOTE: 'Serial1' will be the hardware serial and 'Serial' the USB serial - // whenever 'USBCON' is defined in pins_arduino.h - - #include - - extern HardwareSerial Serial1; -#else // normal hardware serial - extern HardwareSerial Serial; -#define Serial1 Serial /* define as 'Serial' so compatible code won't break */ -#endif - -extern HardwareSerial Serial2; // this is the same regardless of USBCON (there will always be at least 2) - -#ifdef SERIAL_2_PORT_NAME /* note these names are off by 1 with the 'Serial_N_' definitions */ -extern HardwareSerial Serial3; -#endif // SERIAL_2_PORT_NAME -#ifdef SERIAL_3_PORT_NAME -extern HardwareSerial Serial4; -#endif // SERIAL_3_PORT_NAME -#ifdef SERIAL_4_PORT_NAME -extern HardwareSerial Serial5; -#endif // SERIAL_4_PORT_NAME -#ifdef SERIAL_5_PORT_NAME -extern HardwareSerial Serial6; -#endif // SERIAL_5_PORT_NAME -#ifdef SERIAL_6_PORT_NAME -extern HardwareSerial Serial7; -#endif // SERIAL_6_PORT_NAME -#ifdef SERIAL_7_PORT_NAME -extern HardwareSerial Serial8; -#endif // SERIAL_7_PORT_NAME - -// this function calls the serial event handlers. you can override them (hence 'weak') -// the default implementation checks for data available and executes the callback if so -extern void serialEventRun(void) __attribute__((weak)); - -#endif // HardwareSerial_h - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp b/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp deleted file mode 100644 index 3532172..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - IPAddress.cpp - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. 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 -*/ - -#include -#include - -IPAddress::IPAddress() -{ - memset(_address, 0, sizeof(_address)); -} - -IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) -{ - _address[0] = first_octet; - _address[1] = second_octet; - _address[2] = third_octet; - _address[3] = fourth_octet; -} - -IPAddress::IPAddress(uint32_t address) -{ - memcpy(_address, &address, sizeof(_address)); -} - -IPAddress::IPAddress(const uint8_t *address) -{ - memcpy(_address, address, sizeof(_address)); -} - -IPAddress& IPAddress::operator=(const uint8_t *address) -{ - memcpy(_address, address, sizeof(_address)); - return *this; -} - -IPAddress& IPAddress::operator=(uint32_t address) -{ - memcpy(_address, (const uint8_t *)&address, sizeof(_address)); - return *this; -} - -bool IPAddress::operator==(const uint8_t* addr) -{ - return memcmp(addr, _address, sizeof(_address)) == 0; -} - -size_t IPAddress::printTo(Print& p) const -{ - size_t n = 0; - for (int i =0; i < 3; i++) - { - n += p.print(_address[i], DEC); - n += p.print('.'); - } - n += p.print(_address[3], DEC); - return n; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h b/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h deleted file mode 100644 index cd60afd..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - IPAddress.h - Base class that provides IPAddress - Copyright (c) 2011 Adrian McEwen. 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 -*/ - -#ifndef IPAddress_h -#define IPAddress_h - -#include - -// A class to make it easier to handle and pass around IP addresses - -class IPAddress : public Printable -{ -private: - uint8_t _address[4]; // IPv4 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; }; - -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); - - // 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() - { - register const uint32_t *p1 = (const uint32_t *)(const void *)_address; - return *p1; - }; - bool operator==(const IPAddress& addr) - { - register const uint32_t *p1 = (const uint32_t*)_address; - register const uint32_t *p2 = (const uint32_t*)(addr._address); - - return *p1 == *p2; - }; - - bool operator==(const uint8_t* addr); - - // Overloaded index operator to allow getting and setting individual octets of the address - uint8_t operator[](int index) const { return _address[index]; }; - uint8_t& operator[](int index) { return _address[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; -}; - -const IPAddress INADDR_NONE(0,0,0,0); - - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Platform.h b/BootLoaders/Boards/orangerx/cores/xmega/Platform.h deleted file mode 100644 index c7d52d1..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Platform.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef __PLATFORM_H__ -#define __PLATFORM_H__ - -#include -#include -#include -#include -#include - -#ifndef _PLATFORM_H_TYPES_DEFINED_ -#define _PLATFORM_H_TYPES_DEFINED_ -// this is a temporary fix for USCore.h data types and header file include order issues -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; -#endif // _PLATFORM_H_TYPES_DEFINED_ - -#include "Arduino.h" - -#if defined(USBCON) - #include "USBDesc.h" - #include "USBCore.h" - #include "USBAPI.h" -#endif /* if defined(USBCON) */ - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Print.cpp b/BootLoaders/Boards/orangerx/cores/xmega/Print.cpp deleted file mode 100644 index ca78e34..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Print.cpp +++ /dev/null @@ -1,381 +0,0 @@ -/* - Print.cpp - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. 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 - - Modified 23 November 2006 by David A. Mellis - */ - -#include -#include -#include -#include -#include "Arduino.h" - -#include "Print.h" - -// Public Methods ////////////////////////////////////////////////////////////// - -/* default implementation: may be overridden */ -size_t Print::write(const uint8_t *buffer, size_t size) -{ - size_t n = 0; - while (size--) - { - register size_t cb = write(*buffer++); - - if(!cb) // error return (prevents infinite loops) - { - break; - } - - n += cb; - } - return n; -} - -size_t Print::print(const __FlashStringHelper *ifsh) -{ -PGM_P p = reinterpret_cast(ifsh); -size_t n = 0; -char tbuf[32]; // will write 32 chars at a time (helps for USB) -register char *p1; - - - p1 = tbuf; - - while (1) - { - unsigned char c = pgm_read_byte(p++); - - if(c == 0) - { - if(p1 > &(tbuf[0])) - { - n += write(tbuf, p1 - &(tbuf[0])); // write whatever I've got - } - - break; - } - - if(p1 >= &(tbuf[sizeof(tbuf)])) - { - register size_t cb = write(tbuf, p1 - &(tbuf[0])); - - if(!cb) // error (prevents infinite loops) - { - break; - } - - n += cb; - p1 = tbuf; - } - - *(p1++) = c; - } - - return n; -} - -size_t Print::print(const String &s) -{ - return write(s.c_str(), s.length()); -} - -size_t Print::print(const char str[]) -{ - return write(str); -} - -size_t Print::print(char c) -{ - return write(c); -} - -size_t Print::print(unsigned char b, int base) -{ - return print((unsigned long) b, base); -} - -size_t Print::print(int n, int base) -{ - return print((long) n, base); -} - -size_t Print::print(unsigned int n, int base) -{ - return print((unsigned long) n, base); -} - -size_t Print::print(long n, int base) -{ - if (base == 0) - { - return write(n); - } - else if (base == 10) - { - if (n < 0) - { - int t = print('-'); - n = -n; - return printNumber(n, 10) + t; - } - return printNumber(n, 10); - } - 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); -} - -size_t Print::print(double n, int digits) -{ - return printFloat(n, digits); -} - -size_t Print::println(const __FlashStringHelper *ifsh) -{ - size_t n = print(ifsh); - n += println(); - return n; -} - -size_t Print::print(const Printable& x) -{ - return x.printTo(*this); -} - -size_t Print::println(void) -{ -char tbuf[2]; - - tbuf[0] = '\r'; // this should be more efficient, and smaller - tbuf[1] = '\n'; - return write(tbuf, 2); -// size_t n = print('\r'); -// n += print('\n'); -// return n; -} - -size_t Print::println(const String &s) -{ - size_t n = print(s); - n += println(); - return n; -} - -size_t Print::println(const char c[]) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(char c) -{ - size_t n = print(c); - n += println(); - return n; -} - -size_t Print::println(unsigned char b, int base) -{ - size_t n = print(b, base); - n += println(); - return n; -} - -size_t Print::println(int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned int num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(unsigned long num, int base) -{ - size_t n = print(num, base); - n += println(); - return n; -} - -size_t Print::println(double num, int digits) -{ - size_t n = print(num, digits); - n += println(); - return n; -} - -size_t Print::println(const Printable& x) -{ - size_t n = print(x); - n += println(); - return n; -} - -// Private Methods ///////////////////////////////////////////////////////////// - -size_t Print::printNumber(unsigned long n, uint8_t base) -{ - char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. - char *str = &buf[sizeof(buf) - 1]; - - *str = '\0'; - - // prevent crash if called with base == 1 - if (base < 2) - base = 10; - - do - { - unsigned long m = n; - n /= base; - char c = m - base * n; - *--str = c < 10 ? c + '0' : c + 'A' - 10; - } while(n); - - return write(str); -} - -size_t Print::printFloat(double number, uint8_t digits) -{ - size_t n = 0; - - 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 - - // Handle negative numbers - if (number < 0.0) - { - 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) - { - n += print("."); - } - - // Extract digits from the remainder one at a time - while (digits-- > 0) - { - remainder *= 10.0; - int toPrint = int(remainder); - n += print(toPrint); - remainder -= toPrint; - } - - return n; -} - -// things that I added - -int Print::printf(const char *pszFormat, ...) /*__attribute__ ((format(printf, 2, 3)))*/ // added API for 'printf' since it has been suggested... -{ -va_list va; -int cbOut; - - va_start(va, pszFormat); - - cbOut = vsnprintf(NULL, 0, pszFormat, va); - - if(cbOut > 0) - { - char *p1 = (char *)malloc(cbOut + 2); - - if(p1) - { - cbOut = vsnprintf(p1, cbOut + 1, pszFormat, va); - print(p1); - free(p1); - } - } - - va_end(va); - - return cbOut; -} - -int Print::printf_P(const char *pszFormat, ...) /*__attribute__ ((format(printf_P, 2, 3)))*/ // added API for 'printf' since it has been suggested... -{ -va_list va; -int cbOut; - - va_start(va, pszFormat); - - cbOut = vsnprintf_P(NULL, 0, (const char *)pszFormat, va); - - if(cbOut > 0) - { - char *p1 = (char *)malloc(cbOut + 2); - - if(p1) - { - cbOut = vsnprintf_P(p1, cbOut + 1, (const char *)pszFormat, va); - print(p1); - free(p1); - } - } - - va_end(va); - - return cbOut; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Print.h b/BootLoaders/Boards/orangerx/cores/xmega/Print.h deleted file mode 100644 index b49ee14..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Print.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - Print.h - Base class that provides print() and println() - Copyright (c) 2008 David A. Mellis. 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 -*/ - -#ifndef Print_h -#define Print_h - -#include -#include // for size_t - -#include "WString.h" -#include "Printable.h" - -#define DEC 10 -#define HEX 16 -#define OCT 8 -#define BIN 2 - -class Print -{ - private: - int write_error; - size_t printNumber(unsigned long, uint8_t); - size_t printFloat(double, uint8_t); - - protected: - void setWriteError(int err = 1) { write_error = err; } - - public: - Print() : write_error(0) {} // default constructor only assigns 0 to 'write_error' - - int getWriteError() { return write_error; } - void clearWriteError() { setWriteError(0); } - - virtual size_t write(uint8_t) = 0; // derived class must implement - size_t write(const char *str) - { - if (str == NULL) return 0; - return write((const uint8_t *)str, strlen(str)); - } - - // write multiple characters from a buffer - default calls 'write(uint8_t)' on each byte - // NOTE: for better efficiency, a derived class SHOULD implement its own 'write' for a buffer - - virtual size_t write(const uint8_t *buffer, size_t size); // overridable - size_t write(const char *buffer, size_t size) - { - return write((const uint8_t *)buffer, size); - } - - // custom mod - implement 'printf' member function - int printf(const char *pszFormat, ...) __attribute__ ((format(printf, 2, 3))); // added API for 'printf' since it has been suggested... - int printf_P(const char *pszFormat, ...) __attribute__ ((format(printf, 2, 3))); // added API for 'printf_P' since it has been suggested... - - size_t print(const __FlashStringHelper *); - size_t print(const String &); - size_t print(const char[]); - size_t print(char); - size_t print(unsigned char, int = DEC); - size_t print(int, int = DEC); - size_t print(unsigned int, int = DEC); - size_t print(long, int = DEC); - size_t print(unsigned long, int = DEC); - size_t print(double, int = 2); - size_t print(const Printable&); - - size_t println(const __FlashStringHelper *); - size_t println(const String &s); - size_t println(const char[]); - size_t println(char); - size_t println(unsigned char, int = DEC); - size_t println(int, int = DEC); - size_t println(unsigned int, int = DEC); - size_t println(long, int = DEC); - size_t println(unsigned long, int = DEC); - size_t println(double, int = 2); - size_t println(const Printable&); - size_t println(void); -}; - -#endif - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Printable.h b/BootLoaders/Boards/orangerx/cores/xmega/Printable.h deleted file mode 100644 index d03c9af..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Printable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Printable.h - Interface class that allows printing of complex types - Copyright (c) 2011 Adrian McEwen. 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 -*/ - -#ifndef Printable_h -#define Printable_h - -#include - -class Print; - -/** The Printable class provides a way for new classes to allow themselves to be printed. - By deriving from Printable and implementing the printTo method, it will then be possible - for users to print out instances of this class by passing them into the usual - Print::print and Print::println methods. -*/ - -class Printable -{ - public: - virtual size_t printTo(Print& p) const = 0; -}; - -#endif - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Server.h b/BootLoaders/Boards/orangerx/cores/xmega/Server.h deleted file mode 100644 index 77c415c..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Server.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - Server.h - Base class that provides Server - Copyright (c) 2011 Adrian McEwen. 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 -*/ - -#ifndef server_h -#define server_h - -class Server : public Print { -public: - virtual void begin() =0; -}; - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp b/BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp deleted file mode 100644 index 8316a92..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* - Stream.cpp - adds parsing methods to Stream class - Copyright (c) 2008 David A. Mellis. 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 - - Created July 2011 - parsing functions based on TextFinder library by Michael Margolis - */ - -#include "Arduino.h" -#include "Stream.h" - -// if/branch optimization -#define UNLIKELY(x) (__builtin_expect (!!(x), 0)) -#define LIKELY(x) (__builtin_expect (!!(x), 1)) - - -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait -#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field - -// private method to read stream with timeout -int Stream::timedRead() -{ - int c; - - _startMillis = millis(); - - do - { - c = read(); - - if (c >= 0) - return c; - - wait_for_interrupt(); // XMega enhancement - - } while(millis() - _startMillis < _timeout); - - return -1; // -1 indicates timeout -} - -// private method to peek stream with timeout -int Stream::timedPeek() -{ - int c; - - _startMillis = millis(); - - do - { - c = peek(); - - if (c >= 0) - return c; - - wait_for_interrupt(); // XMega enhancement - - } while(millis() - _startMillis < _timeout); - - return -1; // -1 indicates timeout -} - -// returns peek of the next digit in the stream or -1 if timeout -// discards non-numeric characters -int Stream::peekNextDigit() -{ - int c; - while (1) - { - c = timedPeek(); - - // refactored this for (possibly) better efficiency AND readability - seems to be the same size/footprint -// if (c < 0) -// return c; // timeout -// -// if (c == '-') -// return c; -// -// if (c >= '0' && c <= '9') -// return c; - - if(UNLIKELY(c < 0) || // refactored. < 0 is a timeout - UNLIKELY(c == '-') || // negative (TODO: test for leading char only, or lead on exponent) - LIKELY(c >= '0' && c <= '9')) // numeric digit; TODO test for exponent on float? - { - return c; - } - - read(); // discard non-numeric - } -} - -// Public Methods -////////////////////////////////////////////////////////////// - -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) -{ - return findUntil(target, NULL/*""*/); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(char *target, char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} - -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// 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) -{ - size_t index = 0; // maximum target string length is 64k bytes! - size_t termIndex = 0; - int c; - - if(!target || *target == 0) // update, allow NULL pointer - { - return true; // return true if target is a null string - } - - while( (c = timedRead()) > 0) - { - - if(c != target[index]) - { - index = 0; // reset index if any char does not match - } - - if( c == target[index]) - { - //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); - if(++index >= targetLen) // return true if all chars in the target match - { - return true; - } - } - - // allow for NULL 'terminator' - if(terminator && termLen > 0 && - UNLIKELY(c == terminator[termIndex])) - { - if(++termIndex >= termLen) - { - return false; // return false if terminate string found before target string - } - } - else - { - termIndex = 0; - } - } - - return false; -} - - -// returns the first valid (long) integer value from the current position. -// initial characters that are not digits (or the minus sign) are skipped -// function is terminated by the first character that is not a digit. -long Stream::parseInt() -{ - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) -} - -// as above but a given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) -{ - boolean isNegative = false; - long value = 0; - int c; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do - { - if(c == skipChar) - ; // ignore this charactor - else if(c == '-') - isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? - value = value * 10 + c - '0'; - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == skipChar ) - ; - - if(isNegative) - value = -value; - - return value; -} - - -// as parseInt but returns a floating point value -float Stream::parseFloat() -{ - return parseFloat(NO_SKIP_CHAR); -} - -// as above but the given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar) -{ - boolean isNegative = false; - boolean isFraction = false; - long value = 0; - char c; - float fraction = 1.0; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - { - return 0; // zero returned if timeout - } - - do - { - if(c == skipChar) - { - // ignore - } - else if(c == '-') - { - isNegative = true; - } - else if (c == '.') - { - isFraction = true; - } - else if(c >= '0' && c <= '9') // is c a digit? - { - value = value * 10 + c - '0'; - - if(isFraction) - { - fraction *= 0.1; - } - } - - read(); // consume the character we got with peek - c = timedPeek(); - } - - while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ) - ; - - if(isNegative) - value = -value; - if(isFraction) - return value * fraction; - else - return value; -} - -// read characters from stream into buffer -// terminates if length characters have been read, or timeout (see setTimeout) -// returns the number of characters placed in the buffer -// the buffer is NOT null terminated. -// -size_t Stream::readBytes(char *buffer, size_t length) -{ - size_t count = 0; - - while (count < length) - { - int c = timedRead(); - - if (c < 0) - break; - - *buffer++ = (char)c; - count++; - } - - 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) - -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) -{ - if (length < 1) - return 0; - - size_t index = 0; - - while (index < length) - { - int c = timedRead(); - if (c < 0 || c == terminator) break; - *buffer++ = (char)c; - index++; - } - - return index; // return number of characters, not including null terminator -} - -String Stream::readString() -{ - String ret; - - int c = timedRead(); - - while (c >= 0) - { - ret += (char)c; - c = timedRead(); - } - - return ret; -} - -String Stream::readStringUntil(char terminator) -{ - String ret; - - int c = timedRead(); - - while (c >= 0 && c != terminator) - { - ret += (char)c; - c = timedRead(); - } - - return ret; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Stream.h b/BootLoaders/Boards/orangerx/cores/xmega/Stream.h deleted file mode 100644 index 007b4bc..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Stream.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. 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 - - parsing functions based on TextFinder library by Michael Margolis -*/ - -#ifndef Stream_h -#define Stream_h - -#include -#include "Print.h" - -// compatability macros for testing -/* -#define getInt() parseInt() -#define getInt(skipChar) parseInt(skipchar) -#define getFloat() parseFloat() -#define getFloat(skipChar) parseFloat(skipChar) -#define getString( pre_string, post_string, buffer, length) -readBytesBetween( pre_string, terminator, buffer, length) -*/ - -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(); // 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; - - Stream() {_timeout=1000;} - -// parsing methods - - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - - bool find(char *target); // reads data from the stream until the target string is found - // 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 - // returns true if target string is found, false if timed out - - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - - - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. - - float parseFloat(); // float version of parseInt - - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - // 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 - // 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) - - // Arduino String functions to be added here - String readString(); - String readStringUntil(char terminator); - - protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored - - float parseFloat(char skipChar); // as above but the given skipChar is ignored -}; - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp b/BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp deleted file mode 100644 index 198335a..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp +++ /dev/null @@ -1,960 +0,0 @@ -/* Tone.cpp - - A Tone Generator Library - - Written by Brett Hagman - - 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 - -Version Modified By Date Comments -------- ----------- -------- -------- -0001 B Hagman 09/08/02 Initial coding -0002 B Hagman 09/08/18 Multiple pins -0003 B Hagman 09/08/18 Moved initialization from constructor to begin() -0004 B Hagman 09/09/26 Fixed problems with ATmega8 -0005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers - 09/11/25 Changed pin toggle method to XOR - 09/11/25 Fixed timer0 from being excluded -0006 D Mellis 09/12/29 Replaced objects with functions -0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register -0008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY -*************************************************/ - -// COMPLETE re-write for ATXMega by Bob Frazier, S.F.T. Inc. - http://mrp3.com/ - -// NOTE: this still only supports one tone output. However, xmega can do more than one -// due to the way the timers are. In fact, 'E' series can probably do a LOT more -// than one. If you want to implement that, it's a public project, so get it working -// reliably and submit the changes, thanks. - - - -#include -#include -#include "Arduino.h" -#include "pins_arduino.h" - -#if defined(TCC4) || !defined(TCC2) - -// in these cases this file isn't ready for prime time, so disable it for now - -#ifdef TONE_SUPPORTED -#undef TONE_SUPPORTED -#endif // TONE_SUPPORTED - -#else // !TCC4 && TCC2 - -#ifndef TONE_SUPPORTED -#define TONE_SUPPORTED // for now turn it off for 'E" -#endif // TONE_SUPPORTED - -#endif // TCC4 || !TCC2 - - -#ifdef TONE_SUPPORTED - -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#define PROGMEM_ORIG PROGMEM -#else // PROGMEM workaround - -// to avoid the bogus "initialized variables" warning -#ifdef PROGMEM -#undef PROGMEM -#endif // PROGMEM re-define - -#define PROGMEM __attribute__((section(".progmem.tone"))) -#define PROGMEM_ORIG __attribute__((__progmem__)) - -#endif // check for GNUC >= or < 4.6 - - -static PORT_t *pTonePort = NULL; // must assign at startup due to ISR -static uint8_t bToneMask = 0; // bitmask for tone pin -static unsigned long toggle_count = 0; // number of cycles to output - -static void toneBegin(uint8_t _pin, uint8_t _div, uint16_t _per) -{ - pTonePort = (PORT_t *)portModeRegister(digitalPinToPort(_pin)); - bToneMask = digitalPinToBitMask(_pin); - - - // Set the pinMode as OUTPUT - pinMode(_pin, OUTPUT); - -#if NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available */ - - TCE0_INTCTRLA = 0; // temporarily disable overflow interrupt - TCE0_INTCTRLB = 0; // disable other interrupts - TCE0_CTRLA = _div; // divisor for pre-scaler - TCE0_CTRLB = TC_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow') - TCE0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4) - TCE0_CTRLE = 0; // 16-bit mode - TCE0_PER = _per; // period (16-bit value) - TCE0_INTCTRLA = 3; // overflow int level 3 (enables interrupt) - -#elif defined(TCC4) // E series and anything else with 'TCC4' - - TCC4_INTCTRLA = 0; // temporarily disable overflow interrupt - TCC4_INTCTRLB = 0; // disable other interrupts - TCC4_CTRLA = _div; // divisor for pre-scaler - TCC4_CTRLB = TC45_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow') - TCC4_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4) - TCC4_CTRLE = 0; // 16-bit mode - TCC4_PER = _per; // period (16-bit value) - TCC4_INTCTRLA = 3; // overflow int level 3 (enables interrupt) - -#else // other stuff not yet explored by me - - TCC0_INTCTRLA = 0; // temporarily disable overflow interrupt - TCC0_INTCTRLB = 0; // disable other interrupts - TCC0_CTRLA = _div; // divisor for pre-scaler - TCC0_CTRLB = TC_WGMODE_NORMAL_gc; // 'normal' mode (interrupt on 'overflow') - TCC0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4) - TCC0_CTRLE = 0; // 16-bit mode - TCC0_PER = _per; // period (16-bit value) - TCC0_INTCTRLA = 3; // overflow int level 3 (enables interrupt) - -#endif // NUM_DIGITAL_PINS > 18 - - // tone starts now, shuts off when the 'toggle_count' hits zero -} - -// frequency (in hertz) and duration (in milliseconds). - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) -{ -register int8_t b1; -unsigned short per, w2; -unsigned long ulTemp; -static const uint16_t aPreScaler[] PROGMEM = {1,2,4,8,64,256,1024}; // pre-scaler - - // frequency - - // based on the frequency, set up the divider and period - // period is 16-bits - - // NOTE: use the smallest possible divisor - - if(!frequency) - { - return; - } - - ulTemp = frequency * 16384L; // ideal counter 16384 - - for(b1=sizeof(aPreScaler)/sizeof(aPreScaler[0]) - 1; b1 > 0; b1--) - { - w2 = pgm_read_word(&(aPreScaler[0]) + b1); - if(((unsigned long)F_CPU / 2 / w2) >= ulTemp) // note that I flip the bit every OTHER cycle - { - break; - } - } - - if(!b1) - { - w2 = 1; // make sure - } - - // b1 is the divisor bit value for CTRLA, per caches the actual divisor - - per = (F_CPU / 2 / w2) / frequency; - if(!per) - { - per++; - } - - // Calculate the toggle count - if (duration > 0) - { - toggle_count = 2 * frequency * duration / 1000; - } - else - { - toggle_count = -1; - } - - toneBegin(_pin, b1, per); -} - -// XXX: this function only works properly for timer E (the only one we use -// currently). Since I use the ISR on timer E to toggle the pin, it should -// be just fine. - -void disableTimer(uint8_t _timer) -{ -// parameter is ignored - -#if NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available */ - - // disable under/overflow and comparison interrupts FIRST - TCE0_INTCTRLA = 0; // no underflow interrupts - TCE0_INTCTRLB = 0; // no comparison interrupts - - pTonePort = NULL; // make sure - - // re-assign TCE0 defaults. see 'wiring.c' - -#if NUM_DIGITAL_PINS > 22 /* meaning PORTE has 8 pins */ - - TCE2_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 - TCE2_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// TCE2_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCE2_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 - TCE2_CTRLF = 0; // not resetting or anything (13.9.7) - - TCE2_LPER = 255; // count 255 to 0 (total period = 256) - TCE2_HPER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. This, however, would generate a '1' output. - - TCE2_LCMPA = 255; - TCE2_LCMPB = 255; - TCE2_LCMPC = 255; - TCE2_LCMPD = 255; - - TCE2_HCMPA = 255; - TCE2_HCMPB = 255; - TCE2_HCMPC = 255; - TCE2_HCMPD = 255; - - TCE2_INTCTRLA = 0; // no underflow interrupts - TCE2_INTCTRLB = 0; // no comparison interrupts - -#else // 16-bit timer on TCE0 - - TCE0_CTRLA = 5; // b0101 - divide by 64 - D manual 12.11.1 - TCE0_CTRLB = TC_WGMODE_SS_gc; // single-slope PWM. NOTE: this counts UP, whereas the other timers count DOWN - // other bits (high nybble) are OFF - they enable output on the 4 port E pins -// TCE0_CTRLC = 0; // when timer not running, sets compare (12.11.3) - TCE0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4) - TCE0_CTRLE = 1; // normal 8-bit timer (set to 0 for 16-bit mode) (12.11.5) - - // make sure the timer E 'period' register is correctly set at 255 (i.e. 0-255 or 256 clock cycles). - TCE0_PER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // timer 0 can be configured to count UP or DOWN, but for single-slope PWM it is - // always 'UP'. A value of '255' should generate a '1' output for each PWM. - - TCE0_CCA = 255; - TCE0_CCB = 255; - TCE0_CCC = 255; - TCE0_CCD = 255; - -#endif // 8/16 bit timer on E - -#elif defined(TCC4) // E series and anything else with 'TCC4' - - // disable under/overflow and comparison interrupts FIRST - TCC4_INTCTRLA = 0; // no underflow interrupts - TCC4_INTCTRLB = 0; // no comparison interrupts - - pTonePort = NULL; // make sure - - // re-assign TCC0 defaults. see 'wiring.c' - - TCC4_CTRLA = 5; // b0101 - divide by 64 - E manual 13.13.1 - TCC4_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_SINGLESLOPE_gc; // byte mode, single slope -// TCC5_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCC4_CTRLD = 0; // events off - TCC4_CTRLE = 0; // no output on L pins - TCC4_CTRLF = 0; // no output on H pins - - TCC4_PER = 255; // 255 for period limit - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. - - TCC4_CCA = 65535; - TCC4_CCB = 65535; - TCC4_CCC = 65535; - TCC4_CCD = 65535; - -#else // other stuff not yet explored by me - - // disable under/overflow and comparison interrupts FIRST - TCC0_INTCTRLA = 0; // no underflow interrupts - TCC0_INTCTRLB = 0; // no comparison interrupts - - pTonePort = NULL; // make sure - - // re-assign TCC0 defaults. see 'wiring.c' - - TCC2_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 - TCC2_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// TCC2_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCC2_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 - TCC2_CTRLF = 0; // not resetting or anything (13.9.7) - - TCC2_LPER = 255; // count 255 to 0 (total period = 256) - TCC2_HPER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. This, however, would generate a '1' output. - - TCC2_LCMPA = 255; - TCC2_LCMPB = 255; - TCC2_LCMPC = 255; - TCC2_LCMPD = 255; - - TCC2_HCMPA = 255; - TCC2_HCMPB = 255; - TCC2_HCMPC = 255; - TCC2_HCMPD = 255; - - TCC2_INTCTRLA = 0; // no underflow interrupts - TCC2_INTCTRLB = 0; // no comparison interrupts - -#endif // NUM_DIGITAL_PINS > 18 -} - -void noTone(uint8_t _pin) -{ - disableTimer(0); - - digitalWrite(_pin, 0); -} - -#if NUM_DIGITAL_PINS > 18 /* meaning PORTE exists */ -ISR(TCE0_OVF_vect) // the 'overflow' vector on timer E0 -#elif defined(TCC4) // E series and anything else with 'TCC4' -ISR(TCC4_OVF_vect) // the 'overflow' vector on timer C4 -#else // everything else -ISR(TCC0_OVF_vect) // the 'overflow' vector on timer C0 -#endif // PORTE exist check -{ - if(!toggle_count || !pTonePort || !bToneMask -#if 1 /* this section in for bullet-proofing, consider removing */ - || (pTonePort != &PORTA && -#if NUM_ANALOG_PINS > 8 - pTonePort != &PORTB && -#endif // NUM_ANALOG_PINS > 8 - pTonePort != &PORTC && pTonePort != &PORTD && -#if NUM_DIGITAL_PINS > 18 - pTonePort != &PORTE && -#endif // PORTE exist check - pTonePort != &PORTR) -#endif // 1 - ) - { - // disable the timer (also disables the interrupt) - disableTimer(0); - return; - } - - // each time I get an overflow, toggle the tone pin - - pTonePort->OUTTGL = bToneMask; // toggle that bit - toggle_count--; -} - - - -#if 0 // OLD CODE for reference only - -#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) -#define TCCR2A TCCR2 -#define TCCR2B TCCR2 -#define COM2A1 COM21 -#define COM2A0 COM20 -#define OCR2A OCR2 -#define TIMSK2 TIMSK -#define OCIE2A OCIE2 -#define TIMER2_COMPA_vect TIMER2_COMP_vect -#define TIMSK1 TIMSK -#endif - -// timerx_toggle_count: -// > 0 - duration specified -// = 0 - stopped -// < 0 - infinitely (until stop() method called, or new play() called) - -#if !defined(__AVR_ATmega8__) -volatile long timer0_toggle_count; -volatile uint8_t *timer0_pin_port; -volatile uint8_t timer0_pin_mask; -#endif - -volatile long timer1_toggle_count; -volatile uint8_t *timer1_pin_port; -volatile uint8_t timer1_pin_mask; -volatile long timer2_toggle_count; -volatile uint8_t *timer2_pin_port; -volatile uint8_t timer2_pin_mask; - -#if defined(TIMSK3) -volatile long timer3_toggle_count; -volatile uint8_t *timer3_pin_port; -volatile uint8_t timer3_pin_mask; -#endif - -#if defined(TIMSK4) -volatile long timer4_toggle_count; -volatile uint8_t *timer4_pin_port; -volatile uint8_t timer4_pin_mask; -#endif - -#if defined(TIMSK5) -volatile long timer5_toggle_count; -volatile uint8_t *timer5_pin_port; -volatile uint8_t timer5_pin_mask; -#endif - - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ }; - -#elif defined(__AVR_ATmega8__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#elif defined(__AVR_ATmega32U4__) - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER3 - -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 3 /*, 1 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ }; - -#else - -#define AVAILABLE_TONE_PINS 1 -#define USE_TIMER2 - -// Leave timer 0 to last. -const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ }; -static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ }; - -#endif - -// NOTE: K&R coding style edited away. Allman style rules - BF - -static int8_t toneBegin(uint8_t _pin) -{ - int8_t _timer = -1; - - // if we're already using the pin, the timer should be configured. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) - { - if (tone_pins[i] == _pin) - { - return pgm_read_byte(tone_pin_to_timer_PGM + i); - } - } - - // search for an unused timer. - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) - { - if (tone_pins[i] == 255) - { - tone_pins[i] = _pin; - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - break; - } - } - - if (_timer != -1) - { - // Set timer specific stuff - // All timers in CTC mode - // 8 bit timers will require changing prescalar values, - // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar - switch (_timer) - { - #if defined(TCCR0A) && defined(TCCR0B) - case 0: - // 8 bit timer - TCCR0A = 0; - TCCR0B = 0; - bitWrite(TCCR0A, WGM01, 1); - bitWrite(TCCR0B, CS00, 1); - timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer0_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) - case 1: - // 16 bit timer - TCCR1A = 0; - TCCR1B = 0; - bitWrite(TCCR1B, WGM12, 1); - bitWrite(TCCR1B, CS10, 1); - timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer1_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR2A) && defined(TCCR2B) - case 2: - // 8 bit timer - TCCR2A = 0; - TCCR2B = 0; - bitWrite(TCCR2A, WGM21, 1); - bitWrite(TCCR2B, CS20, 1); - timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer2_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) - case 3: - // 16 bit timer - TCCR3A = 0; - TCCR3B = 0; - bitWrite(TCCR3B, WGM32, 1); - bitWrite(TCCR3B, CS30, 1); - timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer3_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) - case 4: - // 16 bit timer - TCCR4A = 0; - TCCR4B = 0; - #if defined(WGM42) - bitWrite(TCCR4B, WGM42, 1); - #elif defined(CS43) - #warning this may not be correct - // atmega32u4 - bitWrite(TCCR4B, CS43, 1); - #endif - bitWrite(TCCR4B, CS40, 1); - timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer4_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - - #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) - case 5: - // 16 bit timer - TCCR5A = 0; - TCCR5B = 0; - bitWrite(TCCR5B, WGM52, 1); - bitWrite(TCCR5B, CS50, 1); - timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); - timer5_pin_mask = digitalPinToBitMask(_pin); - break; - #endif - } - } - - return _timer; -} - - - -// frequency (in hertz) and duration (in milliseconds). - -void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) -{ - uint8_t prescalarbits = 0b001; - long toggle_count = 0; - uint32_t ocr = 0; - int8_t _timer; - - _timer = toneBegin(_pin); - - if (_timer >= 0) - { - // Set the pinMode as OUTPUT - pinMode(_pin, OUTPUT); - - // if we are using an 8 bit timer, scan through prescalars to find the best fit - if (_timer == 0 || _timer == 2) - { - ocr = F_CPU / frequency / 2 - 1; - prescalarbits = 0b001; // ck/1: same for both timers - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 8 - 1; - prescalarbits = 0b010; // ck/8: same for both timers - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 32 - 1; - prescalarbits = 0b011; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = _timer == 0 ? 0b011 : 0b100; - - if (_timer == 2 && ocr > 255) - { - ocr = F_CPU / frequency / 2 / 128 - 1; - prescalarbits = 0b101; - } - - if (ocr > 255) - { - ocr = F_CPU / frequency / 2 / 256 - 1; - prescalarbits = _timer == 0 ? 0b100 : 0b110; - if (ocr > 255) - { - // can't do any better than /1024 - ocr = F_CPU / frequency / 2 / 1024 - 1; - prescalarbits = _timer == 0 ? 0b101 : 0b111; - } - } - } - } - -#if defined(TCCR0B) - if (_timer == 0) - { - TCCR0B = prescalarbits; - } - else -#endif -#if defined(TCCR2B) - { - TCCR2B = prescalarbits; - } -#else - { - // dummy place holder to make the above ifdefs work - } -#endif - } - else - { - // two choices for the 16 bit timers: ck/1 or ck/64 - ocr = F_CPU / frequency / 2 - 1; - - prescalarbits = 0b001; - if (ocr > 0xffff) - { - ocr = F_CPU / frequency / 2 / 64 - 1; - prescalarbits = 0b011; - } - - if (_timer == 1) - { -#if defined(TCCR1B) - TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; -#endif - } -#if defined(TCCR3B) - else if (_timer == 3) - TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR4B) - else if (_timer == 4) - TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; -#endif -#if defined(TCCR5B) - else if (_timer == 5) - TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; -#endif - - } - - - // Calculate the toggle count - if (duration > 0) - { - toggle_count = 2 * frequency * duration / 1000; - } - else - { - toggle_count = -1; - } - - // Set the OCR for the given timer, - // set the toggle count, - // then turn on the interrupts - switch (_timer) - { - -#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) - case 0: - OCR0A = ocr; - timer0_toggle_count = toggle_count; - bitWrite(TIMSK0, OCIE0A, 1); - break; -#endif - - case 1: -#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK1, OCIE1A, 1); -#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) - // this combination is for at least the ATmega32 - OCR1A = ocr; - timer1_toggle_count = toggle_count; - bitWrite(TIMSK, OCIE1A, 1); -#endif - break; - -#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) - case 2: - OCR2A = ocr; - timer2_toggle_count = toggle_count; - bitWrite(TIMSK2, OCIE2A, 1); - break; -#endif - -#if defined(TIMSK3) - case 3: - OCR3A = ocr; - timer3_toggle_count = toggle_count; - bitWrite(TIMSK3, OCIE3A, 1); - break; -#endif - -#if defined(TIMSK4) - case 4: - OCR4A = ocr; - timer4_toggle_count = toggle_count; - bitWrite(TIMSK4, OCIE4A, 1); - break; -#endif - -#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) - case 5: - OCR5A = ocr; - timer5_toggle_count = toggle_count; - bitWrite(TIMSK5, OCIE5A, 1); - break; -#endif - - } - } -} - - -// XXX: this function only works properly for timer 2 (the only one we use -// currently). for the others, it should end the tone, but won't restore -// proper PWM functionality for the timer. -void disableTimer(uint8_t _timer) -{ - switch (_timer) - { - case 0: - #if defined(TIMSK0) - TIMSK0 = 0; - #elif defined(TIMSK) - TIMSK = 0; // atmega32 - #endif - break; - -#if defined(TIMSK1) && defined(OCIE1A) - case 1: - bitWrite(TIMSK1, OCIE1A, 0); - break; -#endif - - case 2: - #if defined(TIMSK2) && defined(OCIE2A) - bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt - #endif - #if defined(TCCR2A) && defined(WGM20) - TCCR2A = (1 << WGM20); - #endif - #if defined(TCCR2B) && defined(CS22) - TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); - #endif - #if defined(OCR2A) - OCR2A = 0; - #endif - break; - -#if defined(TIMSK3) - case 3: - TIMSK3 = 0; - break; -#endif - -#if defined(TIMSK4) - case 4: - TIMSK4 = 0; - break; -#endif - -#if defined(TIMSK5) - case 5: - TIMSK5 = 0; - break; -#endif - } -} - -// XXX: this function only works properly for timer 2 (the only one we use -// currently). for the others, it should end the tone, but won't restore -// proper PWM functionality for the timer. -void disableTimer(uint8_t _timer) - -void noTone(uint8_t _pin) -{ - int8_t _timer = -1; - - for (int i = 0; i < AVAILABLE_TONE_PINS; i++) - { - if (tone_pins[i] == _pin) - { - _timer = pgm_read_byte(tone_pin_to_timer_PGM + i); - tone_pins[i] = 255; - } - } - - disableTimer(_timer); - - digitalWrite(_pin, 0); -} - -#ifdef USE_TIMER0 -ISR(TIMER0_COMPA_vect) -{ - if (timer0_toggle_count != 0) - { - // toggle the pin - *timer0_pin_port ^= timer0_pin_mask; - - if (timer0_toggle_count > 0) - timer0_toggle_count--; - } - else - { - disableTimer(0); - *timer0_pin_port &= ~(timer0_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER1 -ISR(TIMER1_COMPA_vect) -{ - if (timer1_toggle_count != 0) - { - // toggle the pin - *timer1_pin_port ^= timer1_pin_mask; - - if (timer1_toggle_count > 0) - timer1_toggle_count--; - } - else - { - disableTimer(1); - *timer1_pin_port &= ~(timer1_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER2 -ISR(TIMER2_COMPA_vect) -{ - - if (timer2_toggle_count != 0) - { - // toggle the pin - *timer2_pin_port ^= timer2_pin_mask; - - if (timer2_toggle_count > 0) - timer2_toggle_count--; - } - else - { - // need to call noTone() so that the tone_pins[] entry is reset, so the - // timer gets initialized next time we call tone(). - // XXX: this assumes timer 2 is always the first one used. - noTone(tone_pins[0]); -// disableTimer(2); -// *timer2_pin_port &= ~(timer2_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER3 -ISR(TIMER3_COMPA_vect) -{ - if (timer3_toggle_count != 0) - { - // toggle the pin - *timer3_pin_port ^= timer3_pin_mask; - - if (timer3_toggle_count > 0) - timer3_toggle_count--; - } - else - { - disableTimer(3); - *timer3_pin_port &= ~(timer3_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER4 -ISR(TIMER4_COMPA_vect) -{ - if (timer4_toggle_count != 0) - { - // toggle the pin - *timer4_pin_port ^= timer4_pin_mask; - - if (timer4_toggle_count > 0) - timer4_toggle_count--; - } - else - { - disableTimer(4); - *timer4_pin_port &= ~(timer4_pin_mask); // keep pin low after stop - } -} -#endif - - -#ifdef USE_TIMER5 -ISR(TIMER5_COMPA_vect) -{ - if (timer5_toggle_count != 0) - { - // toggle the pin - *timer5_pin_port ^= timer5_pin_mask; - - if (timer5_toggle_count > 0) - timer5_toggle_count--; - } - else - { - disableTimer(5); - *timer5_pin_port &= ~(timer5_pin_mask); // keep pin low after stop - } -} -#endif - -#endif // 0 [OLD CODE] - -#endif // TONE_SUPPORTED - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h b/BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h deleted file mode 100644 index e7a17d4..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h +++ /dev/null @@ -1,275 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ ____ _ _ _ // -// | | | |/ ___| | __ ) / \ _ __ (_) | |__ // -// | | | |\___ \ | _ \ / _ \ | '_ \ | | | '_ \ // -// | |_| | ___) || |_) |/ ___ \ | |_) || | _ | | | | // -// \___/ |____/ |____//_/ \_\| .__/ |_|(_)|_| |_| // -// |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -#ifndef __USBAPI__ -#define __USBAPI__ - -#if defined(USBCON) - -#include "USBCore.h" /* make sure since I use its definitions here */ - -#ifdef DEBUG_CODE -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus -extern void error_print(const char *p1); // TEMPORARY -extern void error_print_(const char *p1); // TEMPORARY -extern void error_printH(unsigned long); // TEMPORARY -extern void error_printH_(unsigned long); // TEMPORARY -extern void error_printL(unsigned long); // TEMPORARY -extern void error_printL_(unsigned long); // TEMPORARY -extern void error_printP(const void * /*PROGMEM*/ p1); // TEMPORARY -extern void error_printP_(const void * /*PROGMEM*/ p1); // TEMPORARY -extern void DumpHex(void *pBuf, uint8_t nBytes); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#else // DEBUG_CODE - -#define error_print(p1) -#define error_print_(p1) -#define error_printH(X) -#define error_printH_(X) -#define error_printL(X) -#define error_printL_(X) -#define error_printP(p1) -#define error_printP_(p1) -#define DumpHex(X,Y) - -#endif // DEBUG_CODE - - -//================================================================================ -//================================================================================ -// USB - -class USBDevice_ -{ -public: - USBDevice_(); - bool configured(); - - void attach(); - void detach(); // Serial port goes down too... - void poll(); - -protected: - static XMegaEPDataStruct *GetEPData(); // necessary -}; - -extern USBDevice_ USBDevice; - -//================================================================================ -//================================================================================ -// Serial over CDC (Serial1 is the physical port) - -class Serial_ : public Stream -{ -protected: - 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 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) etc. from Print - - operator bool(); -}; -extern Serial_ Serial; // NOTE: HardwareSerial.h defines the 1st port as 'Serial1' whenever USBCON defined - -//================================================================================ -//================================================================================ -// Mouse - -#define MOUSE_LEFT 1 -#define MOUSE_RIGHT 2 -#define MOUSE_MIDDLE 4 -#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) - -class Mouse_ -{ -protected: - uint8_t _buttons; - void buttons(uint8_t b); -public: - Mouse_(void); - void begin(void); - void end(void); - void click(uint8_t b = MOUSE_LEFT); - void move(signed char x, signed char y, signed char wheel = 0); - void press(uint8_t b = MOUSE_LEFT); // press LEFT by default - void release(uint8_t b = MOUSE_LEFT); // release LEFT by default - bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default -}; -extern Mouse_ Mouse; - -//================================================================================ -//================================================================================ -// Keyboard - -#define KEY_LEFT_CTRL 0x80 -#define KEY_LEFT_SHIFT 0x81 -#define KEY_LEFT_ALT 0x82 -#define KEY_LEFT_GUI 0x83 -#define KEY_RIGHT_CTRL 0x84 -#define KEY_RIGHT_SHIFT 0x85 -#define KEY_RIGHT_ALT 0x86 -#define KEY_RIGHT_GUI 0x87 - -#define KEY_UP_ARROW 0xDA -#define KEY_DOWN_ARROW 0xD9 -#define KEY_LEFT_ARROW 0xD8 -#define KEY_RIGHT_ARROW 0xD7 -#define KEY_BACKSPACE 0xB2 -#define KEY_TAB 0xB3 -#define KEY_RETURN 0xB0 -#define KEY_ESC 0xB1 -#define KEY_INSERT 0xD1 -#define KEY_DELETE 0xD4 -#define KEY_PAGE_UP 0xD3 -#define KEY_PAGE_DOWN 0xD6 -#define KEY_HOME 0xD2 -#define KEY_END 0xD5 -#define KEY_CAPS_LOCK 0xC1 -#define KEY_F1 0xC2 -#define KEY_F2 0xC3 -#define KEY_F3 0xC4 -#define KEY_F4 0xC5 -#define KEY_F5 0xC6 -#define KEY_F6 0xC7 -#define KEY_F7 0xC8 -#define KEY_F8 0xC9 -#define KEY_F9 0xCA -#define KEY_F10 0xCB -#define KEY_F11 0xCC -#define KEY_F12 0xCD - -// Low level key report: up to 6 keys and shift, ctrl etc at once -typedef struct -{ - uint8_t modifiers; - uint8_t reserved; - uint8_t keys[6]; -} KeyReport; - -class Keyboard_ : public Print -{ -protected: - KeyReport _keyReport; - void sendReport(KeyReport* keys); -public: - Keyboard_(void); - void begin(void); - void end(void); - virtual size_t write(uint8_t k); - virtual size_t press(uint8_t k); - virtual size_t release(uint8_t k); - virtual void releaseAll(void); -}; -extern Keyboard_ Keyboard; - -//================================================================================ -//================================================================================ -// Low level API - -typedef struct -{ - uint8_t bmRequestType; - uint8_t bRequest; - uint8_t wValueL; - uint8_t wValueH; - uint16_t wIndex; - uint16_t wLength; -} Setup; - -//================================================================================ -//================================================================================ -// HID 'Driver' - -int HID_GetNumInterfaces(void); -int HID_GetInterfaceDataLength(void); -int HID_SendInterfaceData(void); -bool HID_SendDeviceDescriptor(void); - -int HID_GetDescriptor(int i); // handles the 'GET DESCRIPTOR' control packet -bool HID_Setup(Setup& setup); // handles a 'SETUP' control packet - -void HID_SendReport(uint8_t id, const void* data, int len); - -void HID_Reset(void); // called whenever I get a bus reset - -//================================================================================ -//================================================================================ -// CDC 'Driver' - -bool CDC_SendIAD(void); -int CDC_GetNumInterfaces(void); -int CDC_GetInterfaceDataLength(void); -int CDC_SendInterfaceData(void); -bool CDC_SendDeviceDescriptor(void); - -int CDC_GetDescriptor(int i); // handles the 'GET DESCRIPTOR' control packet -bool CDC_Setup(Setup& setup); // handles a 'SETUP' control packet -void CDC_FrameReceived(void); // call when frame is received and EP is configured -void CDC_SendACM(void); // call when you need to send a packet on the interrupt EP - -void CDC_Reset(void); // called whenever I get a bus reset - - -//================================================================================ -//================================================================================ - -#define TRANSFER_PGM 0x80 -#define TRANSFER_RELEASE 0x40 -#define TRANSFER_TOGGLE_ON 0x20 /* assign this to pre-set the 'toggle' bit on - only works when send queue is empty */ -#define TRANSFER_TOGGLE_OFF 0x10 /* assign this to pre-set the 'toggle' bit off - only works when send queue is empty */ - -// NOTE: USB_SendControl returns # of bytes sent, or 0x8000 if a ZLP is sent -// it will return 0 on error, such as the inability to allocate a buffer -// control packets send 64 bytes at a time, so the total size is limited -// by the number of available buffers. - -int USB_SendControl(uint8_t flags, const void* d, int len); -#ifdef PROGMEM -int USB_SendControlP(uint8_t flags, const void * PROGMEM d, int len); -// called internally if you use TRANSFER_PGM flag; you can also call this directly -#endif // PROGMEM - -uint16_t USB_Available(uint8_t ep); // returns # of bytes in the buffer on an OUT or CONTROL endpoint -uint16_t USB_SendQLength(uint8_t ep); // returns # of buffers in the send queue for an IN or CONTROL endpoint -bool USB_IsSendQFull(uint8_t ep); // this returns TRUE if there are too many outgoing buffers already (IN, CONTROL) -bool USB_IsStalled(uint8_t ep); // this tells me I'm 'stalled' (BULK IN, INTERRUPT, CONTROL) -int USB_Send(uint8_t ep, const void* data, // send endpoint data. bSendNow marks it "to send" - int len, uint8_t bSendNow); -int USB_Recv(uint8_t ep, void* data, // 'receive' data from endpoint receive queue. returns < 0 on error, or # of bytes - int len); -int USB_Recv(uint8_t ep); // 'receive' one byte of data from endpoint receive queue -void USB_Flush(uint8_t ep); // 'sends' all pending data by marking the buffers "to send" - -uint16_t GetFrameNumber(void); // a debug API to obtain the latest USB frame number -uint8_t USB_GetEPType(uint8_t nEP); // another debug API to return endpoint type by index - -#endif - -#endif /* if defined(USBCON) */ - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp b/BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp deleted file mode 100644 index 31d18e6..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp +++ /dev/null @@ -1,3745 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ ____ ____ // -// | | | |/ ___| | __ ) / ___| ___ _ __ ___ ___ _ __ _ __ // -// | | | |\___ \ | _ \ | | / _ \ | '__|/ _ \ / __|| '_ \ | '_ \ // -// | |_| | ___) || |_) || |___| (_) || | | __/ _| (__ | |_) || |_) | // -// \___/ |____/ |____/ \____|\___/ |_| \___|(_)\___|| .__/ | .__/ // -// |_| |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -/* Copyright (c) 2010, 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. -*/ - - -// ************************************************************************** -// This software incorporates Arthur C. Clarke's 3rd law: -// "Any sufficiently advanced technology is indistinguishable from magic." -// (no chickens were harmed nor sacrificed in the completion of this work) -// ************************************************************************** - -// Updated for the XMegaForArduino project by Bob Frazier, S.F.T. Inc. - -#define DEBUG_CODE /* debug output via 'error_print' etc. - must do this first */ - -#include "Platform.h" -#include "USBAPI.h" -#include "USBDesc.h" - -#include "wiring_private.h" - - -#if defined(USBCON) - -// CONDITIONALS FOR COMPILE-TIME OPTIONS - -//#define DEBUG_MEM /* debug memory and buffer manipulation */ -//#define DEBUG_QUEUE /* debug queues */ -//#define DEBUG_CONTROL /* control packet verbose debugging */ - - -// 'LIKELY' and 'UNLIKELY' - 'if'/branch optimization -#define UNLIKELY(x) (__builtin_expect (!!(x), 0)) -#define LIKELY(x) (__builtin_expect (!!(x), 1)) - - -// This next block of code is to deal with gcc bug 34734 on compilers < 4.6 -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -#define PROGMEM_ORIG PROGMEM -#else // PROGMEM workaround - -// to avoid the bogus "initialized variables" warning -#ifdef PROGMEM -#undef PROGMEM -#endif // PROGMEM re-define - -#define PROGMEM __attribute__((section(".progmem.usbcore"))) -#define PROGMEM_ORIG __attribute__((__progmem__)) - -#endif // check for GNUC >= or < 4.6 - - -// bugs in iox128a1u.h and iox64a1u.h -// the definition for USB_TRNCOMPL_vect and USB_TRNCOMPL_vect_num is wrong -// this can be corrected here. bug reported 'upstream' for avr-libc 1.8.0 and 1.8.1 -// https://savannah.nongnu.org/bugs/index.php?44279 -// -// (note this was causing me to get reboots, until I discovered the problem - very frustrating indeed) - -#if defined (__AVR_ATxmega64A1U__) || defined (__AVR_ATxmega128A1U__) -#undef USB_TRNCOMPL_vect -#undef USB_TRNCOMPL_vect_num -#define USB_TRNCOMPL_vect_num 126 -#define USB_TRNCOMPL_vect _VECTOR(126) /* Transaction complete interrupt */ -#endif // __AVR_ATxmega64A1U__, __AVR_ATxmega128A1U__ - -// additional compatibilty bugs between older and newer versions of iox128a1u.h and iox64a1u.h -#ifdef USB_EP_BUFSIZE_gm -#define USB_EP_SIZE_64_gc USB_EP_BUFSIZE_64_gc /* name change of definition from previous header */ -#endif // USB_EP_BUFSIZE_gm - -#ifndef CLK_USBEN_bm -#define CLK_USBEN_bm CLK_USBSEN_bm /* name change of definition from previous header */ -#endif // CLK_USBEN_bm - - - -// number of endpoints - to determine buffer array sizes -// see definition for _initEndpoints (below) -#ifdef CDC_ENABLED -#ifdef HID_ENABLED -#define INTERNAL_NUM_EP 5 -#else // HID_ENABLED _not_ defined -#define INTERNAL_NUM_EP 4 -#endif // HID_ENABLED -#elif defined(HID_ENABLED) -#define INTERNAL_NUM_EP 2 -#else -#define INTERNAL_NUM_EP 1 -#endif - - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ _____ ____ _ _ ____ _____ _ _ ____ _____ ____ // -// / ___||_ _|| _ \ | | | | / ___||_ _|| | | || _ \ | ____|/ ___| // -// \___ \ | | | |_) || | | || | | | | | | || |_) || _| \___ \ // -// ___) | | | | _ < | |_| || |___ | | | |_| || _ < | |___ ___) | // -// |____/ |_| |_| \_\ \___/ \____| |_| \___/ |_| \_\|_____||____/ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -#define INTERNAL_BUFFER_LENGTH 64 - -// TODO: use separate chain of smaller buffers for control channel??? - -typedef struct __INTERNAL_BUFFER__ -{ - struct __INTERNAL_BUFFER__ * volatile pNext; - volatile uint8_t iIndex; // current pointer - volatile uint8_t iLen; // max pointer - // NOTE: if 'iLen' is zero, the buffer is being filled and 'iIndex' is the length - // when the buffer is released to send, iLen gets the length, iIndex is assigned - // to 0xff. when sendING, iIndex is assigned to 0xfe. On send complete, it's free'd - - uint8_t aBuf[INTERNAL_BUFFER_LENGTH]; -} INTERNAL_BUFFER; - - - -///////////////////////////////////////////////////////////////////////////////////////////////////// -// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG -#ifdef DEBUG_CODE - -// additional debug functions ALSO defined in 'USBAPI.h' - need 'weak' and local definitions -// that way the code still builds/links without the debug functions -extern "C" -{ - extern void error_print(const char *p1) __attribute__((weak)); - extern void error_print_(const char *p1) __attribute__((weak)); - extern void error_printH(unsigned long) __attribute__((weak)); - extern void error_printH_(unsigned long) __attribute__((weak)); - extern void error_printL(unsigned long) __attribute__((weak)); - extern void error_printL_(unsigned long) __attribute__((weak)); - extern void error_printP(const void * p1) __attribute__((weak)); - extern void error_printP_(const void * p1) __attribute__((weak)); - - extern void error_print(const char *p1) { } - extern void error_print_(const char *p1) { } - extern void error_printH(unsigned long) { } - extern void error_printH_(unsigned long) { } - extern void error_printL(unsigned long) { } - extern void error_printL_(unsigned long) { } - extern void error_printP(const void * p1) { } - extern void error_printP_(const void * p1) { } -}; - - -#ifndef TX_RX_LED_INIT -#define LED_SIGNAL0 (LED_BUILTIN-2) /* PQ3 */ -#define LED_SIGNAL1 (LED_BUILTIN-3) /* PQ2 */ -#define LED_SIGNAL2 (LED_BUILTIN-4) /* PQ1 */ -#define LED_SIGNAL3 (LED_BUILTIN-5) /* PQ0 */ - -#define TX_RX_LED_INIT() { pinMode(LED_SIGNAL2,OUTPUT); pinMode(LED_SIGNAL3,OUTPUT); \ - digitalWrite(LED_SIGNAL2,0); digitalWrite(LED_SIGNAL3,0); } -#define TXLED0() digitalWrite(LED_SIGNAL2,0) -#define TXLED1() digitalWrite(LED_SIGNAL2,1) -#define RXLED0() digitalWrite(LED_SIGNAL3,0) -#define RXLED1() digitalWrite(LED_SIGNAL3,1) -#endif // TX_RX_LED_INIT - -#else - -#define DumpHex(X,Y) -#define DumpBuffer(X) - -#endif // DEBUG_CODE - - -// DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG -///////////////////////////////////////////////////////////////////////////////////////////////////// - - -#define EP_TYPE_CONTROL 0x00 -#define EP_TYPE_BULK_IN 0x81 -#define EP_TYPE_BULK_OUT 0x80 -#define EP_TYPE_INTERRUPT_IN 0xC1 -#define EP_TYPE_INTERRUPT_OUT 0xC0 -#define EP_TYPE_ISOCHRONOUS_IN 0x41 -#define EP_TYPE_ISOCHRONOUS_OUT 0x40 - - - -// NOTE: auto ZLP is broken according to 128A1U errata -#define ZLP_BIT 0/*(((uint16_t)USB_EP_ZLP_bm)<<8)*/ - -//================================================================== -//================================================================== - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ ___ _ _ ____ _____ _ _ _ _____ ____ // -// / ___|/ _ \ | \ | |/ ___||_ _| / \ | \ | ||_ _|/ ___| // -// | | | | | || \| |\___ \ | | / _ \ | \| | | | \___ \ // -// | |___| |_| || |\ | ___) | | | / ___ \ | |\ | | | ___) | // -// \____|\___/ |_| \_||____/ |_|/_/ \_\|_| \_| |_| |____/ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - - -const u16 USB_STRING_LANGUAGE[2] PROGMEM = // not actually a 'string' but same format -{ - (3<<8) | (2+2), // high byte is '3', low byte is total length (in bytes) - 0x0409 // English -}; - -// TODO: re-factor string returns into a utility function that builds the header -// and assigns the length correctly using the array address and 'sizeof' -// for now, the string starts with "\x03nn" where 'nn' is the total length -// in bytes for the entire string (including the 'header' char) - -#ifndef USB_PRODUCT_NAME -// if the pins_arduino.h file does NOT define a product name, define one HERE -#if USB_PID == 0x8036 && USB_VID == 0x2341 - #define USB_PRODUCT_NAME L"\x0322" "Arduino Leonardo" /* 16 characters, total length 34 */ -#elif USB_PID == 0x8037 && USB_VID == 0x2341 - #define USB_PRODUCT_NAME L"\x031c" "Arduino Micro" /* 13 characters, total length 28 */ -#elif USB_PID == 0x803C && USB_VID == 0x2341 - #define USB_PRODUCT_NAME L"\x0320" "Arduino Esplora" /* 15 characters, total length 32 */ -#elif USB_PID == 0x9208 && (USB_VID == 0x1b4f || USB_VID == 0x2341) // NOTE: I don't know which VID is right - #define USB_PRODUCT_NAME L"\x0316" "LilyPadUSB" /* 10 characters, total length 22 */ -#elif USB_PID == 0x0010 && USB_VID == 0x2341 // added for 'mega' clone (testing only) - #define USB_PRODUCT_NAME L"\x0322" "Arduino Mega2560" /* 16 characters, total length 34 */ -#elif USB_VID==0x16c0 && USB_PID==0x05e1 /* CDC/ACM device using name-based device identification */ - #define USB_PRODUCT_NAME L"\x0330" "XMegaForArduino Project" /* 23 chars, total length 48 */ -#else - #define USB_PRODUCT_NAME L"\x0330" "XMegaForArduino Project" /* 23 characters, total length 48 */ -#endif // various USB_VID/USB_PID combos -#endif // USB_PRODUCT_NAME - -const wchar_t USB_STRING_PRODUCT_STR[] PROGMEM = USB_PRODUCT_NAME; -#define USB_STRING_PRODUCT ((const u16 *)&(USB_STRING_PRODUCT_STR[0])) - - -#ifndef USB_MANUFACTURER_NAME -// if the pins_arduino.h file does NOT define a manufacturer name, define one HERE -#if USB_VID == 0x2341 - #define USB_MANUFACTURER_NAME L"\x0318" "Arduino LLC" /* string length 11, total 24 */ - #warning using Arduino USB Vendor ID - do NOT ship product with this ID without permission!!! -#elif USB_VID == 0x1b4f - #define USB_MANUFACTURER_NAME L"\x0314" "Sparkfun" /* string length 9, total 20 */ - #warning using SparkFun USB Vendor ID - do NOT ship product with this ID without permission!!! -#elif USB_VID == 0x1d50 - #define USB_MANUFACTURER_NAME L"\x0314" "Openmoko" /* string length 9, total 20 */ - /* Openmoko - see http://wiki.openmoko.org/wiki/USB_Product_IDs */ - #warning make sure you have obtained a proper product ID from Openmoko - see http://wiki.openmoko.org/wiki/USB_Product_IDs -#elif USB_VID==0x16c0 && USB_PID==0x05e1 /* CDC/ACM device using name-based device identification */ - #define USB_MANUFACTURER_NAME L"\x033a" "S.F.T. Inc. http://mrp3.com/" /* string length 28, total length 58 */ -#elif USB_VID == 0x16c0 - #define USB_MANUFACTURER_NAME L"\x0344" "Van Ooijen Technische Informatica" /* string length 34, total 70 */ - #warning Using the default vendor description for VID 16C0H - see https://raw.githubusercontent.com/arduino/ArduinoISP/master/usbdrv/USB-IDs-for-free.txt -#else - #define USB_MANUFACTURER_NAME L"\x0312" "Unknown" /* string length 8, total 18 */ -#endif // various USB_VID/USB_PID combos -#endif // USB_MANUFACTURER_NAME - -const wchar_t USB_STRING_MANUFACTURER_STR[] PROGMEM = USB_MANUFACTURER_NAME; -#define USB_STRING_MANUFACTURER ((const u16 *)&(USB_STRING_MANUFACTURER_STR[0])) - - -// ------------------------------------------- -// DEFAULT DEVICE DESCRIPTOR (device class 0) -// ------------------------------------------- -// this instructs the USB host to use the information in the individual interface descriptors -// see http://www.usb.org/developers/defined_class/#BaseClass00h -const DeviceDescriptor USB_DeviceDescriptor PROGMEM = - D_DEVICE(0x00, // device class (0) - use interface descriptors - 0x00, // device sub-class (0) - 0x00, // device protocol (0) - 64, // packet size (64) - USB_VID, // vendor ID for the USB device - USB_PID, // product ID for the USB device - 0x100, // this indicates USB version 1.0 - USB_STRING_INDEX_MANUFACTURER, // string index for mfg - USB_STRING_INDEX_PRODUCT, // string index for product name - USB_STRING_INDEX_SERIAL, // string index for serial number (0 for 'none') - 1); // number of configurations (1) - - -// ----------------------------- -// ALTERNATE DEVICE DESCRIPTOR -// ----------------------------- -// this is derived from the latest Arduino core - note that it defins a 'miscellaneous' device -// and this descriptor is returned whenever the device is a 'composite'. However, I think the -// logic by which this is used is just WRONG and the above descriptor is probably a better choice. -// For additional info, see http://www.usb.org/developers/defined_class/#BaseClassEFh -const DeviceDescriptor USB_DeviceDescriptorB PROGMEM = - D_DEVICE(0xEF, // device class (0xef, miscellaneous) - 0x02, // device sub-class (2) - 0x01, // device protocol (protocol 1, subclass 2 - Interface Association Descriptor) - 64, // packet size (64) - USB_VID, // vendor ID for the USB device - USB_PID, // product ID for the USB device - 0x100, // this indicates USB version 1.0 - USB_STRING_INDEX_MANUFACTURER, // string index for mfg - USB_STRING_INDEX_PRODUCT, // string index for product name - USB_STRING_INDEX_SERIAL, // string index for serial number (0 for 'none') - 1); // number of configurations (1) - - -//================================================================== -//================================================================== - - -// TODO: make this dynamically generated instead, using supported devices -// this may require 'malloc' for aSendQ and aRecvQ, however... -const u8 _initEndpoints[INTERNAL_NUM_EP] PROGMEM = -{ - EP_TYPE_CONTROL, // EP_TYPE_CONTROL control endpoint [always endpoint 0] - -#ifdef CDC_ENABLED - EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM write, interrupt (endpoint 1) max 8 bytes - EP_TYPE_BULK_OUT, // EP_TYPE_ISOCHRONOUS_OUT, // EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT bulk read (endpoint 2) max 64 bytes - EP_TYPE_BULK_IN, //EP_TYPE_ISOCHRONOUS_IN, // EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN bulk write (endpoint 3) max 64 bytes - -#ifdef HID_ENABLED -#error THIS kind of composite device NOT supported at this time -#endif - -#endif - -#ifdef HID_ENABLED - EP_TYPE_INTERRUPT_IN // HID_ENDPOINT_INT write, interrupt (endpoint 1) -#endif -}; - - -// XMegaForArduino still uses older defs for these (TODO - update to something better) -#define EP_SINGLE_64 0x32 // EP0 and single-buffer int-driven endpoints -#define EP_DOUBLE_64 0x36 // endpoints that support double-buffer out - - - - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ ___ ____ _ _ ____ // -// / ___|| | / _ \ | __ ) / \ | | / ___| // -// | | _ | | | | | || _ \ / _ \ | | \___ \ // -// | |_| || |___| |_| || |_) |/ ___ \ | |___ ___) | // -// \____||_____|\___/ |____//_/ \_\|_____||____/ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -// A linked list of pre-allocated buffers, twice the # of endpoints plus 4 . -// Most endpoints ONLY read OR write, and control EP does both. This lets me have -// 2 read or 2 write buffers per endpoint, perfect for 'ping pong' buffering -// (even if I implement that manually), or one each for bi-directional comms. -// The additional 4 buffers allows me to construct ~256 byte data packets using -// 4 64-byte buffers, and not have to wait for anything being sent. For buffers -// with data larger than 256 bytes, I guess you'll have to get a bigger CPU anyway... - -INTERNAL_BUFFER *pFree = NULL; - -#if INTERNAL_NUM_EP <= 2 -INTERNAL_BUFFER aBufList[8]; // the minimum number is 8 buffers, determined by experimentation -#else // INTERNAL_NUM_EP > 2 -INTERNAL_BUFFER aBufList[INTERNAL_NUM_EP * 2 + 4]; // twice the # of endpoints plus 4 -#endif // INTERNAL_NUM_EP <= 2 - -#define NUM_INTERNAL_BUFFERS (sizeof(aBufList)/sizeof(aBufList[0])) /* universally accurate */ - - -INTERNAL_BUFFER *aSendQ[INTERNAL_NUM_EP]; // send and receive queue head pointers, one per in/out per endpoint -INTERNAL_BUFFER *aRecvQ[INTERNAL_NUM_EP]; - -#define INTERNAL_BUFFER_FILLING(X) ((X)->iLen == 0 && (X)->iIndex < 0xfe) /* buffer filling (or empty) */ -#define INTERNAL_BUFFER_SEND_READY(X) ((X)->iIndex == 0xff) /* ready to send */ -#define INTERNAL_BUFFER_MARK_SEND_READY(X) {(X)->iLen = (X)->iIndex; (X)->iIndex = 0xff;} -#define INTERNAL_BUFFER_SENDING(X) ((X)->iIndex == 0xfe) /* is 'sending' */ -#define INTERNAL_BUFFER_MARK_SENDING(X) {(X)->iIndex = 0xfe;} /* mark 'sending' */ -#define INTERNAL_BUFFER_RECV_EMPTY(X) (!(X)->iIndex && !(X)->iLen) /* empty receive buffer */ -#define INTERNAL_BUFFER_RECV_READY(X) ((X)->iLen > 0) /* received data ready */ - - - -/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ -#ifdef TX_RX_LED_INIT /* only when these are defined */ -#define TX_RX_LED_PULSE_MS 100 -volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ -volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ -#endif // TX_RX_LED_INIT - -static XMegaEPDataStruct epData; // the data pointer for the hardware's memory registers - -//// for debugging only - remove later -//static uint8_t led_toggle; - -static uint8_t bUSBAddress = 0; // when not zero, and a packet has been sent on EP 0, set the address to THIS -static uint8_t _usbConfiguration = 0; // assigned when I get a 'SET CONFIGURATION' control packet - -static uint16_t wProcessingFlag = 0; // 'processing' flag -// the endpoint's bit in 'wProcessingFlag' will be set to '1' whenever an incoming -// packet is being processed. This prevents re-entrant processing of OTHER incoming -// packets while this is going on, so that incoming packets are serialized. -static uint16_t wMultipacketOutFlag = 0; // 'multipacket out I/O' flag -// the endpoint's bit in 'wMultipacketFlag' will be set whenever the 'IN' endpoint is -// being used to receive data (normally it's just 'OUT' that receives). This can happen -// with bulk, interrupt, or control endpoints. yeah, it changes things quite a bit. -static uint16_t wEndpointToggle = 0; // controls use of 'toggle' bit when sending a packet - - - - -///////////////////////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ _ _ // -// | | ___ ___ __ _ | | | _ \ _ __ ___ | |_ ___ | |_ _ _ _ __ ___ ___ // -// | | / _ \ / __|/ _` || | | |_) || '__|/ _ \ | __|/ _ \ | __|| | | || '_ \ / _ \/ __| // -// | |___| (_) || (__| (_| || | | __/ | | | (_) || |_| (_) || |_ | |_| || |_) || __/\__ \ // -// |_____|\___/ \___|\__,_||_| |_| |_| \___/ \__|\___/ \__| \__, || .__/ \___||___/ // -// |___/ |_| // -// // -///////////////////////////////////////////////////////////////////////////////////////////////// - - -static void init_buffers_and_endpoints(void); -static void internal_do_control_request(INTERNAL_BUFFER *pBuf, bool bIsSetup); -static void consolidate_packets(INTERNAL_BUFFER *pHead); - -static void InitEP(u8 index, u8 type, u8 size); - -static bool SendDescriptor(Setup& rSetup); - -static uint16_t buffer_data_pointer(INTERNAL_BUFFER *pBuf); -static INTERNAL_BUFFER * inverse_buffer_data_pointer(uint16_t dataptr); - -static void internal_flush(int index); -static bool internal_send0(int index); -static bool internal_send(int index, const void *pData, uint16_t cbData, uint8_t bSendNow); -static int internal_receive(int index, void *pData, uint16_t nMax); // only for OUT endpoints -static void configure_buffers(void); - -static bool ClassInterfaceRequest(Setup& rSetup); - - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ _ _____ _____ _____ ____ ____ // -// | __ ) | | | || ___|| ___|| ____|| _ \ / ___| // -// | _ \ | | | || |_ | |_ | _| | |_) |\___ \ // -// | |_) || |_| || _| | _| | |___ | _ < ___) | // -// |____/ \___/ |_| |_| |_____||_| \_\|____/ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -static void init_buffers_and_endpoints(void) __attribute__((noinline)); -static INTERNAL_BUFFER *end_of_chain(INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static void configure_buffers(void) __attribute__((noinline)); -static INTERNAL_BUFFER * next_buffer(void) __attribute__((noinline)); -static void free_buffer(INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static void free_queue(INTERNAL_BUFFER **pQ) __attribute__((noinline)); -static uint8_t not_in_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static void add_to_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static void remove_from_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static void remove_from_queue_and_free(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static uint16_t buffer_data_pointer(INTERNAL_BUFFER *pBuf) __attribute__((noinline)); -static INTERNAL_BUFFER * inverse_buffer_data_pointer(uint16_t dataptr) __attribute__((noinline)); - -static void init_buffers_and_endpoints(void) -{ -int index; -uint8_t oldSREG; - -#ifdef DEBUG_MEM - error_printP(F("init_buffers_and_endpoints")); -#endif // DEBUG_MEM - - oldSREG = SREG; - cli(); // to avoid spurious interrupts (just in case) - - memset(&epData, 0, sizeof(epData)); - for(index=0; index <= MAXEP; index++) - { - epData.endpoint[index].out.status = USB_EP_BUSNACK0_bm; // disables I/O - epData.endpoint[index].in.status = USB_EP_BUSNACK0_bm; // necessary for 128A1U rev 'K' etc. (see errata) - - epData.endpoint[index].out.ctrl = USB_EP_TYPE_DISABLE_gc; // to disable it (endpoint 'type 0' disables) - epData.endpoint[index].in.ctrl = USB_EP_TYPE_DISABLE_gc; // initially (disable) - } - - configure_buffers(); // TODO: move code here instead of function call? - - // set up endpoint 0 (always), now that I'm done doing that other stuff - - InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0 and zero out the others - - wProcessingFlag = 0; - wMultipacketOutFlag = 0; - wEndpointToggle = 0; - - bUSBAddress = 0; - -#ifdef TX_RX_LED_INIT - TxLEDPulse = RxLEDPulse = 0; - TXLED0(); - RXLED0(); -#endif // TX_RX_LED_INIT - -#ifdef CDC_ENABLED - CDC_Reset(); -#endif // CDC_ENABLED - -#ifdef HID_ENABLED - HID_Reset(); -#endif // HID_ENABLED - - SREG = oldSREG; -} - - -static INTERNAL_BUFFER *end_of_chain(INTERNAL_BUFFER *pBuf) -{ -uint8_t oldSREG; -register INTERNAL_BUFFER *pRval; - - - if(!pBuf) - { - return NULL; - } - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pRval = pBuf; - - if(pRval < &(aBufList[0]) || pRval >= &(aBufList[NUM_INTERNAL_BUFFERS])) - { - error_printP_(F("end_of_chain: pBuf out of bounds ")); - error_printH((unsigned long)pBuf); - - SREG = oldSREG; - return NULL; - } - - while(pRval->pNext) - { - pRval = pRval->pNext; - - if(pRval < &(aBufList[0]) || pRval >= &(aBufList[NUM_INTERNAL_BUFFERS])) - { - error_printP_(F("end_of_chain: pRval out of bounds ")); - error_printH((unsigned long)pRval); - - SREG = oldSREG; - return NULL; - } - } - - SREG = oldSREG; - - if(pRval >= &(aBufList[0]) && pRval < &(aBufList[NUM_INTERNAL_BUFFERS])) - { - return pRval; - } - - error_printP(F("WARN: end_of_chain - corrupt buffer chain, returns NULL")); - - return NULL; -} - - -// simple pre-allocated buffer management -static void configure_buffers(void) -{ -register uint8_t i1; - -#ifdef DEBUG_MEM - error_printP(F("configure_buffers")); -#endif // DEBUG_MEM - - memset(aBufList, 0, sizeof(aBufList)); - - for(i1=1; i1 < NUM_INTERNAL_BUFFERS; i1++) - { - aBufList[i1 - 1].pNext = &(aBufList[i1]); - } - - // tail gets NULL for 'pNext' - aBufList[NUM_INTERNAL_BUFFERS - 1].pNext = NULL; - - // head of free list is first entry - pFree = &(aBufList[0]); - - // send and receive queues - for(i1=0; i1 < INTERNAL_NUM_EP; i1++) - { - aSendQ[i1] = NULL; - aRecvQ[i1] = NULL; - } -} - - -// this function peels a pointer from the 'free' list and returns it. -// caller must call 'free_buffer' with returned pointer when done with it -// and *NOT* re-use it after calling 'free_buffer'. -static INTERNAL_BUFFER * next_buffer(void) -{ -INTERNAL_BUFFER *pRval; -uint8_t oldSREG; - - -#ifdef DEBUG_MEM - error_printP_(F("next_buffer ")); -#endif // DEBUG_MEM - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pRval = pFree; - - if(pRval) // non-NULL return - { - pFree = pRval->pNext; - pRval->pNext = NULL; - } - - if(!pRval) - { -#ifdef DEBUG_MEM - error_printP_(F("!!pRval NULL!!")); -#else // DEBUG_MEM - error_printP(F("next_buffer !!pRval NULL!!")); -#endif // DEBUG_MEM - } - else if(pRval < &(aBufList[0]) || pRval >= &(aBufList[NUM_INTERNAL_BUFFERS])) - { -#ifdef DEBUG_MEM - error_printP_(F("!!pRval out of bounds!!")); - error_printH_((uint16_t)pRval); -#else // DEBUG_MEM - error_printP_(F("next_buffer !!pRval out of bounds!!")); - error_printH((uint16_t)pRval); -#endif // DEBUG_MEM - - pRval = NULL; // prevent propagating errors - } - else - { -#ifdef DEBUG_MEM - error_printH_((uint16_t)pRval); -#endif // DEBUG_MEM - } - -#ifdef DEBUG_MEM // extra debug - - uint8_t nBuf; - INTERNAL_BUFFER *pR = pFree; - - for(nBuf=0; pR; nBuf++, pR = pR->pNext) - ; - - error_printP_(F(" (")); - error_printL_(nBuf); - error_printP(F(" free)")); - -#endif // DEBUG_MEM - - SREG = oldSREG; - - return pRval; // now it belongs to the caller -} - - -static void free_buffer(INTERNAL_BUFFER *pBuf) -{ -#ifdef DEBUG_MEM - error_printP_(F("free_buffer ")); -#endif // DEBUG_MEM - - // simple sanity test, must be in range ('address valid' could be tested as well) - if(pBuf >= &(aBufList[0]) && pBuf < &(aBufList[NUM_INTERNAL_BUFFERS])) - { - uint8_t oldSREG = SREG; // save int flag - cli(); // locking resource - - pBuf->pNext = pFree; - pFree = pBuf; - - SREG = oldSREG; - -#ifdef DEBUG_MEM - error_printH_((uint16_t)pBuf); -#endif // DEBUG_MEM - } - else - { -#ifdef DEBUG_MEM - error_printP_(F("- address ")); - error_printH_((uint16_t)pBuf); - error_printP_(F(" not valid")); -#endif // DEBUG_MEM - } - -#ifdef DEBUG_MEM // extra debug - - uint8_t nBuf; - INTERNAL_BUFFER *pR = pFree; - - for(nBuf=0; pR; nBuf++, pR = pR->pNext) - ; - - error_printP_(F(" (")); - error_printL_(nBuf); - error_printP(F(" free)")); - -#endif // DEBUG_MEM - -} - -// Free an entire queue, assigning NULL to '*pQ' when done -static void free_queue(INTERNAL_BUFFER **pQ) -{ -INTERNAL_BUFFER *pE; -uint8_t oldSREG; - - if(!pQ) - { - return; - } - -#ifdef DEBUG_MEM // extra debug - error_printP(F("free_queue ")); - - if(pQ >= &(aSendQ[0]) && pQ < &(aSendQ[sizeof(aSendQ)/sizeof(aSendQ[0])])) - { - error_printP_(F("aSendQ[")); - error_printL_(pQ - &(aSendQ[0])); - error_printP(F("]")); - } - else if(pQ >= &(aRecvQ[0]) && pQ < &(aRecvQ[sizeof(aRecvQ)/sizeof(aRecvQ[0])])) - { - error_printP_(F("aRecvQ[")); - error_printL_(pQ - &(aRecvQ[0])); - error_printP(F("]")); - } - else - { - error_printP(F("Q???Q")); - } -#endif // DEBUG_MEM - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pE = *pQ; // NOTE: if NULL, function will do nothing - - *pQ = NULL; // detach entire queue at once - - while(pE) - { - register INTERNAL_BUFFER *pE2 = pE->pNext; - - pE->pNext = NULL; - - free_buffer(pE); - - pE = pE2; // advances to next entry (NULL when done) - } - - SREG = oldSREG; -} - -static uint8_t not_in_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) -{ -INTERNAL_BUFFER *pE; -uint8_t oldSREG; - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pE = *pQ; - - while(pE) - { - if(pE == pBuf) - { - SREG = oldSREG; - return 0; - } - - pE = pE->pNext; - } - - SREG = oldSREG; - - return 1; // buffer not in queue -} - - -static void add_to_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) -{ -INTERNAL_BUFFER *pE; -uint8_t oldSREG; -#ifdef DEBUG_MEM // extra debug -uint8_t nQ; -#endif // DEBUG_MEM // extra debug - - - if(!pQ || !pBuf) - { - return; - } - -#ifdef DEBUG_MEM // extra debug - error_printP_(F("add_to_queue ")); - - if(pQ >= &(aSendQ[0]) && pQ < &(aSendQ[sizeof(aSendQ)/sizeof(aSendQ[0])])) - { - error_printP_(F("aSendQ[")); - error_printL_(pQ - &(aSendQ[0])); - error_printP_(F("]")); - } - else if(pQ >= &(aRecvQ[0]) && pQ < &(aRecvQ[sizeof(aRecvQ)/sizeof(aRecvQ[0])])) - { - error_printP_(F("aRecvQ[")); - error_printL_(pQ - &(aRecvQ[0])); - error_printP_(F("]")); - } - else - { - error_printP_(F("Q???Q")); - } - - error_printP_(F(" length=")); -#endif // DEBUG_MEM - - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pE = *pQ; - - pBuf->pNext = NULL; // make sure - - if(!pE) - { - *pQ = pBuf; - } - else - { - // walk to the end - while(pE->pNext) - { - pE = pE->pNext; - } - - // attach - pE->pNext = pBuf; - } - -#ifdef DEBUG_MEM // extra debug - // count them (for debugging) - pE = *pQ; - nQ = 0; - - while(pE) // just count them - { - nQ++; - pE = pE->pNext; // walk the chain - } - - error_printL(nQ); -#endif // DEBUG_MEM - - SREG = oldSREG; -} - - -// this utility removes the buffer, but does not free it -static void remove_from_queue(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) -{ -INTERNAL_BUFFER *pE; -uint8_t oldSREG; -#ifdef DEBUG_MEM // extra debug -uint8_t nQ; -#endif // DEBUG_MEM // extra debug - - - if(!pQ || !pBuf) - { - return; - } - -#ifdef DEBUG_MEM // extra debug - error_printP_(F("remove_from_queue ")); - - if(pQ >= &(aSendQ[0]) && pQ < &(aSendQ[sizeof(aSendQ)/sizeof(aSendQ[0])])) - { - error_printP_(F("aSendQ[")); - error_printL_(pQ - &(aSendQ[0])); - error_printP_(F("]")); - } - else if(pQ >= &(aRecvQ[0]) && pQ < &(aRecvQ[sizeof(aRecvQ)/sizeof(aRecvQ[0])])) - { - error_printP_(F("aRecvQ[")); - error_printL_(pQ - &(aRecvQ[0])); - error_printP_(F("]")); - } - else - { - error_printP_(F("Q???Q")); - } -#endif // DEBUG_MEM - - - oldSREG = SREG; // save int flag - cli(); // locking resource - - pE = *pQ; - - if(pE) // if not NULL [allow for problems, delete buffer anyway] - { - if(LIKELY(pBuf == pE)) - { -#ifdef DEBUG_MEM // extra debug - error_printP_(F(" (head) ")); -#endif // DEBUG_MEM - - *pQ = pBuf->pNext; // remove the head of the queue (typical) - } - else - { - while(pE && pE->pNext != pBuf) - { - pE = pE->pNext; // walk the chain - } - - if(pE && pE->pNext == pBuf) // found - { -#ifdef DEBUG_MEM // extra debug - error_printP_(F(" (mid) ")); -#endif // DEBUG_MEM - - pE->pNext = pBuf->pNext; // remove 'pBuf' from the chain - } - else - { -#ifdef DEBUG_MEM // extra debug - error_printP_(F(" NOT removing ")); - error_printH_((uint16_t)pBuf); - error_printP_(F(" --> ")); - error_printH_((uint16_t)pBuf->pNext); -#endif // DEBUG_MEM - } - } - - } - - pBuf->pNext = NULL; // always - -#ifdef DEBUG_MEM // extra debug - // count them (for debugging) - pE = *pQ; - nQ = 0; - - while(pE) // just count them - { - nQ++; - pE = pE->pNext; // walk the chain - } - - error_printP_(F(" length=")); - error_printL(nQ); -#endif // DEBUG_MEM - - SREG = oldSREG; -} - - -static void remove_from_queue_and_free(INTERNAL_BUFFER **pQ, INTERNAL_BUFFER *pBuf) -{ - if(pBuf) - { - remove_from_queue(pQ, pBuf); - - free_buffer(pBuf); // and NOW 'pBuf' is back in the 'free' pool - } -} - - -static uint16_t buffer_data_pointer(INTERNAL_BUFFER *pBuf) -{ - if(!pBuf) - { - return 0; - } - - return (uint16_t)&(pBuf->aBuf[0]); // assign 'dataptr' element in USB Endpoint descriptor (sect 20.15 in 'AU' manual) -} - - -static INTERNAL_BUFFER * inverse_buffer_data_pointer(uint16_t dataptr) -{ - if(!dataptr) - { - return NULL; - } - - dataptr -= (uint16_t)&(((INTERNAL_BUFFER *)0)->aBuf[0]); - - return (INTERNAL_BUFFER *)dataptr; -} - - - - - -#ifdef DEBUG_CODE - -static char hex_digit(unsigned char b1) -{ - if(b1 < 10) - { - return b1 + '0'; - } - else if(b1 < 16) - { - return (b1 - 10) + 'A'; - } - - return '?'; -} - -void DumpHex(void *pBuf, uint8_t nBytes) -{ -char tbuf[60]; -uint8_t *pD; -char *pOut, nCol, c1; -short iCtr; - - error_printP_(F("Dump of data nBytes=")); - error_printL(nBytes); - error_printP(F(" --------------------------------------")); - - pOut = tbuf; - *pOut = 0; // must do this - - for(iCtr=0, nCol=0, pD = (uint8_t *)pBuf; iCtr < (int)nBytes; iCtr++, pD++) - { - if(!nCol) - { - pOut = tbuf; - - if(iCtr > 0) - { - error_print(tbuf); - tbuf[0] = 0; // always do this - } - - *(pOut++) = hex_digit((iCtr >> 4) & 0xf); - *(pOut++) = hex_digit(iCtr & 0xf); - *(pOut++) = ':'; - } - else - { - *(pOut++) = ' '; - } - - c1 = *pD; - - *(pOut++) = hex_digit((c1 >> 4) & 0xf); - *(pOut++) = hex_digit(c1 & 0xf); - *pOut = 0; // always do this - - if(nCol < 15) - { - nCol++; - } - else - { - nCol = 0; // starts new line - } - } - - if(tbuf[0]) - { - error_print(tbuf); - } -} - -void DumpBuffer(INTERNAL_BUFFER *pBuf) -{ -char tbuf[60]; -uint8_t *pD; -char *pOut, nCol, c1; -short iCtr; - - error_printP_(F("Dump of buffer ")); - error_printH_((uint16_t)pBuf); - error_printP_(F(" iIndex=")); - error_printL_(pBuf->iIndex); - error_printP_(F(" iLen=")); - error_printL_(pBuf->iLen); - error_printP_(F(" pNext=")); - error_printH((uint16_t)pBuf->pNext); - error_printP(F(" --------------------------------------")); - - pOut = tbuf; - *pOut = 0; - - for(iCtr=0, nCol=0, pD = pBuf->aBuf; pD < &(pBuf->aBuf[sizeof(pBuf->aBuf)]) && iCtr < pBuf->iLen; iCtr++, pD++) - { - if(!nCol) - { - pOut = tbuf; - - if(iCtr > 0) - { - error_print(tbuf); - tbuf[0] = 0; // always do this - } - - *(pOut++) = hex_digit((iCtr >> 4) & 0xf); - *(pOut++) = hex_digit(iCtr & 0xf); - *(pOut++) = ':'; - } - else - { - *(pOut++) = ' '; - } - - c1 = *pD; - - *(pOut++) = hex_digit((c1 >> 4) & 0xf); - *(pOut++) = hex_digit(c1 & 0xf); - *pOut = 0; // always do this - - if(nCol < 15) - { - nCol++; - } - else - { - nCol = 0; // starts new line - } - } - - if(tbuf[0]) - { - error_print(tbuf); - } - - -} - -#endif // DEBUG_CODE - - - -////////////////////////////////////////////////////////////////////////////// -// // -// ___ __ __ _ // -// / _ \ _ _ ___ _ _ ___ | \/ | __ _ _ __ ___ | |_ // -// | | | || | | | / _ \| | | | / _ \ | |\/| | / _` || '_ ` _ \ | __| // -// | |_| || |_| || __/| |_| || __/ | | | || (_| || | | | | || |_ // -// \__\_\ \__,_| \___| \__,_| \___| |_| |_| \__, ||_| |_| |_| \__| // -// |___/ // -// // -////////////////////////////////////////////////////////////////////////////// - - -static void set_up_EP_for_receive(int index) -{ -INTERNAL_BUFFER *pBuf; - - // assumed interrupts are OFF, setting up single endpoint to receive data - // with a fresh buffer added to the queue. existing buffers in recv queue are left 'as-is'. - - - // queue up the next one if there is one - pBuf = aRecvQ[index]; - - while(pBuf) - { - if(INTERNAL_BUFFER_RECV_EMPTY(pBuf)) // find empty buffer already in queue - { - break; - } - - pBuf = pBuf->pNext; - } - - if(!pBuf) // receive queue has ONLY non-empty buffers (or none at all) - allocate a new one - { - pBuf = next_buffer(); - - if(pBuf) - { - pBuf->iIndex = pBuf->iLen = 0; // make sure buffer is 'empty' - add_to_queue(&(aRecvQ[index]), pBuf); // this adds the new buffer to the chain, leaving the others 'as-is' - } - } - - epData.endpoint[index].out.status |= USB_EP_BUSNACK0_bm // make sure these are on, first - | USB_EP_UNF_bm | USB_EP_STALL_bm; // writing 1 is supposed to clear them - epData.endpoint[index].out.status &= ~(USB_EP_UNF_bm | USB_EP_STALL_bm); // but I'll do THIS, too - - epData.endpoint[index].out.cnt = 0; - epData.endpoint[index].out.auxdata = 0; - - if(pBuf) - { - epData.endpoint[index].out.dataptr = buffer_data_pointer(pBuf); //(uint16_t)pBuf; - - // I'm going to turn all of the 'bad bits' off... - epData.endpoint[index].out.status |= USB_EP_STALL_bm; // this turns off the bit by writing a '1' - - epData.endpoint[index].out.status &= USB_EP_TOGGLE_bm; // this allows receiving data (the old toggle bit remains) - } - else - { - epData.endpoint[index].out.dataptr = 0; // no buffer (stalled) - } - - epData.endpoint[index].out.ctrl &= ~_BV(2); // in case it was on, turn off the stall -} - - -static void DispatchIncomingPacket(uint8_t index, INTERNAL_BUFFER *pE, bool bIsSetup) -{ -uint16_t wProcessingMask = 1 << index; - - - wProcessingFlag |= wProcessingMask; // indicate I'm processing, and avoid recursion - - if(index == 0 /* && bOldStatus & USB_EP_SETUP_bm */) - { - // consolidate all of the packets pointed to by 'pRecvQ[0]' - - consolidate_packets(aRecvQ[0]); - pE = aRecvQ[0]; // grab packet from new head of queue (should be ALL of them actually) [for now assume only 1, later check] - - remove_from_queue(&(aRecvQ[index]), pE); // removes it from the queue (does not delete) - // NOTE: *ONLY* the control endpoint does this... - - if(pE->iLen) - { - internal_do_control_request(pE, bIsSetup); // always for endpoint 0 - } - - free_buffer(pE); // free up buffer [I am done with it] - - internal_flush(0); // flush the CONTROL endpoint's output buffers, now that I've done whatever operation this is - } - else - { - // TODO: handle BULK and INTERRUPT endpoints correctly - - if(pE->iLen) - { - // NOTE: this needs to remove the buffer from the queue to avoid - // any memory leaks. If not, it could fill up... - - if(// internal_get_endpoint_type(index) != EP_TYPE_CONTROL && - aRecvQ[index] != pE) - { - consolidate_packets(aRecvQ[index]); - } - else - { - pE->iIndex = 0; // always, to indicate where I am in the buffer [at the beginning] - } - - // NOTE: buffer remains in queue or is deleted by callback - } - else // zero-length packet - { - error_printP_(F("Received zero-length packet EP=")); - error_printL(index); - - // regardless, this packet must now be disposed of - - remove_from_queue(&(aRecvQ[index]), pE); // removes it from the queue (does not delete) - free_buffer(pE); // remove buffer (ZLP ignored for now) - } - } - - wProcessingFlag &= ~wProcessingMask; // indicate I'm no longer processing, and allow callbacks again -} - -static void check_recv_queue(void) -{ -int index; -INTERNAL_BUFFER *pE;//, *pEtmp; -uint8_t oldSREG; - - - oldSREG = SREG; - cli(); // this must be done with interrupts blocked - - for(index=MAXEP; index >= 0; index--) - { - uint16_t wProcessingMask = 1 << index; - - // skip disabled endpoints - if((epData.endpoint[index].out.ctrl & USB_EP_TYPE_gm) == USB_EP_TYPE_DISABLE_gc) - { - continue; // endpoint disabled (skip it) - } - - // skip endpoints that are currently processing something - if(wProcessingFlag & wProcessingMask) - { - continue; // skip something that's already processing, in case of recursion - } - -#ifdef ENABLE_PINGPPONG - // a special section for certain *kinds* of endpoints - // If I must receive data from the 'IN' endpoint as well as the 'OUT', such as - // for a BULK or INTERRUPT endpoint, I check for that here. - // NOTE: a CONTROL endpoint cannot do 'ping pong' mode. See AU manual section 20.6 - - if(wMultipacketOutFlag & wProcessingMask) // I'm currently using 'IN' to receive for this endpoint - { - pE = inverse_buffer_data_pointer(epData.endpoint[index].in.dataptr); - - if(!pE) // an internal error - clear the bit and process the packet in the queue - { - wMultipacketOutFlag &= ~wProcessingMask; // I'm no longer using 'IN' to receive for this endpoint - - if(index || aSendQ[0]) // NOT control, or send queue not empty - { - continue; // receive is stalled for the moment so skip this next part - } - } - else if((epData.endpoint[index].in.status & USB_EP_TRNCOMPL0_bm) // note: 'SETUP' is TRNCOMPL1, as needed - || (epData.endpoint[index].in.status & USB_EP_SETUP_bm)) // TODO: is this right?? - { - register uint8_t bOldStatus = epData.endpoint[index].in.status; - - // OK so what I did was to attach THIS packet to the receive queue, THEN assign its pointer - // to the IN endpoint, THEN wait for data to show up. Now that data has shown up, I need to - // consolidate it, and then process it "as it would have been". - - epData.endpoint[index].in.status = USB_EP_BUSNACK0_bm | // mark it 'do not send/receive' - (bOldStatus & ~(USB_EP_SETUP_bm | USB_EP_TRNCOMPL0_bm)); // turn these 2 bits off - - epData.endpoint[0].in.dataptr = 0; // zero out data pointer so I can send again - epData.endpoint[0].in.cnt = 0; - - wMultipacketOutFlag &= ~wProcessingMask; // I'm no longer using 'IN' to receive for this endpoint - - DispatchIncomingPacket(index, pE, 0); // not a SETUP because not index zero - - if(index || !aSendQ[0]) // remember, control endpoints don't receive until done sending - { -#ifdef DEBUG_QUEUE - error_printP(F("check_recv_queue -set up for receive (b)")); -#endif // DEBUG_QUEUE - - set_up_EP_for_receive(index); // set up to receive - } - - continue; - } - else - { - continue; // waiting for receive to complete - } - } -#endif // ENABLE_PINGPONG - - pE = inverse_buffer_data_pointer(epData.endpoint[index].out.dataptr); - - // check for an endpoint that has 'BUSNACK0' set - if((!pE || (epData.endpoint[index].out.status & USB_EP_BUSNACK0_bm)) && // NOT receiving at the moment - !aRecvQ[index]) // no new buffers to attach - { - // NOTE: control endpoints need to re-establish themselves to listen for more packets, - // whenever the send queue is empty, so flow through in THOSE cases - - if(!index && aSendQ[0]) // control, and send queue not empty - { - continue; // receive is stalled for the moment so skip this next part - } - - if(index && _usbConfiguration == 0) - { - continue; // when unconfigured, don't automatically add a new buffer - } - - // TODO: a callback to determine whether I should NOT add a buffer automatically?? - - // flow through and it should work - } - - // check for errors before anything else - if(epData.endpoint[index].out.status & USB_EP_STALL_bm) - { -#ifdef DEBUG_QUEUE - // first, handle "sent" transaction - error_printP_(F("check_recv_queue ")); - error_printL_(index); - error_printP(F(" - USB_EP_STALL")); -#endif // DEBUG_QUEUE - - // for now - turn off any 'stall' bit in the control reg and status reg - - epData.endpoint[index].out.status |= USB_EP_STALL_bm; - - if((epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { - // clear the stall bits in the control reg in case they were on - epData.endpoint[index].out.ctrl &= ~_BV(2); // note that this is NOT USB_EP_STALL_bm but the actual 'stall' command bit - } - - epData.endpoint[index].out.status &= ~USB_EP_STALL_bm; // just turn it off [for now] - - continue; - } - - if(pE) // && !(epData.endpoint[index].out.status & USB_EP_BUSNACK0_bm)) // AM receiving at the moment - { - // check for received data. If received, set up length and other info, and - // make sure it's at the end of the receive queue. THEN set up another buffer - // for it automatically, except for endpoint 0. 'buffer combining' might be good - // as well, if possible. - - if(epData.endpoint[index].out.status & USB_EP_UNF_bm) // TODO: allow me to read 'long packets' when this happens - { -#ifdef DEBUG_QUEUE - // first, handle "sent" transaction - error_printP_(F("check_recv_queue ")); - error_printL_(index); - error_printP(F(" - USB_EP_UNF toggle=")); - error_printL(epData.endpoint[index].out.status & USB_EP_TOGGLE_bm); - - // TODO: should I flip the toggle bit in this case??? Is it due to a DATA1/0 with toggle clear/set? -#endif // DEBUG_QUEUE - - epData.endpoint[index].out.status |= USB_EP_UNF_bm; - epData.endpoint[index].out.status &= ~USB_EP_UNF_bm; // just turn it off [for now] - if(index) - { - epData.endpoint[index].out.status ^= USB_EP_TOGGLE_bm; // does this work? - } - - // TODO: see if this ever happens - -// continue; // let this cycle around a bit more [I probably didn't read anything] - } - - if((epData.endpoint[index].out.status & USB_EP_TRNCOMPL0_bm) // note: 'SETUP' is TRNCOMPL1, as needed - || (/*!index &&*/ (epData.endpoint[index].out.status & USB_EP_SETUP_bm))) // TRNCOMPL1 for index != 0 - { - uint8_t bOldStatus = epData.endpoint[index].out.status; - - register Setup *pSetup = (Setup *)&(pE->aBuf[0]); - -// epData.endpoint[index].out.status = USB_EP_BUSNACK0_bm // mark 'do not receive' -// | (bOldStatus & ~(USB_EP_SETUP_bm | USB_EP_TRNCOMPL0_bm)); // turn these 2 bits off - - epData.endpoint[index].out.status |= USB_EP_BUSNACK0_bm; // mark 'do not receive' - -// if(index && -// (epData.endpoint[index].out.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) -// { -// epData.endpoint[index].out.ctrl |= _BV(2); // set the 'stall' flag for bulk in, basically -// } - -// if(bOldStatus & (USB_EP_UNF_bm | USB_EP_STALL_bm)) -// { -// epData.endpoint[index].out.status |= (USB_EP_UNF_bm | USB_EP_STALL_bm); // to clear them (?) -// epData.endpoint[index].out.status &= ~(USB_EP_UNF_bm | USB_EP_STALL_bm); // to clear them -// -// bOldStatus &= ~(USB_EP_UNF_bm | USB_EP_STALL_bm); // to clear them -// } - - if(!index || - (epData.endpoint[index].out.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { - // IF the out status has the toggle bit set, indicate it in 'wEndpointToggle' - // so that I correctly assign the TOGGLE bit when I reply - - // NOTE that the toggle bit SHOULD flip correctly with each complete transaction - - if(!(epData.endpoint[index].out.status & USB_EP_TOGGLE_bm)) // was 'toggle' ON or OFF for the last packet? - { - wEndpointToggle |= wProcessingMask; // do NOT use the 'toggle' bit when I get next packet or send a reply - } - else - { - wEndpointToggle &= ~wProcessingMask; // indicate that I need to use the 'toggle' bit when I get/send - } - } - -#ifdef TX_RX_LED_INIT - RxLEDPulse = TX_RX_LED_PULSE_MS; - RXLED1(); // LED pm - macro must be defined in variants 'pins_arduino.h' -#endif // TX_RX_LED_INIT - -#ifdef DEBUG_QUEUE - error_printP_(F("check_recv_queue ")); - error_printL_(index); - - if(bOldStatus & USB_EP_TRNCOMPL0_bm) - { - error_printP_(F(" USB_EP_TRNCOMPL0_bm ")); - } - else - { - error_printP_(F(" USB_EP_SETUP_bm ")); - } - - error_printL_(index); - error_printP_(F(": status=")); - error_printH_(bOldStatus); - error_printP_(F("H length=")); - error_printL_(epData.endpoint[index].out.cnt); - error_printP_(F(" address=")); - error_printH(epData.endpoint[index].out.dataptr); -#endif // DEBUG_QUEUE - - // ASSERT( epData.endpoint[index].out.dataptr == buffer_data_pointer(aRecvQ[index]) ); - - //(INTERNAL_BUFFER *)(void *)(epData.endpoint[index].out.dataptr); <-- wrong - - // TODO: verify pE is valid AND/OR a part of the chain - - pE->iIndex = 0; - pE->iLen = epData.endpoint[index].out.cnt; - - // 'HOST TO DEVICE' CONTROL PACKET WITH A DATA PAYLOAD - - if(!index && // to handle control packets that have data payloads... - !(epData.endpoint[0].out.status & USB_EP_TRNCOMPL0_bm) && - epData.endpoint[0].out.cnt >= sizeof(Setup) && - (pSetup->bmRequestType & REQUEST_DIRECTION) == REQUEST_HOSTTODEVICE && - pSetup->wLength > 0) // SETUP has a data payload! - { - error_printP_(F("CTRL packet, payload=")); - error_printL_(pSetup->wLength); - error_printP_(F(" toggle=")); - error_printL(epData.endpoint[0].out.status & USB_EP_TOGGLE_bm); - - pE = next_buffer(); // get a new buffer - - if(pE) - { - add_to_queue(&aRecvQ[0], pE); - - epData.endpoint[0].out.auxdata = 0; - epData.endpoint[0].out.dataptr = buffer_data_pointer(pE); // new pointer - epData.endpoint[0].out.cnt = 0; // immediate receive - - // with a packet payload, I need to receive a DATA 1 packet to complete the transaction - epData.endpoint[0].out.status = USB_EP_TOGGLE_bm; // allows me to read data (toggle bit set) - - continue; - } - - // note if pE is NULL, then I proceed forward with truncated packet anyway. - } - - - // THIS IS WHERE I DISPATCH THE INCOMING PACKET - - DispatchIncomingPacket(index, pE, bOldStatus & USB_EP_SETUP_bm ? 1 : 0); - - // check the send queue, see if there's anything waiting. chances are there ARE things waiting. - // if something is waiting, make sure it's sent before allowing more receive data - - if(!index && aSendQ[0]) // something is waiting to send on the control endpoint - { -#ifdef DEBUG_QUEUE - error_printP(F("check_recv_queue - waiting for send queue empty")); -#endif // DEBUG_QUEUE - - epData.endpoint[0].out.dataptr = 0; // no data will be received until I have empty send queue - epData.endpoint[0].out.cnt = 0; - } - else - { - set_up_EP_for_receive(index); // set up to receive (without checking/freeing buffers) - // NOTE: if there is no buffer, this will leave the endpoint in 'BUSNACK0' mode - } - } - } - else if(index || !aSendQ[0]) // remember, control endpoints don't receive until done sending - { -#ifdef DEBUG_QUEUE - error_printP_(F("check_recv_queue - set up EP ")); - error_printL_(index); - error_printP(F(" for receive")); -#endif // DEBUG_QUEUE - - set_up_EP_for_receive(index); // set up to receive - } - } - - SREG = oldSREG; -} - -static void check_send_queue(void) -{ -int index; -INTERNAL_BUFFER *pX; -uint8_t oldSREG; - - - oldSREG = SREG; - cli(); // this must be done with interrupts blocked - - for(index=0; index <= MAXEP; index++) - { - uint16_t wProcessingMask = 1 << index; - - // skip those not enabled - if((epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) == USB_EP_TYPE_DISABLE_gc) - { - continue; - } - - if(wMultipacketOutFlag & wProcessingMask) // I'm currently using 'IN' to receive for this endpoint - { - continue; // skip it - it should be left alone - } - - pX = inverse_buffer_data_pointer(epData.endpoint[index].in.dataptr); - uint8_t status = epData.endpoint[index].in.status; - - // check for errors before anything else - - if((status & USB_EP_STALL_bm) || // stall - (status & USB_EP_UNF_bm)) // underflow - { -#ifdef DEBUG_QUEUE - // first, handle "sent" transaction - error_printP_(F("check_send_queue ")); - error_printL_(index); - error_printP_(F(" - ")); - - if(status & USB_EP_STALL_bm) // stall - error_printP_(F(" USB_EP_STALL")); - - if(status & USB_EP_UNF_bm) // underflow - error_printP_(F(" USB_EP_UNF")); - - error_printP(F("!!!")); -#endif // DEBUG_QUEUE - - epData.endpoint[index].in.status |= (USB_EP_STALL_bm | USB_EP_UNF_bm); // do I set them like this? - - if((status & USB_EP_STALL_bm) && - (epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { - error_printP_(F("check_send_queue ")); - error_printL_(index); - error_printP(F(" STALL")); - - epData.endpoint[index].in.ctrl |= _BV(2); // to clear the bits - epData.endpoint[index].in.ctrl &= ~_BV(2); // note that this is NOT USB_EP_STALL_bm but the actual 'stall' command bit - } - - // TODO: should a stall cause TOGGLE to flip? for now, NO - - epData.endpoint[index].in.status &= ~(USB_EP_STALL_bm | USB_EP_UNF_bm); // for now do this - } - - if(pX && - !(epData.endpoint[index].in.status & USB_EP_TRNCOMPL0_bm)) - { - // TODO: check for stale buffer??? - if(epData.endpoint[index].in.status & USB_EP_BUSNACK0_bm) - { - if(index) - { - error_printP_(F("NACK ep=")); - error_printL(index); - } - - epData.endpoint[index].in.status &= ~USB_EP_BUSNACK0_bm; // clear this bit so I'll send - } - - continue; // nothing else needed, I hope - } - - if(pX && - (epData.endpoint[index].in.status & USB_EP_TRNCOMPL0_bm)) // note: 'SETUP' is TRNCOMPL1, if needed - { - uint8_t bOldStatus = epData.endpoint[index].in.status; - - if(index && - (epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { - // IF the out status has the toggle bit set, indicate it in 'wEndpointToggle' - // so that I correctly assign the TOGGLE bit when I send the next packet - - // NOTE that the toggle bit SHOULD flip correctly with each complete transaction - - if(!(epData.endpoint[index].in.status & USB_EP_TOGGLE_bm)) // was 'toggle' ON or OFF for the last packet? - { - wEndpointToggle |= wProcessingMask; // do NOT use the 'toggle' bit when I get next packet or send a reply - } - else - { - wEndpointToggle &= ~wProcessingMask; // indicate that I need to use the 'toggle' bit when I get/send - } - } - - epData.endpoint[index].in.status = USB_EP_BUSNACK0_bm // mark 'do not send' - | (bOldStatus & ~(USB_EP_TRNCOMPL0_bm | USB_EP_SETUP_bm)); // clear these 2 bits - -#ifdef DEBUG_QUEUE - error_printP_(F("check_send_queue ")); - error_printL_(index); - error_printP_(F(" - USB_EP_TRNCOMPL0 ")); - error_printL_(index); - error_printP_(F(": status=")); - error_printH_(bOldStatus); - error_printP_(F(" length=")); - error_printL_(epData.endpoint[index].in.cnt); - error_printP_(F(" address=")); - error_printH(epData.endpoint[index].in.dataptr); -#endif // DEBUG_QUEUE - - // if I need to assign the USB address, do it HERE, after packet send completes - // the process of changing the address after getting the command to do so requires - // that I send a zero-length packet. I'm assuming (here) that 'any packet will do' - // and just handling it after send completes on whatever packet is sent following - // the request. If this fails I'll get another 'bus reset' and it will start again - // and so it's no big deal if it doesn't work... - - if(!index && bUSBAddress) // control endpoint needs to change the USB address? - { -#ifdef DEBUG_QUEUE - error_printP_(F("USB address changed to ")); - error_printL(bUSBAddress); -#endif // DEBUG_QUEUE - - USB_ADDR = bUSBAddress; - bUSBAddress = 0; // so I don't try to change it again and again - } - - // once a buffer has been SENT, I can remove it from the send queue as 'completed'. - - if(pX->iLen >= 64 && !pX->pNext) // last buffer and 'full size', need to send 0-length packet - { - epData.endpoint[index].in.cnt = 0; - epData.endpoint[index].in.dataptr = buffer_data_pointer(pX); // do anyway, should already be 'this' - - if((!index || (epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - && !(wEndpointToggle & wProcessingMask)) // toggle is ON for this endpoint - { - // DATA1 packet - -#ifdef DEBUG_QUEUE - if(index) - { - error_printP_(F("Endpoint ")); - error_printL_(index); - error_printP(F(" using TOGGLE")); - } -#endif // DEBUG_QUEUE - - epData.endpoint[index].in.status = USB_EP_TOGGLE_bm; // set JUST the 'toggle' bit to send - wEndpointToggle |= wProcessingMask; // turn it off next time (it alternates for bulk xfer, yeah) - } - else - { - // DATA0 packet - toggle is always OFF for this endpoint - - epData.endpoint[index].in.status = 0; // send without toggle bit (ISOCHRONOUS always does this) - - if(!index || (epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { -#ifdef DEBUG_QUEUE - if(index) - { - error_printP_(F("Endpoint ")); - error_printL_(index); - error_printP(F(" using !TOGGLE")); - } -#endif // DEBUG_QUEUE - - wEndpointToggle &= ~wProcessingMask; // turn it on next time (it alternates for bulk xfer, yeah) - } - } - - // NOTE: leave pX not NULL; next section will skip, and we're ready to go - } - else - { - remove_from_queue_and_free(&(aSendQ[index]), pX); - pX = NULL; // also a flag to add new buffer in next section - } - } - - if(!pX) // not in process of sending - { - pX = aSendQ[index]; // new buffer (TODO: walk entire chain looking for 'ready to send' packets?) - - if(pX && INTERNAL_BUFFER_SEND_READY(pX)) // only send if ready to send - { -#ifdef DEBUG_QUEUE - error_printP_(F("check_send_queue ")); - error_printL_(index); - error_printP_(F(" NEXT buffer: ")); - error_printH_((unsigned long)pX); - error_printP_(F(" address=")); - error_printH_(buffer_data_pointer(pX)); - error_printP_(F(" length=")); - error_printL(pX->iLen); -#endif // DEBUG_QUEUE - - epData.endpoint[index].in.cnt = pX->iLen; - epData.endpoint[index].in.dataptr = buffer_data_pointer(pX); - - if(!index || (epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc) - { - if(!(wEndpointToggle & wProcessingMask)) - { - if(index) - { -#ifdef DEBUG_QUEUE - error_printP_(F("Endpoint ")); - error_printL_(index); - error_printP(F(" using TOGGLE")); -#endif // DEBUG_QUEUE - } - - epData.endpoint[index].in.status = USB_EP_TOGGLE_bm; // send with toggle bit - wEndpointToggle |= wProcessingMask; // turn it off next time (it alternates for bulk xfer, yeah) - } - else - { - if(index) - { -#ifdef DEBUG_QUEUE - error_printP_(F("Endpoint ")); - error_printL_(index); - error_printP(F(" using !TOGGLE")); -#endif // DEBUG_QUEUE - } - - epData.endpoint[index].in.status = 0; // send without toggle bit - wEndpointToggle &= ~wProcessingMask; // turn it on next time (it alternates for bulk xfer, yeah) - } - } - else - { - epData.endpoint[index].in.status = 0; // send without toggle bit (ISOCHRONOUS always does this) - } - } - else - { - // OK I'm officially "not sending" now, and so I must reset the DATA thingy - - epData.endpoint[index].in.status |= USB_EP_BUSNACK0_bm; // mark 'do not send' (make sure) but leave TOGGLE alone - - epData.endpoint[index].in.cnt = 0; - epData.endpoint[index].in.dataptr = 0; - } - } - } - - SREG = oldSREG; -} - -static void internal_flush(int index) // send all pending data in send queue -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; - - - oldSREG = SREG; - cli(); // disable interrupts - - pB = aSendQ[index]; - - while(pB) - { - if(!INTERNAL_BUFFER_SEND_READY(pB)) - { - INTERNAL_BUFFER_MARK_SEND_READY(pB); - } - - pB = pB->pNext; - } - - SREG = oldSREG; -} - -// queue up "zero length" send data -static bool internal_send0(int index) -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; - - -#ifdef DEBUG_QUEUE - error_printP_(F("internal_send0 ")); - error_printL(index); -#endif // DEBUG_QUEUE - -#ifdef TX_RX_LED_INIT - TxLEDPulse = TX_RX_LED_PULSE_MS; - TXLED1(); // LED pm - macro must be defined in variants 'pins_arduino.h' -#endif // TX_RX_LED_INIT - - - oldSREG = SREG; - cli(); // disable interrupts - - pB = end_of_chain(aSendQ[index]); - - if(pB && !INTERNAL_BUFFER_SEND_READY(pB)) // see if I need to mark the previous buffer as 'ready to send' - { - INTERNAL_BUFFER_MARK_SEND_READY(pB); // mark 'ready to send' so that it goes out - } - - pB = next_buffer(); // always - - if(pB) - { - pB->iIndex = pB->iLen = 0; // zero-length - - INTERNAL_BUFFER_MARK_SEND_READY(pB); // mark 'ready to send' so that it goes out - add_to_queue(&(aSendQ[index]), pB); - - check_send_queue(); - } - - SREG = oldSREG; - - return pB != NULL; // indicate success/fail -} - -// queue up send data -static bool internal_send(int index, const void *pData, uint16_t cbData, uint8_t bSendNow) -{ -INTERNAL_BUFFER *pB; -const uint8_t *pD = (const uint8_t *)pData; -uint8_t oldSREG; - - - if(!cbData) - { - if(bSendNow) - { -#ifdef DEBUG_QUEUE - error_printP_(F("internal_send ")); - error_printL_(index); - error_printP(F(" - calling internal_send0")); -#endif // DEBUG_QUEUE - - return internal_send0(index); // send a ZLP - } - else - { - error_printP_(F("internal_send - zero bytes, no effect")); - } - - return true; // indicate 'ok' anyway - } - - if(!pData) - { - error_printP_(F("internal_send ")); - error_printL_(index); - error_printP(F(" - NULL pointer")); - - return false; - } - -#ifdef DEBUG_QUEUE - error_printP_(F("internal_send USB addr=")); - error_printL_(USB_ADDR); - error_printP_(F(" EP=")); - error_printL_(index); - error_printP_(F(" len=")); - error_printL_(cbData); - error_printP(F(" bytes")); -#endif // DEBUG_QUEUE - -#ifdef TX_RX_LED_INIT - TxLEDPulse = TX_RX_LED_PULSE_MS; - TXLED1(); // LED pm - macro must be defined in variants 'pins_arduino.h' -#endif // TX_RX_LED_INIT - - - oldSREG = SREG; - cli(); // disable interrupts - - pB = end_of_chain(aSendQ[index]); - - if(!pB || INTERNAL_BUFFER_SEND_READY(pB)) // see if I need to allocate a new buffer - { - pB = next_buffer(); - pB->iIndex = pB->iLen = 0; // make sure - } - - while(pB) - { - register uint8_t cb, cbSize; - - if(pB->iIndex < sizeof(pB->aBuf)) - { - cbSize = sizeof(pB->aBuf) - pB->iIndex; - } - else - { - pB->iIndex = sizeof(pB->aBuf); // fix it, in case of corruption - cbSize = 0; - } - - if(cbData > cbSize) - { - cb = cbSize; - } - else - { - cb = cbData; - } - - if(cb) // just in case, should never be zero here - { - memcpy(&(pB->aBuf[pB->iIndex]), pD, cb); - } - - pB->iIndex += cb; // new position within the buffer - pB->iLen = pB->iIndex; // assign these to the same value ('send ready' will use it) - - pD += cb; - cbData -= cb; - - if(bSendNow || pB->iLen >= sizeof(pB->aBuf)) // note that 'aBufList' size MUST match max packet size for EP - { - INTERNAL_BUFFER_MARK_SEND_READY(pB); // mark 'ready to send' so that it goes out - } - - if(not_in_queue(&(aSendQ[index]), pB)) - { - add_to_queue(&(aSendQ[index]), pB); - } - - if(!cbData) // this ends the loop. - { - if(bSendNow) - { - check_send_queue(); // to force a write - } - - SREG = oldSREG; - return true; // done! - } - - pB = next_buffer(); - } - - // if I get here, pB is NULL - - SREG = oldSREG; - -//#ifdef DEBUG_QUEUE - error_printP_(F("internal_send ")); - error_printL_(index); - error_printP(F(" - NULL buffer")); -//#endif // DEBUG_QUEUE - - return false; // if I get here, something failed -} - -// byte-level receive -static int internal_receive(int index, void *pData, uint16_t nMax) -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; -int iRval = 0; -uint8_t *pD = (uint8_t *)pData; - - -#ifdef DEBUG_QUEUE - error_printP_(F("internal_receive ")); - error_printL(index); -#endif // DEBUG_QUEUE - - check_recv_queue(); - - // this manipulates buffers, so stop ints temporarily - - oldSREG = SREG; - cli(); // disable interrupts - - pB = aRecvQ[index]; // first buffer - - while(pB && nMax && pB->iLen > 0)//INTERNAL_BUFFER_RECV_READY(pB)) - { - uint8_t cb = pB->iLen - pB->iIndex; - - if(cb > 0) - { - if(cb > nMax) - { - cb = nMax; - } - - if(pData) - { - memcpy(pD, &(pB->aBuf[pB->iIndex]), cb); - } - - nMax -= cb; - pD += cb; - pB->iIndex += cb; - - iRval += cb; - } - - if(pB->iIndex >= pB->iLen) - { - // get next packet - aRecvQ[index] = pB->pNext; // it's always the head of the queue - pB->pNext = NULL; - free_buffer(pB); - - if(!index) // for control, don't exceed packet boundary - { - break; - } - - pB = aRecvQ[index]; - } - } - - SREG = oldSREG; - return iRval; -} - - -////////////////////////////////////////////////////////////////////////////// -// // -// _____ _ _ _ // -// | ____| _ __ __| | _ __ ___ (_) _ __ | |_ ___ // -// | _| | '_ \ / _` || '_ \ / _ \ | || '_ \ | __|/ __| // -// | |___ | | | || (_| || |_) || (_) || || | | || |_ \__ \ // -// |_____||_| |_| \__,_|| .__/ \___/ |_||_| |_| \__||___/ // -// |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -#ifndef DEBUG_CODE -static uint16_t endpoint_data_pointer(void) __attribute__((noinline)); -#endif // DEBUG_CODE -static void InitializeSingleEndpoint(XMegaEndpointChannel *pEP) __attribute__((noinline)); - -uint16_t endpoint_data_pointer(void) -{ - return (uint16_t)(uint8_t *)&(epData.endpoint[0]); // set 'EP Data' pointer to THIS address -} - - -static void InitializeSingleEndpoint(XMegaEndpointChannel *pEP) -{ - // if the endpoint is in the middle of something, this will 'cancel' it - // NOTE: 'BUSNACK0' is needed by 'in' on 128A1U rev K or earlier [a bug, apparently] - leave it on - pEP->out.status |= USB_EP_BUSNACK0_bm; - pEP->in.status |= USB_EP_BUSNACK0_bm; - - pEP->out.ctrl = USB_EP_TYPE_DISABLE_gc; // to disable it (endpoint 'type 0' disables) - pEP->in.ctrl = USB_EP_TYPE_DISABLE_gc; // initially (disable) - - pEP->in.cnt = 0; - pEP->in.dataptr = 0; - pEP->in.auxdata = 0; - - pEP->out.cnt = 0; - pEP->out.dataptr = 0; - pEP->out.auxdata = 0; - - pEP->out.status = USB_EP_BUSNACK0_bm; // make sure - pEP->in.status = USB_EP_BUSNACK0_bm; -} - - -void InitEP(u8 index, u8 type, u8 size) -{ -uint8_t oldSREG; -int i1; - - - if(index > MAXEP || index >= INTERNAL_NUM_EP) // MAXEP or INTERNAL_NUM_EP will be the highest index (MAXEP is inclusive) - { - return; - } - - // IMPORTANT: the definition of 'in' and 'out' are from the perspective of the USB HOST - // Since I'm on 'the other end', 'in' writes data, 'out' receives it - - oldSREG = SREG; - cli(); // disable interrupts - - // clear the appropriate bit in all of the global state vars - uint16_t wProcessingMask = 1 << index; - - wProcessingFlag &= ~wProcessingMask; - wMultipacketOutFlag &= ~wProcessingMask; - wEndpointToggle &= ~wProcessingMask; - - - // NOTE: this code is based on my research into the documentation (inadequate) and the ATMel Studio - // sample project (somewhat difficult to follow) after spending a couple of weeks or so frustratingly - // attempting to use ONLY the information found in the 'AU' manual, which SHOULD be enough (but was not). - // In particular the behavior CAUSED by the 'NACK0' flag, and the requirement to set it on 'in' endpoints - // upon initialization for 128A1U rev K or earlier was NOT obvious, nor even mentioned as far as I know. - - XMegaEndpointChannel *pEP = &(epData.endpoint[index]); - - error_printP_(F("USB InitEP ")); - error_printL(index); - - InitializeSingleEndpoint(pEP); - - free_queue(&(aSendQ[index])); - free_queue(&(aRecvQ[index])); - - if(index == 0 && type == EP_TYPE_CONTROL) // control (these can receive SETUP requests) - { - // aBuf1 is output, aBuf2 is input - - aRecvQ[0] = next_buffer(); // allocate buffer - - epData.endpoint[0].out.dataptr = buffer_data_pointer(aRecvQ[index]); - - // NOTE: size will be sent as 'EP_SINGLE_64' - - epData.endpoint[0].out.ctrl = USB_EP_TYPE_CONTROL_gc // NOTE: interrupt enabled - | USB_EP_SIZE_64_gc;//(size == EP_SINGLE_64 ? USB_EP_SIZE_64_gc : 0); /* data size */ - - // NOTE: 'BUSNACK0' is needed by 'in' on 128A1U rev K or earlier [a bug, apparently, see errata] - epData.endpoint[0].out.status = 0; // make sure they're ready to go (this allows receive data) - - // cancel 'in' queue - epData.endpoint[0].in.status = USB_EP_BUSNACK0_bm; // leave 'BUSNACK0' bit ON (stalls sending data) - epData.endpoint[0].in.dataptr = 0; - epData.endpoint[0].in.cnt = 0; - - epData.endpoint[0].in.ctrl = USB_EP_TYPE_CONTROL_gc // NOTE: interrupt enabled - | USB_EP_SIZE_64_gc; /* data size */ - - // zero out the rest of the endopints, leaving ONLY the control - for(i1=1; i1 <= MAXEP; i1++) - { - pEP = &(epData.endpoint[i1]); - - InitializeSingleEndpoint(pEP); - - if(i1 < INTERNAL_NUM_EP) - { - free_queue(&(aSendQ[i1])); - free_queue(&(aRecvQ[i1])); - } - } - - // after initializing all endpoints, zero out all of the global state flags for all endpoints - wProcessingFlag = 0; - wMultipacketOutFlag = 0; - wEndpointToggle = 0; - } - else if(type == EP_TYPE_INTERRUPT_IN || type == EP_TYPE_BULK_IN - || type == EP_TYPE_ISOCHRONOUS_IN) /* these types have *ME* write data and send to 'in' for host */ - { - // 'in' is actually the WRITE/SEND function - - pEP->in.status = USB_EP_BUSNACK0_bm; // leave 'BUSNACK0' bit ON (stalls sending data) - pEP->in.dataptr = 0; - pEP->in.auxdata = 0; - - pEP->in.cnt = 0; // no data (so I won't send) - note 'ZLP_BIT' is broken (don't bother) - - pEP->in.ctrl = (type == EP_TYPE_ISOCHRONOUS_IN ? USB_EP_TYPE_ISOCHRONOUS_gc : USB_EP_TYPE_BULK_gc) -// | (type == EP_TYPE_BULK_IN ? USB_EP_INTDSBL_bm : 0) /* disable interrupt */ - | (size == EP_DOUBLE_64 ? USB_EP_SIZE_64_gc : // TODO: set 'double buffer' flag? - size == EP_SINGLE_64 ? USB_EP_SIZE_64_gc : 0); /* data size */ - - if(type != EP_TYPE_ISOCHRONOUS_IN) - { - error_printP(F(" setting TOGGLE bit to '1'")); - wEndpointToggle |= wProcessingMask; // (1 << index); // set bit so next time I don't use TOGGLE - } - } - else if(type == EP_TYPE_INTERRUPT_OUT || type == EP_TYPE_BULK_OUT /* these send *ME* data */ - || type == EP_TYPE_ISOCHRONOUS_OUT) - { - // 'out' is actually the RECEIVE function - - pEP->out.status = USB_EP_BUSNACK0_bm; // disable receive at first - - aRecvQ[index] = next_buffer(); // allocate buffer - pEP->out.dataptr = buffer_data_pointer(aRecvQ[index]); - - pEP->out.auxdata = 0; - - pEP->out.cnt = 0; // no data (so I can receive) - - pEP->out.ctrl = (type == EP_TYPE_ISOCHRONOUS_OUT ? USB_EP_TYPE_ISOCHRONOUS_gc : USB_EP_TYPE_BULK_gc) -// | (type == EP_TYPE_BULK_OUT ? USB_EP_INTDSBL_bm : 0) /* disable interrupt */ - | (size == EP_DOUBLE_64 ? USB_EP_SIZE_64_gc : // TODO: set 'double buffer' flag? - size == EP_SINGLE_64 ? USB_EP_SIZE_64_gc : 0); /* data size */ - - pEP->out.status = 0; // this allows receive data - - if(type != EP_TYPE_ISOCHRONOUS_OUT) - { - error_printP(F(" setting TOGGLE bit to '1'")); - wEndpointToggle |= wProcessingMask; // (1 << index); // set bit so next time I don't use TOGGLE - } - } - // TODO: 'INOUT' types? - else - { - // endpoint 'disabled' now - } - - SREG = oldSREG; // restore interrupts (etc.) - - // TODO: anything else? -} - -// this function consolidates queued packets - useful for receiving bulk data -void consolidate_packets(INTERNAL_BUFFER *pHead) -{ -INTERNAL_BUFFER *pX, *pX2; - - // assume I can consolidate everything into the least number of packets - - if(!pHead) - { - return; - } - - while(pHead->pNext) - { - while(pHead->pNext && pHead->iLen >= sizeof(pHead->aBuf)) - { - pHead = pHead->pNext; // find next non-full buffer - } - - pX = pHead->pNext; - - if(!pX) // first 'incomplete' buffer found - anything else? - { - return; // I am done - } - - error_printP_(F("Consolidating ")); - error_printL(pX->iLen); - error_printP_(F(" left=")); - error_printL(sizeof(pHead->aBuf) - pHead->iLen); - - do - { - uint8_t nLeft = sizeof(pHead->aBuf) - pHead->iLen; - - if(nLeft >= pX->iLen) - { - memcpy(&(pHead->aBuf[pHead->iLen]), pX->aBuf, pX->iLen); - pHead->iLen += pX->iLen; - - pX2 = pX; - pX = pX->pNext; - - remove_from_queue(&pHead, pX2); - free_buffer(pX2); - - if(!pX) - { - return; // I am done - } - } - else - { - memcpy(&(pHead->aBuf[pHead->iLen]), pX->aBuf, nLeft); - pHead->iLen += nLeft; - - pX->iLen -= nLeft; - memmove(&(pX->aBuf[0]), &(pX->aBuf[nLeft]), pX->iLen); - } - - } while(pHead->iLen < sizeof(pHead->aBuf)); - - error_printP_(F("new head length ")); - error_printL(pHead->iLen); - - // get the next head, search for unconsolidated bufs (again) - // slightly less efficient, but simpler algorithm - - pHead = pHead->pNext; - } -} - -uint8_t USB_GetEPType(uint8_t nEP) -{ -uint8_t nRval = 0xff; - - if(nEP < INTERNAL_NUM_EP) - { - nRval = pgm_read_byte(&(_initEndpoints[nEP])); - } - - return nRval; -} - -void internal_do_control_request(INTERNAL_BUFFER *pBuf, bool bIsSetup) -{ -INTERNAL_BUFFER *pX; -uint8_t requestType; - - - if(pBuf && (pBuf->iLen - pBuf->iIndex) >= 8) // control packets only send one of these - { - Setup *pSetup = (Setup *)&(pBuf->aBuf[pBuf->iIndex]); // must point DIRECTLY to packet buffer - uint8_t ok = 0; - - pBuf->iIndex += sizeof(Setup); // add the # of bytes I have read thus far - -#ifdef DEBUG_CONTROL - error_printP_(F("USB setup/control request=")); - error_printL_(pSetup->bRequest); - error_printP_(F(" type=")); - error_printL_(pSetup->bmRequestType); - error_printP_(F(" value=")); - error_printL_(pSetup->wValueH); - error_printP_(F(":")); - error_printL_(pSetup->wValueL); - error_printP_(F(" index=")); - error_printL_(pSetup->wIndex); - error_printP_(F(" length=")); - error_printL(pSetup->wLength); -#endif // DEBUG_CONTROL - - requestType = pSetup->bmRequestType; - - if((requestType & REQUEST_DIRECTION) == REQUEST_DEVICETOHOST) // i.e. an 'in' - { -#ifdef DEBUG_CONTROL - error_printP(F("dev to host request")); -#endif // DEBUG_CONTROL - - // TODO: will there be multiple requests in the buffer? - } - else // HOST TO DEVICE - an 'out' - will be sending ZLP on success - { -#ifdef DEBUG_CONTROL - error_printP(F("host to dev")); // - eat remainder of packet")); -#endif // DEBUG_CONTROL - -// pBuf->iIndex = pBuf->iLen; // this eats the remainder of the packet - } - - if(REQUEST_STANDARD == (requestType & REQUEST_TYPE)) - { - // Standard Requests - uint8_t r; - -#ifdef DEBUG_CONTROL - error_printP_(F("standard request ")); - error_printL(pSetup->bRequest); -#endif // DEBUG_CONTROL - - r = pSetup->bRequest; - - if (GET_STATUS == r) // 0 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: get status")); -#endif // DEBUG_CONTROL - - // send a 2-byte packet with 2 zero bytes in it - pX = next_buffer(); - - if(pX) - { - pX->iLen = pX->iIndex = 2; - pX->aBuf[0] = 0; - pX->aBuf[1] = 0; - - INTERNAL_BUFFER_MARK_SEND_READY(pX); - - add_to_queue(&aSendQ[0], pX); - check_send_queue(); // transmit available packets - } - } - else if (CLEAR_FEATURE == r) // 1 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: clear feature")); -#endif // DEBUG_CONTROL - - ok = true; // temporary - } - else if (SET_FEATURE == r) // 3 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: set feature")); -#endif // DEBUG_CONTROL - - ok = true; // temporary - } - else if (SET_ADDRESS == r) // 5 - { -#ifdef DEBUG_CONTROL - error_printP_(F("CONTROL: set address =")); - error_printL(pSetup->wValueL & 0x7f); -#endif // DEBUG_CONTROL - - bUSBAddress = pSetup->wValueL & 0x7f; // this will asynchronously set the address - - ok = true; - } - else if (GET_DESCRIPTOR == r) // 6 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: get descriptor")); -#endif // DEBUG_CONTROL - - ok = SendDescriptor(*pSetup); // TODO POOBAH FIX THIS - } - else if (SET_DESCRIPTOR == r) // 7 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: set descriptor")); -#endif // DEBUG_CONTROL - - ok = false; - } - else if (GET_CONFIGURATION == r) // 8 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: get config")); -#endif // DEBUG_CONTROL - - // send a 1-byte packet with a 1 byte in it - pX = next_buffer(); - - if(pX) - { - pX->iLen = pX->iIndex = 1; - pX->aBuf[0] = 1; // always config #1??? TODO: see if I should return _usbConfiguration - - INTERNAL_BUFFER_MARK_SEND_READY(pX); - - add_to_queue(&aSendQ[0], pX); - - internal_flush(0); - check_send_queue(); // transmit available packets - } - - ok = true; - } - else if (SET_CONFIGURATION == r) // 9 - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: set config")); -#endif // DEBUG_CONTROL - - if(REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT)) - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: request device")); -#endif // DEBUG_CONTROL - - // SEE SECTION 20.3 in 'AU' manual for sequence of operation - -#ifdef DEBUG_CONTROL - error_printP(F("USB InitEndpoints")); // was 'InitEndpoints()' -#endif // DEBUG_CONTROL - - // init the first one as a control input - for (uint8_t i = 1; i < sizeof(_initEndpoints); i++) - { - InitEP(i, pgm_read_byte(_initEndpoints+i), EP_SINGLE_64); - // EP_DOUBLE_64); // NOTE: EP_DOUBLE_64 allocates a 'double bank' of 64 bytes, with 64 byte max length - } - - _usbConfiguration = pSetup->wValueL; - - ok = true; - } - else - { -#ifdef DEBUG_CONTROL - error_printP(F("CONTROL: other 'set config' request =")); - error_printL(requestType); -#endif // DEBUG_CONTROL - - ok = false; - } - } - else if (GET_INTERFACE == r) // 10 - { -#ifdef DEBUG_CONTROL - error_printP(F("get interface request - temporarily returns NOTHING")); -#endif // DEBUG_CONTROL - - ok = true; // TEMPORARY - } - else if (SET_INTERFACE == r) // 11 - { -#ifdef DEBUG_CONTROL - error_printP(F("set interface request - temporarily does NOTHING")); -#endif // DEBUG_CONTROL - - ok = true; // TEMPORARY - } - else - { - error_printP_(F("CONTROL: unknown request ")); - error_printL_(pSetup->bRequest); - error_printP_(F(", index=")); - error_printL(pSetup->wIndex); - - ok = false; // returns an error, sends ZLP for things that expect data - } - } - else - { -#ifdef DEBUG_CONTROL - error_printP_(F("INTERFACE REQUEST ")); - - if((requestType & REQUEST_TYPE) == REQUEST_CLASS) - { - error_printP_(F("(CLASS)")); - } - else if((requestType & REQUEST_TYPE) == REQUEST_VENDOR) - { - error_printP_(F("(VENDOR)")); - } - else // probably impossible - { - error_printP_(F("type=")); - error_printH_(requestType & REQUEST_TYPE); - } - - error_printP_(F(" request=")); - error_printL_(pSetup->bRequest); - error_printP_(F(" index=")); - error_printL_(pSetup->wIndex); - error_printP_(F(" len=")); - error_printL_(pSetup->wLength); -#endif // DEBUG_CONTROL - - uint8_t idx = pSetup->wIndex; - -#ifdef CDC_ENABLED - if(CDC_ACM_INTERFACE == idx) - { -#ifdef DEBUG_CONTROL - error_printP(F(" (CDC)")); -#endif // DEBUG_CONTROL - - ok = CDC_Setup(*pSetup); // sends 7 control bytes - } -#ifdef HID_ENABLED - else -#endif // HID_ENABLED -#endif // CDC_ENABLED -#ifdef HID_ENABLED - if(HID_INTERFACE == idx) - { -#ifdef DEBUG_CONTROL - error_printP(F(" (HID)")); -#endif // DEBUG_CONTROL - - ok = HID_Setup(*pSetup); - } -#endif // HID_ENABLED -#if defined(CDC_ENABLED) || defined(HID_ENABLED) - else -#endif // defined(CDC_ENABLED) || defined(HID_ENABLED) - { -#ifdef DEBUG_CONTROL - error_printP_(F(" (unknown dev index ")); - error_printL_(idx); - error_printP(F(")")); -#endif // DEBUG_CONTROL - - ok = ClassInterfaceRequest(*pSetup); - } - - internal_flush(0); - check_send_queue(); // send whatever's ready to go - } - - if(ok || (requestType & REQUEST_DIRECTION) != REQUEST_DEVICETOHOST) - { - if(!ok || (requestType & REQUEST_DIRECTION) == REQUEST_HOSTTODEVICE) // i.e. an 'out' or unresponsive 'in' - { -#ifdef DEBUG_CONTROL - if(!ok) // device to host request expects return value so give it one - { - error_printP(F("sending ZLP for DEVICE TO HOST")); - } - else - { - error_printP(F("sending ZLP for HOST TO DEVICE")); - } -#endif // DEBUG_CONTROL - - internal_send0(0); // send a zero-length packet [this acknowledges what I got] - } - else - { - // if I get 'ok' it should have already sent a packet for an 'in' (device to host) - // NOTE: everything else will send a regular packet with data in it - } - - internal_flush(0); // this is actually an asynchronous flush operation - mark 'send it' basically - check_send_queue(); - } - } -} - - - -//////////////////////////////////////////////////////////////////////////////////// -// // -// _ _ _ _ _ _ _ ____ ___ // -// | | | |(_) __ _ | |__ | | ___ __ __ ___ | | / \ | _ \|_ _| // -// | |_| || | / _` || '_ \ _____ | | / _ \\ \ / // _ \| | / _ \ | |_) || | // -// | _ || || (_| || | | ||_____|| || __/ \ V /| __/| | / ___ \ | __/ | | // -// |_| |_||_| \__, ||_| |_| |_| \___| \_/ \___||_| /_/ \_\|_| |___| // -// |___/ // -// // -//////////////////////////////////////////////////////////////////////////////////// - -// "high level" API - manipulates buffers (async only) - no blocking -int USB_SendControlP(uint8_t flags, const void * PROGMEM_ORIG d, int len) -{ - if(!len) // TODO: ZLP? - { - if(internal_send0(0)) - { - return 0x8000; - } - else - { - return 0; // error - } - } - - uint8_t *p1 = (uint8_t *)malloc(len); - - if(!p1) - { - return 0; - } - - memcpy_P(p1, d, len); - - len = internal_send(0, p1, len, 1); // auto-flush packet - - free(p1); - - return len; // return the length that I send or 0 on error -} - -int USB_SendControl(uint8_t flags, const void* d, int len) -{ - if(flags & TRANSFER_PGM) // PROGMEM memory - { - return USB_SendControlP(flags, d, len); - } - - // TODO: TRANSFER_RELEASE, TRANSFER_ZERO <-- what do these do? - - if(!len) // TODO: ZLP? - { - if(internal_send0(0)) // ZLP - { - return 0x8000; - } - else - { - return 0; // error - } - } - - return internal_send(0, d, len, 1); // auto-flush packet -} - - -uint16_t USB_Available(uint8_t ep) -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; -uint16_t iRval = 0; - - // this manipulates buffers, so stop ints temporarily - - oldSREG = SREG; - cli(); // disable interrupts - - pB = aRecvQ[ep]; - - while(pB) - { - if(INTERNAL_BUFFER_RECV_READY(pB)) - { - if(pB->iIndex < pB->iLen) - { - iRval += pB->iLen - pB->iIndex; - } - } - - pB = pB->pNext; - } - - SREG = oldSREG; - - return iRval; -} - - -bool USB_IsStalled(uint8_t index) -{ -bool bRval = false; -uint8_t oldSREG; - - - oldSREG = SREG; - cli(); // disable interrupts - - // checking this requires knowledge of the endpoint type - - if((epData.endpoint[index].out.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_DISABLE_gc) - { - if(epData.endpoint[index].out.status & (USB_EP_UNF_bm | USB_EP_STALL_bm)) - { - bRval = true; - goto the_end; - } - - if((epData.endpoint[index].out.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_ISOCHRONOUS_gc - && (epData.endpoint[index].out.ctrl & _BV(2))) // stall bit ON in control reg - { - bRval = true; - goto the_end; - } - } - - if((epData.endpoint[index].in.ctrl & USB_EP_TYPE_gm) != USB_EP_TYPE_DISABLE_gc) - { - if(epData.endpoint[index].in.status & (USB_EP_UNF_bm | USB_EP_STALL_bm)) - { - bRval = true; - goto the_end; - } - } - -the_end: - - SREG = oldSREG; - - return bRval; -} - - -bool USB_IsSendQFull(uint8_t ep) -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; -uint8_t nBuf = 0; - - // this manipulates buffers, so stop ints temporarily - - oldSREG = SREG; - cli(); // disable interrupts - - pB = aSendQ[ep]; - - while(pB) - { - if(INTERNAL_BUFFER_SEND_READY(pB) || - INTERNAL_BUFFER_SENDING(pB)) - { - nBuf++; - if(nBuf > 2) - { - SREG = oldSREG; - - return true; - } - } - - pB = pB->pNext; - } - - SREG = oldSREG; - - return false; -} - - -uint16_t USB_SendQLength(uint8_t ep) -{ -INTERNAL_BUFFER *pB; -uint8_t oldSREG; -uint16_t iRval = 0; - - // this manipulates buffers, so stop ints temporarily - - oldSREG = SREG; - cli(); // disable interrupts - - pB = aSendQ[ep]; - - while(pB) - { - if(INTERNAL_BUFFER_SEND_READY(pB) || - INTERNAL_BUFFER_SENDING(pB)) - { - iRval += pB->iLen; - } - - pB = pB->pNext; - } - - SREG = oldSREG; - - return iRval; -} - - -void USB_Flush(uint8_t ep) // sends all pending data -{ - internal_flush(ep); -} - - -int USB_Send(uint8_t ep, const void* data, int len, uint8_t bSendNow) -{ -uint8_t index = ep & 0xf; -uint16_t wProcessingMask = 1 << index; - - - if(index && !aSendQ[index]) // nothing in there at the moment? - { - if(ep & TRANSFER_TOGGLE_ON) - { - error_printP_(F("USB_Send - TRANSFER_TOGGLE_ON - ep=")); - error_printL(index); - - wEndpointToggle &= ~wProcessingMask; // toggle bit ON - } - else if(ep & TRANSFER_TOGGLE_OFF) - { - error_printP_(F("USB_Send - TRANSFER_TOGGLE_OFF - ep=")); - error_printL(index); - - wEndpointToggle |= wProcessingMask; // toggle bit OFF - } - } - - return internal_send(index, data, len, bSendNow) ? len : 0; -} - - -int USB_Recv(uint8_t ep, void* data, int len) -{ -int iRval; - - // THIS ONLY WORKS FOR OUT ENDPOINTS - if it's not an 'OUT', then there will - // be no buffered read data available. Does NOT work for control endpoints. - - if(!ep) - { - return -1; // can't use for the control endpoint - } - - iRval = internal_receive(ep, data, len); - - return iRval < 0 ? -1 : iRval; - -// return iRval < 0 ? -1 : iRval == len ? 0 : 1; // TODO: is this right? -} - - -int USB_Recv(uint8_t ep) -{ -static uint8_t a1; -int iRval; - - // THIS ONLY WORKS FOR OUT ENDPOINTS - if it's not an 'OUT', then there will - // be no buffered read data available. Does NOT work for control endpoints. - - if(!ep) - { - return -1; // can't use for the control endpoint - } - - iRval = internal_receive(ep, &a1, 1); - - if(iRval < 0) - { - return -1; - } - else if(iRval == 1) // there was data and I read it (1 byte) - { - return a1; - } - else - { - return 0; // for now [no data] [TODO: block?] - } -} - - -// an API for debugging help (mostly) -uint16_t GetFrameNumber(void) -{ - return epData.framenum; // last frame number read in by the device -} - - - -////////////////////////////////////////////////////////////////////////////// -// // -// ___ _ _ // -// |_ _| _ __ | |_ ___ _ __ _ __ _ _ _ __ | |_ ___ // -// | | | '_ \ | __|/ _ \| '__|| '__|| | | || '_ \ | __|/ __| // -// | | | | | || |_| __/| | | | | |_| || |_) || |_ \__ \ // -// |___||_| |_| \__|\___||_| |_| \__,_|| .__/ \__||___/ // -// |_| // -// // -////////////////////////////////////////////////////////////////////////////// - -// General interrupt (for the xmega, it's 'BUSEVENT' to handle SOF, etc.) -ISR(USB_BUSEVENT_vect) // USB_GEN_vect) -{ -uint8_t udint; -static bool bSOF = false; // use this to detect 'start of frame' - - - udint = *((volatile uint8_t *)&(USB_INTFLAGSACLR));// UDINT; - - // on startup of the hardware - if((udint & (USB_SUSPENDIF_bm | USB_RESUMEIF_bm)) == (USB_SUSPENDIF_bm | USB_RESUMEIF_bm)) - { - // NOTE: I have observed that when you power up the USB for the first time, you get an interrupt - // in which BOTH the RESUME and SUSPEND bits are set. This may *not* be a documented behavior - // but it happens, and I'd like to do something maybe... ? -#ifdef DEBUG_CODE - error_printP(F("USB powerup")); -#endif // DEBUG_CODE - - bSOF = false; - } - else if(udint & USB_SUSPENDIF_bm) - { - // NOTE: I get several suspend/resume combos after pulling the USB cable out - } - else if(udint & USB_RESUMEIF_bm) - { - // NOTE: I get several suspend/resume combos after pulling the USB cable out - - if(!bSOF) // did I get an SOF recently? - { - // NOTE: if this causes spurious misfires on 'disconnected', then use a counter of - // the times I get 'resume IF' and set it to zero when I get an SOF. If the - // resume count happens enough times, call THAT "the disconnect". - - if(_usbConfiguration) // if I didn't, and I'm configured, the device was UN-PLUGGED! - { -#ifdef DEBUG_CODE - error_printP(F("USB Disconnected")); -#endif // DEBUG_CODE - - // TODO: 'On disconnect' handler?? - - goto do_reset_interface; - } - } - else - { - bSOF = false; - } - } - - // End of Reset - happens when you first plug in, etc. - // (typically a reset will do this several times in a row) - if(udint & USB_RSTIF_bm) - { -#ifdef DEBUG_CODE - if(USB_ADDR != 0 || _usbConfiguration) - { - error_printP_(F("USB RESET: ADDR=")); - error_printL(USB_ADDR); - } -#endif // DEBUG_CODE - -do_reset_interface: - - USB_ADDR = 0; // IMMEDIATELY set USB address to 0 on reset. not sure if this is necessary however - - bUSBAddress = 0; // so I don't accidentally set the USB address after a zero-length packet is sent - - _usbConfiguration = 0; // make sure (un-configured) - - // TODO: see if endpoint 0 needs to be re-done or not, perhaps just leaving it - // 'as-is' may be MORE stable than re-doing it every! single! time! - -#ifdef CDC_ENABLED - CDC_Reset(); -#endif // CDC_ENABLED - -#ifdef HID_ENABLED - HID_Reset(); -#endif // HID_ENABLED - - InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // clear queues, init endpoints - - // clear any 'stall' event this might cause (it can happen) - *((volatile uint8_t *)&(USB_INTFLAGSACLR)) = USB_STALLIF_bm; // clears the bit - - goto the_end; - } - - if(udint & USB_UNFIF_bm) - { - check_send_queue(); // getting an early start on this - } - - if(udint & USB_OVFIF_bm) - { -// error_printP(F("OVF detected")); - note, seems to happen kinda often - - check_recv_queue(); // getting an early start on this - } - - // Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too - if(udint & USB_SOFIF_bm) - { - // every time I get a 'start of frame' I will assign 'true' to 'bSOF'. If I - // get a suspend/resume with no 'start of frame' in between, then I know that - // the USB is no longer connected, and I can shut it down. - - bSOF = true; - -#ifdef TX_RX_LED_INIT - // check whether the one-shot period has elapsed. if so, turn off the LED - if(TxLEDPulse && !(--TxLEDPulse)) - { - TXLED0(); // LED off - macro must be defined in variants 'pins_arduino.h' - } - if (RxLEDPulse && !(--RxLEDPulse)) - { - RXLED0(); // LED off - macro must be defined in variants 'pins_arduino.h' - } -#endif // TX_RX_LED_INIT - -// // if anything needs to be sent or received, make it happen NOW -// -// check_send_queue(); // check SEND queue first -// check_recv_queue(); // check this too, just in case, probably nothing - - if(_usbConfiguration) // am I 'configured' ? - { -#ifdef CDC_ENABLED - CDC_FrameReceived(); // callback for housekeeping things -#endif // CDC_ENABLED - } - } - -the_end: - // if any other flags were set during the ISR, I should get another interrupt - - *((volatile uint8_t *)&(USB_INTFLAGSACLR)) = udint; // clear whatever flags I processed this time - - return; // warning avoidance -} - -// Transaction Complete -ISR(USB_TRNCOMPL_vect) -{ -uint8_t udint; - - - udint = *((volatile uint8_t *)&(USB_INTFLAGSBCLR)); - - // since I never know exactly why I was interrupted, I'll check all of the queues - // to see if anything was sent/received, then process it. - - check_recv_queue(); // NOTE: this dispatches received packets for me - check_send_queue(); - - *((volatile uint8_t *)&(USB_INTFLAGSBCLR)) = udint; // now it's safe to clear interrupt flags - // NOTE: only the 2 lower bits of INTFLAGSB are actually used - - return; // warning avoidance -} - - -///////////////////////////////////////////////////////////////////////////////// -// // -// __ __ _ _ _ _ _ _ _ _ _ // -// | \/ |(_) __| | | | ___ __ __ ___ | | | | | || |_ (_)| | ___ // -// | |\/| || | / _` | _____ | | / _ \\ \ / // _ \| | | | | || __|| || |/ __| // -// | | | || || (_| ||_____|| || __/ \ V /| __/| | | |_| || |_ | || |\__ \ // -// |_| |_||_| \__,_| |_| \___| \_/ \___||_| \___/ \__||_||_||___/ // -// // -// // -///////////////////////////////////////////////////////////////////////////////// - -// mostly OLD CODE that needs to be adapted, or eliminated - -//================================================================== -//================================================================== - -// Handle CLASS_INTERFACE requests -static bool ClassInterfaceRequest(Setup& rSetup) -{ - u8 i = rSetup.wIndex; - -#ifdef CDC_ENABLED - if (CDC_ACM_INTERFACE == i) - { - error_printP(F("ClassInterfaceRequest - return CDC_Setup()")); - return CDC_Setup(rSetup); - } -#endif - -#ifdef HID_ENABLED - if (HID_INTERFACE == i) - { - error_printP(F("ClassInterfaceRequest - return HID_Setup()")); - return HID_Setup(rSetup); - } -#endif - - error_printP(F("ClassInterfaceRequest - return FALSE")); - - return false; -} - - -// Construct a dynamic configuration descriptor -// TODO: This really needs dynamic endpoint allocation etc - -static bool SendConfiguration(int maxlen) -{ -int interfaces, total; - - error_printP_(F("USB SendConfiguration - maxlen=")); - error_printL(maxlen); - - // Count and measure interfaces - // to do this properly, I'll allocate a packet, build it, and then - // add it to the send queue. MUCH better! - - interfaces = 0; - total = 0; - -#ifdef CDC_ENABLED - interfaces += CDC_GetNumInterfaces(); - total += CDC_GetInterfaceDataLength(); -#endif // CDC_ENABLED - -#ifdef HID_ENABLED - interfaces += HID_GetNumInterfaces(); - total += HID_GetInterfaceDataLength(); -#endif // HID_ENABLED - - // NOTE: 'total' says how long it's supposed to be. the next request will get ALL of it - // when 'maxlen' is only big enough for ConfigDescriptor. SO, I _must_ indicate - // the TRUE size of the response, but only send what I can. - - ConfigDescriptor config = D_CONFIG(total + sizeof(ConfigDescriptor),interfaces); - - // this default config assignment consists of the following information: - // - // clen total + sizeof(ConfigDescriptor) total length of all info - // numInterfaces interfaces total number of interfaces - // config 1 config number to assign - // iconfig 0 string description for config - // attributes USB_CONFIG_BUS_POWERED attributes of config - // maxPower USB_CONFIG_POWER_MA(500) max bus power - - // if I want a string index for my description I must assign it manually - config.iconfig = USB_STRING_INDEX_CONFIG; - - if(maxlen <= (int)sizeof(ConfigDescriptor)) - { - USB_SendControl(0, &config, sizeof(ConfigDescriptor)); // just 'config' - } - else - { - internal_send(0, &config, sizeof(ConfigDescriptor), 0); // 9 bytes into the output buffer - - // follow this with the REST of the descriptor -#ifdef CDC_ENABLED - CDC_SendInterfaceData(); // TODO: allow me to send without marking 'send now' -#endif // CDC_ENABLED -#ifdef HID_ENABLED - HID_SendInterfaceData(); -#endif // HID_ENABLED - } - - return true; -} - - -// NOTE this function does *NOT* do what it says on the tin... - -static bool SendDescriptor(Setup& rSetup) -{ -u8 t; -bool bRval; - - error_printP(F("USB SendDescriptor")); - -//#ifdef LED_SIGNAL1 -// digitalWrite(LED_SIGNAL1,digitalRead(LED_SIGNAL1) == LOW ? HIGH : LOW); -//#endif // LED_SIGNAL1 - - t = rSetup.wValueH; - if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) // 2 - { - error_printP_(F("Send Configuration [descriptor type] - length=")); - error_printL(rSetup.wLength); - - bRval = SendConfiguration(rSetup.wLength); - - return bRval; - } - -#ifdef HID_ENABLED - else if (HID_REPORT_DESCRIPTOR_TYPE == t) // 0x22 - { - error_printP(F("HID Get Descriptor [HID REPORT descriptor type]")); - - return HID_GetDescriptor(rSetup.wLength); - } -#endif - - u8 desc_length = 0; - const u8* desc_addr = 0; - if (USB_DEVICE_DESCRIPTOR_TYPE == t) // 1 - { - if (rSetup.wLength == 8) // this actually happens - it expects 8 bytes - this differentiates IAD vs Descriptor - { -#ifdef CDC_ENABLED - return CDC_SendIAD(); // send the 8-byte IAD thingy -#else - // TODO: something?? - - return false; // it will fail anyway -#endif // CDC_ENABLED - } - else if (rSetup.wLength == 9) // experiment - { -#ifdef CDC_ENABLED -#ifdef HID_ENABLED // both HID and CDC - desc_addr = (const u8 *)&USB_DeviceDescriptorB; // this one requires 'association type' -#else // !HID_ENABLED - return CDC_SendDeviceDescriptor(); // send the 9-byte device descriptor -#endif // HID_ENABLED -#endif // CDC_ENABLED - } - else - { - error_printP_(F("Device Descriptor Type - length was ")); - error_printL(rSetup.wLength); - } - - desc_addr = (const u8*)&USB_DeviceDescriptor; // always - } - else if (USB_DEVICE_QUALIFIER_TYPE == t) // 6 - { -// error_printP(F("Device Qualifier Type - a USB 2 request")); - // according to available documentation, it's a USB 2.0 request that wants to know how - // the device will behave in high speed mode (vs full speed mode). Since I don't support - // high speed mode, I'll 'nack' it with a zero length packet. - - // https://msdn.microsoft.com/en-us/library/windows/hardware/ff539288%28v=vs.85%29.aspx - - internal_send0(0); // ZLP which keeps host from waiting - return true; // for now indicate "it worked" - } - else if (USB_DEVICE_DEBUG_TYPE == t) // 10 - { - error_printP(F("Device DEBUG Type - a USB 2 request?")); - - internal_send0(0); // ZLP which keeps host from waiting - return true; // for now indicate "it worked" - } - else if (USB_INTERFACE_ASSOCIATION_TYPE == t) // 11 - { -#ifdef CDC_ENABLED - return CDC_SendIAD(); // send the 8-byte IAD thingy in response -#else // !CDC_ENABLED - internal_send0(0); // ZLP which keeps host from waiting - return true; // for now indicate "it worked" -#endif // CDC_ENABLED - } - else if (USB_STRING_DESCRIPTOR_TYPE == t) // 3 - { - if(rSetup.wValueL == USB_STRING_INDEX_LANGUAGE) - { - desc_addr = (const u8*) USB_STRING_LANGUAGE; //&(USB_STRING_LANGUAGE[0]); - } - else if(rSetup.wValueL == USB_STRING_INDEX_PRODUCT) - { - desc_addr = (const u8 *) USB_STRING_PRODUCT; // &(USB_STRING_PRODUCT[0]); - } - else if(rSetup.wValueL == USB_STRING_INDEX_MANUFACTURER) - { - desc_addr = (const u8 *) USB_STRING_MANUFACTURER; // &(USB_STRING_MANUFACTURER[0]); - } - else if(rSetup.wValueL == USB_STRING_INDEX_DESCRIPTION) - { - static const wchar_t szStr[] PROGMEM = L"\x0346" L"XMegaForArduino USB implementation"; // len=34 - - desc_addr = (const u8 *)szStr; - } - else if(rSetup.wValueL == USB_STRING_INDEX_VERSION) - { - static const wchar_t szStr[] PROGMEM = L"\x0310" L"1.00.00"; // len=7 - - desc_addr = (const u8 *)szStr; - } - else if(rSetup.wValueL == USB_STRING_INDEX_URL) - { - static const wchar_t szStr[] PROGMEM = L"\x0356" L"http://github.com/XMegaForArduino/arduino/"; // len=42 - - desc_addr = (const u8 *)szStr; - } - else if(rSetup.wValueL == USB_STRING_INDEX_CONFIG) - { - static const wchar_t szStr[] PROGMEM = L"\x034c" L"Default XMegaForArduino Configuration"; // len=37 - - desc_addr = (const u8 *)szStr; - } - else if(rSetup.wValueL == USB_STRING_INDEX_SERIAL) - { - wchar_t tbuf[22]; // 7 hex digits with ':' between, plus lead byte + 1 extra - short i1, i2; - - // build the serial # string (20 wide chars) - // use ascii/unicode basic values of 0-255 only for simplicity - - for(i1=0, i2=1; i1 < 7; i1++) - { - char c1; - uint8_t b1; - - // use the CPU's unique signature information to generate a serial number - if(i1 < 6) - { - b1 = readCalibrationData(8 + i1); // 8 is 'LOTNUM0'; there are 6 of them - } - else - { - b1 = readCalibrationData(0x10); // WAFNUM is offset 10H - } - - if(i1) - { - tbuf[i2++] = ':'; - } - - c1 = (b1 >> 4) & 0xf; - if(c1 < 10) - { - c1 += '0'; - } - else - { - c1 += 'A' - 10; - } - - tbuf[i2++] = c1; - - c1 = b1 & 0xf; - if(c1 < 10) - { - c1 += '0'; - } - else - { - c1 += 'A' - 10; - } - - tbuf[i2++] = c1; - } - - // now the lead-in byte, 300H + length (in bytes) - i2 *= sizeof(wchar_t); // the actual length now in i2 - - tbuf[0] = 0x300 + i2; - - USB_SendControl(0, (const u8 *)tbuf, i2); - return true; - } - - // TODO: others? - else - { - error_printP_(F("SendDescriptor - bad setup index ")); - error_printL(rSetup.wValueL); - - return false; - } - } - else - { - error_printP_(F("*** Unknown Descriptor Type - ")); - error_printL(t); - - return false; - } - - if(desc_addr == 0) - { - error_printP(F("SendDescriptor - zero pointer")); - - return false; - } - else if(desc_length == 0) - { - desc_length = pgm_read_byte(desc_addr); // first byte of the descriptor, always - } - - USB_SendControlP(TRANSFER_PGM, desc_addr, desc_length); - - return true; -} - - - -//////////////////////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ ____ ____ _ _ // -// | | | |/ ___| | __ ) | _ \ ___ __ __(_) ___ ___ ___ | | __ _ ___ ___ // -// | | | |\___ \ | _ \ | | | | / _ \\ \ / /| | / __|/ _ \ / __|| | / _` |/ __|/ __| // -// | |_| | ___) || |_) || |_| || __/ \ V / | || (__| __/ | (__ | || (_| |\__ \\__ \ // -// \___/ |____/ |____/ |____/ \___| \_/ |_| \___|\___|_____ \___||_| \__,_||___/|___/ // -// |_____| // -// // -//////////////////////////////////////////////////////////////////////////////////////////////// - -USBDevice_ USBDevice; - -USBDevice_::USBDevice_() -{ -} - -void USBDevice_::attach() -{ -// error_printP(F("USB - attach")); - - uint8_t oldSREG = SREG; // save int flag - cli(); // no interrupt handling until I'm done setting this up - - USB_INTCTRLA = 0; - USB_INTCTRLB = 0; - - USB_INTFLAGSACLR = 0xff; // clear all int flags - USB_INTFLAGSBCLR = 0x3; // clear all int flags - - _usbConfiguration = 0; - - // enable the USB clock using the 32mhz RC oscillator - // assume either slow (6mhz) or fast (48mhz) - // and of course the pre-scaler must be assigned accordingly - // Also, assume that the oscillator is *SET UP* *PROPERLY* already, and - // that all I have to do is configure the PLL to run at 48Mhz - - // setting up the PLL - source is usually RC32M 'divided by 4' then multiplied by 6 for 48Mhz - - USB_CTRLA = 0; // shut down USB - USB_CTRLB = 0; // detach D- and D+ - - CLK_USBCTRL = 0; // shut off USB clock - section 7.9.5 in AU manual - - OSC_CTRL &= ~(OSC_PLLEN_bm); // disable PLL osc - section 7.9.1 in AU manual - -#ifdef USE_RC2M // am I using the 2Mhz oscillator for the USB instead of 32Mhz? - - OSC_CTRL |= OSC_RC2MEN_bm; // enable 2M osc - - while(!(OSC_STATUS & OSC_RC2MRDY_bm)) // wait for 2M RC osc to be 'ready' - { - // TODO: timeout? I must wait until the osc is stable - } - - // now config PLL and USB clock stuff - - // 2Mhz as the source, multiplicatino factor of 24 = 48Mhz - OSC_PLLCTRL = OSC_PLLSRC_RC2M_gc | 24; // 24 times the 2Mhz frequency - - // TODO: set up the calibration PLL for 2Mhz ? - -#else // !USE_RC2M - I am using the 32Mhz oscillator with the PLL - this is normal - - // 32Mhz (divided by 4, so it's 8Mhz) as the source - // multiplication factor of 6 - result = 48Mhz - OSC_PLLCTRL = OSC_PLLSRC_RC32M_gc | 6; // 6 times the 8Mhz frequency - section 7.10.6 in AU manual - -#endif // USE_RC2M - - OSC_CTRL |= OSC_PLLEN_bm; // re-enable PLL - section 7.9.5 in AU manual - - while(!(OSC_STATUS & OSC_PLLRDY_bm)) // wait for PLL to be 'ready' - { - // TODO: timeout? I need to wait until it's stable - } - - -#ifdef FAST_USB /* note this is 12Mbit operation, 'FULL' speed, not 'HIGH' speed 480Mbit */ - CLK_USBCTRL = CLK_USBSRC_PLL_gc; // use PLL (divide by 1, no division) - section 7.9.5 in AU manual - -#else // SLOW - CLK_USBCTRL = CLK_USBSRC_PLL_gc // use PLL - section 7.9.5 in AU manual - | CLK_USBPSDIV_8_gc; // divide by 8 for 6mhz operation (12Mhz? see 7.3.6 which says 12Mhz or 48Mhz) - -#endif // FAST_USB or SLOW - - CLK_USBCTRL |= CLK_USBEN_bm; // enable bit - section 7.9.5 in AU manual - - - // assign CAL register from product signatures (4.17.17,18) - USB_CAL0 = readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_USBCAL0); // docs say 'CALL' - USB_CAL1 = readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_USBCAL1); // docs say 'CALH' - - // set the max # of endpoints, speed, and 'store frame number' flags - USB_CTRLA = MAXEP // max # of endpoints minus 1 - section 20.14.1 in AU manual -#ifdef FAST_USB - | USB_SPEED_bm // FAST USB - all ahead 'FULL' - aka 'FULL' speed ahead! - ok bad PUNishment -#endif // FAST_USB - | USB_STFRNUM_bm // store the frame number (mostly for debugging) - // TODO: FIFO ? - ; - - init_buffers_and_endpoints(); // initialize everything in RAM registers, basically - - USB_EPPTR = endpoint_data_pointer(); // assign the data pointer to the RAM registers - section 20.14.7,8 - // NOTE: the xmega USB implementation puts most of the 'register' info for USB into RAM - - USB_ADDR = 0; // set USB address to 0 (before doing the first 'SETUP' request) - - // LAST of all, enable interrupts - USB_INTCTRLB = USB_TRNIE_bm | USB_SETUPIE_bm; // enable 'transaction complete' and 'setup' interrupts - USB_INTCTRLA = USB_SOFIE_bm // enable the start of frame interrupt - | USB_BUSEVIE_bm // 'bus event' interrupt - suspend, resume, reset - // for the RESET event, RESETIF will be set (20.14.11 in AU manual) - | USB_INTLVL1_bm; // int level 2 (deliberately lower than serial port, SPI, I2C) -// | USB_INTLVL0_bm | USB_INTLVL1_bm; // int level 3 (for if there are performance problems with int level 2) - - - // NOW enable the USB - USB_CTRLA |= USB_ENABLE_bm; // and, we're UP and RUNNING! section 20.14.1 in AU manual - - SREG = oldSREG; // restore int flags - - // attach the wiring for D- and D+ AFTER everything else. - - USB_CTRLB = USB_ATTACH_bm; // attach D- and D+ (also enables pullup resistors based on speed) - - // on A1U and A4U devices, this is PD6 (D-) and PD7 (D+) [YMMV on the other processors] - // this is partly why it's good to use PORTC for the primary SPI, etc. since PORTD - // gets used for 'other things' (like USB). Default serial port on PORTD is still ok. - - -#ifdef TX_RX_LED_INIT - TX_RX_LED_INIT(); // macro must be defined in variants 'pins_arduino.h' for the USB activity lights -#endif // TX_RX_LED_INIT - - error_printP(F("USB Attach (done)")); - - // NOTE: at THIS point the ISR will manage everything else. The USB will receive - // messages to set up the connection, etc. and the ISR will drive it. -} - -void USBDevice_::detach() -{ - error_printP(F("USB - detach")); - - uint8_t oldSREG = SREG; // save int flag - cli(); // no interrupt handling until I'm done setting this up - - USB_INTCTRLA = 0; // disabling interrupts - USB_INTCTRLB = 0; - USB_CTRLB = 0; // detach D- and D+ - USB_CTRLA = 0; // shut down USB - CLK_USBCTRL = 0; // shut off USB clock - - init_buffers_and_endpoints(); // re-initialize these - - _usbConfiguration = 0; - - SREG = oldSREG; // restore int flags - - error_printP(F("USB Detach (done)")); -} - -// added this for access to USB device structures -XMegaEPDataStruct *USBDevice_::GetEPData() -{ - return &epData; -} - -// Check for interrupts -// TODO: VBUS detection -bool USBDevice_::configured() -{ - return _usbConfiguration; -} - -void USBDevice_::poll() -{ -} - -#endif /* if defined(USBCON) */ - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/USBCore.h b/BootLoaders/Boards/orangerx/cores/xmega/USBCore.h deleted file mode 100644 index 3223618..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/USBCore.h +++ /dev/null @@ -1,442 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ ____ ____ _ // -// | | | |/ ___| | __ ) / ___| ___ _ __ ___ | |__ // -// | | | |\___ \ | _ \ | | / _ \ | '__|/ _ \ | '_ \ // -// | |_| | ___) || |_) || |___| (_) || | | __/ _ | | | | // -// \___/ |____/ |____/ \____|\___/ |_| \___|(_)|_| |_| // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -// Copyright (c) 2010, 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 __USBCORE_H__ -#define __USBCORE_H__ - -// USB implementation MUST have USB_VID and USB_PID defined - can be done in 'boards.txt' -#if defined(USBCON) /* TODO add others here, things that require VID and PID for USB */ -#ifdef USB_VID -#if USB_VID==null -#error cannot work with NULL value for VID -#endif // USB_VID==null -#else -#error must define USB_VID -#endif // USB_VID - -#ifdef USB_PID -#if USB_PID==null -#error cannot work with NULL value for PID -#endif // USB_PID==null -#else -#error must define USB_PID -#endif // USB_PID -#endif // defined(USBCON) - - -#define FAST_USB /* necessary for 'FULL' speed operation - this is 12Mbit, not 480Mbit USB 2 'HIGH' speed - 'LOW' may not work properly */ - -#ifndef _PLATFORM_H_TYPES_DEFINED_ /* TEMPORARY FIX, SEE Platform.h */ -#define _PLATFORM_H_TYPES_DEFINED_ -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned long u32; -#endif // _PLATFORM_H_TYPES_DEFINED_ - -// 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 /* device to host, i.e. 'in' - when not set, it's 'out' (host to device) */ -#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) - -// Class requests - -#define CDC_SET_LINE_CODING 0x20 -#define CDC_GET_LINE_CODING 0x21 -#define CDC_SET_CONTROL_LINE_STATE 0x22 - -#define MSC_RESET 0xFF -#define MSC_GET_MAX_LUN 0xFE - -#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 - -// 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_QUALIFIER_TYPE 6 -#define USB_OTHER_SPEED_CONFIGURATION_TYPE 7 -#define USB_INTERFACE_POWER_TYPE 8 -#define USB_OTG_TYPE 9 -#define USB_DEVICE_DEBUG_TYPE 10 -#define USB_INTERFACE_ASSOCIATION_TYPE 11 /* see InterfaceAssociationDescriptor_ecn.pdf */ -// NOTE: for USB_INTERFACE_ASSOCIATION_TYPE respond with IADDescriptor - -#define USB_DEVICE_CLASS_ZERO 0x00 -#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 - -// bMaxPower in Configuration Descriptor -#define USB_CONFIG_POWER_MA(mA) ((mA)/2) - -// bEndpointAddress in Endpoint Descriptor -#define USB_ENDPOINT_DIRECTION_MASK 0x80 -#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00) -#define USB_ENDPOINT_IN(addr) ((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 TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) - -#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 MSC_SUBCLASS_SCSI 0x06 -#define MSC_PROTOCOL_BULK_ONLY 0x50 - -#define HID_HID_DESCRIPTOR_TYPE 0x21 -#define HID_REPORT_DESCRIPTOR_TYPE 0x22 -#define HID_PHYSICAL_DESCRIPTOR_TYPE 0x23 - -// CONTROL LINE STATE and SERIAL STATE - BIT VALUES (16-bits, LE) -// USED BY 'SET CONTROL LINE STATE' and 'SERIAL STATE' FOR CAM INTERRUPT 'IN' -#define CONTROL_LINE_STATE_DTR 0x01 /* data terminal ready [ok to send on IN] */ -#define CONTROL_LINE_STATE_RTS 0x02 /* ready to send [has data ready for OUT] */ -#define SERIAL_STATE_RX_CARRIER_DCD 0x01 /* receive carrier detect - on to allow receive */ -#define SERIAL_STATE_TX_CARRIER_DSR 0x02 /* data set ready - inform host I have data */ -#define SERIAL_STATE_BREAK_DETECT 0x04 /* 'break' detect */ -#define SERIAL_STATE_RING_DETECT 0x08 /* 'ring' detect */ -#define SERIAL_STATE_FRAMING_ERROR 0x10 /* framing error */ -#define SERIAL_STATE_PARITY_ERROR 0x20 /* parity error */ -#define SERIAL_STATE_OVERRUN 0x40 /* overrun input (data lost) */ - - -// A1U series needs 16-byte alignment for endpoint structure -#if defined(__AVR_ATxmega64A1U__) || defined(__AVR_ATxmega128A1U__) -#define A1U_SERIES -#endif // A1U - -// Device -typedef struct _device_descriptor_ -{ - u8 len; // 18 - u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE - u16 usbVersion; // 0x200 - u8 deviceClass; - u8 deviceSubClass; - u8 deviceProtocol; - u8 packetSize0; // Packet 0 - u16 idVendor; - u16 idProduct; - u16 deviceVersion; // 0x100 - u8 iManufacturer; - u8 iProduct; - u8 iSerialNumber; - u8 bNumConfigurations; -} DeviceDescriptor; - -// Config -typedef struct _config_descriptor_ -{ - u8 len; // 9 - u8 dtype; // 2 - u16 clen; // total length - u8 numInterfaces; - u8 config; - u8 iconfig; - u8 attributes; - u8 maxPower; -} ConfigDescriptor; - -// String - -// Interface -typedef struct _interface_descriptor_ -{ - u8 len; // 9 - u8 dtype; // 4 - u8 number; - u8 alternate; - u8 numEndpoints; - u8 interfaceClass; - u8 interfaceSubClass; - u8 protocol; - u8 iInterface; -} InterfaceDescriptor; - -// Endpoint -typedef struct _endpoint_descriptor_ -{ - u8 len; // 7 - u8 dtype; // 5 - u8 addr; - u8 attr; - u16 packetSize; - u8 interval; -} EndpointDescriptor; - -// Interface Association Descriptor -// Used to bind 2 interfaces together in CDC compostite device -typedef struct _iad_descriptor_ -{ - u8 len; // 8 - u8 dtype; // 11 - u8 firstInterface; - u8 interfaceCount; - u8 functionClass; - u8 funtionSubClass; - u8 functionProtocol; - u8 iInterface; -} IADDescriptor; - -// CDC CS interface descriptor -typedef struct _cdccs_interface_descriptor_ -{ - u8 len; // 5 - u8 dtype; // 0x24 - u8 subtype; - u8 d0; - u8 d1; -} CDCCSInterfaceDescriptor; - -typedef struct _cdccs_interface_descriptor4_ -{ - u8 len; // 4 - u8 dtype; // 0x24 - u8 subtype; - u8 d0; -} CDCCSInterfaceDescriptor4; - -typedef struct _cm_functional_descriptor_ -{ - u8 len; // 5 - u8 dtype; // 0x24 - u8 subtype; // 1 - u8 bmCapabilities; - u8 bDataInterface; -} CMFunctionalDescriptor; - -typedef struct _acm_functional_descriptor_ -{ - u8 len; - u8 dtype; // 0x24 - u8 subtype; // 1 - u8 bmCapabilities; -} ACMFunctionalDescriptor; - -typedef struct _cdc_descriptor_ -{ -// // IAD -// IADDescriptor iad; // for complex endpoints (apparently not critical) - - // 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 _msc_descriptor_ -{ - InterfaceDescriptor msc; - EndpointDescriptor in; - EndpointDescriptor out; -} MSCDescriptor; - -typedef struct _hid_desc_descriptor_ -{ - u8 len; // 9 - u8 dtype; // 0x21 - u8 addr; - u8 versionL; // 0x101 - u8 versionH; // 0x101 - u8 country; - u8 desctype; // 0x22 report - u8 descLenL; - u8 descLenH; -} HIDDescDescriptor; - -typedef struct _hid_descriptor_ -{ - InterfaceDescriptor hid; - HIDDescDescriptor desc; - EndpointDescriptor in; -} HIDDescriptor; - - -// XMEGA STRUCTURES - -#define MAXEP 5 /*15*/ /* 4 bit value, 0-15 - see 20.14.1 'CTRLA register' in AU manual */ -// I assigned this to '5' because there are only 5 endpoints being used by THIS code. -// The 'mega' code could only have a total of 6 and 0 was always the 'control' endpoint -// and setting a 'smaller-than-maximum' value for XMEGA burns up less RAM. -// If this poses a problem I _could_ malloc the structures, but to be effective, it would -// have to require a reboot to change it, or you'd get major RAM fragmentation -// -// TODO: put MAXEP into pins_arduino.h and override if too small (or not defined already) - -typedef union _xmega_fifo_entry_ -{ - struct - { - uint8_t h, l; - }; - uint16_t heW; // high endian word -} XMegaFIFOEntry; - -typedef struct _xmega_fifo_ -{ - XMegaFIFOEntry in; - XMegaFIFOEntry out; -} XMegaFIFO; - -// see AU manual, pg 231 section 20.4 -typedef struct _xmega_endpoint_descriptor_ -{ - volatile uint8_t status; - volatile uint8_t ctrl; - volatile uint16_t /*HLByteWord*/ cnt; // so, cnt.w is the 16-bit value, cnt.l and cnt.h the 8-bit low/high - // it is the 'data count' value. it may be zero. - // only bits 1:0 of cnt.h are valid. cnt.w should be 'and'd with 0x3ff - // the high bit of cnt.w and cnt.h is the 'AZLP' (auto zero length packet) bit - // see AU manual section 20.15.4 - volatile uint16_t /*HLByteWord*/ dataptr; // pointer to data buffer. max packet length assigned to CTRL [1:0] or [2:0] - // see table 20-5 in AU manual for max packet length. may need 2 buffers "that long" - volatile uint16_t /*HLByteWord*/ auxdata; // used for multi-packet transfers -} XMegaEndpointDescriptor; // NOTE: 2 per channel (one 'out', one 'in') pointed by EPPTR - -typedef struct _xmega_endpoint_channel_ -{ - XMegaEndpointDescriptor out; - XMegaEndpointDescriptor in; -} XMegaEndpointChannel -#ifdef A1U_SERIES - __attribute (( aligned (16) )); -#else // not an A1U series - __attribute__ (( aligned (2) /*, packed*/)); -#endif // A1U or not - -// also section 20.4 in AU manual -typedef struct _XMegaEPDataStruct_ -{ -#ifdef A1U_SERIES -#if ((MAXEP+1)%4) != 0 // A1U needs 16-byte boundary, not merely word-aligned - uint8_t padding[sizeof(XMegaFIFO) * (4 - ((MAXEP+1)%4))]; // this should 16-byte align 'endpoint' as required -#endif // needs padding -#endif // XMEGA A1U series - XMegaFIFO fifo[MAXEP + 1]; - XMegaEndpointChannel endpoint[MAXEP + 1]; // point EPPTR to THIS (must be word boundary) - volatile uint16_t framenum; // 1 word frame number -} XMegaEPDataStruct /*__attribute__ ((packed))*/; // note: point EPPTR to &endpoint[0], word alignment needed - -#ifdef DEBUG_CODE -uint16_t endpoint_data_pointer(void); -#define EP_DATA_STRUCT() ((XMegaEPDataStruct *)(endpoint_data_pointer() - (uint16_t)&(((XMegaEPDataStruct *)0)->endpoint[0]))) -#endif // DEBUG_CODE - -// this is the USB Device Descriptor -#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ - { 18, 1, 0x200, _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_POWER_MA(500) } - -#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_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ - { 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } - -#define D_HIDREPORT(_descriptorLength) \ - { 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } - -#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 } -#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 } - - -#endif - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h b/BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h deleted file mode 100644 index d403833..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h +++ /dev/null @@ -1,83 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// // -// _ _ ____ ____ ____ _ // -// | | | |/ ___| | __ ) | _ \ ___ ___ ___ | |__ // -// | | | |\___ \ | _ \ | | | | / _ \/ __| / __| | '_ \ // -// | |_| | ___) || |_) || |_| || __/\__ \| (__ _ | | | | // -// \___/ |____/ |____/ |____/ \___||___/ \___|(_)|_| |_| // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -/* 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. -*/ - -// NOTE: don't define these here; define them in pins_arduino.h -//#define CDC_ENABLED -//#define HID_ENABLED - - -#ifdef CDC_ENABLED -#define CDC_INTERFACE_COUNT 2 -#define CDC_ENDPOINT_COUNT 3 -#else -#define CDC_INTERFACE_COUNT 0 -#define CDC_ENPOINT_COUNT 0 -#endif - -#ifdef HID_ENABLED -#define HID_INTERFACE_COUNT 1 -#define HID_ENPOINT_COUNT 1 -#else -#define HID_INTERFACE_COUNT 0 -#define HID_ENPOINT_COUNT 0 -#endif - -#define CDC_ACM_INTERFACE 0 // CDC ACM interface -#define CDC_DATA_INTERFACE 1 // CDC Data interface -#define CDC_FIRST_ENDPOINT 1 -#define CDC_ENDPOINT_ACM (CDC_FIRST_ENDPOINT) // CDC First -#define CDC_ENDPOINT_OUT (CDC_FIRST_ENDPOINT+1) -#define CDC_ENDPOINT_IN (CDC_FIRST_ENDPOINT+2) - -#define HID_INTERFACE (CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT) // HID Interface -#define HID_FIRST_ENDPOINT (CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) -#define HID_ENDPOINT_INT (HID_FIRST_ENDPOINT) - -#define INTERFACE_COUNT (MSC_INTERFACE + MSC_INTERFACE_COUNT) - -#ifdef CDC_ENABLED -#define CDC_RX CDC_ENDPOINT_OUT -#define CDC_TX CDC_ENDPOINT_IN -#define CDC_ACM CDC_ENDPOINT_ACM -#endif - -#ifdef HID_ENABLED -#define HID_TX HID_ENDPOINT_INT -#endif - -// string indexes/indices for USB_STRING_DESCRIPTOR_TYPE -#define USB_STRING_INDEX_LANGUAGE 0 /* not actually a STRING though */ -#define USB_STRING_INDEX_MANUFACTURER 1 -#define USB_STRING_INDEX_PRODUCT 2 -#define USB_STRING_INDEX_DESCRIPTION 3 -#define USB_STRING_INDEX_VERSION 4 -#define USB_STRING_INDEX_URL 5 -#define USB_STRING_INDEX_SERIAL 6 -#define USB_STRING_INDEX_CONFIG 7 - - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/Udp.h b/BootLoaders/Boards/orangerx/cores/xmega/Udp.h deleted file mode 100644 index dfa425a..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/Udp.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Udp.cpp: Library to send/receive UDP packets. - * - * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these) - * 1) UDP does not guarantee the order in which assembled UDP packets are received. This - * might not happen often in practice, but in larger network topologies, a UDP - * packet can be received out of sequence. - * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being - * aware of it. Again, this may not be a concern in practice on small local networks. - * For more information, see http://www.cafeaulait.org/course/week12/35.html - * - * MIT License: - * Copyright (c) 2008 Bjoern Hartmann - * 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. - * - * bjoern@cs.stanford.edu 12/30/2008 - */ - -#ifndef udp_h -#define udp_h - -#include -#include - -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; - // 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; - // 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; - // Write a single byte into the packet - 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; - - // 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; - // Number of bytes remaining in the current packet - virtual int available() =0; - // Read a single byte from the current packet - 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; - // 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; - // 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 - - // Return the IP address of the host who sent the current incoming packet - virtual IPAddress remoteIP() =0; - // Return the port of the host who sent the current incoming packet - virtual uint16_t remotePort() =0; -protected: - uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); }; -}; - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h b/BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h deleted file mode 100644 index 79733b5..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - WCharacter.h - Character utility functions for Wiring & Arduino - Copyright (c) 2010 Hernando Barragan. 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 - */ - -#ifndef Character_h -#define Character_h - -#include - -// WCharacter.h prototypes -inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); -inline boolean isAlpha(int c) __attribute__((always_inline)); -inline boolean isAscii(int c) __attribute__((always_inline)); -inline boolean isWhitespace(int c) __attribute__((always_inline)); -inline boolean isControl(int c) __attribute__((always_inline)); -inline boolean isDigit(int c) __attribute__((always_inline)); -inline boolean isGraph(int c) __attribute__((always_inline)); -inline boolean isLowerCase(int c) __attribute__((always_inline)); -inline boolean isPrintable(int c) __attribute__((always_inline)); -inline boolean isPunct(int c) __attribute__((always_inline)); -inline boolean isSpace(int c) __attribute__((always_inline)); -inline boolean isUpperCase(int c) __attribute__((always_inline)); -inline boolean 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)); - - -// Checks for an alphanumeric character. -// It is equivalent to (isalpha(c) || isdigit(c)). -inline boolean isAlphaNumeric(int c) -{ - return ( isalnum(c) == 0 ? false : true); -} - - -// Checks for an alphabetic character. -// It is equivalent to (isupper(c) || islower(c)). -inline boolean isAlpha(int c) -{ - return ( isalpha(c) == 0 ? false : true); -} - - -// Checks whether c is a 7-bit unsigned char value -// that fits into the ASCII character set. -inline boolean isAscii(int c) -{ - return ( isascii (c) == 0 ? false : true); -} - - -// Checks for a blank character, that is, a space or a tab. -inline boolean isWhitespace(int c) -{ - return ( isblank (c) == 0 ? false : true); -} - - -// Checks for a control character. -inline boolean isControl(int c) -{ - return ( iscntrl (c) == 0 ? false : true); -} - - -// Checks for a digit (0 through 9). -inline boolean isDigit(int c) -{ - return ( isdigit (c) == 0 ? false : true); -} - - -// Checks for any printable character except space. -inline boolean isGraph(int c) -{ - return ( isgraph (c) == 0 ? false : true); -} - - -// Checks for a lower-case character. -inline boolean isLowerCase(int c) -{ - return (islower (c) == 0 ? false : true); -} - - -// Checks for any printable character including space. -inline boolean isPrintable(int c) -{ - return ( isprint (c) == 0 ? false : true); -} - - -// Checks for any printable character which is not a space -// or an alphanumeric character. -inline boolean isPunct(int c) -{ - return ( ispunct (c) == 0 ? false : true); -} - - -// 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 boolean isSpace(int c) -{ - return ( isspace (c) == 0 ? false : true); -} - - -// Checks for an uppercase letter. -inline boolean isUpperCase(int c) -{ - return ( isupper (c) == 0 ? false : true); -} - - -// 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 boolean isHexadecimalDigit(int c) -{ - return ( isxdigit (c) == 0 ? false : true); -} - - -// 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); -} - - -// Warning: -// 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); -} - - -// Converts the letter c to upper case, if possible. -inline int toUpperCase(int c) -{ - return toupper (c); -} - -#endif \ No newline at end of file diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c b/BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c deleted file mode 100644 index d30043a..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c +++ /dev/null @@ -1,808 +0,0 @@ -/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */ - -/* - Part of the Wiring project - http://wiring.uniandes.edu.co - - Copyright (c) 2004-05 Hernando Barragan - - 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 - - Modified 24 November 2006 by David A. Mellis - Modified 1 August 2010 by Mark Sproul - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#include -#include -#include -#include -#include - -#include "wiring_private.h" - -// interrupts on the xmega are handled differently than the mega -// there are 2 interrupt vectors for each port. Typical xmega -// will use ports A, B, C, D, E, and R. The vectors for those -// are as follows: -// -// PORTn_INT0_vect -// - and - -// PORTn_INT1_vect -// -// where 'n' is A, B, C, D, E, or R -// -// Additional vectors are: -// -// OSC_XOSCF_vect (external oscillator failure, NMI) -// -// RTC_OVF_vect (real-time clock overflow) -// RTC_COMP_vect (real-time clock compare) -// -// TWIC_TWIS_vect (2-wire slave on port C) -// TWIC_TWIM_vect (2-wire master on port C) -// TWIE_TWIS_vect (2-wire slave on port E) -// TWIE_TWIM_vect (2-wire master on port E) -// -// timers - 'n' is C or D -// TCn0_OVF_vect (n timer 0 overflow) -// TCn1_OVF_vect (n timer 1 overflow) -// TCn2_LUNF_vect (n timer 2 low byte underflow) -// TCn2_HUNF_vect (n timer 2 high byte underflow) -// TCE0_OVF_vect (E timer 0 overflow) -// TCn0_ERR_vect (n timer 0 error) -// TCn1_ERR_vect (n timer 1 error) -// TCE0_ERR_vect (E timer 0 error) -// TCn0_CCA_vect (n timer 0 compare or capture A) -// TCn1_CCA_vect (n timer 1 compare or capture A) -// TCn2_LCMPA_vect (n timer 2 low-byte compare or capture A) -// TCE0_CCA_vect (E timer 0 compare or capture A) -// TCn0_CCB_vect (n timer 0 compare or capture B) -// TCn1_CCB_vect (n timer 1 compare or capture B) -// TCn2_LCMPB_vect (n timer 2 low-byte compare or capture B) -// TCE0_CCB_vect (E timer 0 compare or capture B) -// TCn0_CCC_vect (n timer 0 compare or capture C) -// TCn2_LCMPC_vect (n timer 2 low-byte compare or capture C) -// TCE0_CCC_vect (E timer 0 compare or capture C) -// TCn0_CCD_vect (n timer 0 compare or capture D) -// TCn2_LCMPD_vect (n timer 2 low-byte compare or capture D) -// TCE0_CCD_vect (E timer 0 compare or capture D) -// -// SPIn_INT_vect (SPI C or D) -// -// USARTn0_RXC_vect (USART 'n' [C or D] receive complete) -// USARTn0_DRE_vect (USART 'n' [C or D] data reg empty) -// USARTn0_TXC_vect (USART 'n' [C or D] transmit complete) -// -// NOTE: a 'USARTE' interrupt vector also exists, but isn't -// implemented on the D4 series -// -// ASYNC interrupts are only possible on pin 2 for each of the 5 -// ports ('R' only has 2 pins, 0 and 1, so no async interrupt). -// Sleep modes typically need ASYNC interrupts to wake up. - -// The interrupt will be handled for a particular port, and not for -// a particular interrupt. The 'attachInterrupt' function will default -// to pin 2 (asynchronous interrupt) unless otherwise specified in the -// 'mode' parameter. - -// BOOTLOADER NOTES -// -// Bit 6 of the CTRL reg must be assigned to '0'. Bit 7 can be assigned -// to '1' to enable 'round robin' scheduling using the priority bits. -// Bits 0-2 (HILVLEN, MEDLVLEN, LOLVLEN) should also be assigned to '1' -// to allow all 3 interrupt levels to execute. ('D' manual 10.8.3 pg 102) -// The CTRL reg can be assigned to b10000111 to accomplish this. Bit 6 -// needs to use the "configuration change protection" method to change it -// and may need to be assigned separately. - - - -// interrupt mode - predefined values are LOW, CHANGE, RISING, FALLING, HIGH -// additional bits are 'or'd with mode - -static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; -static volatile uint8_t intPins[EXTERNAL_NUM_INTERRUPTS]; // added - store pins for this interrupt -// volatile static voidFuncPtr twiIntFunc; - - -// NOTE: I _HATE_ K&R style so I'll make it Allman style as I go along... - -void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) -{ -uint8_t iPinBits, iPriBits, iModeBits, iInv, iNum, iMask; -uint8_t oldSREG; -uint8_t intInfo; -PORT_t *port; - - - // for compatibility with newer IDE, 'interruptNum' can be encoded with pin information. - // if it is, then the pin info will be derived from pin info in 'mode' and 'interruptNum' - // pin info will be incorporated into it. - - intInfo = ((interruptNum & 0xe0) >> 5); // is an int pin encoded here by digitalPinToInterrupt ? - interruptNum &= 0x1f; // so the rest of the code will work correctly - - if(interruptNum >= EXTERNAL_NUM_INTERRUPTS) - { - return; - } - - iPinBits = (uint8_t)((mode & INT_MODE_PIN_MASK) >> 8); - - if(intInfo) - { - intInfo = ((intInfo + 2) & 7); // convert to actual pin number - - iPinBits |= _BV(intInfo); // set respective bit in 'iPinBits' - } - - if(!iPinBits) - { - if(interruptNum == PORTR_INT0 -#ifdef PORTR_INT1 - || interruptNum == PORTR_INT1 -#endif // PORTR_INT1 - ) // not valid for these - { - return; // do nothing (for now) - } - - iPinBits = _BV(2); // set bit for pin 2 if none specified [i.e. 'default'] - } - - iPriBits = (mode & INT_MODE_PRI_MASK) - >> INT_MODE_PRI_SHIFT; - - if(!iPriBits) // not assigned - { - iPriBits = 3; // for now, just use the highest priority - } - - mode &= INT_MODE_MODE_MASK; - iInv = 0; - - if(mode == LOW) // normally will be this, for backward hardware compatibility - { - iModeBits = PORT_ISC_LEVEL_gc; // b011, high level continuously generates events - } - else if(mode == HIGH) // these constants correspond to the mega's bit mask on ISC00,ISC10 - { - iModeBits = PORT_ISC_LEVEL_gc; // b011, high level continuously generates events - iInv = 1; // invert input (so 'high level' becomes 'low level') - - // NOTE: this was verified by experimentation. The documentation is misleading, suggesting - // that a LEVEL interrupt triggered on HIGH, not on LOW. But it triggers on LOW. So - // if you want HIGH, you must invert it. Not the other way around. Yeah. - } - else if(mode == CHANGE) - { - iModeBits = PORT_ISC_BOTHEDGES_gc; // BOTHEDGES - see table 11-6 - } - else if(mode == RISING) - { - iModeBits = PORT_ISC_RISING_gc; // b001, RISING - } - else if(mode == FALLING) - { - iModeBits = PORT_ISC_FALLING_gc; // b010, FALLING - } - else - { - iModeBits = PORT_ISC_BOTHEDGES_gc; // BOTH (the default - note INTPUT_DISABLED (sic) won't buffer the input, so it's useless except for analog channels) - } - - if(iInv) - { - iModeBits |= _BV(PORT_INVEN_bp); // set the 'inverted' bit - } - - oldSREG = SREG; // store the interrupt flag basically - - cli(); // disable interrupts for a bit - - intFunc[interruptNum] = userFunc; - intPins[interruptNum] = iPinBits; // save what pins I used - - // Enable the interrupt (smaller code to use if/else and pointer) - - iNum = 0; - if(interruptNum == PORTA_INT0 -#ifdef PORTA_INT1 - || interruptNum == PORTA_INT1 -#endif // PORTA_INT1 - ) - { - port = &PORTA; -#ifdef PORTA_INT1 - if(interruptNum == PORTA_INT1) - { - iNum = 1; - } -#endif // PORTA_INT1 - } -#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */ - else if(interruptNum == PORTB_INT0 -#ifdef PORTB_INT1 - || interruptNum == PORTB_INT1 -#endif // PORTB_INT1 - ) - { - port = &PORTB; -#ifdef PORTB_INT1 - if(interruptNum == PORTB_INT1) - { - iNum = 1; - } -#endif // PORTB_INT1 - } -#endif // NUM_ANALOG_PINS > 8 - else if(interruptNum == PORTC_INT0 -#ifdef PORTC_INT1 - || interruptNum == PORTC_INT1 -#endif // PORTC_INT1 - ) - { - port = &PORTC; -#ifdef PORTC_INT1 - if(interruptNum == PORTC_INT1) - { - iNum = 1; - } -#endif // PORTC_INT1 - } - else if(interruptNum == PORTD_INT0 -#ifdef PORTD_INT1 - || interruptNum == PORTD_INT1 -#endif // PORTD_INT1 - ) - { - port = &PORTD; -#ifdef PORTD_INT1 - if(interruptNum == PORTD_INT1) - { - iNum = 1; - } -#endif // PORTC_INT1 - } -#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */ - else if(interruptNum == PORTE_INT0 -#ifdef PORTE_INT1 - || interruptNum == PORTE_INT1 -#endif // PORTE_INT1 - ) - { - port = &PORTE; -#ifdef PORTE_INT1 - if(interruptNum == PORTE_INT1) - { - iNum = 1; - } -#endif // PORTE_INT1 - } -#endif // NUM_DIGITAL_PINS > 18 - else if(interruptNum == PORTR_INT0 -#ifdef PORTR_INT1 - || interruptNum == PORTR_INT1 -#endif // PORTR_INT1 - ) - { - port = &PORTR; -#ifdef PORTR_INT1 - if(interruptNum == PORTR_INT1) - { - iNum = 1; - } -#endif // PORTR_INT1 - } - else - { - return; // do nothing - } - - // On certain processors there's only one interrupt, so it's called 'INTMASK' - // we test for this here - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - if(!iNum) - { - // set interrupt mask for PORT A, int 0 vector - port->INTMASK |= iPinBits; // enable int zero for these pins - port->INTCTRL = (port->INTCTRL & ~(PORT_INTLVL_gm)) - | (iPriBits & 3); - } -#else // INT0MASK and INT1MASK supported - if(!iNum) - { - // set interrupt mask for PORT A, int 0 vector - port->INT0MASK |= iPinBits; // enable int zero for these pins - port->INTCTRL = (port->INTCTRL & ~(PORT_INT0LVL_gm)) - | (iPriBits & 3); - } - else // if(iNum == 1) - { - port->INT1MASK |= iPinBits; // enable int zero for these pins - port->INTCTRL = (port->INTCTRL & ~(PORT_INT1LVL_gm)) - | ((iPriBits & 3) << PORT_INT1LVL_gp); - } -#endif // INT0MASK and INT1MASK supported - - for(iNum=0, iMask = 1; iNum < 8; iNum++, iMask <<= 1) - { - register8_t *pCTRL = &(port->PIN0CTRL) + iNum; // treat PIN0CTRL through PIN7CTRL as an array - - // set corresponding 'type' in the interrupt control regs for the individual bits - - if(iPinBits & iMask) // is this bit set in 'iPinBits'? - { - // enable the interrupt pin's mode bits and assign the 'invert' flag as needed - - *pCTRL = (*pCTRL & ~(PORT_ISC_gm | PORT_INVEN_bm)) - | iModeBits; - } - } - - SREG = oldSREG; // restore it, interrupts (probably) re-enabled - // NOTE that this may throw an interrupt right away -} - - - -void detachInterrupt(uint8_t interruptNum) -{ -uint8_t iPinBits, iNum, iMask; -uint8_t oldSREG; -PORT_t *port; - - - // NOTE: this function will turn OFF the 'invert' bit if it's set for a HIGH level interrupt - // and digitalRead _SHOULD_ be consistent before/after this call. - - if(interruptNum >= EXTERNAL_NUM_INTERRUPTS) - { - return; - } - - oldSREG = SREG; // keep track of interrupt flag state - - cli(); // clear the interrupt flag - - // grab 'pin bits' so I know what to flip around - iPinBits = intPins[interruptNum]; // what I used when I added it - - intFunc[interruptNum] = 0; - intPins[interruptNum] = 0; // zero both of these - - // disable the interrupt - - // Enable the interrupt (smaller code to use if/else and pointer) - - iNum = 0; - if(interruptNum == PORTA_INT0 -#ifdef PORTA_INT1 - || interruptNum == PORTA_INT1 -#endif // PORTA_INT1 - ) - { - port = &PORTA; -#ifdef PORTA_INT1 - if(interruptNum == PORTA_INT1) - { - iNum = 1; - } -#endif // PORTA_INT1 - } -#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */ - else if(interruptNum == PORTB_INT0 -#ifdef PORTB_INT1 - || interruptNum == PORTB_INT1 -#endif // PORTB_INT1 - ) - { - port = &PORTB; -#ifdef PORTB_INT1 - if(interruptNum == PORTB_INT1) - { - iNum = 1; - } -#endif // PORTB_INT1 - } -#endif // NUM_ANALOG_PINS > 8 - else if(interruptNum == PORTC_INT0 -#ifdef PORTC_INT1 - || interruptNum == PORTC_INT1 -#endif // PORTC_INT1 - ) - { - port = &PORTC; -#ifdef PORTC_INT1 - if(interruptNum == PORTC_INT1) - { - iNum = 1; - } -#endif // PORTC_INT1 - } - else if(interruptNum == PORTD_INT0 -#ifdef PORTD_INT1 - || interruptNum == PORTD_INT1 -#endif // PORTD_INT1 - ) - { - port = &PORTD; -#ifdef PORTD_INT1 - if(interruptNum == PORTD_INT1) - { - iNum = 1; - } -#endif // PORTD_INT1 - } -#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */ - else if(interruptNum == PORTE_INT0 -#ifdef PORTE_INT1 - || interruptNum == PORTE_INT1 -#endif // PORTE_INT1 - ) - { - port = &PORTE; -#ifdef PORTE_INT1 - if(interruptNum == PORTE_INT1) - { - iNum = 1; - } -#endif // PORTE_INT1 - } -#endif // NUM_DIGITAL_PINS > 18 - else if(interruptNum == PORTR_INT0 -#ifdef PORTR_INT1 - || interruptNum == PORTR_INT1 -#endif // PORTR_INT1 - ) - { - port = &PORTR; -#ifdef PORTR_INT1 - if(interruptNum == PORTR_INT1) - { - iNum = 1; - } -#endif // PORTR_INT1 - } - else - { - return; // do nothing - } - - // On certain processors there's only one interrupt, so it's called 'INTMASK' - // we test for this here - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - if(!iNum) - { - // set interrupt mask for PORT A, int 0 vector - port->INTMASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ? - port->INTCTRL &= ~(PORT_INTLVL_gm); // set interrupt control to 'OFF' - port->INTFLAGS = _BV(0); // clear the int flag - -#else // INT0MASK and INT1MASK supported - if(!iNum) - { - // set interrupt mask for PORT A, int 0 vector - port->INT0MASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ? - port->INTCTRL &= ~(PORT_INT0LVL_gm); // set interrupt control to 'OFF' - port->INTFLAGS = _BV(0); // clear the int 0 flag - } - else // if(iNum == 1) - { -#endif // INT0MASK and INT1MASK supported - // if this matches a CTS port, I do _NOT_ want to disable interrupts -#if defined(SERIAL_0_CTS_ENABLED) && defined(SERIAL_1_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == port) - { -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - if(SERIAL_1_CTS_PORT == port) - { - port->INTMASK = SERIAL_0_CTS_PIN | SERIAL_1_CTS_PIN; // disable interrupts but leave BOTH enabled - } - else - { - port->INTMASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled - } - - port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this -#else // INT0MASK and INT1MASK supported - if(SERIAL_1_CTS_PORT == port) - { - port->INT1MASK = SERIAL_0_CTS_PIN | SERIAL_1_CTS_PIN; // disable interrupts but leave BOTH enabled - } - else - { - port->INT1MASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled - } - - port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this -#endif // INT0MASK and INT1MASK supported - } - else if(SERIAL_1_CTS_PORT == port) - { -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - port->INTMASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this -#else // INT0MASK and INT1MASK supported - port->INT1MASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this -#endif // INT0MASK and INT1MASK supported - } -#elif defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == port) - { -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - port->INTMASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this -#else // INT0MASK and INT1MASK supported - port->INT1MASK = SERIAL_0_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this -#endif // INT0MASK and INT1MASK supported - } -#elif defined(SERIAL_1_CTS_ENABLED) - if(SERIAL_1_CTS_PORT == port) - { -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - port->INTMASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INTLVL_gm; // max priority when I do this -#else // INT0MASK and INT1MASK supported - port->INT1MASK = SERIAL_1_CTS_PIN; // disable interrupts but leave THIS one enabled - - port->INTCTRL |= PORT_INT1LVL_gm; // max priority when I do this -#endif // INT0MASK and INT1MASK supported - } -#endif // SERIAL_0/1_CTS_ENABLED - -#if defined(SERIAL_0_CTS_ENABLED) || defined(SERIAL_1_CTS_ENABLED) - else -#endif // SERIAL_0/1_CTS_ENABLED - - { -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - port->INTMASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ? - port->INTCTRL &= ~(PORT_INTLVL_gm); // set interrupt control to 'OFF' -#else // INT0MASK and INT1MASK supported - port->INT1MASK = 0; // disable interrupts - TODO, read this instead of 'iPinBits' ? - port->INTCTRL &= ~(PORT_INT1LVL_gm); // set interrupt control to 'OFF' -#endif // INT0MASK and INT1MASK supported - } - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ - port->INTFLAGS = _BV(0); // clear the int 0 flag -#else // INT0MASK and INT1MASK supported - port->INTFLAGS = _BV(1); // clear the int 1 flag -#endif // INT0MASK and INT1MASK supported - } - - for(iNum=0, iMask = 1; iNum < 8; iNum++, iMask <<= 1) - { - register8_t *pCTRL = &(port->PIN0CTRL) + iNum; // treat PIN0CTRL through PIN7CTRL as an array - - // set corresponding 'type' in the interrupt control regs for the individual bits - - if(iPinBits & iMask) // is this bit set in 'iPinBits'? - { - *pCTRL &= ~(PORT_ISC_gm | PORT_INVEN_bm); // turn off invert flag and reset to 'BOTH' (the default) - } - } - - SREG = oldSREG; // restore it, interrupts (probably) re-enabled - -} - - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ -ISR(PORTA_INT_vect) -#else // INT0MASK and INT1MASK supported -ISR(PORTA_INT0_vect) -#endif // INT0MASK and INT1MASK supported -{ - if(intFunc[PORTA_INT0]) - intFunc[PORTA_INT0](); - -#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported -} - -ISR(PORTA_INT1_vect) -{ - if(intFunc[PORTA_INT1]) - intFunc[PORTA_INT1](); -#endif // INT0MASK and INT1MASK supported - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTA)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTA)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} - -#if NUM_ANALOG_PINS > 8 /* which means we have PORT B */ -ISR(PORTB_INT0_vect) -{ - if(intFunc[PORTB_INT0]) - intFunc[PORTB_INT0](); -} - -ISR(PORTB_INT1_vect) -{ - if(intFunc[PORTB_INT1]) - intFunc[PORTB_INT1](); - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTB)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTB)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} -#endif // NUM_ANALOG_PINS > 8 - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ -ISR(PORTC_INT_vect) -#else // INT0MASK and INT1MASK supported -ISR(PORTC_INT0_vect) -#endif // INT0MASK and INT1MASK supported -{ - if(intFunc[PORTC_INT0]) - intFunc[PORTC_INT0](); -#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported -} - -ISR(PORTC_INT1_vect) -{ - if(intFunc[PORTC_INT1]) - intFunc[PORTC_INT1](); -#endif // INT0MASK and INT1MASK supported - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTC)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTC)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ -ISR(PORTD_INT_vect) -#else // INT0MASK and INT1MASK supported -ISR(PORTD_INT0_vect) -#endif // INT0MASK and INT1MASK supported -{ - if(intFunc[PORTD_INT0]) - intFunc[PORTD_INT0](); -#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported -} - -ISR(PORTD_INT1_vect) -{ - if(intFunc[PORTD_INT1]) - intFunc[PORTD_INT1](); -#endif // INT0MASK and INT1MASK supported - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTD)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTD)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} - - -#if NUM_DIGITAL_PINS > 18 /* which means we have PORT E */ -ISR(PORTE_INT0_vect) -{ - if(intFunc[PORTE_INT0]) - intFunc[PORTE_INT0](); -} - -ISR(PORTE_INT1_vect) -{ - if(intFunc[PORTE_INT1]) - intFunc[PORTE_INT1](); - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTE)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTE)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} -#endif // NUM_DIGITAL_PINS > 18 - -// TODO: ISRs for PORTF, PORTH, PORTJ, PORTK, PORTQ - -#ifndef PORTC_INT0MASK /* meaning there's only one int vector and not two */ -ISR(PORTR_INT_vect) -#else // INT0MASK and INT1MASK supported -ISR(PORTR_INT0_vect) -#endif // INT0MASK and INT1MASK supported -{ - if(intFunc[PORTR_INT0]) - intFunc[PORTR_INT0](); -#ifdef PORTC_INT0MASK // INT0MASK and INT1MASK supported -} - -ISR(PORTR_INT1_vect) -{ - if(intFunc[PORTR_INT1]) - intFunc[PORTR_INT1](); -#endif // INT0MASK and INT1MASK supported - -#if defined(SERIAL_0_CTS_ENABLED) - if(SERIAL_0_CTS_PORT == &(PORTR)) // this should compile as a constant expression - { - serial_0_cts_callback(); - } -#endif // SERIAL_0_CTS_ENABLED - -#ifdef SERIAL_1_CTS_ENABLED - if(SERIAL_1_CTS_PORT == &(PORTR)) - { - serial_1_cts_callback(); - } -#endif // SERIAL_1_CTS_ENABLED -} - - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp b/BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp deleted file mode 100644 index 2120c4c..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- 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 - Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/ - - 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 - - $Id$ -*/ - -extern "C" { - #include "stdlib.h" -} - -void randomSeed(unsigned int seed) -{ - if (seed != 0) { - srandom(seed); - } -} - -long random(long howbig) -{ - if (howbig == 0) { - return 0; - } - return random() % howbig; -} - -long random(long howsmall, long howbig) -{ - if (howsmall >= howbig) { - return howsmall; - } - long diff = howbig - howsmall; - return random(diff) + howsmall; -} - -long map(long x, long in_min, long in_max, long out_min, long out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -unsigned int makeWord(unsigned int w) { return w; } -unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; } \ No newline at end of file diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp b/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp deleted file mode 100644 index ed880ce..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp +++ /dev/null @@ -1,744 +0,0 @@ -/* - WString.cpp - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.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 -*/ - -#include "WString.h" - -/*********************************************/ -/* Constructors */ -/*********************************************/ - -String::String(const char *cstr) -{ - init(); - if (cstr) copy(cstr, strlen(cstr)); -} - -String::String(const String &value) -{ - init(); - *this = value; -} - -String::String(const __FlashStringHelper *pstr) -{ - init(); - *this = pstr; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String::String(String &&rval) -{ - init(); - move(rval); -} -String::String(StringSumHelper &&rval) -{ - init(); - move(rval); -} -#endif - -String::String(char c) -{ - 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; -} - -String::String(int value, unsigned char base) -{ - 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; -} - -String::String(long value, unsigned char base) -{ - 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; -} - -String::String(float value, unsigned char decimalPlaces) -{ - 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); -} - -String::~String() -{ - free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 0; -} - -void String::invalidate(void) -{ - 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; -} - -unsigned char String::changeBuffer(unsigned int maxStrLen) -{ - 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) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; -} - -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; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -void String::move(String &rhs) -{ - if (buffer) { - if (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) -{ - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String & String::operator = (String &&rval) -{ - if (this != &rval) move(rval); - return *this; -} - -String & String::operator = (StringSumHelper &&rval) -{ - if (this != &rval) move(rval); - return *this; -} -#endif - -String & String::operator = (const char *cstr) -{ - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; -} - -String & String::operator = (const __FlashStringHelper *pstr) -{ - if (pstr) copy(pstr, strlen_P((PGM_P)pstr)); - else invalidate(); - - return *this; -} - -/*********************************************/ -/* concat */ -/*********************************************/ - -unsigned char String::concat(const String &s) -{ - 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 char String::concat(const char *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); -} - -unsigned char String::concat(unsigned char num) -{ - 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)); -} - -unsigned char String::concat(unsigned int num) -{ - 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)); -} - -unsigned char String::concat(unsigned long num) -{ - 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)); -} - -unsigned char String::concat(double num) -{ - char buf[20]; - char* string = dtostrf(num, 4, 2, buf); - return concat(string, strlen(string)); -} - -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; -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -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 & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, float num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, double num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs)) a.invalidate(); - return a; -} - -/*********************************************/ -/* Comparison */ -/*********************************************/ - -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); -} - -unsigned char String::equals(const String &s2) const -{ - 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; -} - -unsigned char String::operator<(const String &rhs) const -{ - return compareTo(rhs) < 0; -} - -unsigned char String::operator>(const String &rhs) const -{ - return compareTo(rhs) > 0; -} - -unsigned char String::operator<=(const String &rhs) const -{ - return compareTo(rhs) <= 0; -} - -unsigned char String::operator>=(const String &rhs) const -{ - return compareTo(rhs) >= 0; -} - -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; -} - -unsigned char String::startsWith( const String &s2 ) const -{ - if (len < s2.len) return 0; - return startsWith(s2, 0); -} - -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; -} - -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; -} - -/*********************************************/ -/* Character Access */ -/*********************************************/ - -char String::charAt(unsigned int loc) const -{ - return operator[](loc); -} - -void String::setCharAt(unsigned int loc, char c) -{ - if (loc < len) buffer[loc] = c; -} - -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]; -} - -char String::operator[]( unsigned int index ) const -{ - 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; -} - -/*********************************************/ -/* Search */ -/*********************************************/ - -int String::indexOf(char c) const -{ - return indexOf(c, 0); -} - -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; -} - -int String::indexOf(const String &s2) const -{ - 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; -} - -int String::lastIndexOf( char theChar ) const -{ - 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; -} - -int String::lastIndexOf(const String &s2) const -{ - 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; -} - -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; -} - -/*********************************************/ -/* Modification */ -/*********************************************/ - -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){ - if (index >= len) { return; } - int count = len - index; - remove(index, count); -} - -void String::remove(unsigned int index, unsigned int count){ - if (index >= len) { return; } - if (count <= 0) { return; } - if (index + count > len) { 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); - } -} - -void String::toUpperCase(void) -{ - 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; -} - -/*********************************************/ -/* Parsing / Conversion */ -/*********************************************/ - -long String::toInt(void) const -{ - if (buffer) return atol(buffer); - return 0; -} - -float String::toFloat(void) const -{ - if (buffer) return float(atof(buffer)); - return 0; -} diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WString.h b/BootLoaders/Boards/orangerx/cores/xmega/WString.h deleted file mode 100644 index 7402430..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/WString.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - WString.h - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.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 -*/ - -#ifndef String_class_h -#define String_class_h -#ifdef __cplusplus - -#include -#include -#include -#include - -// When compiling programs with this class, the following gcc parameters -// dramatically increase performance and memory (RAM) efficiency, typically -// with little or no increase in code size. -// -felide-constructors -// -std=c++0x - -class __FlashStringHelper; -#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) - -// An inherited class for holding the result of a concatenation. These -// result objects are assumed to be writable by subsequent concatenations. -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); - #ifdef __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); - #ifdef __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; } - - // 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; - -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); - #ifdef __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) {} -}; - -#endif // __cplusplus -#endif // String_class_h diff --git a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c deleted file mode 100644 index 4cd765f..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c +++ /dev/null @@ -1,267 +0,0 @@ -/* Copyright (c) 2002, 2004, 2010 Joerg Wunsch - Copyright (c) 2010 Gerben van den Broeke - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - - -/* $Id: malloc.c 2149 2010-06-09 20:45:37Z joerg_wunsch $ */ - -#include -#include "sectionname.h" -#include "stdlib_private.h" - -#include - -/* - * Exported interface: - * - * When extending the data segment, the allocator will not try to go - * beyond the current stack limit, decreased by __malloc_margin bytes. - * Thus, all possible stack frames of interrupt routines that could - * interrupt the current function, plus all further nested function - * calls must not require more stack space, or they'll risk to collide - * with the data segment. - */ - -/* May be changed by the user only before the first malloc() call. */ - -size_t __malloc_margin = 128; -char *__malloc_heap_start = &__heap_start; -char *__malloc_heap_end = &__heap_end; - -char *__brkval; -struct __freelist *__flp; - -ATTRIBUTE_CLIB_SECTION -void * -malloc(size_t len) -{ - struct __freelist *fp1, *fp2, *sfp1=NULL, *sfp2=NULL; // BBB - added '=NULL' for sfp1, sfp2 as they were warned as being uninitialized - char *cp; - size_t s, avail; - - /* - * Our minimum chunk size is the size of a pointer (plus the - * size of the "sz" field, but we don't need to account for - * this), otherwise we could not possibly fit a freelist entry - * into the chunk later. - */ - if (len < sizeof(struct __freelist) - sizeof(size_t)) - len = sizeof(struct __freelist) - sizeof(size_t); - - /* - * First, walk the free list and try finding a chunk that - * would match exactly. If we found one, we are done. While - * walking, note down the smallest chunk we found that would - * still fit the request -- we need it for step 2. - * - */ - for (s = 0, fp1 = __flp, fp2 = 0; - fp1; - fp2 = fp1, fp1 = fp1->nx) { - if (fp1->sz < len) - continue; - if (fp1->sz == len) { - /* - * Found it. Disconnect the chunk from the - * freelist, and return it. - */ - if (fp2) - fp2->nx = fp1->nx; - else - __flp = fp1->nx; - return &(fp1->nx); - } - else { - if (s == 0 || fp1->sz < s) { - /* this is the smallest chunk found so far */ - s = fp1->sz; - sfp1 = fp1; - sfp2 = fp2; - } - } - } - /* - * Step 2: If we found a chunk on the freelist that would fit - * (but was too large), look it up again and use it, since it - * is our closest match now. Since the freelist entry needs - * to be split into two entries then, watch out that the - * difference between the requested size and the size of the - * chunk found is large enough for another freelist entry; if - * not, just enlarge the request size to what we have found, - * and use the entire chunk. - */ - if (s) { - if (s - len < sizeof(struct __freelist)) { - /* Disconnect it from freelist and return it. */ - if (sfp2) - sfp2->nx = sfp1->nx; - else - __flp = sfp1->nx; - return &(sfp1->nx); - } - /* - * Split them up. Note that we leave the first part - * as the new (smaller) freelist entry, and return the - * upper portion to the caller. This saves us the - * work to fix up the freelist chain; we just need to - * fixup the size of the current entry, and note down - * the size of the new chunk before returning it to - * the caller. - */ - cp = (char *)sfp1; - s -= len; - cp += s; - sfp2 = (struct __freelist *)cp; - sfp2->sz = len; - sfp1->sz = s - sizeof(size_t); - return &(sfp2->nx); - } - /* - * Step 3: If the request could not be satisfied from a - * freelist entry, just prepare a new chunk. This means we - * need to obtain more memory first. The largest address just - * not allocated so far is remembered in the brkval variable. - * Under Unix, the "break value" was the end of the data - * segment as dynamically requested from the operating system. - * Since we don't have an operating system, just make sure - * that we don't collide with the stack. - */ - if (__brkval == 0) - __brkval = __malloc_heap_start; - cp = __malloc_heap_end; - if (cp == 0) - cp = STACK_POINTER() - __malloc_margin; - if (cp <= __brkval) - /* - * Memory exhausted. - */ - return 0; - avail = cp - __brkval; - /* - * Both tests below are needed to catch the case len >= 0xfffe. - */ - if (avail >= len && avail >= len + sizeof(size_t)) { - fp1 = (struct __freelist *)__brkval; - __brkval += len + sizeof(size_t); - fp1->sz = len; - return &(fp1->nx); - } - /* - * Step 4: There's no help, just fail. :-/ - */ - return 0; -} - - -ATTRIBUTE_CLIB_SECTION -void -free(void *p) -{ - struct __freelist *fp1, *fp2, *fpnew; - char *cp1, *cp2, *cpnew; - - /* ISO C says free(NULL) must be a no-op */ - if (p == 0) - return; - - cpnew = p; - cpnew -= sizeof(size_t); - fpnew = (struct __freelist *)cpnew; - fpnew->nx = 0; - - /* - * Trivial case first: if there's no freelist yet, our entry - * will be the only one on it. If this is the last entry, we - * can reduce __brkval instead. - */ - if (__flp == 0) { - if ((char *)p + fpnew->sz == __brkval) - __brkval = cpnew; - else - __flp = fpnew; - return; - } - - /* - * Now, find the position where our new entry belongs onto the - * freelist. Try to aggregate the chunk with adjacent chunks - * if possible. - */ - for (fp1 = __flp, fp2 = 0; - fp1; - fp2 = fp1, fp1 = fp1->nx) { - if (fp1 < fpnew) - continue; - cp1 = (char *)fp1; - fpnew->nx = fp1; - if ((char *)&(fpnew->nx) + fpnew->sz == cp1) { - /* upper chunk adjacent, assimilate it */ - fpnew->sz += fp1->sz + sizeof(size_t); - fpnew->nx = fp1->nx; - } - if (fp2 == 0) { - /* new head of freelist */ - __flp = fpnew; - return; - } - break; - } - /* - * Note that we get here either if we hit the "break" above, - * or if we fell off the end of the loop. The latter means - * we've got a new topmost chunk. Either way, try aggregating - * with the lower chunk if possible. - */ - fp2->nx = fpnew; - cp2 = (char *)&(fp2->nx); - if (cp2 + fp2->sz == cpnew) { - /* lower junk adjacent, merge */ - fp2->sz += fpnew->sz + sizeof(size_t); - fp2->nx = fpnew->nx; - } - /* - * If there's a new topmost chunk, lower __brkval instead. - */ - for (fp1 = __flp, fp2 = 0; - fp1->nx != 0; - fp2 = fp1, fp1 = fp1->nx) - /* advance to entry just before end of list */; - cp2 = (char *)&(fp1->nx); - if (cp2 + fp1->sz == __brkval) { - if (fp2 == NULL) - /* Freelist is empty now. */ - __flp = NULL; - else - fp2->nx = NULL; - __brkval = cp2 - sizeof(size_t); - } -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c deleted file mode 100644 index 4ba546c..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (c) 2004, 2010 Joerg Wunsch - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ -/* $Id: realloc.c 2127 2010-06-07 14:49:37Z joerg_wunsch $ */ - -#include -#include -#include "sectionname.h" -#include "stdlib_private.h" - -#include - -ATTRIBUTE_CLIB_SECTION -void * -realloc(void *ptr, size_t len) -{ - struct __freelist *fp1, *fp2, *fp3, *ofp3; - char *cp, *cp1; - void *memp; - size_t s, incr; - - /* Trivial case, required by C standard. */ - if (ptr == 0) - return malloc(len); - - cp1 = (char *)ptr; - cp1 -= sizeof(size_t); - fp1 = (struct __freelist *)cp1; - - cp = (char *)ptr + len; /* new next pointer */ - if (cp < cp1) - /* Pointer wrapped across top of RAM, fail. */ - return 0; - - /* - * See whether we are growing or shrinking. When shrinking, - * we split off a chunk for the released portion, and call - * free() on it. Therefore, we can only shrink if the new - * size is at least sizeof(struct __freelist) smaller than the - * previous size. - */ - if (len <= fp1->sz) { - /* The first test catches a possible unsigned int - * rollover condition. */ - if (fp1->sz <= sizeof(struct __freelist) || - len > fp1->sz - sizeof(struct __freelist)) - return ptr; - fp2 = (struct __freelist *)cp; - fp2->sz = fp1->sz - len - sizeof(size_t); - fp1->sz = len; - free(&(fp2->nx)); - return ptr; - } - - /* - * If we get here, we are growing. First, see whether there - * is space in the free list on top of our current chunk. - */ - incr = len - fp1->sz; - cp = (char *)ptr + fp1->sz; - fp2 = (struct __freelist *)cp; - for (s = 0, ofp3 = 0, fp3 = __flp; - fp3; - ofp3 = fp3, fp3 = fp3->nx) { - if (fp3 == fp2 && fp3->sz + sizeof(size_t) >= incr) { - /* found something that fits */ - if (fp3->sz + sizeof(size_t) - incr > sizeof(struct __freelist)) { - /* split off a new freelist entry */ - cp = (char *)ptr + len; - fp2 = (struct __freelist *)cp; - fp2->nx = fp3->nx; - fp2->sz = fp3->sz - incr; - fp1->sz = len; - } else { - /* it just fits, so use it entirely */ - fp1->sz += fp3->sz + sizeof(size_t); - fp2 = fp3->nx; - } - if (ofp3) - ofp3->nx = fp2; - else - __flp = fp2; - return ptr; - } - /* - * Find the largest chunk on the freelist while - * walking it. - */ - if (fp3->sz > s) - s = fp3->sz; - } - /* - * If we are the topmost chunk in memory, and there was no - * large enough chunk on the freelist that could be re-used - * (by a call to malloc() below), quickly extend the - * allocation area if possible, without need to copy the old - * data. - */ - if (__brkval == (char *)ptr + fp1->sz && len > s) { - cp1 = __malloc_heap_end; - cp = (char *)ptr + len; - if (cp1 == 0) - cp1 = STACK_POINTER() - __malloc_margin; - if (cp < cp1) { - __brkval = cp; - fp1->sz = len; - return ptr; - } - /* If that failed, we are out of luck. */ - return 0; - } - - /* - * Call malloc() for a new chunk, then copy over the data, and - * release the old region. - */ - if ((memp = malloc(len)) == 0) - return 0; - memcpy(memp, ptr, fp1->sz); - free(ptr); - return memp; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/sectionname.h b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/sectionname.h deleted file mode 100644 index 8e0f448..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/sectionname.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2009 Atmel Corporation - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef __SECTIONNAME_H__ -#define __SECTIONNAME_H__ - -/* Put all avr-libc functions in a common, unique sub-section name under .text. */ - -#define CLIB_SECTION .text.avr-libc -#define MLIB_SECTION .text.avr-libc.fplib - -#define STR(x) _STR(x) -#define _STR(x) #x - -#define ATTRIBUTE_CLIB_SECTION __attribute__ ((section (STR(CLIB_SECTION)))) -#define ATTRIBUTE_MLIB_SECTION __attribute__ ((section (STR(MLIB_SECTION)))) - -#define ASSEMBLY_CLIB_SECTION .section CLIB_SECTION, "ax", @progbits -#define ASSEMBLY_MLIB_SECTION .section MLIB_SECTION, "ax", @progbits - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/stdlib_private.h b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/stdlib_private.h deleted file mode 100644 index acc72c5..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/stdlib_private.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2004, Joerg Wunsch - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holders nor the names of - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -/* $Id: stdlib_private.h 1657 2008-03-24 17:11:08Z arcanum $ */ - -#include -#include -#include - -#if !defined(__DOXYGEN__) - -struct __freelist { - size_t sz; - struct __freelist *nx; -}; - -#endif - -extern char *__brkval; /* first location not yet allocated */ -extern struct __freelist *__flp; /* freelist pointer (head of freelist) */ -extern size_t __malloc_margin; /* user-changeable before the first malloc() */ -extern char *__malloc_heap_start; -extern char *__malloc_heap_end; - -extern char __heap_start; -extern char __heap_end; - -/* Needed for definition of AVR_STACK_POINTER_REG. */ -#include - -#define STACK_POINTER() ((char *)AVR_STACK_POINTER_REG) - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/binary.h b/BootLoaders/Boards/orangerx/cores/xmega/binary.h deleted file mode 100644 index aec4c73..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/binary.h +++ /dev/null @@ -1,534 +0,0 @@ -/* - binary.h - Definitions for binary constants - Copyright (c) 2006 David A. Mellis. 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 -*/ - -#ifndef Binary_h -#define Binary_h - -#define B0 0 -#define B00 0 -#define B000 0 -#define B0000 0 -#define B00000 0 -#define B000000 0 -#define B0000000 0 -#define B00000000 0 -#define B1 1 -#define B01 1 -#define B001 1 -#define B0001 1 -#define B00001 1 -#define B000001 1 -#define B0000001 1 -#define B00000001 1 -#define B10 2 -#define B010 2 -#define B0010 2 -#define B00010 2 -#define B000010 2 -#define B0000010 2 -#define B00000010 2 -#define B11 3 -#define B011 3 -#define B0011 3 -#define B00011 3 -#define B000011 3 -#define B0000011 3 -#define B00000011 3 -#define B100 4 -#define B0100 4 -#define B00100 4 -#define B000100 4 -#define B0000100 4 -#define B00000100 4 -#define B101 5 -#define B0101 5 -#define B00101 5 -#define B000101 5 -#define B0000101 5 -#define B00000101 5 -#define B110 6 -#define B0110 6 -#define B00110 6 -#define B000110 6 -#define B0000110 6 -#define B00000110 6 -#define B111 7 -#define B0111 7 -#define B00111 7 -#define B000111 7 -#define B0000111 7 -#define B00000111 7 -#define B1000 8 -#define B01000 8 -#define B001000 8 -#define B0001000 8 -#define B00001000 8 -#define B1001 9 -#define B01001 9 -#define B001001 9 -#define B0001001 9 -#define B00001001 9 -#define B1010 10 -#define B01010 10 -#define B001010 10 -#define B0001010 10 -#define B00001010 10 -#define B1011 11 -#define B01011 11 -#define B001011 11 -#define B0001011 11 -#define B00001011 11 -#define B1100 12 -#define B01100 12 -#define B001100 12 -#define B0001100 12 -#define B00001100 12 -#define B1101 13 -#define B01101 13 -#define B001101 13 -#define B0001101 13 -#define B00001101 13 -#define B1110 14 -#define B01110 14 -#define B001110 14 -#define B0001110 14 -#define B00001110 14 -#define B1111 15 -#define B01111 15 -#define B001111 15 -#define B0001111 15 -#define B00001111 15 -#define B10000 16 -#define B010000 16 -#define B0010000 16 -#define B00010000 16 -#define B10001 17 -#define B010001 17 -#define B0010001 17 -#define B00010001 17 -#define B10010 18 -#define B010010 18 -#define B0010010 18 -#define B00010010 18 -#define B10011 19 -#define B010011 19 -#define B0010011 19 -#define B00010011 19 -#define B10100 20 -#define B010100 20 -#define B0010100 20 -#define B00010100 20 -#define B10101 21 -#define B010101 21 -#define B0010101 21 -#define B00010101 21 -#define B10110 22 -#define B010110 22 -#define B0010110 22 -#define B00010110 22 -#define B10111 23 -#define B010111 23 -#define B0010111 23 -#define B00010111 23 -#define B11000 24 -#define B011000 24 -#define B0011000 24 -#define B00011000 24 -#define B11001 25 -#define B011001 25 -#define B0011001 25 -#define B00011001 25 -#define B11010 26 -#define B011010 26 -#define B0011010 26 -#define B00011010 26 -#define B11011 27 -#define B011011 27 -#define B0011011 27 -#define B00011011 27 -#define B11100 28 -#define B011100 28 -#define B0011100 28 -#define B00011100 28 -#define B11101 29 -#define B011101 29 -#define B0011101 29 -#define B00011101 29 -#define B11110 30 -#define B011110 30 -#define B0011110 30 -#define B00011110 30 -#define B11111 31 -#define B011111 31 -#define B0011111 31 -#define B00011111 31 -#define B100000 32 -#define B0100000 32 -#define B00100000 32 -#define B100001 33 -#define B0100001 33 -#define B00100001 33 -#define B100010 34 -#define B0100010 34 -#define B00100010 34 -#define B100011 35 -#define B0100011 35 -#define B00100011 35 -#define B100100 36 -#define B0100100 36 -#define B00100100 36 -#define B100101 37 -#define B0100101 37 -#define B00100101 37 -#define B100110 38 -#define B0100110 38 -#define B00100110 38 -#define B100111 39 -#define B0100111 39 -#define B00100111 39 -#define B101000 40 -#define B0101000 40 -#define B00101000 40 -#define B101001 41 -#define B0101001 41 -#define B00101001 41 -#define B101010 42 -#define B0101010 42 -#define B00101010 42 -#define B101011 43 -#define B0101011 43 -#define B00101011 43 -#define B101100 44 -#define B0101100 44 -#define B00101100 44 -#define B101101 45 -#define B0101101 45 -#define B00101101 45 -#define B101110 46 -#define B0101110 46 -#define B00101110 46 -#define B101111 47 -#define B0101111 47 -#define B00101111 47 -#define B110000 48 -#define B0110000 48 -#define B00110000 48 -#define B110001 49 -#define B0110001 49 -#define B00110001 49 -#define B110010 50 -#define B0110010 50 -#define B00110010 50 -#define B110011 51 -#define B0110011 51 -#define B00110011 51 -#define B110100 52 -#define B0110100 52 -#define B00110100 52 -#define B110101 53 -#define B0110101 53 -#define B00110101 53 -#define B110110 54 -#define B0110110 54 -#define B00110110 54 -#define B110111 55 -#define B0110111 55 -#define B00110111 55 -#define B111000 56 -#define B0111000 56 -#define B00111000 56 -#define B111001 57 -#define B0111001 57 -#define B00111001 57 -#define B111010 58 -#define B0111010 58 -#define B00111010 58 -#define B111011 59 -#define B0111011 59 -#define B00111011 59 -#define B111100 60 -#define B0111100 60 -#define B00111100 60 -#define B111101 61 -#define B0111101 61 -#define B00111101 61 -#define B111110 62 -#define B0111110 62 -#define B00111110 62 -#define B111111 63 -#define B0111111 63 -#define B00111111 63 -#define B1000000 64 -#define B01000000 64 -#define B1000001 65 -#define B01000001 65 -#define B1000010 66 -#define B01000010 66 -#define B1000011 67 -#define B01000011 67 -#define B1000100 68 -#define B01000100 68 -#define B1000101 69 -#define B01000101 69 -#define B1000110 70 -#define B01000110 70 -#define B1000111 71 -#define B01000111 71 -#define B1001000 72 -#define B01001000 72 -#define B1001001 73 -#define B01001001 73 -#define B1001010 74 -#define B01001010 74 -#define B1001011 75 -#define B01001011 75 -#define B1001100 76 -#define B01001100 76 -#define B1001101 77 -#define B01001101 77 -#define B1001110 78 -#define B01001110 78 -#define B1001111 79 -#define B01001111 79 -#define B1010000 80 -#define B01010000 80 -#define B1010001 81 -#define B01010001 81 -#define B1010010 82 -#define B01010010 82 -#define B1010011 83 -#define B01010011 83 -#define B1010100 84 -#define B01010100 84 -#define B1010101 85 -#define B01010101 85 -#define B1010110 86 -#define B01010110 86 -#define B1010111 87 -#define B01010111 87 -#define B1011000 88 -#define B01011000 88 -#define B1011001 89 -#define B01011001 89 -#define B1011010 90 -#define B01011010 90 -#define B1011011 91 -#define B01011011 91 -#define B1011100 92 -#define B01011100 92 -#define B1011101 93 -#define B01011101 93 -#define B1011110 94 -#define B01011110 94 -#define B1011111 95 -#define B01011111 95 -#define B1100000 96 -#define B01100000 96 -#define B1100001 97 -#define B01100001 97 -#define B1100010 98 -#define B01100010 98 -#define B1100011 99 -#define B01100011 99 -#define B1100100 100 -#define B01100100 100 -#define B1100101 101 -#define B01100101 101 -#define B1100110 102 -#define B01100110 102 -#define B1100111 103 -#define B01100111 103 -#define B1101000 104 -#define B01101000 104 -#define B1101001 105 -#define B01101001 105 -#define B1101010 106 -#define B01101010 106 -#define B1101011 107 -#define B01101011 107 -#define B1101100 108 -#define B01101100 108 -#define B1101101 109 -#define B01101101 109 -#define B1101110 110 -#define B01101110 110 -#define B1101111 111 -#define B01101111 111 -#define B1110000 112 -#define B01110000 112 -#define B1110001 113 -#define B01110001 113 -#define B1110010 114 -#define B01110010 114 -#define B1110011 115 -#define B01110011 115 -#define B1110100 116 -#define B01110100 116 -#define B1110101 117 -#define B01110101 117 -#define B1110110 118 -#define B01110110 118 -#define B1110111 119 -#define B01110111 119 -#define B1111000 120 -#define B01111000 120 -#define B1111001 121 -#define B01111001 121 -#define B1111010 122 -#define B01111010 122 -#define B1111011 123 -#define B01111011 123 -#define B1111100 124 -#define B01111100 124 -#define B1111101 125 -#define B01111101 125 -#define B1111110 126 -#define B01111110 126 -#define B1111111 127 -#define B01111111 127 -#define B10000000 128 -#define B10000001 129 -#define B10000010 130 -#define B10000011 131 -#define B10000100 132 -#define B10000101 133 -#define B10000110 134 -#define B10000111 135 -#define B10001000 136 -#define B10001001 137 -#define B10001010 138 -#define B10001011 139 -#define B10001100 140 -#define B10001101 141 -#define B10001110 142 -#define B10001111 143 -#define B10010000 144 -#define B10010001 145 -#define B10010010 146 -#define B10010011 147 -#define B10010100 148 -#define B10010101 149 -#define B10010110 150 -#define B10010111 151 -#define B10011000 152 -#define B10011001 153 -#define B10011010 154 -#define B10011011 155 -#define B10011100 156 -#define B10011101 157 -#define B10011110 158 -#define B10011111 159 -#define B10100000 160 -#define B10100001 161 -#define B10100010 162 -#define B10100011 163 -#define B10100100 164 -#define B10100101 165 -#define B10100110 166 -#define B10100111 167 -#define B10101000 168 -#define B10101001 169 -#define B10101010 170 -#define B10101011 171 -#define B10101100 172 -#define B10101101 173 -#define B10101110 174 -#define B10101111 175 -#define B10110000 176 -#define B10110001 177 -#define B10110010 178 -#define B10110011 179 -#define B10110100 180 -#define B10110101 181 -#define B10110110 182 -#define B10110111 183 -#define B10111000 184 -#define B10111001 185 -#define B10111010 186 -#define B10111011 187 -#define B10111100 188 -#define B10111101 189 -#define B10111110 190 -#define B10111111 191 -#define B11000000 192 -#define B11000001 193 -#define B11000010 194 -#define B11000011 195 -#define B11000100 196 -#define B11000101 197 -#define B11000110 198 -#define B11000111 199 -#define B11001000 200 -#define B11001001 201 -#define B11001010 202 -#define B11001011 203 -#define B11001100 204 -#define B11001101 205 -#define B11001110 206 -#define B11001111 207 -#define B11010000 208 -#define B11010001 209 -#define B11010010 210 -#define B11010011 211 -#define B11010100 212 -#define B11010101 213 -#define B11010110 214 -#define B11010111 215 -#define B11011000 216 -#define B11011001 217 -#define B11011010 218 -#define B11011011 219 -#define B11011100 220 -#define B11011101 221 -#define B11011110 222 -#define B11011111 223 -#define B11100000 224 -#define B11100001 225 -#define B11100010 226 -#define B11100011 227 -#define B11100100 228 -#define B11100101 229 -#define B11100110 230 -#define B11100111 231 -#define B11101000 232 -#define B11101001 233 -#define B11101010 234 -#define B11101011 235 -#define B11101100 236 -#define B11101101 237 -#define B11101110 238 -#define B11101111 239 -#define B11110000 240 -#define B11110001 241 -#define B11110010 242 -#define B11110011 243 -#define B11110100 244 -#define B11110101 245 -#define B11110110 246 -#define B11110111 247 -#define B11111000 248 -#define B11111001 249 -#define B11111010 250 -#define B11111011 251 -#define B11111100 252 -#define B11111101 253 -#define B11111110 254 -#define B11111111 255 - -#endif diff --git a/BootLoaders/Boards/orangerx/cores/xmega/main.cpp b/BootLoaders/Boards/orangerx/cores/xmega/main.cpp deleted file mode 100644 index aa9092e..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/main.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - main.cpp - Main loop for Arduino sketches - Copyright (c) 2005-2013 Arduino Team. 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 -*/ - -//#include Platform.h includes Arduino.h -#include /* to make sure that Arduino.h is included, as well as pins_arduino.h and other things */ - - -#ifdef EIND -// if I have an EIND register, I want it pre-loaded with the correct value -// for info on THIS thing, see http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html -// in essence, 'init3' section functions run just before 'main()' - -// must prototype it to get all of the attributes -static void __attribute__((section(".init3"),naked,used,no_instrument_function)) init3_set_eind (void); - -void init3_set_eind (void) -{ - __asm volatile ("ldi r24,pm_hh8(__trampolines_start)\n\t" - "out %i0,r24" :: "n" (&EIND) : "r24","memory"); -} -#endif // EIND - -//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 main(void) -{ - - init(); - - initVariant(); - -// TEMPORARY - moved [so I can debug it] -//#if defined(USBCON) -// USBDevice.attach(); -//#endif - - setup(); - - for (;;) { - loop(); - if (serialEventRun) serialEventRun(); - } - - return 0; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/new.cpp b/BootLoaders/Boards/orangerx/cores/xmega/new.cpp deleted file mode 100644 index 51ea5a3..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/new.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -void * operator new(size_t size) -{ - return malloc(size); -} - -void * operator new[](size_t size) -{ - return malloc(size); -} - -void operator delete(void * ptr) -{ - free(ptr); -} - -void operator delete[](void * ptr) -{ - free(ptr); -} - -int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; -void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; -void __cxa_guard_abort (__guard *) {}; - -void __cxa_pure_virtual(void) {}; - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/new.h b/BootLoaders/Boards/orangerx/cores/xmega/new.h deleted file mode 100644 index 8c93ceb..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/new.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Header to define new/delete operators as they aren't provided by avr-gcc by default - Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453 - */ - -#ifndef NEW_H -#define NEW_H - -#include - -void * operator new(size_t size); -void * operator new[](size_t size); -void operator delete(void * ptr); -void operator delete[](void * ptr); - -__extension__ typedef int __guard __attribute__((mode (__DI__))); - -extern "C" int __cxa_guard_acquire(__guard *); -extern "C" void __cxa_guard_release (__guard *); -extern "C" void __cxa_guard_abort (__guard *); - -extern "C" void __cxa_pure_virtual(void); - -#endif - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring.c b/BootLoaders/Boards/orangerx/cores/xmega/wiring.c deleted file mode 100644 index b62afdb..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* - wiring.c - Partial implementation of the Wiring API for the ATmega8. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#include "wiring_private.h" - -#include // Include for sleep mode (see 'wait_for_interrupt()') - - -// The xmega architecture differs significantly from the mega in a number -// of ways that render the existing code unworkable. Therefore a complete -// re-write was done to ensure 100% compatibility at the code level. - - - -// the prescaler is set so that timer0 ticks every 64 clock cycles, and the -// the overflow handler is called every 256 ticks. -// (NOTE: for 'E' series, it's 32 clock sycles) -//#ifdef TCC4 /* using timer 4,5 rather than 0,2 - 'E' series */ -//#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(32 * 256)) -//#else // TCC4 -#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) -//#endif // TCC4 - -// the whole number of milliseconds per timer0 overflow -#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) - -// NOTE: xmega runs at 32 mhz typically. However, it uses THE PERIPHERAL CLOCK -// for the timer. Normally this is the same as the CPU clock unless you use -// some crazy clock pre-scaler. -// See sections 6.9 and 6.10 in D manual for system clock setup - -// the fractional number of milliseconds per timer0 overflow. we shift right -// by three to fit these numbers into a byte. (for the clock speeds we care -// about - 8 and 16 MHz and 32 Mhz for xmega - this doesn't lose precision.) - -#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) -#define FRACT_MAX (1000 >> 3) - -volatile unsigned long timer0_overflow_count = 0; -volatile unsigned long timer0_millis = 0; -static unsigned char timer0_fract = 0; - -// timer zero overflow - affects pins 5 and 6 for PWM on Arduino and compatibles -// what I want to do is simulate what the Arduino already does, using TCD2 -// since it will share the same pre-scaler AND clock for all of the port D PWM out - -// the timer prescaler MUST tick every 64 clock cycles for this to work, just like the mega TIMER 0 -// NOTE: at 32Mhz MICROSECONDS_PER_TIMER0_OVERFLOW will be 512 - consider a divider of 128 instead -// unless you want 2khz for the PWM (which is actually a good idea, for servos etc.) - - -////////////////////////////////////////////////////////////////////////////// -// // -// _____ _ ___ ____ ____ // -// |_ _|(_) _ __ ___ ___ _ __ |_ _|/ ___| | _ \ // -// | | | || '_ ` _ \ / _ \| '__| | | \___ \ | |_) | // -// | | | || | | | | || __/| | | | ___) || _ < // -// |_| |_||_| |_| |_| \___||_| |___||____/ |_| \_\ // -// // -// // -////////////////////////////////////////////////////////////////////////////// - -#ifdef TCC4 // 'E' series or later that has TCC4 and TCD5 -ISR(TCD5_OVF_vect) -#elif !defined(TCD2_LUNF_vect) -ISR(TCD0_OVF_vect) // for A series -#else // USING TCD2 -ISR(TCD2_LUNF_vect) -#endif // TCD2, TCD5 -{ - // for this to work the limit must be 255 (8-bit mode) - -#ifdef TCC4 // 'E' series or later that has TCC4 and TCD5 - TCD5_INTFLAGS = 1; // clears the flag so I don't 'spin' (this behavior changed from previous timers) -#endif // 'E' series - - // copy these to local variables so they can be stored in registers - // (volatile variables must be read from memory on every access) - unsigned long m = timer0_millis; - unsigned char f = timer0_fract; - -#if MILLIS_INC > 0 - m += MILLIS_INC; -#endif // MILLIS_INC - f += FRACT_INC; - if (f >= FRACT_MAX) - { - f -= FRACT_MAX; - m += 1; - } - - timer0_fract = f; - timer0_millis = m; - timer0_overflow_count++; -} - -unsigned long millis() -{ - unsigned long m; - uint8_t oldSREG = SREG; - - // 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) - cli(); - m = timer0_millis; - SREG = oldSREG; - - return m; -} - -unsigned long micros() -{ - unsigned long m; - uint8_t t, oldSREG; - - oldSREG = SREG; - cli(); // for consistency, don't let this part get interrupted - - m = timer0_overflow_count; // for xmega it's really an underflow except 'E' series -#ifdef TCC4 - t = 255 - (TCD5_CNT & 0xff); -#elif !defined(TCD2) - t = 255 - (TCD0_CNT & 0xff); -#else // TCC4 - t = 255 - TCD2_LCNT; // 'low' count, it's what we interrupt on (and it always counts DOWN) - // must subtract count value from 255 for this to work correctly -#endif // TCC4 - - // check the interrupt flag to see if I just got an underflow - -#ifdef TCC4 - if((TCD5_INTFLAGS & _BV(0)) && (t < 255)) // which means I overflowed but didn't call the ISR yet -#elif !defined(TCD2) - if((TCD0_INTFLAGS & _BV(0)) && (t < 255)) // which means I underflowed but didn't call the ISR yet -#else // TCC4 - if((TCD2_INTFLAGS & _BV(0)) && (t < 255)) // which means I underflowed but didn't call the ISR yet -#endif // TCC4 - { - m++; // increment ISR count for more accurate microseconds - } - - SREG = oldSREG; - - return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); // TODO: make the '64' a #define ? -} - -void delay(unsigned long ms) -{ - uint16_t start = (uint16_t)micros(); - - while (ms > 0) /* BF - fixed K&R style to Allman for readability/consistency */ - { - if (((uint16_t)micros() - start) >= 1000) - { - ms--; - start += 1000; - } - } -} - -// XMEGA-specific code -void wait_for_interrupt(void) -{ - cli(); // disable interrupts - - set_sleep_mode(SLEEP_MODE_IDLE); // everything on but CPU and NVRAM - - sleep_enable(); - - sei(); // re-enable interrupts - - sleep_cpu(); // go to sleep - - sleep_disable(); // first thing to do out of sleep -} - -void low_power_delay(unsigned long ms) -{ - uint16_t start = (uint16_t)micros(); - - while (ms > 0) - { - wait_for_interrupt(); // up to 1msec perhaps? - - while (((uint16_t)micros() - start) >= 1000) - { - ms--; - start += 1000; - } - } -} - - -/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */ -// NOTE: for XMEGA, you can have a 32mhz clock -void delayMicroseconds(unsigned int us) -{ - // NOTE: for 32mhz clock, max time is 65536 / 8 or about 8k microsecs - - // 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 >= 32000000L /* the xmega typically has this */ - - // for a one-microsecond delay, simply wait 12 cycles and return. The overhead - // of the function call yields a delay of exactly a one microsecond. - __asm__ __volatile__ ( - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop" "\n\t" - "nop"); //just waiting 12 cycle - if (--us == 0) - return; - - // the following loop takes a 1/8 of a microsecond (4 cycles) - // per iteration, so execute it five times for each microsecond of - // delay requested. - us = (us<<3);// * 8 - - // account for the time taken in the preceeding commands. - us -= 2; // 2 clock cycles - -#elif F_CPU >= 20000000L - // for the 20 MHz clock on rare Arduino boards - - // for a one-microsecond delay, simply wait 2 cycle and return. The overhead - // of the function call yields a delay of exactly a one microsecond. - __asm__ __volatile__ ( - "nop" "\n\t" - "nop"); //just waiting 2 cycle - if (--us == 0) - return; - - // 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 - - // account for the time taken in the preceeding commands. - us -= 2; - -#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 yields a delay of approximately 1 1/8 us. - if (--us == 0) - return; - - // the following loop takes a quarter of a microsecond (4 cycles) - // per iteration, so execute it four times for each microsecond of - // delay requested. - us <<= 2; - - // account for the time taken in the preceeding commands. - us -= 2; -#else - // for the 8 MHz internal clock on the ATmega168 - - // for a one- or two-microsecond delay, simply return. the overhead of - // the function calls takes more than two microseconds. can't just - // subtract two, since us is unsigned; we'd overflow. - if (--us == 0) - return; - if (--us == 0) - return; - - // the following loop takes half of a microsecond (4 cycles) - // per iteration, so execute it twice for each microsecond of - // delay requested. - us <<= 1; - - // partially compensate for the time taken by the preceeding commands. - // we can't subtract any more than this or we'd overflow w/ small delays. - us--; -#endif - - // busy wait - __asm__ __volatile__ ( - "1: sbiw %0,1" "\n\t" // 2 cycles - "brne 1b" : "=w" (us) : "0" (us) // 2 cycles - ); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ ____ _ _ ____ _ // -// / ___| _ _ ___ | |_ ___ _ __ ___ / ___|| | ___ ___ | | __ / ___| ___ | |_ _ _ _ __ // -// \___ \ | | | |/ __|| __|/ _ \| '_ ` _ \ | | | | / _ \ / __|| |/ / \___ \ / _ \| __|| | | || '_ \ // -// ___) || |_| |\__ \| |_| __/| | | | | | | |___ | || (_) || (__ | < ___) || __/| |_ | |_| || |_) | // -// |____/ \__, ||___/ \__|\___||_| |_| |_| \____||_| \___/ \___||_|\_\ |____/ \___| \__| \__,_|| .__/ // -// |___/ |_| // -// // -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -// this function is separate since it provides a specific functionality -// and aids in readability by separating it from the main 'init()' code -// regardless of the extra bytes needed to make the function call -void clock_setup(void) -{ -unsigned short sCtr; -register unsigned char c1; - - // TODO: get rid of magic bit numbers, and use bit value constants from iox64d4.h etc. (ongoing) - - // TODO: consider clock setup using PLL and 2Mhz multiplied by 16, to free up the 32Mhz to be - // used by the USB at 48Mhz (sync on SOF). this would be an alternate config for USB devices. - - // -------------------------------------------------------------------------------------------- - // CLOCK SETUP - // - // enable BOTH the 32Mhz and 32.768KHz internal clocks [ignore what else might be set for now] - // -------------------------------------------------------------------------------------------- - - OSC_CTRL |= OSC_RC32KEN_bm | OSC_RC32MEN_bm; // CLK_SCLKSEL_RC32M_gc | CLK_SCLKSEL_RC32K_gc; - - if(!(CLK_LOCK & CLK_LOCK_bm)) // clock lock bit NOT set, so I can muck with the clock - { - if((CLK_CTRL & CLK_SCLKSEL_gm) != CLK_SCLKSEL_RC32M_gc) // it's not already 32 Mhz - { - // wait until 32mhz clock is 'stable' - - for(sCtr=32767; sCtr > 0; sCtr--) // TODO: remove counter? - { - // spin on oscillator status bit for 32Mhz oscillator - - if(OSC_STATUS & OSC_RC32MRDY_bm/*CLK_SCLKSEL_RC32M_gc*/) // 32Mhz oscillator is 'ready' (6.10.2) - { - break; - } - } - - // for now, I can allow the clock to NOT be changed if it's - // not ready. This prevents infinite loop inside startup code - - if(!(OSC_STATUS & OSC_RC32MRDY_bm/*CLK_SCLKSEL_RC32M_gc*/)) // is my oscillator 'ready' ? - { - return; // exit - don't change anything - } - - // switch to 32Mhz clock using internal source - - CCP = CCP_IOREG_gc; // 0xd8 - see D manual, sect 3.14.1 (protected I/O) - CLK_CTRL = CLK_SCLKSEL_RC32M_gc; // set the clock to 32Mhz (6.9.1) - } - - if(CLK_PSCTRL != 0) - { - CCP = CCP_IOREG_gc; // 0xd8 - see D manual, sect 3.14.1 (protected I/O) - CLK_PSCTRL = CLK_PSADIV_1_gc | CLK_PSBCDIV_1_1_gc/*0*/; // set the clock divider(s) to 1:1 (6.9.2) - } - - // now that I've changed the clock, disable 2Mhz, PLL, and external clocks - // 32.768KHz should remain active, but I need to make sure it's stable - OSC_CTRL &= // ~(_BV(4) | _BV(3) | _BV(0)); // sect 6.10.1 - disable PLL, external, 2Mhz clocks - ~(OSC_PLLEN_bm | OSC_XOSCEN_bm - | OSC_RC2MEN_bm /* disable the 2Mhz oscillator - startup code *DOES* do this, boot code does NOT */ -#ifdef OSC_RC8MCAL // only present in 'E' series - for now shut it off - | OSC_RC8MEN_bm /* disable the 8M oscillator (when present) */ -#endif // OSC_RC8MCAL - ); - - // wait until 32.768KHz clock is 'stable'. this one goes for a while - // in case it doesn't stabilize in a reasonable time. I figure about - // 64*255 clock cycles should be enough, ya think? Timeout if it's not - // actually ready, I don't want infinite loops. TODO: re-consider? - for(sCtr=65535; sCtr > 0; sCtr--) - { - for(c1=255; c1 > 0; c1--) - { - if(OSC_STATUS & OSC_RC32KRDY_bm/*CLK_SCLKSEL_RC32K_gc*/) // 32.768KHz oscillator is 'ready' (6.10.2) - { - sCtr = 1; // this will bail out of the outer loop - break; - } - } - } - - // enable DFLL auto-calibration of the 32Mhz internal oscillator - // (it uses the reasonably precise 32.768KHz clock to do it) - - OSC_DFLLCTRL = 0; // sect 6.10.7 - select 32.768KHz osc for everything, basically - DFLLRC32M_CTRL = 1; // set the bit to enable DFLL calibration - section 6.11.1 - } - - // I'll be using the 1.024khz clock (from the 32.768KHz clock) for the real-time counter - // this will give me a reasonable "about 1 millisecond" accuracy on the RTC - - // NOTE: I may not have checked for this if I skipped the previous section, - // so now I check again, just in case, to make sure the 32.768KHz osc is stable - for(sCtr=65535; sCtr > 0; sCtr--) - { - for(c1=255; c1 > 0; c1--) - { - if(OSC_STATUS & OSC_RC32KRDY_bm/*CLK_SCLKSEL_RC32K_gc*/) // 32.768KHz oscillator is 'ready' (6.10.2) - { - sCtr = 1; // this will bail out of the outer loop - break; - } - } - } - - if(!(OSC_STATUS & OSC_RC32KRDY_bm/*CLK_SCLKSEL_RC32K_gc*/)) // is my oscillator 'ready' ? - { - return; // exit - don't change anything else. Better to fail than to hang - } - - - // RUN-TIME clock - use internal 1.024 khz source. cal'd 32khz needed for this (but it's running) - // The RTC can be used to wake up the CPU. It uses VERY little current. - - CLK_RTCCTRL = CLK_RTCSRC_RCOSC_gc; // section 6.9.4 -} - - -// this was derived from a message board post. The function is public to make it easy to -// use the 'Production Signature Row'. There is a unique identifier for the CPU as well as -// calibration data for the ADC available, and also USB settings (for USB-capable devices) -// See sect. 4.14 "Production Signature Row" in 'D' manual. -uint8_t readCalibrationData(uint16_t iIndex) -{ - uint8_t rVal; - - /* Load the NVM Command register to read the calibration row. */ - NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc; // see the section on NVM operations and lpm instruction - -// rVal = pgm_read_byte_near(iIndex); // effectively the same thing as the inline assembler - __asm__ ("lpm %0, Z\n" : "=r" (rVal) : "z" (iIndex)); // do it THIS way instead - - /* Clean up NVM Command register. */ - NVM_CMD = NVM_CMD_NO_OPERATION_gc; - - return(rVal); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// // -// _____ _ ___ _ _ _ _ _ _ _ // -// |_ _|(_) _ __ ___ ___ _ __ |_ _| _ __ (_)| |_ (_) __ _ | |(_) ____ __ _ | |_ (_) ___ _ __ // -// | | | || '_ ` _ \ / _ \| '__| | | | '_ \ | || __|| | / _` || || ||_ // _` || __|| | / _ \ | '_ \ // -// | | | || | | | | || __/| | | | | | | || || |_ | || (_| || || | / /| (_| || |_ | || (_) || | | | // -// |_| |_||_| |_| |_| \___||_| |___||_| |_||_| \__||_| \__,_||_||_|/___|\__,_| \__||_| \___/ |_| |_| // -// // -// // -/////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef TCC2 -static void Timer2Init(TC2_t *port) -{ - port->CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 - port->CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// port->CTRLC = 0; // when timer not running, sets compare (13.9.3) - port->CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 - port->CTRLF = 0; // not resetting or anything (13.9.7) - - port->LPER = 255; // count 255 to 0 (total period = 256) - port->HPER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. This, however, would generate a '1' output. - - port->LCMPA = 255; - port->LCMPB = 255; - port->LCMPC = 255; - port->LCMPD = 255; - - port->HCMPA = 255; - port->HCMPB = 255; - port->HCMPC = 255; - port->HCMPD = 255; - - // disable underflow and comparison interrupts - port->INTCTRLA = 0; // no underflow interrupts - port->INTCTRLB = 0; // no comparison interrupts -} -#elif defined(TCC0) // use TC0_t -static void Timer2Init(TC0_t *port) -{ - // TCC2 - // first the clock selection - port->CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 - port->CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// TCC2_CTRLC = 0; // when timer not running, sets compare (13.9.3) - port->CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 -#ifdef TCC0_CTRLFCLR // NOTE: is this correct? - port->CTRLFCLR = 0xff; // this does NOT map to anything for TC_t, but I want zeros in CTRLF so 'just in case' - port->CTRLFSET = 0; // this maps to 'CTRLF' for TC2_t, and this assignment should work on its own -#else // TCC0_CTRLFCLR - // NOTE: this code will probably NOT be compiled due to the way TC0_t maps to TC2_t - port->CTRLF = 0; // not resetting or anything (13.9.7) -#endif // TCC0_CTRLFCLR - - port->PER = 255; -// TCC2_LPER = 255; // count 255 to 0 (total period = 256) -// TCC2_HPER = 255; // should this be zero? - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. This, however, would generate a '1' output. - -// ((uint8_t *)&(port->CCA))[0] = 255; // low bytes -// ((uint8_t *)&(port->CCB))[0] = 255; -// ((uint8_t *)&(port->CCC))[0] = 255; -// ((uint8_t *)&(port->CCD))[0] = 255; - -// ((uint8_t *)&(port->CCA))[1] = 255; // high bytes -// ((uint8_t *)&(port->CCB))[1] = 255; -// ((uint8_t *)&(port->CCC))[1] = 255; -// ((uint8_t *)&(port->CCD))[1] = 255; - - // NOTE: according to the docs, 16-bit registers MUST be accessed - // low byte first, then high byte, before the actual value - // is transferred to the register. THIS code will. - // see A1U manual sect. 3.11 (and others as well) - - port->CCA = 0xffff; - port->CCB = 0xffff; - port->CCC = 0xffff; - port->CCD = 0xffff; - - // disable underflow and comparison interrupts - port->INTCTRLA = 0; // no underflow interrupts - port->INTCTRLB = 0; // no comparison interrupts -} -#endif // TCC2 - - -////////////////////////////////////////////////////////////////////////////// -// // -// ____ _ ___ _ _ // -// / ___| _ _ ___ | |_ ___ _ __ ___ |_ _| _ __ (_)| |_ // -// \___ \ | | | |/ __|| __|/ _ \| '_ ` _ \ | | | '_ \ | || __| // -// ___) || |_| |\__ \| |_| __/| | | | | | | | | | | || || |_ // -// |____/ \__, ||___/ \__|\___||_| |_| |_| |___||_| |_||_| \__| // -// |___/ // -// // -////////////////////////////////////////////////////////////////////////////// - -// NOTE: calibration data for ADC must be loaded BEFORE it's initialized -// ADCA.CALL = readCalibrationData(&PRODSIGNATURES_ADCACAL0); -// ADCA.CALH = readCalibrationData(&PRODSIGNATURES_ADCACAL1); - -void init() -{ - - - cli(); // do this before _ANYTHING_ - - // ---------------------------------------------------------- - // first thing first - the system clock _MUST_ run at 32Mhz - // ---------------------------------------------------------- - - clock_setup(); - - - // The watchdog timer MUST be off (the bootloader should do this too) - // this next section of code will disable it. - - CCP = CCP_IOREG_gc; // 0xd8 - see D manual, sect 3.14.1 (protected I/O) - WDT_CTRL = 1; // sets watchdog timer "enable" bit to zero - bit 0 must be set to change bit 1 - section 9.7.1 - CCP = CCP_IOREG_gc; // 0xd8 - see D manual, sect 3.14.1 (protected I/O) - WDT_WINCTRL = 1; // sets watchdog 'window' timer "enable" bit to zero - bit 0 must be set to change bit 1 - section 9.7.2 - - NVM_INTCTRL = 0; // disable interrupts in the NVM subsystem - -#ifdef WEXC_OUTOVDIS - WEXC_OUTOVDIS = 0; // in essence, it should allow waveform output on all pins (default value) - // assigning this to FFH prevents PWM output on PORTC - does not appear to affect PORTD - - WEXC_CTRL = 0; // hopefully disabling everything - WEXC_SWAP = 0; // no bit swapping - WEXC_PGO = 0; // disable PGV output on all bits - -#endif // WEXC_OUTOVDIS - -#ifdef HIRESC_CTRLA - HIRESC_CTRLA = 0; // disable hi-res timer extension -#endif // HIRESC_CTRLA - - - // -------------------------------- - // INITIAL TIMER CONFIGURATION - // -------------------------------- - - // For the E series, set up timers TCC4, TCC5, and TCD5 in 'normal' mode with a pre-scale of 64. - // TODO: consider CC ISR for PWM and manual bit-flip, if it's even possible. - // - // For everything else, set up timers TCC2 and TCD2 and TCE0. Use pre-scale of 64. - // If other timers exist (like 'A' series) initialize them as well. - // - // For a 32Mhz clock they will run at 2Khz with the appropriate pre-scale + divide. - // For PWM out, use the comparison result to drive the appropriate pins. - - // If you don't need PWM, or want 'other than 2khz', you can re-configure the other timers, - // but leave TCD2 (or TCD5) alone because it's needed for the system clock (via TCD2_LUNF_vect, etc.) - - -#ifdef TCC4 /* this is my trigger for 'E' series */ - - // TCD5 first (the system timer) - TCD5_INTCTRLA = 0; // no underflow interrupts - TCD5_INTCTRLB = 0; // no comparison interrupts - - TCD5_CTRLA = 5; // b0101 - divide by 64 - E manual 13.13.1 -// TCD5_CTRLB = TC45_BYTEM_BYTEMODE_gc; // byte mode, normal mode - TCD5_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_SINGLESLOPE_gc; // byte mode, single slope -// TCD5_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_DSBOTH_gc; // byte mode, dual slope, ovf on bottom AND top -//// TCD5_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCD5_CTRLD = 0; // events off - TCD5_CTRLE = 0; // no output on L pins - TCD5_CTRLF = 0; // no output on H pins - - TCD5_PER = 255; // 255 for period limit - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. - - TCD5_CCA = 65535; - TCD5_CCB = 65535; - - TCD5_CTRLGCLR = 0xfe; - TCD5_CTRLGSET = 1; // count DOWN - - // enable the underflow interrupt on A, disable on B, disable comparison interrupts - TCD5_INTCTRLA = 0x3; // enable LOW underflow interrupt, pri level 3 (see 13.9.5 in D manual) - -// TODO: this is not well documented - does it even work for TIMER D5 ?? -#ifdef TCD5_PIN_SHIFT /* shifting PWM output pins, normally 4,5,6,7 */ - PORTD_REMAP = (PORTD_REMAP & PORT_USART0_bm) | TCD5_PIN_SHIFT; -#else // PORTD_REMAP - PORTD_REMAP &= PORT_USART0_bm; // all other pins are zero except maybe USART0 remap -#endif // PORTD_REMAP - - -// if 'HIRES' enabled, shut it off -#ifdef HIRESC_ENABLE - HIRESC_ENABLE = HIRES_HREN_NONE_gc; -#endif // HIRESC_ENABLE - - PORTC_REMAP &= PORT_USART0_bm; // all other pins are zero except maybe USART0 remap - - // TCC4 - // first the clock selection - TCC4_CTRLA = 5; // b0101 - divide by 64 - E manual 13.13.1 - TCC4_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_SINGLESLOPE_gc; // byte mode, single slope -// TCC4_CTRLB = TC45_BYTEM_BYTEMODE_gc | TC45_WGMODE_DSBOTH_gc; // byte mode, dual slope, ovf on bottom AND top -//// TCC4_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCC4_CTRLD = 0; // events off - TCC4_CTRLE = 0; // no output on L pins - TCC4_CTRLF = 0; // no output on H pins - - TCC4_PER = 255; // 255 for period limit - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. - - TCC4_CCA = 65535; - TCC4_CCB = 65535; - TCC4_CCC = 65535; - TCC4_CCD = 65535; - - TCC4_CTRLGCLR = 0xfe; - TCC4_CTRLGSET = 1; // count DOWN - - // disable underflow and comparison interrupts - TCC4_INTCTRLA = 0; // no underflow interrupts - TCC4_INTCTRLB = 0; // no comparison interrupts - - - // also set up TCC5 - -#ifdef TCC5 - - TCC5_INTCTRLA = 0; // no underflow interrupts - TCC5_INTCTRLB = 0; // no comparison interrupts - - TCC5_CTRLA = 5; // b0101 - divide by 64 - E manual 13.13.1 - TCC5_CTRLB = TC45_WGMODE_NORMAL_gc; // 'normal' mode, 16-bit mode -//// TCC5_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCC5_CTRLD = 0; // events off - TCC5_CTRLE = 0; // no output on L pins - TCC5_CTRLF = 0; // no output on H pins - - TCC5_PER = 255; // 255 for period limit - - TCC5_CCA = 0; - TCC5_CCB = 0; - - TCC5_CTRLGCLR = 0xff; - TCC5_CTRLGSET = 0; // count UP - - // disable underflow and comparison interrupts - TCC5_INTCTRLA = 0; // no underflow interrupts - TCC5_INTCTRLB = 0; // no comparison interrupts - -#endif // TCC5 - - -#else // everything else uses TCD2 for system timer - -#ifndef TCC2 /* A1 series doesn't define this properly, so use TCC0 and TCD0, etc. */ - - // TCD2 - // first the clock selection - TCD0_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 (should be the same for 'A' and others) - TCD0_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// TCD0_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCD0_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 -#ifdef TCD0_CTRLFCLR - TCD0_CTRLFCLR = 0xff; -#else // TCD0_CTRLFCLR - TCD0_CTRLF = 0; // not resetting or anything (13.9.7) -#endif // TCD0_CTRLFCLR - - TCD0_PER = 255; -// TCD2_LPER = 255; // count 255 to 0 (total period = 256) -// TCD2_HPER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. use FFFFH in the compare registers. - - // NOTE: according to the docs, 16-bit registers MUST be accessed - // low byte first, then high byte, before the actual value - // is transferred to the register. THIS code will do that. - // see A1U manual sect. 3.11 (and others as well) - - TCD0_CCA = 0xffff; - TCD0_CCB = 0xffff; - TCD0_CCC = 0xffff; - TCD0_CCD = 0xffff; - - // enable the underflow interrupt on A, disable on B, disable comparison interrupts - TCD0_INTCTRLA = 0x3; // enable LOW underflow interrupt, pri level 3 (see 13.9.5 in D manual) - TCD0_INTCTRLB = 0; // no comparison or underflow interrupts on anything else - - Timer2Init(&TCC0); - -#else // TCC2 - - // TCD2 - // first the clock selection - TCD2_CTRLA = 5; // b0101 - divide by 64 - D manual 13.9.1 - TCD2_CTRLB = 0; // compare outputs disabled on all 8 bits (13.9.2) -// TCD2_CTRLC = 0; // when timer not running, sets compare (13.9.3) - TCD2_CTRLE = 0x2; // b10 - 'split' mode - D manual 13.9.4 - TCD2_CTRLF = 0; // not resetting or anything (13.9.7) - - TCD2_LPER = 255; // count 255 to 0 (total period = 256) - TCD2_HPER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // 'timer 2' counts DOWN. Timer 2 regs are 8-bit. - - TCD2_LCMPA = 255; - TCD2_LCMPB = 255; - TCD2_LCMPC = 255; - TCD2_LCMPD = 255; - - TCD2_HCMPA = 255; - TCD2_HCMPB = 255; - TCD2_HCMPC = 255; - TCD2_HCMPD = 255; - - // enable the underflow interrupt on A, disable on B, disable comparison interrupts - TCD2_INTCTRLA = 0x3; // enable LOW underflow interrupt, pri level 3 (see 13.9.5 in D manual) - TCD2_INTCTRLB = 0; // no comparison or underflow interrupts on anything else - - Timer2Init(&TCC2); - -#endif // TCC2 - -#endif // TCD5 or TCD2 - - -#if NUM_DIGITAL_PINS > 22 /* meaning PORTE is available and has 8 pins */ - -#if !defined(TCE2) && defined(TCE0) - - Timer2Init(&TCE0); - -#elif defined(TCE2) // TCE2 defined, use that - - Timer2Init(&TCE2); - -#endif // TCE2, TCE0 - - -#if NUM_DIGITAL_PINS > 30 /* meaning PORTF exists */ - -#if !defined(TCF2) && defined(TCF0) - - Timer2Init(&TCF0); - -#elif defined(TCF2) // TCF2 defined, use that - - Timer2Init(&TCF2); - -#endif // TCF2, TCF0 - - -// TODO: other timers on other ports when more than 38 pins available? - - -#endif // NUM_DIGITAL_PINS > 30 - - -#elif NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available with only 4 pins */ - - // now set up TCE0 as an 8-bit timer so it's compatible with Arduino's PWM - // first the clock selection - TCE0_CTRLA = 5; // b0101 - divide by 64 - D manual 12.11.1 - TCE0_CTRLB = TC_WGMODE_SS_gc; // single-slope PWM. NOTE: this counts UP, whereas the other timers count DOWN - // other bits (high nybble) are OFF - they enable output on the 4 port E pins -// TCE0_CTRLC = 0; // when timer not running, sets compare (12.11.3) - TCE0_CTRLD = 0; // not an event timer, 16-bit mode (12.11.4) - TCE0_CTRLE = 1; // normal 8-bit timer (set to 0 for 16-bit mode) (12.11.5) - - // disable under/overflow and comparison interrupts - TCE0_INTCTRLA = 0; // no underflow interrupts - TCE0_INTCTRLB = 0; // no comparison interrupts - - // make sure the timer E 'period' register is correctly set at 255 (i.e. 0-255 or 256 clock cycles). - TCE0_PER = 255; - - // pre-assign comparison registers to 'zero' (for PWM out) which is actually 255 - // timer 0 can be configured to count UP or DOWN, but for single-slope PWM it is - // always 'UP'. A value of '255' should generate a '1' output for each PWM. - - TCE0_CCA = 255; - TCE0_CCB = 255; - TCE0_CCC = 255; - TCE0_CCD = 255; - -#endif // NUM_DIGITAL_PINS > 18, 22 - - - - // in case the bootloader enabled serial or TWI, disable it - // and make sure the associated port input pins are inputs - // - // NOTE: Port R pins 0 and 1 will be outputs, but all others should be inputs - // PR0 and PR1 are designated LED output pins for this design. PR1 is - // the blinking LED pin used by the bootloader. These will NOT be re-assigned - // at this time, but left 'as-is'. - - // ----------------------------------------- - // DISABLE TWI (specifically TWI interrupts) - // ----------------------------------------- - -#ifdef TWIC_CTRL - TWIC_MASTER_CTRLA = 0; - TWIC_SLAVE_CTRLA = 0; -#endif // TWIC_CTRL -#ifdef TWID_CTRL - TWID_MASTER_CTRLA = 0; - TWID_SLAVE_CTRLA = 0; -#endif // TWID -//#if NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available */ -#ifdef TWIE_CTRL - TWIE_MASTER_CTRLA = 0; - TWIE_SLAVE_CTRLA = 0; -#endif // TWIE_CTRL -#ifdef TWIF_CTRL - TWIF_MASTER_CTRLA = 0; - TWIF_SLAVE_CTRLA = 0; -#endif // TWIF - - // -------------------- - // DISABLE SERIAL PORTS - // -------------------- - - USARTD0_CTRLA = 0; // disables interrupts - USARTD0_CTRLB = 0; // disables TX and RX pin override - USARTC0_CTRLA = 0; // do the same thing - USARTC0_CTRLB = 0; // for both port C and D - -#ifdef USARTC0_CTRLD - USARTC0_CTRLD = 0; // E5 has this register, must assign to zero -#endif // USARTC0_CTRLD -#ifdef USARTD0_CTRLD - USARTD0_CTRLD = 0; // E5 has this register, must assign to zero -#endif // USARTC0_CTRLD - - // other serial ports found on A series -#ifdef USARTDD1_CTRLA - USARTD1_CTRLA = 0; // disables interrupts - USARTD1_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA -#ifdef USARTDC1_CTRLA - USARTC1_CTRLA = 0; // disables interrupts - USARTC1_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA -#ifdef USARTDE0_CTRLA - USARTE0_CTRLA = 0; // disables interrupts - USARTE0_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA -#ifdef USARTDE1_CTRLA - USARTE1_CTRLA = 0; // disables interrupts - USARTE1_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA -#ifdef USARTDF0_CTRLA - USARTF0_CTRLA = 0; // disables interrupts - USARTF0_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA -#ifdef USARTDF1_CTRLA - USARTF1_CTRLA = 0; // disables interrupts - USARTF1_CTRLB = 0; // disables interrupts -#endif // USARTD1_CTRLA - - - - //-------------------------------------------------------------- - // all pins on all ports are inputs except for the LEDs on PR0,1 - //-------------------------------------------------------------- - - PORTC_DIR = 0; // all 'port C' pins are now inputs - PORTD_DIR = 0; // all 'port D' pins are now inputs -#ifdef PORTE_DIR - PORTE_DIR = 0; // all 'port E' pins are now inputs -#endif // PORTE_DIR - -#ifdef PORTF_DIR - PORTF_DIR = 0; -#endif // PORTF_DIR - -#ifdef PORTF_DIR - PORTF_DIR = 0; -#endif // PORTF_DIR - -#ifdef PORTG_DIR - PORTG_DIR = 0; -#endif // PORTF_DIR - -#ifdef PORTH_DIR - PORTH_DIR = 0; -#endif // PORTF_DIR - -// TODO: external ram support for A series? - -#ifdef PORTJ_DIR - PORTJ_DIR = 0; -#endif // PORTF_DIR - -#ifdef PORTK_DIR - PORTK_DIR = 0; -#endif // PORTF_DIR - -#ifdef PORTQ_DIR - PORTQ_DIR = 0; -#endif // PORTF_DIR - -// port R - outputs on pin 1 if LED_BUILTIN defined as 'PR1' - - PORTR_OUT = 0; // turn them off -#ifdef LED_BUILTIN -#if LED_BUILTIN == PR1 - PORTR_DIR = 2; // define as output -#else - PORTR_DIR = 0; -#endif // LED_BUILTIN == PR1 -#else - PORTR_DIR = 0; -#endif // LED_BUILTIN not defined - - // Added code to pre-set input pins also - note PIN0CTRL through PIN7CTRL are like an array - // also, 'PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc' evaluates to '0' and is the normal default - memset((void *)&(PORTC.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); - memset((void *)&(PORTD.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); - -#ifdef PORTE -#if NUM_DIGITAL_PINS > 22 /* meaning there is a PORT E available and it has 8 pins */ - memset((void *)&(PORTE.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#else // NUM_DIGITAL_PINS <= 22 - memset((void *)&(PORTE.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 4); -#endif // NUM_DIGITAL_PINS > 22 -#endif // PORTE defined - -#ifdef PORTF_DIR - memset((void *)&(PORTF.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#endif // PORTF_DIR - -#ifdef PORTG_DIR - memset((void *)&(PORTG.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#endif // PORTG_DIR - -#ifdef PORTH_DIR - memset((void *)&(PORTH.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#endif // PORTH_DIR - -// TODO: external ram support for A series? - -#ifdef PORTJ_DIR - memset((void *)&(PORTJ.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#endif // PORTJ_DIR - -#ifdef PORTK_DIR - memset((void *)&(PORTK.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 8); -#endif // PORTK_DIR - -#ifdef PORTQ_DIR /* PORTQ only has 4 pins */ - memset((void *)&(PORTQ.PIN0CTRL), PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc, 4); // always 4? -#endif // PORTQ_DIR - - // PORT R (which is typically an output on both pins) - PORTR.PIN0CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc; - PORTR.PIN1CTRL = PORT_ISC_BOTHEDGES_gc | PORT_OPC_TOTEM_gc; - - - // --------------------------------------------------- - // ANALOG INPUT PINS - 'INPUT_DISABLED' (recommended) - // --------------------------------------------------- - - PORTA_DIR = 0; // direction bits - set all of them as input -#if defined(PORTB_DIR)// NUM_ANALOG_PINS > 8 /* meaning there is a PORT B */ - PORTB_DIR = 0; -#endif // NUM_ANALOG_PINS > 8 - - // all analog pins set up for 'INPUT_DISABLED' which is recommended for analog read - memset((void *)&(PORTA.PIN0CTRL), PORT_ISC_INPUT_DISABLE_gc | PORT_OPC_TOTEM_gc, 8); -#ifdef PORTB -#if NUM_ANALOG_INPUTS > 12 - memset((void *)&(PORTB.PIN0CTRL), PORT_ISC_INPUT_DISABLE_gc | PORT_OPC_TOTEM_gc, 8); -#elif NUM_ANALOG_INPUTS > 8 - memset((void *)&(PORTB.PIN0CTRL), PORT_ISC_INPUT_DISABLE_gc | PORT_OPC_TOTEM_gc, 4); -#endif // NUM_ANALOG_INPUTS > 8, 12 -#endif // PORTB - - - // TODO: handling PORTC as analog input for 'E' series? - - // -------------------- - // INTERRUPT CONTROLLER - // -------------------- - - // FINALLY, set up the interrupt controller for priority-based interrupts - // _AND_ enable them. Important. See 10.8.3 in D manual. - // - // This also makes sure the IVT is at the bottom of NVRAM, not the boot section - // It's very important to make sure the IVT is pointed at 00:0000 and not someplace else - // *BEFORE* I enable interrupts. - - *((volatile uint8_t *)&(CCP)) = CCP_IOREG_gc; // 0xd8 - see D manual, sect 3.14.1 (protected I/O) - *((volatile uint8_t *)&(PMIC_CTRL)) = PMIC_RREN_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm; - - - adc_setup(); // set up the ADC (function exported from wiring_analog.c) - - // this needs to be called before setup() or some functions won't work there - // but it's safe to enable interrupts so I shall simply do it! - - sei(); -} - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c b/BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c deleted file mode 100644 index f1883bd..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c +++ /dev/null @@ -1,859 +0,0 @@ -/* - wiring_analog.c - analog input and output - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - Modified 28 September 2010 by Mark Sproul - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#include "wiring_private.h" -#include "pins_arduino.h" - -//#define DEBUG_CODE -#ifdef DEBUG_CODE -extern void DebugOutL(unsigned long lVal); -extern void DebugOutP(const void * PROGMEM pStr); -#endif // DEBUG_CODE - -#ifndef ADCA_SAMPCTRL -#define ADCA_SAMPCTRL _SFR_MEM8(0x0208) /* missing from header for some reason, struct defines it as reserved_0x08 */ -#endif // ADCA_SAMPCTRL - - -uint8_t analog_reference, muxctrl_muxneg; // = ADC_REFSEL2_bp;// the default analog reference is Vcc / 2 (now assigned in adc_setup) - - -// NOTE: On the A-series processors with more than a handful of inputs, -// it is NOT possible to use 'diff input with gain' on MORE than -// A0-A7. On later processors (like D series) it _IS_ possible. -// Because of this, the 'hack' that allows rail-rail measurements -// is no longer possible on PB0-PB7. PA0-PA7 will still work. -// IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL' -// then you can read all 15 remaining values with whatever VRef you want. - -// adc_setup() - call this from init() and whenever you wake up from sleep mode -void adc_setup(void) -{ - // calibration is a 16-bit register - CAL0 + (CAL1 << 8) - ADCA_CAL = (uint16_t)readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_ADCACAL0) - | (((uint16_t)readCalibrationData((uint8_t)(uint16_t)&PRODSIGNATURES_ADCACAL1)) << 8); - - // must make sure power reduction register enables the ADC - PR_PRPA &= ~PR_ADC_bm; // clear this bit to enable the ADC clock - - // assign clock prescaler for 100khz, and clear the interrupt bit - // also make sure the 'interrupt enable' is OFF - - ADCA_EVCTRL = 0; // no triggering events (sect 22.14.4) - - ADCA_PRESCALER = ADC_PRESCALER_DIV256_gc; // 100khz, approximately, for 32Mhz clock - - ADCA_CTRLA = _BV(ADC_ENABLE_bp); // enables the ADC - ADCA_CTRLB = _BV(6) | _BV(4); // medium current limit, signed mode [temporary] - // _BV(6) | _BV(5); // section 22.14.2, 'HIGH' current limit, no apparent bit value constants in iox64d4.h - // NOTE: all other bits are zero - no 'freerun', 12-bit right-justified unsigned mode - - analog_reference = 1; // which is NONE of the possibilities - ADCA_REFCTRL = 0; // pre-assign zero to this, as I'll OR bits into it - -#ifdef USE_AREF - analogReference(USE_AREF); -#else // everything else - NOTE: do I want to do this different for 'A' series? - analogReference(analogReference_VCCDIV2); -#endif // USE_AREF - - - // TODO: is this actually a RESERVED functionality? - ADCA_SAMPCTRL = 24; // sect 22.14.8 - this value + 1 is # of "half cycles" used for sampling - // in this case, it's 25 "half cycles" at 100khz, or appx 8khz (125uS) - // adjust this for 'best accuracy' without taking for-freaking-evar - // also make sure the sample rate is lower than the 'HIGH LIMIT' max rate (see 22.14.2) - - // set up the channel (no offset calc at this time - later do an offset calc) - ADCA_CH0_SCAN = 0; // disable scan - ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3 - - - // clear interrupt flag (probably not needed) - ADCA_INTFLAGS = _BV(ADC_CH0IF_bp); // write a 1 to the interrupt bit (which clears it - 22.14.6) - - analogRead(0); // do a single conversion so that everything stabilizes - -// these are taken care of at the beginning of the function, as a 16-bit register assignment to ADCA_CAL -// ADCA.CALL = readCalibrationData(&PRODSIGNATURES_ADCACAL0); -// ADCA.CALH = readCalibrationData(&PRODSIGNATURES_ADCACAL1); -} - - -// see _analogReference_ enum - -static uint8_t normal_adca_ch0_ctrl_bits(void) // also assigns 'muxctrl_muxneg' -{ -#if defined (__AVR_ATxmega8E5__) || defined (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__) - - // NOTE: the E5 has a significant difference in how it handles 'DIFF WITH GAIN' - // ADC_CH_INPUTMODE_DIFFWGAINL_gc uses A0-A3, GND, and internal GND (not same as D and earlier) - // ADC_CH_INPUTMODE_DIFFWGAINH_gc uses A4-A7 and GND (see E manual table 24-16,17 pg 366-7) (similar to D and earlier) - - if(analog_reference == analogReference_VCCDIV2) - { - return ADC_CH_INPUTMODE_DIFFWGAINH_gc | ADC_CH_GAIN_DIV2_gc; // gain of 1/2 for VCC/2 - } - else - { - return ADC_CH_INPUTMODE_DIFFWGAINH_gc | ADC_CH_GAIN_1X_gc; - } - -#else // everything NOT an 'E' series - - if(analog_reference == analogReference_VCCDIV2) - { - // NOTE: On the A-series processors with more than a handful of inputs, - // it is NOT possible to use 'diff input with gain' on MORE than - // A0-A7. On later processors (like D series) it _IS_ possible. - // Because of this, the 'hack' that allows rail-rail measurements - // is no longer possible on PB0-PB7. PA0-PA7 will still work. - // IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL' - // then you can read all 15 remaining values with whatever VRef you want. - - return ADC_CH_INPUTMODE_DIFFWGAIN_gc | ADC_CH_GAIN_DIV2_gc; // gain of 1/2 for VCC/2 - } - else - { - // NOTE: this one uses a different 'muxneg' (see below, 'analogReference()') - - return ADC_CH_INPUTMODE_DIFF_gc | ADC_CH_GAIN_1X_gc; - } - -#endif // E series or not -} - -void analogReference(uint8_t bMode) -{ - if((bMode & ADC_REFSEL_gm) != bMode) - { - bMode &= ADC_REFSEL_gm; - } - - if(bMode != analog_reference) - { - analog_reference = bMode; - - // changes to this must be reflected in ADCA_REFCTRL and ADCA_CH0_MUXCTRL - // when I read a specific pin. I assign the 'muxneg' bits according muxctrl_muxneg - - ADCA_REFCTRL = (ADCA_REFCTRL & ~(ADC_REFSEL_gm)) - | analog_reference // section 22.14.3, or 28.16.3 in 'AU' manual - | ADC_BANDGAP_bm; // enable 'bandgap' i.e. 1V reference - - // NOTE: all other ADCA_REFCTRL bits are zero (like tempref) - section 22.14.3 - - // ASSIGNING ADCA_CH0_CTRL and muxctrl_muxneg - - ADCA_CH0_CTRL = normal_adca_ch0_ctrl_bits(); - - // assign 'muxneg' according to what teh analog reference is - -#if defined (__AVR_ATxmega8E5__) || (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__) - - muxctrl_muxneg = 7; /* bits 111 which is GND for MUXNEG - see E manual 24.15.2 */ - -#else // everything NOT an 'E' series - - if(analog_reference == analogReference_VCCDIV2) - { - // analog delta WITH GAIN always uses this - muxctrl_muxneg = 7; /* bits 111 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */ - } - else - { - // analog delta WITHOUT GAIN uses THIS - muxctrl_muxneg = 5; /* bits 101 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */ - } - -#endif // E series or not - - } -} - - -// For 100% atmega compatibility, analogRead will return a value of 0-1023 -// for input voltages of 0 to Vcc (assuming AVCC is connected to VCC, etc.) -// by using a gain of 1/2, a comparison of Vcc/2, and signed conversion - -int analogRead(uint8_t pin) -{ - short iRval; - - // this is pure XMEGA code - - if(pin >= A0) - { - if(pin >= (NUM_ANALOG_INPUTS + A0)) // pin number too high? - { - return 0; // not a valid analog input - } -#ifdef analogInputToAnalogPin - pin = analogInputToAnalogPin(pin); -#else // analogInputToAnalogPin - pin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An -#endif // analogInputToAnalogPin - } - else - { - // NOTE: for pins less than 'A0', assume it's referring to the analog index (0 to NUM_ANALOG_INPUTS-1) - - if(pin >= NUM_ANALOG_INPUTS) - { - return 0; // not a valid analog input - } - -#ifdef analogInputToAnalogPin - pin = analogInputToAnalogPin(pin + A0); // calc pin number (might not have 0 mapped to A0) -#endif // analogInputToAnalogPin - } - - // ANALOG REFERENCE - in some cases I can map one of the analog inputs - // as an analog reference. For now, assume it's Vcc/2. - - // NOTE: On the A-series processors with more than a handful of inputs, - // it is NOT possible to use 'diff input with gain' on MORE than - // A0-A7. On later processors (like D series) it _IS_ possible. - // Because of this, the 'hack' that allows rail-rail measurements - // is no longer possible on PB0-PB7. PA0-PA7 will still work. - // IF PA0 or PB0 is used as VRef (see 28.16.3 in AU manual) via 'REFCTRL' - // then you can read all 15 remaining values with whatever VRef you want. - - - ADCA_CH0_SCAN = 0; // disable scan - ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual - | muxctrl_muxneg; // typically, GND is the 'other input' (change via 'analogReference()') - - ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3 - -#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */ - ADCA_CH0_INTFLAGS = ADC_CH_IF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4) -#else // everyone else - ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4) -#endif // ADC_CH_IF_bm - - // NOTE: this will clear any re-assigned gain bits, etc. - // (if you want to preserve those, need to call 'analogReadDeltaWithGain()') - - ADCA_CH0_CTRL = normal_adca_ch0_ctrl_bits() - | ADC_CH_START_bm; // conversion start (bit will clear itself I think) - -#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */ - while(!(ADCA_CH0_INTFLAGS & ADC_CH_IF_bm)) { } -#else // everyone else - while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm)) { } -#endif // ADC_CH_IF_bm - - iRval = ADCA_CH0_RES; - - if(iRval < 0) // backward compatibility - { - return 0; - } - - return iRval / 2; // -1023 to 1023 but clipped at zero (so 0 to 1023 only) -} - -// THIS function returns a full 12-bit signed integer value (no scaling) -int analogReadDeltaWithGain(uint8_t pin, uint8_t negpin, uint8_t gain) -{ -short iRval; -uint8_t mode; - - // this is pure XMEGA code - // NOTE: On the A-series processors with more than a handful of inputs, - // it is NOT possible to use 'diff input with gain' on MORE than - // A0-A7. On later processors (like D series) it _IS_ possible. - - // TODO: check for A0-A7 for 'pin' for A series? - - - if(pin >= A0) - { - if(pin >= (NUM_ANALOG_INPUTS + A0)) // pin number too high? - { - return 0; // not a valid analog input - } -#ifdef analogInputToAnalogPin - pin = analogInputToAnalogPin(pin); -#else // analogInputToAnalogPin - pin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An -#endif // analogInputToAnalogPin - } - else - { - // NOTE: for pins less than 'A0', assume it's referring to the analog index (0 to NUM_ANALOG_INPUTS-1) - - if(pin >= NUM_ANALOG_INPUTS) - { - return 0; // not a valid analog input - } - -#ifdef analogInputToAnalogPin - pin = analogInputToAnalogPin(pin + A0); // calc pin number (might not have 0 mapped to A0) -#endif // analogInputToAnalogPin - } - -#if defined (__AVR_ATxmega8E5__) || defined (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__) - - // NOTE: the E5 has a significant difference in how it handles 'DIFF WITH GAIN' - // ADC_CH_INPUTMODE_DIFFWGAINL_gc uses A0-A3, GND, and internal GND (not same as D and earlier) - // ADC_CH_INPUTMODE_DIFFWGAINH_gc uses A4-A7 and GND (see E manual table 24-16,17 pg 366-7) (similar to D and earlier) - - if(negpin != ANALOG_READ_DELTA_USE_GND) - { - if(negpin >= A0) - { -#ifdef analogInputToAnalogPin - negpin = analogInputToAnalogPin(negpin); -#else // analogInputToAnalogPin - negpin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An -#endif // analogInputToAnalogPin - } - else - { - if(negpin >= NUM_ANALOG_INPUTS) - { - return 0; // not a valid analog input - } - -#ifdef analogInputToAnalogPin - negpin = analogInputToAnalogPin(negpin + A0); // calc pin number (might not have 0 mapped to A0) -#endif // analogInputToAnalogPin - } - - if(negpin >= 0 && negpin <= 3) - { - mode = ADC_CH_INPUTMODE_DIFFWGAINL_gc; - } - else if(negpin > 7) - { - return 0; // dis-allowed combination - } - else - { - mode = ADC_CH_INPUTMODE_DIFFWGAINH_gc; - - negpin -= 4; // so that it's 0-3 - } - } - else - { - mode = ADC_CH_INPUTMODE_DIFFWGAINL_gc; // see 24.15.2 section on 'MUXNEG' when using INTERNAL GND or PAD GND - } - -#else // NOT an 'E5' - - mode = ADC_CH_INPUTMODE_DIFFWGAIN_gc; - - // now for the negative pin, which will depend on a number of things - if(negpin != ANALOG_READ_DELTA_USE_GND) - { - if(negpin >= A0) - { -#ifdef analogInputToAnalogPin - negpin = analogInputToAnalogPin(negpin); -#else // analogInputToAnalogPin - negpin -= A0; // this works when PA0-PA7 and PB0-PBn are in sequence for A0-An -#endif // analogInputToAnalogPin - } - else - { - if(negpin >= NUM_ANALOG_INPUTS) - { - return 0; // not a valid analog input - } - -#ifdef analogInputToAnalogPin - negpin = analogInputToAnalogPin(negpin + A0); // calc pin number (might not have 0 mapped to A0) -#endif // analogInputToAnalogPin - } - - - if(negpin >= 0 && negpin <= 3 && gain != ADC_CH_GAIN_1X_gc) // allow this *IF* gain is 1X - { - return 0; // dis-allowed combination - } - else if(negpin >= 0 && negpin <= 3) - { - mode = ADC_CH_INPUTMODE_DIFF_gc; // just 'diff' mode, with 1X gain, for A0 to A3 - } - else if(negpin > 7) - { - return 0; // dis-allowed combination - } - else - { - negpin -= 4; // so that it's 0-3 - } - } - -#endif // 'E' series, or not - - ADCA_CH0_SCAN = 0; // disable scan - - // NOTE: assume 'CONVMODE' (CTRLB) is set to 'Signed' - if(negpin == ANALOG_READ_DELTA_USE_GND) - { -#if defined (__AVR_ATxmega8E5__) || (__AVR_ATxmega16E5__) || defined (__AVR_ATxmega32E5__) - ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual - | 7; /* bits 111 which is GND for MUXNEG - see E manual 24.15.2 */ -#else // everything NOT an 'E' series - if(mode == ADC_CH_INPUTMODE_DIFFWGAIN_gc) - { - ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual - | 7; /* bits 111 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */ - } - else - { - ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual - | 5; /* bits 101 which is GND for MUXNEG - see D manual 22.15.2, A manual 28.17.2 */ - } -#endif // E series or not - } - else - { - ADCA_CH0_MUXCTRL = (pin << ADC_CH_MUXPOS_gp) // sect 22.15.2 in 'D' manual, 28.17.2 in 'A' manual, 24.15.2 in 'E' manual - | negpin; // DIFF or 'DIFF WITH GAIN' uses this - } - - ADCA_CH0_INTCTRL = 0; // no interrupts, flag on complete sect 22.15.3 - -#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */ - ADCA_CH0_INTFLAGS = ADC_CH_IF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4) -#else // everyone else - ADCA_CH0_INTFLAGS = ADC_CH_CHIF_bm; // write a 1 to the interrupt bit (which clears it - 22.15.4) -#endif // ADC_CH_IF_bm - - - if(negpin == ANALOG_READ_DELTA_USE_GND) - { - // NOTE: On the A-series processors with more than a handful of inputs, - // it is NOT possible to use 'diff input with gain' on MORE than - // A0-A7. On later processors (like D series) it _IS_ possible. - - ADCA_CH0_CTRL = mode // ADC_CH_INPUTMODE_DIFFWGAIN_gc - | (gain & ADC_CH_GAIN_gm) - | ADC_CH_START_bm; // conversion start (bit will clear itself I think) - } - else - { - ADCA_CH0_CTRL = mode // ADC_CH_INPUTMODE_DIFFWGAIN_gc - | (gain & ADC_CH_GAIN_gm) - | ADC_CH_START_bm; // conversion start (bit will clear itself I think) - } - -#ifdef ADC_CH_IF_bm /* iox16e5.h and iox32e5.h - probably the ATMel Studio version */ - while(!(ADCA_CH0_INTFLAGS & ADC_CH_IF_bm)) { } -#else // everyone else - while(!(ADCA_CH0_INTFLAGS & ADC_CH_CHIF_bm)) { } -#endif // ADC_CH_IF_bm - - iRval = ADCA_CH0_RES; - - // TODO: scaling and clipping if needed, else +/- 2047 - - return iRval; -} - - -// Right now, PWM output only works on the pins with hardware support. -// These are defined in the appropriate pins_arduino.h file. For the -// rest of the pins, we default to digital output with a 1 or 0 - -#ifdef TCC4 -static void DoAnalogWriteForPort(TC4_t *port, uint8_t bit, uint8_t val); -#elif defined(TCC2) -static void DoAnalogWriteForPort(TC2_t *port, uint8_t bit, uint8_t val); -#else // TCC0 -static void DoAnalogWriteForPort(TC0_t *port, uint8_t bit, uint8_t val); -#endif // TCC4, TCC2, TCC0 - -// NOTE: for the xxE5, only 3, 4, 8, 9 seem to work properly with the default configuration -// that would be PORTD pins 4 and 5, and PORTC pins 2 and 3. PORTC pins 0 and 1 -// are mapped to the TWI pins SDA and SCL. As such, PORTD pins 4 and 5, and PORTC pins 0-3 -// will be allowed. Others will not. PORTD pins 6 and 7 are 'erratic' at best. - -void analogWrite(uint8_t pin, int val) -{ - // 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 consistenty with Wiring, which doesn't require a pinMode - // call for the analog output pins. - - // NOTE: period registers all contain zeros, which is the MAXIMUM period of 0-255 -#ifdef TCC4 /* 'E' series and later that have TCC4 */ - uint8_t mode; -#endif // TCC4 - uint8_t bit = digitalPinToBitMask(pin); - - pinMode(pin, OUTPUT); // forces 'totem pole' - TODO allow for something different? - - // note 'val' is a SIGNED INTEGER. deal with 'out of range' values accordingly - - if (val <= 0) - { - digitalWrite(pin, LOW); - } - else if (val >= 255) - { - digitalWrite(pin, HIGH); - } - else - { - // NOTE: according to the docs, 16-bit registers MUST be accessed - // low byte first, then high byte, before the actual value - // is transferred to the register. THIS code will. - // see A1U manual sect. 3.11 (and others as well) - - switch(digitalPinToTimer(pin)) - { -#ifdef TCC4 /* 'E' series and later that have TCC4 */ - - case TIMERC4: -#ifdef DEBUG_CODE - DebugOutP(PSTR("TIMERC4 ")); - DebugOutL(bit); - DebugOutP(PSTR(",")); - DebugOutL(val); - DebugOutP(PSTR("\r\n")); -#endif // DEBUG_CODE - - DoAnalogWriteForPort(&TCC4, bit, val); // TODO: smaller if inlined here? - break; - - case TIMERD5: - // THIS code is unique to the E5, most likely, so it's inlined - if(bit == 1 || bit == 16) // TODO: either bit? not sure if I can re-map these to 0-3 - { - *((volatile uint16_t *)&(TCD5_CCA)) = (TCD5_CCA & 0xff00) | (val & 0xff); - mode = (TCD5_CTRLE & ~TC5_LCCAMODE_gm) | TC5_LCCAMODE0_bm; - } - else if(bit == 2 || bit == 32) - { - *((volatile uint16_t *)&(TCD5_CCB)) = (TCD5_CCB & 0xff00) | (val & 0xff); - mode = (TCD5_CTRLE & ~TC5_LCCBMODE_gm) | TC5_LCCBMODE0_bm; - } - else if(bit == 4 || bit == 64) - { - *((volatile uint16_t *)&(TCD5_CCA)) = (TCD5_CCA & 0xff) | ((val << 8) & 0xff00); - mode = (TCD5_CTRLF & ~TC5_HCCAMODE_gm) | TC5_HCCAMODE0_bm; - } - else if(bit == 8 || bit == 128) - { - *((volatile uint16_t *)&(TCD5_CCB)) = (TCD5_CCB & 0xff) | ((val << 8) & 0xff00); - mode = (TCD5_CTRLF & ~TC5_HCCBMODE_gm) | TC5_HCCBMODE0_bm; - } - else - { - break; - } - -#ifdef DEBUG_CODE - DebugOutP(PSTR("TIMERD5 ")); - DebugOutL(bit); - DebugOutP(PSTR(",")); - DebugOutL(val); - DebugOutP(PSTR(",")); - DebugOutL(TCD5_CCA); - DebugOutP(PSTR(",")); - DebugOutL(TCD5_CCB); - DebugOutP(PSTR(",")); - DebugOutL(mode); - DebugOutP(PSTR("\r\n")); -#endif // DEBUG_CODE - - if(bit == 1 || bit == 2 || bit == 16 || bit == 32) - { - *((volatile uint8_t *)&(TCD5_CTRLE)) = mode; -#ifdef DEBUG_CODE - DebugOutP(PSTR("E!\r\n")); -#endif // DEBUG_CODE - } - else - { - *((volatile uint8_t *)&(TCD5_CTRLF)) = mode; -#ifdef DEBUG_CODE - DebugOutP(PSTR("F!\r\n")); -#endif // DEBUG_CODE - } - - break; - -#else // everything else NOT an 'E' series - - case TIMERD2: -#ifndef TCD2 - DoAnalogWriteForPort(&TCD0, bit, val); -#else // TCD2 defined - DoAnalogWriteForPort(&TCD2, bit, val); -#endif // TCD2 defined - break; - - case TIMERC2: - -#ifndef TCC2 - DoAnalogWriteForPort(&TCC0, bit, val); -#else // TCC2 defined - DoAnalogWriteForPort(&TCC2, bit, val); -#endif // TCC2 defined - break; - -#if NUM_DIGITAL_PINS > 22 /* meaning there is a PORT E available with 8 pins */ - - case TIMERE2: // TIMER 'E2' for 8-bits - -#ifndef TCE2 - DoAnalogWriteForPort(&TCE0, bit, val); -#else // TCE2 defined - DoAnalogWriteForPort(&TCE2, bit, val); -#endif // TCE2 defined - break; - -#if NUM_DIGITAL_PINS > 30 /* meaning there is a PORT F available */ - - case TIMERF2: - -#ifndef TCF2 - DoAnalogWriteForPort(&TCF0, bit, val); -#else // TCF2 defined - DoAnalogWriteForPort(&TCF2, bit, val); -#endif // TCF2 defined - break; - - -#endif // NUM_DIGITAL_PINS > 30 - -#elif NUM_DIGITAL_PINS > 18 /* meaning there is a PORT E available but with only 4 pins */ - - case TIMERE0: - // timer E0 counts UP, but a value of 0 would still generate a '0' output because - // the output STARTS at a 1, and flips to 0 when the CTR reaches the CC register - // Similarly, a value of 255 would generate a '1'. see section 12.8.3 in the 'D' manual - if(bit == 1) - { - TCE0_CCA = val; // NOTE: these are 16-bit registers (but I'm in 8-bit mode so it's fine) - } - else if(bit == 2) - { - TCE0_CCB = val; - } - else if(bit == 4) - { - TCE0_CCC = val; - } - else if(bit == 8) - { - TCE0_CCD = val; - } - -// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode -// TCE0_CTRLB = TC_WGMODE_SS_gc; // single-slope PWM. NOTE: this counts UP, whereas the other timers count DOWN - - TCE0_CTRLB |= (bit << 4); // enables output (0-3 only, but that's all PORT E has anyway) - // note that the 'enable' bits are in CTRLB and in upper nybble - break; - - -#endif // NUM_DIGITAL_PINS >= 18, 24 - -#endif // TCC4 check - - case NOT_ON_TIMER: - default: - if (val < 128) - { - digitalWrite(pin, LOW); - } - else - { - digitalWrite(pin, HIGH); - } - } - } -} - - - -#ifdef TCC4 -void DoAnalogWriteForPort(TC4_t *port, uint8_t bit, uint8_t val) -{ -uint8_t modeE, modeF; - - modeE = port->CTRLE; - modeF = port->CTRLF; - - if(bit == 1) - { - port->CCA = (port->CCA & 0xff00) | (val & 0xff); - modeE = (modeE & ~TC4_LCCAMODE_gm) | TC45_LCCAMODE_COMP_gc; - } - else if(bit == 2) - { - port->CCB = (port->CCB & 0xff00) | (val & 0xff); - modeE = (modeE & ~TC4_LCCBMODE_gm) | TC45_LCCBMODE_COMP_gc; - } - else if(bit == 4) - { - port->CCC = (port->CCC & 0xff00) | (val & 0xff); - modeE = (modeE & ~TC4_LCCCMODE_gm) | TC45_LCCCMODE_COMP_gc; - } - else if(bit == 8) - { - port->CCD = (port->CCD & 0xff00) | (val & 0xff); - modeE = (modeE & ~TC4_LCCDMODE_gm) | TC45_LCCDMODE_COMP_gc; - } - else if(bit == 16) - { - port->CCA = (port->CCA & 0xff) | ((val << 8) & 0xff00); - modeF = (modeF & ~TC4_HCCAMODE_gm) | TC45_HCCAMODE_COMP_gc; - } - else if(bit == 32) - { - port->CCB = (port->CCB & 0xff) | ((val << 8) & 0xff00); - modeF = (modeF & ~TC4_HCCBMODE_gm) | TC45_HCCBMODE_COMP_gc; - } - else if(bit == 64) - { - port->CCC = (port->CCC & 0xff) | ((val << 8) & 0xff00); - modeF = (modeF & ~TC4_HCCCMODE_gm) | TC45_HCCCMODE_COMP_gc; - } - else if(bit == 128) - { - port->CCD = (port->CCD & 0xff) | ((val << 8) & 0xff00); - modeF = (modeF & ~TC4_HCCDMODE_gm) | TC45_HCCDMODE_COMP_gc; - } - else - { - return; - } - - port->CTRLE = modeE; - port->CTRLF = modeF; - -// if(bit <= 8) -// { -// port->CTRLE = mode; -// } -// else -// { -// port->CTRLF = mode; -// } -} -#elif defined(TCC2) -void DoAnalogWriteForPort(TC2_t *port, uint8_t bit, uint8_t val) -{ - // NOTE: timers C2 and D2 count DOWN, always. However, the output starts at zero - // and flips to 1 when CTR reaches the CMP value. So a value of 255 would be - // '1' and 0 would be '0', as is expected. See 'D' manual 13.6.2 - if(bit == 1) - { - port->LCMPA = val; - } - else if(bit == 2) - { - port->LCMPB = val; - } - else if(bit == 4) - { - port->LCMPC = val; - } - else if(bit == 8) - { - port->LCMPD = val; - } - else if(bit == 16) - { - port->HCMPA = val; - } - else if(bit == 32) - { - port->HCMPB = val; - } - else if(bit == 64) - { - port->HCMPC = val; - } - else if(bit == 128) - { - port->HCMPD = val; - } - -// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode -// port->CTRLB = TC45_WGMODE_SINGLESLOPE_gc; - port->CTRLB |= bit; // enables output -} -#else // TCC0 -void DoAnalogWriteForPort(TC0_t *port, uint8_t bit, uint8_t val) -{ - // NOTE: timers C2 and D2 count DOWN, always. However, the output starts at zero - // and flips to 1 when CTR reaches the CMP value. So a value of 255 would be - // '1' and 0 would be '0', as is expected. See 'D' manual 13.6.2 - if(bit == 1) - { - port->CCA = (port->CCA & 0xff00) | (val & 0xff); - } - else if(bit == 2) - { - port->CCB = (port->CCB & 0xff00) | (val & 0xff); - } - else if(bit == 4) - { - port->CCC = (port->CCC & 0xff00) | (val & 0xff); - } - else if(bit == 8) - { - port->CCD = (port->CCD & 0xff00) | (val & 0xff); - } - else if(bit == 16) - { - port->CCA = (port->CCA & 0xff) | ((val << 8) & 0xff00); - } - else if(bit == 32) - { - port->CCB = (port->CCB & 0xff) | ((val << 8) & 0xff00); - } - else if(bit == 64) - { - port->CCC = (port->CCC & 0xff) | ((val << 8) & 0xff00); - } - else if(bit == 128) - { - port->CCD = (port->CCD & 0xff) | ((val << 8) & 0xff00); - } - -// this is a reminder that the low nybble should be assigned the correct value for single-slope PWM mode -// port->CTRLB = TC45_WGMODE_SINGLESLOPE_gc; - port->CTRLB |= bit; // enables output -} -#endif // TCC4, TCC2, TCC0 - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c b/BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c deleted file mode 100644 index 0c3598c..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c +++ /dev/null @@ -1,428 +0,0 @@ -/* - wiring_digital.c - digital input and output functions - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - Modified 28 September 2010 by Mark Sproul - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - In some cases, the xmega updates make assumptions about the pin assignments. - See 'pins_arduino.h' for more detail. - -*/ - -#define ARDUINO_MAIN -#include "wiring_private.h" -#include "pins_arduino.h" - -void pinMode(uint8_t pin, uint8_t mode) -{ - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - uint8_t sense = mode & INPUT_SENSE_MASK; - uint8_t invert = mode & INPUT_OUTPUT_INVERT; - volatile uint8_t *reg, /* *out,*/ *ctrl; - - mode &= INPUT_OUTPUT_MASK; // remove 'sense' bits - - if (port == NOT_A_PIN) - { - return; - } - - reg = portModeRegister(port); // D manual section 11.12.1 - - if(sense == INPUT_SENSE_DISABLED && reg != &PORTR_DIR) // 'DISABLED' - { - sense = PORT_ISC_INPUT_DISABLE_gc; // bit values for 'INTPUT_DISABLED' (sic) - } - else if(sense == INPUT_SENSE_RISING) - { - sense = PORT_ISC_RISING_gc; // rising - } - else if(sense == INPUT_SENSE_FALLING) - { - sense = PORT_ISC_FALLING_gc; // falling - } - else if(sense == INPUT_SENSE_LEVEL) - { - sense = PORT_ISC_LEVEL_gc; // LOW level (except events, which use HIGH level) - } - else // if(sense == INPUT_SENSE_BOTH) all others including 'DEFAULT' - { - sense = PORT_ISC_BOTHEDGES_gc; // 'both rising and falling' - } - - if(invert) // inverted bit value - { - sense |= _BV(PORT_INVEN_bp); // see 11.12.15 in D manual - 'invert' bit - } - - - // JWS: can I let the optimizer do this? -// reg = portModeRegister(port); // D manual section 11.12.1 (MOVED upwards, BBB) -// out = portOutputRegister(port); // D manual section 11.12.5 (not used - BBB) - ctrl = pinControlRegister(pin); // D manual section 11.12.15 - - uint8_t oldSREG = SREG; - cli(); // clear interrupt flag until I'm done assigning pin stuff - - if (mode == INPUT) - { - *ctrl = sense | PORT_OPC_TOTEM_gc; - - *reg &= ~bit; - } - else if (mode == INPUT_PULLUP) - { - *ctrl = sense | PORT_OPC_PULLUP_gc; // input pullup - - *reg &= ~bit; - } - else if (mode == INPUT_AND_PULLUP) - { - *ctrl = sense | PORT_OPC_WIREDANDPULL_gc; // wired 'and' (open drain) with pullup - - *reg &= ~bit; - } - else if (mode == INPUT_PULLDOWN) - { - *ctrl = sense | PORT_OPC_PULLDOWN_gc; // input pullDOWN - - *reg &= ~bit; - } - else if (mode == INPUT_OR_PULLDOWN) - { - *ctrl = sense | PORT_OPC_WIREDORPULL_gc; // wired 'or' (open drain) with pulldown - - *reg &= ~bit; - } - else if (mode == INPUT_BUS_KEEPER) - { - *ctrl = sense | PORT_OPC_BUSKEEPER_gc; // bus keeper - - *reg &= ~bit; - } - else if (mode == OUTPUT_OR) - { - *ctrl = sense | PORT_OPC_WIREDOR_gc; // wired 'or' (open drain) - - *reg |= bit; - } - else if (mode == OUTPUT_AND) - { - *ctrl = sense | PORT_OPC_WIREDAND_gc; // wired 'and' (open drain) - - *reg |= bit; - } - else if (mode == OUTPUT_OR_PULLDOWN) - { - *ctrl = sense | PORT_OPC_WIREDORPULL_gc; // wired 'or' (open drain) with pulldown - - *reg |= bit; - } - else if (mode == OUTPUT_AND_PULLUP) - { - *ctrl = sense | PORT_OPC_WIREDANDPULL_gc; // wired 'and' (open drain) with pullup - - *reg |= bit; - } - else // if(mode == OUTPUT) assume OUTPUT without open drain and/or nor pullup/down - { - *ctrl = sense | PORT_OPC_TOTEM_gc; // 'totem pole' (the default) - - *reg |= bit; - } - - SREG = oldSREG; - -} - -// Forcing this inline keeps the callers from having to push their own stuff -// on the stack. It is a good performance win and only takes 1 more byte per -// 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. -// -// Mark Sproul: -// - Removed inline. Save 170 bytes on atmega1280 -// - changed to a switch statment; added 32 bytes but much easier to read and maintain. -// - Added more #ifdefs, now compiles for atmega645 -// -//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); -//static inline void turnOffPWM(uint8_t timer) - -// BBB - added 'bit' parameter for xmega - it's a bit MASK, not a bit number -// use the result from digitalPinToBitMask(pin) for 'bit' - -static void turnOffPWM(uint8_t timer, uint8_t bit) -{ -#ifdef TCC4 /* 'E' series and later that have TCC4 */ -register uint8_t mode; -#endif // TCC4 - - switch (timer) - { -#ifdef TCC4 /* 'E' series and later that have TCC4 */ - case TIMERC4: - - if(bit == 1) - { - mode = (TCC4_CTRLE & ~TC4_LCCAMODE_gm); - } - else if(bit == 2) - { - mode = (TCC4_CTRLE & ~TC4_LCCBMODE_gm); - } - else if(bit == 4) - { - mode = (TCC4_CTRLE & ~TC4_LCCCMODE_gm); - } - else if(bit == 8) - { - mode = (TCC4_CTRLE & ~TC4_LCCDMODE_gm); - } - else if(bit == 16) - { - mode = (TCC4_CTRLF & ~TC4_HCCAMODE_gm); - } - else if(bit == 32) - { - mode = (TCC4_CTRLF & ~TC4_HCCBMODE_gm); - } - else if(bit == 64) - { - mode = (TCC4_CTRLF & ~TC4_HCCCMODE_gm); - } - else if(bit == 128) - { - mode = (TCC4_CTRLF & ~TC4_HCCDMODE_gm); - } - else - { - break; - } - - if(bit <= 8) - { - TCC4_CTRLE = mode; - } - else - { - TCC4_CTRLF = mode; - } - - break; - - case TIMERD5: - - if(bit == 1 || bit == 16) - { - mode = (TCD5_CTRLE & ~TC5_LCCAMODE_gm); - } - else if(bit == 2 || bit == 32) - { - mode = (TCD5_CTRLE & ~TC5_LCCBMODE_gm); - } - else if(bit == 4 || bit == 64) - { - mode = (TCD5_CTRLF & ~TC5_HCCAMODE_gm); - } - else if(bit == 8 || bit == 128) - { - mode = (TCD5_CTRLF & ~TC5_HCCBMODE_gm); - } - else - { - break; - } - - // TODO: check to see if it was enabled AND the bit was configured properly for PWM - // AND was properly mapped (L vs H, REMAP register?) - if(bit == 1 || bit == 2 || bit == 16 || bit == 32) - { - TCD5_CTRLE = mode; - } - else - { - TCD5_CTRLF = mode; - } - - break; - -#else // everything else NOT an 'E' series - -#ifndef TCC2 /* A1 series does not define this and I need TC0 */ - - case TIMERD2: - TCD0_CTRLB &= ~bit; // DISables PWM output - break; - - case TIMERC2: - TCC0_CTRLB &= ~bit; // DISables PWM output - break; - -#if NUM_DIGITAL_PINS > 22 /* which means we have PORT E but with 8 pins, not 4 */ - - case TIMERE2: - TCE0_CTRLB &= ~bit; // DISables PWM output - break; - -#if NUM_DIGITAL_PINS > 30 /* which means we have PORT F */ - - case TIMERF2: - TCF0_CTRLB &= ~bit; // DISables PWM output - break; -#endif // NUM_DIGITAL_PINS > 30 - -#elif NUM_DIGITAL_PINS > 18 /* which means we have PORT E but only with 4 pins */ - case TIMERE0: - TCE0_CTRLB &= ~(bit << 4); // DISables PWM output - // note that the 'enable' bits are in CTRLB and in upper nybble - break; -#endif // NUM_DIGITAL_PINS > 18, 22 - -#else // TCC2 - case TIMERD2: - TCD2_CTRLB &= ~bit; // DISables PWM output - break; - - case TIMERC2: - TCC2_CTRLB &= ~bit; // DISables PWM output - break; - -#if NUM_DIGITAL_PINS > 22 /* which means we have PORT E but with 8 pins, not 4 */ - - case TIMERE2: - TCE2_CTRLB &= ~bit; // DISables PWM output - break; - -#if NUM_DIGITAL_PINS > 30 /* which means we have PORT F */ - - case TIMERF2: - TCF2_CTRLB &= ~bit; // DISables PWM output - break; -#endif // NUM_DIGITAL_PINS > 30 - -#elif NUM_DIGITAL_PINS > 18 /* which means we have PORT E but only with 4 pins */ -// TODO: 64d4 has 4 pins on PORT E. 128A1 has 8 pins on PORT E. determine which to use? - case TIMERE0: - TCE0_CTRLB &= ~(bit << 4); // DISables PWM output - // note that the 'enable' bits are in CTRLB and in upper nybble - break; -#endif // NUM_DIGITAL_PINS > 18, 22 - -#endif // TCC2 -#endif // TCC4 - } -} - -void digitalWrite(uint8_t pin, uint8_t val) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *out, *ctrl; - - if (port == NOT_A_PIN) - { - return; - } - - ctrl = pinControlRegister(pin); // D manual section 11.12.15 - - if(*ctrl & _BV(PORT_INVEN_bp)) // inverted - { - val = !val; // invert the value (so it's consistent with the pin) - } - - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - - // TODO: move this feature to pinMode() like it should be - // or set a flag to be used with analogWrite() - // (for now it's probably faster just to call it) - - if (timer != NOT_ON_TIMER) - { - turnOffPWM(timer, bit); - } - - out = portOutputRegister(port); - - uint8_t oldSREG = SREG; - cli(); - - if (val == LOW) - { - *out &= ~bit; - } - else - { - *out |= bit; - } - - SREG = oldSREG; -} - -int digitalRead(uint8_t pin) -{ - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *ctrl; - uint8_t bSet; - - if (port == NOT_A_PIN) - { - return LOW; - } - - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - - // TODO: move this feature to pinMode() like it should be - // or set a flag to be used with analogWrite() - // (for now it's probably faster just to call it) - - if (timer != NOT_ON_TIMER) - { - turnOffPWM(timer, bit); - } - - bSet = (*portInputRegister(port) & bit) ? true : false; - - // if the 'invert' flag is on, I invert the digital value - // this is so that the result of 'digitalRead' and 'digitalWrite' - // are ALWAYS consistent with the actual pin level. Inversion is - // needed for proper interrupt control. So for the best consistency, - // the invert flag will only (really) be needed for LEVEL interrupts. - - ctrl = pinControlRegister(pin); // D manual section 11.12.15 - - if(*ctrl & _BV(PORT_INVEN_bp)) // inverted - { - bSet = !bSet; - } - - return bSet ? HIGH : LOW; -} - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h b/BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h deleted file mode 100644 index 3218324..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - wiring_private.h - Internal header file. - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ -*/ - -#ifndef WiringPrivate_h -#define WiringPrivate_h - -#include -#include -#include -#include - -#include "Arduino.h" - -// things that need to be defined in order for the code to compile - -// definitions for ADC-related product signature row entries -#ifndef PRODSIGNATURES_ADCACAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_ADCACAL0 _SFR_MEM8(0x0020) -#endif // PRODSIGNATURES_ADCACAL0 - -#ifndef PRODSIGNATURES_ADCACAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_ADCACAL1 _SFR_MEM8(0x0021) -#endif // PRODSIGNATURES_ADCACAL1 - -#ifndef PRODSIGNATURES_ADCBCAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_ADCBCAL0 _SFR_MEM8(0x0024) -#endif // PRODSIGNATURES_ADCBCAL0 - -#ifndef PRODSIGNATURES_ADCBCAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_ADCBCAL1 _SFR_MEM8(0x0025) -#endif // PRODSIGNATURES_ADCBCAL1 - -// definitions for USB-related product signature row entries -#ifndef PRODSIGNATURES_USBCAL0 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_USBCAL0 _SFR_MEM8(0x001a) -#endif // PRODSIGNATURES_USBCAL0 - -#ifndef PRODSIGNATURES_USBCAL1 /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_USBCAL1 _SFR_MEM8(0x001b) -#endif // PRODSIGNATURES_USBCAL1 - -#ifndef PRODSIGNATURES_USBRCOSC /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_USBRCOSC _SFR_MEM8(0x001c) -#endif // PRODSIGNATURES_USBRCOSC - -#ifndef PRODSIGNATURES_USBRCOSCA /* _MOST_ headers don't define this properly - see ATMel Studio headers */ -#define PRODSIGNATURES_USBRCOSCA _SFR_MEM8(0x001d) -#endif // PRODSIGNATURES_USBRCOSCA - - - -#ifndef ADCA_CH0_SCAN /* A1 headers don't define this properly */ -#define ADCA_CH0_SCAN _SFR_MEM8(0x0226) -#define ADC_REFSEL_INTVCC2_gc (0x04<<4) -#define ADC_CH_GAIN_DIV2_gc (0x07<<2) -#endif // ADCA_CH0_SCAN - -#ifndef ADC_REFSEL2_bm /* A1 headers don't define this properly, but A1U headers do [and others] */ -#define ADC_REFSEL2_bm (1<<6) /* Reference Selection bit 2 mask. */ -#define ADC_REFSEL2_bp 6 /* Reference Selection bit 2 position. */ -#endif // ADC_REFSEL2_bm - -#ifndef PORT_USART0_bm -#define PORT_USART0_bm 0x10 /* Usart0 bit mask for port remap register. */ -#endif // PORT_USART0_bm - - -#ifdef __cplusplus -extern "C"{ -#endif - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -// NOTE: xmega is SO different that these need to be in pins_arduino.h -// some xmegas have 2 per port, others 1 per port, and the # of ports vary greatly -//#define EXTERNAL_INT_0 0 -//#define EXTERNAL_INT_1 1 -//#define EXTERNAL_INT_2 2 -//#define EXTERNAL_INT_3 3 -//#define EXTERNAL_INT_4 4 -//#define EXTERNAL_INT_5 5 -//#define EXTERNAL_INT_6 6 -//#define EXTERNAL_INT_7 7 - -// CPU-specific definitions go into the 'pins_arduino.h' files anyway -// -//#if defined(SOME_CPU) -//#define EXTERNAL_NUM_INTERRUPTS 8 -//#endif - -typedef void (*voidFuncPtr)(void); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif - - diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c b/BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c deleted file mode 100644 index ee16fdc..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - wiring_pulse.c - pulseIn() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.h" -#include "pins_arduino.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 - * to 3 minutes in length, but must be called at least a few dozen microseconds - * before the start of the pulse. */ -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); - unsigned long width = 0; // keep initialization out of time critical area - - // convert the timeout from microseconds to a number of times through - // the initial loop; it takes 16 clock cycles per iteration. - unsigned long numloops = 0; - unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; - - // wait for any previous pulse to end - while ((*portInputRegister(port) & bit) == stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to start - while ((*portInputRegister(port) & bit) != stateMask) - if (numloops++ == maxloops) - return 0; - - // wait for the pulse to stop - while ((*portInputRegister(port) & bit) == stateMask) { - if (numloops++ == maxloops) - return 0; - width++; - } - - // convert the reading to microseconds. The loop has been determined - // to be 20 clock cycles long and have about 16 clocks between the edge - // and the start of the loop. There will be some error introduced by - // the interrupt handlers. - return clockCyclesToMicroseconds(width * 21 + 16); -} diff --git a/BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c b/BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c deleted file mode 100644 index e335755..0000000 --- a/BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - wiring_shift.c - shiftOut() function - Part of Arduino - http://www.arduino.cc/ - - Copyright (c) 2005-2006 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 - - $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ -*/ - -#include "wiring_private.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, 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); - } -} diff --git a/BootLoaders/Boards/orangerx/platform.local.txt b/BootLoaders/Boards/orangerx/platform.local.txt deleted file mode 100644 index 28b3377..0000000 --- a/BootLoaders/Boards/orangerx/platform.local.txt +++ /dev/null @@ -1,25 +0,0 @@ -## Save hex -recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file=multi-orx.hex - -## Override some platform.txt settings to create a .bin instead of a .hex file -## The two lines below can be uncommented to have the compiler create a .bin file instead of a .hex file -#compiler.elf2hex.flags=-O binary -R .eeprom -#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}.bin" - -## Make a .bin version of the .hex file -## The line below can be uncommented to have a .bin file made as well as the .hex file -#recipe.hooks.objcopy.postobjcopy.00.pattern.windows="{compiler.path}{compiler.objcopy.cmd}" -I ihex "{build.path}/{build.project_name}.hex" -O binary "{build.path}/{build.project_name}.bin" - -## Copy hex -# Make a copy of the compiled binary with the version number in the file name -recipe.hooks.objcopy.postobjcopy.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} -recipe.hooks.objcopy.postobjcopy.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} - -# If we're exporting the hex file, rename it with the version number -recipe.hooks.savehex.postsavehex.01.pattern.windows="{runtime.platform.path}/tools/win/do_version.bat" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.linux="{runtime.platform.path}/tools/linux/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.linux64="{runtime.platform.path}/tools/linux64/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT -recipe.hooks.savehex.postsavehex.01.pattern.macosx="{runtime.platform.path}/tools/macosx/do_version" "{build.path}" "{build.project_name}" "{build.source.path}" {build.board} EXPORT diff --git a/BootLoaders/Boards/orangerx/platform.txt b/BootLoaders/Boards/orangerx/platform.txt deleted file mode 100644 index da6dcb2..0000000 --- a/BootLoaders/Boards/orangerx/platform.txt +++ /dev/null @@ -1,124 +0,0 @@ -name=Multi 4-in-1 OrangeRX -version=1.0.1 - -# this was borrowed from the installed version of 'platform.txt' -# XMEGA compile variables -# --------------------- - -compiler.warning_flags=-w -compiler.warning_flags.none=-w -compiler.warning_flags.default= -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.path}/bin/ -compiler.c.cmd=avr-gcc -compiler.c.flags=-c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -MMD -flto -compiler.c.elf.flags={compiler.warning_flags} -Os -flto -Wl,--gc-sections -compiler.c.elf.cmd=avr-gcc -compiler.S.flags=-c -g -x assembler-with-cpp -flto -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 -MMD -flto -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.elf2hex.flags=-O ihex -R .eeprom -compiler.elf2hex.cmd=avr-objcopy -compiler.ldflags= -compiler.size.cmd=avr-size - -# This can be overridden in boards.txt -build.extra_flags= - -# These can be overridden in platform.local.txt -compiler.c.extra_flags= -compiler.c.elf.extra_flags= -compiler.S.extra_flags= -compiler.cpp.extra_flags= -compiler.ar.extra_flags= -compiler.objcopy.eep.extra_flags= -compiler.elf2hex.extra_flags= - -# XMEGA compile patterns -# -------------------- - -## Compile c files -recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile c++ files -recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Compile S files -recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.S.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}" - -## Create archives -# archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value -archive_file_path={build.path}/{archive_file} -recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}" - -## Combine gc-sections, archives, and objects -recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm - -## Create output files (.eep and .hex) -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 hex -recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file={build.project_name}.{build.variant}.hex - -## 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.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* -recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).* - -## Preprocessor -preproc.includes.flags=-w -x c++ -M -MG -MP -recipe.preproc.includes="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.includes.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" - -preproc.macros.flags=-w -x c++ -E -CC -recipe.preproc.macros="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} {preproc.macros.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{preprocessed_file_path}" - -# XMEGA Uploader/Programmers tools -# ------------------------------ - -tools.avrdude.path={runtime.tools.avrdude.path} -tools.avrdude.cmd.path={path}/bin/avrdude -# NOTE: change to avrdude.conf path - using the one specified by this hardware package -# THIS is a LOT 'nicer' than overwriting the system file. Some packages actually do that... -tools.avrdude.config.path={runtime.platform.path}/avrdude.conf - -tools.avrdude.upload.params.verbose=-v -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} -P{serial.port} -b{upload.speed} -D "-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" - -tools.avrdude.erase.params.verbose=-v -tools.avrdude.erase.params.quiet=-q -q -tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Ufuse1:w:{bootloader.fuse1}:m -Ufuse2:w:{bootloader.fuse2}:m -Ufuse4:w:{bootloader.fuse4}:m -Ufuse5:w:{bootloader.fuse5}: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} "-Uboot:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -Ulock:w:{bootloader.lock_bits}:m - -tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu} - -# USB Default Flags -# Default blank usb manufacturer will be filled in at compile time -# - from numeric vendor ID, set to Unknown otherwise -build.usb_manufacturer="Unknown" -build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' - - diff --git a/BootLoaders/Boards/orangerx/tools/linux/do_version b/BootLoaders/Boards/orangerx/tools/linux/do_version deleted file mode 100755 index 184015b..0000000 --- a/BootLoaders/Boards/orangerx/tools/linux/do_version +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -BUILD_PATH=$1 -PROJECT_NAME=$2 -SKETCH_PATH=$3 -MULTI_BOARD=$4 -EXPORT_FLAG=$5 - -MULTI_TYPE=orx - -if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then - MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - - MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION -else - MULTI_VERSION= -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" -fi - -if [ $# -eq 5 ]; then - if [ $EXPORT_FLAG == "EXPORT" ]; then - - if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" - fi - if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" - fi - - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex" - fi - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin" - fi - fi -fi diff --git a/BootLoaders/Boards/orangerx/tools/linux64/do_version b/BootLoaders/Boards/orangerx/tools/linux64/do_version deleted file mode 100755 index 184015b..0000000 --- a/BootLoaders/Boards/orangerx/tools/linux64/do_version +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -BUILD_PATH=$1 -PROJECT_NAME=$2 -SKETCH_PATH=$3 -MULTI_BOARD=$4 -EXPORT_FLAG=$5 - -MULTI_TYPE=orx - -if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then - MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - - MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION -else - MULTI_VERSION= -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" -fi - -if [ $# -eq 5 ]; then - if [ $EXPORT_FLAG == "EXPORT" ]; then - - if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" - fi - if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" - fi - - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex" - fi - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin" - fi - fi -fi diff --git a/BootLoaders/Boards/orangerx/tools/macosx/do_version b/BootLoaders/Boards/orangerx/tools/macosx/do_version deleted file mode 100755 index 184015b..0000000 --- a/BootLoaders/Boards/orangerx/tools/macosx/do_version +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -BUILD_PATH=$1 -PROJECT_NAME=$2 -SKETCH_PATH=$3 -MULTI_BOARD=$4 -EXPORT_FLAG=$5 - -MULTI_TYPE=orx - -if [ -e "$BUILD_PATH/sketch/Multiprotocol.h" ]; then - MAJOR_VERSION=$(grep "VERSION_MAJOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - MINOR_VERSION=$(grep "VERSION_MINOR" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - REVISION_VERSION=$(grep "VERSION_REVISION" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - PATCH_VERSION=$(grep "VERSION_PATCH" "$BUILD_PATH/sketch/Multiprotocol.h" | awk -v N=3 '{print $N}') - - MULTI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$REVISION_VERSION.$PATCH_VERSION -else - MULTI_VERSION= -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" -fi - -if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$BUILD_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" -fi - -if [ $# -eq 5 ]; then - if [ $EXPORT_FLAG == "EXPORT" ]; then - - if [ -e "$BUILD_PATH/$PROJECT_NAME.hex" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.hex" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.hex" - fi - if [ -e "$BUILD_PATH/$PROJECT_NAME.bin" ]; then - cp "$BUILD_PATH/$PROJECT_NAME.bin" "$SKETCH_PATH/multi-$MULTI_TYPE-$MULTI_VERSION.bin" - fi - - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.hex" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.hex" - fi - if [ -e "$SKETCH_PATH/multi-$MULTI_TYPE.bin" ]; then - rm "$SKETCH_PATH/multi-$MULTI_TYPE.bin" - fi - fi -fi diff --git a/BootLoaders/Boards/orangerx/tools/win/do_version.bat b/BootLoaders/Boards/orangerx/tools/win/do_version.bat deleted file mode 100644 index 1681960..0000000 --- a/BootLoaders/Boards/orangerx/tools/win/do_version.bat +++ /dev/null @@ -1,67 +0,0 @@ -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -REM SET DEBUG=1 - -SET BUILD_PATH=%1 -SET PROJECT_NAME=%2 -SET SKETCH_PATH=%3 -SET MULTI_BOARD=%4 -SET EXPORT_FLAG=%5 - -REM Remove double-quotes from the paths -SET BUILD_PATH=%BUILD_PATH:"=% -SET SKETCH_PATH=%SKETCH_PATH:"=% - -IF DEFINED DEBUG ( - ECHO Sketch Path: %SKETCH_PATH% - ECHO Multi board: %MULTI_BOARD% -) - -SET MULTI_TYPE=orx - -IF EXIST "%BUILD_PATH%\sketch\Multiprotocol.h" ( - IF DEFINED DEBUG ECHO Getting Multi-MODULE firmware version from "%BUILD_PATH%\sketch\Multiprotocol.h" - FOR /F "tokens=* usebackq" %%A in (`%SystemRoot%\system32\findstr.exe /C:"#define VERSION_MAJOR" "%BUILD_PATH%\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i - FOR /F "tokens=* usebackq" %%B in (`%SystemRoot%\system32\findstr.exe /C:"#define VERSION_MINOR" "%BUILD_PATH%\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i - FOR /F "tokens=* usebackq" %%C in (`%SystemRoot%\system32\findstr.exe /C:"#define VERSION_REVISION" "%BUILD_PATH%\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i - FOR /F "tokens=* usebackq" %%D in (`%SystemRoot%\system32\findstr.exe /C:"#define VERSION_PATCH_LEVEL" "%BUILD_PATH%\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%D") do SET PATCH_VERSION=%%i - SET MULTI_VER=!MAJOR_VERSION!.!MINOR_VERSION!.!REVISION_VERSION!.!PATCH_VERSION! -) ELSE ( - SET MULTI_VER= -) - -IF DEFINED DEBUG ECHO Multi-MODULE firmware version: %MULTI_VER% - -REM Copy the compiled file to the sketch folder with the version number in the file name -IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" ( - IF DEFINED DEBUG ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y - COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL -) - -IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" ( - IF DEFINED DEBUG ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y - COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%BUILD_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL -) - -IF "%EXPORT_FLAG%"=="EXPORT" ( -REM Copy the compiled file to the sketch folder with the version number in the file name - IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.hex" ( - IF DEFINED DEBUG ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y - COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL - ) - - IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" ( - IF DEFINED DEBUG ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y - COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL - ) - - IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" ( - IF DEFINED DEBUG ECHO DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" - DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL - ) - IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" ( - IF DEFINED DEBUG ECHO DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" - DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL - ) -) diff --git a/BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h b/BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h deleted file mode 100644 index 81ff9f8..0000000 --- a/BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h +++ /dev/null @@ -1,702 +0,0 @@ -/* - 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 - - Updated for 'xmega' core by bob frazier, S.F.T. Inc. - http://mrp3.com/ - - X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A - - The xmega code mods make a considerable number of assumptions - about the pin number assignments (as defined here): - - DEFAULT MAPPING ('DIGITAL_IO_PIN_SHIFT' NOT DEFINED) - ---------------------------------------------------- - PORTD - digital 0-7 - PORTC - digital 8-15 - PORTE - digital 16-20 - PORTR - digital 20-21 (built-in LED on PORTR pin 1, aka '21') - PORTA - analog 0-7, digital 22-29 - PORTB - analog 8-11, digital 30-33 - - SPI is assumed to be on PORTC (pins 4-7) - Serial is implemented on PORTD, Serial2 on PORTC, both using pins 2,3 (no flow control) - PORTR pin 1 is assumed to be connected to an LED. Pin 1 is the 'built-in' LED, defined - as 'LED_BUILTIN', and is active HIGH. - - Your Mileage May Vary, depending on your board layout. Some boards shift the - digital pin assignments by 2 so that digital I/O pin 0 is PORTD Rx, pin 13 is PORTC SCK, just - like the Arduino ATmega board. Then they align the physical pins so that a regular Arduino shield - will work, and assign PORTD 0-1 to 2 different digital I/O pin numbers (such as 20 and 21). - - To facilitate that specific change, uncomment the #define for 'DIGITAL_IO_PIN_SHIFT', below. - Alternately you can create a separate version of this file with a different variant name, - such as 'xmega-compat', with the #define uncommented, stored in an appropriately named directory. - - ============================ - HARDWARE SERIAL FLOW CONTROL - ============================ - - This version of the xmega Arduino startup+support files supports HARDWARE FLOW CONTROL on BOTH serial ports via - RTS (output) and CTS (input). CTS is implemented as input from remote device's DTR. RTS is implemented as DTR output. - - To implement RTS/CTS, use definitions similar to the following in your version of this header file - - NOTE: RTS(DTR) will be configured as an output, active low (high tells sender to stop sending data to the UART) - CTS will be configured as an input, active low (high stops data from being sent out via UART) - - CTS high to low transition causes an interrupt that may result in serial I/O (for faster response time). - - // RTS(DTR) as GPIO 0 (port D pin 0) - #define SERIAL_0_RTS_PORT_NAME PORTD - #define SERIAL_0_RTS_PIN_INDEX 0 - - // CTS as GPIO 1 (port D pin 1) - #define SERIAL_0_CTS_PORT_NAME PORTD - #define SERIAL_0_CTS_PIN_INDEX 1 - - use similar definitions for serial 1, aka 'SERIAL_1_CTS_PORT' - - NOTE: you can even use PORTA or PORTB pins for this, if you don't need to measure analog volts on those pins - - X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A X M E G A - -*/ - -#ifndef Pins_Arduino_h -#define Pins_Arduino_h - -#include - -// for now, the default xmega uses a simple assignment of digital pin numbers, beginning with port D -// to accomodate a useful "compatibility" shield design, these pins can be shifted so that the pin -// that maps to 'digitalRead(0)' would be D2 rather than D0. This also puts 'Serial' on pins 0 and 1 -// exactly like the Arduino UNO. For any other mapping, create your own 'pins_arduino.h' file. -// -#define DIGITAL_IO_PIN_SHIFT /* COMMENT THIS to disable the shifting of digital pin assignments for Arduino shield compatibility */ - -// default two-wire port is TWIC. '#define'ing USE_TWIC maps it to digital pins 20 and 21. Only valid with DIGITAL_IO_PIN_SHIFT '#define'd -#define USE_TWIC /* define this to re-map TWIC to digital pins 20 and 21, similar to an Arduino Mega2560. requires DIGITAL_IO_PIN_SHIFT */ - - -#define NUM_DIGITAL_PINS 22 -#define NUM_ANALOG_INPUTS 12 -#define analogInputToDigitalPin(p) ((p < 12) ? (p) + 22 : -1) -#ifdef DIGITAL_IO_PIN_SHIFT -#ifdef USE_TWIC -#define digitalPinHasPWM(p) ((p) < 18 || (p) == 20 || (p) == 21) /* PORTC pins 0 and 1 are 20 and 21, respectively */ -#else // USE_TWIC -#define digitalPinHasPWM(p) ((p) < 18 || (p) == 20 || (p) == 21) /* PORTD pins 0 and 1 are 20 and 21, respectively */ -#endif // USE_TWIC -#else // no digital I/O pin shift -#define digitalPinHasPWM(p) ((p) < 20) /* port E pin 3 is the highest one that has PWM */ -#endif // DIGITAL_IO_PIN_SHIFT - -// this returns the DEFAULT INTERRUPT (in this case, interrupt 0) for any digital or analog pin -// If you choose a port's pin 2, it will be the same as using 'PORTn_INT0' -#define digitalPinToInterrupt(p) \ - ( pgm_read_byte(&port_to_int0_PGM[pgm_read_byte(&digital_pin_to_port_PGM[p])]) | \ - ( ((pgm_read_byte(&digital_pin_to_bit_mask_PGM[p]) - 2) & 7) << 5 ) ) - - -// xmega-specific - Interrupt 'vector number' assignments: - -// Interrupts are PORT-SPECIFIC, not pin specific. -// pin 2 on any port is always asynchronous (except for 'R' which doesn't have a pin 2) -// all other pins can manage synchronous interrupts. 'wakeup' from sleep mode -// and other async interrupts must be on a 'pin 2', on ports A through E -// -// Each port has 2 separate interrupt vectors. They can be assigned different pins. -// The same pin can also be assigned to both vectors on the same port, if desired. - -#define PORTD_INT0 0 -#define PORTD_INT1 1 -#define PORTC_INT0 2 -#define PORTC_INT1 3 -#define PORTE_INT0 4 -#define PORTE_INT1 5 -#define PORTA_INT0 6 -#define PORTA_INT1 7 -#define PORTB_INT0 8 -#define PORTB_INT1 9 -#define PORTR_INT0 10 -#define PORTR_INT1 11 - -#define EXTERNAL_NUM_INTERRUPTS 12 /* defined here instead of wiring_private.h - max value is 32 */ - -// was in wiring_external.h, moved here -#define EXTERNAL_INT_0 0 -#define EXTERNAL_INT_1 1 -#define EXTERNAL_INT_2 2 -#define EXTERNAL_INT_3 3 -#define EXTERNAL_INT_4 4 -#define EXTERNAL_INT_5 5 -#define EXTERNAL_INT_6 6 -#define EXTERNAL_INT_7 7 -#define EXTERNAL_INT_8 8 -#define EXTERNAL_INT_9 9 -#define EXTERNAL_INT_10 10 -#define EXTERNAL_INT_11 11 - -// xmega 'D' series has 2 sets of UART and SPI. -// The default UART is assigned on Port D, pins PD2-3 -// The default SPI is assigned on Port C, pins PC4-7 -// -// Also there are multiple 2-wire ports, the default being assigned to PC0-1 -// see definition for DEFAULT_TWI and USE_TWIC -// -// Standard GPIO pins are assigned as follows: -// PD0-7 Digital 0-7 -// PC0-7 Digital 8-15 -// PE0-3 digital 16-19 -// PR0-1 digital 20-21 -// PA0-7 analog A0-A7 -// PB0-3 analog A8-A11 -// -// '#define'ing DIGITAL_IO_PIN_SHIFT shifts this down by 2, and places PD0-1 on 20-21 -// This is for Arduino 'atmega' compatibility with respect to existing shields, so that -// you don't have to re-map pin numbers with #defines in existing software that hard-codes them -// or makes assumptions about pin numbers vs functionality [except TWI won't ever match up] -// -// '#define'ing USE_TWIC puts PC0-1 on 20-21 (corresponding to TWI pins on later Arduinos) -// -// -// ALL PORT REMAP registers must be assigned to 0 (default mappings for pins) -// this puts PWM output on pins 0-3 for PORT E (the timers are split for C and D) -// Additionally, CLKOUT should be 0 (no clock outputs on any port/pin). -// -// TIMERS -// Timer 0 should be configured as 'Tx2' (for 8 PWM outputs) by default, essentially -// as a dual 8-bit timer, more or less compatible with the Arduino's 3 timers and -// supporting all 8 pins on ports C and D for PWM output. Port C's timer supports -// the system clock. -// -// See 'D' manual chapter 13 for more on this - - -// ------------------------------------------ -// DEFINITIONS FOR SERIAL PORTS AND TWI PORTS -// ------------------------------------------ - - -// TWI ports -#define DEFAULT_TWI TWIC /* note see definitions for SDA and SCL, below - alter accordingly */ - -// the XMega64D4 has two TWI ports -#define TWI_PORT0 TWIC -#define TWI_VECTOR_S0 TWIC_TWIS_vect -#define TWI_VECTOR_M0 TWIC_TWIM_vect -#define TWI_PORT1 TWIE -#define TWI_VECTOR_S1 TWIE_TWIS_vect -#define TWI_VECTOR_M1 TWIE_TWIM_vect - -#define TWI_INTERFACE_COUNT 2 - - -// obsolete - consider removal in all of them -//#define TWIC_VECT_ENABLE /* use this to select the correct interrupt vectors for default */ - - -// serial port 0 -#define SERIAL_0_PORT_NAME PORTD -#define SERIAL_0_USART_NAME USARTD0 -#define SERIAL_0_USART_DATA USARTD0_DATA -#define SERIAL_0_RXC_ISR ISR(USARTD0_RXC_vect) -#define SERIAL_0_DRE_ISR ISR(USARTD0_DRE_vect) -//#define SERIAL_0_REMAP PORTD_REMAP /* define THIS to re-map the pins from 0-3 to 4-7 on serial port 0 */ -#define SERIAL_0_REMAP_BIT 4 /* the bit needed to remap the port if SERIAL_0_REMAP is defined */ -#define SERIAL_0_RX_PIN_INDEX 2 /* the pin number on the port, not the mapped digital pin number */ -#define SERIAL_0_TX_PIN_INDEX 3 /* the pin number on the port, not the mapped digital pin number */ -#define USARTD0_VECTOR_EXISTS - -// serial port 1 -#define SERIAL_1_PORT_NAME PORTC -#define SERIAL_1_USART_NAME USARTC0 -#define SERIAL_1_USART_DATA USARTC0_DATA -#define SERIAL_1_RXC_ISR ISR(USARTC0_RXC_vect) -#define SERIAL_1_DRE_ISR ISR(USARTC0_DRE_vect) -//#define SERIAL_1_REMAP PORTC_REMAP /* define THIS to re-map the pins from 0-3 to 4-7 on serial port 1 */ -#define SERIAL_1_REMAP_BIT 4 /* the bit needed to remap the port if SERIAL_1_REMAP is defined */ -#define SERIAL_1_RX_PIN_INDEX 2 /* the pin number on the port, not the mapped digital pin number */ -#define SERIAL_1_TX_PIN_INDEX 3 /* the pin number on the port, not the mapped digital pin number */ -#define USARTC0_VECTOR_EXISTS - - - -// For atmega/Arduino shield compatibility, with DIGITAL_IO_PIN_SHIFT defined -// typical board/pin layout might be like this (for shield pins): -// -// NOTE: this design/layout assumes USE_TWIC is defined, so TWI is on TWIC (port C pins 0/1) -// -// M M -// S I O T R -// A C S S S x x -// S S R G K O I S 2 2 T R -// C D E N 1 1 1 1 x x -// L A F D 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -// ----o-o-o-o-o-o-o-o-o-o--o-o-o-o-o-o-o-o---- -// P P P P P P P P P P P P P P P P -// C C C C C C C C C C D D D D D D -// 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 -// -// -// T O P V I E W -// -// -// P P P P P P -// A A A A A A -// 5 4 3 2 1 0 -// ------------o-o-o-o-o-o-o-o--o-o-o-o-o-o---- -// G I R 3 5 G G V A A A A A A -// N O E . V N N i 5 4 3 2 1 0 -// D R S 3 D D n -// E E V -// F T -// -// As with the MEGA2560 and other 'mega' Arduino boards, additional connectors would -// break out the additional pins, with appropriate labeling. Additionally, there should -// be an LED on PORTR pin 1 for 'LED_BUILTIN'. -// -// This layout is based on the 'Rev 3' Arduino. -// -// NOTE - NO AREF: AREF is not connected. AREF is a bit of an issue on xmega because -// it DOES! NOT! WORK! THE! SAME! as it does on the ATmegaXXX and so you would need to -// (literally) steal one of the additional analog input pins to implement it. It's not -// impossible, or even THAT difficult. I'm just not doing it here. - - - -#ifdef DIGITAL_IO_PIN_SHIFT // aka digital I/O pin 0 is PORTD pin 2 - -// SHIFTED I/O pins (atmega compatibility) - see xmega mod description in comment at top - -// default SPI -static const uint8_t SS = 10; -static const uint8_t MOSI = 11; -static const uint8_t MISO = 12; -static const uint8_t SCK = 13; - -// primary SPI on PC4-7 -static const uint8_t SS0 = 10; -static const uint8_t MOSI0 = 11; -static const uint8_t MISO0 = 12; -static const uint8_t SCK0 = 13; - -// secondary SPI on PD4-7 -static const uint8_t SS1 = 2; -static const uint8_t MOSI1 = 3; -static const uint8_t MISO1 = 4; -static const uint8_t SCK1 = 5; - -// default 2-wire on PC0,PC1 - TWIC -#ifdef USE_TWIC -static const uint8_t SDA = 20; -static const uint8_t SCL = 21; -#else // !USE_TWIC -static const uint8_t SDA = 6; -static const uint8_t SCL = 7; -#endif // USE_TWIC - -// port-specific 2-wire -#ifdef USE_TWIC -static const uint8_t SDA0 = 20; -static const uint8_t SCL0 = 21; -#else // !USE_TWIC -static const uint8_t SDA0 = 6; -static const uint8_t SCL0 = 7; -#endif // USE_TWIC -static const uint8_t SDA1 = 14; -static const uint8_t SCL1 = 15; - - -// keep track of the indices for port R since its control register -// settings should be slightly different - D manual table 11-6 -#define PR0 18 -#define PR1 19 - -#else // no digital I/O pin shifting, PORTD pin 0 is digital I/O pin 0 (as it should be) - -// default "no shift" pin assignments - -// default SPI -static const uint8_t SS = 12; -static const uint8_t MOSI = 13; -static const uint8_t MISO = 14; -static const uint8_t SCK = 15; - -// primary SPI on PC4-7 -static const uint8_t SS0 = 12; -static const uint8_t MOSI0 = 13; -static const uint8_t MISO0 = 14; -static const uint8_t SCK0 = 15; - -// secondary SPI on PD4-7 -static const uint8_t SS1 = 4; -static const uint8_t MOSI1 = 5; -static const uint8_t MISO1 = 6; -static const uint8_t SCK1 = 7; - -// default 2-wire on PC0,PC1 - TWIC (TWIE appears to be broken) -static const uint8_t SDA = 8; -static const uint8_t SCL = 9; -static const uint8_t SDA0 = 8; -static const uint8_t SCL0 = 9; -static const uint8_t SDA1 = 16; -static const uint8_t SCL1 = 17; - -// keep track of the indices for port R since its control register -// settings should be slightly different - D manual table 11-6 -#define PR0 20 -#define PR1 21 - -#endif // DIGITAL_IO_PIN_SHIFT - - -// default 'status' LED on PR1 -//static const uint8_t LED_BUILTIN = PR1; -#define LED_BUILTIN PR1 /* Arduino 1.06 uses #define, not a const uint8_t */ - -static const uint8_t A0 = 22; -static const uint8_t A1 = 23; -static const uint8_t A2 = 24; -static const uint8_t A3 = 25; -static const uint8_t A4 = 26; -static const uint8_t A5 = 27; -static const uint8_t A6 = 28; -static const uint8_t A7 = 29; -static const uint8_t A8 = 30; -static const uint8_t A9 = 31; -static const uint8_t A10 = 32; -static const uint8_t A11 = 33; - -// on the xmega64d4, PA2, PB2, PC2, PD2, and PE2 are asynchronous ints. Others are 'synchronous' which means -// that they must be held in their 'interrupt state' long enough for the system to detect them. In any case -// all digital input pins can be use as interrupts, synchronous or otherwise. - - - -#ifdef ARDUINO_MAIN - - -const uint16_t PROGMEM port_to_mode_PGM[] = { - NOT_A_PORT, // 0 - (uint16_t) &PORTA_DIR, // PA - (uint16_t) &PORTB_DIR, // PB - (uint16_t) &PORTC_DIR, // PC - (uint16_t) &PORTD_DIR, // PD - (uint16_t) &PORTE_DIR, // PE - (uint16_t) &PORTR_DIR, // PR -}; - -const uint16_t PROGMEM port_to_output_PGM[] = { - NOT_A_PORT, // 0 - (uint16_t) &PORTA_OUT, // PA - (uint16_t) &PORTB_OUT, // PB - (uint16_t) &PORTC_OUT, // PC - (uint16_t) &PORTD_OUT, // PD - (uint16_t) &PORTE_OUT, // PE - (uint16_t) &PORTR_OUT, // PR -}; - -const uint16_t PROGMEM port_to_input_PGM[] = { - NOT_A_PORT, // 0 - (uint16_t) &PORTA_IN, // PA - (uint16_t) &PORTB_IN, // PB - (uint16_t) &PORTC_IN, // PC - (uint16_t) &PORTD_IN, // PD - (uint16_t) &PORTE_IN, // PE - (uint16_t) &PORTR_IN, // PR -}; - -const uint8_t PROGMEM port_to_int0_PGM[] = { - NOT_AN_INTERRUPT, // 0 - PORTA_INT0, // PA - PORTB_INT0, // PB - PORTC_INT0, // PC - PORTD_INT0, // PD - PORTE_INT0, // PE - PORTR_INT0, // PR -}; - -// xmega has a per-pin config register as well. Normally these will be 00000111 for analog, 00000000 for digital 'totem pole' -// for 'INPUT_PULLUP' these will be 00011111 -// bits 2:0 (trigger) 000 both edges 001 rising 010 falling 011 level 111 input buffer disabled -// note: 'input buffer disabled' required to use the 'IN' register (so default here) -// also port R does not support 'INTPUT_DISABLED' (sic) so use BOTHEDGES [0] instead -// bits 5:3 (out/pull) 000 TOTEM [normal], 001 bus keeper [sticky], 010 pulldown, 011 pullup, -// 100 wired 'or', 101 wired 'and', 110 wired 'or' pulldown, 111 wired 'and' pullup -// bit 6: "invert logic" (0 = normal, 1 = inverted) -// bit 7: unused, must be zero -// NOTE: PORTA through PORTE (PORTF?) support 'input buffer disabled' and this setting is recommended -// for analog inputs. PORTR apparently does NOT support this (set to zero?) - -const uint16_t PROGMEM digital_pin_to_control_PGM[] = { -#ifndef DIGITAL_IO_PIN_SHIFT - (uint16_t) &PORTD_PIN0CTRL, // PD 0 ** 0 ** - (uint16_t) &PORTD_PIN1CTRL, // PD 1 ** 1 ** -#endif // DIGITAL_IO_PIN_SHIFT -// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined - (uint16_t) &PORTD_PIN2CTRL, // PD 2 ** 2 ** USARTD_RX ASYNC - (uint16_t) &PORTD_PIN3CTRL, // PD 3 ** 3 ** USARTD_TX - (uint16_t) &PORTD_PIN4CTRL, // PD 4 ** 4 ** - (uint16_t) &PORTD_PIN5CTRL, // PD 5 ** 5 ** - (uint16_t) &PORTD_PIN6CTRL, // PD 6 ** 6 ** - (uint16_t) &PORTD_PIN7CTRL, // PD 7 ** 7 ** -#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - (uint16_t) &PORTD_PIN0CTRL, // PD 0 ** 8 ** map PORTD pins 0/1 here if TWIC is used - (uint16_t) &PORTD_PIN1CTRL, // PD 1 ** 9 ** -#else - (uint16_t) &PORTC_PIN0CTRL, // PC 0 ** 8 ** SDA - (uint16_t) &PORTC_PIN1CTRL, // PC 1 ** 9 ** SCL -#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - (uint16_t) &PORTC_PIN2CTRL, // PC 2 ** 10 ** ASYNC - (uint16_t) &PORTC_PIN3CTRL, // PC 3 ** 11 ** - (uint16_t) &PORTC_PIN4CTRL, // PC 4 ** 12 ** SPI_SS - (uint16_t) &PORTC_PIN5CTRL, // PC 5 ** 13 ** SPI_MOSI - (uint16_t) &PORTC_PIN6CTRL, // PC 6 ** 14 ** SPI_MISO - (uint16_t) &PORTC_PIN7CTRL, // PC 7 ** 15 ** SPI_SCK - (uint16_t) &PORTE_PIN0CTRL, // PE 0 ** 16 ** SDA1 - (uint16_t) &PORTE_PIN1CTRL, // PE 1 ** 17 ** SCL1 - (uint16_t) &PORTE_PIN2CTRL, // PE 2 ** 18 ** ASYNC - (uint16_t) &PORTE_PIN3CTRL, // PE 3 ** 19 ** - (uint16_t) &PORTR_PIN0CTRL, // PR 0 ** 20 ** - (uint16_t) &PORTR_PIN1CTRL, // PR 1 ** 21 ** default LED -#ifdef DIGITAL_IO_PIN_SHIFT -#ifdef USE_TWIC - (uint16_t) &PORTC_PIN0CTRL, // PC 0 ** the new 20 ** SDA, SDA0 - (uint16_t) &PORTC_PIN1CTRL, // PC 1 ** the new 21 ** SCL, SCL0 -#else - (uint16_t) &PORTD_PIN0CTRL, // PD 0 ** the new 20 ** - (uint16_t) &PORTD_PIN1CTRL, // PD 1 ** the new 21 ** -#endif // USE_TWIC -#endif // DIGITAL_IO_PIN_SHIFT - (uint16_t) &PORTA_PIN0CTRL, // PA 0 ** 22 ** A0 - (uint16_t) &PORTA_PIN1CTRL, // PA 1 ** 23 ** A1 - (uint16_t) &PORTA_PIN2CTRL, // PA 2 ** 24 ** A2 ASYNC - (uint16_t) &PORTA_PIN3CTRL, // PA 3 ** 25 ** A3 - (uint16_t) &PORTA_PIN4CTRL, // PA 4 ** 26 ** A4 - (uint16_t) &PORTA_PIN5CTRL, // PA 5 ** 27 ** A5 - (uint16_t) &PORTA_PIN6CTRL, // PA 6 ** 28 ** A6 - (uint16_t) &PORTA_PIN7CTRL, // PA 7 ** 29 ** A7 - (uint16_t) &PORTB_PIN0CTRL, // PB 0 ** 30 ** A8 - (uint16_t) &PORTB_PIN1CTRL, // PB 1 ** 31 ** A9 - (uint16_t) &PORTB_PIN2CTRL, // PB 2 ** 32 ** A10 ASYNC - (uint16_t) &PORTB_PIN3CTRL, // PB 3 ** 33 ** A11 -}; - -const uint8_t PROGMEM digital_pin_to_port_PGM[] = { - // PORTLIST - // ------------------------------------------- -#ifndef DIGITAL_IO_PIN_SHIFT - _PD, // PD 0 ** 0 ** - _PD, // PD 1 ** 1 ** -#endif // DIGITAL_IO_PIN_SHIFT -// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined - _PD, // PD 2 ** 2 ** USARTD_RX - _PD, // PD 3 ** 3 ** USARTD_TX - _PD, // PD 4 ** 4 ** - _PD, // PD 5 ** 5 ** - _PD, // PD 6 ** 6 ** - _PD, // PD 7 ** 7 ** -#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - _PD, // PD 0 ** 8 ** - _PD, // PD 1 ** 9 ** -#else - _PC, // PC 0 ** 8 ** SDA - _PC, // PC 1 ** 9 ** SCL -#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - _PC, // PC 2 ** 10 ** - _PC, // PC 3 ** 11 ** - _PC, // PC 4 ** 12 ** SPI_SS - _PC, // PC 5 ** 13 ** SPI_MOSI - _PC, // PC 6 ** 14 ** SPI_MISO - _PC, // PC 7 ** 15 ** SPI_SCK - _PE, // PE 0 ** 16 ** SDA - _PE, // PE 1 ** 17 ** SCL - _PE, // PE 2 ** 18 ** - _PE, // PE 3 ** 19 ** - _PR, // PR 0 ** 20 ** - _PR, // PR 1 ** 21 ** default LED -#ifdef DIGITAL_IO_PIN_SHIFT -#ifdef USE_TWIC - _PC, // PC 0 ** the new 20 ** SDA - _PC, // PC 1 ** the new 21 ** SCL -#else - _PD, // PD 0 ** the new 20 ** - _PD, // PD 1 ** the new 21 ** -#endif // USE_TWIC -#endif // DIGITAL_IO_PIN_SHIFT - _PA, // PA 0 ** 22 ** A0 - _PA, // PA 1 ** 23 ** A1 - _PA, // PA 2 ** 24 ** A2 - _PA, // PA 3 ** 25 ** A3 - _PA, // PA 4 ** 26 ** A4 - _PA, // PA 5 ** 27 ** A5 - _PA, // PA 6 ** 28 ** A6 - _PA, // PA 7 ** 29 ** A7 - _PB, // PB 0 ** 30 ** A8 - _PB, // PB 1 ** 31 ** A9 - _PB, // PB 2 ** 32 ** A10 - _PB, // PB 3 ** 33 ** A11 -}; - -const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { - // PIN IN PORT - // ------------------------------------------- -#ifndef DIGITAL_IO_PIN_SHIFT - _BV( 0 ), // PD 0 ** 0 ** - _BV( 1 ), // PD 1 ** 1 ** -#endif // DIGITAL_IO_PIN_SHIFT -// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined - _BV( 2 ), // PD 2 ** 2 ** USARTD_RX - _BV( 3 ), // PD 3 ** 3 ** USARTD_TX - _BV( 4 ), // PD 4 ** 4 ** - _BV( 5 ), // PD 5 ** 5 ** - _BV( 6 ), // PD 6 ** 6 ** - _BV( 7 ), // PD 7 ** 7 ** -#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - _BV( 0 ), // PD 0 ** 8 ** - _BV( 1 ), // PD 1 ** 9 ** -#else - _BV( 0 ), // PC 0 ** 8 ** SDA - _BV( 1 ), // PC 1 ** 9 ** SCL -#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - _BV( 2 ), // PC 2 ** 10 ** - _BV( 3 ), // PC 3 ** 11 ** - _BV( 4 ), // PC 4 ** 12 ** SPI_SS - _BV( 5 ), // PC 5 ** 13 ** SPI_MOSI - _BV( 6 ), // PC 6 ** 14 ** SPI_MISO - _BV( 7 ), // PC 7 ** 15 ** SPI_SCK - _BV( 0 ), // PE 0 ** 16 ** SDA - _BV( 1 ), // PE 1 ** 17 ** SCL - _BV( 2 ), // PE 2 ** 18 ** - _BV( 3 ), // PE 3 ** 19 ** - _BV( 0 ), // PR 0 ** 20 ** - _BV( 1 ), // PR 1 ** 21 ** default LED -#ifdef DIGITAL_IO_PIN_SHIFT -#ifdef USE_TWIC - _BV( 0 ), // PC 0 ** the new 20 ** SDA - _BV( 1 ), // PC 1 ** the new 21 ** SCL -#else - _BV( 0 ), // PD 0 ** the new 20 ** - _BV( 1 ), // PD 1 ** the new 21 ** -#endif // USE_TWIC -#endif // DIGITAL_IO_PIN_SHIFT - _BV( 0 ), // PA 0 ** 22 ** A0 - _BV( 1 ), // PA 1 ** 23 ** A1 - _BV( 2 ), // PA 2 ** 24 ** A2 - _BV( 3 ), // PA 3 ** 25 ** A3 - _BV( 4 ), // PA 4 ** 26 ** A4 - _BV( 5 ), // PA 5 ** 27 ** A5 - _BV( 6 ), // PA 6 ** 28 ** A6 - _BV( 7 ), // PA 7 ** 29 ** A7 - _BV( 0 ), // PB 0 ** 30 ** A8 - _BV( 1 ), // PB 1 ** 31 ** A9 - _BV( 2 ), // PB 2 ** 32 ** A10 - _BV( 3 ), // PB 3 ** 33 ** A11 -}; - -const uint8_t PROGMEM digital_pin_to_timer_PGM[] = { - // TIMERS - // ------------------------------------------- - // for now 'NOT_ON_TIMER' for all - later, assign timers based - // on pins 0-3 being enabled as PWM out for ports A through E - // corresponding to timers A through D (see D manual sections 11.12.14, - // also see D manual sect 13.6 for using the 'compare' channel on 'TCx2' to generate - // a PWM output. Must select pin as output, _AND_ enable the 'compare' output - // for the appropriate pin. LCMPENx/HCMPENx registers to enable it. - -#ifndef DIGITAL_IO_PIN_SHIFT - TIMERD2, // PD 0 ** 0 ** - TIMERD2, // PD 1 ** 1 ** -#endif // DIGITAL_IO_PIN_SHIFT -// subtract 2 from the digital pin number if DIGITAL_IO_PIN_SHIFT is defined - TIMERD2, // PD 2 ** 2 ** USARTD_RX - TIMERD2, // PD 3 ** 3 ** USARTD_TX - TIMERD2, // PD 4 ** 4 ** - TIMERD2, // PD 5 ** 5 ** - TIMERD2, // PD 6 ** 6 ** - TIMERD2, // PD 7 ** 7 ** -#if defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - TIMERD2, // PD 0 ** 8 ** - TIMERD2, // PD 1 ** 9 ** -#else - TIMERC2, // PC 0 ** 8 ** SDA - TIMERC2, // PC 1 ** 9 ** SCL -#endif // defined(DIGITAL_IO_PIN_SHIFT) && defined(USE_TWIC) - TIMERC2, // PC 2 ** 10 ** - TIMERC2, // PC 3 ** 11 ** - TIMERC2, // PC 4 ** 12 ** SPI_SS - TIMERC2, // PC 5 ** 13 ** SPI_MOSI - TIMERC2, // PC 6 ** 14 ** SPI_MISO - TIMERC2, // PC 7 ** 15 ** SPI_SCK - TIMERE0, // PE 0 ** 16 ** SDA - TIMERE0, // PE 1 ** 17 ** SCL - TIMERE0, // PE 2 ** 18 ** - TIMERE0, // PE 3 ** 19 ** - NOT_ON_TIMER, // PR 0 ** 20 ** - NOT_ON_TIMER, // PR 1 ** 21 ** default LED -#ifdef DIGITAL_IO_PIN_SHIFT -#ifdef USE_TWIC - TIMERC2, // PC 0 ** the new 20 ** SDA - TIMERC2, // PC 1 ** the new 21 ** SCL -#else - TIMERD2, // PD 0 ** the new 20 ** - TIMERD2, // PD 1 ** the new 21 ** -#endif // USE_TWIC -#endif // DIGITAL_IO_PIN_SHIFT - NOT_ON_TIMER, // PA 0 ** 22 ** A0 - NOT_ON_TIMER, // PA 1 ** 23 ** A1 - NOT_ON_TIMER, // PA 2 ** 24 ** A2 - NOT_ON_TIMER, // PA 3 ** 25 ** A3 - NOT_ON_TIMER, // PA 4 ** 26 ** A4 - NOT_ON_TIMER, // PA 5 ** 27 ** A5 - NOT_ON_TIMER, // PA 6 ** 28 ** A6 - NOT_ON_TIMER, // PA 7 ** 29 ** A7 - NOT_ON_TIMER, // PB 0 ** 30 ** A8 - NOT_ON_TIMER, // PB 1 ** 31 ** A9 - NOT_ON_TIMER, // PB 2 ** 32 ** A10 - NOT_ON_TIMER, // PB 3 ** 33 ** A11 -}; - -#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 Serial -#define SERIAL_HARDWARE_OPEN Serial2 - -#endif - - diff --git a/BootLoaders/Boards/stm32/tools/win/do_version.bat b/BootLoaders/Boards/stm32/tools/win/do_version.bat index 8be9f84..f124cc0 100644 --- a/BootLoaders/Boards/stm32/tools/win/do_version.bat +++ b/BootLoaders/Boards/stm32/tools/win/do_version.bat @@ -18,7 +18,11 @@ IF DEFINED DEBUG ( ECHO Multi board: %MULTI_BOARD% ) -SET MULTI_TYPE=stm +IF %MULTI_BOARD%==MULTI_NO_BOOT SET MULTI_TYPE=avr +IF %MULTI_BOARD%==MULTI_FLASH_FROM_TX SET MULTI_TYPE=avr +IF %MULTI_BOARD%==MULTI_STM32_NO_BOOT SET MULTI_TYPE=stm +IF %MULTI_BOARD%==MULTI_STM32_FLASH_FROM_TX SET MULTI_TYPE=stm +IF %MULTI_BOARD%==MULTI_ORANGERX SET MULTI_TYPE=orx IF EXIST "%BUILD_PATH%\sketch\Multiprotocol.h" ( IF DEFINED DEBUG ECHO Getting Multi-MODULE firmware version from "%BUILD_PATH%\sketch\Multiprotocol.h"