Browse Source

first commit

root 8 years ago
commit
1b78be2fbc
19 changed files with 3859 additions and 0 deletions
  1. 547 0
      Makefile
  2. 139 0
      Makefile.1284
  3. 34 0
      Makefile.atmel
  4. 15 0
      Makefile.custom
  5. 124 0
      Makefile.extras
  6. 90 0
      Makefile.isp
  7. 99 0
      README.TXT
  8. 3 0
      README.md
  9. BIN
      SimpleBGC_2_40b8.zip
  10. BIN
      SimpleBGC_GUI_2_40b8.zip
  11. 56 0
      baudcheck.c
  12. 848 0
      boot.h
  13. 60 0
      build.sh
  14. 32 0
      makeall
  15. 9 0
      omake
  16. 1 0
      omake.bat
  17. 963 0
      optiboot.c
  18. 795 0
      pin_defs.h
  19. 44 0
      stk500.h

+ 547 - 0
Makefile

@@ -0,0 +1,547 @@
+# Makefile for ATmegaBOOT
+# E.Lins, 18.7.2005
+# $Id$
+#
+# Instructions
+#
+# To make bootloader .hex file:
+# make diecimila
+# make lilypad
+# make ng
+# etc...
+#
+# To burn bootloader .hex file:
+# make diecimila_isp
+# make lilypad_isp
+# make ng_isp
+# etc...
+#
+# Edit History
+# 201406xx: WestfW: More Makefile restructuring.
+#                   Split off Makefile.1284, Makefile.extras, Makefile.custom
+#                   So that in theory, the main Makefile contains only the
+#                   official platforms, and does not need to be modified to
+#                   add "less supported" chips and boards.
+# 201303xx: WestfW: Major Makefile restructuring.
+#                   Allows options on Make command line "make xx LED=B3"
+#                   (see also pin_defs.h)
+#                   Divide into "chip" targets and "board" targets.
+#                   Most boards are (recursive) board targets with options.
+#                   Move isp target to separate makefile (fixes m8 EFUSE)
+#                   Some (many) targets will now be rebuilt when not
+#                     strictly necessary, so that options will be included.
+#                     (any "make" with options will always compile.)
+#                   Set many variables with ?= so they can be overridden
+#                   Use arduinoISP settings as default for ISP targets
+#
+#
+# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
+# * This software is licensed under version 2 of the Gnu Public Licence.
+# * See optiboot.c for details.
+
+#----------------------------------------------------------------------
+#
+# program name should not be changed...
+PROGRAM    = optiboot
+
+# The default behavior is to build using tools that are in the users
+# current path variables, but we can also build using an installed
+# Arduino user IDE setup, or the Arduino source tree.
+# Uncomment this next lines to build within the arduino environment,
+# using the arduino-included avrgcc toolset (mac and pc)
+# ENV ?= arduino
+# ENV ?= arduinodev
+# OS ?= macosx
+# OS ?= windows
+
+# export symbols to recursive makes (for ISP)
+export
+
+# defaults
+MCU_TARGET = atmega168
+LDSECTIONS  = -Wl,--section-start=.text=0x3e00 -Wl,--section-start=.version=0x3ffe
+
+# Build environments
+# Start of some ugly makefile-isms to allow optiboot to be built
+# in several different environments.  See the README.TXT file for
+# details.
+
+# default
+fixpath = $(1)
+SH := bash
+
+ifeq ($(ENV), arduino)
+# For Arduino, we assume that we're connected to the optiboot directory
+# included with the arduino distribution, which means that the full set
+# of avr-tools are "right up there" in standard places.
+# (except that in 1.5.x, there's an additional level of "up")
+TESTDIR := $(firstword $(wildcard ../../../tools/*))
+ifeq (,$(TESTDIR))
+# Arduino 1.5.x tool location compared to optiboot dir
+  TOOLROOT = ../../../../tools
+else
+# Arduino 1.0 (and earlier) tool location
+  TOOLROOT = ../../../tools
+endif
+GCCROOT = $(TOOLROOT)/avr/bin/
+
+ifeq ($(OS), windows)
+# On windows, SOME of the tool paths will need to have backslashes instead
+# of forward slashes (because they use windows cmd.exe for execution instead
+# of a unix/mingw shell?)  We also have to ensure that a consistent shell
+# is used even if a unix shell is installed (ie as part of WINAVR)
+fixpath = $(subst /,\,$1)
+SHELL = cmd.exe
+SH = sh
+endif
+
+else ifeq ($(ENV), arduinodev)
+# Arduino IDE source code environment.  Use the unpacked compilers created
+# by the build (you'll need to do "ant build" first.)
+ifeq ($(OS), macosx)
+TOOLROOT = ../../../../build/macosx/work/Arduino.app/Contents/Resources/Java/hardware/tools
+endif
+ifeq ($(OS), windows)
+TOOLROOT = ../../../../build/windows/work/hardware/tools
+endif
+
+GCCROOT = $(TOOLROOT)/avr/bin/
+AVRDUDE_CONF = -C$(TOOLROOT)/avr/etc/avrdude.conf
+
+else
+GCCROOT =
+AVRDUDE_CONF =
+endif
+
+STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe"
+STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \
+           -lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt
+STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt
+#
+# End of build environment code.
+
+
+OBJ        = $(PROGRAM).o
+OPTIMIZE = -Os -fno-split-wide-types -mrelax
+
+DEFS       = 
+
+#
+# platforms support EEPROM and large bootloaders need the eeprom functions that
+# are defined in libc, even though we explicity remove it with -nostdlib because
+# of the space-savings.
+LIBS       =  -lc
+
+CC         = $(GCCROOT)avr-gcc
+
+# Override is only needed by avr-lib build system.
+
+override CFLAGS        = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS)
+override LDFLAGS       = $(LDSECTIONS) -Wl,--relax -nostartfiles -nostdlib
+#-Wl,--gc-sections
+
+OBJCOPY        = $(GCCROOT)avr-objcopy
+OBJDUMP        = $(call fixpath,$(GCCROOT)avr-objdump)
+
+SIZE           = $(GCCROOT)avr-size
+
+#
+# Make command-line Options.
+# Permit commands like "make atmega328 LED_START_FLASHES=10" to pass the
+# appropriate parameters ("-DLED_START_FLASHES=10") to gcc
+#
+
+ifdef BAUD_RATE
+BAUD_RATE_CMD = -DBAUD_RATE=$(BAUD_RATE)
+dummy = FORCE
+else
+BAUD_RATE_CMD = -DBAUD_RATE=115200
+endif
+
+ifdef LED_START_FLASHES
+LED_START_FLASHES_CMD = -DLED_START_FLASHES=$(LED_START_FLASHES)
+dummy = FORCE
+else
+LED_START_FLASHES_CMD = -DLED_START_FLASHES=3
+endif
+
+# BIG_BOOT: Include extra features, up to 1K.
+ifdef BIGBOOT
+BIGBOOT_CMD = -DBIGBOOT=1
+dummy = FORCE
+endif
+
+ifdef SOFT_UART
+SOFT_UART_CMD = -DSOFT_UART=1
+dummy = FORCE
+endif
+
+ifdef LED_DATA_FLASH
+LED_DATA_FLASH_CMD = -DLED_DATA_FLASH=1
+dummy = FORCE
+endif
+
+ifdef LED
+LED_CMD = -DLED=$(LED)
+dummy = FORCE
+endif
+
+ifdef SINGLESPEED
+SS_CMD = -DSINGLESPEED=1
+endif
+
+COMMON_OPTIONS = $(BAUD_RATE_CMD) $(LED_START_FLASHES_CMD) $(BIGBOOT_CMD)
+COMMON_OPTIONS += $(SOFT_UART_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(SS_CMD)
+
+#UART is handled separately and only passed for devices with more than one.
+ifdef UART
+UART_CMD = -DUART=$(UART)
+endif
+
+# Not supported yet
+# ifdef SUPPORT_EEPROM
+# SUPPORT_EEPROM_CMD = -DSUPPORT_EEPROM
+# dummy = FORCE
+# endif
+
+# Not supported yet
+# ifdef TIMEOUT_MS
+# TIMEOUT_MS_CMD = -DTIMEOUT_MS=$(TIMEOUT_MS)
+# dummy = FORCE
+# endif
+#
+
+#.PRECIOUS: %.elf
+
+#---------------------------------------------------------------------------
+# "Chip-level Platform" targets.
+# A "Chip-level Platform" compiles for a particular chip, but probably does
+# not have "standard" values for things like clock speed, LED pin, etc.
+# Makes for chip-level platforms should usually explicitly define their
+# options like: "make atmega1285 AVR_FREQ=16000000L LED=D0"
+#---------------------------------------------------------------------------
+#
+# Note about fuses:
+# the efuse should really be 0xf8; since, however, only the lower
+# three bits of that byte are used on the atmega168, avrdude gets
+# confused if you specify 1's for the higher bits, see:
+# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
+#
+# similarly, the lock bits should be 0xff instead of 0x3f (to
+# unlock the bootloader section) and 0xcf instead of 0x2f (to
+# lock it), but since the high two bits of the lock byte are
+# unused, avrdude would get confused.
+#---------------------------------------------------------------------------
+#
+
+# Test platforms
+# Virtual boot block test
+virboot8: TARGET = atmega8
+virboot8: MCU_TARGET = atmega8
+virboot8: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION' '-Dsave_vect_num=EE_RDY_vect_num'
+virboot8: AVR_FREQ ?= 16000000L 
+virboot8: LDSECTIONS  = -Wl,--section-start=.text=0x1c00 -Wl,--section-start=.version=0x1ffe
+virboot8: $(PROGRAM)_virboot8.hex
+virboot8: $(PROGRAM)_virboot8.lst
+
+
+virboot328: TARGET = atmega328
+virboot328: MCU_TARGET = atmega328p
+virboot328: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION'
+virboot328: AVR_FREQ ?= 16000000L
+virboot328: LDSECTIONS  = -Wl,--section-start=.text=0x7d80 -Wl,--section-start=.version=0x7ffe
+virboot328: $(PROGRAM)_virboot328.hex
+virboot328: $(PROGRAM)_virboot328.lst
+
+virboot328_isp: virboot328
+virboot328_isp: TARGET = virboot328
+virboot328_isp: MCU_TARGET = atmega328p
+# no boot section, SPIEN
+virboot328_isp: HFUSE ?= DF
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+virboot328_isp: LFUSE ?= FF
+# 2.7V brownout
+virboot328_isp: EFUSE ?= 05
+virboot328_isp: isp
+
+
+# Diecimila, Duemilanove with m168, and NG use identical bootloaders
+# Call it "atmega168" for generality and clarity, keep "diecimila" for
+# backward compatibility of makefile
+#
+atmega168: TARGET = atmega168
+atmega168: MCU_TARGET = atmega168
+atmega168: CFLAGS += $(COMMON_OPTIONS)
+atmega168: AVR_FREQ ?= 16000000L 
+atmega168: $(PROGRAM)_atmega168.hex
+atmega168: $(PROGRAM)_atmega168.lst
+
+atmega168_isp: atmega168
+atmega168_isp: TARGET = atmega168
+# 2.7V brownout
+atmega168_isp: HFUSE ?= DD
+# Full swing (16MHz) 16KCK/14CK+65ms
+atmega168_isp: LFUSE ?= F7
+# 512 byte boot
+atmega168_isp: EFUSE ?= 04
+atmega168_isp: isp
+
+atmega16: TARGET = atmega16
+atmega16: MCU_TARGET = atmega16
+atmega16: CFLAGS += $(COMMON_OPTIONS)
+atmega16: AVR_FREQ ?= 16000000L 
+atmega16: $(PROGRAM)_atmega16.hex
+atmega16: $(PROGRAM)_atmega16.lst
+
+atmega328: TARGET = atmega328
+atmega328: MCU_TARGET = atmega328p
+atmega328: CFLAGS += $(COMMON_OPTIONS)
+atmega328: AVR_FREQ ?= 16000000L
+atmega328: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
+atmega328: $(PROGRAM)_atmega328.hex
+atmega328: $(PROGRAM)_atmega328.lst
+
+atmega328_isp: atmega328
+atmega328_isp: TARGET = atmega328
+atmega328_isp: MCU_TARGET = atmega328p
+# 512 byte boot, SPIEN
+atmega328_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega328_isp: LFUSE ?= FF
+# 2.7V brownout
+atmega328_isp: EFUSE ?= 05
+atmega328_isp: isp
+
+#Atmega1280
+atmega1280: MCU_TARGET = atmega1280
+atmega1280: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT $(UART_CMD)
+atmega1280: AVR_FREQ ?= 16000000L
+atmega1280: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00  -Wl,--section-start=.version=0x1fffe
+atmega1280: $(PROGRAM)_atmega1280.hex
+atmega1280: $(PROGRAM)_atmega1280.lst
+
+
+# ATmega8
+#
+atmega8: TARGET = atmega8
+atmega8: MCU_TARGET = atmega8
+atmega8: CFLAGS += $(COMMON_OPTIONS)
+atmega8: AVR_FREQ ?= 16000000L 
+atmega8: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe -Wl,--gc-sections -Wl,--undefined=optiboot_version
+atmega8: $(PROGRAM)_atmega8.hex
+atmega8: $(PROGRAM)_atmega8.lst
+
+atmega8_isp: atmega8
+atmega8_isp: TARGET = atmega8
+atmega8_isp: MCU_TARGET = atmega8
+# SPIEN, CKOPT (for full swing xtal), Bootsize=512B
+atmega8_isp: HFUSE ?= CC
+# 2.7V brownout, 16MHz Xtal, 16KCK/14CK+65ms
+atmega8_isp: LFUSE ?= BF
+atmega8_isp: isp
+
+
+#---------------------------------------------------------------------------
+# "Board-level Platform" targets.
+# A "Board-level Platform" implies a manufactured platform with a particular
+# AVR_FREQ, LED, and so on.  Parameters are not particularly changable from
+# the "make" command line.
+# Most of the board-level platform builds should envoke make recursively
+#  appropriate specific options
+#---------------------------------------------------------------------------
+# 20MHz clocked platforms
+#
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
+#
+
+pro20: TARGET = pro_20mhz
+pro20: CHIP = atmega168
+pro20:
+	$(MAKE) atmega168 AVR_FREQ=20000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro20_isp: pro20
+pro20_isp: TARGET = pro_20mhz
+# 4.3V brownout (for max speed!)
+pro20_isp: HFUSE ?= DC
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro20_isp: LFUSE ?= F7
+# 512 byte boot
+pro20_isp: EFUSE ?= 04
+pro20_isp: isp
+
+# 16MHz clocked platforms
+#
+# These are capable of 230400 baud, or 115200 baud on PC (Arduino Avrdude issue)
+#
+
+pro16: TARGET = pro_16MHz
+pro16: CHIP = atmega168
+pro16:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro16_isp: pro16
+pro16_isp: TARGET = pro_16MHz
+# 2.7V brownout
+pro16_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro16_isp: LFUSE ?= F7
+# 512 byte boot
+pro16_isp: EFUSE ?= 04
+pro16_isp: isp
+
+diecimila: TARGET = diecimila
+diecimila: CHIP = atmega168
+diecimila:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+diecimila_isp: diecimila
+diecimila_isp: TARGET = diecimila
+# 2.7V brownout
+diecimila_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+diecimila_isp: LFUSE ?= F7
+# 512 byte boot
+diecimila_isp: EFUSE ?= 04
+diecimila_isp: isp
+
+# MEGA1280 Board (this is different from the atmega1280 chip platform)
+# Mega has a minimum boot size of 1024 bytes, so enable extra functions
+# Note that optiboot does not (can not) work on the MEGA2560
+#mega: TARGET = atmega1280
+mega1280: atmega1280
+
+mega1280_isp: mega1280
+mega1280_isp: TARGET = atmega1280
+mega1280_isp: MCU_TARGET = atmega1280
+# 1024 byte boot
+mega1280_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+mega1280_isp: LFUSE ?= FF
+# 2.7V brownout; wants F5 for some reason...
+mega1280_isp: EFUSE ?= F5
+mega1280_isp: isp
+
+# 8MHz clocked platforms
+#
+# These are capable of 115200 baud
+# Note that "new" Arduinos with an AVR as USB/Serial converter will NOT work
+# with an 8MHz target Arduino.  The bitrate errors are in opposite directions,
+# and total too large a number.
+#
+
+lilypad: TARGET = $@
+lilypad: CHIP = atmega168
+lilypad:
+	$(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+lilypad_isp: lilypad
+lilypad_isp: TARGET = lilypad
+# 2.7V brownout
+lilypad_isp: HFUSE ?= DD
+# Internal 8MHz osc (8MHz) Slow rising power
+lilypad_isp: LFUSE ?= E2
+# 512 byte boot
+lilypad_isp: EFUSE ?= 04
+lilypad_isp: isp
+
+# lilypad_resonator is the same as a 8MHz lilypad, except for fuses.
+lilypad_resonator: lilypad
+
+lilypad_resonator_isp: lilypad
+lilypad_resonator_isp: TARGET = lilypad
+# 2.7V brownout
+lilypad_resonator_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+lilypad_resonator_isp: LFUSE ?= C6
+# 512 byte boot
+lilypad_resonator_isp: EFUSE ?= 04
+lilypad_resonator_isp: isp
+
+pro8: TARGET = pro_8MHz
+pro8: CHIP = atmega168
+pro8:
+	$(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+pro8_isp: pro8
+pro8_isp: TARGET = pro_8MHz
+# 2.7V brownout
+pro8_isp: HFUSE ?= DD
+# Full swing xtal (20MHz) 258CK/14CK+4.1ms
+pro8_isp: LFUSE ?= C6
+# 512 byte boot
+pro8_isp: EFUSE ?= 04
+pro8_isp: isp
+
+atmega328_pro8: TARGET = atmega328_pro_8MHz
+atmega328_pro8: CHIP = atmega328
+atmega328_pro8:
+	$(MAKE) $(CHIP) AVR_FREQ=8000000L LED_START_FLASHES=3
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+atmega328_pro8_isp: atmega328_pro8
+atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
+atmega328_pro8_isp: MCU_TARGET = atmega328p
+# 512 byte boot, SPIEN
+atmega328_pro8_isp: HFUSE ?= DE
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega328_pro8_isp: LFUSE ?= FF
+# 2.7V brownout
+atmega328_pro8_isp: EFUSE ?= 05
+atmega328_pro8_isp: isp
+
+#
+# Include additional platforms
+include Makefile.atmel
+include Makefile.extras
+include Makefile.1284
+include Makefile.custom
+
+
+#---------------------------------------------------------------------------
+#
+# Generic build instructions
+#
+
+FORCE:
+
+baudcheck: FORCE
+	- @$(CC) --version
+	- @$(CC) $(CFLAGS) -E baudcheck.c -o baudcheck.tmp.sh
+	- @$(SH) baudcheck.tmp.sh
+
+isp: $(TARGET)
+	$(MAKE) -f Makefile.isp isp TARGET=$(TARGET)
+
+isp-stk500: $(PROGRAM)_$(TARGET).hex
+	$(STK500-1)
+	$(STK500-2)
+
+%.elf: $(OBJ) baudcheck $(dummy)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBS)
+	$(SIZE) $@
+
+clean:
+	rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.tmp.sh
+
+%.lst: %.elf
+	$(OBJDUMP) -h -S $< > $@
+
+%.hex: %.elf
+	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex $< $@
+
+%.srec: %.elf
+	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O srec $< $@
+
+%.bin: %.elf
+	$(OBJCOPY) -j .text -j .data -j .version --set-section-flags .version=alloc,load -O binary $< $@

+ 139 - 0
Makefile.1284

@@ -0,0 +1,139 @@
+#
+# Makefile for 40-pin AVR chips, including ATmega644 and ATmega1284
+#
+# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
+# * This software is licensed under version 2 of the Gnu Public Licence.
+# * See optiboot.c for details.
+
+# Chip level targets
+#
+atmega644p: TARGET = atmega644p
+atmega644p: MCU_TARGET = atmega644p
+atmega644p: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT
+atmega644p: AVR_FREQ ?= 16000000L
+atmega644p: LDSECTIONS  = -Wl,--section-start=.text=0xfc00 -Wl,--section-start=.version=0xfffe
+atmega644p: CFLAGS += $(UART_CMD)
+atmega644p: $(PROGRAM)_atmega644p.hex
+atmega644p: $(PROGRAM)_atmega644p.lst
+
+atmega1284: TARGET = atmega1284p
+atmega1284: MCU_TARGET = atmega1284p
+atmega1284: CFLAGS += $(COMMON_OPTIONS) -DBIGBOOT
+atmega1284: AVR_FREQ ?= 16000000L
+atmega1284: LDSECTIONS  = -Wl,--section-start=.text=0x1fc00 -Wl,--section-start=.version=0x1fffe
+atmega1284: CFLAGS += $(UART_CMD)
+atmega1284: $(PROGRAM)_atmega1284p.hex
+atmega1284: $(PROGRAM)_atmega1284p.lst
+
+atmega1284p: atmega1284
+
+atmega1284_isp: atmega1284
+atmega1284_isp: TARGET = atmega1284p
+atmega1284_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+atmega1284_isp: HFUSE ?= DE
+# Full Swing xtal (16MHz) 16KCK/14CK+65ms
+atmega1284_isp: LFUSE ?= F7
+# 2.7V brownout
+atmega1284_isp: EFUSE ?= FD
+atmega1284_isp: isp
+
+#
+# Board-level targets
+#
+
+# Sanguino has a minimum boot size of 1024 bytes, so enable extra functions
+#
+sanguino: TARGET = $@
+sanguino: CHIP = atmega644p
+sanguino:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B0
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+sanguino_isp: sanguino
+sanguino_isp: TARGET = sanguino
+sanguino_isp: MCU_TARGET = atmega644p
+# 1024 byte boot
+sanguino_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+sanguino_isp: LFUSE ?= F7
+# 2.7V brownout
+sanguino_isp: EFUSE ?= FD
+sanguino_isp: isp
+
+mighty1284: TARGET = $@
+mighty1284: CHIP = atmega1284p
+mighty1284:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B7
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+mighty1284_isp: mighty1284
+mighty1284_isp: TARGET = mighty1284
+mighty1284_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+mighty1284_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+mighty1284_isp: LFUSE ?= F7
+# 2.7V brownout
+mighty1284_isp: EFUSE ?= FD
+mighty1284_isp: isp
+
+bobuino: TARGET = $@
+bobuino: CHIP = atmega1284p
+bobuino:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B7
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+bobuino_isp: bobuino
+bobuino_isp: TARGET = bobuino
+bobuino_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+bobuino_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+bobuino_isp: LFUSE ?= F7
+# 2.7V brownout
+bobuino_isp: EFUSE ?= FD
+bobuino_isp: isp
+
+#
+# Wicked Devices "Wildfire" boards (1284 with wireless!)
+#
+
+wildfirev2: TARGET = $@
+wildfirev2: CHIP = atmega1284p
+wildfirev2:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B7 BAUD_RATE=1000000
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+wildfirev2_isp: wildfirev2
+wildfirev2_isp: TARGET = wildfirev2
+wildfirev2_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+wildfirev2_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+wildfirev2_isp: LFUSE ?= F7
+# 2.7V brownout
+wildfirev2_isp: EFUSE ?= FD
+wildfirev2_isp: isp
+
+wildfirev3: TARGET = $@
+wildfirev3: CHIP = atmega1284p
+wildfirev3:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B5
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+wildfirev3_isp: wildfirev3
+wildfirev3_isp: TARGET = wildfirev3
+wildfirev3_isp: MCU_TARGET = atmega1284p
+# 1024 byte boot
+wildfirev3_isp: HFUSE ?= DE
+# Full swing xtal (16MHz) 16KCK/14CK+65ms
+wildfirev3_isp: LFUSE ?= F7
+# 2.7V brownout
+wildfirev3_isp: EFUSE ?= FD
+wildfirev3_isp: isp

+ 34 - 0
Makefile.atmel

@@ -0,0 +1,34 @@
+# 
+# Support for the Atmel Xplained mini eval boards that are mostly
+#   compatible with Arduino.  (168pb, 328p, and 328pb chips.)
+#
+# Currently these all masquerade as 168 or 328p, because the IDE
+#  does not yet have compiler support for the -pb variants.
+#
+# These boards have an mEDBG debug chip that:
+#   1) means that optiboot can only be programmed via Atmel Studio
+#   2) prevents optiboot from working at 115200bps.
+#   3) provides 16MHz (at 5V) via Xin on the chip.
+#  
+# 
+#
+xplained168pb: TARGET = $@
+xplained168pb: CHIP = atmega168
+xplained168pb:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L BAUD_RATE=57600
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+xplained328pb: TARGET = $@
+xplained328pb: CHIP = atmega328
+xplained328pb:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L BAUD_RATE=57600
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+xplained328p: TARGET = $@
+xplained328p: CHIP = atmega328
+xplained328p:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L BAUD_RATE=57600
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst

+ 15 - 0
Makefile.custom

@@ -0,0 +1,15 @@
+#
+# Makefile for "custom" platforms.   Add your board here.
+#
+# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
+# * This software is licensed under version 2 of the Gnu Public Licence.
+# * See optiboot.c for details.
+
+
+wildfire: TARGET = $@
+wildfire: CHIP = atmega1284p
+wildfire:
+	$(MAKE) $(CHIP) AVR_FREQ=16000000L LED=B5
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+

+ 124 - 0
Makefile.extras

@@ -0,0 +1,124 @@
+#
+# Makefile for "other" implemented platforms.
+#
+# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
+# * This software is licensed under version 2 of the Gnu Public Licence.
+# * See optiboot.c for details.
+#
+
+#
+# Extra chips (maybe) supported by optiboot
+# Note that these are usually only minimally tested.
+#
+
+#
+# ATmega88
+#
+atmega88: TARGET = atmega88
+atmega88: MCU_TARGET = atmega88
+atmega88: CFLAGS += $(COMMON_OPTIONS)
+atmega88: AVR_FREQ ?= 16000000L 
+atmega88: LDSECTIONS  = -Wl,--section-start=.text=0x1e00 -Wl,--section-start=.version=0x1ffe -Wl,--gc-sections -Wl,--undefined=optiboot_version
+atmega88: $(PROGRAM)_atmega88.hex
+atmega88: $(PROGRAM)_atmega88.lst
+
+atmega88_isp: atmega88
+atmega88_isp: TARGET = atmega88
+atmega88_isp: MCU_TARGET = atmega88
+# 2.7V brownout
+atmega88_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega88_isp: LFUSE ?= FF
+# 512 byte boot
+atmega88_isp: EFUSE ?= 04
+atmega88_isp: isp
+
+atmega88p_isp: atmega88
+atmega88p_isp: TARGET = atmega88
+atmega88p_isp: MCU_TARGET = atmega88p
+# 2.7V brownout
+atmega88p_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega88p_isp: LFUSE ?= FF
+# 512 byte boot
+atmega88p_isp: EFUSE ?= 04
+atmega88p_isp: isp
+
+#
+# ATmega168p [QFN32]
+#
+atmega168p: TARGET = atmega168p
+atmega168p: MCU_TARGET = atmega168p
+atmega168p: CFLAGS += $(COMMON_OPTIONS)
+atmega168p: AVR_FREQ ?= 16000000L 
+atmega168p: $(PROGRAM)_atmega168p_16MHz.hex
+atmega168p: $(PROGRAM)_atmega168p_16MHz.lst
+
+atmega168p_isp: atmega168p
+atmega168p_isp: TARGET = atmega168p
+# 2.7V brownout
+atmega168p_isp: HFUSE ?= DD
+# Low power xtal (16MHz) 16KCK/14CK+65ms
+atmega168p_isp: LFUSE ?= FF
+# 512 byte boot
+atmega168p_isp: EFUSE ?= 04
+atmega168p_isp: isp
+
+#
+# ATmega32
+#
+atmega32: TARGET = atmega32
+atmega32: MCU_TARGET = atmega32
+atmega32: CFLAGS += $(COMMON_OPTIONS)
+atmega32: AVR_FREQ ?= 11059200L
+atmega32: LDSECTIONS  = -Wl,--section-start=.text=0x7e00 -Wl,--section-start=.version=0x7ffe
+atmega32: $(PROGRAM)_atmega32.hex
+atmega32: $(PROGRAM)_atmega32.lst
+
+atmega32_isp: atmega32
+atmega32_isp: TARGET = atmega32
+atmega32_isp: MCU_TARGET = atmega32
+# No OCD or JTAG, SPIEN, CKOPT (for full swing xtal), Bootsize=512B
+atmega32_isp: HFUSE ?= CE
+# 2.7V brownout, 16MHz Xtal, 16KCK/14CK+65ms
+atmega32_isp: LFUSE ?= BF
+atmega32_isp: isp
+
+
+
+#
+# ATtiny84
+#
+attiny84: TARGET = attiny84
+attiny84: MCU_TARGET = attiny84
+attiny84: CFLAGS += $(COMMON_OPTIONS) -DSOFT_UART -DVIRTUAL_BOOT_PARTITION -Dsave_vect_num=4
+attiny84: LDSECTIONS = -Wl,--section-start=.text=0x1d00 -Wl,--section-start=.version=0x1ffe -Wl,--gc-sections -Wl,--undefined=optiboot_version
+attiny84: $(PROGRAM)_attiny84.hex
+attiny84: $(PROGRAM)_attiny84.lst
+
+
+
+# 1MHz clocked platforms/boards
+#
+# These are capable of 9600 baud
+#
+
+luminet: TARGET = $@
+luminet: CHIP = attiny84
+luminet:
+	$(MAKE) $(CHIP) AVR_FREQ=1000000L LED_START_FLASHES=0 BAUD_RATE=9600
+	mv $(PROGRAM)_$(CHIP).hex $(PROGRAM)_$(TARGET).hex
+	mv $(PROGRAM)_$(CHIP).lst $(PROGRAM)_$(TARGET).lst
+
+luminet_isp: luminet
+luminet_isp: TARGET = luminet
+luminet_isp: MCU_TARGET = attiny84
+# Brownout disabled
+luminet_isp: HFUSE ?= DF
+# 1MHz internal oscillator, slowly rising power
+luminet_isp: LFUSE ?= 62
+# Self-programming enable
+luminet_isp: EFUSE ?= FE
+luminet_isp: isp
+
+

+ 90 - 0
Makefile.isp

@@ -0,0 +1,90 @@
+# Makefile.isp for Optiboot
+# Bill Westfield (WestfW@yahoo.com)  March, 2013
+# $Id$
+#
+# Instructions:
+#
+# This is a "daughter" Makefile that burns the bootloader using a ISP
+# device programmer.  It is designed to inherit assorted variables from
+# the parent optiboot "Makefile"...  Using a daughter makefile makes
+# certain variable manipulations more obvious.
+#
+# To burn bootloader .hex file, invoke the main Makefile using:
+# make diecimila_isp
+# make lilypad_isp
+# make ng_isp
+# etc...
+#
+#
+# Note: inherit paths/etc from parent Makefile.
+#
+#---------------------------------------------------------------------------
+# 
+# * Copyright 2013-2015 by Bill Westfield.  Part of Optiboot.
+# * This software is licensed under version 2 of the Gnu Public Licence.
+# * See optiboot.c for details.
+# 
+#---------------------------------------------------------------------------
+
+# enter the parameters for the avrdude isp tool  -b19200
+#
+
+# Inherit avrdude paths from top-level makefile
+AVRDUDE_ROOT ?= $(GCCROOT)
+AVRDUDE_CONF ?= -C$(TOOLROOT)/avr/etc/avrdude.conf
+
+# These are the parameters for a usb-based STK500v2 programmer.
+# Exact type unknown.  (historical Makefile values.)
+#ISPTOOL	   = stk500v2
+#ISPPORT	   =  usb
+#ISPSPEED   = -b 115200
+#
+#
+# These are parameters for using an Arduino with the ArduinoISP sketch
+#  as the programmer.  On a mac, for a particular Uno as programmer.
+ISPTOOL	?= stk500v1
+ISPPORT	?= /dev/tty.usbserial-FTD61T6Q
+ISPSPEED ?= -b19200
+
+
+
+# Not all chips have EFUSE.
+
+ifdef EFUSE
+EFUSE_CMD= -U efuse:w:0x$(EFUSE):m
+endif
+
+#
+# avrdude commands to erase chip, unlock memory, and program fuses.
+#
+ISPFUSES =	-e -u -U lock:w:0x3f:m $(EFUSE_CMD) \
+	 	-U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
+
+
+#
+# avrdude commands to program the new bootloader, and protect the bootloader
+# space from accidental SPM writes.  Note: "2f" allows boot section to be read
+# by the application, which is different than the arduino default.
+#
+ISPFLASH =	-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x2f:m
+
+# There are certain complicated caused by the fact that the default state
+# of a fuse is a "1" rather than a "0", especially with respect to fuse bits
+# that have not been implemented.  Those would normally not be included, but
+# unimplemented fuses still default to being "1"
+#
+# the efuse should really be 0xf8; since, however, only the lower
+# three bits of that byte are used on the atmega168, avrdude gets
+# confused if you specify 1's for the higher bits, see:
+# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
+#
+# similarly, the lock bits should be 0xff instead of 0x3f (to
+# unlock the bootloader section) and 0xcf instead of 0x2f (to
+# lock it), but since the high two bits of the lock byte are
+# unused, avrdude would get confused.
+
+isp: $(PROGRAM)_$(TARGET).hex
+	$(AVRDUDE_ROOT)avrdude $(AVRDUDE_CONF) -c $(ISPTOOL) \
+              -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
+	$(ISPFUSES) \
+	$(ISPFLASH)

+ 99 - 0
README.TXT

@@ -0,0 +1,99 @@
+This directory contains the Optiboot small bootloader for AVR
+microcontrollers, somewhat modified specifically for the Arduino
+environment.
+
+Optiboot is more fully described here: http://github.com/Optiboot/optiboot
+and is the work of Peter Knight (aka Cathedrow), building on work of Jason P
+Kyle, Spiff, and Ladyada.  More recent maintenance and modifications are by
+Bill Westfield (aka WestfW)
+
+Arduino-specific issues are tracked as part of the Arduino project
+at http://github.com/arduino/Arduino
+
+
+Most of the information in this file is superceeded by the wiki content at
+https://github.com/Optiboot/optiboot/wiki
+
+It's till here "just in case."
+
+------------------------------------------------------------
+
+Building optiboot for Arduino.
+
+Production builds of optiboot for Arduino are done on a Mac in "unix mode"
+using CrossPack-AVR-20100115.  CrossPack tracks WINAVR (for windows), which
+is just a package of avr-gcc and related utilities, so similar builds should
+work on Windows or Linux systems.
+
+One of the Arduino-specific changes is modifications to the makefile to
+allow building optiboot using only the tools installed as part of the
+Arduino environment, or the Arduino source development tree.  All three
+build procedures should yield identical binaries (.hex files) (although
+this may change if compiler versions drift apart between CrossPack and
+the Arduino IDE.)
+
+
+Building Optiboot in the Arduino IDE Install.
+
+Work in the .../hardware/arduino/bootloaders/optiboot/ and use the
+"omake <targets>" command, which just generates a command that uses
+the arduino-included "make" utility with a command like:
+    make OS=windows ENV=arduino <targets>
+or  make OS=macosx ENV=arduino <targets>
+On windows, this assumes you're using the windows command shell.  If
+you're using a cygwin or mingw shell, or have one of those in your
+path, the build will probably break due to slash vs backslash issues.
+On a Mac, if you have the developer tools installed, you can use the
+Apple-supplied version of make.
+The makefile uses relative paths ("../../../tools/" and such) to find
+the programs it needs, so you need to work in the existing optiboot
+directory (or something created at the same "level") for it to work.
+
+
+Building Optiboot in the Arduino Source Development Install.
+
+In this case, there is no special shell script, and you're assumed to
+have "make" installed somewhere in your path.
+Build the Arduino source ("ant build") to unpack the tools into the
+expected directory.
+Work in Arduino/hardware/arduino/bootloaders/optiboot and use
+    make OS=windows ENV=arduinodev <targets>
+or  make OS=macosx ENV=arduinodev <targets>
+
+
+Programming Chips Using the _isp Targets
+
+The CPU targets have corresponding ISP targets that will actuall
+program the bootloader into a chip. "atmega328_isp" for the atmega328,
+for example.  These will set the fuses and lock bits as appropriate as
+well as uploading the bootloader code.
+
+ISP Targets in Version 5.0 and later:
+
+The isp targets are now built using a separate "Makefile.isp" makefile,
+which should make modification easier and more obvious.  This also fixes
+the atmega8_isp target problem mentioned below.  The default
+configuration assumes an ArduinoISP setup, but you will probably need to
+update at least the serial port, since those are different for each
+Arduino board and/or system/
+
+
+ISP Targets in Version 4.6 and earlier:
+
+The older makefiles default to using a USB programmer, but you can use a
+serial programmer like ArduinoISP by changing the appropriate variables
+when you invoke make:
+
+   make ISPTOOL=stk500v1 ISPPORT=/dev/tty.usbserial-A20e1eAN  \
+        ISPSPEED=-b19200 atmega328_isp
+
+The "atmega8_isp" target does not currently work, because the mega8
+doesn't have the "extended" fuse that the generic ISP target wants to
+pass on to avrdude.  You'll need to run avrdude manually.
+
+
+Standard Targets
+
+I've reduced the pre-built and source-version-controlled targets
+(.hex and .lst files included in the git repository) to just the
+three basic 16MHz targets: atmega8, atmega16, atmega328.

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+New optiboot (last version mai 2016)
+New Alexmos software nulled
+

BIN
SimpleBGC_2_40b8.zip


BIN
SimpleBGC_GUI_2_40b8.zip


+ 56 - 0
baudcheck.c

@@ -0,0 +1,56 @@
+/*
+ * baudcheck.c
+ * Mar, 2013 by Bill Westfield (WestfW@yahoo.com)
+ * Exercises in executing arithmetic code on a system that we can't count
+ * on having the usual languages or tools installed.
+ *
+ * This little "C program" is run through the C preprocessor using the same
+ * arguments as our "real" target (which should assure that it gets the
+ * same values for clock speed and desired baud rate), and produces as
+ * output a shell script that can be run through bash, and THAT in turn
+ * writes the desired output...
+ *
+ * Note that the C-style comments are stripped by the C preprocessor.
+ *
+ * Copyright 2013-2015 by Bill Westfield.
+ * This software is licensed under version 2 of the Gnu Public Licence.
+ * See optiboot.c for details.
+ */
+
+/*
+ * First strip any trailing "L" from the defined constants.  To do this
+ * we need to make the constants into shell variables first.
+ */
+bpsx=BAUD_RATE
+bps=${bpsx/L/}
+bps=${bps/U/}
+fcpux=F_CPU
+fcpu=${fcpux/L/}
+fcpu=${fcpu/U/}
+
+// echo f_cpu = $fcpu, baud = $bps
+/*
+ * Compute the divisor
+ */
+BAUD_SETTING=$(( ( ($fcpu + $bps * 4) / (($bps * 8))) - 1 ))
+// echo baud setting = $BAUD_SETTING
+
+/*
+ * Based on the computer divisor, calculate the actual bitrate,
+ * And the error.  Since we're all integers, we have to calculate
+ * the tenths part of the error separately.
+ */
+BAUD_ACTUAL=$(( ($fcpu/(8 * (($BAUD_SETTING)+1))) ))
+BAUD_ERROR=$(( (( 100*($BAUD_ACTUAL - $bps) ) / $bps) ))
+ERR_TS=$(( ((( 1000*($BAUD_ACTUAL - $bps) ) / $bps) - $BAUD_ERROR * 10) ))
+ERR_TENTHS=$(( ERR_TS > 0 ? ERR_TS: -ERR_TS ))
+
+/*
+ * Print a nice message containing the info we've calculated
+ */
+echo BAUD RATE CHECK: Desired: $bps,  Real: $BAUD_ACTUAL, UBRRL = $BAUD_SETTING, Error=$BAUD_ERROR.$ERR_TENTHS\%
+
+
+
+
+

+ 848 - 0
boot.h

@@ -0,0 +1,848 @@
+/* Modified to use out for SPM access
+** Peter Knight, Optiboot project http://optiboot.googlecode.com
+**
+** Todo: Tidy up
+**
+** "_short" routines execute 1 cycle faster and use 1 less word of flash
+** by using "out" instruction instead of "sts".
+**
+** Additional elpm variants that trust the value of RAMPZ
+*/
+
+/* Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007  Eric B. Weddington
+   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: boot.h,v 1.27.2.3 2008/09/30 13:58:48 arcanum Exp $ */
+
+#ifndef _AVR_BOOT_H_
+#define _AVR_BOOT_H_    1
+
+/** \file */
+/** \defgroup avr_boot <avr/boot.h>: Bootloader Support Utilities
+    \code
+    #include <avr/io.h>
+    #include <avr/boot.h>
+    \endcode
+
+    The macros in this module provide a C language interface to the
+    bootloader support functionality of certain AVR processors. These
+    macros are designed to work with all sizes of flash memory.
+
+    Global interrupts are not automatically disabled for these macros. It
+    is left up to the programmer to do this. See the code example below. 
+    Also see the processor datasheet for caveats on having global interrupts 
+    enabled during writing of the Flash.
+
+    \note Not all AVR processors provide bootloader support. See your
+    processor datasheet to see if it provides bootloader support.
+
+    \todo From email with Marek: On smaller devices (all except ATmega64/128),
+    __SPM_REG is in the I/O space, accessible with the shorter "in" and "out"
+    instructions - since the boot loader has a limited size, this could be an
+    important optimization.
+
+    \par API Usage Example
+    The following code shows typical usage of the boot API.
+
+    \code
+    #include <inttypes.h>
+    #include <avr/interrupt.h>
+    #include <avr/pgmspace.h>
+    
+    void boot_program_page (uint32_t page, uint8_t *buf)
+    {
+        uint16_t i;
+        uint8_t sreg;
+
+        // Disable interrupts.
+
+        sreg = SREG;
+        cli();
+    
+        eeprom_busy_wait ();
+
+        boot_page_erase (page);
+        boot_spm_busy_wait ();      // Wait until the memory is erased.
+
+        for (i=0; i<SPM_PAGESIZE; i+=2)
+        {
+            // Set up little-endian word.
+
+            uint16_t w = *buf++;
+            w += (*buf++) << 8;
+        
+            boot_page_fill (page + i, w);
+        }
+
+        boot_page_write (page);     // Store buffer in flash page.
+        boot_spm_busy_wait();       // Wait until the memory is written.
+
+        // Reenable RWW-section again. We need this if we want to jump back
+        // to the application after bootloading.
+
+        boot_rww_enable ();
+
+        // Re-enable interrupts (if they were ever enabled).
+
+        SREG = sreg;
+    }\endcode */
+
+#include <avr/eeprom.h>
+#include <avr/io.h>
+#include <inttypes.h>
+#include <limits.h>
+
+/* Check for SPM Control Register in processor. */
+#if defined (SPMCSR)
+#  define __SPM_REG    SPMCSR
+#elif defined (SPMCR)
+#  define __SPM_REG    SPMCR
+#else
+#  error AVR processor does not provide bootloader support!
+#endif
+
+
+/* Check for SPM Enable bit. */
+#if defined(SPMEN)
+#  define __SPM_ENABLE  SPMEN
+#elif defined(SELFPRGEN)
+#  define __SPM_ENABLE  SELFPRGEN
+#else
+#  error Cannot find SPM Enable bit definition!
+#endif
+
+/** \ingroup avr_boot
+    \def BOOTLOADER_SECTION
+
+    Used to declare a function or variable to be placed into a
+    new section called .bootloader. This section and its contents
+    can then be relocated to any address (such as the bootloader
+    NRWW area) at link-time. */
+
+#define BOOTLOADER_SECTION    __attribute__ ((section (".bootloader")))
+
+/* Create common bit definitions. */
+#ifdef ASB
+#define __COMMON_ASB    ASB
+#else
+#define __COMMON_ASB    RWWSB
+#endif
+
+#ifdef ASRE
+#define __COMMON_ASRE   ASRE
+#else
+#define __COMMON_ASRE   RWWSRE
+#endif
+
+/* Define the bit positions of the Boot Lock Bits. */
+
+#define BLB12           5
+#define BLB11           4
+#define BLB02           3
+#define BLB01           2
+
+/** \ingroup avr_boot
+    \def boot_spm_interrupt_enable()
+    Enable the SPM interrupt. */
+
+#define boot_spm_interrupt_enable()   (__SPM_REG |= (uint8_t)_BV(SPMIE))
+
+/** \ingroup avr_boot
+    \def boot_spm_interrupt_disable()
+    Disable the SPM interrupt. */
+
+#define boot_spm_interrupt_disable()  (__SPM_REG &= (uint8_t)~_BV(SPMIE))
+
+/** \ingroup avr_boot
+    \def boot_is_spm_interrupt()
+    Check if the SPM interrupt is enabled. */
+
+#define boot_is_spm_interrupt()       (__SPM_REG & (uint8_t)_BV(SPMIE))
+
+/** \ingroup avr_boot
+    \def boot_rww_busy()
+    Check if the RWW section is busy. */
+
+#define boot_rww_busy()          (__SPM_REG & (uint8_t)_BV(__COMMON_ASB))
+
+/** \ingroup avr_boot
+    \def boot_spm_busy()
+    Check if the SPM instruction is busy. */
+
+#define boot_spm_busy()               (__SPM_REG & (uint8_t)_BV(__SPM_ENABLE))
+
+/** \ingroup avr_boot
+    \def boot_spm_busy_wait()
+    Wait while the SPM instruction is busy. */
+
+#define boot_spm_busy_wait()          do{}while(boot_spm_busy())
+
+#define __BOOT_PAGE_ERASE         (_BV(__SPM_ENABLE) | _BV(PGERS))
+#define __BOOT_PAGE_WRITE         (_BV(__SPM_ENABLE) | _BV(PGWRT))
+#define __BOOT_PAGE_FILL          _BV(__SPM_ENABLE)
+#define __BOOT_RWW_ENABLE         (_BV(__SPM_ENABLE) | _BV(__COMMON_ASRE))
+#define __BOOT_LOCK_BITS_SET      (_BV(__SPM_ENABLE) | _BV(BLBSET))
+
+#define __boot_page_fill_short(address, data)   \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw  r0, %3\n\t"                       \
+        "out %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        "clr  r1\n\t"                            \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
+          "z" ((uint16_t)address),               \
+          "r" ((uint16_t)data)                   \
+        : "r0"                                   \
+    );                                           \
+}))
+
+#define __boot_page_fill_normal(address, data)   \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw  r0, %3\n\t"                       \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        "clr  r1\n\t"                            \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
+          "z" ((uint16_t)address),               \
+          "r" ((uint16_t)data)                   \
+        : "r0"                                   \
+    );                                           \
+}))
+
+#define __boot_page_fill_alternate(address, data)\
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw  r0, %3\n\t"                       \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        ".word 0xffff\n\t"                       \
+        "nop\n\t"                                \
+        "clr  r1\n\t"                            \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
+          "z" ((uint16_t)address),               \
+          "r" ((uint16_t)data)                   \
+        : "r0"                                   \
+    );                                           \
+}))
+
+#define __boot_page_fill_extended(address, data) \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw  r0, %4\n\t"                       \
+        "movw r30, %A3\n\t"                      \
+        "sts %1, %C3\n\t"                        \
+        "sts %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        "clr  r1\n\t"                            \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
+          "r" ((uint32_t)address),               \
+          "r" ((uint16_t)data)                   \
+        : "r0", "r30", "r31"                     \
+    );                                           \
+}))
+
+#define __boot_page_fill_extended_short(address, data) \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw  r0, %4\n\t"                       \
+        "movw r30, %A3\n\t"                      \
+        "out %1, %C3\n\t"                        \
+        "out %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        "clr  r1\n\t"                            \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_FILL),       \
+          "r" ((uint32_t)address),               \
+          "r" ((uint16_t)data)                   \
+        : "r0", "r30", "r31"                     \
+    );                                           \
+}))
+
+#define __boot_page_erase_short(address)        \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "out %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+
+#define __boot_page_erase_normal(address)        \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+#define __boot_page_erase_alternate(address)     \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        ".word 0xffff\n\t"                       \
+        "nop\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+#define __boot_page_erase_extended(address)      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw r30, %A3\n\t"                      \
+        "sts  %1, %C3\n\t"                       \
+        "sts %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
+          "r" ((uint32_t)address)                \
+        : "r30", "r31"                           \
+    );                                           \
+}))
+#define __boot_page_erase_extended_short(address)      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw r30, %A3\n\t"                      \
+        "out  %1, %C3\n\t"                       \
+        "out %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_ERASE),      \
+          "r" ((uint32_t)address)                \
+        : "r30", "r31"                           \
+    );                                           \
+}))
+
+#define __boot_page_write_short(address)        \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "out %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+#define __boot_page_write_normal(address)        \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+#define __boot_page_write_alternate(address)     \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        ".word 0xffff\n\t"                       \
+        "nop\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
+          "z" ((uint16_t)address)                \
+    );                                           \
+}))
+
+#define __boot_page_write_extended(address)      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw r30, %A3\n\t"                      \
+        "sts %1, %C3\n\t"                        \
+        "sts %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "i" (_SFR_MEM_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
+          "r" ((uint32_t)address)                \
+        : "r30", "r31"                           \
+    );                                           \
+}))
+#define __boot_page_write_extended_short(address)      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "movw r30, %A3\n\t"                      \
+        "out %1, %C3\n\t"                        \
+        "out %0, %2\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "i" (_SFR_IO_ADDR(RAMPZ)),            \
+          "r" ((uint8_t)__BOOT_PAGE_WRITE),      \
+          "r" ((uint32_t)address)                \
+        : "r30", "r31"                           \
+    );                                           \
+}))
+
+#define __boot_rww_enable_short()                      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "out %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
+    );                                           \
+}))
+
+#define __boot_rww_enable()                      \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
+    );                                           \
+}))
+
+#define __boot_rww_enable_alternate()            \
+(__extension__({                                 \
+    __asm__ __volatile__                         \
+    (                                            \
+        "sts %0, %1\n\t"                         \
+        "spm\n\t"                                \
+        ".word 0xffff\n\t"                       \
+        "nop\n\t"                                \
+        :                                        \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t)__BOOT_RWW_ENABLE)       \
+    );                                           \
+}))
+
+/* From the mega16/mega128 data sheets (maybe others):
+
+     Bits by SPM To set the Boot Loader Lock bits, write the desired data to
+     R0, write "X0001001" to SPMCR and execute SPM within four clock cycles
+     after writing SPMCR. The only accessible Lock bits are the Boot Lock bits
+     that may prevent the Application and Boot Loader section from any
+     software update by the MCU.
+
+     If bits 5..2 in R0 are cleared (zero), the corresponding Boot Lock bit
+     will be programmed if an SPM instruction is executed within four cycles
+     after BLBSET and SPMEN (or SELFPRGEN) are set in SPMCR. The Z-pointer is 
+     don't care during this operation, but for future compatibility it is 
+     recommended to load the Z-pointer with $0001 (same as used for reading the 
+     Lock bits). For future compatibility It is also recommended to set bits 7, 
+     6, 1, and 0 in R0 to 1 when writing the Lock bits. When programming the 
+     Lock bits the entire Flash can be read during the operation. */
+
+#define __boot_lock_bits_set_short(lock_bits)                    \
+(__extension__({                                           \
+    uint8_t value = (uint8_t)(~(lock_bits));               \
+    __asm__ __volatile__                                   \
+    (                                                      \
+        "ldi r30, 1\n\t"                                   \
+        "ldi r31, 0\n\t"                                   \
+        "mov r0, %2\n\t"                                   \
+        "out %0, %1\n\t"                                   \
+        "spm\n\t"                                          \
+        :                                                  \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),                  \
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
+          "r" (value)                                      \
+        : "r0", "r30", "r31"                               \
+    );                                                     \
+}))
+
+#define __boot_lock_bits_set(lock_bits)                    \
+(__extension__({                                           \
+    uint8_t value = (uint8_t)(~(lock_bits));               \
+    __asm__ __volatile__                                   \
+    (                                                      \
+        "ldi r30, 1\n\t"                                   \
+        "ldi r31, 0\n\t"                                   \
+        "mov r0, %2\n\t"                                   \
+        "sts %0, %1\n\t"                                   \
+        "spm\n\t"                                          \
+        :                                                  \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
+          "r" (value)                                      \
+        : "r0", "r30", "r31"                               \
+    );                                                     \
+}))
+
+#define __boot_lock_bits_set_alternate(lock_bits)          \
+(__extension__({                                           \
+    uint8_t value = (uint8_t)(~(lock_bits));               \
+    __asm__ __volatile__                                   \
+    (                                                      \
+        "ldi r30, 1\n\t"                                   \
+        "ldi r31, 0\n\t"                                   \
+        "mov r0, %2\n\t"                                   \
+        "sts %0, %1\n\t"                                   \
+        "spm\n\t"                                          \
+        ".word 0xffff\n\t"                                 \
+        "nop\n\t"                                          \
+        :                                                  \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
+          "r" (value)                                      \
+        : "r0", "r30", "r31"                               \
+    );                                                     \
+}))
+
+/*
+   Reading lock and fuse bits:
+
+     Similarly to writing the lock bits above, set BLBSET and SPMEN (or 
+     SELFPRGEN) bits in __SPMREG, and then (within four clock cycles) issue an 
+     LPM instruction.
+
+     Z address:       contents:
+     0x0000           low fuse bits
+     0x0001           lock bits
+     0x0002           extended fuse bits
+     0x0003           high fuse bits
+
+     Sounds confusing, doesn't it?
+
+     Unlike the macros in pgmspace.h, no need to care for non-enhanced
+     cores here as these old cores do not provide SPM support anyway.
+ */
+
+/** \ingroup avr_boot
+    \def GET_LOW_FUSE_BITS
+    address to read the low fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_LOW_FUSE_BITS           (0x0000)
+/** \ingroup avr_boot
+    \def GET_LOCK_BITS
+    address to read the lock bits, using boot_lock_fuse_bits_get
+ */
+#define GET_LOCK_BITS               (0x0001)
+/** \ingroup avr_boot
+    \def GET_EXTENDED_FUSE_BITS
+    address to read the extended fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_EXTENDED_FUSE_BITS      (0x0002)
+/** \ingroup avr_boot
+    \def GET_HIGH_FUSE_BITS
+    address to read the high fuse bits, using boot_lock_fuse_bits_get
+ */
+#define GET_HIGH_FUSE_BITS          (0x0003)
+
+/** \ingroup avr_boot
+    \def boot_lock_fuse_bits_get(address)
+
+    Read the lock or fuse bits at \c address.
+
+    Parameter \c address can be any of GET_LOW_FUSE_BITS,
+    GET_LOCK_BITS, GET_EXTENDED_FUSE_BITS, or GET_HIGH_FUSE_BITS.
+
+    \note The lock and fuse bits returned are the physical values,
+    i.e. a bit returned as 0 means the corresponding fuse or lock bit
+    is programmed.
+ */
+#define boot_lock_fuse_bits_get_short(address)                   \
+(__extension__({                                           \
+    uint8_t __result;                                      \
+    __asm__ __volatile__                                   \
+    (                                                      \
+        "ldi r30, %3\n\t"                                  \
+        "ldi r31, 0\n\t"                                   \
+        "out %1, %2\n\t"                                   \
+        "lpm %0, Z\n\t"                                    \
+        : "=r" (__result)                                  \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),                  \
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
+          "M" (address)                                    \
+        : "r0", "r30", "r31"                               \
+    );                                                     \
+    __result;                                              \
+}))
+
+#define boot_lock_fuse_bits_get(address)                   \
+(__extension__({                                           \
+    uint8_t __result;                                      \
+    __asm__ __volatile__                                   \
+    (                                                      \
+        "ldi r30, %3\n\t"                                  \
+        "ldi r31, 0\n\t"                                   \
+        "sts %1, %2\n\t"                                   \
+        "lpm %0, Z\n\t"                                    \
+        : "=r" (__result)                                  \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),                  \
+          "r" ((uint8_t)__BOOT_LOCK_BITS_SET),             \
+          "M" (address)                                    \
+        : "r0", "r30", "r31"                               \
+    );                                                     \
+    __result;                                              \
+}))
+
+/** \ingroup avr_boot
+    \def boot_signature_byte_get(address)
+
+    Read the Signature Row byte at \c address.  For some MCU types,
+    this function can also retrieve the factory-stored oscillator
+    calibration bytes.
+
+    Parameter \c address can be 0-0x1f as documented by the datasheet.
+    \note The values are MCU type dependent.
+*/
+
+#define __BOOT_SIGROW_READ (_BV(__SPM_ENABLE) | _BV(SIGRD))
+
+#define boot_signature_byte_get_short(addr) \
+(__extension__({                      \
+      uint16_t __addr16 = (uint16_t)(addr);     \
+      uint8_t __result;                         \
+      __asm__ __volatile__                      \
+      (                                         \
+        "out %1, %2\n\t"                        \
+        "lpm %0, Z" "\n\t"                      \
+        : "=r" (__result)                       \
+        : "i" (_SFR_IO_ADDR(__SPM_REG)),        \
+          "r" ((uint8_t) __BOOT_SIGROW_READ),   \
+          "z" (__addr16)                        \
+      );                                        \
+      __result;                                 \
+}))
+
+#define boot_signature_byte_get(addr) \
+(__extension__({                      \
+      uint16_t __addr16 = (uint16_t)(addr);     \
+      uint8_t __result;                         \
+      __asm__ __volatile__                      \
+      (                                         \
+        "sts %1, %2\n\t"                        \
+        "lpm %0, Z" "\n\t"                      \
+        : "=r" (__result)                       \
+        : "i" (_SFR_MEM_ADDR(__SPM_REG)),       \
+          "r" ((uint8_t) __BOOT_SIGROW_READ),   \
+          "z" (__addr16)                        \
+      );                                        \
+      __result;                                 \
+}))
+
+/** \ingroup avr_boot
+    \def boot_page_fill(address, data)
+
+    Fill the bootloader temporary page buffer for flash 
+    address with data word. 
+
+    \note The address is a byte address. The data is a word. The AVR 
+    writes data to the buffer a word at a time, but addresses the buffer
+    per byte! So, increment your address by 2 between calls, and send 2
+    data bytes in a word format! The LSB of the data is written to the lower 
+    address; the MSB of the data is written to the higher address.*/
+
+/** \ingroup avr_boot
+    \def boot_page_erase(address)
+
+    Erase the flash page that contains address.
+
+    \note address is a byte address in flash, not a word address. */
+
+/** \ingroup avr_boot
+    \def boot_page_write(address)
+
+    Write the bootloader temporary page buffer 
+    to flash page that contains address.
+    
+    \note address is a byte address in flash, not a word address. */
+
+/** \ingroup avr_boot
+    \def boot_rww_enable()
+
+    Enable the Read-While-Write memory section. */
+
+/** \ingroup avr_boot
+    \def boot_lock_bits_set(lock_bits)
+
+    Set the bootloader lock bits.
+
+    \param lock_bits A mask of which Boot Loader Lock Bits to set.
+
+    \note In this context, a 'set bit' will be written to a zero value.
+    Note also that only BLBxx bits can be programmed by this command.
+
+    For example, to disallow the SPM instruction from writing to the Boot
+    Loader memory section of flash, you would use this macro as such:
+
+    \code
+    boot_lock_bits_set (_BV (BLB11));
+    \endcode
+
+    \note Like any lock bits, the Boot Loader Lock Bits, once set,
+    cannot be cleared again except by a chip erase which will in turn
+    also erase the boot loader itself. */
+
+/* Normal versions of the macros use 16-bit addresses.
+   Extended versions of the macros use 32-bit addresses.
+   Alternate versions of the macros use 16-bit addresses and require special
+   instruction sequences after LPM.
+
+   FLASHEND is defined in the ioXXXX.h file.
+   USHRT_MAX is defined in <limits.h>. */ 
+
+#if defined(__AVR_ATmega161__) || defined(__AVR_ATmega163__) \
+    || defined(__AVR_ATmega323__)
+
+/* Alternate: ATmega161/163/323 and 16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_alternate(address, data)
+#define boot_page_erase(address)      __boot_page_erase_alternate(address)
+#define boot_page_write(address)      __boot_page_write_alternate(address)
+#define boot_rww_enable()             __boot_rww_enable_alternate()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_alternate(lock_bits)
+
+#elif (FLASHEND > USHRT_MAX)
+
+/* Extended: >16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_extended_short(address, data)
+#define boot_page_erase(address)      __boot_page_erase_extended_short(address)
+#define boot_page_write(address)      __boot_page_write_extended_short(address)
+#define boot_rww_enable()             __boot_rww_enable_short()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
+
+#else
+
+/* Normal: 16 bit address */
+#define boot_page_fill(address, data) __boot_page_fill_short(address, data)
+#define boot_page_erase(address)      __boot_page_erase_short(address)
+#define boot_page_write(address)      __boot_page_write_short(address)
+#define boot_rww_enable()             __boot_rww_enable_short()
+#define boot_lock_bits_set(lock_bits) __boot_lock_bits_set_short(lock_bits)
+
+#endif
+
+/** \ingroup avr_boot
+
+    Same as boot_page_fill() except it waits for eeprom and spm operations to
+    complete before filling the page. */
+
+#define boot_page_fill_safe(address, data) \
+do { \
+    boot_spm_busy_wait();                       \
+    eeprom_busy_wait();                         \
+    boot_page_fill(address, data);              \
+} while (0)
+
+/** \ingroup avr_boot
+
+    Same as boot_page_erase() except it waits for eeprom and spm operations to
+    complete before erasing the page. */
+
+#define boot_page_erase_safe(address) \
+do { \
+    boot_spm_busy_wait();                       \
+    eeprom_busy_wait();                         \
+    boot_page_erase (address);                  \
+} while (0)
+
+/** \ingroup avr_boot
+
+    Same as boot_page_write() except it waits for eeprom and spm operations to
+    complete before writing the page. */
+
+#define boot_page_write_safe(address) \
+do { \
+    boot_spm_busy_wait();                       \
+    eeprom_busy_wait();                         \
+    boot_page_write (address);                  \
+} while (0)
+
+/** \ingroup avr_boot
+
+    Same as boot_rww_enable() except waits for eeprom and spm operations to
+    complete before enabling the RWW mameory. */
+
+#define boot_rww_enable_safe() \
+do { \
+    boot_spm_busy_wait();                       \
+    eeprom_busy_wait();                         \
+    boot_rww_enable();                          \
+} while (0)
+
+/** \ingroup avr_boot
+
+    Same as boot_lock_bits_set() except waits for eeprom and spm operations to
+    complete before setting the lock bits. */
+
+#define boot_lock_bits_set_safe(lock_bits) \
+do { \
+    boot_spm_busy_wait();                       \
+    eeprom_busy_wait();                         \
+    boot_lock_bits_set (lock_bits);             \
+} while (0)
+
+#endif /* _AVR_BOOT_H_ */

