diff --git a/BootLoaders/Boards/avr/platform.local.txt b/BootLoaders/Boards/avr/platform.local.txt index 1322d9b..65ae6a9 100644 --- a/BootLoaders/Boards/avr/platform.local.txt +++ b/BootLoaders/Boards/avr/platform.local.txt @@ -1,3 +1,16 @@ ## Save hex recipe.output.tmp_file={build.project_name}.hex -recipe.output.save_file=multifw.hex +recipe.output.save_file=multi-avr.hex + +## 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/avr/tools/linux/do_version b/BootLoaders/Boards/avr/tools/linux/do_version new file mode 100755 index 0000000..ba2a182 --- /dev/null +++ b/BootLoaders/Boards/avr/tools/linux/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=avr + +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/avr/tools/linux64/do_version b/BootLoaders/Boards/avr/tools/linux64/do_version new file mode 100755 index 0000000..ba2a182 --- /dev/null +++ b/BootLoaders/Boards/avr/tools/linux64/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=avr + +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/avr/tools/macosx/do_version b/BootLoaders/Boards/avr/tools/macosx/do_version new file mode 100755 index 0000000..ba2a182 --- /dev/null +++ b/BootLoaders/Boards/avr/tools/macosx/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=avr + +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/avr/tools/win/do_version.bat b/BootLoaders/Boards/avr/tools/win/do_version.bat new file mode 100644 index 0000000..4cda254 --- /dev/null +++ b/BootLoaders/Boards/avr/tools/win/do_version.bat @@ -0,0 +1,54 @@ +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +SET BUILD_PATH=%1 +SET PROJECT_NAME=%2 +SET SKETCH_PATH=%3 +SET MULTI_BOARD=%4 +SET EXPORT_FLAG=%5 + +REM ECHO Multi board: %MULTI_BOARD% + +SET MULTI_TYPE=avr + +IF EXIST "%1\sketch\Multiprotocol.h" ( + REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h" + FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\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= +) + +REM 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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_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" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL + ) + + IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL + ) + + IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" ( + DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL + ) + IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" ( + DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL + ) +) diff --git a/BootLoaders/Boards/orangerx/avrdude.conf b/BootLoaders/Boards/orangerx/avrdude.conf new file mode 100644 index 0000000..7e23b0a --- /dev/null +++ b/BootLoaders/Boards/orangerx/avrdude.conf @@ -0,0 +1,15067 @@ +# $Id: avrdude.conf.in 1360 2015-10-31 20:50:52Z joerg_wunsch $ -*- text -*- +# +# AVRDUDE Configuration File +# +# This file contains configuration data used by AVRDUDE which describes +# the programming hardware pinouts and also provides part definitions. +# AVRDUDE's "-C" command line option specifies the location of the +# configuration file. The "-c" option names the programmer configuration +# which must match one of the entry's "id" parameter. The "-p" option +# identifies which part AVRDUDE is going to be programming and must match +# one of the parts' "id" parameter. +# +# DO NOT MODIFY THIS FILE. Modifications will be overwritten the next +# time a "make install" is run. For user-specific additions, use the +# "-C +filename" commandline option. +# +# Possible entry formats are: +# +# programmer +# parent # optional parent +# id = [, [, ] ...] ; # are quoted strings +# desc = ; # quoted string +# type = ; # programmer type, quoted string +# # supported programmer types can be listed by "-c ?type" +# connection_type = parallel | serial | usb +# baudrate = ; # baudrate for avr910-programmer +# vcc = [, ... ] ; # pin number(s) +# buff = [, ... ] ; # pin number(s) +# reset = ; # pin number +# sck = ; # pin number +# mosi = ; # pin number +# miso = ; # pin number +# errled = ; # pin number +# rdyled = ; # pin number +# pgmled = ; # pin number +# vfyled = ; # pin number +# usbvid = ; # USB VID (Vendor ID) +# usbpid = [, ...] # USB PID (Product ID) (1) +# usbdev = ; # USB interface or other device info +# usbvendor = ; # USB Vendor Name +# usbproduct = ; # USB Product Name +# usbsn = ; # USB Serial Number +# +# To invert a bit, use = ~ , the spaces are important. +# For a pin list all pins must be inverted. +# A single pin can be specified as usual = ~ , for lists +# specify it as follows = ~ ( [, ... ] ) . +# +# (1) Not all programmer types can process a list of PIDs. +# ; +# +# part +# id = ; # quoted string +# desc = ; # quoted string +# has_jtag = ; # part has JTAG i/f +# has_debugwire = ; # part has debugWire i/f +# has_pdi = ; # part has PDI i/f +# has_tpi = ; # part has TPI i/f +# devicecode = ; # deprecated, use stk500_devcode +# stk500_devcode = ; # numeric +# avr910_devcode = ; # numeric +# signature = ; # signature bytes +# usbpid = ; # DFU USB PID +# chip_erase_delay = ; # micro-seconds +# reset = dedicated | io; +# retry_pulse = reset | sck; +# pgm_enable = ; +# chip_erase = ; +# chip_erase_delay = ; # chip erase delay (us) +# # STK500 parameters (parallel programming IO lines) +# pagel = ; # pin name in hex, i.e., 0xD7 +# bs2 = ; # pin name in hex, i.e., 0xA0 +# serial = ; # can use serial downloading +# parallel = ; # can use par. programming +# # STK500v2 parameters, to be taken from Atmel's XML files +# timeout = ; +# stabdelay = ; +# cmdexedelay = ; +# synchloops = ; +# bytedelay = ; +# pollvalue = ; +# pollindex = ; +# predelay = ; +# postdelay = ; +# pollmethod = ; +# mode = ; +# delay = ; +# blocksize = ; +# readsize = ; +# hvspcmdexedelay = ; +# # STK500v2 HV programming parameters, from XML +# pp_controlstack = , , ...; # PP only +# hvsp_controlstack = , , ...; # HVSP only +# hventerstabdelay = ; +# progmodedelay = ; # PP only +# latchcycles = ; +# togglevtg = ; +# poweroffdelay = ; +# resetdelayms = ; +# resetdelayus = ; +# hvleavestabdelay = ; +# resetdelay = ; +# synchcycles = ; # HVSP only +# chiperasepulsewidth = ; # PP only +# chiperasepolltimeout = ; +# chiperasetime = ; # HVSP only +# programfusepulsewidth = ; # PP only +# programfusepolltimeout = ; +# programlockpulsewidth = ; # PP only +# programlockpolltimeout = ; +# # JTAG ICE mkII parameters, also from XML files +# allowfullpagebitstream = ; +# enablepageprogramming = ; +# idr = ; # IO addr of IDR (OCD) reg. +# rampz = ; # IO addr of RAMPZ reg. +# spmcr = ; # mem addr of SPMC[S]R reg. +# eecr = ; # mem addr of EECR reg. +# # (only when != 0x3c) +# is_at90s1200 = ; # AT90S1200 part +# is_avr32 = ; # AVR32 part +# +# memory +# paged = ; # yes / no +# size = ; # bytes +# page_size = ; # bytes +# num_pages = ; # numeric +# min_write_delay = ; # micro-seconds +# max_write_delay = ; # micro-seconds +# readback_p1 = ; # byte value +# readback_p2 = ; # byte value +# pwroff_after_write = ; # yes / no +# read = ; +# write = ; +# read_lo = ; +# read_hi = ; +# write_lo = ; +# write_hi = ; +# loadpage_lo = ; +# loadpage_hi = ; +# writepage = ; +# ; +# ; +# +# If any of the above parameters are not specified, the default value +# of 0 is used for numerics or the empty string ("") for string +# values. If a required parameter is left empty, AVRDUDE will +# complain. +# +# Parts can also inherit parameters from previously defined parts +# using the following syntax. In this case specified integer and +# string values override parameter values from the parent part. New +# memory definitions are added to the definitions inherited from the +# parent. +# +# part parent # quoted string +# id = ; # quoted string +# +# ; +# +# NOTES: +# * 'devicecode' is the device code used by the STK500 (see codes +# listed below) +# * Not all memory types will implement all instructions. +# * AVR Fuse bits and Lock bits are implemented as a type of memory. +# * Example memory types are: +# "flash", "eeprom", "fuse", "lfuse" (low fuse), "hfuse" (high +# fuse), "signature", "calibration", "lock" +# * The memory type specified on the avrdude command line must match +# one of the memory types defined for the specified chip. +# * The pwroff_after_write flag causes avrdude to attempt to +# power the device off and back on after an unsuccessful write to +# the affected memory area if VCC programmer pins are defined. If +# VCC pins are not defined for the programmer, a message +# indicating that the device needs a power-cycle is printed out. +# This flag was added to work around a problem with the +# at90s4433/2333's; see the at90s4433 errata at: +# +# http://www.atmel.com/dyn/resources/prod_documents/doc1280.pdf +# +# INSTRUCTION FORMATS +# +# Instruction formats are specified as a comma seperated list of +# string values containing information (bit specifiers) about each +# of the 32 bits of the instruction. Bit specifiers may be one of +# the following formats: +# +# '1' = the bit is always set on input as well as output +# +# '0' = the bit is always clear on input as well as output +# +# 'x' = the bit is ignored on input and output +# +# 'a' = the bit is an address bit, the bit-number matches this bit +# specifier's position within the current instruction byte +# +# 'aN' = the bit is the Nth address bit, bit-number = N, i.e., a12 +# is address bit 12 on input, a0 is address bit 0. +# +# 'i' = the bit is an input data bit +# +# 'o' = the bit is an output data bit +# +# Each instruction must be composed of 32 bit specifiers. The +# instruction specification closely follows the instruction data +# provided in Atmel's data sheets for their parts. +# +# See below for some examples. +# +# +# The following are STK500 part device codes to use for the +# "devicecode" field of the part. These came from Atmel's software +# section avr061.zip which accompanies the application note +# AVR061 available from: +# +# http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf +# + +#define ATTINY10 0x10 /* the _old_ one that never existed! */ +#define ATTINY11 0x11 +#define ATTINY12 0x12 +#define ATTINY15 0x13 +#define ATTINY13 0x14 + +#define ATTINY22 0x20 +#define ATTINY26 0x21 +#define ATTINY28 0x22 +#define ATTINY2313 0x23 + +#define AT90S1200 0x33 + +#define AT90S2313 0x40 +#define AT90S2323 0x41 +#define AT90S2333 0x42 +#define AT90S2343 0x43 + +#define AT90S4414 0x50 +#define AT90S4433 0x51 +#define AT90S4434 0x52 +#define ATMEGA48 0x59 + +#define AT90S8515 0x60 +#define AT90S8535 0x61 +#define AT90C8534 0x62 +#define ATMEGA8515 0x63 +#define ATMEGA8535 0x64 + +#define ATMEGA8 0x70 +#define ATMEGA88 0x73 +#define ATMEGA168 0x86 + +#define ATMEGA161 0x80 +#define ATMEGA163 0x81 +#define ATMEGA16 0x82 +#define ATMEGA162 0x83 +#define ATMEGA169 0x84 + +#define ATMEGA323 0x90 +#define ATMEGA32 0x91 + +#define ATMEGA64 0xA0 + +#define ATMEGA103 0xB1 +#define ATMEGA128 0xB2 +#define AT90CAN128 0xB3 +#define AT90CAN64 0xB3 +#define AT90CAN32 0xB3 + +#define AT86RF401 0xD0 + +#define AT89START 0xE0 +#define AT89S51 0xE0 +#define AT89S52 0xE1 + +# The following table lists the devices in the original AVR910 +# appnote: +# |Device |Signature | Code | +# +-------+----------+------+ +# |tiny12 | 1E 90 05 | 0x55 | +# |tiny15 | 1E 90 06 | 0x56 | +# | | | | +# | S1200 | 1E 90 01 | 0x13 | +# | | | | +# | S2313 | 1E 91 01 | 0x20 | +# | S2323 | 1E 91 02 | 0x48 | +# | S2333 | 1E 91 05 | 0x34 | +# | S2343 | 1E 91 03 | 0x4C | +# | | | | +# | S4414 | 1E 92 01 | 0x28 | +# | S4433 | 1E 92 03 | 0x30 | +# | S4434 | 1E 92 02 | 0x6C | +# | | | | +# | S8515 | 1E 93 01 | 0x38 | +# | S8535 | 1E 93 03 | 0x68 | +# | | | | +# |mega32 | 1E 95 01 | 0x72 | +# |mega83 | 1E 93 05 | 0x65 | +# |mega103| 1E 97 01 | 0x41 | +# |mega161| 1E 94 01 | 0x60 | +# |mega163| 1E 94 02 | 0x64 | + +# Appnote AVR109 also has a table of AVR910 device codes, which +# lists: +# dev avr910 signature +# ATmega8 0x77 0x1E 0x93 0x07 +# ATmega8515 0x3B 0x1E 0x93 0x06 +# ATmega8535 0x6A 0x1E 0x93 0x08 +# ATmega16 0x75 0x1E 0x94 0x03 +# ATmega162 0x63 0x1E 0x94 0x04 +# ATmega163 0x66 0x1E 0x94 0x02 +# ATmega169 0x79 0x1E 0x94 0x05 +# ATmega32 0x7F 0x1E 0x95 0x02 +# ATmega323 0x73 0x1E 0x95 0x01 +# ATmega64 0x46 0x1E 0x96 0x02 +# ATmega128 0x44 0x1E 0x97 0x02 +# +# These codes refer to "BOOT" device codes which are apparently +# different than standard device codes, for whatever reasons +# (often one above the standard code). + +# There are several extended versions of AVR910 implementations around +# in the Internet. These add the following codes (only devices that +# actually exist are listed): + +# ATmega8515 0x3A +# ATmega128 0x43 +# ATmega64 0x45 +# ATtiny26 0x5E +# ATmega8535 0x69 +# ATmega32 0x72 +# ATmega16 0x74 +# ATmega8 0x76 +# ATmega169 0x78 + +# +# Overall avrdude defaults; suitable for ~/.avrduderc +# +default_parallel = "/dev/ppi0"; +default_serial = "/dev/cuad0"; +# default_bitclock = 2.5; + +# Turn off safemode by default +#default_safemode = no; + + +# +# PROGRAMMER DEFINITIONS +# + +# http://wiring.org.co/ +# Basically STK500v2 protocol, with some glue to trigger the +# bootloader. +programmer + id = "wiring"; + desc = "Wiring"; + type = "wiring"; + connection_type = serial; +; + +programmer + id = "arduino"; + desc = "Arduino"; + type = "arduino"; + connection_type = serial; +; +# this will interface with the chips on these programmers: +# +# http://real.kiev.ua/old/avreal/en/adapters +# http://www.amontec.com/jtagkey.shtml, jtagkey-tiny.shtml +# http://www.olimex.com/dev/arm-usb-ocd.html, arm-usb-tiny.html +# http://www.ethernut.de/en/hardware/turtelizer/index.html +# http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html +# http://dangerousprototypes.com/docs/FT2232_breakout_board +# http://www.ftdichip.com/Products/Modules/DLPModules.htm,DLP-2232*,DLP-USB1232H +# http://flashrom.org/FT2232SPI_Programmer +# +# The drivers will look for a specific device and use the first one found. +# If you have mulitple devices, then look for unique information (like SN) +# And fill that in here. +# +# Note that the pin numbers for the main ISP signals (reset, sck, +# mosi, miso) are fixed and cannot be changed, since they must match +# the way the Multi-Protocol Synchronous Serial Engine (MPSSE) of +# these FTDI ICs has been designed. + +programmer + id = "avrftdi"; + desc = "FT2232D based generic programmer"; + type = "avrftdi"; + connection_type = usb; + usbvid = 0x0403; + usbpid = 0x6010; + usbvendor = ""; + usbproduct = ""; + usbdev = "A"; + usbsn = ""; +#ISP-signals - lower ADBUS-Nibble (default) + reset = 3; + sck = 0; + mosi = 1; + miso = 2; +#LED SIGNALs - higher ADBUS-Nibble +# errled = 4; +# rdyled = 5; +# pgmled = 6; +# vfyled = 7; +#Buffer Signal - ACBUS - Nibble +# buff = 8; +; +# This is an implementation of the above with a buffer IC (74AC244) and +# 4 LEDs directly attached, all active low. +programmer + id = "2232HIO"; + desc = "FT2232H based generic programmer"; + type = "avrftdi"; + connection_type = usb; + usbvid = 0x0403; +# Note: This PID is reserved for generic H devices and +# should be programmed into the EEPROM +# usbpid = 0x8A48; + usbpid = 0x6010; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals + reset = 3; + sck = 0; + mosi = 1; + miso = 2; + buff = ~4; +#LED SIGNALs + errled = ~ 11; + rdyled = ~ 14; + pgmled = ~ 13; + vfyled = ~ 12; +; + +#The FT4232H can be treated as FT2232H, but it has a different USB +#device ID of 0x6011. +programmer parent "avrftdi" + id = "4232h"; + desc = "FT4232H based generic programmer"; + usbpid = 0x6011; +; + +programmer + id = "jtagkey"; + desc = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2"; + type = "avrftdi"; + connection_type = usb; + usbvid = 0x0403; +# Note: This PID is used in all JTAGKey variants + usbpid = 0xCFF8; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals => 20 - Pin connector on JTAGKey + reset = 3; # TMS 7 violet + sck = 0; # TCK 9 white + mosi = 1; # TDI 5 green + miso = 2; # TDO 13 orange + buff = ~4; +# VTG VREF 1 brown with red tip +# GND GND 20 black +# The colors are on the 20 pin breakout cable +# from Amontec +; + +# UM232H module from FTDI and Glyn.com.au. +# See helix.air.net.au for detailed usage information. +# J1: Connect pin 2 and 3 for USB power. +# J2: Connect pin 2 and 3 for USB power. +# J2: Pin 7 is SCK +# : Pin 8 is MOSI +# : Pin 9 is MISO +# : Pin 11 is RST +# : Pin 6 is ground +# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get +# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant. +programmer + id = "UM232H"; + desc = "FT232H based module from FTDI and Glyn.com.au"; + type = "avrftdi"; + usbvid = 0x0403; +# Note: This PID is reserved for generic 232H devices and +# should be programmed into the EEPROM + usbpid = 0x6014; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals + sck = 0; + mosi = 1; + miso = 2; + reset = 3; +; + +# C232HM module from FTDI and Glyn.com.au. +# : Orange is SCK +# : Yellow is MOSI +# : Green is MISO +# : Brown is RST +# : Black is ground +# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get +# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant. +programmer + id = "C232HM"; + desc = "FT232H based module from FTDI and Glyn.com.au"; + type = "avrftdi"; + usbvid = 0x0403; +# Note: This PID is reserved for generic 232H devices and +# should be programmed into the EEPROM + usbpid = 0x6014; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; +#ISP-signals + sck = 0; + mosi = 1; + miso = 2; + reset = 3; +; + + +# On the adapter you can read "O-Link". On the PCB is printed "OpenJTAG v3.1" +# You can find it as "OpenJTAG ARM JTAG USB" in the internet. +# (But there are also several projects called Open JTAG, eg. +# http://www.openjtag.org, which are completely different.) +# http://www.100ask.net/shop/english.html (website seems to be outdated) +# http://item.taobao.com/item.htm?id=1559277013 +# http://www.micro4you.com/store/openjtag-arm-jtag-usb.html (schematics!) +# some other sources which call it O-Link +# http://www.andahammer.com/olink/ +# http://www.developmentboard.net/31-o-link-debugger.html +# http://armwerks.com/catalog/o-link-debugger-copy/ +# or just have a look at ebay ... +# It is basically the same entry as jtagkey with different usb ids. +programmer parent "jtagkey" + id = "o-link"; + desc = "O-Link, OpenJTAG from www.100ask.net"; + usbvid = 0x1457; + usbpid = 0x5118; + usbvendor = "www.100ask.net"; + usbproduct = "USB<=>JTAG&RS232"; +; + +# http://wiki.openmoko.org/wiki/Debug_Board_v3 +programmer + id = "openmoko"; + desc = "Openmoko debug board (v3)"; + type = "avrftdi"; + usbvid = 0x1457; + usbpid = 0x5118; + usbdev = "A"; + usbvendor = ""; + usbproduct = ""; + usbsn = ""; + reset = 3; # TMS 7 + sck = 0; # TCK 9 + mosi = 1; # TDI 5 + miso = 2; # TDO 13 +; + +# Only Rev. A boards. +# Schematic and user manual: http://www.cs.put.poznan.pl/wswitala/download/pdf/811EVBK.pdf +programmer + id = "lm3s811"; + desc = "Luminary Micro LM3S811 Eval Board (Rev. A)"; + type = "avrftdi"; + connection_type = usb; + usbvid = 0x0403; + usbpid = 0xbcd9; + usbvendor = "LMI"; + usbproduct = "LM3S811 Evaluation Board"; + usbdev = "A"; + usbsn = ""; +#ISP-signals - lower ACBUS-Nibble (default) + reset = 3; + sck = 0; + mosi = 1; + miso = 2; +# Enable correct buffers + buff = 7; +; + +# submitted as bug #46020 +programmer + id = "tumpa"; + desc = "TIAO USB Multi-Protocol Adapter"; + type = "avrftdi"; + connection_type = usb; + usbvid = 0x0403; + usbpid = 0x8A98; + usbdev = "A"; + usbvendor = "TIAO"; + usbproduct = ""; + usbsn = ""; + sck = 0; # TCK 9 + mosi = 1; # TDI 5 + miso = 2; # TDO 13 + reset = 3; # TMS 7 +; + +programmer + id = "avrisp"; + desc = "Atmel AVR ISP"; + type = "stk500"; + connection_type = serial; +; + +programmer + id = "avrispv2"; + desc = "Atmel AVR ISP V2"; + type = "stk500v2"; + connection_type = serial; +; + +programmer + id = "avrispmkII"; + desc = "Atmel AVR ISP mkII"; + type = "stk500v2"; + connection_type = usb; +; + +programmer parent "avrispmkII" + id = "avrisp2"; +; + +programmer + id = "buspirate"; + desc = "The Bus Pirate"; + type = "buspirate"; + connection_type = serial; +; + +programmer + id = "buspirate_bb"; + desc = "The Bus Pirate (bitbang interface, supports TPI)"; + type = "buspirate_bb"; + connection_type = serial; + # pins are bits in bitbang byte (numbers are 87654321) + # 1|POWER|PULLUP|AUX|MOSI|CLK|MISO|CS + reset = 1; + sck = 3; + mosi = 4; + miso = 2; + #vcc = 7; This is internally set independent of this setting. +; + +# This is supposed to be the "default" STK500 entry. +# Attempts to select the correct firmware version +# by probing for it. Better use one of the entries +# below instead. +programmer + id = "stk500"; + desc = "Atmel STK500"; + type = "stk500generic"; + connection_type = serial; +; + +programmer + id = "stk500v1"; + desc = "Atmel STK500 Version 1.x firmware"; + type = "stk500"; + connection_type = serial; +; + +programmer + id = "mib510"; + desc = "Crossbow MIB510 programming board"; + type = "stk500"; + connection_type = serial; +; + +programmer + id = "stk500v2"; + desc = "Atmel STK500 Version 2.x firmware"; + type = "stk500v2"; + connection_type = serial; +; + +programmer + id = "stk500pp"; + desc = "Atmel STK500 V2 in parallel programming mode"; + type = "stk500pp"; + connection_type = serial; +; + +programmer + id = "stk500hvsp"; + desc = "Atmel STK500 V2 in high-voltage serial programming mode"; + type = "stk500hvsp"; + connection_type = serial; +; + +programmer + id = "stk600"; + desc = "Atmel STK600"; + type = "stk600"; + connection_type = usb; +; + +programmer + id = "stk600pp"; + desc = "Atmel STK600 in parallel programming mode"; + type = "stk600pp"; + connection_type = usb; +; + +programmer + id = "stk600hvsp"; + desc = "Atmel STK600 in high-voltage serial programming mode"; + type = "stk600hvsp"; + connection_type = usb; +; + +programmer + id = "avr910"; + desc = "Atmel Low Cost Serial Programmer"; + type = "avr910"; + connection_type = serial; +; + +programmer + id = "ft245r"; + desc = "FT245R Synchronous BitBang"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 1; # D1 + sck = 0; # D0 + mosi = 2; # D2 + reset = 4; # D4 +; + +programmer + id = "ft232r"; + desc = "FT232R Synchronous BitBang"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 1; # RxD + sck = 0; # TxD + mosi = 2; # RTS + reset = 4; # DTR +; + +# see http://www.bitwizard.nl/wiki/index.php/FTDI_ATmega +programmer + id = "bwmega"; + desc = "BitWizard ftdi_atmega builtin programmer"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 5; # DSR + sck = 6; # DCD + mosi = 3; # CTS + reset = 7; # RI +; + +# see http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html +# Note: pins are numbered from 1! +programmer + id = "arduino-ft232r"; + desc = "Arduino: FT232R connected to ISP"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 3; # CTS X3(1) + sck = 5; # DSR X3(2) + mosi = 6; # DCD X3(3) + reset = 7; # RI X3(4) +; + +# website mentioned above uses this id +programmer parent "arduino-ft232r" + id = "diecimila"; + desc = "alias for arduino-ft232r"; +; + +# There is a ATmega328P kit PCB called "uncompatino". +# This board allows ISP via its on-board FT232R. +# This is designed like Arduino Duemilanove but has no standard ICPS header. +# Its 4 pairs of pins are shorted to enable ftdi_syncbb. +# http://akizukidenshi.com/catalog/g/gP-07487/ +# http://akizukidenshi.com/download/ds/akizuki/k6096_manual_20130816.pdf +programmer + id = "uncompatino"; + desc = "uncompatino with all pairs of pins shorted"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 3; # cts + sck = 5; # dsr + mosi = 6; # dcd + reset = 7; # ri +; + +# FTDI USB to serial cable TTL-232R-5V with a custom adapter for ICSP +# http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm +# http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf +# For ICSP pinout see for example http://www.atmel.com/images/doc2562.pdf +# (Figure 1. ISP6PIN header pinout and Table 1. Connections required for ISP ...) +# TTL-232R GND 1 Black -> ICPS GND (pin 6) +# TTL-232R CTS 2 Brown -> ICPS MOSI (pin 4) +# TTL-232R VCC 3 Red -> ICPS VCC (pin 2) +# TTL-232R TXD 4 Orange -> ICPS RESET (pin 5) +# TTL-232R RXD 5 Yellow -> ICPS SCK (pin 3) +# TTL-232R RTS 6 Green -> ICPS MISO (pin 1) +# Except for VCC and GND, you can connect arbitual pairs as long as +# the following table is adjusted. +programmer + id = "ttl232r"; + desc = "FTDI TTL232R-5V with ICSP adapter"; + type = "ftdi_syncbb"; + connection_type = usb; + miso = 2; # rts + sck = 1; # rxd + mosi = 3; # cts + reset = 0; # txd +; + +programmer + id = "usbasp"; + desc = "USBasp, http://www.fischl.de/usbasp/"; + type = "usbasp"; + connection_type = usb; + usbvid = 0x16C0; # VOTI + usbpid = 0x05DC; # Obdev's free shared PID + usbvendor = "www.fischl.de"; + usbproduct = "USBasp"; + + # following variants are autodetected for id "usbasp" + + # original usbasp from fischl.de + # see above "usbasp" + + # old usbasp from fischl.de + #usbvid = 0x03EB; # ATMEL + #usbpid = 0xC7B4; # (unoffical) USBasp + #usbvendor = "www.fischl.de"; + #usbproduct = "USBasp"; + + # NIBObee (only if -P nibobee is given on command line) + # see below "nibobee" +; + +programmer + id = "nibobee"; + desc = "NIBObee"; + type = "usbasp"; + connection_type = usb; + usbvid = 0x16C0; # VOTI + usbpid = 0x092F; # NIBObee PID + usbvendor = "www.nicai-systems.com"; + usbproduct = "NIBObee"; +; + +programmer + id = "usbasp-clone"; + desc = "Any usbasp clone with correct VID/PID"; + type = "usbasp"; + connection_type = usb; + usbvid = 0x16C0; # VOTI + usbpid = 0x05DC; # Obdev's free shared PID + #usbvendor = ""; + #usbproduct = ""; +; + +programmer + id = "usbtiny"; + desc = "USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/"; + type = "usbtiny"; + connection_type = usb; + usbvid = 0x1781; + usbpid = 0x0c9f; +; + +programmer + id = "butterfly"; + desc = "Atmel Butterfly Development Board"; + type = "butterfly"; + connection_type = serial; +; + +programmer + id = "avr109"; + desc = "Atmel AppNote AVR109 Boot Loader"; + type = "butterfly"; + connection_type = serial; +; + +programmer + id = "avr911"; + desc = "Atmel AppNote AVR911 AVROSP"; + type = "butterfly"; + connection_type = serial; +; + +# suggested in http://forum.mikrokopter.de/topic-post48317.html +programmer + id = "mkbutterfly"; + desc = "Mikrokopter.de Butterfly"; + type = "butterfly_mk"; + connection_type = serial; +; + +programmer parent "mkbutterfly" + id = "butterfly_mk"; +; + +programmer + id = "jtagmkI"; + desc = "Atmel JTAG ICE (mkI)"; + baudrate = 115200; # default is 115200 + type = "jtagmki"; + connection_type = serial; +; + +# easier to type +programmer parent "jtagmkI" + id = "jtag1"; +; + +# easier to type +programmer parent "jtag1" + id = "jtag1slow"; + baudrate = 19200; +; + +# The JTAG ICE mkII has both, serial and USB connectivity. As it is +# mostly used through USB these days (AVR Studio 5 only supporting it +# that way), we make connection_type = usb the default. Users are +# still free to use a serial port with the -P option. + +programmer + id = "jtagmkII"; + desc = "Atmel JTAG ICE mkII"; + baudrate = 19200; # default is 19200 + type = "jtagmkii"; + connection_type = usb; +; + +# easier to type +programmer parent "jtagmkII" + id = "jtag2slow"; +; + +# JTAG ICE mkII @ 115200 Bd +programmer parent "jtag2slow" + id = "jtag2fast"; + baudrate = 115200; +; + +# make the fast one the default, people will love that +programmer parent "jtag2fast" + id = "jtag2"; +; + +# JTAG ICE mkII in ISP mode +programmer + id = "jtag2isp"; + desc = "Atmel JTAG ICE mkII in ISP mode"; + baudrate = 115200; + type = "jtagmkii_isp"; + connection_type = usb; +; + +# JTAG ICE mkII in debugWire mode +programmer + id = "jtag2dw"; + desc = "Atmel JTAG ICE mkII in debugWire mode"; + baudrate = 115200; + type = "jtagmkii_dw"; + connection_type = usb; +; + +# JTAG ICE mkII in AVR32 mode +programmer + id = "jtagmkII_avr32"; + desc = "Atmel JTAG ICE mkII im AVR32 mode"; + baudrate = 115200; + type = "jtagmkii_avr32"; + connection_type = usb; +; + +# JTAG ICE mkII in AVR32 mode +programmer + id = "jtag2avr32"; + desc = "Atmel JTAG ICE mkII im AVR32 mode"; + baudrate = 115200; + type = "jtagmkii_avr32"; + connection_type = usb; +; + +# JTAG ICE mkII in PDI mode +programmer + id = "jtag2pdi"; + desc = "Atmel JTAG ICE mkII PDI mode"; + baudrate = 115200; + type = "jtagmkii_pdi"; + connection_type = usb; +; + +# AVR Dragon in JTAG mode +programmer + id = "dragon_jtag"; + desc = "Atmel AVR Dragon in JTAG mode"; + baudrate = 115200; + type = "dragon_jtag"; + connection_type = usb; +; + +# AVR Dragon in ISP mode +programmer + id = "dragon_isp"; + desc = "Atmel AVR Dragon in ISP mode"; + baudrate = 115200; + type = "dragon_isp"; + connection_type = usb; +; + +# AVR Dragon in PP mode +programmer + id = "dragon_pp"; + desc = "Atmel AVR Dragon in PP mode"; + baudrate = 115200; + type = "dragon_pp"; + connection_type = usb; +; + +# AVR Dragon in HVSP mode +programmer + id = "dragon_hvsp"; + desc = "Atmel AVR Dragon in HVSP mode"; + baudrate = 115200; + type = "dragon_hvsp"; + connection_type = usb; +; + +# AVR Dragon in debugWire mode +programmer + id = "dragon_dw"; + desc = "Atmel AVR Dragon in debugWire mode"; + baudrate = 115200; + type = "dragon_dw"; + connection_type = usb; +; + +# AVR Dragon in PDI mode +programmer + id = "dragon_pdi"; + desc = "Atmel AVR Dragon in PDI mode"; + baudrate = 115200; + type = "dragon_pdi"; + connection_type = usb; +; + +programmer + id = "jtag3"; + desc = "Atmel AVR JTAGICE3 in JTAG mode"; + type = "jtagice3"; + connection_type = usb; + usbpid = 0x2110, 0x2140; +; + +programmer + id = "jtag3pdi"; + desc = "Atmel AVR JTAGICE3 in PDI mode"; + type = "jtagice3_pdi"; + connection_type = usb; + usbpid = 0x2110, 0x2140; +; + +programmer + id = "jtag3dw"; + desc = "Atmel AVR JTAGICE3 in debugWIRE mode"; + type = "jtagice3_dw"; + connection_type = usb; + usbpid = 0x2110, 0x2140; +; + +programmer + id = "jtag3isp"; + desc = "Atmel AVR JTAGICE3 in ISP mode"; + type = "jtagice3_isp"; + connection_type = usb; + usbpid = 0x2110, 0x2140; +; + +programmer + id = "xplainedpro"; + desc = "Atmel AVR XplainedPro in JTAG mode"; + type = "jtagice3"; + connection_type = usb; + usbpid = 0x2111; +; + +programmer + id = "atmelice"; + desc = "Atmel-ICE (ARM/AVR) in JTAG mode"; + type = "jtagice3"; + connection_type = usb; + usbpid = 0x2141; +; + +programmer + id = "atmelice_pdi"; + desc = "Atmel-ICE (ARM/AVR) in PDI mode"; + type = "jtagice3_pdi"; + connection_type = usb; + usbpid = 0x2141; +; + +programmer + id = "atmelice_dw"; + desc = "Atmel-ICE (ARM/AVR) in debugWIRE mode"; + type = "jtagice3_dw"; + connection_type = usb; + usbpid = 0x2141; +; + +programmer + id = "atmelice_isp"; + desc = "Atmel-ICE (ARM/AVR) in ISP mode"; + type = "jtagice3_isp"; + connection_type = usb; + usbpid = 0x2141; +; + + +programmer + id = "pavr"; + desc = "Jason Kyle's pAVR Serial Programmer"; + type = "avr910"; + connection_type = serial; +; + +programmer + id = "pickit2"; + desc = "MicroChip's PICkit2 Programmer"; + type = "pickit2"; + connection_type = usb; +; + +programmer + id = "flip1"; + desc = "FLIP USB DFU protocol version 1 (doc7618)"; + type = "flip1"; + connection_type = usb; +; + +programmer + id = "flip2"; + desc = "FLIP USB DFU protocol version 2 (AVR4023)"; + type = "flip2"; + connection_type = usb; +; + +# Parallel port programmers. + +programmer + id = "bsd"; + desc = "Brian Dean's Programmer, http://www.bsdhome.com/avrdude/"; + type = "par"; + connection_type = parallel; + vcc = 2, 3, 4, 5; + reset = 7; + sck = 8; + mosi = 9; + miso = 10; +; + +programmer + id = "stk200"; + desc = "STK200"; + type = "par"; + connection_type = parallel; + buff = 4, 5; + sck = 6; + mosi = 7; + reset = 9; + miso = 10; +; + +# The programming dongle used by the popular Ponyprog +# utility. It is almost similar to the STK200 one, +# except that there is a LED indicating that the +# programming is currently in progress. + +programmer parent "stk200" + id = "pony-stk200"; + desc = "Pony Prog STK200"; + pgmled = 8; +; + +programmer + id = "dt006"; + desc = "Dontronics DT006"; + type = "par"; + connection_type = parallel; + reset = 4; + sck = 5; + mosi = 2; + miso = 11; +; + +programmer parent "dt006" + id = "bascom"; + desc = "Bascom SAMPLE programming cable"; +; + +programmer + id = "alf"; + desc = "Nightshade ALF-PgmAVR, http://nightshade.homeip.net/"; + type = "par"; + connection_type = parallel; + vcc = 2, 3, 4, 5; + buff = 6; + reset = 7; + sck = 8; + mosi = 9; + miso = 10; + errled = 1; + rdyled = 14; + pgmled = 16; + vfyled = 17; +; + +programmer + id = "sp12"; + desc = "Steve Bolt's Programmer"; + type = "par"; + connection_type = parallel; + vcc = 4,5,6,7,8; + reset = 3; + sck = 2; + mosi = 9; + miso = 11; +; + +programmer + id = "picoweb"; + desc = "Picoweb Programming Cable, http://www.picoweb.net/"; + type = "par"; + connection_type = parallel; + reset = 2; + sck = 3; + mosi = 4; + miso = 13; +; + +programmer + id = "abcmini"; + desc = "ABCmini Board, aka Dick Smith HOTCHIP"; + type = "par"; + connection_type = parallel; + reset = 4; + sck = 3; + mosi = 2; + miso = 10; +; + +programmer + id = "futurlec"; + desc = "Futurlec.com programming cable."; + type = "par"; + connection_type = parallel; + reset = 3; + sck = 2; + mosi = 1; + miso = 10; +; + + +# From the contributor of the "xil" jtag cable: +# The "vcc" definition isn't really vcc (the cable gets its power from +# the programming circuit) but is necessary to switch one of the +# buffer lines (trying to add it to the "buff" lines doesn't work in +# avrdude versions before 5.5j). +# With this, TMS connects to RESET, TDI to MOSI, TDO to MISO and TCK +# to SCK (plus vcc/gnd of course) +programmer + id = "xil"; + desc = "Xilinx JTAG cable"; + type = "par"; + connection_type = parallel; + mosi = 2; + sck = 3; + reset = 4; + buff = 5; + miso = 13; + vcc = 6; +; + + +programmer + id = "dapa"; + desc = "Direct AVR Parallel Access cable"; + type = "par"; + connection_type = parallel; + vcc = 3; + reset = 16; + sck = 1; + mosi = 2; + miso = 11; +; + +programmer + id = "atisp"; + desc = "AT-ISP V1.1 programming cable for AVR-SDK1 from micro-research.co.th"; + type = "par"; + connection_type = parallel; + reset = ~6; + sck = ~8; + mosi = ~7; + miso = ~10; +; + +programmer + id = "ere-isp-avr"; + desc = "ERE ISP-AVR "; + type = "par"; + connection_type = parallel; + reset = ~4; + sck = 3; + mosi = 2; + miso = 10; +; + +programmer + id = "blaster"; + desc = "Altera ByteBlaster"; + type = "par"; + connection_type = parallel; + sck = 2; + miso = 11; + reset = 3; + mosi = 8; + buff = 14; +; + +# It is almost same as pony-stk200, except vcc on pin 5 to auto +# disconnect port (download on http://electropol.free.fr/spip/spip.php?article27) +programmer parent "pony-stk200" + id = "frank-stk200"; + desc = "Frank STK200"; + buff = ; # delete buff pin assignment + vcc = 5; +; + +# The AT98ISP Cable is a simple parallel dongle for AT89 family. +# http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2877 +programmer + id = "89isp"; + desc = "Atmel at89isp cable"; + type = "par"; + connection_type = parallel; + reset = 17; + sck = 1; + mosi = 2; + miso = 10; +; + + +#This programmer bitbangs GPIO lines using the Linux sysfs GPIO interface +# +#To enable it set the configuration below to match the GPIO lines connected to the +#relevant ISP header pins and uncomment the entry definition. In case you don't +#have the required permissions to edit this system wide config file put the +#entry in a separate .conf file and use it with -C+.conf +#on the command line. +# +#To check if your avrdude build has support for the linuxgpio programmer compiled in, +#use -c?type on the command line and look for linuxgpio in the list. If it's not available +#you need pass the --enable-linuxgpio=yes option to configure and recompile avrdude. +# +#programmer +# id = "linuxgpio"; +# desc = "Use the Linux sysfs interface to bitbang GPIO lines"; +# type = "linuxgpio"; +# reset = ?; +# sck = ?; +# mosi = ?; +# miso = ?; +#; + +# some ultra cheap programmers use bitbanging on the +# serialport. +# +# PC - DB9 - Pins for RS232: +# +# GND 5 -- |O +# | O| <- 9 RI +# DTR 4 <- |O | +# | O| <- 8 CTS +# TXD 3 <- |O | +# | O| -> 7 RTS +# RXD 2 -> |O | +# | O| <- 6 DSR +# DCD 1 -> |O +# +# Using RXD is currently not supported. +# Using RI is not supported under Win32 but is supported under Posix. + +# serial ponyprog design (dasa2 in uisp) +# reset=!txd sck=rts mosi=dtr miso=cts + +programmer + id = "ponyser"; + desc = "design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts"; + type = "serbb"; + connection_type = serial; + reset = ~3; + sck = 7; + mosi = 4; + miso = 8; +; + +# Same as above, different name +# reset=!txd sck=rts mosi=dtr miso=cts + +programmer parent "ponyser" + id = "siprog"; + desc = "Lancos SI-Prog "; +; + +# unknown (dasa in uisp) +# reset=rts sck=dtr mosi=txd miso=cts + +programmer + id = "dasa"; + desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts"; + type = "serbb"; + connection_type = serial; + reset = 7; + sck = 4; + mosi = 3; + miso = 8; +; + +# unknown (dasa3 in uisp) +# reset=!dtr sck=rts mosi=txd miso=cts + +programmer + id = "dasa3"; + desc = "serial port banging, reset=!dtr sck=rts mosi=txd miso=cts"; + type = "serbb"; + connection_type = serial; + reset = ~4; + sck = 7; + mosi = 3; + miso = 8; +; + +# C2N232i (jumper configuration "auto") +# reset=dtr sck=!rts mosi=!txd miso=!cts + +programmer + id = "c2n232i"; + desc = "serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts"; + type = "serbb"; + connection_type = serial; + reset = 4; + sck = ~7; + mosi = ~3; + miso = ~8; +; + +# +# PART DEFINITIONS +# + +#------------------------------------------------------------ +# ATtiny11 +#------------------------------------------------------------ + +# This is an HVSP-only device. + +part + id = "t11"; + desc = "ATtiny11"; + stk500_devcode = 0x11; + signature = 0x1e 0x90 0x04; + chip_erase_delay = 20000; + + timeout = 200; + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + blocksize = 64; + readsize = 256; + delay = 5; + ; + + memory "flash" + size = 1024; + blocksize = 128; + readsize = 256; + delay = 3; + ; + + memory "signature" + size = 3; + ; + + memory "lock" + size = 1; + ; + + memory "calibration" + size = 1; + ; + + memory "fuse" + size = 1; + ; +; + +#------------------------------------------------------------ +# ATtiny12 +#------------------------------------------------------------ + +part + id = "t12"; + desc = "ATtiny12"; + stk500_devcode = 0x12; + avr910_devcode = 0x55; + signature = 0x1e 0x90 0x05; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 8; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + size = 1024; + min_write_delay = 4500; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +; + +#------------------------------------------------------------ +# ATtiny13 +#------------------------------------------------------------ + +part + id = "t13"; + desc = "ATtiny13"; + has_debugwire = yes; + flash_instr = 0xB4, 0x0E, 0x1E; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x14; + signature = 0x1e 0x90 0x07; + chip_erase_delay = 4000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 90; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 0; + + memory "eeprom" + size = 64; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 5; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 1024; + page_size = 32; + num_pages = 32; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 0 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny15 +#------------------------------------------------------------ + +part + id = "t15"; + desc = "ATtiny15"; + stk500_devcode = 0x13; + avr910_devcode = 0x56; + signature = 0x1e 0x90 0x06; + chip_erase_delay = 8200; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 5; + synchcycles = 6; + latchcycles = 16; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 64; + min_write_delay = 8200; + max_write_delay = 8200; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + size = 1024; + min_write_delay = 4100; + max_write_delay = 4100; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x o o o o x x o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x i i i i 1 1 i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +; + +#------------------------------------------------------------ +# AT90s1200 +#------------------------------------------------------------ + +part + id = "1200"; + desc = "AT90S1200"; + is_at90s1200 = yes; + stk500_devcode = 0x33; + avr910_devcode = 0x13; + signature = 0x1e 0x90 0x01; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 1; + bytedelay = 0; + pollindex = 0; + pollvalue = 0xFF; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 64; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x x a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 32; + readsize = 256; + ; + memory "flash" + size = 1024; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x02; + delay = 15; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s4414 +#------------------------------------------------------------ + +part + id = "4414"; + desc = "AT90S4414"; + stk500_devcode = 0x50; + avr910_devcode = 0x28; + signature = 0x1e 0x92 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s2313 +#------------------------------------------------------------ + +part + id = "2313"; + desc = "AT90S2313"; + stk500_devcode = 0x40; + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 128; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 2048; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x i i x", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s2333 +#------------------------------------------------------------ + +part + id = "2333"; +##### WARNING: No XML file for device 'AT90S2333'! ##### + desc = "AT90S2333"; + stk500_devcode = 0x42; + avr910_devcode = 0x34; + signature = 0x1e 0x91 0x05; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + size = 2048; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + pwroff_after_write = yes; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + + +#------------------------------------------------------------ +# AT90s2343 (also AT90s2323 and ATtiny22) +#------------------------------------------------------------ + +part + id = "2343"; + desc = "AT90S2343"; + stk500_devcode = 0x43; + avr910_devcode = 0x4c; + signature = 0x1e 0x91 0x03; + chip_erase_delay = 18000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x00, + 0x68, 0x78, 0x68, 0x68, 0x00, 0x00, 0x68, 0x78, + 0x78, 0x00, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 0; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 50; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + memory "flash" + size = 2048; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 128; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o o x x x x o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o o x x x x o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + + +#------------------------------------------------------------ +# AT90s4433 +#------------------------------------------------------------ + +part + id = "4433"; + desc = "AT90S4433"; + stk500_devcode = 0x51; + avr910_devcode = 0x30; + signature = 0x1e 0x92 0x03; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + pwroff_after_write = yes; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s4434 +#------------------------------------------------------------ + +part + id = "4434"; +##### WARNING: No XML file for device 'AT90S4434'! ##### + desc = "AT90S4434"; + stk500_devcode = 0x52; + avr910_devcode = 0x6c; + signature = 0x1e 0x92 0x02; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + memory "eeprom" + size = 256; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + ; + memory "flash" + size = 4096; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 i i i i i", + "x x x x x x x x x x x x x x x x"; + ; + memory "lock" + size = 1; + min_write_delay = 9000; + max_write_delay = 20000; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + ; + ; + +#------------------------------------------------------------ +# AT90s8515 +#------------------------------------------------------------ + +part + id = "8515"; + desc = "AT90S8515"; + stk500_devcode = 0x60; + avr910_devcode = 0x38; + signature = 0x1e 0x93 0x01; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 512; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 8192; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x7f; + readback_p2 = 0x7f; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# AT90s8535 +#------------------------------------------------------------ + +part + id = "8535"; + desc = "AT90S8535"; + stk500_devcode = 0x61; + avr910_devcode = 0x68; + signature = 0x1e 0x93 0x03; + chip_erase_delay = 20000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 1; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0x00; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "flash" + size = 8192; + min_write_delay = 9000; + max_write_delay = 20000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write_lo = " 0 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + write_hi = " 0 1 0 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 128; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "fuse" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x x o"; + write = "1 0 1 0 1 1 0 0 1 0 1 1 1 1 1 i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x o o x x x x x x"; + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + ; + +#------------------------------------------------------------ +# ATmega103 +#------------------------------------------------------------ + +part + id = "m103"; + desc = "ATmega103"; + stk500_devcode = 0xB1; + avr910_devcode = 0x41; + signature = 0x1e 0x97 0x01; + chip_erase_delay = 112000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x8E, 0x9E, 0x2E, 0x3E, 0xAE, 0xBE, + 0x4E, 0x5E, 0xCE, 0xDE, 0x6E, 0x7E, 0xEE, 0xDE, + 0x66, 0x76, 0xE6, 0xF6, 0x6A, 0x7A, 0xEA, 0x7A, + 0x7F, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 15; + chiperasepolltimeout = 0; + programfusepulsewidth = 2; + programfusepolltimeout = 0; + programlockpulsewidth = 0; + programlockpolltimeout = 10; + + memory "eeprom" + size = 4096; + min_write_delay = 4000; + max_write_delay = 9000; + readback_p1 = 0x80; + readback_p2 = 0x7f; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 22000; + max_write_delay = 56000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x11; + delay = 70; + blocksize = 256; + readsize = 256; + ; + + memory "fuse" + size = 1; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x x o x o 1 o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 1 i 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x o o x"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 i i 1", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega64 +#------------------------------------------------------------ + +part + id = "m64"; + desc = "ATmega64"; + has_jtag = yes; + stk500_devcode = 0xA0; + avr910_devcode = 0x45; + signature = 0x1e 0x96 0x02; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x22; + spmcr = 0x68; + allowfullpagebitstream = yes; + + ocdrev = 2; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + + +#------------------------------------------------------------ +# ATmega128 +#------------------------------------------------------------ + +part + id = "m128"; + desc = "ATmega128"; + has_jtag = yes; + stk500_devcode = 0xB2; + avr910_devcode = 0x43; + signature = 0x1e 0x97 0x02; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x22; + spmcr = 0x68; + rampz = 0x3b; + allowfullpagebitstream = yes; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 12; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN128 +#------------------------------------------------------------ + +part + id = "c128"; + desc = "AT90CAN128"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x97 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN64 +#------------------------------------------------------------ + +part + id = "c64"; + desc = "AT90CAN64"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x96 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90CAN32 +#------------------------------------------------------------ + +part + id = "c32"; + desc = "AT90CAN32"; + has_jtag = yes; + stk500_devcode = 0xB3; +# avr910_devcode = 0x43; + signature = 0x1e 0x95 0x81; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + eecr = 0x3f; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 256; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega16 +#------------------------------------------------------------ + +part + id = "m16"; + desc = "ATmega16"; + has_jtag = yes; + stk500_devcode = 0x82; + avr910_devcode = 0x74; + signature = 0x1e 0x94 0x03; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 100; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = yes; + + ocdrev = 2; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x04; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "calibration" + size = 4; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega164P +#------------------------------------------------------------ + +# close to ATmega16 + +part parent "m16" + id = "m164p"; + desc = "ATmega164P"; + signature = 0x1e 0x94 0x0a; + + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + allowfullpagebitstream = no; + chip_erase_delay = 55000; + + ocdrev = 3; + ; + + +#------------------------------------------------------------ +# ATmega324P +#------------------------------------------------------------ + +# similar to ATmega164P + +part + id = "m324p"; + desc = "ATmega324P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x95 0x08; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 55000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega324PA +#------------------------------------------------------------ + +# similar to ATmega324P + +part parent "m324p" + id = "m324pa"; + desc = "ATmega324PA"; + signature = 0x1e 0x95 0x11; + + ocdrev = 3; + ; + + +#------------------------------------------------------------ +# ATmega644 +#------------------------------------------------------------ + +# similar to ATmega164 + +part + id = "m644"; + desc = "ATmega644"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x96 0x09; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 55000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega644P +#------------------------------------------------------------ + +# similar to ATmega164p + +part parent "m644" + id = "m644p"; + desc = "ATmega644P"; + signature = 0x1e 0x96 0x0a; + + ocdrev = 3; + ; + + + +#------------------------------------------------------------ +# ATmega1284 +#------------------------------------------------------------ + +# similar to ATmega164 + +part + id = "m1284"; + desc = "ATmega1284"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x97 0x06; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 55000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega1284P +#------------------------------------------------------------ + +# similar to ATmega164p + +part + id = "m1284p"; + desc = "ATmega1284P"; + has_jtag = yes; + stk500_devcode = 0x82; # no STK500v1 support, use the ATmega16 one + avr910_devcode = 0x74; + signature = 0x1e 0x97 0x05; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 55000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega162 +#------------------------------------------------------------ + +part + id = "m162"; + desc = "ATmega162"; + has_jtag = yes; + stk500_devcode = 0x83; + avr910_devcode = 0x63; + signature = 0x1e 0x94 0x04; + chip_erase_delay = 9000; + pagel = 0xd7; + bs2 = 0xa0; + + idr = 0x04; + spmcr = 0x57; + allowfullpagebitstream = yes; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + ocdrev = 2; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + + ; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 16000; + max_write_delay = 16000; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; +; + + + +#------------------------------------------------------------ +# ATmega163 +#------------------------------------------------------------ + +part + id = "m163"; + desc = "ATmega163"; + stk500_devcode = 0x81; + avr910_devcode = 0x64; + signature = 0x1e 0x94 0x02; + chip_erase_delay = 32000; + pagel = 0xd7; + bs2 = 0xa0; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 30; + programfusepulsewidth = 0; + programfusepolltimeout = 2; + programlockpulsewidth = 0; + programlockpolltimeout = 2; + + + memory "eeprom" + size = 512; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 16000; + max_write_delay = 16000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x11; + delay = 20; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o x x o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i 1 1 i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x x x x x 1 o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x 1 1 1 1 1 i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x 0 x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega169 +#------------------------------------------------------------ + +part + id = "m169"; + desc = "ATmega169"; + has_jtag = yes; + stk500_devcode = 0x85; + avr910_devcode = 0x78; + signature = 0x1e 0x94 0x05; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + ocdrev = 2; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega329 +#------------------------------------------------------------ + +part + id = "m329"; + desc = "ATmega329"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x95 0x03; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega329P +#------------------------------------------------------------ +# Identical to ATmega329 except of the signature + +part parent "m329" + id = "m329p"; + desc = "ATmega329P"; + signature = 0x1e 0x95 0x0b; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega3290 +#------------------------------------------------------------ + +# identical to ATmega329 + +part parent "m329" + id = "m3290"; + desc = "ATmega3290"; + signature = 0x1e 0x95 0x04; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega3290P +#------------------------------------------------------------ + +# identical to ATmega3290 except of the signature + +part parent "m3290" + id = "m3290p"; + desc = "ATmega3290P"; + signature = 0x1e 0x95 0x0c; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega649 +#------------------------------------------------------------ + +part + id = "m649"; + desc = "ATmega649"; + has_jtag = yes; +# stk500_devcode = 0x85; # no STK500 support, only STK500v2 +# avr910_devcode = 0x?; # try the ATmega169 one: + avr910_devcode = 0x75; + signature = 0x1e 0x96 0x03; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega6490 +#------------------------------------------------------------ + +# identical to ATmega649 + +part parent "m649" + id = "m6490"; + desc = "ATmega6490"; + signature = 0x1e 0x96 0x04; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega32 +#------------------------------------------------------------ + +part + id = "m32"; + desc = "ATmega32"; + has_jtag = yes; + stk500_devcode = 0x91; + avr910_devcode = 0x72; + signature = 0x1e 0x95 0x02; + chip_erase_delay = 9000; + pagel = 0xd7; + bs2 = 0xa0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = yes; + + ocdrev = 2; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega161 +#------------------------------------------------------------ + +part + id = "m161"; + desc = "ATmega161"; + stk500_devcode = 0x80; + avr910_devcode = 0x60; + signature = 0x1e 0x94 0x01; + chip_erase_delay = 28000; + pagel = 0xd7; + bs2 = 0xa0; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 30; + programfusepulsewidth = 0; + programfusepolltimeout = 2; + programlockpulsewidth = 0; + programlockpolltimeout = 2; + + memory "eeprom" + size = 512; + min_write_delay = 3400; + max_write_delay = 3400; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 5; + blocksize = 128; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 14000; + max_write_delay = 14000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 16; + blocksize = 128; + readsize = 256; + ; + + memory "fuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 x x x x x x x x", + "x x x x x x x x x o x o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 x x x x x", + "x x x x x x x x 1 i 1 i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATmega8 +#------------------------------------------------------------ + +part + id = "m8"; + desc = "ATmega8"; + stk500_devcode = 0x70; + avr910_devcode = 0x76; + signature = 0x1e 0x93 0x07; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 10000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + page_size = 4; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + +#------------------------------------------------------------ +# ATmega8515 +#------------------------------------------------------------ + +part + id = "m8515"; + desc = "ATmega8515"; + stk500_devcode = 0x63; + avr910_devcode = 0x3A; + signature = 0x1e 0x93 0x06; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + + + +#------------------------------------------------------------ +# ATmega8535 +#------------------------------------------------------------ + +part + id = "m8535"; + desc = "ATmega8535"; + stk500_devcode = 0x64; + avr910_devcode = 0x69; + signature = 0x1e 0x93 0x08; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 6; + togglevtg = 0; + poweroffdelay = 0; + resetdelayms = 0; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + mode = 0x04; + delay = 20; + blocksize = 128; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 2000; + max_write_delay = 2000; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 0 0 x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + + +#------------------------------------------------------------ +# ATtiny26 +#------------------------------------------------------------ + +part + id = "t26"; + desc = "ATtiny26"; + stk500_devcode = 0x21; + avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x09; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + mode = 0x04; + delay = 10; + blocksize = 64; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 16; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x x x x i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 4; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny261 +#------------------------------------------------------------ +# Close to ATtiny26 + +part + id = "t261"; + desc = "ATtiny261"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x0c; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + size = 128; + page_size = 4; + num_pages = 32; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = "1 0 1 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 x x x x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x x a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny461 +#------------------------------------------------------------ +# Close to ATtiny261 + +part + id = "t461"; + desc = "ATtiny461"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x92 0x08; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + size = 256; + page_size = 4; + num_pages = 64; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATtiny861 +#------------------------------------------------------------ +# Close to ATtiny461 + +part + id = "t861"; + desc = "ATtiny861"; + has_debugwire = yes; + flash_instr = 0xB4, 0x00, 0x10; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x00, 0xB4, 0x00, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +# stk500_devcode = 0x21; +# avr910_devcode = 0x5e; + signature = 0x1e 0x93 0x0d; + pagel = 0xb3; + bs2 = 0xb2; + chip_erase_delay = 4000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 0; + + pp_controlstack = + 0xC4, 0xE4, 0xC4, 0xE4, 0xCC, 0xEC, 0xCC, 0xEC, + 0xD4, 0xF4, 0xD4, 0xF4, 0xDC, 0xFC, 0xDC, 0xFC, + 0xC8, 0xE8, 0xD8, 0xF8, 0x4C, 0x6C, 0x5C, 0x7C, + 0xEC, 0xBC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 2; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + size = 512; + num_pages = 128; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4000; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read = " 1 0 1 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0 x x x x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 x x x x x x x x", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 1 1 1 i i", + "x x x x x x x x x x x x x x x x"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + +; + + +#------------------------------------------------------------ +# ATmega48 +#------------------------------------------------------------ + +part + id = "m48"; + desc = "ATmega48"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x59; +# avr910_devcode = 0x; + signature = 0x1e 0x92 0x05; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 45000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + page_size = 4; + size = 256; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x x", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega48P +#------------------------------------------------------------ + +part parent "m48" + id = "m48p"; + desc = "ATmega48P"; + signature = 0x1e 0x92 0x0a; + + ocdrev = 1; + ; + +#------------------------------------------------------------ +# ATmega88 +#------------------------------------------------------------ + +part + id = "m88"; + desc = "ATmega88"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x73; +# avr910_devcode = 0x; + signature = 0x1e 0x93 0x0a; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega88P +#------------------------------------------------------------ + +part parent "m88" + id = "m88p"; + desc = "ATmega88P"; + signature = 0x1e 0x93 0x0f; + + ocdrev = 1; + ; + +#------------------------------------------------------------ +# ATmega168 +#------------------------------------------------------------ + +part + id = "m168"; + desc = "ATmega168"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x94 0x06; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + page_size = 4; + size = 512; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# ATmega168P +#------------------------------------------------------------ + +part parent "m168" + id = "m168p"; + desc = "ATmega168P"; + signature = 0x1e 0x94 0x0b; + + ocdrev = 1; +; + +#------------------------------------------------------------ +# ATtiny88 +#------------------------------------------------------------ + +part + id = "t88"; + desc = "ATtiny88"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x73; +# avr910_devcode = 0x; + signature = 0x1e 0x93 0x11; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + page_size = 4; + size = 64; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 64; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega328 +#------------------------------------------------------------ + +part + id = "m328"; + desc = "ATmega328"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x95 0x14; + pagel = 0xd7; + bs2 = 0xc2; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; + page_size = 4; + size = 1024; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +part parent "m328" + id = "m328p"; + desc = "ATmega328P"; + signature = 0x1e 0x95 0x0F; + + ocdrev = 1; +; + +#------------------------------------------------------------ +# ATmega32m1 +#------------------------------------------------------------ + +part parent "m328" + id = "m32m1"; + desc = "ATmega32M1"; + # stk500_devcode = 0x; + # avr910_devcode = 0x; + signature = 0x1e 0x95 0x84; + bs2 = 0xe2; + + memory "efuse" + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x i i i i i i"; + ; +; + +#------------------------------------------------------------ +# ATtiny2313 +#------------------------------------------------------------ + +part + id = "t2313"; + desc = "ATtiny2313"; + has_debugwire = yes; + flash_instr = 0xB2, 0x0F, 0x1F; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x23; +## Use the ATtiny26 devcode: + avr910_devcode = 0x5e; + signature = 0x1e 0x91 0x0a; + pagel = 0xD4; + bs2 = 0xD6; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, + 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, + 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, + 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 0; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + +# The information in the data sheet of April/2004 is wrong, this works: + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + +# The information in the data sheet of April/2004 is wrong, this works: + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + +# The information in the data sheet of April/2004 is wrong, this works: + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny2313 has Signature Bytes: 0x1E 0x91 0x0A. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; +# The Tiny2313 has calibration data for both 4 MHz and 8 MHz. +# The information in the data sheet of April/2004 is wrong, this works: + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny4313 +#------------------------------------------------------------ + +part + id = "t4313"; + desc = "ATtiny4313"; + has_debugwire = yes; + flash_instr = 0xB2, 0x0F, 0x1F; + eeprom_instr = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBA, 0x0F, 0xB2, 0x0F, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x23; +## Use the ATtiny26 devcode: + avr910_devcode = 0x5e; + signature = 0x1e 0x92 0x0d; + pagel = 0xD4; + bs2 = 0xD6; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, + 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, + 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, + 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 0; + + memory "eeprom" + size = 256; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny4313 has Signature Bytes: 0x1E 0x92 0x0D. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM2 +#------------------------------------------------------------ + +part + id = "pwm2"; + desc = "AT90PWM2"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x65; +## avr910_devcode = ?; + signature = 0x1e 0x93 0x81; + pagel = 0xD8; + bs2 = 0xE2; + reset = io; + chip_erase_delay = 9000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 64; + readsize = 256; + ; +# AT90PWM2 has Signature Bytes: 0x1E 0x93 0x81. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90PWM3 +#------------------------------------------------------------ + +# Completely identical to AT90PWM2 (including the signature!) + +part parent "pwm2" + id = "pwm3"; + desc = "AT90PWM3"; + ; + +#------------------------------------------------------------ +# AT90PWM2B +#------------------------------------------------------------ +# Same as AT90PWM2 but different signature. + +part parent "pwm2" + id = "pwm2b"; + desc = "AT90PWM2B"; + signature = 0x1e 0x93 0x83; + + ocdrev = 1; + ; + +#------------------------------------------------------------ +# AT90PWM3B +#------------------------------------------------------------ + +# Completely identical to AT90PWM2B (including the signature!) + +part parent "pwm2b" + id = "pwm3b"; + desc = "AT90PWM3B"; + + ocdrev = 1; + ; + +#------------------------------------------------------------ +# AT90PWM316 +#------------------------------------------------------------ + +# Similar to AT90PWM3B, but with 16 kiB flash, 512 B EEPROM, and 1024 B SRAM. + +part parent "pwm3b" + id = "pwm316"; + desc = "AT90PWM316"; + signature = 0x1e 0x94 0x83; + + ocdrev = 1; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x21; + delay = 6; + blocksize = 128; + readsize = 256; + ; + ; + +#------------------------------------------------------------ +# AT90PWM216 +#------------------------------------------------------------ +# Completely identical to AT90PWM316 (including the signature!) + +part parent "pwm316" + id = "pwm216"; + desc = "AT90PWM216"; + ; + +#------------------------------------------------------------ +# ATtiny25 +#------------------------------------------------------------ + +part + id = "t25"; + desc = "ATtiny25"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x08; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny25 has Signature Bytes: 0x1E 0x91 0x08. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny45 +#------------------------------------------------------------ + +part + id = "t45"; + desc = "ATtiny45"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x92 0x06; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 256; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny45 has Signature Bytes: 0x1E 0x92 0x08. (Data sheet 2586C-AVR-06/05 (doc2586.pdf) indicates otherwise!) + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny85 +#------------------------------------------------------------ + +part + id = "t85"; + desc = "ATtiny85"; + has_debugwire = yes; + flash_instr = 0xB4, 0x02, 0x12; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x02, 0xB4, 0x02, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x93 0x0b; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x00; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny85 has Signature Bytes: 0x1E 0x93 0x08. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega640 +#------------------------------------------------------------ +# Almost same as ATmega1280, except for different memory sizes + +part + id = "m640"; + desc = "ATmega640"; + signature = 0x1e 0x96 0x08; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega1280 +#------------------------------------------------------------ + +part + id = "m1280"; + desc = "ATmega1280"; + signature = 0x1e 0x97 0x03; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega1281 +#------------------------------------------------------------ +# Identical to ATmega1280 + +part parent "m1280" + id = "m1281"; + desc = "ATmega1281"; + signature = 0x1e 0x97 0x04; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega2560 +#------------------------------------------------------------ + +part + id = "m2560"; + desc = "ATmega2560"; + signature = 0x1e 0x98 0x01; + has_jtag = yes; + stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 4; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 262144; + page_size = 256; + num_pages = 1024; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega2561 +#------------------------------------------------------------ + +part parent "m2560" + id = "m2561"; + desc = "ATmega2561"; + signature = 0x1e 0x98 0x02; + + ocdrev = 4; + ; + +#------------------------------------------------------------ +# ATmega128RFA1 +#------------------------------------------------------------ +# Identical to ATmega2561 but half the ROM + +part parent "m2561" + id = "m128rfa1"; + desc = "ATmega128RFA1"; + signature = 0x1e 0xa7 0x01; + chip_erase_delay = 55000; + bs2 = 0xE2; + + ocdrev = 3; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 50000; + max_write_delay = 50000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 256; + readsize = 256; + ; + ; + +#------------------------------------------------------------ +# ATmega256RFR2 +#------------------------------------------------------------ + +part parent "m2561" + id = "m256rfr2"; + desc = "ATmega256RFR2"; + signature = 0x1e 0xa8 0x02; + chip_erase_delay = 18500; + bs2 = 0xE2; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 8192; + min_write_delay = 13000; + max_write_delay = 13000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + + ocdrev = 4; + ; + +#------------------------------------------------------------ +# ATmega128RFR2 +#------------------------------------------------------------ + +part parent "m128rfa1" + id = "m128rfr2"; + desc = "ATmega128RFR2"; + signature = 0x1e 0xa7 0x02; + + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega64RFR2 +#------------------------------------------------------------ + +part parent "m128rfa1" + id = "m64rfr2"; + desc = "ATmega64RFR2"; + signature = 0x1e 0xa6 0x02; + + + ocdrev = 3; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 50000; + max_write_delay = 50000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 256; + readsize = 256; + ; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 13000; + max_write_delay = 13000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + + ; + +#------------------------------------------------------------ +# ATmega2564RFR2 +#------------------------------------------------------------ + +part parent "m256rfr2" + id = "m2564rfr2"; + desc = "ATmega2564RFR2"; + signature = 0x1e 0xa8 0x03; + ; + +#------------------------------------------------------------ +# ATmega1284RFR2 +#------------------------------------------------------------ + +part parent "m128rfr2" + id = "m1284rfr2"; + desc = "ATmega1284RFR2"; + signature = 0x1e 0xa7 0x03; + ; + +#------------------------------------------------------------ +# ATmega644RFR2 +#------------------------------------------------------------ + +part parent "m64rfr2" + id = "m644rfr2"; + desc = "ATmega644RFR2"; + signature = 0x1e 0xa6 0x03; + ; + +#------------------------------------------------------------ +# ATtiny24 +#------------------------------------------------------------ + +part + id = "t24"; + desc = "ATtiny24"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x91 0x0b; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 128; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 2048; + page_size = 32; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x x a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny24 has Signature Bytes: 0x1E 0x91 0x0B. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny44 +#------------------------------------------------------------ + +part + id = "t44"; + desc = "ATtiny44"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x92 0x07; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 256; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny44 has Signature Bytes: 0x1E 0x92 0x07. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny84 +#------------------------------------------------------------ + +part + id = "t84"; + desc = "ATtiny84"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; +## no STK500 devcode in XML file, use the ATtiny45 one + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x93 0x0c; + reset = io; + chip_erase_delay = 4500; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + hvsp_controlstack = + 0x4C, 0x0C, 0x1C, 0x2C, 0x3C, 0x64, 0x74, 0x66, + 0x68, 0x78, 0x68, 0x68, 0x7A, 0x6A, 0x68, 0x78, + 0x78, 0x7D, 0x6D, 0x0C, 0x80, 0x40, 0x20, 0x10, + 0x11, 0x08, 0x04, 0x02, 0x03, 0x08, 0x04, 0x0F; + hventerstabdelay = 100; + hvspcmdexedelay = 0; + synchcycles = 6; + latchcycles = 1; + togglevtg = 1; + poweroffdelay = 25; + resetdelayms = 0; + resetdelayus = 70; + hvleavestabdelay = 100; + resetdelay = 25; + chiperasepolltimeout = 40; + chiperasetime = 0; + programfusepolltimeout = 25; + programlockpolltimeout = 25; + + ocdrev = 1; + + memory "eeprom" + size = 512; + paged = no; + page_size = 4; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x a8", + "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " x a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 8192; + page_size = 64; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 32; + readsize = 256; + ; +# ATtiny84 has Signature Bytes: 0x1E 0x93 0x0C. + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x x x x x x x i i"; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATtiny43U +#------------------------------------------------------------ + +part + id = "t43u"; + desc = "ATtiny43u"; + has_debugwire = yes; + flash_instr = 0xB4, 0x07, 0x17; + eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, + 0xBC, 0x07, 0xB4, 0x07, 0xBA, 0x0D, 0xBB, 0xBC, + 0x99, 0xE1, 0xBB, 0xAC; + stk500_devcode = 0x14; +## avr910_devcode = ?; +## Try the AT90S2313 devcode: + avr910_devcode = 0x20; + signature = 0x1e 0x92 0x0C; + reset = io; + chip_erase_delay = 1000; + + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, 0x4E, 0x5E, + 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, 0x06, 0x16, 0x46, 0x56, + 0x0A, 0x1A, 0x4A, 0x5A, 0x1E, 0x7C, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + hvspcmdexedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 20; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + memory "eeprom" + size = 64; + paged = yes; + page_size = 4; + num_pages = 16; + min_write_delay = 4000; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", + "0 0 a4 a3 a2 a1 a0 o o o o o o o o"; + + write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", + "0 0 a5 a4 a3 a2 a1 a0 i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x x", + " 0 0 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 5; + blocksize = 4; + readsize = 256; + ; + memory "flash" + paged = yes; + size = 4096; + page_size = 64; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x x a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 64; + readsize = 256; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + memory "lock" + size = 1; + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x x x x i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 4500; + max_write_delay = 4500; + ; + + memory "calibration" + size = 2; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# ATmega32u4 +#------------------------------------------------------------ + +part + id = "m32u4"; + desc = "ATmega32U4"; + signature = 0x1e 0x95 0x87; + usbpid = 0x2ff4; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB646 +#------------------------------------------------------------ + +part + id = "usb646"; + desc = "AT90USB646"; + signature = 0x1e 0x96 0x82; + usbpid = 0x2ff9; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x x a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB647 +#------------------------------------------------------------ +# identical to AT90USB646 + +part parent "usb646" + id = "usb647"; + desc = "AT90USB647"; + signature = 0x1e 0x96 0x82; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# AT90USB1286 +#------------------------------------------------------------ + +part + id = "usb1286"; + desc = "AT90USB1286"; + signature = 0x1e 0x97 0x82; + usbpid = 0x2ffb; + has_jtag = yes; +# stk500_devcode = 0xB2; +# avr910_devcode = 0x43; + chip_erase_delay = 9000; + pagel = 0xD7; + bs2 = 0xA0; + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + rampz = 0x3b; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 4096; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " x x x x a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 131072; + page_size = 256; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 256; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x x i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 x x x x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB1287 +#------------------------------------------------------------ +# identical to AT90USB1286 + +part parent "usb1286" + id = "usb1287"; + desc = "AT90USB1287"; + signature = 0x1e 0x97 0x82; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# AT90USB162 +#------------------------------------------------------------ + +part + id = "usb162"; + desc = "AT90USB162"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x94 0x82; + usbpid = 0x2ffa; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# AT90USB82 +#------------------------------------------------------------ +# Changes against AT90USB162 (beside IDs) +# memory "flash" +# size = 8192; +# num_pages = 64; + +part + id = "usb82"; + desc = "AT90USB82"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x93 0x82; + usbpid = 0x2ff7; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 128; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega32U2 +#------------------------------------------------------------ +# Changes against AT90USB162 (beside IDs) +# memory "flash" +# size = 32768; +# num_pages = 256; +# memory "eeprom" +# size = 1024; +# num_pages = 256; +part + id = "m32u2"; + desc = "ATmega32U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x95 0x8a; + usbpid = 0x2ff0; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + num_pages = 256; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; +#------------------------------------------------------------ +# ATmega16U2 +#------------------------------------------------------------ +# Changes against ATmega32U2 (beside IDs) +# memory "flash" +# size = 16384; +# num_pages = 128; +# memory "eeprom" +# size = 512; +# num_pages = 128; +part + id = "m16u2"; + desc = "ATmega16U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x94 0x89; + usbpid = 0x2fef; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 128; + num_pages = 128; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega8U2 +#------------------------------------------------------------ +# Changes against ATmega16U2 (beside IDs) +# memory "flash" +# size = 8192; +# page_size = 64; +# blocksize = 64; + +part + id = "m8u2"; + desc = "ATmega8U2"; + has_jtag = no; + has_debugwire = yes; + signature = 0x1e 0x93 0x89; + usbpid = 0x2fee; + chip_erase_delay = 9000; + reset = io; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + pagel = 0xD7; + bs2 = 0xC6; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + ocdrev = 1; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 512; + num_pages = 128; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0x00; + readback_p2 = 0x00; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 20; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 8192; + page_size = 128; + num_pages = 64; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0x00; + readback_p2 = 0x00; + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + ; + + memory "lfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x i i i i i i i i"; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + ; +#------------------------------------------------------------ +# ATmega325 +#------------------------------------------------------------ + +part + id = "m325"; + desc = "ATmega325"; + signature = 0x1e 0x95 0x05; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 4; /* for parallel programming */ + size = 1024; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 0 a9 a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 32768; + page_size = 128; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega645 +#------------------------------------------------------------ + +part + id = "m645"; + desc = "ATmega645"; + signature = 0x1E 0x96 0x05; + has_jtag = yes; +# stk500_devcode = 0x??; # No STK500v1 support? +# avr910_devcode = 0x??; # Try the ATmega16 one + avr910_devcode = 0x74; + pagel = 0xd7; + bs2 = 0xa0; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F, + 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F, + 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B, + 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 5; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + idr = 0x31; + spmcr = 0x57; + allowfullpagebitstream = no; + + ocdrev = 3; + + memory "eeprom" + paged = no; /* leave this "no" */ + page_size = 8; /* for parallel programming */ + size = 2048; + min_write_delay = 9000; + max_write_delay = 9000; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 0 0 0 a10 a9 a8", + " a7 a6 a5 a4 a3 0 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 10; + blocksize = 8; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 65536; + page_size = 256; + num_pages = 256; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 0 0 0 0 0", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " 0 0 0 0 0 0 0 0"; + + mode = 0x41; + delay = 10; + blocksize = 128; + readsize = 256; + ; + + memory "lock" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 1 1 i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "lfuse" + size = 1; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "hfuse" + size = 1; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "0 0 0 0 0 0 0 0 i i i i i i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "efuse" + size = 1; + + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "0 0 0 0 0 0 0 0 1 1 1 1 1 i i i"; + min_write_delay = 9000; + max_write_delay = 9000; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 a1 a0 o o o o o o o o"; + ; + + memory "calibration" + size = 1; + + read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + ; + +#------------------------------------------------------------ +# ATmega3250 +#------------------------------------------------------------ + +part parent "m325" + id = "m3250"; + desc = "ATmega3250"; + signature = 0x1E 0x95 0x06; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# ATmega6450 +#------------------------------------------------------------ + +part parent "m645" + id = "m6450"; + desc = "ATmega6450"; + signature = 0x1E 0x96 0x06; + + ocdrev = 3; + ; + +#------------------------------------------------------------ +# AVR XMEGA family common values +#------------------------------------------------------------ + +part + id = ".xmega"; + desc = "AVR XMEGA family common values"; + has_pdi = yes; + nvm_base = 0x01c0; + mcu_base = 0x0090; + +# needed for wiring aka stk500v2 protocol + reset = dedicated; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + + memory "signature" + size = 3; + offset = 0x1000090; +# needed for wiring aka stk500v2 protocol + read = "0 0 1 1 0 0 0 0 x x x x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; + + memory "prodsig" + size = 0x32; + offset = 0x8e0200; + page_size = 0x32; + readsize = 0x32; + ; + + memory "fuse1" + size = 1; + offset = 0x8f0021; + ; + + memory "fuse2" + size = 1; + offset = 0x8f0022; + ; + + memory "fuse4" + size = 1; + offset = 0x8f0024; + ; + + memory "fuse5" + size = 1; + offset = 0x8f0025; + ; + + memory "lock" + size = 1; + offset = 0x8f0027; + ; + + memory "data" + # SRAM, only used to supply the offset + offset = 0x1000000; + ; +; + +#------------------------------------------------------------ +# ATxmega16A4U +#------------------------------------------------------------ + +part parent ".xmega" + id = "x16a4u"; + desc = "ATxmega16A4U"; + signature = 0x1e 0x94 0x41; + usbpid = 0x2fe3; + + memory "eeprom" + size = 0x400; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x4000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x803000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x1000; + offset = 0x804000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x5000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x100; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega16C4 +#------------------------------------------------------------ + +part parent "x16a4u" + id = "x16c4"; + desc = "ATxmega16C4"; + signature = 0x1e 0x95 0x44; +; + +#------------------------------------------------------------ +# ATxmega16D4 +#------------------------------------------------------------ + +part parent "x16a4u" + id = "x16d4"; + desc = "ATxmega16D4"; + signature = 0x1e 0x94 0x42; +; + +#------------------------------------------------------------ +# ATxmega16A4 +#------------------------------------------------------------ + +part parent "x16a4u" + id = "x16a4"; + desc = "ATxmega16A4"; + signature = 0x1e 0x94 0x41; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega32A4U +#------------------------------------------------------------ + +part parent ".xmega" + id = "x32a4u"; + desc = "ATxmega32A4U"; + signature = 0x1e 0x95 0x41; + usbpid = 0x2fe4; + + memory "eeprom" + size = 0x400; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x8000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x807000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x1000; + offset = 0x808000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x9000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x100; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega32C4 +#------------------------------------------------------------ + +part parent "x32a4u" + id = "x32c4"; + desc = "ATxmega32C4"; + signature = 0x1e 0x94 0x43; +; + +#------------------------------------------------------------ +# ATxmega32D4 +#------------------------------------------------------------ + +part parent "x32a4u" + id = "x32d4"; + desc = "ATxmega32D4"; + signature = 0x1e 0x95 0x42; +; + +#------------------------------------------------------------ +# ATxmega32A4 +#------------------------------------------------------------ + +part parent "x32a4u" + id = "x32a4"; + desc = "ATxmega32A4"; + signature = 0x1e 0x95 0x41; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega64A4U +#------------------------------------------------------------ + +part parent ".xmega" + id = "x64a4u"; + desc = "ATxmega64A4U"; + signature = 0x1e 0x96 0x46; + usbpid = 0x2fe5; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x10000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x80f000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x1000; + offset = 0x810000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x11000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x100; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega64C3 +#------------------------------------------------------------ + +part parent "x64a4u" + id = "x64c3"; + desc = "ATxmega64C3"; + signature = 0x1e 0x96 0x49; + usbpid = 0x2fd6; +; + +#------------------------------------------------------------ +# ATxmega64D3 +#------------------------------------------------------------ + +part parent "x64a4u" + id = "x64d3"; + desc = "ATxmega64D3"; + signature = 0x1e 0x96 0x4a; +; + +#------------------------------------------------------------ +# ATxmega64D4 +#------------------------------------------------------------ + +part parent "x64a4u" + id = "x64d4"; + desc = "ATxmega64D4"; + signature = 0x1e 0x96 0x47; +; + +#------------------------------------------------------------ +# ATxmega64A1 +#------------------------------------------------------------ + +part parent "x64a4u" + id = "x64a1"; + desc = "ATxmega64A1"; + signature = 0x1e 0x96 0x4e; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega64A1U +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64a1u"; + desc = "ATxmega64A1U"; + signature = 0x1e 0x96 0x4e; + usbpid = 0x2fe8; +; + +#------------------------------------------------------------ +# ATxmega64A3 +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64a3"; + desc = "ATxmega64A3"; + signature = 0x1e 0x96 0x42; +; + +#------------------------------------------------------------ +# ATxmega64A3U +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64a3u"; + desc = "ATxmega64A3U"; + signature = 0x1e 0x96 0x42; + usbpid = 0x2fe5; +; + +#------------------------------------------------------------ +# ATxmega64A4 +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64a4"; + desc = "ATxmega64A4"; + signature = 0x1e 0x96 0x46; +; + +#------------------------------------------------------------ +# ATxmega64B1 +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64b1"; + desc = "ATxmega64B1"; + signature = 0x1e 0x96 0x52; + usbpid = 0x2fe1; +; + +#------------------------------------------------------------ +# ATxmega64B3 +#------------------------------------------------------------ + +part parent "x64a1" + id = "x64b3"; + desc = "ATxmega64B3"; + signature = 0x1e 0x96 0x51; + usbpid = 0x2fdf; +; + +#------------------------------------------------------------ +# ATxmega128C3 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x128c3"; + desc = "ATxmega128C3"; + signature = 0x1e 0x97 0x52; + usbpid = 0x2fd7; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x20000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "apptable" + size = 0x2000; + offset = 0x81e000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x820000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "flash" + size = 0x22000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; +# needed for wiring aka stk500v2 protocol + paged = yes; # this appears to affect how it is read/written with stk500v2 + num_pages = 272; + blocksize = 0x200; + mode = 0x41; + delay = 10; + + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x200; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega128D3 +#------------------------------------------------------------ + +part parent "x128c3" + id = "x128d3"; + desc = "ATxmega128D3"; + signature = 0x1e 0x97 0x48; +; + +#------------------------------------------------------------ +# ATxmega128D4 +#------------------------------------------------------------ + +part parent "x128c3" + id = "x128d4"; + desc = "ATxmega128D4"; + signature = 0x1e 0x97 0x47; +; + +#------------------------------------------------------------ +# ATxmega128A1 +#------------------------------------------------------------ + +part parent "x128c3" + id = "x128a1"; + desc = "ATxmega128A1"; + signature = 0x1e 0x97 0x4c; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega128A1 revision D +#------------------------------------------------------------ + +part parent "x128a1" + id = "x128a1d"; + desc = "ATxmega128A1revD"; + signature = 0x1e 0x97 0x41; +; + +#------------------------------------------------------------ +# ATxmega128A1U +#------------------------------------------------------------ + +part parent "x128a1" + id = "x128a1u"; + desc = "ATxmega128A1U"; + signature = 0x1e 0x97 0x4c; + usbpid = 0x2fed; +; + +#------------------------------------------------------------ +# ATxmega128A3 +#------------------------------------------------------------ + +part parent "x128a1" + id = "x128a3"; + desc = "ATxmega128A3"; + signature = 0x1e 0x97 0x42; +; + +#------------------------------------------------------------ +# ATxmega128A3U +#------------------------------------------------------------ + +part parent "x128a1" + id = "x128a3u"; + desc = "ATxmega128A3U"; + signature = 0x1e 0x97 0x42; + usbpid = 0x2fe6; +; + +#------------------------------------------------------------ +# ATxmega128A4 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x128a4"; + desc = "ATxmega128A4"; + signature = 0x1e 0x97 0x46; + has_jtag = yes; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x20000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x81f000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x820000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "flash" + size = 0x22000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; +# needed for wiring aka stk500v2 protocol + paged = yes; # this appears to affect how it is read/written with stk500v2 + num_pages = 272; + blocksize = 0x200; + mode = 0x41; + delay = 10; + + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x200; + readsize = 0x100; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega128A4U +#------------------------------------------------------------ + +part parent ".xmega" + id = "x128a4u"; + desc = "ATxmega128A4U"; + signature = 0x1e 0x97 0x46; + usbpid = 0x2fde; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x20000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x81f000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x22000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x100; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega128B1 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x128b1"; + desc = "ATxmega128B1"; + signature = 0x1e 0x97 0x4d; + usbpid = 0x2fea; + has_jtag = yes; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x20000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "apptable" + size = 0x2000; + offset = 0x81e000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x820000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "flash" + size = 0x22000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; + + memory "usersig" + size = 0x100; + offset = 0x8e0400; + page_size = 0x100; + readsize = 0x100; + ; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega128B3 +#------------------------------------------------------------ + +part parent "x128b1" + id = "x128b3"; + desc = "ATxmega128B3"; + signature = 0x1e 0x97 0x4b; + usbpid = 0x2fe0; +; + +#------------------------------------------------------------ +# ATxmega192C3 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x192c3"; + desc = "ATxmega192C3"; + signature = 0x1e 0x97 0x51; + # usbpid = 0x2f??; + + memory "eeprom" + size = 0x800; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x30000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "apptable" + size = 0x2000; + offset = 0x82e000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x830000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "flash" + size = 0x32000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; +# needed for wiring aka stk500v2 protocol + paged = yes; # this appears to affect how it is read/written with stk500v2 + num_pages = 400; + blocksize = 0x200; + mode = 0x41; + delay = 10; + + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x200; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega192D3 +#------------------------------------------------------------ + +part parent "x192c3" + id = "x192d3"; + desc = "ATxmega192D3"; + signature = 0x1e 0x97 0x49; +; + +#------------------------------------------------------------ +# ATxmega192A1 +#------------------------------------------------------------ + +part parent "x192c3" + id = "x192a1"; + desc = "ATxmega192A1"; + signature = 0x1e 0x97 0x4e; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega192A3 +#------------------------------------------------------------ + +part parent "x192a1" + id = "x192a3"; + desc = "ATxmega192A3"; + signature = 0x1e 0x97 0x44; +; + +#------------------------------------------------------------ +# ATxmega192A3U +#------------------------------------------------------------ + +part parent "x192a1" + id = "x192a3u"; + desc = "ATxmega192A3U"; + signature = 0x1e 0x97 0x44; + usbpid = 0x2fe7; +; + +#------------------------------------------------------------ +# ATxmega256C3 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x256c3"; + desc = "ATxmega256C3"; + signature = 0x1e 0x98 0x46; + usbpid = 0x2fda; + + memory "eeprom" + size = 0x1000; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x40000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "apptable" + size = 0x2000; + offset = 0x83e000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x840000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "flash" + size = 0x42000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; +# needed for wiring aka stk500v2 protocol + paged = yes; # this appears to affect how it is read/written with stk500v2 + num_pages = 528; + blocksize = 0x200; + mode = 0x41; + delay = 10; + + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x200; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega256D3 +#------------------------------------------------------------ + +part parent "x256c3" + id = "x256d3"; + desc = "ATxmega256D3"; + signature = 0x1e 0x98 0x44; +; + +#------------------------------------------------------------ +# ATxmega256A1 +#------------------------------------------------------------ + +part parent "x256c3" + id = "x256a1"; + desc = "ATxmega256A1"; + signature = 0x1e 0x98 0x46; + has_jtag = yes; + + memory "fuse0" + size = 1; + offset = 0x8f0020; + ; +; + +#------------------------------------------------------------ +# ATxmega256A3 +#------------------------------------------------------------ + +part parent "x256a1" + id = "x256a3"; + desc = "ATxmega256A3"; + signature = 0x1e 0x98 0x42; +; + +#------------------------------------------------------------ +# ATxmega256A3U +#------------------------------------------------------------ + +part parent "x256a1" + id = "x256a3u"; + desc = "ATxmega256A3U"; + signature = 0x1e 0x98 0x42; + usbpid = 0x2fec; +; + +#------------------------------------------------------------ +# ATxmega256A3B +#------------------------------------------------------------ + +part parent "x256a1" + id = "x256a3b"; + desc = "ATxmega256A3B"; + signature = 0x1e 0x98 0x43; +; + +#------------------------------------------------------------ +# ATxmega256A3BU +#------------------------------------------------------------ + +part parent "x256a1" + id = "x256a3bu"; + desc = "ATxmega256A3BU"; + signature = 0x1e 0x98 0x43; + usbpid = 0x2fe2; +; + +#------------------------------------------------------------ +# ATxmega384C3 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x384c3"; + desc = "ATxmega384C3"; + signature = 0x1e 0x98 0x45; + usbpid = 0x2fdb; + + memory "eeprom" + size = 0x1000; + offset = 0x8c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x60000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "apptable" + size = 0x2000; + offset = 0x85e000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "boot" + size = 0x2000; + offset = 0x860000; + page_size = 0x200; + readsize = 0x100; + ; + + memory "flash" + size = 0x62000; + offset = 0x800000; + page_size = 0x200; + readsize = 0x100; +# needed for wiring aka stk500v2 protocol + paged = yes; # this appears to affect how it is read/written with stk500v2 + num_pages = 784; + blocksize = 0x200; + mode = 0x41; + delay = 10; + + read_lo = " 0 0 1 0 0 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " x x x x x x x x", + " x a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + "a15 a14 a13 a12 a11 a10 a9 a8", + " a7 x x x x x x x", + " x x x x x x x x"; + + load_ext_addr = " 0 1 0 0 1 1 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 0 a16", + " 0 0 0 0 0 0 0 0"; + ; + + memory "usersig" + size = 0x200; + offset = 0x8e0400; + page_size = 0x200; + readsize = 0x100; + ; +; + +#------------------------------------------------------------ +# ATxmega384D3 +#------------------------------------------------------------ + +part parent "x384c3" + id = "x384d3"; + desc = "ATxmega384D3"; + signature = 0x1e 0x98 0x47; +; + +#------------------------------------------------------------ +# ATxmega8E5 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x8e5"; + desc = "ATxmega8E5"; + signature = 0x1e 0x93 0x41; + + memory "eeprom" + size = 0x0200; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x2000; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "apptable" + size = 0x800; + offset = 0x00801800; + page_size = 0x80; + readsize = 0x100; + ; + + memory "boot" + size = 0x800; + offset = 0x00802000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "flash" + size = 0x2800; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "usersig" + size = 0x80; + offset = 0x8e0400; + page_size = 0x80; + readsize = 0x100; + ; + + memory "fuse6" + size = 1; + offset = 0x8f0026; + ; + +; + +#------------------------------------------------------------ +# ATxmega16E5 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x16e5"; + desc = "ATxmega16E5"; + signature = 0x1e 0x94 0x45; + + memory "eeprom" + size = 0x0200; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x4000; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x00803000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "boot" + size = 0x1000; + offset = 0x00804000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "flash" + size = 0x5000; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "usersig" + size = 0x80; + offset = 0x8e0400; + page_size = 0x80; + readsize = 0x100; + ; + + memory "fuse6" + size = 1; + offset = 0x8f0026; + ; + +; + +#------------------------------------------------------------ +# ATxmega32E5 +#------------------------------------------------------------ + +part parent ".xmega" + id = "x32e5"; + desc = "ATxmega32E5"; + signature = 0x1e 0x95 0x4c; + + memory "eeprom" + size = 0x0400; + offset = 0x08c0000; + page_size = 0x20; + readsize = 0x100; + ; + + memory "application" + size = 0x8000; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "apptable" + size = 0x1000; + offset = 0x00807000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "boot" + size = 0x1000; + offset = 0x00808000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "flash" + size = 0x9000; + offset = 0x0800000; + page_size = 0x80; + readsize = 0x100; + ; + + memory "usersig" + size = 0x80; + offset = 0x8e0400; + page_size = 0x80; + readsize = 0x100; + ; + + memory "fuse6" + size = 1; + offset = 0x8f0026; + ; + +; + +#------------------------------------------------------------ +# AVR32UC3A0512 +#------------------------------------------------------------ + +part + id = "uc3a0512"; + desc = "AT32UC3A0512"; + signature = 0xED 0xC0 0x3F; + has_jtag = yes; + is_avr32 = yes; + + memory "flash" + paged = yes; + page_size = 512; # bytes + readsize = 512; # bytes + num_pages = 1024; # could be set dynamicly + size = 0x00080000; # could be set dynamicly + offset = 0x80000000; + ; +; + +part parent "uc3a0512" + id = "ucr2"; + desc = "deprecated, use 'uc3a0512'"; +; + +#------------------------------------------------------------ +# ATtiny1634. +#------------------------------------------------------------ + +part + id = "t1634"; + desc = "ATtiny1634"; + has_debugwire = yes; + flash_instr = 0xB6, 0x01, 0x11; + eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00, + 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF, + 0x99, 0xF9, 0xBB, 0xAF; + stk500_devcode = 0x86; + # avr910_devcode = 0x; + signature = 0x1e 0x94 0x12; + pagel = 0xB3; + bs2 = 0xB1; + reset = io; + chip_erase_delay = 9000; + pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1", + "x x x x x x x x x x x x x x x x"; + + chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x", + "x x x x x x x x x x x x x x x x"; + + timeout = 200; + stabdelay = 100; + cmdexedelay = 25; + synchloops = 32; + bytedelay = 0; + pollindex = 3; + pollvalue = 0x53; + predelay = 1; + postdelay = 1; + pollmethod = 1; + + pp_controlstack = + 0x0E, 0x1E, 0x0E, 0x1E, 0x2E, 0x3E, 0x2E, 0x3E, + 0x4E, 0x5E, 0x4E, 0x5E, 0x6E, 0x7E, 0x6E, 0x7E, + 0x26, 0x36, 0x66, 0x76, 0x2A, 0x3A, 0x6A, 0x7A, + 0x2E, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + hventerstabdelay = 100; + progmodedelay = 0; + latchcycles = 0; + togglevtg = 1; + poweroffdelay = 15; + resetdelayms = 1; + resetdelayus = 0; + hvleavestabdelay = 15; + resetdelay = 15; + chiperasepulsewidth = 0; + chiperasepolltimeout = 10; + programfusepulsewidth = 0; + programfusepolltimeout = 5; + programlockpulsewidth = 0; + programlockpolltimeout = 5; + + memory "eeprom" + paged = no; + page_size = 4; + size = 256; + min_write_delay = 3600; + max_write_delay = 3600; + readback_p1 = 0xff; + readback_p2 = 0xff; + read = " 1 0 1 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + write = " 1 1 0 0 0 0 0 0", + " 0 0 0 x x x x a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_lo = " 1 1 0 0 0 0 0 1", + " 0 0 0 0 0 0 0 0", + " 0 0 0 0 0 0 a1 a0", + " i i i i i i i i"; + + writepage = " 1 1 0 0 0 0 1 0", + " 0 0 x x x x x a8", + " a7 a6 a5 a4 a3 a2 0 0", + " x x x x x x x x"; + + mode = 0x41; + delay = 5; + blocksize = 4; + readsize = 256; + ; + + memory "flash" + paged = yes; + size = 16384; + page_size = 32; + num_pages = 512; + min_write_delay = 4500; + max_write_delay = 4500; + readback_p1 = 0xff; + readback_p2 = 0xff; + read_lo = " 0 0 1 0 0 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + read_hi = " 0 0 1 0 1 0 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 a3 a2 a1 a0", + " o o o o o o o o"; + + loadpage_lo = " 0 1 0 0 0 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + loadpage_hi = " 0 1 0 0 1 0 0 0", + " 0 0 0 x x x x x", + " x x a5 a4 a3 a2 a1 a0", + " i i i i i i i i"; + + writepage = " 0 1 0 0 1 1 0 0", + " 0 0 0 a12 a11 a10 a9 a8", + " a7 a6 x x x x x x", + " x x x x x x x x"; + + mode = 0x41; + delay = 6; + blocksize = 128; + readsize = 256; + + ; + + memory "lfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "hfuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0", + "x x x x x x x x i i i i i i i i"; + ; + + memory "efuse" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", + "x x x x x x x x o o o o o o o o"; + + write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", + "x x x x x x x x x x x i i i i i"; + ; + + memory "lock" + size = 1; + min_write_delay = 4500; + max_write_delay = 4500; + read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0", + "x x x x x x x x x x x x x x o o"; + + write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", + "x x x x x x x x 1 1 1 1 1 1 i i"; + ; + + memory "calibration" + size = 1; + read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", + "0 0 0 0 0 0 0 0 o o o o o o o o"; + ; + + memory "signature" + size = 3; + read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x", + "x x x x x x a1 a0 o o o o o o o o"; + ; +; + +#------------------------------------------------------------ +# Common values for reduced core tinys (4/5/9/10/20/40) +#------------------------------------------------------------ + +part + id = ".reduced_core_tiny"; + desc = "Common values for reduced core tinys"; + has_tpi = yes; + + memory "signature" + size = 3; + offset = 0x3fc0; + page_size = 16; + ; + + memory "fuse" + size = 1; + offset = 0x3f40; + page_size = 16; + blocksize = 4; + ; + + memory "calibration" + size = 1; + offset = 0x3f80; + page_size = 16; + ; + + memory "lockbits" + size = 1; + offset = 0x3f00; + page_size = 16; + ; +; + +#------------------------------------------------------------ +# ATtiny4 +#------------------------------------------------------------ + +part parent ".reduced_core_tiny" + id = "t4"; + desc = "ATtiny4"; + signature = 0x1e 0x8f 0x0a; + + memory "flash" + size = 512; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; +; + +#------------------------------------------------------------ +# ATtiny5 +#------------------------------------------------------------ + +part parent "t4" + id = "t5"; + desc = "ATtiny5"; + signature = 0x1e 0x8f 0x09; +; + +#------------------------------------------------------------ +# ATtiny9 +#------------------------------------------------------------ + +part parent ".reduced_core_tiny" + id = "t9"; + desc = "ATtiny9"; + signature = 0x1e 0x90 0x08; + + memory "flash" + size = 1024; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; +; + +#------------------------------------------------------------ +# ATtiny10 +#------------------------------------------------------------ + +part parent "t9" + id = "t10"; + desc = "ATtiny10"; + signature = 0x1e 0x90 0x03; +; + +#------------------------------------------------------------ +# ATtiny20 +#------------------------------------------------------------ + +part parent ".reduced_core_tiny" + id = "t20"; + desc = "ATtiny20"; + signature = 0x1e 0x91 0x0F; + + memory "flash" + size = 2048; + offset = 0x4000; + page_size = 16; + blocksize = 128; + ; +; + +#------------------------------------------------------------ +# ATtiny40 +#------------------------------------------------------------ + +part parent ".reduced_core_tiny" + id = "t40"; + desc = "ATtiny40"; + signature = 0x1e 0x92 0x0E; + + memory "flash" + size = 4096; + offset = 0x4000; + page_size = 64; + blocksize = 128; + ; +; + +#------------------------------------------------------------ +# ATmega406 +#------------------------------------------------------------ + +part + id = "m406"; + desc = "ATMEGA406"; + has_jtag = yes; + signature = 0x1e 0x95 0x07; + + # STK500 parameters (parallel programming IO lines) + pagel = 0xa7; + bs2 = 0xa0; + serial = no; + parallel = yes; + + # STK500v2 HV programming parameters, from XML + pp_controlstack = 0x0e, 0x1e, 0x0f, 0x1f, 0x2e, 0x3e, 0x2f, 0x3f, + 0x4e, 0x5e, 0x4f, 0x5f, 0x6e, 0x7e, 0x6f, 0x7f, + 0x66, 0x76, 0x67, 0x77, 0x6a, 0x7a, 0x6b, 0x7b, + 0xbe, 0xfd, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00; + + # JTAG ICE mkII parameters, also from XML files + allowfullpagebitstream = no; + enablepageprogramming = yes; + idr = 0x51; + rampz = 0x00; + spmcr = 0x57; + eecr = 0x3f; + + memory "eeprom" + paged = no; + size = 512; + page_size = 4; + blocksize = 4; + readsize = 4; + num_pages = 128; + ; + + memory "flash" + paged = yes; + size = 40960; + page_size = 128; + blocksize = 128; + readsize = 128; + num_pages = 320; + ; + + memory "hfuse" + size = 1; + ; + + memory "lfuse" + size = 1; + ; + + memory "lockbits" + size = 1; + ; + + memory "signature" + size = 3; + ; +; + + diff --git a/BootLoaders/Boards/orangerx/boards.txt b/BootLoaders/Boards/orangerx/boards.txt new file mode 100644 index 0000000..0980eb8 --- /dev/null +++ b/BootLoaders/Boards/orangerx/boards.txt @@ -0,0 +1,19 @@ +# 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 +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 new file mode 100644 index 0000000..0ee9cd8 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Arduino.h @@ -0,0 +1,450 @@ +/* + 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 new file mode 100644 index 0000000..e07a17d --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/CDC.cpp @@ -0,0 +1,541 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// ____ ____ ____ // +// / ___|| _ \ / ___| ___ _ __ _ __ // +// | | | | | || | / __|| '_ \ | '_ \ // +// | |___ | |_| || |___ _| (__ | |_) || |_) | // +// \____||____/ \____|(_)\___|| .__/ | .__/ // +// |_| |_| // +// // +////////////////////////////////////////////////////////////////////////////// + +/* 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 new file mode 100644 index 0000000..b8e5d93 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Client.h @@ -0,0 +1,45 @@ +/* + 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 new file mode 100644 index 0000000..53fd4b5 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/HID.cpp @@ -0,0 +1,593 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// _ _ ___ ____ // +// | | | ||_ _|| _ \ ___ _ __ _ __ // +// | |_| | | | | | | | / __|| '_ \ | '_ \ // +// | _ | | | | |_| |_| (__ | |_) || |_) | // +// |_| |_||___||____/(_)\___|| .__/ | .__/ // +// |_| |_| // +// // +////////////////////////////////////////////////////////////////////////////// + +/* 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 new file mode 100644 index 0000000..de5cfb5 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.cpp @@ -0,0 +1,1869 @@ +/* + 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 new file mode 100644 index 0000000..fab2201 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/HardwareSerial.h @@ -0,0 +1,143 @@ +/* + 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 new file mode 100644 index 0000000..3532172 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.cpp @@ -0,0 +1,74 @@ +/* + 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 new file mode 100644 index 0000000..cd60afd --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/IPAddress.h @@ -0,0 +1,82 @@ +/* + 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 new file mode 100644 index 0000000..c7d52d1 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Platform.h @@ -0,0 +1,27 @@ + +#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 new file mode 100644 index 0000000..ca78e34 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Print.cpp @@ -0,0 +1,381 @@ +/* + 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 new file mode 100644 index 0000000..b49ee14 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Print.h @@ -0,0 +1,97 @@ +/* + 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 new file mode 100644 index 0000000..d03c9af --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Printable.h @@ -0,0 +1,40 @@ +/* + 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 new file mode 100644 index 0000000..77c415c --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Server.h @@ -0,0 +1,28 @@ +/* + 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 new file mode 100644 index 0000000..8316a92 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Stream.cpp @@ -0,0 +1,362 @@ +/* + 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 new file mode 100644 index 0000000..007b4bc --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Stream.h @@ -0,0 +1,96 @@ +/* + 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 new file mode 100644 index 0000000..198335a --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Tone.cpp @@ -0,0 +1,960 @@ +/* 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 new file mode 100644 index 0000000..e7a17d4 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/USBAPI.h @@ -0,0 +1,275 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// _ _ ____ ____ _ _ _ // +// | | | |/ ___| | __ ) / \ _ __ (_) | |__ // +// | | | |\___ \ | _ \ / _ \ | '_ \ | | | '_ \ // +// | |_| | ___) || |_) |/ ___ \ | |_) || | _ | | | | // +// \___/ |____/ |____//_/ \_\| .__/ |_|(_)|_| |_| // +// |_| // +// // +////////////////////////////////////////////////////////////////////////////// + +#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 new file mode 100644 index 0000000..31d18e6 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/USBCore.cpp @@ -0,0 +1,3745 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// _ _ ____ ____ ____ // +// | | | |/ ___| | __ ) / ___| ___ _ __ ___ ___ _ __ _ __ // +// | | | |\___ \ | _ \ | | / _ \ | '__|/ _ \ / __|| '_ \ | '_ \ // +// | |_| | ___) || |_) || |___| (_) || | | __/ _| (__ | |_) || |_) | // +// \___/ |____/ |____/ \____|\___/ |_| \___|(_)\___|| .__/ | .__/ // +// |_| |_| // +// // +////////////////////////////////////////////////////////////////////////////// + +/* 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 new file mode 100644 index 0000000..3223618 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/USBCore.h @@ -0,0 +1,442 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// _ _ ____ ____ ____ _ // +// | | | |/ ___| | __ ) / ___| ___ _ __ ___ | |__ // +// | | | |\___ \ | _ \ | | / _ \ | '__|/ _ \ | '_ \ // +// | |_| | ___) || |_) || |___| (_) || | | __/ _ | | | | // +// \___/ |____/ |____/ \____|\___/ |_| \___|(_)|_| |_| // +// // +// // +////////////////////////////////////////////////////////////////////////////// + +// 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 new file mode 100644 index 0000000..d403833 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/USBDesc.h @@ -0,0 +1,83 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// _ _ ____ ____ ____ _ // +// | | | |/ ___| | __ ) | _ \ ___ ___ ___ | |__ // +// | | | |\___ \ | _ \ | | | | / _ \/ __| / __| | '_ \ // +// | |_| | ___) || |_) || |_| || __/\__ \| (__ _ | | | | // +// \___/ |____/ |____/ |____/ \___||___/ \___|(_)|_| |_| // +// // +// // +////////////////////////////////////////////////////////////////////////////// + +/* 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 new file mode 100644 index 0000000..dfa425a --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/Udp.h @@ -0,0 +1,88 @@ +/* + * 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 new file mode 100644 index 0000000..79733b5 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/WCharacter.h @@ -0,0 +1,168 @@ +/* + 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 new file mode 100644 index 0000000..d30043a --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/WInterrupts.c @@ -0,0 +1,808 @@ +/* -*- 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/Multiprotocol/WMath.cpp.orangetx b/BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp similarity index 89% rename from Multiprotocol/WMath.cpp.orangetx rename to BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp index 42731e4..2120c4c 100644 --- a/Multiprotocol/WMath.cpp.orangetx +++ b/BootLoaders/Boards/orangerx/cores/xmega/WMath.cpp @@ -42,14 +42,14 @@ long random(long howbig) return random() % howbig; } -//long random(long howsmall, long howbig) -//{ -// if (howsmall >= howbig) { -// return howsmall; -// } -// long diff = howbig - howsmall; -// return random(diff) + howsmall; -//} +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) { diff --git a/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp b/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp new file mode 100644 index 0000000..ed880ce --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/WString.cpp @@ -0,0 +1,744 @@ +/* + 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 new file mode 100644 index 0000000..7402430 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/WString.h @@ -0,0 +1,224 @@ +/* + 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 new file mode 100644 index 0000000..4cd765f --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/malloc.c @@ -0,0 +1,267 @@ +/* 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 new file mode 100644 index 0000000..4ba546c --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/realloc.c @@ -0,0 +1,150 @@ +/* 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 new file mode 100644 index 0000000..8e0f448 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/sectionname.h @@ -0,0 +1,49 @@ +/* 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 new file mode 100644 index 0000000..acc72c5 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/avr-libc/stdlib_private.h @@ -0,0 +1,58 @@ +/* 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 new file mode 100644 index 0000000..aec4c73 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/binary.h @@ -0,0 +1,534 @@ +/* + 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 new file mode 100644 index 0000000..aa9092e --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/main.cpp @@ -0,0 +1,68 @@ +/* + 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 new file mode 100644 index 0000000..51ea5a3 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/new.cpp @@ -0,0 +1,28 @@ +#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 new file mode 100644 index 0000000..8c93ceb --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/new.h @@ -0,0 +1,24 @@ +/* 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 new file mode 100644 index 0000000..b62afdb --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring.c @@ -0,0 +1,1088 @@ +/* + 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 new file mode 100644 index 0000000..f1883bd --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring_analog.c @@ -0,0 +1,859 @@ +/* + 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 new file mode 100644 index 0000000..0c3598c --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring_digital.c @@ -0,0 +1,428 @@ +/* + 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 new file mode 100644 index 0000000..3218324 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring_private.h @@ -0,0 +1,125 @@ +/* + 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 new file mode 100644 index 0000000..ee16fdc --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring_pulse.c @@ -0,0 +1,69 @@ +/* + 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 new file mode 100644 index 0000000..e335755 --- /dev/null +++ b/BootLoaders/Boards/orangerx/cores/xmega/wiring_shift.c @@ -0,0 +1,55 @@ +/* + 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 new file mode 100644 index 0000000..28b3377 --- /dev/null +++ b/BootLoaders/Boards/orangerx/platform.local.txt @@ -0,0 +1,25 @@ +## 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 new file mode 100644 index 0000000..da6dcb2 --- /dev/null +++ b/BootLoaders/Boards/orangerx/platform.txt @@ -0,0 +1,124 @@ +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 new file mode 100755 index 0000000..184015b --- /dev/null +++ b/BootLoaders/Boards/orangerx/tools/linux/do_version @@ -0,0 +1,47 @@ +#!/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 new file mode 100755 index 0000000..184015b --- /dev/null +++ b/BootLoaders/Boards/orangerx/tools/linux64/do_version @@ -0,0 +1,47 @@ +#!/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 new file mode 100755 index 0000000..184015b --- /dev/null +++ b/BootLoaders/Boards/orangerx/tools/macosx/do_version @@ -0,0 +1,47 @@ +#!/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 new file mode 100644 index 0000000..af69adf --- /dev/null +++ b/BootLoaders/Boards/orangerx/tools/win/do_version.bat @@ -0,0 +1,54 @@ +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +SET BUILD_PATH=%1 +SET PROJECT_NAME=%2 +SET SKETCH_PATH=%3 +SET MULTI_BOARD=%4 +SET EXPORT_FLAG=%5 + +REM ECHO Multi board: %MULTI_BOARD% + +SET MULTI_TYPE=orx + +IF EXIST "%1\sketch\Multiprotocol.h" ( + REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h" + FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\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= +) + +REM 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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_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" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL + ) + + IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL + ) + + IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" ( + DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL + ) + IF EXIST "%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 new file mode 100644 index 0000000..81ff9f8 --- /dev/null +++ b/BootLoaders/Boards/orangerx/variants/xmega32d4/pins_arduino.h @@ -0,0 +1,702 @@ +/* + 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/platform.txt b/BootLoaders/Boards/stm32/platform.txt index 230f0a5..75cf2c6 100644 --- a/BootLoaders/Boards/stm32/platform.txt +++ b/BootLoaders/Boards/stm32/platform.txt @@ -103,7 +103,20 @@ recipe.size.regex.data=^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* ## Save Compiled Binary recipe.output.tmp_file={build.project_name}.bin #recipe.output.save_file={build.project_name}.{build.variant}.bin -recipe.output.save_file=multifw.bin +recipe.output.save_file=multi-stm.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 # Uploader tools # ------------------- diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-prefix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-suffix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/linux/dfu-util/dfu-util old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux/do_version b/BootLoaders/Boards/stm32/tools/linux/do_version new file mode 100755 index 0000000..b469a5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=stm + +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/stm32/tools/linux/maple_upload b/BootLoaders/Boards/stm32/tools/linux/maple_upload old mode 100644 new mode 100755 index 50d2ae5..8afaa65 --- a/BootLoaders/Boards/stm32/tools/linux/maple_upload +++ b/BootLoaders/Boards/stm32/tools/linux/maple_upload @@ -2,23 +2,32 @@ #set -e - - if [ $# -lt 4 ]; then echo "Usage: $0 $# " >&2 exit 1 fi + dummy_port="$1"; altID="$2"; usbID="$3"; binfile="$4"; dummy_port_fullpath="/dev/$1" + if [ $# -eq 5 ]; then dfuse_addr="--dfuse-address $5" else dfuse_addr="" fi - # Get the directory where the script is running. DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +# Get the right upload-reset tool +uname -m | grep "x86_64" 2>&1 1>/dev/null +if [ $? -eq 0 ]; then + # Do 64-bit stuff + RESET_UTIL=${DIR}/../linux64/upload-reset +else + # Do 32-bit stuff + RESET_UTIL=${DIR}/upload-reset +fi + # ----------------- IMPORTANT ----------------- # The 2nd parameter to upload-reset is the delay after resetting before it exits # This value is in milliseonds @@ -26,7 +35,7 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) # 750ms to 1500ms seems to work on my Mac -"${DIR}/upload-reset" ${dummy_port_fullpath} 750 +"${RESET_UTIL}" ${dummy_port_fullpath} 750 #DFU_UTIL=$(dirname $0)/dfu-util/dfu-util diff --git a/BootLoaders/Boards/stm32/tools/linux/serial_upload b/BootLoaders/Boards/stm32/tools/linux/serial_upload old mode 100644 new mode 100755 index 755444a..c540e5d --- a/BootLoaders/Boards/stm32/tools/linux/serial_upload +++ b/BootLoaders/Boards/stm32/tools/linux/serial_upload @@ -1,2 +1,13 @@ #!/bin/bash -$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" +port=$1 +addr=$2 +file=$3 + +uname -m | grep "x86_64" 2>&1 1>/dev/null +if [ $? -eq 0 ]; then + # Do 64-bit stuff + $(dirname $0)/../linux64/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port" +else + # Do 32-bit stuff + $(dirname $0)/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port" +fi diff --git a/BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/linux/stm32flash/stm32flash old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux/tx_upload b/BootLoaders/Boards/stm32/tools/linux/tx_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux/upload-reset b/BootLoaders/Boards/stm32/tools/linux/upload-reset old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-prefix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-suffix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/linux64/dfu-util/dfu-util old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/do_version b/BootLoaders/Boards/stm32/tools/linux64/do_version new file mode 100755 index 0000000..b469a5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/linux64/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=stm + +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/stm32/tools/linux64/maple_upload b/BootLoaders/Boards/stm32/tools/linux64/maple_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/serial_upload b/BootLoaders/Boards/stm32/tools/linux64/serial_upload old mode 100644 new mode 100755 index 755444a..c540e5d --- a/BootLoaders/Boards/stm32/tools/linux64/serial_upload +++ b/BootLoaders/Boards/stm32/tools/linux64/serial_upload @@ -1,2 +1,13 @@ #!/bin/bash -$(dirname $0)/stm32flash/stm32flash -g 0x8000000 -b 115200 -w "$4" /dev/"$1" +port=$1 +addr=$2 +file=$3 + +uname -m | grep "x86_64" 2>&1 1>/dev/null +if [ $? -eq 0 ]; then + # Do 64-bit stuff + $(dirname $0)/../linux64/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port" +else + # Do 32-bit stuff + $(dirname $0)/stm32flash/stm32flash -g $addr -b 57600 -w "$file" /dev/"$port" +fi diff --git a/BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/linux64/stm32flash/stm32flash old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/tx_upload b/BootLoaders/Boards/stm32/tools/linux64/tx_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/linux64/upload-reset b/BootLoaders/Boards/stm32/tools/linux64/upload-reset old mode 100644 new mode 100755 index 26985b8..77563d6 Binary files a/BootLoaders/Boards/stm32/tools/linux64/upload-reset and b/BootLoaders/Boards/stm32/tools/linux64/upload-reset differ diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-prefix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-suffix old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util b/BootLoaders/Boards/stm32/tools/macosx/dfu-util/dfu-util old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/do_version b/BootLoaders/Boards/stm32/tools/macosx/do_version new file mode 100755 index 0000000..b469a5c --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/macosx/do_version @@ -0,0 +1,47 @@ +#!/bin/bash + +BUILD_PATH=$1 +PROJECT_NAME=$2 +SKETCH_PATH=$3 +MULTI_BOARD=$4 +EXPORT_FLAG=$5 + +MULTI_TYPE=stm + +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/stm32/tools/macosx/maple_upload b/BootLoaders/Boards/stm32/tools/macosx/maple_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/serial_upload b/BootLoaders/Boards/stm32/tools/macosx/serial_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash b/BootLoaders/Boards/stm32/tools/macosx/stm32flash/stm32flash old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/tx_upload b/BootLoaders/Boards/stm32/tools/macosx/tx_upload old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/macosx/upload-reset b/BootLoaders/Boards/stm32/tools/macosx/upload-reset old mode 100644 new mode 100755 diff --git a/BootLoaders/Boards/stm32/tools/win/do_version.bat b/BootLoaders/Boards/stm32/tools/win/do_version.bat new file mode 100644 index 0000000..cf6b92f --- /dev/null +++ b/BootLoaders/Boards/stm32/tools/win/do_version.bat @@ -0,0 +1,54 @@ +@ECHO OFF +SETLOCAL EnableDelayedExpansion + +SET BUILD_PATH=%1 +SET PROJECT_NAME=%2 +SET SKETCH_PATH=%3 +SET MULTI_BOARD=%4 +SET EXPORT_FLAG=%5 + +REM ECHO Multi board: %MULTI_BOARD% + +SET MULTI_TYPE=stm + +IF EXIST "%1\sketch\Multiprotocol.h" ( + REM ECHO Getting Multi-MODULE firmware version from "%1\sketch\Multiprotocol.h" + FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i + FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\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= +) + +REM 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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_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" ( + REM ECHO COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_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" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.hex" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.hex" /Y >NUL + ) + + IF EXIST "%BUILD_PATH%\%PROJECT_NAME%.bin" ( + COPY "%BUILD_PATH%\%PROJECT_NAME%.bin" "%SKETCH_PATH%\multi-%MULTI_TYPE%-%MULTI_VER%.bin" /Y >NUL + ) + + IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" ( + DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.bin" >NUL + ) + IF EXIST "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" ( + DEL "%SKETCH_PATH%\multi-%MULTI_TYPE%.hex" >NUL + ) +) diff --git a/BootLoaders/Boards/stm32/tools/win/get_version.bat b/BootLoaders/Boards/stm32/tools/win/get_version.bat deleted file mode 100644 index 9babfbe..0000000 --- a/BootLoaders/Boards/stm32/tools/win/get_version.bat +++ /dev/null @@ -1,9 +0,0 @@ -@ECHO OFF - -FOR /F "tokens=* usebackq skip=2" %%A in (`find "#define VERSION_MAJOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%A") do SET MAJOR_VERSION=%%i -FOR /F "tokens=* usebackq skip=2" %%B in (`find "#define VERSION_MINOR" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%B") do SET MINOR_VERSION=%%i -FOR /F "tokens=* usebackq skip=2" %%C in (`find "#define VERSION_REVISION" "%1\sketch\Multiprotocol.h"`) DO FOR /F "tokens=3" %%i in ("%%C") do SET REVISION_VERSION=%%i -FOR /F "tokens=* usebackq skip=2" %%D in (`find "#define VERSION_PATCH_LEVEL" "%1\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% -ECHO %MULTI_VER% diff --git a/BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz b/BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz new file mode 100644 index 0000000..956b360 Binary files /dev/null and b/BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz differ diff --git a/BootLoaders/package_multi_4in1_board_index.json b/BootLoaders/package_multi_4in1_board_index.json index d9e678a..710f260 100644 --- a/BootLoaders/package_multi_4in1_board_index.json +++ b/BootLoaders/package_multi_4in1_board_index.json @@ -24,6 +24,23 @@ }], "toolsDependencies": [] }, + { + "name": "Multi 4-in-1 AVR Board", + "architecture": "avr", + "version": "1.0.1", + "category": "Contributed", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/package_multi_4in1_avr_board_v1.0.1.tar.gz", + "archiveFileName": "package_multi_4in1_avr_board_v1.0.1.tar.gz", + "checksum": "SHA-256:504A5C1ABFB366917FC35A3744CC21FA30D572AAA70007D2BC69277BC1D0E2C4", + "size": "3102", + "boards": [{ + "name": "Multi 4-in-1 (Atmega328p, 3.3V, 16MHz)" + }], + "toolsDependencies": [] + }, { "name": "Multi 4-in-1 STM32 Board", "architecture": "STM32F1", @@ -44,6 +61,44 @@ "name": "arm-none-eabi-gcc", "version": "4.8.3-2014q1" }] + }, + { + "name": "Multi 4-in-1 STM32 Board", + "architecture": "STM32F1", + "version": "1.0.1", + "category": "Contributed", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz", + "archiveFileName": "package_multi_4in1_stm32_board_v1.0.1.tar.gz", + "checksum": "SHA-256:9CC271776146A6CEC8CFB5B8DAB4DB7270C6589B43BA5759D65984AB2D89EA96", + "size": "10336733", + "boards": [{ + "name": "Multi 4-in-1 (STM32F103C)" + }], + "toolsDependencies": [{ + "packager": "arduino", + "name": "arm-none-eabi-gcc", + "version": "4.8.3-2014q1" + }] + }, + { + "name": "Multi 4-in-1 OrangeRX Board", + "architecture": "orangerx", + "version": "1.0.1", + "category": "Contributed", + "help": { + "online": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module" + }, + "url": "https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/raw/master/BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz", + "archiveFileName": "package_multi_4in1_orangerx_board_v1.0.1.tar.gz", + "checksum": "SHA-256:03D095CB9F79C881375B35C8F9671306224C03CE2F02117806E55903C77FF2D5", + "size": "162457", + "boards": [{ + "name": "Multi 4-in-1 (OrangeRX)" + }], + "toolsDependencies": [] } ], "tools": [] diff --git a/BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz b/BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz new file mode 100644 index 0000000..44ed07f Binary files /dev/null and b/BootLoaders/package_multi_4in1_orangerx_board_v1.0.1.tar.gz differ diff --git a/BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz b/BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz new file mode 100644 index 0000000..0b507df Binary files /dev/null and b/BootLoaders/package_multi_4in1_stm32_board_v1.0.1.tar.gz differ diff --git a/Multiprotocol/Build_orangetx.cmd b/Multiprotocol/Build_orangetx.cmd deleted file mode 100644 index b6323bd..0000000 --- a/Multiprotocol/Build_orangetx.cmd +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -if "%AVR32_HOME%"=="" ( -echo. -echo You must install winavr to compile Multi for OrangeTX: https://sourceforge.net/projects/winavr/ -echo. -pause -exit /b -) -if exist MultiOrange.cpp.orangetx ren *.orangetx *. -if exist .dep (make clean) -md .dep -make -if exist MultiOrange.hex ( -avr-objcopy -I ihex MultiOrange.hex -O binary MultiOrange.bin -echo. -echo Compilation OK. -echo Use MultiOrange.hex or MultiOrange.bin to program your OrangeTX module. -echo. -) -pause diff --git a/Multiprotocol/Makefile.orangetx b/Multiprotocol/Makefile.orangetx deleted file mode 100644 index 00f119c..0000000 --- a/Multiprotocol/Makefile.orangetx +++ /dev/null @@ -1,624 +0,0 @@ -# Hey Emacs, this is a -*- makefile -*- -#---------------------------------------------------------------------------- -# WinAVR Makefile -# -# On command line: -# -# make all = Make software. -# -# make clean = Clean out built project files. -# -# make coff = Convert ELF to AVR COFF. -# -# make extcoff = Convert ELF to AVR Extended COFF. -# -# make program = Download the hex file to the device, using avrdude. -# Please customize the avrdude settings below first! -# -# make debug = Start either simulavr or avarice as specified for debugging, -# with avr-gdb or avr-insight as the front end for debugging. -# -# make filename.s = Just compile filename.c into the assembler code only. -# -# make filename.i = Create a preprocessed source file for use in submitting -# bug reports to the GCC project. -# -# To rebuild project do "make clean" then "make all". -#---------------------------------------------------------------------------- - - -# MCU name -MCU = atxmega32d4 - - -# Processor frequency. -# This will define a symbol, F_CPU, in all source code files equal to the -# processor frequency. You can then use this symbol in your source code to -# calculate timings. Do NOT tack on a 'UL' at the end, this will be done -# automatically to create a 32-bit value in your source code. -# Typical values are: -# F_CPU = 1000000 -# F_CPU = 1843200 -# F_CPU = 2000000 -# F_CPU = 3686400 -# F_CPU = 4000000 -# F_CPU = 7372800 -# F_CPU = 8000000 -# F_CPU = 11059200 -# F_CPU = 14745600 -# F_CPU = 16000000 -# F_CPU = 18432000 -# F_CPU = 20000000 -F_CPU = 32000000 - - -# Output format. (can be srec, ihex, binary) -FORMAT = ihex - - -# Target file name (without extension). -TARGET = MultiOrange - - -# Object files directory -# To put object files in current directory, use a dot (.), do NOT make -# this an empty or blank macro! -OBJDIR = . - - -# List C source files here. (C dependencies are automatically generated.) -SRC = - - -# List C++ source files here. (C dependencies are automatically generated.) -CPPSRC = $(TARGET).cpp -CPPSRC += Wmath.cpp -#CPPSRC += DSM2_cyrf6936.cpp - -# List Assembler source files here. -# Make them always end in a capital .S. Files ending in a lowercase .s -# will not be considered source files but generated files (assembler -# output from the compiler), and will be deleted upon "make clean"! -# Even though the DOS/Win* filesystem matches both .s and .S the same, -# it will preserve the spelling of the filenames, and gcc itself does -# care about how the name is spelled on its command-line. -ASRC = - - -# Optimization level, can be [0, 1, 2, 3, s]. -# 0 = turn off optimization. s = optimize for size. -# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) -OPT = s - - -# Debugging format. -# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. -# AVR Studio 4.10 requires dwarf-2. -# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. -#DEBUG = stabs -DEBUG = dwarf-2 - - -# List any extra directories to look for include files here. -# Each directory must be seperated by a space. -# Use forward slashes for directory separators. -# For a directory that has spaces, enclose it in quotes. -EXTRAINCDIRS = - - -# Compiler flag to set the C Standard level. -# c89 = "ANSI" C -# gnu89 = c89 plus GCC extensions -# c99 = ISO C99 standard (not yet fully implemented) -# gnu99 = c99 plus GCC extensions -CSTANDARD = -std=gnu99 - - -# Place -D or -U options here for C sources -CDEFS = -DF_CPU=$(F_CPU)UL - - -# Place -D or -U options here for ASM sources -ADEFS = -DF_CPU=$(F_CPU) - - -# Place -D or -U options here for C++ sources -CPPDEFS = -DF_CPU=$(F_CPU)UL -#CPPDEFS += -D__STDC_LIMIT_MACROS -#CPPDEFS += -D__STDC_CONSTANT_MACROS - - - -#---------------- Compiler Options C ---------------- -# -g*: generate debugging information -# -O*: optimization level -# -f...: tuning, see GCC manual and avr-libc documentation -# -Wall...: warning level -# -Wa,...: tell GCC to pass this to the assembler. -# -adhlns...: create assembler listing -CFLAGS = -g$(DEBUG) -CFLAGS += $(CDEFS) -CFLAGS += -O$(OPT) -CFLAGS += -funsigned-char -CFLAGS += -funsigned-bitfields -CFLAGS += -fpack-struct -CFLAGS += -fshort-enums -CFLAGS += -Wall -CFLAGS += -Wno-main -CFLAGS += -Wstrict-prototypes -#CFLAGS += -mshort-calls -#CFLAGS += -fno-unit-at-a-time -#CFLAGS += -Wundef -#CFLAGS += -Wunreachable-code -#CFLAGS += -Wsign-compare -CFLAGS += -Wa,-adlns=$(<:%.c=$(OBJDIR)/%.lst) -CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -CFLAGS += $(CSTANDARD) -# Next line dumps rtl file -#CFLAGS += -dr -#CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst) - - -#---------------- Compiler Options C++ ---------------- -# -g*: generate debugging information -# -O*: optimization level -# -f...: tuning, see GCC manual and avr-libc documentation -# -Wall...: warning level -# -Wa,...: tell GCC to pass this to the assembler. -# -adhlns...: create assembler listing -CPPFLAGS = -g$(DEBUG) -CPPFLAGS += $(CPPDEFS) -CPPFLAGS += -O$(OPT) -CPPFLAGS += -funsigned-char -CPPFLAGS += -funsigned-bitfields -CPPFLAGS += -fpack-struct -CPPFLAGS += -fshort-enums -CPPFLAGS += -fno-exceptions -CPPFLAGS += -Wall -CFLAGS += -Wundef -#CPPFLAGS += -mshort-calls -#CPPFLAGS += -fno-unit-at-a-time -#CPPFLAGS += -Wstrict-prototypes -#CPPFLAGS += -Wunreachable-code -#CPPFLAGS += -Wsign-compare -CPPFLAGS += -Wa,-adlns=$(<:%.cpp=$(OBJDIR)/%.lst) -CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) -#CPPFLAGS += $(CSTANDARD) -#CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst) - - -#---------------- Assembler Options ---------------- -# -Wa,...: tell GCC to pass this to the assembler. -# -adhlns: create listing -# -gstabs: have the assembler create line number information; note that -# for use in COFF files, additional information about filenames -# and function names needs to be present in the assembler source -# files -- see avr-libc docs [FIXME: not yet described there] -# -listing-cont-lines: Sets the maximum number of continuation lines of hex -# dump that will be displayed for a given single line of source input. -ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100 - - -#---------------- Library Options ---------------- -# Minimalistic printf version -PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min - -# Floating point printf version (requires MATH_LIB = -lm below) -PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt - -# If this is left blank, then it will use the Standard printf version. -PRINTF_LIB = -#PRINTF_LIB = $(PRINTF_LIB_MIN) -#PRINTF_LIB = $(PRINTF_LIB_FLOAT) - - -# Minimalistic scanf version -SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min - -# Floating point + %[ scanf version (requires MATH_LIB = -lm below) -SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt - -# If this is left blank, then it will use the Standard scanf version. -SCANF_LIB = -#SCANF_LIB = $(SCANF_LIB_MIN) -#SCANF_LIB = $(SCANF_LIB_FLOAT) - - -MATH_LIB = -lm - - -# List any extra directories to look for libraries here. -# Each directory must be seperated by a space. -# Use forward slashes for directory separators. -# For a directory that has spaces, enclose it in quotes. -EXTRALIBDIRS = - - - -#---------------- External Memory Options ---------------- - -# 64 KB of external RAM, starting after internal RAM (ATmega128!), -# used for variables (.data/.bss) and heap (malloc()). -#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff - -# 64 KB of external RAM, starting after internal RAM (ATmega128!), -# only used for heap (malloc()). -#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff - -EXTMEMOPTS = - - - -#---------------- Linker Options ---------------- -# -Wl,...: tell GCC to pass this to linker. -# -Map: create map file -# --cref: add cross reference to map file -LDFLAGS = -Wl,-Map=$(TARGET).map,--cref -LDFLAGS += $(EXTMEMOPTS) -LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS)) -LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) -#LDFLAGS += -Wl,--section-start=.text=0x00D0 -#LDFLAGS += -Wl,--section-start=.vectors=0x0080 -#LDFLAGS += -T avr3-167.ld -LDFLAGS += -N - - - -#---------------- Programming Options (avrdude) ---------------- - -# Programming hardware: alf avr910 avrisp bascom bsd -# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500 -# -# Type: avrdude -c ? -# to get a full listing. -# -AVRDUDE_PROGRAMMER = stk500 - -# com1 = serial port. Use lpt1 to connect to parallel port. -AVRDUDE_PORT = com3 - -AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex -#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep - - -# Uncomment the following if you want avrdude's erase cycle counter. -# Note that this counter needs to be initialized first using -Yn, -# see avrdude manual. -#AVRDUDE_ERASE_COUNTER = -y - -# Uncomment the following if you do /not/ wish a verification to be -# performed after programming the device. -#AVRDUDE_NO_VERIFY = -V - -# Increase verbosity level. Please use this when submitting bug -# reports about avrdude. See -# to submit bug reports. -#AVRDUDE_VERBOSE = -v -v - -AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) -AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) -AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) - - - -#---------------- Debugging Options ---------------- - -# For simulavr only - target MCU frequency. -DEBUG_MFREQ = $(F_CPU) - -# Set the DEBUG_UI to either gdb or insight. -# DEBUG_UI = gdb -DEBUG_UI = insight - -# Set the debugging back-end to either avarice, simulavr. -DEBUG_BACKEND = avarice -#DEBUG_BACKEND = simulavr - -# GDB Init Filename. -GDBINIT_FILE = __avr_gdbinit - -# When using avarice settings for the JTAG -JTAG_DEV = /dev/com1 - -# Debugging port used to communicate between GDB / avarice / simulavr. -DEBUG_PORT = 4242 - -# Debugging host used to communicate between GDB / avarice / simulavr, normally -# just set to localhost unless doing some sort of crazy debugging when -# avarice is running on a different computer. -DEBUG_HOST = localhost - - - -#============================================================================ - - -# Define programs and commands. -SHELL = sh -CC = avr-gcc -OBJCOPY = avr-objcopy -OBJDUMP = avr-objdump -SIZE = avr-size -AR = avr-ar rcs -NM = avr-nm -AVRDUDE = avrdude -REMOVE = rm -f -REMOVEDIR = rm -rf -COPY = cp -WINSHELL = cmd - - -# Define Messages -# English -MSG_ERRORS_NONE = Errors: none -MSG_BEGIN = -------- begin -------- -MSG_END = -------- end -------- -MSG_SIZE_BEFORE = Size before: -MSG_SIZE_AFTER = Size after: -MSG_COFF = Converting to AVR COFF: -MSG_EXTENDED_COFF = Converting to AVR Extended COFF: -MSG_FLASH = Creating load file for Flash: -MSG_EEPROM = Creating load file for EEPROM: -MSG_EXTENDED_LISTING = Creating Extended Listing: -MSG_SYMBOL_TABLE = Creating Symbol Table: -MSG_LINKING = Linking: -MSG_COMPILING = Compiling C: -MSG_COMPILING_CPP = Compiling C++: -MSG_ASSEMBLING = Assembling: -MSG_CLEANING = Cleaning project: -MSG_CREATING_LIBRARY = Creating library: - - - - -# Define all object files. -OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) - -# Define all listing files. -LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) - - -# Compiler flags to generate dependency files. -GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d - - -# Combine all necessary flags and optional flags. -# Add target processor to flags. -ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) -ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) -ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) - - - - - -# Default target. -all: begin gccversion sizebefore build sizeafter end - -# Change the build target to build a HEX file or a library. -build: elf hex eep lss sym bin -#build: lib - - -elf: $(TARGET).elf -hex: $(TARGET).hex -bin: $(TARGET).bin -eep: $(TARGET).eep -lss: $(TARGET).lss -sym: $(TARGET).sym -LIBNAME=lib$(TARGET).a -lib: $(LIBNAME) - - - -# Eye candy. -# AVR Studio 3.x does not check make's exit code but relies on -# the following magic strings to be generated by the compile job. -begin: - @echo - @echo $(MSG_BEGIN) - -end: - @echo $(MSG_END) - @echo - - -# Display size of file. -HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex -ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf - -sizebefore: - @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \ - 2>/dev/null; echo; fi - -sizeafter: - @if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \ - 2>/dev/null; echo; fi - - - -# Display compiler version information. -gccversion : - @$(CC) --version - - - -# Program the device. -program: $(TARGET).hex $(TARGET).eep - $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) - - -# Generate avr-gdb config/init file which does the following: -# define the reset signal, load the target file, connect to target, and set -# a breakpoint at main(). -gdb-config: - @$(REMOVE) $(GDBINIT_FILE) - @echo define reset >> $(GDBINIT_FILE) - @echo SIGNAL SIGHUP >> $(GDBINIT_FILE) - @echo end >> $(GDBINIT_FILE) - @echo file $(TARGET).elf >> $(GDBINIT_FILE) - @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE) -ifeq ($(DEBUG_BACKEND),simulavr) - @echo load >> $(GDBINIT_FILE) -endif - @echo break main >> $(GDBINIT_FILE) - -debug: gdb-config $(TARGET).elf -ifeq ($(DEBUG_BACKEND), avarice) - @echo Starting AVaRICE - Press enter when "waiting to connect" message displays. - @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \ - $(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT) - @$(WINSHELL) /c pause - -else - @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \ - $(DEBUG_MFREQ) --port $(DEBUG_PORT) -endif - @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE) - - - - -# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. -COFFCONVERT = $(OBJCOPY) --debugging -COFFCONVERT += --change-section-address .data-0x800000 -COFFCONVERT += --change-section-address .bss-0x800000 -COFFCONVERT += --change-section-address .noinit-0x800000 -COFFCONVERT += --change-section-address .eeprom-0x810000 - - - -coff: $(TARGET).elf - @echo - @echo $(MSG_COFF) $(TARGET).cof - $(COFFCONVERT) -O coff-avr $< $(TARGET).cof - - -extcoff: $(TARGET).elf - @echo - @echo $(MSG_EXTENDED_COFF) $(TARGET).cof - $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof - - - -# Create final output files (.hex, .eep) from ELF output file. -%.hex: %.elf - @echo - @echo $(MSG_FLASH) $@ - $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ - -%.bin: %.elf - $(OBJCOPY) -O binary $< $@ - -%.eep: %.elf - @echo - @echo $(MSG_EEPROM) $@ - -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0 - -# Create extended listing file from ELF output file. -%.lss: %.elf - @echo - @echo $(MSG_EXTENDED_LISTING) $@ - $(OBJDUMP) -h -S $< > $@ - -# Create a symbol table from ELF output file. -%.sym: %.elf - @echo - @echo $(MSG_SYMBOL_TABLE) $@ - $(NM) -n $< > $@ - - - -# Create library from object files. -.SECONDARY : $(TARGET).a -.PRECIOUS : $(OBJ) -%.a: $(OBJ) - @echo - @echo $(MSG_CREATING_LIBRARY) $@ - $(AR) $@ $(OBJ) - - -# Link: create ELF output file from object files. -.SECONDARY : $(TARGET).elf -.PRECIOUS : $(OBJ) -%.elf: $(OBJ) - @echo - @echo $(MSG_LINKING) $@ - $(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS) - - -# Compile: create object files from C source files. -$(OBJDIR)/%.o : %.c - @echo - @echo $(MSG_COMPILING) $< - $(CC) -c $(ALL_CFLAGS) $< -o $@ - - -# Compile: create object files from C++ source files. -$(OBJDIR)/%.o : %.cpp - @echo - @echo $(MSG_COMPILING_CPP) $< - $(CC) -c $(ALL_CPPFLAGS) $< -o $@ - - -# Compile: create assembler files from C source files. -%.s : %.c - $(CC) -S $(ALL_CFLAGS) $< -o $@ - - -# Compile: create assembler files from C++ source files. -%.s : %.cpp - $(CC) -S $(ALL_CPPFLAGS) $< -o $@ - - -# Assemble: create object files from assembler source files. -$(OBJDIR)/%.o : %.S - @echo - @echo $(MSG_ASSEMBLING) $< - $(CC) -c $(ALL_ASFLAGS) $< -o $@ - - -# Create preprocessed source for use in sending a bug report. -%.i : %.c - $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ - - -# Target: clean project. -clean: begin clean_list end - -clean_list : - @echo - @echo $(MSG_CLEANING) - $(REMOVE) $(TARGET).hex - $(REMOVE) $(TARGET).eep - $(REMOVE) $(TARGET).cof - $(REMOVE) $(TARGET).elf - $(REMOVE) $(TARGET).map - $(REMOVE) $(TARGET).sym - $(REMOVE) $(TARGET).lss - $(REMOVE) $(CPPSRC:%.cpp=%.o) - $(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst) - $(REMOVE) $(SRC:.c=.s) - $(REMOVE) $(SRC:.c=.d) - $(REMOVE) $(SRC:.c=.i) - $(REMOVEDIR) .dep - - -# Create object files directory -$(shell mkdir $(OBJDIR) 2>/dev/null) - - -# Include the dependency files. --include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) - - -# Listing of phony targets. -.PHONY : all begin finish end sizebefore sizeafter gccversion \ -build elf hex eep lss sym coff extcoff \ -clean clean_list program debug gdb-config - - - - diff --git a/Multiprotocol/MultiOrange.cpp.orangetx b/Multiprotocol/MultiOrange.h similarity index 89% rename from Multiprotocol/MultiOrange.cpp.orangetx rename to Multiprotocol/MultiOrange.h index 6fa9fe6..6bda063 100644 --- a/Multiprotocol/MultiOrange.cpp.orangetx +++ b/Multiprotocol/MultiOrange.h @@ -55,6 +55,9 @@ extern void TelemetryUpdate() ; extern uint16_t initDsm() ; extern uint16_t ReadDsm() ; +extern void setup() ; +extern void loop() ; + #define yield() #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) @@ -139,27 +142,29 @@ void init() PORTA.PIN7CTRL = 0x18 ; } -#include "Multiprotocol.ino" -#include "SPI.ino" -#include "Common.ino" -#include "Arduino.ino" +//#ifndef ARDUINO_AVR_XMEGA32D4 +//#include "Multiprotocol.ino" +//#include "SPI.ino" +//#include "Common.ino" +//#include "Arduino.ino" -#include "cyrf6936_SPI.ino" -#include "DSM_cyrf6936.ino" -#include "Devo_cyrf6936.ino" -#include "J6Pro_cyrf6936.ino" -#include "WK2x01_cyrf6936.ino" +//#include "cyrf6936_SPI.ino" +//#include "DSM_cyrf6936.ino" +//#include "Devo_cyrf6936.ino" +//#include "J6Pro_cyrf6936.ino" +//#include "WK2x01_cyrf6936.ino" -#include "Telemetry.ino" +//#include "Telemetry.ino" +//#endif -int main(void) -{ - init() ; - setup() ; - for(;;) - { - loop() ; - } -} +//int main(void) +//{ +// init() ; +// setup() ; +// for(;;) +// { +// loop() ; +// } +//} diff --git a/Multiprotocol/Multiprotocol.ino b/Multiprotocol/Multiprotocol.ino index 1a8f96b..53498df 100644 --- a/Multiprotocol/Multiprotocol.ino +++ b/Multiprotocol/Multiprotocol.ino @@ -28,7 +28,7 @@ #ifdef __arm__ // Let's automatically select the board if arm is selected #define STM32_BOARD #endif -#ifdef ARDUINO_AVR_XMEGA32D4 +#if defined (ARDUINO_AVR_XMEGA32D4) || defined (ARDUINO_MULTI_ORANGERX) #include "MultiOrange.h" #endif @@ -49,7 +49,6 @@ #ifndef STM32_BOARD #include #else - #include #include #include #include diff --git a/docs/Compiling_OrangeTx.md b/docs/Compiling_OrangeTx.md new file mode 100644 index 0000000..2708697 --- /dev/null +++ b/docs/Compiling_OrangeTx.md @@ -0,0 +1,73 @@ +# Compiling and Programming (OrangeRX) + +Multiprotocol firmware is compiled using the Arduino IDE. The guide below will walk you through all the steps to compile and upload your customized firmware. + +**These instructions are for the OrangeRX version of the Multiprotocol module.** If you are compling for a different module please go to the dedicated page [Atmega328p](Compiling.md) or [STM32](Compiling_STM32.md) page. + +## Index +1. [Tools Required](#tools-required) +1. [Preparation](#preparation) + 1. [Install the Arduino IDE](#install-the-arduino-ide) + 1. [Download the Multiprotocol source and open the project](#download-the-multiprotocol-source-and-open-the-project) + 1. [Install the Multi 4-in-1 board](#install-the-multi-4-in-1-board) + 1. [Configure the Arduino IDE](#configure-the-arduino-ide) +1. [Configure the firmware](#configure-the-firmware) + 1. [Customize the firmware to match your hardware and your needs](#customize-the-firmware-to-match-your-hardware-and-your-needs) + 1. [Verify the firmware](#verify-the-firmware) +1. [Compiling and uploading the firmware](#compiling-and-uploading-the-firmware) + 1. [Upload the firmware](#upload-the-firmware) + 1. [Flash from TX](#flash-from-tx) +1. [Troubleshooting](#troubleshooting) + +## Tools required +Flashing the bootloader to the OrangeRX module requires either a PPI-capable programmer or an Arduino Pro Mini programmed with a sketch which can program the bootloader. + +Flashing the bootloader is outside the scope of this documentation. Full instructions are available [here](http://openrcforums.com/forum/viewtopic.php?f=40&t=8753&sid=bbd74327cc518303e1c7f9e2ace04339#p114549). + +## Preparation +### Install the Arduino IDE +1. Download and install the Arduino IDE. The currently supported Arduino version is 1.8.5, available for [Windows]( https://www.arduino.cc/download_handler.php?f=/arduino-1.8.5-windows.exe) and [Mac OSX](https://www.arduino.cc/download_handler.php?f=/arduino-1.8.5-macosx.zip) +1. It is recommended to upgrade Java to the [latest version](https://www.java.com/en/download/) + +### Download the Multiprotocol source and open the project +1. Either + 1. Download the zip file with the Multiprotocol module source code from [here](https://github.com/pascallanger/DIY-Multiprotocol-TX-Module/archive/master.zip) and unzip and copy the source code folder **Multiprotocol** to a location of your choosing, or + 1. Clone the project using Git or Github Desktop, then +1. Double-click the **Multiprotocol.ino** file in the **Multiprotocol** folder to open the project in the Arduino IDE + +### Install the Multi 4-in-1 board +1. Follow [these instructions](/BootLoaders/README.md) to install the **Multi 4-in-1 OrangeRX Board** in the Arduino IDE + +### Configure the Arduino IDE +1. Under **Tools -> Board** select **'Multi 4-in-1 (OrangeRX)'** + +## Configure the firmware +### Customize the firmware to match your hardware and your needs +All customization is done by editing the ```_Config.h ``` file in the Multiprotocol Arduino project. + +The OrangeRX module has more than enough flash space for all the compatible protocols so, unlike the Atmega328p-based module, it is not necessary to disable unused protocols. + +You can still disable protocols if you wish, and you may also enable or disable other optional Multiprotocol features. + +### Verify the firmware +To check that the program will compile correctly and fit in the Atmega click **Sketch -> Verify/Compile**, or press **Ctrl+R**. + +If there are no errors and you see output like this: +``` +Sketch uses 31874 bytes (97%) of program storage space. Maximum is 32768 bytes. +Global variables use 1083 bytes (52%) of dynamic memory, leaving 965 bytes for local variables. Maximum is 2048 bytes. +``` +You can proceed to the next step. + +## Compiling and uploading the firmware + +### Upload the firmware +You are now ready to upload the firmware to the multiprotocol module. Uploading is done via the 'Flash-from-TX' method. + +**Note:** 'Flash from TX' is only available with radios running ersky9x r221e2 or newer. + +#### Flash from TX +1. In the Arduino IDE click **Sketch -> Export compiled Binary**, or press **Ctrl+Alt+S** +1. Locate the file named **multi-orx-[version].hex** in the **Multiprotocol** folder +1. Follow the instructions [here](/docs/Flash_from_Tx.md) to upload the firmware using your radio +