+ 60 - 0
build.sh

@@ -0,0 +1,60 @@
+#!/bin/bash
+export VERSION=1
+export REV=07-05-2016
+set -e
+set +x
+ESC=$(echo -en \\0033)
+BOLD="$ESC[1m"
+OFF="$ESC[0m"
+
+bold() {
+    echo "$BOLD$1$OFF"
+}
+
+fail() {
+    bold "$@"
+    exit 1
+}
+
+clean() { # Clean environement 
+make clean
+#rm SimpleBGC_2_40b8+bootloader.zip
+}
+
+bootloader() { # Build bootloader only
+make MCU=atmega328p LED_START_FLASHES=3 BAUD_RATE=115200L LED_DATA_FLASH=1 atmega328
+}
+
+fusion() { # Build bootloader and fusion with SimpleBGC_2.40
+unzip SimpleBGC_2_40b8.zip
+srec_cat SimpleBGC_2_40b8.hex -intel optiboot_atmega328.hex -intel -o SimpleBGC_2_40b8+bootloader.hex -intel
+zip SimpleBGC_2_40b8+bootloader.zip SimpleBGC_2_40b8+bootloader.hex
+}
+
+flashboot() { # Build and flash bootloader only
+avrdude -c usbasp -p atmega328p -b19200 -e -u -U lock:w:0x3f:m -U efuse:w:0x05:m -U hfuse:w:0xDC:m -U lfuse:w:0xFF:m -U flash:w:optiboot_atmega328.hex -U lock:w:0x3f:m
+}
+
+flashall() { # Build fusion SimpleBGC and flash
+avrdude -c usbasp -p atmega328p -b19200 -e -u -U lock:w:0x3f:m -U efuse:w:0x05:m -U hfuse:w:0xDC:m -U lfuse:w:0xFF:m -U flash:w:SimpleBGC_2_40b8+bootloader.hex -U lock:w:0x3f:m
+}
+
+cd "$SRC_DIR"
+case "$1" in
+    clean)    clean;;
+    bootloader) clean ; bootloader ;;
+    fusion)     clean ; bootloader ; fusion ;;
+    flashboot)  clean ; bootloader ; flashboot ;;
+    flashfusion) clean; bootloader ; fusion ; flashall ;;
+    *)
+        echo >&2 "${BOLD}Mosbootloader v:$VERSION rev:$REV"
+	echo >&2 "${BOLD}Usage: $0 (clean | bootloader | fusion | flashboot | flashfusion)$OFF"
+        echo >&2
+        echo >&2 "Build actions:"
+        grep "() { #" $0 | grep -v grep | sort | sed -e "s:^:  :" -e "s:() { #:  @:" | while read i; do
+            echo "   " $(eval "echo $i") | tr @ \\t
+        done
+        exit 1
+        ;;
+esac
+

+ 32 - 0
makeall

@@ -0,0 +1,32 @@
+#!/bin/bash
+make clean
+#
+#  buildable platforms of somewhat questionable support level
+make lilypad
+make pro8
+make pro16
+make pro20
+make atmega328_pro8
+make sanguino
+make mega1280
+make luminet
+make diecimila
+make bobuino
+make wildfirev2
+make atmega1284
+make atmega32
+make atmega88
+make atmega168p
+
+#
+# Atmel development board targets
+make xplained168pb
+make xplained328p
+make xplained328pb
+
+#
+# The "big three" standard bootloaders.
+# These need to be built AFTER the platforms, or they'll get renamed
+make atmega8
+make atmega168
+make atmega328

+ 9 - 0
omake

@@ -0,0 +1,9 @@
+#%/bin/bash
+if [ -d ../../../tools ]; then
+  mypath=../../../tools/avr/bin
+else
+ mypath=../../../../tools/avr/bin
+fi
+
+echo $mypath/make OS=macosx ENV=arduino $*
+$mypath/make OS=macosx ENV=arduino $*

+ 1 - 0
omake.bat

@@ -0,0 +1 @@
+..\..\..\tools\avr\utils\bin\make OS=windows ENV=arduino %*

+ 963 - 0
optiboot.c

@@ -0,0 +1,963 @@
+#define FUNC_READ 1
+#define FUNC_WRITE 1
+/**********************************************************/
+/* Optiboot bootloader for Arduino                        */
+/*                                                        */
+/* http://optiboot.googlecode.com                         */
+/*                                                        */
+/* Arduino-maintained version : See README.TXT            */
+/* http://code.google.com/p/arduino/                      */
+/*  It is the intent that changes not relevant to the     */
+/*  Arduino production envionment get moved from the      */
+/*  optiboot project to the arduino project in "lumps."   */
+/*                                                        */
+/* Heavily optimised bootloader that is faster and        */
+/* smaller than the Arduino standard bootloader           */
+/*                                                        */
+/* Enhancements:                                          */
+/*   Fits in 512 bytes, saving 1.5K of code space         */
+/*   Higher baud rate speeds up programming               */
+/*   Written almost entirely in C                         */
+/*   Customisable timeout with accurate timeconstant      */
+/*   Optional virtual UART. No hardware UART required.    */
+/*   Optional virtual boot partition for devices without. */
+/*                                                        */
+/* What you lose:                                         */
+/*   Implements a skeleton STK500 protocol which is       */
+/*     missing several features including EEPROM          */
+/*     programming and non-page-aligned writes            */
+/*   High baud rate breaks compatibility with standard    */
+/*     Arduino flash settings                             */
+/*                                                        */
+/* Fully supported:                                       */
+/*   ATmega168 based devices  (Diecimila etc)             */
+/*   ATmega328P based devices (Duemilanove etc)           */
+/*                                                        */
+/* Beta test (believed working.)                          */
+/*   ATmega8 based devices (Arduino legacy)               */
+/*   ATmega328 non-picopower devices                      */
+/*   ATmega644P based devices (Sanguino)                  */
+/*   ATmega1284P based devices                            */
+/*   ATmega1280 based devices (Arduino Mega)              */
+/*                                                        */
+/* Alpha test                                             */
+/*   ATmega32                                             */
+/*                                                        */
+/* Work in progress:                                      */
+/*   ATtiny84 based devices (Luminet)                     */
+/*                                                        */
+/* Does not support:                                      */
+/*   USB based devices (eg. Teensy, Leonardo)             */
+/*                                                        */
+/* Assumptions:                                           */
+/*   The code makes several assumptions that reduce the   */
+/*   code size. They are all true after a hardware reset, */
+/*   but may not be true if the bootloader is called by   */
+/*   other means or on other hardware.                    */
+/*     No interrupts can occur                            */
+/*     UART and Timer 1 are set to their reset state      */
+/*     SP points to RAMEND                                */
+/*                                                        */
+/* Code builds on code, libraries and optimisations from: */
+/*   stk500boot.c          by Jason P. Kyle               */
+/*   Arduino bootloader    http://arduino.cc              */
+/*   Spiff's 1K bootloader http://spiffie.org/know/arduino_1k_bootloader/bootloader.shtml */
+/*   avr-libc project      http://nongnu.org/avr-libc     */
+/*   Adaboot               http://www.ladyada.net/library/arduino/bootloader.html */
+/*   AVR305                Atmel Application Note         */
+/*                                                        */
+
+/* Copyright 2013-2015 by Bill Westfield.                 */
+/* Copyright 2010 by Peter Knight.                        */
+/*                                                        */
+/* This program is free software; you can redistribute it */
+/* and/or modify it under the terms of the GNU General    */
+/* Public License as published by the Free Software       */
+/* Foundation; either version 2 of the License, or        */
+/* (at your option) any later version.                    */
+/*                                                        */
+/* This program is distributed in the hope that it will   */
+/* be useful, but WITHOUT ANY WARRANTY; without even the  */
+/* implied warranty of MERCHANTABILITY or FITNESS FOR A   */
+/* PARTICULAR PURPOSE.  See the GNU General Public        */
+/* License for more details.                              */
+/*                                                        */
+/* You should have received a copy of the GNU General     */
+/* Public License along with this program; if not, write  */
+/* to the Free Software Foundation, Inc.,                 */
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
+/*                                                        */
+/* Licence can be viewed at                               */
+/* http://www.fsf.org/licenses/gpl.txt                    */
+/*                                                        */
+/**********************************************************/
+
+
+/**********************************************************/
+/*                                                        */
+/* Optional defines:                                      */
+/*                                                        */
+/**********************************************************/
+/*                                                        */
+/* BIGBOOT:                                              */
+/* Build a 1k bootloader, not 512 bytes. This turns on    */
+/* extra functionality.                                   */
+/*                                                        */
+/* BAUD_RATE:                                             */
+/* Set bootloader baud rate.                              */
+/*                                                        */
+/* SOFT_UART:                                             */
+/* Use AVR305 soft-UART instead of hardware UART.         */
+/*                                                        */
+/* LED_START_FLASHES:                                     */
+/* Number of LED flashes on bootup.                       */
+/*                                                        */
+/* LED_DATA_FLASH:                                        */
+/* Flash LED when transferring data. For boards without   */
+/* TX or RX LEDs, or for people who like blinky lights.   */
+/*                                                        */
+/* SUPPORT_EEPROM:                                        */
+/* Support reading and writing from EEPROM. This is not   */
+/* used by Arduino, so off by default.                    */
+/*                                                        */
+/* TIMEOUT_MS:                                            */
+/* Bootloader timeout period, in milliseconds.            */
+/* 500,1000,2000,4000,8000 supported.                     */
+/*                                                        */
+/* UART:                                                  */
+/* UART number (0..n) for devices with more than          */
+/* one hardware uart (644P, 1284P, etc)                   */
+/*                                                        */
+/**********************************************************/
+
+/**********************************************************/
+/* Version Numbers!                                       */
+/*                                                        */
+/* Arduino Optiboot now includes this Version number in   */
+/* the source and object code.                            */
+/*                                                        */
+/* Version 3 was released as zip from the optiboot        */
+/*  repository and was distributed with Arduino 0022.     */
+/* Version 4 starts with the arduino repository commit    */
+/*  that brought the arduino repository up-to-date with   */
+/*  the optiboot source tree changes since v3.            */
+/* Version 5 was created at the time of the new Makefile  */
+/*  structure (Mar, 2013), even though no binaries changed*/
+/* It would be good if versions implemented outside the   */
+/*  official repository used an out-of-seqeunce version   */
+/*  number (like 104.6 if based on based on 4.5) to       */
+/*  prevent collisions.                                   */
+/*                                                        */
+/**********************************************************/
+
+/**********************************************************/
+/* Edit History:					  */
+/*							  */
+/* Aug 2014						  */
+/* 6.2 WestfW: make size of length variables dependent    */
+/*              on the SPM_PAGESIZE.  This saves space    */
+/*              on the chips where it's most important.   */
+/* 6.1 WestfW: Fix OPTIBOOT_CUSTOMVER (send it!)	  */
+/*             Make no-wait mod less picky about	  */
+/*               skipping the bootloader.		  */
+/*             Remove some dead code			  */
+/* Jun 2014						  */
+/* 6.0 WestfW: Modularize memory read/write functions	  */
+/*             Remove serial/flash overlap		  */
+/*              (and all references to NRWWSTART/etc)	  */
+/*             Correctly handle pagesize > 255bytes       */
+/*             Add EEPROM support in BIGBOOT (1284)       */
+/*             EEPROM write on small chips now causes err */
+/*             Split Makefile into smaller pieces         */
+/*             Add Wicked devices Wildfire		  */
+/*	       Move UART=n conditionals into pin_defs.h   */
+/*	       Remove LUDICOUS_SPEED option		  */
+/*	       Replace inline assembler for .version      */
+/*              and add OPTIBOOT_CUSTOMVER for user code  */
+/*             Fix LED value for Bobuino (Makefile)       */
+/*             Make all functions explicitly inline or    */
+/*              noinline, so we fit when using gcc4.8     */
+/*             Change optimization options for gcc4.8	  */
+/*             Make ENV=arduino work in 1.5.x trees.	  */
+/* May 2014                                               */
+/* 5.0 WestfW: Add support for 1Mbps UART                 */
+/* Mar 2013                                               */
+/* 5.0 WestfW: Major Makefile restructuring.              */
+/*             See Makefile and pin_defs.h                */
+/*             (no binary changes)                        */
+/*                                                        */
+/* 4.6 WestfW/Pito: Add ATmega32 support                  */
+/* 4.6 WestfW/radoni: Don't set LED_PIN as an output if   */
+/*                    not used. (LED_START_FLASHES = 0)   */
+/* Jan 2013						  */
+/* 4.6 WestfW/dkinzer: use autoincrement lpm for read     */
+/* 4.6 WestfW/dkinzer: pass reset cause to app in R2      */
+/* Mar 2012                                               */
+/* 4.5 WestfW: add infrastructure for non-zero UARTS.     */
+/* 4.5 WestfW: fix SIGNATURE_2 for m644 (bad in avr-libc) */
+/* Jan 2012:                                              */
+/* 4.5 WestfW: fix NRWW value for m1284.                  */
+/* 4.4 WestfW: use attribute OS_main instead of naked for */
+/*             main().  This allows optimizations that we */
+/*             count on, which are prohibited in naked    */
+/*             functions due to PR42240.  (keeps us less  */
+/*             than 512 bytes when compiler is gcc4.5     */
+/*             (code from 4.3.2 remains the same.)        */
+/* 4.4 WestfW and Maniacbug:  Add m1284 support.  This    */
+/*             does not change the 328 binary, so the     */
+/*             version number didn't change either. (?)   */
+/* June 2011:                                             */
+/* 4.4 WestfW: remove automatic soft_uart detect (didn't  */
+/*             know what it was doing or why.)  Added a   */
+/*             check of the calculated BRG value instead. */
+/*             Version stays 4.4; existing binaries are   */
+/*             not changed.                               */
+/* 4.4 WestfW: add initialization of address to keep      */
+/*             the compiler happy.  Change SC'ed targets. */
+/*             Return the SW version via READ PARAM       */
+/* 4.3 WestfW: catch framing errors in getch(), so that   */
+/*             AVRISP works without HW kludges.           */
+/*  http://code.google.com/p/arduino/issues/detail?id=368n*/
+/* 4.2 WestfW: reduce code size, fix timeouts, change     */
+/*             verifySpace to use WDT instead of appstart */
+/* 4.1 WestfW: put version number in binary.		  */
+/**********************************************************/
+
+#define OPTIBOOT_MAJVER 6
+#define OPTIBOOT_MINVER 2
+
+/*
+ * OPTIBOOT_CUSTOMVER should be defined (by the makefile) for custom edits
+ * of optiboot.  That way you don't wind up with very different code that
+ * matches the version number of a "released" optiboot.
+ */
+
+#if !defined(OPTIBOOT_CUSTOMVER)
+#define OPTIBOOT_CUSTOMVER 0
+#endif
+
+unsigned const int __attribute__((section(".version"))) 
+optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
+
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/eeprom.h>
+
+/*
+ * Note that we use our own version of "boot.h"
+ * <avr/boot.h> uses sts instructions, but this version uses out instructions
+ * This saves cycles and program memory.  Sorry for the name overlap.
+ */
+#include "boot.h"
+
+
+// We don't use <avr/wdt.h> as those routines have interrupt overhead we don't need.
+
+/*
+ * pin_defs.h
+ * This contains most of the rather ugly defines that implement our
+ * ability to use UART=n and LED=D3, and some avr family bit name differences.
+ */
+#include "pin_defs.h"
+
+/*
+ * stk500.h contains the constant definitions for the stk500v1 comm protocol
+ */
+#include "stk500.h"
+
+#ifndef LED_START_FLASHES
+#define LED_START_FLASHES 0
+#endif
+
+/* set the UART baud rate defaults */
+#ifndef BAUD_RATE
+#if F_CPU >= 8000000L
+#define BAUD_RATE   115200L // Highest rate Avrdude win32 will support
+#elif F_CPU >= 1000000L
+#define BAUD_RATE   9600L   // 19200 also supported, but with significant error
+#elif F_CPU >= 128000L
+#define BAUD_RATE   4800L   // Good for 128kHz internal RC
+#else
+#define BAUD_RATE 1200L     // Good even at 32768Hz
+#endif
+#endif
+
+#ifndef UART
+#define UART 0
+#endif
+
+#define BAUD_SETTING (( (F_CPU + BAUD_RATE * 4L) / ((BAUD_RATE * 8L))) - 1 )
+#define BAUD_ACTUAL (F_CPU/(8 * ((BAUD_SETTING)+1)))
+#if BAUD_ACTUAL <= BAUD_RATE
+  #define BAUD_ERROR (( 100*(BAUD_RATE - BAUD_ACTUAL) ) / BAUD_RATE)
+  #if BAUD_ERROR >= 5
+    #error BAUD_RATE error greater than -5%
+  #elif BAUD_ERROR >= 2
+    #warning BAUD_RATE error greater than -2%
+  #endif
+#else
+  #define BAUD_ERROR (( 100*(BAUD_ACTUAL - BAUD_RATE) ) / BAUD_RATE)
+  #if BAUD_ERROR >= 5
+    #error BAUD_RATE error greater than 5%
+  #elif BAUD_ERROR >= 2
+    #warning BAUD_RATE error greater than 2%
+  #endif
+#endif
+
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 > 250
+#error Unachievable baud rate (too slow) BAUD_RATE 
+#endif // baud rate slow check
+#if (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 < 3
+#if BAUD_ERROR != 0 // permit high bitrates (ie 1Mbps@16MHz) if error is zero
+#error Unachievable baud rate (too fast) BAUD_RATE 
+#endif
+#endif // baud rate fastn check
+
+/* Watchdog settings */
+#define WATCHDOG_OFF    (0)
+#define WATCHDOG_16MS   (_BV(WDE))
+#define WATCHDOG_32MS   (_BV(WDP0) | _BV(WDE))
+#define WATCHDOG_64MS   (_BV(WDP1) | _BV(WDE))
+#define WATCHDOG_125MS  (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_250MS  (_BV(WDP2) | _BV(WDE))
+#define WATCHDOG_500MS  (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_1S     (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
+#define WATCHDOG_2S     (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#ifndef __AVR_ATmega8__
+#define WATCHDOG_4S     (_BV(WDP3) | _BV(WDE))
+#define WATCHDOG_8S     (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
+#endif
+
+
+/*
+ * We can never load flash with more than 1 page at a time, so we can save
+ * some code space on parts with smaller pagesize by using a smaller int.
+ */
+#if SPM_PAGESIZE > 255
+typedef uint16_t pagelen_t ;
+#define GETLENGTH(len) len = getch()<<8; len |= getch()
+#else
+typedef uint8_t pagelen_t;
+#define GETLENGTH(len) (void) getch() /* skip high byte */; len = getch()
+#endif
+
+
+/* Function Prototypes
+ * The main() function is in init9, which removes the interrupt vector table
+ * we don't need. It is also 'OS_main', which means the compiler does not
+ * generate any entry or exit code itself (but unlike 'naked', it doesn't
+ * supress some compile-time options we want.)
+ */
+
+int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9")));
+
+void __attribute__((noinline)) putch(char);
+uint8_t __attribute__((noinline)) getch(void);
+void __attribute__((noinline)) verifySpace();
+void __attribute__((noinline)) watchdogConfig(uint8_t x);
+
+static inline void getNch(uint8_t);
+static inline void flash_led(uint8_t);
+static inline void watchdogReset();
+static inline void writebuffer(int8_t memtype, uint8_t *mybuff,
+			       uint16_t address, pagelen_t len);
+static inline void read_mem(uint8_t memtype,
+			    uint16_t address, pagelen_t len);
+
+#ifdef SOFT_UART
+void uartDelay() __attribute__ ((naked));
+#endif
+void appStart(uint8_t rstFlags) __attribute__ ((naked));
+
+/*
+ * RAMSTART should be self-explanatory.  It's bigger on parts with a
+ * lot of peripheral registers.  Let 0x100 be the default
+ * Note that RAMSTART (for optiboot) need not be exactly at the start of RAM.
+ */
+#if !defined(RAMSTART)  // newer versions of gcc avr-libc define RAMSTART
+#define RAMSTART 0x100
+#if defined (__AVR_ATmega644P__)
+// correct for a bug in avr-libc
+#undef SIGNATURE_2
+#define SIGNATURE_2 0x0A
+#elif defined(__AVR_ATmega1280__)
+#undef RAMSTART
+#define RAMSTART (0x200)
+#endif
+#endif
+
+/* C zero initialises all global variables. However, that requires */
+/* These definitions are NOT zero initialised, but that doesn't matter */
+/* This allows us to drop the zero init code, saving us memory */
+#define buff    ((uint8_t*)(RAMSTART))
+
+/* Virtual boot partition support */
+#ifdef VIRTUAL_BOOT_PARTITION
+#define rstVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define rstVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+5))
+#define saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#define saveVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7))
+// Vector to save original reset jump:
+//   SPM Ready is least probably used, so it's default
+//   if not, use old way WDT_vect_num,
+//   or simply set custom save_vect_num in Makefile using vector name
+//   or even raw number.
+#if !defined (save_vect_num)
+#if defined (SPM_RDY_vect_num)
+#define save_vect_num (SPM_RDY_vect_num)
+#elif defined (SPM_READY_vect_num)
+#define save_vect_num (SPM_READY_vect_num)
+#elif defined (WDT_vect_num)
+#define save_vect_num (WDT_vect_num)
+#else
+#error Cant find SPM or WDT interrupt vector for this CPU
+#endif
+#endif //save_vect_num
+// check if it's on the same page (code assumes that)
+#if (SPM_PAGESIZE <= save_vect_num)
+#error Save vector not in the same page as reset!
+#endif
+#if FLASHEND > 8192
+// AVRs with more than 8k of flash have 4-byte vectors, and use jmp.
+//  We save only 16 bits of address, so devices with more than 128KB
+//  may behave wrong for upper part of address space.
+#define rstVect0 2
+#define rstVect1 3
+#define saveVect0 (save_vect_num*4+2)
+#define saveVect1 (save_vect_num*4+3)
+#define appstart_vec (save_vect_num*2)
+#else
+// AVRs with up to 8k of flash have 2-byte vectors, and use rjmp.
+#define rstVect0 0
+#define rstVect1 1
+#define saveVect0 (save_vect_num*2)
+#define saveVect1 (save_vect_num*2+1)
+#define appstart_vec (save_vect_num)
+#endif
+#else
+#define appstart_vec (0)
+#endif // VIRTUAL_BOOT_PARTITION
+
+
+/* main program starts here */
+int main(void) {
+  uint8_t ch;
+
+  /*
+   * Making these local and in registers prevents the need for initializing
+   * them, and also saves space because code no longer stores to memory.
+   * (initializing address keeps the compiler happy, but isn't really
+   *  necessary, and uses 4 bytes of flash.)
+   */
+  register uint16_t address = 0;
+  register pagelen_t  length;
+
+  // After the zero init loop, this is the first code to run.
+  //
+  // This code makes the following assumptions:
+  //  No interrupts will execute
+  //  SP points to RAMEND
+  //  r1 contains zero
+  //
+  // If not, uncomment the following instructions:
+  // cli();
+  asm volatile ("clr __zero_reg__");
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  SP=RAMEND;  // This is done by hardware reset
+#endif
+
+  /*
+   * modified Adaboot no-wait mod.
+   * Pass the reset reason to app.  Also, it appears that an Uno poweron
+   * can leave multiple reset flags set; we only want the bootloader to
+   * run on an 'external reset only' status
+   */
+#if !defined(__AVR_ATmega16__)
+  ch = MCUSR;
+  MCUSR = 0;
+#else
+  ch = MCUCSR;
+  MCUCSR = 0;
+#endif
+  if (ch & (_BV(WDRF) | _BV(BORF) | _BV(PORF)))
+      appStart(ch);
+
+#if LED_START_FLASHES > 0
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+#endif
+
+#ifndef SOFT_UART
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  UCSRA = _BV(U2X); //Double speed mode USART
+  UCSRB = _BV(RXEN) | _BV(TXEN);  // enable Rx & Tx
+  UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);  // config USART; 8N1
+  UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#else
+  UART_SRA = _BV(U2X0); //Double speed mode USART0
+  UART_SRB = _BV(RXEN0) | _BV(TXEN0);
+  UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
+  UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#endif
+#endif
+
+  // Set up watchdog to trigger after 1s
+  watchdogConfig(WATCHDOG_1S);
+
+#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH)
+  /* Set LED pin as output */
+  LED_DDR |= _BV(LED);
+#endif
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+#endif
+
+#if LED_START_FLASHES > 0
+  /* Flash onboard LED to signal entering of bootloader */
+  flash_led(LED_START_FLASHES * 2);
+#endif
+
+  /* Forever loop: exits by causing WDT reset */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      unsigned char which = getch();
+      verifySpace();
+      /*
+       * Send optiboot version as "SW version"
+       * Note that the references to memory are optimized away.
+       */
+      if (which == 0x82) {
+	  putch(optiboot_version & 0xFF);
+      } else if (which == 0x81) {
+	  putch(optiboot_version >> 8);
+      } else {
+	/*
+	 * GET PARAMETER returns a generic 0x03 reply for
+         * other parameters - enough to keep Avrdude happy
+	 */
+	putch(0x03);
+      }
+    }
+    else if(ch == STK_SET_DEVICE) {
+      // SET DEVICE is ignored
+      getNch(20);
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+      // LOAD ADDRESS
+      uint16_t newAddress;
+      newAddress = getch();
+      newAddress = (newAddress & 0xff) | (getch() << 8);
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+      address = newAddress;
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+      // UNIVERSAL command is ignored
+      getNch(4);
+      putch(0x00);
+    }
+    /* Write memory, length is big endian and is in bytes */
+    else if(ch == STK_PROG_PAGE) {
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t desttype;
+      uint8_t *bufPtr;
+      pagelen_t savelength;
+
+      GETLENGTH(length);
+      savelength = length;
+      desttype = getch();
+
+      // read a page worth of contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+      while (--length);
+
+      // Read command terminator, start reply
+      verifySpace();
+
+#ifdef VIRTUAL_BOOT_PARTITION
+#if FLASHEND > 8192
+/*
+ * AVR with 4-byte ISR Vectors and "jmp"
+ * WARNING: this works only up to 128KB flash!
+ */
+      if (address == 0) {
+	// This is the reset vector page. We need to live-patch the
+	// code so the bootloader runs first.
+	//
+	// Save jmp targets (for "Verify")
+	rstVect0_sav = buff[rstVect0];
+	rstVect1_sav = buff[rstVect1];
+	saveVect0_sav = buff[saveVect0];
+	saveVect1_sav = buff[saveVect1];
+
+        // Move RESET jmp target to 'save' vector
+        buff[saveVect0] = rstVect0_sav;
+        buff[saveVect1] = rstVect1_sav;
+
+        // Add jump to bootloader at RESET vector
+        // WARNING: this works as long as 'main' is in first section
+        buff[rstVect0] = ((uint16_t)main) & 0xFF;
+        buff[rstVect1] = ((uint16_t)main) >> 8;
+      }
+
+#else
+/*
+ * AVR with 2-byte ISR Vectors and rjmp
+ */
+      if ((uint16_t)(void*)address == rstVect0) {
+        // This is the reset vector page. We need to live-patch
+        // the code so the bootloader runs first.
+        //
+        // Move RESET vector to 'save' vector
+	// Save jmp targets (for "Verify")
+	rstVect0_sav = buff[rstVect0];
+	rstVect1_sav = buff[rstVect1];
+	saveVect0_sav = buff[saveVect0];
+	saveVect1_sav = buff[saveVect1];
+
+	// Instruction is a relative jump (rjmp), so recalculate.
+	uint16_t vect=(rstVect0_sav & 0xff) | ((rstVect1_sav & 0x0f)<<8); //calculate 12b displacement
+	vect = (vect-save_vect_num) & 0x0fff; //substract 'save' interrupt position and wrap around 4096
+        // Move RESET jmp target to 'save' vector
+        buff[saveVect0] = vect & 0xff;
+        buff[saveVect1] = (vect >> 8) | 0xc0; //
+        // Add rjump to bootloader at RESET vector
+        vect = ((uint16_t)main) &0x0fff; //WARNIG: this works as long as 'main' is in first section
+        buff[0] = vect & 0xFF; // rjmp 0x1c00 instruction
+	buff[1] = (vect >> 8) | 0xC0;
+      }
+#endif // FLASHEND
+#endif // VBP
+
+      writebuffer(desttype, buff, address, savelength);
+
+
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+      uint8_t desttype;
+      GETLENGTH(length);
+
+      desttype = getch();
+
+      verifySpace();
+
+      read_mem(desttype, address, length);
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+      putch(SIGNATURE_0);
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
+      // Adaboot no-wait mod
+      watchdogConfig(WATCHDOG_16MS);
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    }
+    putch(STK_OK);
+  }
+}
+
+void putch(char ch) {
+#ifndef SOFT_UART
+  while (!(UART_SRA & _BV(UDRE0)));
+  UART_UDR = ch;
+#else
+  __asm__ __volatile__ (
+    "   com %[ch]\n" // ones complement, carry set
+    "   sec\n"
+    "1: brcc 2f\n"
+    "   cbi %[uartPort],%[uartBit]\n"
+    "   rjmp 3f\n"
+    "2: sbi %[uartPort],%[uartBit]\n"
+    "   nop\n"
+    "3: rcall uartDelay\n"
+    "   rcall uartDelay\n"
+    "   lsr %[ch]\n"
+    "   dec %[bitcnt]\n"
+    "   brne 1b\n"
+    :
+    :
+      [bitcnt] "d" (10),
+      [ch] "r" (ch),
+      [uartPort] "I" (_SFR_IO_ADDR(UART_PORT)),
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
+}
+
+uint8_t getch(void) {
+  uint8_t ch;
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  LED_PORT ^= _BV(LED);
+#else
+  LED_PIN |= _BV(LED);
+#endif
+#endif
+
+#ifdef SOFT_UART
+    watchdogReset();
+  __asm__ __volatile__ (
+    "1: sbic  %[uartPin],%[uartBit]\n"  // Wait for start edge
+    "   rjmp  1b\n"
+    "   rcall uartDelay\n"          // Get to middle of start bit
+    "2: rcall uartDelay\n"              // Wait 1 bit period
+    "   rcall uartDelay\n"              // Wait 1 bit period
+    "   clc\n"
+    "   sbic  %[uartPin],%[uartBit]\n"
+    "   sec\n"
+    "   dec   %[bitCnt]\n"
+    "   breq  3f\n"
+    "   ror   %[ch]\n"
+    "   rjmp  2b\n"
+    "3:\n"
+    :
+      [ch] "=r" (ch)
+    :
+      [bitCnt] "d" (9),
+      [uartPin] "I" (_SFR_IO_ADDR(UART_PIN)),
+      [uartBit] "I" (UART_RX_BIT)
+    :
+      "r25"
+);
+#else
+  while(!(UART_SRA & _BV(RXC0)))
+    ;
+  if (!(UART_SRA & _BV(FE0))) {
+      /*
+       * A Framing Error indicates (probably) that something is talking
+       * to us at the wrong bit rate.  Assume that this is because it
+       * expects to be talking to the application, and DON'T reset the
+       * watchdog.  This should cause the bootloader to abort and run
+       * the application "soon", if it keeps happening.  (Note that we
+       * don't care that an invalid char is returned...)
+       */
+    watchdogReset();
+  }
+
+  ch = UART_UDR;
+#endif
+
+#ifdef LED_DATA_FLASH
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  LED_PORT ^= _BV(LED);
+#else
+  LED_PIN |= _BV(LED);
+#endif
+#endif
+
+  return ch;
+}
+
+#ifdef SOFT_UART
+// AVR305 equation: #define UART_B_VALUE (((F_CPU/BAUD_RATE)-23)/6)
+// Adding 3 to numerator simulates nearest rounding for more accurate baud rates
+#define UART_B_VALUE (((F_CPU/BAUD_RATE)-20)/6)
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
+
+void uartDelay() {
+  __asm__ __volatile__ (
+    "ldi r25,%[count]\n"
+    "1:dec r25\n"
+    "brne 1b\n"
+    "ret\n"
+    ::[count] "M" (UART_B_VALUE)
+  );
+}
+#endif
+
+void getNch(uint8_t count) {
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) {
+    watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
+    while (1)			      // and busy-loop so that WD causes
+      ;				      //  a reset and app start.
+  }
+  putch(STK_INSYNC);
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
+    while(!(TIFR1 & _BV(TOV1)));
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+    LED_PORT ^= _BV(LED);
+#else
+    LED_PIN |= _BV(LED);
+#endif
+    watchdogReset();
+  } while (--count);
+}
+#endif
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    "wdr\n"
+  );
+}
+
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+  WDTCSR = x;
+}
+
+void appStart(uint8_t rstFlags) {
+  // save the reset flags in the designated register
+  //  This can be saved in a main program by putting code in .init0 (which
+  //  executes before normal c init code) to save R2 to a global variable.
+  __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
+
+  watchdogConfig(WATCHDOG_OFF);
+  // Note that appstart_vec is defined so that this works with either
+  // real or virtual boot partitions.
+  __asm__ __volatile__ (
+    // Jump to 'save' or RST vector
+    "ldi r30,%[rstvec]\n"
+    "clr r31\n"
+    "ijmp\n"::[rstvec] "M"(appstart_vec)
+  );
+}
+
+/*
+ * void writebuffer(memtype, buffer, address, length)
+ */
+static inline void writebuffer(int8_t memtype, uint8_t *mybuff,
+			       uint16_t address, pagelen_t len)
+{
+    switch (memtype) {
+    case 'E': // EEPROM
+#if defined(SUPPORT_EEPROM) || defined(BIGBOOT)
+        while(len--) {
+	    eeprom_write_byte((uint8_t *)(address++), *mybuff++);
+        }
+#else
+	/*
+	 * On systems where EEPROM write is not supported, just busy-loop
+	 * until the WDT expires, which will eventually cause an error on
+	 * host system (which is what it should do.)
+	 */
+	while (1)
+	    ; // Error: wait for WDT
+#endif
+	break;
+    default:  // FLASH
+	/*
+	 * Default to writing to Flash program memory.  By making this
+	 * the default rather than checking for the correct code, we save
+	 * space on chips that don't support any other memory types.
+	 */
+	{
+	    // Copy buffer into programming buffer
+	    uint8_t *bufPtr = mybuff;
+	    uint16_t addrPtr = (uint16_t)(void*)address;
+
+	    /*
+	     * Start the page erase and wait for it to finish.  There
+	     * used to be code to do this while receiving the data over
+	     * the serial link, but the performance improvement was slight,
+	     * and we needed the space back.
+	     */
+	    __boot_page_erase_short((uint16_t)(void*)address);
+	    boot_spm_busy_wait();
+
+	    /*
+	     * Copy data from the buffer into the flash write buffer.
+	     */
+	    do {
+		uint16_t a;
+		a = *bufPtr++;
+		a |= (*bufPtr++) << 8;
+		__boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+		addrPtr += 2;
+	    } while (len -= 2);
+
+	    /*
+	     * Actually Write the buffer to flash (and wait for it to finish.)
+	     */
+	    __boot_page_write_short((uint16_t)(void*)address);
+	    boot_spm_busy_wait();
+#if defined(RWWSRE)
+	    // Reenable read access to flash
+	    boot_rww_enable();
+#endif
+	} // default block
+	break;
+    } // switch
+}
+
+static inline void read_mem(uint8_t memtype, uint16_t address, pagelen_t length)
+{
+    uint8_t ch;
+
+    switch (memtype) {
+
+#if defined(SUPPORT_EEPROM) || defined(BIGBOOT)
+    case 'E': // EEPROM
+	do {
+	    putch(eeprom_read_byte((uint8_t *)(address++)));
+	} while (--length);
+	break;
+#endif
+    default:
+	do {
+#ifdef VIRTUAL_BOOT_PARTITION
+        // Undo vector patch in bottom page so verify passes
+	    if (address == rstVect0) ch = rstVect0_sav;
+	    else if (address == rstVect1) ch = rstVect1_sav;
+	    else if (address == saveVect0) ch = saveVect0_sav;
+	    else if (address == saveVect1) ch = saveVect1_sav;
+	    else ch = pgm_read_byte_near(address);
+	    address++;
+#elif defined(RAMPZ)
+	    // Since RAMPZ should already be set, we need to use EPLM directly.
+	    // Also, we can use the autoincrement version of lpm to update "address"
+	    //      do putch(pgm_read_byte_near(address++));
+	    //      while (--length);
+	    // read a Flash and increment the address (may increment RAMPZ)
+	    __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
+#else
+	    // read a Flash byte and increment the address
+	    __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address): "1" (address));
+#endif
+	    putch(ch);
+	} while (--length);
+	break;
+    } // switch
+}

+ 795 - 0
pin_defs.h

@@ -0,0 +1,795 @@
+/*
+ * pin_defs.h
+ * optiboot helper defining the default pin assignments (LED, SOFT_UART)
+ * for the various chips that are supported.  This also has some ugly macros
+ * for selecting among various UARTs and LED possibilities using command-line
+ * defines like "UART=2 LED=B5"
+ *
+ * Copyright 2013-2015 by Bill Westfield.
+ * Copyright 2010 by Peter Knight.
+ * This software is licensed under version 2 of the Gnu Public Licence.
+ * See optiboot.c for details.
+ */
+
+/*------------------------------------------------------------------------ */
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
+/*------------------------------------------------------------------------ */
+
+/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove
+ */ 
+#if !defined(LED)
+#define LED B5
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTD
+#define UART_PIN    PIND
+#define UART_DDR    DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/*
+ * Handle devices with up to 4 uarts (eg m1280.)  Rather inelegantly.
+ * Note that mega8/m32 still needs special handling, because ubrr is handled
+ * differently.
+ */
+#if UART == 0
+# define UART_SRA UCSR0A
+# define UART_SRB UCSR0B
+# define UART_SRC UCSR0C
+# define UART_SRL UBRR0L
+# define UART_UDR UDR0
+#elif UART == 1
+#if !defined(UDR1)
+#error UART == 1, but no UART1 on device
+#endif
+# define UART_SRA UCSR1A
+# define UART_SRB UCSR1B
+# define UART_SRC UCSR1C
+# define UART_SRL UBRR1L
+# define UART_UDR UDR1
+#elif UART == 2
+#if !defined(UDR2)
+#error UART == 2, but no UART2 on device
+#endif
+# define UART_SRA UCSR2A
+# define UART_SRB UCSR2B
+# define UART_SRC UCSR2C
+# define UART_SRL UBRR2L
+# define UART_UDR UDR2
+#elif UART == 3
+#if !defined(UDR1)
+#error UART == 3, but no UART3 on device
+#endif
+# define UART_SRA UCSR3A
+# define UART_SRB UCSR3B
+# define UART_SRC UCSR3C
+# define UART_SRL UBRR3L
+# define UART_UDR UDR3
+#endif
+
+#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  //Name conversion R.Wiersma
+  #define UCSR0A	UCSRA
+  #define UDR0 		UDR
+  #define UDRE0 	UDRE
+  #define RXC0		RXC
+  #define FE0           FE
+  #define TIFR1 	TIFR
+  #define WDTCSR	WDTCR
+#endif
+#if defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+  #define WDCE		WDTOE
+#endif
+
+/* Luminet support */
+/*------------------------------------------------------------------------ */
+#if defined(__AVR_ATtiny84__)
+/*------------------------------------------------------------------------ */
+/* Red LED is connected to pin PA4 */ 
+#if !defined(LED)
+#define LED         A4
+#endif
+
+/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
+#ifdef SOFT_UART
+#define UART_PORT   PORTA
+#define UART_PIN    PINA
+#define UART_DDR    DDRA
+#define UART_TX_BIT 2
+#define UART_RX_BIT 3
+#endif
+#endif
+
+/*------------------------------------------------------------------------ */
+/* Sanguino support (and other 40pin DIP cpus) */
+#if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega32__) || defined (__AVR_ATmega16__)
+/*------------------------------------------------------------------------ */
+/* Onboard LED is connected to pin PB0 on Sanguino */ 
+#if !defined(LED)
+#define LED         B0
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTD
+#define UART_PIN    PIND
+#define UART_DDR    DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/*------------------------------------------------------------------------ */
+/* Mega support */
+#if defined(__AVR_ATmega1280__)
+/*------------------------------------------------------------------------ */
+/* Onboard LED is connected to pin PB7 on Arduino Mega */ 
+#if !defined(LED)
+#define LED         B7
+#endif
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTE
+#define UART_PIN    PINE
+#define UART_DDR    DDRE
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * A bunch of macros to enable the LED to be specifed as "B5" for bit 5 
+ * of port B, and similar.
+ */
+
+#define A0 0x100
+#define A1 0x101
+#define A2 0x102
+#define A3 0x103
+#define A4 0x104
+#define A5 0x105
+#define A6 0x106
+#define A7 0x107
+
+#define B0 0x200
+#define B1 0x201
+#define B2 0x202
+#define B3 0x203
+#define B4 0x204
+#define B5 0x205
+#define B6 0x206
+#define B7 0x207
+
+#define C0 0x300
+#define C1 0x301
+#define C2 0x302
+#define C3 0x303
+#define C4 0x304
+#define C5 0x305
+#define C6 0x306
+#define C7 0x307
+
+#define D0 0x400
+#define D1 0x401
+#define D2 0x402
+#define D3 0x403
+#define D4 0x404
+#define D5 0x405
+#define D6 0x406
+#define D7 0x407
+
+#define E0 0x500
+#define E1 0x501
+#define E2 0x502
+#define E3 0x503
+#define E4 0x504
+#define E5 0x505
+#define E6 0x506
+#define E7 0x507
+
+#define F0 0x600
+#define F1 0x601
+#define F2 0x602
+#define F3 0x603
+#define F4 0x604
+#define F5 0x605
+#define F6 0x606
+#define F7 0x607
+
+#define G0 0x700
+#define G1 0x701
+#define G2 0x702
+#define G3 0x703
+#define G4 0x704
+#define G5 0x705
+#define G6 0x706
+#define G7 0x707
+
+#define H0 0x800
+#define H1 0x801
+#define H2 0x802
+#define H3 0x803
+#define H4 0x804
+#define H5 0x805
+#define H6 0x806
+#define H7 0x807
+
+#define J0 0xA00
+#define J1 0xA01
+#define J2 0xA02
+#define J3 0xA03
+#define J4 0xA04
+#define J5 0xA05
+#define J6 0xA06
+#define J7 0xA07
+
+#define K0 0xB00
+#define K1 0xB01
+#define K2 0xB02
+#define K3 0xB03
+#define K4 0xB04
+#define K5 0xB05
+#define K6 0xB06
+#define K7 0xB07
+
+#define L0 0xC00
+#define L1 0xC01
+#define L2 0xC02
+#define L3 0xC03
+#define L4 0xC04
+#define L5 0xC05
+#define L6 0xC06
+#define L7 0xC07
+
+
+
+#if LED == B0
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB0
+#elif LED == B1
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB1
+#elif LED == B2
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB2
+#elif LED == B3
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB3
+#elif LED == B4
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB4
+#elif LED == B5
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB5
+#elif LED == B6
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB6
+#elif LED == B7
+#undef LED
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED	    PINB7
+
+#elif LED == C0
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC0
+#elif LED == C1
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC1
+#elif LED == C2
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC2
+#elif LED == C3
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC3
+#elif LED == C4
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC4
+#elif LED == C5
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC5
+#elif LED == C6
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC6
+#elif LED == C7
+#undef LED
+#define LED_DDR     DDRC
+#define LED_PORT    PORTC
+#define LED_PIN     PINC
+#define LED	    PINC7
+
+#elif LED == D0
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND0
+#elif LED == D1
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND1
+#elif LED == D2
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND2
+#elif LED == D3
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND3
+#elif LED == D4
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND4
+#elif LED == D5
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND5
+#elif LED == D6
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND6
+#elif LED == D7
+#undef LED
+#define LED_DDR     DDRD
+#define LED_PORT    PORTD
+#define LED_PIN     PIND
+#define LED	    PIND7
+
+#elif LED == E0
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE0
+#elif LED == E1
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE1
+#elif LED == E2
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE2
+#elif LED == E3
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE3
+#elif LED == E4
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE4
+#elif LED == E5
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE5
+#elif LED == E6
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE6
+#elif LED == E7
+#undef LED
+#define LED_DDR     DDRE
+#define LED_PORT    PORTE
+#define LED_PIN     PINE
+#define LED	    PINE7
+
+#elif LED == F0
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF0
+#elif LED == F1
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF1
+#elif LED == F2
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF2
+#elif LED == F3
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF3
+#elif LED == F4
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF4
+#elif LED == F5
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF5
+#elif LED == F6
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF6
+#elif LED == F7
+#undef LED
+#define LED_DDR     DDRF
+#define LED_PORT    PORTF
+#define LED_PIN     PINF
+#define LED	    PINF7
+
+#elif LED == G0
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING0
+#elif LED == G1
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING1
+#elif LED == G2
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING2
+#elif LED == G3
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING3
+#elif LED == G4
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING4
+#elif LED == G5
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING5
+#elif LED == G6
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING6
+#elif LED == G7
+#undef LED
+#define LED_DDR     DDRG
+#define LED_PORT    PORTG
+#define LED_PIN     PING
+#define LED	    PING7
+
+#elif LED == H0
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH0
+#elif LED == H1
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH1
+#elif LED == H2
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH2
+#elif LED == H3
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH3
+#elif LED == H4
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH4
+#elif LED == H5
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH5
+#elif LED == H6
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH6
+#elif LED == H7
+#undef LED
+#define LED_DDR     DDRH
+#define LED_PORT    PORTH
+#define LED_PIN     PINH
+#define LED	    PINH7
+
+#elif LED == J0
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ0
+#elif LED == J1
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ1
+#elif LED == J2
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ2
+#elif LED == J3
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ3
+#elif LED == J4
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ4
+#elif LED == J5
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ5
+#elif LED == J6
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ6
+#elif LED == J7
+#undef LED
+#define LED_DDR     DDRJ
+#define LED_PORT    PORTJ
+#define LED_PIN     PINJ
+#define LED	    PINJ7
+
+#elif LED == K0
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK0
+#elif LED == K1
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK1
+#elif LED == K2
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK2
+#elif LED == K3
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK3
+#elif LED == K4
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK4
+#elif LED == K5
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK5
+#elif LED == K6
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK6
+#elif LED == K7
+#undef LED
+#define LED_DDR     DDRK
+#define LED_PORT    PORTK
+#define LED_PIN     PINK
+#define LED	    PINK7
+
+#elif LED == L0
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL0
+#elif LED == L1
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL1
+#elif LED == L2
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL2
+#elif LED == L3
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL3
+#elif LED == L4
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL4
+#elif LED == L5
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL5
+#elif LED == L6
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL6
+#elif LED == L7
+#undef LED
+#define LED_DDR     DDRL
+#define LED_PORT    PORTL
+#define LED_PIN     PINL
+#define LED	    PINL7
+
+#elif LED == A0
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA0
+#elif LED == A1
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA1
+#elif LED == A2
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA2
+#elif LED == A3
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA3
+#elif LED == A4
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA4
+#elif LED == A5
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA5
+#elif LED == A6
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA6
+#elif LED == A7
+#undef LED
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED	    PINA7
+
+#else
+#error -------------------------------------------
+#error Unrecognized LED name.  Should be like "B5"
+#error -------------------------------------------
+#endif

+ 44 - 0
stk500.h

@@ -0,0 +1,44 @@
+/* STK500 constants list, from AVRDUDE
+ *
+ * Trivial set of constants derived from Atmel App Note AVR061
+ * Not copyrighted.  Released to the public domain.
+ */
+
+#define STK_OK              0x10
+#define STK_FAILED          0x11  // Not used
+#define STK_UNKNOWN         0x12  // Not used
+#define STK_NODEVICE        0x13  // Not used
+#define STK_INSYNC          0x14  // ' '
+#define STK_NOSYNC          0x15  // Not used
+#define ADC_CHANNEL_ERROR   0x16  // Not used
+#define ADC_MEASURE_OK      0x17  // Not used
+#define PWM_CHANNEL_ERROR   0x18  // Not used
+#define PWM_ADJUST_OK       0x19  // Not used
+#define CRC_EOP             0x20  // 'SPACE'
+#define STK_GET_SYNC        0x30  // '0'
+#define STK_GET_SIGN_ON     0x31  // '1'
+#define STK_SET_PARAMETER   0x40  // '@'
+#define STK_GET_PARAMETER   0x41  // 'A'
+#define STK_SET_DEVICE      0x42  // 'B'
+#define STK_SET_DEVICE_EXT  0x45  // 'E'
+#define STK_ENTER_PROGMODE  0x50  // 'P'
+#define STK_LEAVE_PROGMODE  0x51  // 'Q'
+#define STK_CHIP_ERASE      0x52  // 'R'
+#define STK_CHECK_AUTOINC   0x53  // 'S'
+#define STK_LOAD_ADDRESS    0x55  // 'U'
+#define STK_UNIVERSAL       0x56  // 'V'
+#define STK_PROG_FLASH      0x60  // '`'
+#define STK_PROG_DATA       0x61  // 'a'
+#define STK_PROG_FUSE       0x62  // 'b'
+#define STK_PROG_LOCK       0x63  // 'c'
+#define STK_PROG_PAGE       0x64  // 'd'
+#define STK_PROG_FUSE_EXT   0x65  // 'e'
+#define STK_READ_FLASH      0x70  // 'p'
+#define STK_READ_DATA       0x71  // 'q'
+#define STK_READ_FUSE       0x72  // 'r'
+#define STK_READ_LOCK       0x73  // 's'
+#define STK_READ_PAGE       0x74  // 't'
+#define STK_READ_SIGN       0x75  // 'u'
+#define STK_READ_OSCCAL     0x76  // 'v'
+#define STK_READ_FUSE_EXT   0x77  // 'w'
+#define STK_READ_OSCCAL_EXT 0x78  // 'x'