Browse Source

First release

cathedrow 15 years ago
parent
commit
4602ee304a
43 changed files with 8687 additions and 0 deletions
  1. 138 0
      optiboot/boards.txt
  2. 213 0
      optiboot/bootloaders/optiboot/Makefile
  3. 11 0
      optiboot/bootloaders/optiboot/makeall
  4. 377 0
      optiboot/bootloaders/optiboot/optiboot.c
  5. 34 0
      optiboot/bootloaders/optiboot/optiboot_atmega328.hex
  6. 483 0
      optiboot/bootloaders/optiboot/optiboot_atmega328.lst
  7. 34 0
      optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex
  8. 483 0
      optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst
  9. 34 0
      optiboot/bootloaders/optiboot/optiboot_diecimila.hex
  10. 483 0
      optiboot/bootloaders/optiboot/optiboot_diecimila.lst
  11. 34 0
      optiboot/bootloaders/optiboot/optiboot_lilypad.hex
  12. 483 0
      optiboot/bootloaders/optiboot/optiboot_lilypad.lst
  13. 34 0
      optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.hex
  14. 483 0
      optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.lst
  15. 34 0
      optiboot/bootloaders/optiboot/optiboot_ng.hex
  16. 483 0
      optiboot/bootloaders/optiboot/optiboot_ng.lst
  17. 34 0
      optiboot/bootloaders/optiboot/optiboot_pro_16MHz.hex
  18. 483 0
      optiboot/bootloaders/optiboot/optiboot_pro_16MHz.lst
  19. 34 0
      optiboot/bootloaders/optiboot/optiboot_pro_20mhz.hex
  20. 483 0
      optiboot/bootloaders/optiboot/optiboot_pro_20mhz.lst
  21. 34 0
      optiboot/bootloaders/optiboot/optiboot_pro_8MHz.hex
  22. 483 0
      optiboot/bootloaders/optiboot/optiboot_pro_8MHz.lst
  23. 226 0
      optiboot/cores/arduino/HardwareSerial.cpp
  24. 66 0
      optiboot/cores/arduino/HardwareSerial.h
  25. 206 0
      optiboot/cores/arduino/Print.cpp
  26. 62 0
      optiboot/cores/arduino/Print.h
  27. 515 0
      optiboot/cores/arduino/Tone.cpp
  28. 1 0
      optiboot/cores/arduino/WConstants.h
  29. 215 0
      optiboot/cores/arduino/WInterrupts.c
  30. 60 0
      optiboot/cores/arduino/WMath.cpp
  31. 32 0
      optiboot/cores/arduino/WProgram.h
  32. 3 0
      optiboot/cores/arduino/_ReadMe.txt
  33. 515 0
      optiboot/cores/arduino/binary.h
  34. 14 0
      optiboot/cores/arduino/main.cpp
  35. 469 0
      optiboot/cores/arduino/pins_arduino.c
  36. 76 0
      optiboot/cores/arduino/pins_arduino.h
  37. 238 0
      optiboot/cores/arduino/wiring.c
  38. 133 0
      optiboot/cores/arduino/wiring.h
  39. 179 0
      optiboot/cores/arduino/wiring_analog.c
  40. 111 0
      optiboot/cores/arduino/wiring_digital.c
  41. 68 0
      optiboot/cores/arduino/wiring_private.h
  42. 66 0
      optiboot/cores/arduino/wiring_pulse.c
  43. 40 0
      optiboot/cores/arduino/wiring_shift.c

+ 138 - 0
optiboot/boards.txt

@@ -0,0 +1,138 @@
+# Optiboot Arduino support
+# Peter Knight, 2010
+
+##############################################################
+
+atmega328o.name=[Optiboot] Arduino Duemilanove or Nano w/ ATmega328
+atmega328o.upload.protocol=stk500
+atmega328o.upload.maximum_size=32256
+atmega328o.upload.speed=115200
+atmega328o.bootloader.low_fuses=0xff
+atmega328o.bootloader.high_fuses=0xde
+atmega328o.bootloader.extended_fuses=0x05
+atmega328o.bootloader.path=optiboot
+atmega328o.bootloader.file=optiboot_atmega328.hex
+atmega328o.bootloader.unlock_bits=0x3F
+atmega328o.bootloader.lock_bits=0x0F
+atmega328o.build.mcu=atmega328p
+atmega328o.build.f_cpu=16000000L
+atmega328o.build.core=arduino
+
+##############################################################
+
+diecimilao.name=[Optiboot] Arduino Diecimila, Duemilanove, or Nano w/ ATmega168
+diecimilao.upload.protocol=stk500
+diecimilao.upload.maximum_size=15360
+diecimilao.upload.speed=19200
+diecimilao.bootloader.low_fuses=0xff
+diecimilao.bootloader.high_fuses=0xdd
+diecimilao.bootloader.extended_fuses=0x02
+diecimilao.bootloader.path=optiboot
+diecimilao.bootloader.file=optiboot_diecimila.hex
+diecimilao.bootloader.unlock_bits=0x3F
+diecimilao.bootloader.lock_bits=0x0F
+diecimilao.build.mcu=atmega168
+diecimilao.build.f_cpu=16000000L
+diecimilao.build.core=arduino
+
+##############################################################
+
+minio.name=[Optiboot] Arduino Mini
+minio.upload.protocol=stk500
+minio.upload.maximum_size=15360
+minio.upload.speed=19200
+minio.bootloader.low_fuses=0xff
+minio.bootloader.high_fuses=0xdd
+minio.bootloader.extended_fuses=0x02
+minio.bootloader.path=optiboot
+minio.bootloader.file=optiboot_ng.hex
+minio.bootloader.unlock_bits=0x3F
+minio.bootloader.lock_bits=0x0F
+minio.build.mcu=atmega168
+minio.build.f_cpu=16000000L
+minio.build.core=arduino
+
+##############################################################
+
+lilypad328o.name=[Optiboot] LilyPad Arduino w/ ATmega328
+lilypad328o.upload.protocol=stk500
+lilypad328o.upload.maximum_size=31744
+lilypad328o.upload.speed=57600
+lilypad328o.bootloader.low_fuses=0xff
+lilypad328o.bootloader.high_fuses=0xdc
+lilypad328o.bootloader.extended_fuses=0x05
+lilypad328o.bootloader.path=optiboot
+lilypad328o.bootloader.file=optiboot_atmega328_pro_8MHz.hex
+lilypad328o.bootloader.unlock_bits=0x3F
+lilypad328o.bootloader.lock_bits=0x0F
+lilypad328o.build.mcu=atmega328p
+lilypad328o.build.f_cpu=8000000L
+lilypad328o.build.core=arduino
+
+##############################################################
+
+lilypado.name=[Optiboot] LilyPad Arduino w/ ATmega168
+lilypado.upload.protocol=stk500
+lilypado.upload.maximum_size=14336
+lilypado.upload.speed=19200
+lilypado.bootloader.low_fuses=0xe2
+lilypado.bootloader.high_fuses=0xdd
+lilypado.bootloader.extended_fuses=0x02
+lilypado.bootloader.path=lilypad
+lilypado.bootloader.file=optiboot_lilypad.hex
+lilypado.bootloader.unlock_bits=0x3F
+lilypado.bootloader.lock_bits=0x0F
+lilypado.build.mcu=atmega168
+lilypado.build.f_cpu=8000000L
+lilypado.build.core=arduino
+
+##############################################################
+
+pro328o.name=[Optiboot] Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328
+pro328o.upload.protocol=stk500
+pro328o.upload.maximum_size=30720
+pro328o.upload.speed=57600
+pro328o.bootloader.low_fuses=0xff
+pro328o.bootloader.high_fuses=0xdc
+pro328o.bootloader.extended_fuses=0x05
+pro328o.bootloader.path=optiboot
+pro328o.bootloader.file=optiboot_atmega328_pro_8MHz.hex
+pro328o.bootloader.unlock_bits=0x3F
+pro328o.bootloader.lock_bits=0x0F
+pro328o.build.mcu=atmega328p
+pro328o.build.f_cpu=8000000L
+pro328o.build.core=arduino
+
+##############################################################
+
+proo.name=[Optiboot] Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168
+proo.upload.protocol=stk500
+proo.upload.maximum_size=14336
+proo.upload.speed=19200
+proo.bootloader.low_fuses=0xc6
+proo.bootloader.high_fuses=0xdd
+proo.bootloader.extended_fuses=0x02
+proo.bootloader.path=optiboot
+proo.bootloader.file=optiboot_pro_8MHz.hex
+proo.bootloader.unlock_bits=0x3F
+proo.bootloader.lock_bits=0x0F
+proo.build.mcu=atmega168
+proo.build.f_cpu=8000000L
+proo.build.core=arduino
+
+##############################################################
+
+atmega168o.name=[Optiboot] Arduino NG or older w/ ATmega168
+atmega168o.upload.protocol=stk500
+atmega168o.upload.maximum_size=14336
+atmega168o.upload.speed=19200
+atmega168o.bootloader.low_fuses=0xff
+atmega168o.bootloader.high_fuses=0xdd
+atmega168o.bootloader.extended_fuses=0x02
+atmega168o.bootloader.path=optiboot
+atmega168o.bootloader.file=optiboot_ng.hex
+atmega168o.bootloader.unlock_bits=0x3F
+atmega168o.bootloader.lock_bits=0x0F
+atmega168o.build.mcu=atmega168
+atmega168o.build.f_cpu=16000000L
+atmega168o.build.core=arduino

+ 213 - 0
optiboot/bootloaders/optiboot/Makefile

@@ -0,0 +1,213 @@
+# 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...
+
+# program name should not be changed...
+PROGRAM    = optiboot
+
+# enter the parameters for the avrdude isp tool
+ISPTOOL	   = stk500v2
+ISPPORT	   = usb
+ISPSPEED   = -b 115200
+
+MCU_TARGET = atmega168
+LDSECTION  = --section-start=.text=0x3e00
+
+# 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 0x0f (to
+# lock it), but since the high two bits of the lock byte are
+# unused, avrdude would get confused.
+
+ISPFUSES    = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
+-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m
+ISPFLASH    = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
+-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m
+
+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
+
+OBJ        = $(PROGRAM).o
+OPTIMIZE = -Os -fno-inline-small-functions -fno-split-wide-types -mshort-calls
+
+DEFS       = 
+LIBS       =
+
+CC         = 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       = -Wl,$(LDSECTION) -Wl,--relax -nostartfiles
+
+OBJCOPY        = avr-objcopy
+OBJDUMP        = avr-objdump
+
+lilypad: TARGET = lilypad
+lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
+lilypad: AVR_FREQ = 8000000L
+lilypad: $(PROGRAM)_lilypad.hex
+lilypad: $(PROGRAM)_lilypad.lst
+
+lilypad_isp: lilypad
+lilypad_isp: TARGET = lilypad
+lilypad_isp: HFUSE = DD
+lilypad_isp: LFUSE = E2
+lilypad_isp: EFUSE = 02
+lilypad_isp: isp
+
+lilypad_resonator: TARGET = lilypad_resonator
+lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3'
+lilypad_resonator: AVR_FREQ = 8000000L
+lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex
+lilypad_resonator: $(PROGRAM)_lilypad_resonator.lst
+
+lilypad_resonator_isp: lilypad_resonator
+lilypad_resonator_isp: TARGET = lilypad_resonator
+lilypad_resonator_isp: HFUSE = DD
+lilypad_resonator_isp: LFUSE = C6
+lilypad_resonator_isp: EFUSE = 02
+lilypad_resonator_isp: isp
+
+pro8: TARGET = pro_8MHz
+pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro8: AVR_FREQ = 8000000L
+pro8: $(PROGRAM)_pro_8MHz.hex
+pro8: $(PROGRAM)_pro_8MHz.lst
+
+pro8_isp: pro8
+pro8_isp: TARGET = pro_8MHz
+pro8_isp: HFUSE = DD
+pro8_isp: LFUSE = C6
+pro8_isp: EFUSE = 02
+pro8_isp: isp
+
+pro16: TARGET = pro_16MHz
+pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro16: AVR_FREQ = 16000000L
+pro16: $(PROGRAM)_pro_16MHz.hex
+pro16: $(PROGRAM)_pro_16MHz.lst
+
+pro16_isp: pro16
+pro16_isp: TARGET = pro_16MHz
+pro16_isp: HFUSE = DD
+pro16_isp: LFUSE = C6
+pro16_isp: EFUSE = 02
+pro16_isp: isp
+
+pro20: TARGET = pro_20mhz
+pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS'
+pro20: AVR_FREQ = 20000000L
+pro20: $(PROGRAM)_pro_20mhz.hex
+pro20: $(PROGRAM)_pro_20mhz.lst
+
+pro20_isp: pro20
+pro20_isp: TARGET = pro_20mhz
+pro20_isp: HFUSE = DD
+pro20_isp: LFUSE = C6
+pro20_isp: EFUSE = 02
+pro20_isp: isp
+
+diecimila: TARGET = diecimila
+diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1'
+diecimila: AVR_FREQ = 16000000L 
+diecimila: $(PROGRAM)_diecimila.hex
+diecimila: $(PROGRAM)_diecimila.lst
+
+diecimila_isp: diecimila
+diecimila_isp: TARGET = diecimila
+diecimila_isp: HFUSE = DD
+diecimila_isp: LFUSE = FF
+diecimila_isp: EFUSE = 02
+diecimila_isp: isp
+
+ng: TARGET = ng
+ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3'
+ng: AVR_FREQ = 16000000L
+ng: $(PROGRAM)_ng.hex
+ng: $(PROGRAM)_ng.lst
+
+ng_isp: ng
+ng_isp: TARGET = ng
+ng_isp: HFUSE = DD
+ng_isp: LFUSE = FF
+ng_isp: EFUSE = 02
+ng_isp: isp
+
+atmega328: TARGET = atmega328
+atmega328: MCU_TARGET = atmega328p
+atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3' '-DBAUD_RATE=115200'
+atmega328: AVR_FREQ = 16000000L
+atmega328: LDSECTION  = --section-start=.text=0x7e00
+atmega328: $(PROGRAM)_atmega328.hex
+atmega328: $(PROGRAM)_atmega328.lst
+
+atmega328_isp: atmega328
+atmega328_isp: TARGET = atmega328
+atmega328_isp: MCU_TARGET = atmega328p
+atmega328_isp: HFUSE = DE
+atmega328_isp: LFUSE = FF
+atmega328_isp: EFUSE = 05
+atmega328_isp: isp
+
+atmega328_pro8: TARGET = atmega328_pro_8MHz
+atmega328_pro8: MCU_TARGET = atmega328p
+atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DBAUD_RATE=57600'
+atmega328_pro8: AVR_FREQ = 8000000L
+atmega328_pro8: LDSECTION  = --section-start=.text=0x7e00
+atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex
+atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.lst
+
+atmega328_pro8_isp: atmega328_pro8
+atmega328_pro8_isp: TARGET = atmega328_pro_8MHz
+atmega328_pro8_isp: MCU_TARGET = atmega328p
+atmega328_pro8_isp: HFUSE = DE
+atmega328_pro8_isp: LFUSE = FF
+atmega328_pro8_isp: EFUSE = 05
+atmega328_pro8_isp: isp
+
+isp: $(TARGET)
+	$(ISPFUSES)
+	$(ISPFLASH)
+
+isp-stk500: $(PROGRAM)_$(TARGET).hex
+	$(STK500-1)
+	$(STK500-2)
+
+%.elf: $(OBJ)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+clean:
+	rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex
+
+%.lst: %.elf
+	$(OBJDUMP) -h -S $< > $@
+
+%.hex: %.elf
+	$(OBJCOPY) -j .text -j .data -O ihex $< $@
+
+%.srec: %.elf
+	$(OBJCOPY) -j .text -j .data -O srec $< $@
+
+%.bin: %.elf
+	$(OBJCOPY) -j .text -j .data -O binary $< $@

+ 11 - 0
optiboot/bootloaders/optiboot/makeall

@@ -0,0 +1,11 @@
+#!/bin/bash
+make clean
+make lilypad
+make lilypad_resonator
+make pro8
+make pro16
+make pro20
+make diecimila
+make ng
+make atmega328
+make atmega328_pro8

+ 377 - 0
optiboot/bootloaders/optiboot/optiboot.c

@@ -0,0 +1,377 @@
+/**********************************************************/
+/* Optiboot bootloader for Arduino                        */
+/*                                                        */
+/* Heavily optimised bootloader that is faster and        */
+/* smaller than the Arduino standard bootloader           */
+/*                                                        */
+/* Enhancements:                                          */
+/*   Fits in 512 bytes, saving 1.5K of code space         */
+/*   Background page erasing speeds up programming        */
+/*   Higher baud rate speeds up programming               */
+/*   Written almost entirely in C                         */
+/*   Customisable timeout with accurate timeconstant      */
+/*                                                        */
+/* 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                             */
+/*                                                        */
+/* Currently supports:                                    */
+/*   ATmega168 based devices (Diecimila etc)              */
+/*   ATmega328P based devices (Duemilanove etc)           */
+/*                                                        */
+/* Does not support:                                      */
+/*   ATmega1280 based devices (eg. Mega)                  */
+/*                                                        */
+/* 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 */
+/*                                                        */
+/* 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                    */
+/*                                                        */
+/**********************************************************/
+
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <avr/boot.h>
+
+#define NOWAIT
+
+/* Build-time variables */
+/* BAUD_RATE       Programming baud rate */
+/* LED_NO_FLASHES  Number of LED flashes on boot */
+/* FLASH_TIME_MS   Duration of each LED flash */
+/* BOOT_TIMEOUT_MS Serial port wait time before exiting bootloader */
+
+/* set the UART baud rate */
+#ifndef BAUD_RATE
+#define BAUD_RATE   19200
+#endif
+
+/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duemilanove */ 
+#define LED_DDR  DDRB
+#define LED_PORT PORTB
+#define LED_PIN  PINB
+#define LED      PINB5
+
+/* STK500 constants list, from AVRDUDE */
+#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'
+
+/* Function Prototypes */
+/* The main function is in init9, which removes the interrupt vector table */
+/* we don't need. It is also 'naked', which means the compiler does not    */
+/* generate any entry or exit code itself. */
+int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
+void putch(char);
+uint8_t getch(void);
+static inline void getNch(uint8_t); /* "static inline" is a compiler hint to reduce code size */
+void verifySpace();
+static inline void flash_led(uint8_t);
+void setTimer(uint16_t counts);
+uint8_t getLen();
+void appStart() __attribute__ ((naked));
+
+/* 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*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+  // 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();
+  // SP=RAMEND;  // This is done by hardware reset
+  // asm volatile ("clr __zero_reg__");
+
+  uint8_t ch;
+
+#if 0
+  // The compiler normally generates sts instructions for setting
+  // up I/O space registers. But that takes 6 bytes per register.
+  // This code can do it in 2, with an overhead of 20 bytes.
+  // This starts to pay off when initialising 6 or more registers
+  __asm__ volatile (
+    "ldi r30,lo8(init_table)\n"
+    "ldi r31,hi8(init_table)\n"
+    "ldi r29,0\n"
+    "init_loop:lpm r28,Z+\n"
+    "lpm r0,Z+\n"
+    "tst r28\n"
+    "breq init_exit+2\n"
+    "st Y,r0\n"
+    "rjmp init_loop\n"
+    "init_table:\n"
+    ".byte %[addr1]\n"
+    ".byte %[val1]\n"
+    ".byte %[addr2]\n"
+    ".byte %[val2]\n"
+    ".byte %[addr3]\n"
+    ".byte %[val3]\n"
+    ".byte %[addr4]\n"
+    ".byte %[val4]\n"
+    ".byte %[addr5]\n"
+    ".byte %[val5]\n"
+    "init_exit:.word 0\n"
+    // Clobbers R0,R28,R29,R30,R31
+    // But that is fine so we won't tell the compiler
+    // otherwise it will generate useless extra code
+    ::
+    [addr1]"i"(_SFR_MEM_ADDR(TCCR1B)), [val1]"i"(_BV(CS12) | _BV(CS10)),
+    [addr2]"i"(_SFR_MEM_ADDR(UCSR0A)), [val2]"i"(_BV(U2X0)),
+    [addr3]"i"(_SFR_MEM_ADDR(UCSR0B)), [val3]"i"(_BV(RXEN0) | _BV(TXEN0)),
+    [addr4]"i"(_SFR_MEM_ADDR(UCSR0C)), [val4]"i"(_BV(UCSZ00) | _BV(UCSZ01)),
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+  MCUSR = 0;
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+  WDTCSR = 0;
+  if (!(ch & _BV(EXTRF))) appStart();
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+
+  /* flash onboard LED to signal entering of bootloader */
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+      putch(0x03);
+    }
+    else if(ch == STK_SET_DEVICE) {
+      // SET DEVICE is ignored
+      getNch(20);
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+      // LOAD ADDRESS
+      address = getch();
+      address = (address & 0xff) | (getch() << 8);
+      address += address; // Convert from word address to byte address
+      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 *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+      while (--length);
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+
+      // Read command terminator, start reply
+      verifySpace();
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+      // READ PAGE - we only read flash
+      getLen();
+      verifySpace();
+      do putch(pgm_read_byte_near(address++));
+      while (--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 == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    }
+    putch(STK_OK);
+  }
+}
+
+void putch(char ch) {
+  while (!(UCSR0A & _BV(UDRE0)));
+  UDR0 = ch;
+}
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    while(!(TIFR1 & _BV(TOV1)));
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    "clr r30\n"
+    "clr r31\n"
+    "ijmp\n"
+  );
+}

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_atmega328.hex

@@ -0,0 +1,34 @@
+:107E000085E08093810082E08093C00098E19093A8
+:107E1000C10086E08093C20080E18093C40084B7F3
+:107E200014BE909360001092600081FFC1D0259A2B
+:107E300006E080E39CEFB5D0B09BFECF1D9A0150C9
+:107E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E112
+:107E5000FF2EB1D0813421F481E0C7D083E024C06B
+:107E6000823411F484E103C0853419F485E0BDD077
+:107E70008DC08535A1F49FD0082F10E0109301022A
+:107E80000093000298D090E0982F8827802B912BA8
+:107E9000880F991F909301028093000276C0863567
+:107EA00029F484E0A2D080E074D070C0843609F058
+:107EB00046C090D0863409F07BD0E0910002F0916A
+:107EC000010283E080935700E895C0E0D1E073D0D1
+:107ED0008993809102028150809302028823B9F72E
+:107EE00007B600FCFDCF7BD040910002509101020B
+:107EF000A0E0B1E02C9130E011968C91119790E0C8
+:107F0000982F8827822B932B1296FA010C01D0927E
+:107F10005700E89511244E5F5F4FF1E0A038BF078E
+:107F200049F7E0910002F0910102E0925700E895D4
+:107F300007B600FCFDCFF0925700E89527C08437C4
+:107F4000B9F448D04CD0E0910002F0910102319692
+:107F5000F0930102E09300023197E4918E2F19D043
+:107F600080910202815080930202882361F70EC043
+:107F7000853739F434D08EE10CD085E90AD08FE012
+:107F800093CF813511F4C092600029D080E101D0F7
+:107F900060CF982F8091C00085FFFCCF9093C600E2
+:107FA0000895909385008093840081E086BB0895B6
+:107FB000EE27FF2709942D988CE791EEF2DF02C09F
+:107FC000B099F6DF8091C00087FFFACF2D9A80919B
+:107FD000C6000895F0DFEFDF80930202ECCFEBDF05
+:107FE000803209F0E5DF84E1D4CF1F93182FE3DF5F
+:0A7FF0001150E9F7F4DF1F91089526
+:0400000300007E007B
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_atmega328.lst

@@ -0,0 +1,483 @@
+
+optiboot_atmega328.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00007e00  00007e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00007e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    7e00:	85 e0       	ldi	r24, 0x05	; 5
+    7e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    7e06:	82 e0       	ldi	r24, 0x02	; 2
+    7e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    7e0c:	98 e1       	ldi	r25, 0x18	; 24
+    7e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    7e12:	86 e0       	ldi	r24, 0x06	; 6
+    7e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    7e18:	80 e1       	ldi	r24, 0x10	; 16
+    7e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    7e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    7e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    7e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    7e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    7e2a:	81 ff       	sbrs	r24, 1
+    7e2c:	c1 d0       	rcall	.+386    	; 0x7fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    7e2e:	25 9a       	sbi	0x04, 5	; 4
+    7e30:	06 e0       	ldi	r16, 0x06	; 6
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    7e32:	80 e3       	ldi	r24, 0x30	; 48
+    7e34:	9c ef       	ldi	r25, 0xFC	; 252
+    7e36:	b5 d0       	rcall	.+362    	; 0x7fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    7e38:	b0 9b       	sbis	0x16, 0	; 22
+    7e3a:	fe cf       	rjmp	.-4      	; 0x7e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    7e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    7e3e:	01 50       	subi	r16, 0x01	; 1
+    7e40:	c1 f7       	brne	.-16     	; 0x7e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    7e42:	dd 24       	eor	r13, r13
+    7e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    7e46:	b8 e0       	ldi	r27, 0x08	; 8
+    7e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    7e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    7e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    7e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    7e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    7e52:	b1 d0       	rcall	.+354    	; 0x7fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    7e54:	81 34       	cpi	r24, 0x41	; 65
+    7e56:	21 f4       	brne	.+8      	; 0x7e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    7e58:	81 e0       	ldi	r24, 0x01	; 1
+    7e5a:	c7 d0       	rcall	.+398    	; 0x7fea <verifySpace+0xc>
+      putch(0x03);
+    7e5c:	83 e0       	ldi	r24, 0x03	; 3
+    7e5e:	24 c0       	rjmp	.+72     	; 0x7ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    7e60:	82 34       	cpi	r24, 0x42	; 66
+    7e62:	11 f4       	brne	.+4      	; 0x7e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    7e64:	84 e1       	ldi	r24, 0x14	; 20
+    7e66:	03 c0       	rjmp	.+6      	; 0x7e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    7e68:	85 34       	cpi	r24, 0x45	; 69
+    7e6a:	19 f4       	brne	.+6      	; 0x7e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    7e6c:	85 e0       	ldi	r24, 0x05	; 5
+    7e6e:	bd d0       	rcall	.+378    	; 0x7fea <verifySpace+0xc>
+    7e70:	8d c0       	rjmp	.+282    	; 0x7f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    7e72:	85 35       	cpi	r24, 0x55	; 85
+    7e74:	a1 f4       	brne	.+40     	; 0x7e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    7e76:	9f d0       	rcall	.+318    	; 0x7fb6 <getch>
+    7e78:	08 2f       	mov	r16, r24
+    7e7a:	10 e0       	ldi	r17, 0x00	; 0
+    7e7c:	10 93 01 02 	sts	0x0201, r17
+    7e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    7e84:	98 d0       	rcall	.+304    	; 0x7fb6 <getch>
+    7e86:	90 e0       	ldi	r25, 0x00	; 0
+    7e88:	98 2f       	mov	r25, r24
+    7e8a:	88 27       	eor	r24, r24
+    7e8c:	80 2b       	or	r24, r16
+    7e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    7e90:	88 0f       	add	r24, r24
+    7e92:	99 1f       	adc	r25, r25
+    7e94:	90 93 01 02 	sts	0x0201, r25
+    7e98:	80 93 00 02 	sts	0x0200, r24
+    7e9c:	76 c0       	rjmp	.+236    	; 0x7f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    7e9e:	86 35       	cpi	r24, 0x56	; 86
+    7ea0:	29 f4       	brne	.+10     	; 0x7eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    7ea2:	84 e0       	ldi	r24, 0x04	; 4
+    7ea4:	a2 d0       	rcall	.+324    	; 0x7fea <verifySpace+0xc>
+      putch(0x00);
+    7ea6:	80 e0       	ldi	r24, 0x00	; 0
+    7ea8:	74 d0       	rcall	.+232    	; 0x7f92 <putch>
+    7eaa:	70 c0       	rjmp	.+224    	; 0x7f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    7eac:	84 36       	cpi	r24, 0x64	; 100
+    7eae:	09 f0       	breq	.+2      	; 0x7eb2 <main+0xb2>
+    7eb0:	46 c0       	rjmp	.+140    	; 0x7f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    7eb2:	90 d0       	rcall	.+288    	; 0x7fd4 <getLen>
+    7eb4:	86 34       	cpi	r24, 0x46	; 70
+    7eb6:	09 f0       	breq	.+2      	; 0x7eba <main+0xba>
+    7eb8:	7b d0       	rcall	.+246    	; 0x7fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    7eba:	e0 91 00 02 	lds	r30, 0x0200
+    7ebe:	f0 91 01 02 	lds	r31, 0x0201
+    7ec2:	83 e0       	ldi	r24, 0x03	; 3
+    7ec4:	80 93 57 00 	sts	0x0057, r24
+    7ec8:	e8 95       	spm
+    7eca:	c0 e0       	ldi	r28, 0x00	; 0
+    7ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    7ece:	73 d0       	rcall	.+230    	; 0x7fb6 <getch>
+    7ed0:	89 93       	st	Y+, r24
+      while (--length);
+    7ed2:	80 91 02 02 	lds	r24, 0x0202
+    7ed6:	81 50       	subi	r24, 0x01	; 1
+    7ed8:	80 93 02 02 	sts	0x0202, r24
+    7edc:	88 23       	and	r24, r24
+    7ede:	b9 f7       	brne	.-18     	; 0x7ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    7ee0:	07 b6       	in	r0, 0x37	; 55
+    7ee2:	00 fc       	sbrc	r0, 0
+    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    7ee6:	7b d0       	rcall	.+246    	; 0x7fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    7ee8:	40 91 00 02 	lds	r20, 0x0200
+    7eec:	50 91 01 02 	lds	r21, 0x0201
+    7ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    7ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    7ef4:	2c 91       	ld	r18, X
+    7ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    7ef8:	11 96       	adiw	r26, 0x01	; 1
+    7efa:	8c 91       	ld	r24, X
+    7efc:	11 97       	sbiw	r26, 0x01	; 1
+    7efe:	90 e0       	ldi	r25, 0x00	; 0
+    7f00:	98 2f       	mov	r25, r24
+    7f02:	88 27       	eor	r24, r24
+    7f04:	82 2b       	or	r24, r18
+    7f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    7f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    7f0a:	fa 01       	movw	r30, r20
+    7f0c:	0c 01       	movw	r0, r24
+    7f0e:	d0 92 57 00 	sts	0x0057, r13
+    7f12:	e8 95       	spm
+    7f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    7f16:	4e 5f       	subi	r20, 0xFE	; 254
+    7f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    7f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    7f1c:	a0 38       	cpi	r26, 0x80	; 128
+    7f1e:	bf 07       	cpc	r27, r31
+    7f20:	49 f7       	brne	.-46     	; 0x7ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    7f22:	e0 91 00 02 	lds	r30, 0x0200
+    7f26:	f0 91 01 02 	lds	r31, 0x0201
+    7f2a:	e0 92 57 00 	sts	0x0057, r14
+    7f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    7f30:	07 b6       	in	r0, 0x37	; 55
+    7f32:	00 fc       	sbrc	r0, 0
+    7f34:	fd cf       	rjmp	.-6      	; 0x7f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    7f36:	f0 92 57 00 	sts	0x0057, r15
+    7f3a:	e8 95       	spm
+    7f3c:	27 c0       	rjmp	.+78     	; 0x7f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    7f3e:	84 37       	cpi	r24, 0x74	; 116
+    7f40:	b9 f4       	brne	.+46     	; 0x7f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    7f42:	48 d0       	rcall	.+144    	; 0x7fd4 <getLen>
+      verifySpace();
+    7f44:	4c d0       	rcall	.+152    	; 0x7fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    7f46:	e0 91 00 02 	lds	r30, 0x0200
+    7f4a:	f0 91 01 02 	lds	r31, 0x0201
+    7f4e:	31 96       	adiw	r30, 0x01	; 1
+    7f50:	f0 93 01 02 	sts	0x0201, r31
+    7f54:	e0 93 00 02 	sts	0x0200, r30
+    7f58:	31 97       	sbiw	r30, 0x01	; 1
+    7f5a:	e4 91       	lpm	r30, Z+
+    7f5c:	8e 2f       	mov	r24, r30
+    7f5e:	19 d0       	rcall	.+50     	; 0x7f92 <putch>
+      while (--length);
+    7f60:	80 91 02 02 	lds	r24, 0x0202
+    7f64:	81 50       	subi	r24, 0x01	; 1
+    7f66:	80 93 02 02 	sts	0x0202, r24
+    7f6a:	88 23       	and	r24, r24
+    7f6c:	61 f7       	brne	.-40     	; 0x7f46 <main+0x146>
+    7f6e:	0e c0       	rjmp	.+28     	; 0x7f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    7f70:	85 37       	cpi	r24, 0x75	; 117
+    7f72:	39 f4       	brne	.+14     	; 0x7f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    7f74:	34 d0       	rcall	.+104    	; 0x7fde <verifySpace>
+      putch(SIGNATURE_0);
+    7f76:	8e e1       	ldi	r24, 0x1E	; 30
+    7f78:	0c d0       	rcall	.+24     	; 0x7f92 <putch>
+      putch(SIGNATURE_1);
+    7f7a:	85 e9       	ldi	r24, 0x95	; 149
+    7f7c:	0a d0       	rcall	.+20     	; 0x7f92 <putch>
+      putch(SIGNATURE_2);
+    7f7e:	8f e0       	ldi	r24, 0x0F	; 15
+    7f80:	93 cf       	rjmp	.-218    	; 0x7ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    7f82:	81 35       	cpi	r24, 0x51	; 81
+    7f84:	11 f4       	brne	.+4      	; 0x7f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    7f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    7f8a:	29 d0       	rcall	.+82     	; 0x7fde <verifySpace>
+    }
+    putch(STK_OK);
+    7f8c:	80 e1       	ldi	r24, 0x10	; 16
+    7f8e:	01 d0       	rcall	.+2      	; 0x7f92 <putch>
+    7f90:	60 cf       	rjmp	.-320    	; 0x7e52 <main+0x52>
+
+00007f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    7f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    7f94:	80 91 c0 00 	lds	r24, 0x00C0
+    7f98:	85 ff       	sbrs	r24, 5
+    7f9a:	fc cf       	rjmp	.-8      	; 0x7f94 <putch+0x2>
+  UDR0 = ch;
+    7f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    7fa0:	08 95       	ret
+
+00007fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    7fa2:	90 93 85 00 	sts	0x0085, r25
+    7fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    7faa:	81 e0       	ldi	r24, 0x01	; 1
+    7fac:	86 bb       	out	0x16, r24	; 22
+}
+    7fae:	08 95       	ret
+
+00007fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    7fb0:	ee 27       	eor	r30, r30
+    7fb2:	ff 27       	eor	r31, r31
+    7fb4:	09 94       	ijmp
+
+00007fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    7fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    7fb8:	8c e7       	ldi	r24, 0x7C	; 124
+    7fba:	91 ee       	ldi	r25, 0xE1	; 225
+    7fbc:	f2 df       	rcall	.-28     	; 0x7fa2 <setTimer>
+    7fbe:	02 c0       	rjmp	.+4      	; 0x7fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    7fc0:	b0 99       	sbic	0x16, 0	; 22
+    7fc2:	f6 df       	rcall	.-20     	; 0x7fb0 <appStart>
+    7fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    7fc8:	87 ff       	sbrs	r24, 7
+    7fca:	fa cf       	rjmp	.-12     	; 0x7fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    7fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    7fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    7fd2:	08 95       	ret
+
+00007fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    7fd4:	f0 df       	rcall	.-32     	; 0x7fb6 <getch>
+  length = getch();
+    7fd6:	ef df       	rcall	.-34     	; 0x7fb6 <getch>
+    7fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    7fdc:	ec cf       	rjmp	.-40     	; 0x7fb6 <getch>
+
+00007fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    7fde:	eb df       	rcall	.-42     	; 0x7fb6 <getch>
+    7fe0:	80 32       	cpi	r24, 0x20	; 32
+    7fe2:	09 f0       	breq	.+2      	; 0x7fe6 <verifySpace+0x8>
+    7fe4:	e5 df       	rcall	.-54     	; 0x7fb0 <appStart>
+  putch(STK_INSYNC);
+    7fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    7fe8:	d4 cf       	rjmp	.-88     	; 0x7f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    7fea:	1f 93       	push	r17
+    7fec:	18 2f       	mov	r17, r24
+
+00007fee <getNch>:
+  do getch(); while (--count);
+    7fee:	e3 df       	rcall	.-58     	; 0x7fb6 <getch>
+    7ff0:	11 50       	subi	r17, 0x01	; 1
+    7ff2:	e9 f7       	brne	.-6      	; 0x7fee <getNch>
+  verifySpace();
+    7ff4:	f4 df       	rcall	.-24     	; 0x7fde <verifySpace>
+}
+    7ff6:	1f 91       	pop	r17
+    7ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.hex

@@ -0,0 +1,34 @@
+:107E000085E08093810082E08093C00098E19093A8
+:107E1000C10086E08093C20080E18093C40084B7F3
+:107E200014BE909360001092600081FFC1D0259A2B
+:107E300002E088E19EEFB5D0B09BFECF1D9A0150C5
+:107E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E112
+:107E5000FF2EB1D0813421F481E0C7D083E024C06B
+:107E6000823411F484E103C0853419F485E0BDD077
+:107E70008DC08535A1F49FD0082F10E0109301022A
+:107E80000093000298D090E0982F8827802B912BA8
+:107E9000880F991F909301028093000276C0863567
+:107EA00029F484E0A2D080E074D070C0843609F058
+:107EB00046C090D0863409F07BD0E0910002F0916A
+:107EC000010283E080935700E895C0E0D1E073D0D1
+:107ED0008993809102028150809302028823B9F72E
+:107EE00007B600FCFDCF7BD040910002509101020B
+:107EF000A0E0B1E02C9130E011968C91119790E0C8
+:107F0000982F8827822B932B1296FA010C01D0927E
+:107F10005700E89511244E5F5F4FF1E0A038BF078E
+:107F200049F7E0910002F0910102E0925700E895D4
+:107F300007B600FCFDCFF0925700E89527C08437C4
+:107F4000B9F448D04CD0E0910002F0910102319692
+:107F5000F0930102E09300023197E4918E2F19D043
+:107F600080910202815080930202882361F70EC043
+:107F7000853739F434D08EE10CD085E90AD08FE012
+:107F800093CF813511F4C092600029D080E101D0F7
+:107F900060CF982F8091C00085FFFCCF9093C600E2
+:107FA0000895909385008093840081E086BB0895B6
+:107FB000EE27FF2709942D988EEB90EFF2DF02C099
+:107FC000B099F6DF8091C00087FFFACF2D9A80919B
+:107FD000C6000895F0DFEFDF80930202ECCFEBDF05
+:107FE000803209F0E5DF84E1D4CF1F93182FE3DF5F
+:0A7FF0001150E9F7F4DF1F91089526
+:0400000300007E007B
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_atmega328_pro_8MHz.lst

@@ -0,0 +1,483 @@
+
+optiboot_atmega328_pro_8MHz.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00007e00  00007e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00007e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    7e00:	85 e0       	ldi	r24, 0x05	; 5
+    7e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    7e06:	82 e0       	ldi	r24, 0x02	; 2
+    7e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    7e0c:	98 e1       	ldi	r25, 0x18	; 24
+    7e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    7e12:	86 e0       	ldi	r24, 0x06	; 6
+    7e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    7e18:	80 e1       	ldi	r24, 0x10	; 16
+    7e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    7e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    7e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    7e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    7e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    7e2a:	81 ff       	sbrs	r24, 1
+    7e2c:	c1 d0       	rcall	.+386    	; 0x7fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    7e2e:	25 9a       	sbi	0x04, 5	; 4
+    7e30:	02 e0       	ldi	r16, 0x02	; 2
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    7e32:	88 e1       	ldi	r24, 0x18	; 24
+    7e34:	9e ef       	ldi	r25, 0xFE	; 254
+    7e36:	b5 d0       	rcall	.+362    	; 0x7fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    7e38:	b0 9b       	sbis	0x16, 0	; 22
+    7e3a:	fe cf       	rjmp	.-4      	; 0x7e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    7e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    7e3e:	01 50       	subi	r16, 0x01	; 1
+    7e40:	c1 f7       	brne	.-16     	; 0x7e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    7e42:	dd 24       	eor	r13, r13
+    7e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    7e46:	b8 e0       	ldi	r27, 0x08	; 8
+    7e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    7e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    7e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    7e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    7e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    7e52:	b1 d0       	rcall	.+354    	; 0x7fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    7e54:	81 34       	cpi	r24, 0x41	; 65
+    7e56:	21 f4       	brne	.+8      	; 0x7e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    7e58:	81 e0       	ldi	r24, 0x01	; 1
+    7e5a:	c7 d0       	rcall	.+398    	; 0x7fea <verifySpace+0xc>
+      putch(0x03);
+    7e5c:	83 e0       	ldi	r24, 0x03	; 3
+    7e5e:	24 c0       	rjmp	.+72     	; 0x7ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    7e60:	82 34       	cpi	r24, 0x42	; 66
+    7e62:	11 f4       	brne	.+4      	; 0x7e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    7e64:	84 e1       	ldi	r24, 0x14	; 20
+    7e66:	03 c0       	rjmp	.+6      	; 0x7e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    7e68:	85 34       	cpi	r24, 0x45	; 69
+    7e6a:	19 f4       	brne	.+6      	; 0x7e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    7e6c:	85 e0       	ldi	r24, 0x05	; 5
+    7e6e:	bd d0       	rcall	.+378    	; 0x7fea <verifySpace+0xc>
+    7e70:	8d c0       	rjmp	.+282    	; 0x7f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    7e72:	85 35       	cpi	r24, 0x55	; 85
+    7e74:	a1 f4       	brne	.+40     	; 0x7e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    7e76:	9f d0       	rcall	.+318    	; 0x7fb6 <getch>
+    7e78:	08 2f       	mov	r16, r24
+    7e7a:	10 e0       	ldi	r17, 0x00	; 0
+    7e7c:	10 93 01 02 	sts	0x0201, r17
+    7e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    7e84:	98 d0       	rcall	.+304    	; 0x7fb6 <getch>
+    7e86:	90 e0       	ldi	r25, 0x00	; 0
+    7e88:	98 2f       	mov	r25, r24
+    7e8a:	88 27       	eor	r24, r24
+    7e8c:	80 2b       	or	r24, r16
+    7e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    7e90:	88 0f       	add	r24, r24
+    7e92:	99 1f       	adc	r25, r25
+    7e94:	90 93 01 02 	sts	0x0201, r25
+    7e98:	80 93 00 02 	sts	0x0200, r24
+    7e9c:	76 c0       	rjmp	.+236    	; 0x7f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    7e9e:	86 35       	cpi	r24, 0x56	; 86
+    7ea0:	29 f4       	brne	.+10     	; 0x7eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    7ea2:	84 e0       	ldi	r24, 0x04	; 4
+    7ea4:	a2 d0       	rcall	.+324    	; 0x7fea <verifySpace+0xc>
+      putch(0x00);
+    7ea6:	80 e0       	ldi	r24, 0x00	; 0
+    7ea8:	74 d0       	rcall	.+232    	; 0x7f92 <putch>
+    7eaa:	70 c0       	rjmp	.+224    	; 0x7f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    7eac:	84 36       	cpi	r24, 0x64	; 100
+    7eae:	09 f0       	breq	.+2      	; 0x7eb2 <main+0xb2>
+    7eb0:	46 c0       	rjmp	.+140    	; 0x7f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    7eb2:	90 d0       	rcall	.+288    	; 0x7fd4 <getLen>
+    7eb4:	86 34       	cpi	r24, 0x46	; 70
+    7eb6:	09 f0       	breq	.+2      	; 0x7eba <main+0xba>
+    7eb8:	7b d0       	rcall	.+246    	; 0x7fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    7eba:	e0 91 00 02 	lds	r30, 0x0200
+    7ebe:	f0 91 01 02 	lds	r31, 0x0201
+    7ec2:	83 e0       	ldi	r24, 0x03	; 3
+    7ec4:	80 93 57 00 	sts	0x0057, r24
+    7ec8:	e8 95       	spm
+    7eca:	c0 e0       	ldi	r28, 0x00	; 0
+    7ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    7ece:	73 d0       	rcall	.+230    	; 0x7fb6 <getch>
+    7ed0:	89 93       	st	Y+, r24
+      while (--length);
+    7ed2:	80 91 02 02 	lds	r24, 0x0202
+    7ed6:	81 50       	subi	r24, 0x01	; 1
+    7ed8:	80 93 02 02 	sts	0x0202, r24
+    7edc:	88 23       	and	r24, r24
+    7ede:	b9 f7       	brne	.-18     	; 0x7ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    7ee0:	07 b6       	in	r0, 0x37	; 55
+    7ee2:	00 fc       	sbrc	r0, 0
+    7ee4:	fd cf       	rjmp	.-6      	; 0x7ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    7ee6:	7b d0       	rcall	.+246    	; 0x7fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    7ee8:	40 91 00 02 	lds	r20, 0x0200
+    7eec:	50 91 01 02 	lds	r21, 0x0201
+    7ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    7ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    7ef4:	2c 91       	ld	r18, X
+    7ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    7ef8:	11 96       	adiw	r26, 0x01	; 1
+    7efa:	8c 91       	ld	r24, X
+    7efc:	11 97       	sbiw	r26, 0x01	; 1
+    7efe:	90 e0       	ldi	r25, 0x00	; 0
+    7f00:	98 2f       	mov	r25, r24
+    7f02:	88 27       	eor	r24, r24
+    7f04:	82 2b       	or	r24, r18
+    7f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    7f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    7f0a:	fa 01       	movw	r30, r20
+    7f0c:	0c 01       	movw	r0, r24
+    7f0e:	d0 92 57 00 	sts	0x0057, r13
+    7f12:	e8 95       	spm
+    7f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    7f16:	4e 5f       	subi	r20, 0xFE	; 254
+    7f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    7f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    7f1c:	a0 38       	cpi	r26, 0x80	; 128
+    7f1e:	bf 07       	cpc	r27, r31
+    7f20:	49 f7       	brne	.-46     	; 0x7ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    7f22:	e0 91 00 02 	lds	r30, 0x0200
+    7f26:	f0 91 01 02 	lds	r31, 0x0201
+    7f2a:	e0 92 57 00 	sts	0x0057, r14
+    7f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    7f30:	07 b6       	in	r0, 0x37	; 55
+    7f32:	00 fc       	sbrc	r0, 0
+    7f34:	fd cf       	rjmp	.-6      	; 0x7f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    7f36:	f0 92 57 00 	sts	0x0057, r15
+    7f3a:	e8 95       	spm
+    7f3c:	27 c0       	rjmp	.+78     	; 0x7f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    7f3e:	84 37       	cpi	r24, 0x74	; 116
+    7f40:	b9 f4       	brne	.+46     	; 0x7f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    7f42:	48 d0       	rcall	.+144    	; 0x7fd4 <getLen>
+      verifySpace();
+    7f44:	4c d0       	rcall	.+152    	; 0x7fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    7f46:	e0 91 00 02 	lds	r30, 0x0200
+    7f4a:	f0 91 01 02 	lds	r31, 0x0201
+    7f4e:	31 96       	adiw	r30, 0x01	; 1
+    7f50:	f0 93 01 02 	sts	0x0201, r31
+    7f54:	e0 93 00 02 	sts	0x0200, r30
+    7f58:	31 97       	sbiw	r30, 0x01	; 1
+    7f5a:	e4 91       	lpm	r30, Z+
+    7f5c:	8e 2f       	mov	r24, r30
+    7f5e:	19 d0       	rcall	.+50     	; 0x7f92 <putch>
+      while (--length);
+    7f60:	80 91 02 02 	lds	r24, 0x0202
+    7f64:	81 50       	subi	r24, 0x01	; 1
+    7f66:	80 93 02 02 	sts	0x0202, r24
+    7f6a:	88 23       	and	r24, r24
+    7f6c:	61 f7       	brne	.-40     	; 0x7f46 <main+0x146>
+    7f6e:	0e c0       	rjmp	.+28     	; 0x7f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    7f70:	85 37       	cpi	r24, 0x75	; 117
+    7f72:	39 f4       	brne	.+14     	; 0x7f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    7f74:	34 d0       	rcall	.+104    	; 0x7fde <verifySpace>
+      putch(SIGNATURE_0);
+    7f76:	8e e1       	ldi	r24, 0x1E	; 30
+    7f78:	0c d0       	rcall	.+24     	; 0x7f92 <putch>
+      putch(SIGNATURE_1);
+    7f7a:	85 e9       	ldi	r24, 0x95	; 149
+    7f7c:	0a d0       	rcall	.+20     	; 0x7f92 <putch>
+      putch(SIGNATURE_2);
+    7f7e:	8f e0       	ldi	r24, 0x0F	; 15
+    7f80:	93 cf       	rjmp	.-218    	; 0x7ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    7f82:	81 35       	cpi	r24, 0x51	; 81
+    7f84:	11 f4       	brne	.+4      	; 0x7f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    7f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    7f8a:	29 d0       	rcall	.+82     	; 0x7fde <verifySpace>
+    }
+    putch(STK_OK);
+    7f8c:	80 e1       	ldi	r24, 0x10	; 16
+    7f8e:	01 d0       	rcall	.+2      	; 0x7f92 <putch>
+    7f90:	60 cf       	rjmp	.-320    	; 0x7e52 <main+0x52>
+
+00007f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    7f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    7f94:	80 91 c0 00 	lds	r24, 0x00C0
+    7f98:	85 ff       	sbrs	r24, 5
+    7f9a:	fc cf       	rjmp	.-8      	; 0x7f94 <putch+0x2>
+  UDR0 = ch;
+    7f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    7fa0:	08 95       	ret
+
+00007fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    7fa2:	90 93 85 00 	sts	0x0085, r25
+    7fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    7faa:	81 e0       	ldi	r24, 0x01	; 1
+    7fac:	86 bb       	out	0x16, r24	; 22
+}
+    7fae:	08 95       	ret
+
+00007fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    7fb0:	ee 27       	eor	r30, r30
+    7fb2:	ff 27       	eor	r31, r31
+    7fb4:	09 94       	ijmp
+
+00007fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    7fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    7fb8:	8e eb       	ldi	r24, 0xBE	; 190
+    7fba:	90 ef       	ldi	r25, 0xF0	; 240
+    7fbc:	f2 df       	rcall	.-28     	; 0x7fa2 <setTimer>
+    7fbe:	02 c0       	rjmp	.+4      	; 0x7fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    7fc0:	b0 99       	sbic	0x16, 0	; 22
+    7fc2:	f6 df       	rcall	.-20     	; 0x7fb0 <appStart>
+    7fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    7fc8:	87 ff       	sbrs	r24, 7
+    7fca:	fa cf       	rjmp	.-12     	; 0x7fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    7fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    7fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    7fd2:	08 95       	ret
+
+00007fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    7fd4:	f0 df       	rcall	.-32     	; 0x7fb6 <getch>
+  length = getch();
+    7fd6:	ef df       	rcall	.-34     	; 0x7fb6 <getch>
+    7fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    7fdc:	ec cf       	rjmp	.-40     	; 0x7fb6 <getch>
+
+00007fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    7fde:	eb df       	rcall	.-42     	; 0x7fb6 <getch>
+    7fe0:	80 32       	cpi	r24, 0x20	; 32
+    7fe2:	09 f0       	breq	.+2      	; 0x7fe6 <verifySpace+0x8>
+    7fe4:	e5 df       	rcall	.-54     	; 0x7fb0 <appStart>
+  putch(STK_INSYNC);
+    7fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    7fe8:	d4 cf       	rjmp	.-88     	; 0x7f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    7fea:	1f 93       	push	r17
+    7fec:	18 2f       	mov	r17, r24
+
+00007fee <getNch>:
+  do getch(); while (--count);
+    7fee:	e3 df       	rcall	.-58     	; 0x7fb6 <getch>
+    7ff0:	11 50       	subi	r17, 0x01	; 1
+    7ff2:	e9 f7       	brne	.-6      	; 0x7fee <getNch>
+  verifySpace();
+    7ff4:	f4 df       	rcall	.-24     	; 0x7fde <verifySpace>
+}
+    7ff6:	1f 91       	pop	r17
+    7ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_diecimila.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20087E68093C40084B727
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300002E080E39CEFB5D0B09BFECF1D9A01500D
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_diecimila.lst

@@ -0,0 +1,483 @@
+
+optiboot_diecimila.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	87 e6       	ldi	r24, 0x67	; 103
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	02 e0       	ldi	r16, 0x02	; 2
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	80 e3       	ldi	r24, 0x30	; 48
+    3e34:	9c ef       	ldi	r25, 0xFC	; 252
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
+    3fba:	91 ee       	ldi	r25, 0xE1	; 225
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_lilypad.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20083E38093C40084B72E
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300006E088E19EEFB5D0B09BFECF1D9A015001
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_lilypad.lst

@@ -0,0 +1,483 @@
+
+optiboot_lilypad.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	83 e3       	ldi	r24, 0x33	; 51
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	06 e0       	ldi	r16, 0x06	; 6
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	88 e1       	ldi	r24, 0x18	; 24
+    3e34:	9e ef       	ldi	r25, 0xFE	; 254
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
+    3fba:	90 ef       	ldi	r25, 0xF0	; 240
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20083E38093C40084B72E
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300006E088E19EEFB5D0B09BFECF1D9A015001
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_lilypad_resonator.lst

@@ -0,0 +1,483 @@
+
+optiboot_lilypad_resonator.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	83 e3       	ldi	r24, 0x33	; 51
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	06 e0       	ldi	r16, 0x06	; 6
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	88 e1       	ldi	r24, 0x18	; 24
+    3e34:	9e ef       	ldi	r25, 0xFE	; 254
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
+    3fba:	90 ef       	ldi	r25, 0xF0	; 240
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_ng.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20087E68093C40084B727
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300006E080E39CEFB5D0B09BFECF1D9A015009
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_ng.lst

@@ -0,0 +1,483 @@
+
+optiboot_ng.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	87 e6       	ldi	r24, 0x67	; 103
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	06 e0       	ldi	r16, 0x06	; 6
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	80 e3       	ldi	r24, 0x30	; 48
+    3e34:	9c ef       	ldi	r25, 0xFC	; 252
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
+    3fba:	91 ee       	ldi	r25, 0xE1	; 225
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20087E68093C40084B727
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300002E080E39CEFB5D0B09BFECF1D9A01500D
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988CE791EEF2DF02C0DF
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_pro_16MHz.lst

@@ -0,0 +1,483 @@
+
+optiboot_pro_16MHz.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	87 e6       	ldi	r24, 0x67	; 103
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	02 e0       	ldi	r16, 0x02	; 2
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	80 e3       	ldi	r24, 0x30	; 48
+    3e34:	9c ef       	ldi	r25, 0xFC	; 252
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8c e7       	ldi	r24, 0x7C	; 124
+    3fba:	91 ee       	ldi	r25, 0xE1	; 225
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20081E88093C40084B72B
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300002E08CE39BEFB5D0B09BFECF1D9A015002
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988BED99EDF2DF02C0D3
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_pro_20mhz.lst

@@ -0,0 +1,483 @@
+
+optiboot_pro_20mhz.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	81 e8       	ldi	r24, 0x81	; 129
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	02 e0       	ldi	r16, 0x02	; 2
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	8c e3       	ldi	r24, 0x3C	; 60
+    3e34:	9b ef       	ldi	r25, 0xFB	; 251
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8b ed       	ldi	r24, 0xDB	; 219
+    3fba:	99 ed       	ldi	r25, 0xD9	; 217
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 34 - 0
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.hex

@@ -0,0 +1,34 @@
+:103E000085E08093810082E08093C00098E19093E8
+:103E1000C10086E08093C20083E38093C40084B72E
+:103E200014BE909360001092600081FFC1D0259A6B
+:103E300002E088E19EEFB5D0B09BFECF1D9A015005
+:103E4000C1F7DD24D394B8E0CB2EA5E0EA2EF1E152
+:103E5000FF2EB1D0813421F481E0C7D083E024C0AB
+:103E6000823411F484E103C0853419F485E0BDD0B7
+:103E70008DC08535A1F49FD0082F10E0109301026A
+:103E80000093000298D090E0982F8827802B912BE8
+:103E9000880F991F909301028093000276C08635A7
+:103EA00029F484E0A2D080E074D070C0843609F098
+:103EB00046C090D0863409F07BD0E0910002F091AA
+:103EC000010283E080935700E895C0E0D1E073D011
+:103ED0008993809102028150809302028823B9F76E
+:103EE00007B600FCFDCF7BD040910002509101024B
+:103EF000A0E0B1E02C9130E011968C91119790E008
+:103F0000982F8827822B932B1296FA010C01D092BE
+:103F10005700E89511244E5F5F4FF1E0A038BF07CE
+:103F200049F7E0910002F0910102E0925700E89514
+:103F300007B600FCFDCFF0925700E89527C0843704
+:103F4000B9F448D04CD0E0910002F09101023196D2
+:103F5000F0930102E09300023197E4918E2F19D083
+:103F600080910202815080930202882361F70EC083
+:103F7000853739F434D08EE10CD084E90AD086E05C
+:103F800093CF813511F4C092600029D080E101D037
+:103F900060CF982F8091C00085FFFCCF9093C60022
+:103FA0000895909385008093840081E086BB0895F6
+:103FB000EE27FF2709942D988EEB90EFF2DF02C0D9
+:103FC000B099F6DF8091C00087FFFACF2D9A8091DB
+:103FD000C6000895F0DFEFDF80930202ECCFEBDF45
+:103FE000803209F0E5DF84E1D4CF1F93182FE3DF9F
+:0A3FF0001150E9F7F4DF1F91089566
+:0400000300003E00BB
+:00000001FF

+ 483 - 0
optiboot/bootloaders/optiboot/optiboot_pro_8MHz.lst

@@ -0,0 +1,483 @@
+
+optiboot_pro_8MHz.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001fa  00003e00  00003e00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000024e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000064  00000000  00000000  00000276  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   0000022f  00000000  00000000  000002da  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 00000164  00000000  00000000  00000509  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003c8  00000000  00000000  0000066d  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000a38  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000011c  00000000  00000000  00000ac8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d6  00000000  00000000  00000be4  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000dba  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00003e00 <main>:
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3e00:	85 e0       	ldi	r24, 0x05	; 5
+    3e02:	80 93 81 00 	sts	0x0081, r24
+    [addr5]"i"(_SFR_MEM_ADDR(UBRR0L)), [val5]"i"((F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1)
+  );
+#else
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    3e06:	82 e0       	ldi	r24, 0x02	; 2
+    3e08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    3e0c:	98 e1       	ldi	r25, 0x18	; 24
+    3e0e:	90 93 c1 00 	sts	0x00C1, r25
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    3e12:	86 e0       	ldi	r24, 0x06	; 6
+    3e14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    3e18:	83 e3       	ldi	r24, 0x33	; 51
+    3e1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    3e1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    3e20:	14 be       	out	0x34, r1	; 52
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    3e22:	90 93 60 00 	sts	0x0060, r25
+  WDTCSR = 0;
+    3e26:	10 92 60 00 	sts	0x0060, r1
+  if (!(ch & _BV(EXTRF))) appStart();
+    3e2a:	81 ff       	sbrs	r24, 1
+    3e2c:	c1 d0       	rcall	.+386    	; 0x3fb0 <appStart>
+
+  /* set LED pin as output */
+  LED_DDR |= _BV(LED);
+    3e2e:	25 9a       	sbi	0x04, 5	; 4
+    3e30:	02 e0       	ldi	r16, 0x02	; 2
+  putch(STK_INSYNC);
+}
+
+void flash_led(uint8_t count) {
+  do {
+    setTimer(-(F_CPU/(1024*16))); // 62ms
+    3e32:	88 e1       	ldi	r24, 0x18	; 24
+    3e34:	9e ef       	ldi	r25, 0xFE	; 254
+    3e36:	b5 d0       	rcall	.+362    	; 0x3fa2 <setTimer>
+    while(!(TIFR1 & _BV(TOV1)));
+    3e38:	b0 9b       	sbis	0x16, 0	; 22
+    3e3a:	fe cf       	rjmp	.-4      	; 0x3e38 <main+0x38>
+    LED_PIN |= _BV(LED);
+    3e3c:	1d 9a       	sbi	0x03, 5	; 3
+  } while (--count);
+    3e3e:	01 50       	subi	r16, 0x01	; 1
+    3e40:	c1 f7       	brne	.-16     	; 0x3e32 <main+0x32>
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e42:	dd 24       	eor	r13, r13
+    3e44:	d3 94       	inc	r13
+      putch(SIGNATURE_1);
+      putch(SIGNATURE_2);
+    }
+    else if (ch == 'Q') {
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3e46:	b8 e0       	ldi	r27, 0x08	; 8
+    3e48:	cb 2e       	mov	r12, r27
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3e4a:	a5 e0       	ldi	r26, 0x05	; 5
+    3e4c:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3e4e:	f1 e1       	ldi	r31, 0x11	; 17
+    3e50:	ff 2e       	mov	r15, r31
+  flash_led(NUM_LED_FLASHES * 2);
+
+  /* forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    3e52:	b1 d0       	rcall	.+354    	; 0x3fb6 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    3e54:	81 34       	cpi	r24, 0x41	; 65
+    3e56:	21 f4       	brne	.+8      	; 0x3e60 <main+0x60>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    3e58:	81 e0       	ldi	r24, 0x01	; 1
+    3e5a:	c7 d0       	rcall	.+398    	; 0x3fea <verifySpace+0xc>
+      putch(0x03);
+    3e5c:	83 e0       	ldi	r24, 0x03	; 3
+    3e5e:	24 c0       	rjmp	.+72     	; 0x3ea8 <main+0xa8>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    3e60:	82 34       	cpi	r24, 0x42	; 66
+    3e62:	11 f4       	brne	.+4      	; 0x3e68 <main+0x68>
+      // SET DEVICE is ignored
+      getNch(20);
+    3e64:	84 e1       	ldi	r24, 0x14	; 20
+    3e66:	03 c0       	rjmp	.+6      	; 0x3e6e <main+0x6e>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    3e68:	85 34       	cpi	r24, 0x45	; 69
+    3e6a:	19 f4       	brne	.+6      	; 0x3e72 <main+0x72>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    3e6c:	85 e0       	ldi	r24, 0x05	; 5
+    3e6e:	bd d0       	rcall	.+378    	; 0x3fea <verifySpace+0xc>
+    3e70:	8d c0       	rjmp	.+282    	; 0x3f8c <main+0x18c>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    3e72:	85 35       	cpi	r24, 0x55	; 85
+    3e74:	a1 f4       	brne	.+40     	; 0x3e9e <main+0x9e>
+      // LOAD ADDRESS
+      address = getch();
+    3e76:	9f d0       	rcall	.+318    	; 0x3fb6 <getch>
+    3e78:	08 2f       	mov	r16, r24
+    3e7a:	10 e0       	ldi	r17, 0x00	; 0
+    3e7c:	10 93 01 02 	sts	0x0201, r17
+    3e80:	00 93 00 02 	sts	0x0200, r16
+      address = (address & 0xff) | (getch() << 8);
+    3e84:	98 d0       	rcall	.+304    	; 0x3fb6 <getch>
+    3e86:	90 e0       	ldi	r25, 0x00	; 0
+    3e88:	98 2f       	mov	r25, r24
+    3e8a:	88 27       	eor	r24, r24
+    3e8c:	80 2b       	or	r24, r16
+    3e8e:	91 2b       	or	r25, r17
+      address += address; // Convert from word address to byte address
+    3e90:	88 0f       	add	r24, r24
+    3e92:	99 1f       	adc	r25, r25
+    3e94:	90 93 01 02 	sts	0x0201, r25
+    3e98:	80 93 00 02 	sts	0x0200, r24
+    3e9c:	76 c0       	rjmp	.+236    	; 0x3f8a <main+0x18a>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    3e9e:	86 35       	cpi	r24, 0x56	; 86
+    3ea0:	29 f4       	brne	.+10     	; 0x3eac <main+0xac>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    3ea2:	84 e0       	ldi	r24, 0x04	; 4
+    3ea4:	a2 d0       	rcall	.+324    	; 0x3fea <verifySpace+0xc>
+      putch(0x00);
+    3ea6:	80 e0       	ldi	r24, 0x00	; 0
+    3ea8:	74 d0       	rcall	.+232    	; 0x3f92 <putch>
+    3eaa:	70 c0       	rjmp	.+224    	; 0x3f8c <main+0x18c>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    3eac:	84 36       	cpi	r24, 0x64	; 100
+    3eae:	09 f0       	breq	.+2      	; 0x3eb2 <main+0xb2>
+    3eb0:	46 c0       	rjmp	.+140    	; 0x3f3e <main+0x13e>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+      
+      if (getLen() != 'F') appStart(); // Abort is not flash programming
+    3eb2:	90 d0       	rcall	.+288    	; 0x3fd4 <getLen>
+    3eb4:	86 34       	cpi	r24, 0x46	; 70
+    3eb6:	09 f0       	breq	.+2      	; 0x3eba <main+0xba>
+    3eb8:	7b d0       	rcall	.+246    	; 0x3fb0 <appStart>
+  
+      // Immediately start page erase - this will 4.5ms
+      boot_page_erase((uint16_t)(void*)address);
+    3eba:	e0 91 00 02 	lds	r30, 0x0200
+    3ebe:	f0 91 01 02 	lds	r31, 0x0201
+    3ec2:	83 e0       	ldi	r24, 0x03	; 3
+    3ec4:	80 93 57 00 	sts	0x0057, r24
+    3ec8:	e8 95       	spm
+    3eca:	c0 e0       	ldi	r28, 0x00	; 0
+    3ecc:	d1 e0       	ldi	r29, 0x01	; 1
+
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    3ece:	73 d0       	rcall	.+230    	; 0x3fb6 <getch>
+    3ed0:	89 93       	st	Y+, r24
+      while (--length);
+    3ed2:	80 91 02 02 	lds	r24, 0x0202
+    3ed6:	81 50       	subi	r24, 0x01	; 1
+    3ed8:	80 93 02 02 	sts	0x0202, r24
+    3edc:	88 23       	and	r24, r24
+    3ede:	b9 f7       	brne	.-18     	; 0x3ece <main+0xce>
+
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    3ee0:	07 b6       	in	r0, 0x37	; 55
+    3ee2:	00 fc       	sbrc	r0, 0
+    3ee4:	fd cf       	rjmp	.-6      	; 0x3ee0 <main+0xe0>
+
+      // Read command terminator, start reply
+      verifySpace();
+    3ee6:	7b d0       	rcall	.+246    	; 0x3fde <verifySpace>
+      
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    3ee8:	40 91 00 02 	lds	r20, 0x0200
+    3eec:	50 91 01 02 	lds	r21, 0x0201
+    3ef0:	a0 e0       	ldi	r26, 0x00	; 0
+    3ef2:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    3ef4:	2c 91       	ld	r18, X
+    3ef6:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    3ef8:	11 96       	adiw	r26, 0x01	; 1
+    3efa:	8c 91       	ld	r24, X
+    3efc:	11 97       	sbiw	r26, 0x01	; 1
+    3efe:	90 e0       	ldi	r25, 0x00	; 0
+    3f00:	98 2f       	mov	r25, r24
+    3f02:	88 27       	eor	r24, r24
+    3f04:	82 2b       	or	r24, r18
+    3f06:	93 2b       	or	r25, r19
+#define buff    ((uint8_t*)(0x100))
+#define address (*(uint16_t*)(0x200))
+#define length  (*(uint8_t*)(0x202))
+
+/* main program starts here */
+int main(void) {
+    3f08:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        boot_page_fill((uint16_t)(void*)addrPtr,a);
+    3f0a:	fa 01       	movw	r30, r20
+    3f0c:	0c 01       	movw	r0, r24
+    3f0e:	d0 92 57 00 	sts	0x0057, r13
+    3f12:	e8 95       	spm
+    3f14:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    3f16:	4e 5f       	subi	r20, 0xFE	; 254
+    3f18:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    3f1a:	f1 e0       	ldi	r31, 0x01	; 1
+    3f1c:	a0 38       	cpi	r26, 0x80	; 128
+    3f1e:	bf 07       	cpc	r27, r31
+    3f20:	49 f7       	brne	.-46     	; 0x3ef4 <main+0xf4>
+      
+      // Write from programming buffer
+      boot_page_write((uint16_t)(void*)address);
+    3f22:	e0 91 00 02 	lds	r30, 0x0200
+    3f26:	f0 91 01 02 	lds	r31, 0x0201
+    3f2a:	e0 92 57 00 	sts	0x0057, r14
+    3f2e:	e8 95       	spm
+      boot_spm_busy_wait();
+    3f30:	07 b6       	in	r0, 0x37	; 55
+    3f32:	00 fc       	sbrc	r0, 0
+    3f34:	fd cf       	rjmp	.-6      	; 0x3f30 <main+0x130>
+
+      // Reenable read access to flash
+      boot_rww_enable();
+    3f36:	f0 92 57 00 	sts	0x0057, r15
+    3f3a:	e8 95       	spm
+    3f3c:	27 c0       	rjmp	.+78     	; 0x3f8c <main+0x18c>
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    3f3e:	84 37       	cpi	r24, 0x74	; 116
+    3f40:	b9 f4       	brne	.+46     	; 0x3f70 <main+0x170>
+      // READ PAGE - we only read flash
+      getLen();
+    3f42:	48 d0       	rcall	.+144    	; 0x3fd4 <getLen>
+      verifySpace();
+    3f44:	4c d0       	rcall	.+152    	; 0x3fde <verifySpace>
+      do putch(pgm_read_byte_near(address++));
+    3f46:	e0 91 00 02 	lds	r30, 0x0200
+    3f4a:	f0 91 01 02 	lds	r31, 0x0201
+    3f4e:	31 96       	adiw	r30, 0x01	; 1
+    3f50:	f0 93 01 02 	sts	0x0201, r31
+    3f54:	e0 93 00 02 	sts	0x0200, r30
+    3f58:	31 97       	sbiw	r30, 0x01	; 1
+    3f5a:	e4 91       	lpm	r30, Z+
+    3f5c:	8e 2f       	mov	r24, r30
+    3f5e:	19 d0       	rcall	.+50     	; 0x3f92 <putch>
+      while (--length);
+    3f60:	80 91 02 02 	lds	r24, 0x0202
+    3f64:	81 50       	subi	r24, 0x01	; 1
+    3f66:	80 93 02 02 	sts	0x0202, r24
+    3f6a:	88 23       	and	r24, r24
+    3f6c:	61 f7       	brne	.-40     	; 0x3f46 <main+0x146>
+    3f6e:	0e c0       	rjmp	.+28     	; 0x3f8c <main+0x18c>
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    3f70:	85 37       	cpi	r24, 0x75	; 117
+    3f72:	39 f4       	brne	.+14     	; 0x3f82 <main+0x182>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    3f74:	34 d0       	rcall	.+104    	; 0x3fde <verifySpace>
+      putch(SIGNATURE_0);
+    3f76:	8e e1       	ldi	r24, 0x1E	; 30
+    3f78:	0c d0       	rcall	.+24     	; 0x3f92 <putch>
+      putch(SIGNATURE_1);
+    3f7a:	84 e9       	ldi	r24, 0x94	; 148
+    3f7c:	0a d0       	rcall	.+20     	; 0x3f92 <putch>
+      putch(SIGNATURE_2);
+    3f7e:	86 e0       	ldi	r24, 0x06	; 6
+    3f80:	93 cf       	rjmp	.-218    	; 0x3ea8 <main+0xa8>
+    }
+    else if (ch == 'Q') {
+    3f82:	81 35       	cpi	r24, 0x51	; 81
+    3f84:	11 f4       	brne	.+4      	; 0x3f8a <main+0x18a>
+      // Adaboot no-wait mod
+      WDTCSR = _BV(WDE);
+    3f86:	c0 92 60 00 	sts	0x0060, r12
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    3f8a:	29 d0       	rcall	.+82     	; 0x3fde <verifySpace>
+    }
+    putch(STK_OK);
+    3f8c:	80 e1       	ldi	r24, 0x10	; 16
+    3f8e:	01 d0       	rcall	.+2      	; 0x3f92 <putch>
+    3f90:	60 cf       	rjmp	.-320    	; 0x3e52 <main+0x52>
+
+00003f92 <putch>:
+  }
+}
+
+void putch(char ch) {
+    3f92:	98 2f       	mov	r25, r24
+  while (!(UCSR0A & _BV(UDRE0)));
+    3f94:	80 91 c0 00 	lds	r24, 0x00C0
+    3f98:	85 ff       	sbrs	r24, 5
+    3f9a:	fc cf       	rjmp	.-8      	; 0x3f94 <putch+0x2>
+  UDR0 = ch;
+    3f9c:	90 93 c6 00 	sts	0x00C6, r25
+}
+    3fa0:	08 95       	ret
+
+00003fa2 <setTimer>:
+
+void setTimer(uint16_t counts) {
+  TCNT1 = counts;
+    3fa2:	90 93 85 00 	sts	0x0085, r25
+    3fa6:	80 93 84 00 	sts	0x0084, r24
+  TIFR1 = _BV(TOV1);
+    3faa:	81 e0       	ldi	r24, 0x01	; 1
+    3fac:	86 bb       	out	0x16, r24	; 22
+}
+    3fae:	08 95       	ret
+
+00003fb0 <appStart>:
+  length = getch();
+  return getch();
+}
+
+void appStart() {
+  __asm__ __volatile__ (
+    3fb0:	ee 27       	eor	r30, r30
+    3fb2:	ff 27       	eor	r31, r31
+    3fb4:	09 94       	ijmp
+
+00003fb6 <getch>:
+  TCNT1 = counts;
+  TIFR1 = _BV(TOV1);
+}
+
+uint8_t getch(void) {
+  LED_PORT &= ~_BV(LED);
+    3fb6:	2d 98       	cbi	0x05, 5	; 5
+  setTimer(-(F_CPU/(1024*2))); // 500ms
+    3fb8:	8e eb       	ldi	r24, 0xBE	; 190
+    3fba:	90 ef       	ldi	r25, 0xF0	; 240
+    3fbc:	f2 df       	rcall	.-28     	; 0x3fa2 <setTimer>
+    3fbe:	02 c0       	rjmp	.+4      	; 0x3fc4 <getch+0xe>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+    3fc0:	b0 99       	sbic	0x16, 0	; 22
+    3fc2:	f6 df       	rcall	.-20     	; 0x3fb0 <appStart>
+    3fc4:	80 91 c0 00 	lds	r24, 0x00C0
+    3fc8:	87 ff       	sbrs	r24, 7
+    3fca:	fa cf       	rjmp	.-12     	; 0x3fc0 <getch+0xa>
+  LED_PORT |= _BV(LED);
+    3fcc:	2d 9a       	sbi	0x05, 5	; 5
+  return UDR0;
+    3fce:	80 91 c6 00 	lds	r24, 0x00C6
+}
+    3fd2:	08 95       	ret
+
+00003fd4 <getLen>:
+    LED_PIN |= _BV(LED);
+  } while (--count);
+}
+
+uint8_t getLen() {
+  getch();
+    3fd4:	f0 df       	rcall	.-32     	; 0x3fb6 <getch>
+  length = getch();
+    3fd6:	ef df       	rcall	.-34     	; 0x3fb6 <getch>
+    3fd8:	80 93 02 02 	sts	0x0202, r24
+  return getch();
+}
+    3fdc:	ec cf       	rjmp	.-40     	; 0x3fb6 <getch>
+
+00003fde <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    3fde:	eb df       	rcall	.-42     	; 0x3fb6 <getch>
+    3fe0:	80 32       	cpi	r24, 0x20	; 32
+    3fe2:	09 f0       	breq	.+2      	; 0x3fe6 <verifySpace+0x8>
+    3fe4:	e5 df       	rcall	.-54     	; 0x3fb0 <appStart>
+  putch(STK_INSYNC);
+    3fe6:	84 e1       	ldi	r24, 0x14	; 20
+}
+    3fe8:	d4 cf       	rjmp	.-88     	; 0x3f92 <putch>
+  while(!(UCSR0A & _BV(RXC0))) if (TIFR1 & _BV(TOV1)) appStart();
+  LED_PORT |= _BV(LED);
+  return UDR0;
+}
+
+void getNch(uint8_t count) {
+    3fea:	1f 93       	push	r17
+    3fec:	18 2f       	mov	r17, r24
+
+00003fee <getNch>:
+  do getch(); while (--count);
+    3fee:	e3 df       	rcall	.-58     	; 0x3fb6 <getch>
+    3ff0:	11 50       	subi	r17, 0x01	; 1
+    3ff2:	e9 f7       	brne	.-6      	; 0x3fee <getNch>
+  verifySpace();
+    3ff4:	f4 df       	rcall	.-24     	; 0x3fde <verifySpace>
+}
+    3ff6:	1f 91       	pop	r17
+    3ff8:	08 95       	ret

+ 226 - 0
optiboot/cores/arduino/HardwareSerial.cpp

@@ -0,0 +1,226 @@
+/*
+  HardwareSerial.cpp - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  
+  Modified 23 November 2006 by David A. Mellis
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include "wiring.h"
+#include "wiring_private.h"
+
+#include "HardwareSerial.h"
+
+// Define constants and variables for buffering incoming serial data.  We're
+// using a ring buffer (I think), in which rx_buffer_head is the index of the
+// location to which to write the next incoming character and rx_buffer_tail
+// is the index of the location from which to read.
+#define RX_BUFFER_SIZE 128
+
+struct ring_buffer {
+  unsigned char buffer[RX_BUFFER_SIZE];
+  int head;
+  int tail;
+};
+
+ring_buffer rx_buffer = { { 0 }, 0, 0 };
+
+#if defined(__AVR_ATmega1280__)
+ring_buffer rx_buffer1 = { { 0 }, 0, 0 };
+ring_buffer rx_buffer2 = { { 0 }, 0, 0 };
+ring_buffer rx_buffer3 = { { 0 }, 0, 0 };
+#endif
+
+inline void store_char(unsigned char c, ring_buffer *rx_buffer)
+{
+  int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;
+
+  // if we should be storing the received character into the location
+  // just before the tail (meaning that the head would advance to the
+  // current location of the tail), we're about to overflow the buffer
+  // and so we don't write the character or advance the head.
+  if (i != rx_buffer->tail) {
+    rx_buffer->buffer[rx_buffer->head] = c;
+    rx_buffer->head = i;
+  }
+}
+
+#if defined(__AVR_ATmega1280__)
+
+SIGNAL(SIG_USART0_RECV)
+{
+  unsigned char c = UDR0;
+  store_char(c, &rx_buffer);
+}
+
+SIGNAL(SIG_USART1_RECV)
+{
+  unsigned char c = UDR1;
+  store_char(c, &rx_buffer1);
+}
+
+SIGNAL(SIG_USART2_RECV)
+{
+  unsigned char c = UDR2;
+  store_char(c, &rx_buffer2);
+}
+
+SIGNAL(SIG_USART3_RECV)
+{
+  unsigned char c = UDR3;
+  store_char(c, &rx_buffer3);
+}
+
+#else
+
+#if defined(__AVR_ATmega8__)
+SIGNAL(SIG_UART_RECV)
+#else
+SIGNAL(USART_RX_vect)
+#endif
+{
+#if defined(__AVR_ATmega8__)
+  unsigned char c = UDR;
+#else
+  unsigned char c = UDR0;
+#endif
+  store_char(c, &rx_buffer);
+}
+
+#endif
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
+  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
+  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
+  volatile uint8_t *udr,
+  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
+{
+  _rx_buffer = rx_buffer;
+  _ubrrh = ubrrh;
+  _ubrrl = ubrrl;
+  _ucsra = ucsra;
+  _ucsrb = ucsrb;
+  _udr = udr;
+  _rxen = rxen;
+  _txen = txen;
+  _rxcie = rxcie;
+  _udre = udre;
+  _u2x = u2x;
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void HardwareSerial::begin(long baud)
+{
+  uint16_t baud_setting;
+  bool use_u2x;
+
+  // U2X mode is needed for baud rates higher than (CPU Hz / 16)
+  if (baud > F_CPU / 16) {
+    use_u2x = true;
+  } else {
+    // figure out if U2X mode would allow for a better connection
+    
+    // calculate the percent difference between the baud-rate specified and
+    // the real baud rate for both U2X and non-U2X mode (0-255 error percent)
+    uint8_t nonu2x_baud_error = abs((int)(255-((F_CPU/(16*(((F_CPU/8/baud-1)/2)+1))*255)/baud)));
+    uint8_t u2x_baud_error = abs((int)(255-((F_CPU/(8*(((F_CPU/4/baud-1)/2)+1))*255)/baud)));
+    
+    // prefer non-U2X mode because it handles clock skew better
+    use_u2x = (nonu2x_baud_error > u2x_baud_error);
+  }
+  
+  if (use_u2x) {
+    *_ucsra = 1 << _u2x;
+    baud_setting = (F_CPU / 4 / baud - 1) / 2;
+  } else {
+    *_ucsra = 0;
+    baud_setting = (F_CPU / 8 / baud - 1) / 2;
+  }
+
+  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
+  *_ubrrh = baud_setting >> 8;
+  *_ubrrl = baud_setting;
+
+  sbi(*_ucsrb, _rxen);
+  sbi(*_ucsrb, _txen);
+  sbi(*_ucsrb, _rxcie);
+}
+
+void HardwareSerial::end()
+{
+  cbi(*_ucsrb, _rxen);
+  cbi(*_ucsrb, _txen);
+  cbi(*_ucsrb, _rxcie);  
+}
+
+uint8_t HardwareSerial::available(void)
+{
+  return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
+}
+
+int HardwareSerial::read(void)
+{
+  // if the head isn't ahead of the tail, we don't have any characters
+  if (_rx_buffer->head == _rx_buffer->tail) {
+    return -1;
+  } else {
+    unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
+    _rx_buffer->tail = (_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
+    return c;
+  }
+}
+
+void HardwareSerial::flush()
+{
+  // don't reverse this or there may be problems if the RX interrupt
+  // occurs after reading the value of rx_buffer_head but before writing
+  // the value to rx_buffer_tail; the previous value of rx_buffer_head
+  // may be written to rx_buffer_tail, making it appear as if the buffer
+  // don't reverse this or there may be problems if the RX interrupt
+  // occurs after reading the value of rx_buffer_head but before writing
+  // the value to rx_buffer_tail; the previous value of rx_buffer_head
+  // may be written to rx_buffer_tail, making it appear as if the buffer
+  // were full, not empty.
+  _rx_buffer->head = _rx_buffer->tail;
+}
+
+void HardwareSerial::write(uint8_t c)
+{
+  while (!((*_ucsra) & (1 << _udre)))
+    ;
+
+  *_udr = c;
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+#if defined(__AVR_ATmega8__)
+HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
+#else
+HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
+#endif
+
+#if defined(__AVR_ATmega1280__)
+HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
+HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
+HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
+#endif

+ 66 - 0
optiboot/cores/arduino/HardwareSerial.h

@@ -0,0 +1,66 @@
+/*
+  HardwareSerial.h - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef HardwareSerial_h
+#define HardwareSerial_h
+
+#include <inttypes.h>
+
+#include "Print.h"
+
+struct ring_buffer;
+
+class HardwareSerial : public Print
+{
+  private:
+    ring_buffer *_rx_buffer;
+    volatile uint8_t *_ubrrh;
+    volatile uint8_t *_ubrrl;
+    volatile uint8_t *_ucsra;
+    volatile uint8_t *_ucsrb;
+    volatile uint8_t *_udr;
+    uint8_t _rxen;
+    uint8_t _txen;
+    uint8_t _rxcie;
+    uint8_t _udre;
+    uint8_t _u2x;
+  public:
+    HardwareSerial(ring_buffer *rx_buffer,
+      volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
+      volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
+      volatile uint8_t *udr,
+      uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x);
+    void begin(long);
+    void end();
+    uint8_t available(void);
+    int read(void);
+    void flush(void);
+    virtual void write(uint8_t);
+    using Print::write; // pull in write(str) and write(buf, size) from Print
+};
+
+extern HardwareSerial Serial;
+
+#if defined(__AVR_ATmega1280__)
+extern HardwareSerial Serial1;
+extern HardwareSerial Serial2;
+extern HardwareSerial Serial3;
+#endif
+
+#endif

+ 206 - 0
optiboot/cores/arduino/Print.cpp

@@ -0,0 +1,206 @@
+/*
+ Print.cpp - Base class that provides print() and println()
+ Copyright (c) 2008 David A. Mellis.  All right reserved.
+ 
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ 
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+ 
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ 
+ Modified 23 November 2006 by David A. Mellis
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "wiring.h"
+
+#include "Print.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+/* default implementation: may be overridden */
+void Print::write(const char *str)
+{
+  while (*str)
+    write(*str++);
+}
+
+/* default implementation: may be overridden */
+void Print::write(const uint8_t *buffer, size_t size)
+{
+  while (size--)
+    write(*buffer++);
+}
+
+void Print::print(const char str[])
+{
+  write(str);
+}
+
+void Print::print(char c, int base)
+{
+  print((long) c, base);
+}
+
+void Print::print(unsigned char b, int base)
+{
+  print((unsigned long) b, base);
+}
+
+void Print::print(int n, int base)
+{
+  print((long) n, base);
+}
+
+void Print::print(unsigned int n, int base)
+{
+  print((unsigned long) n, base);
+}
+
+void Print::print(long n, int base)
+{
+  if (base == 0) {
+    write(n);
+  } else if (base == 10) {
+    if (n < 0) {
+      print('-');
+      n = -n;
+    }
+    printNumber(n, 10);
+  } else {
+    printNumber(n, base);
+  }
+}
+
+void Print::print(unsigned long n, int base)
+{
+  if (base == 0) write(n);
+  else printNumber(n, base);
+}
+
+void Print::print(double n, int digits)
+{
+  printFloat(n, digits);
+}
+
+void Print::println(void)
+{
+  print('\r');
+  print('\n');  
+}
+
+void Print::println(const char c[])
+{
+  print(c);
+  println();
+}
+
+void Print::println(char c, int base)
+{
+  print(c, base);
+  println();
+}
+
+void Print::println(unsigned char b, int base)
+{
+  print(b, base);
+  println();
+}
+
+void Print::println(int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(unsigned int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(unsigned long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(double n, int digits)
+{
+  print(n, digits);
+  println();
+}
+
+// Private Methods /////////////////////////////////////////////////////////////
+
+void Print::printNumber(unsigned long n, uint8_t base)
+{
+  unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 
+  unsigned long i = 0;
+
+  if (n == 0) {
+    print('0');
+    return;
+  } 
+
+  while (n > 0) {
+    buf[i++] = n % base;
+    n /= base;
+  }
+
+  for (; i > 0; i--)
+    print((char) (buf[i - 1] < 10 ?
+      '0' + buf[i - 1] :
+      'A' + buf[i - 1] - 10));
+}
+
+void Print::printFloat(double number, uint8_t digits) 
+{ 
+  // Handle negative numbers
+  if (number < 0.0)
+  {
+     print('-');
+     number = -number;
+  }
+
+  // Round correctly so that print(1.999, 2) prints as "2.00"
+  double rounding = 0.5;
+  for (uint8_t i=0; i<digits; ++i)
+    rounding /= 10.0;
+  
+  number += rounding;
+
+  // Extract the integer part of the number and print it
+  unsigned long int_part = (unsigned long)number;
+  double remainder = number - (double)int_part;
+  print(int_part);
+
+  // Print the decimal point, but only if there are digits beyond
+  if (digits > 0)
+    print("."); 
+
+  // Extract digits from the remainder one at a time
+  while (digits-- > 0)
+  {
+    remainder *= 10.0;
+    int toPrint = int(remainder);
+    print(toPrint);
+    remainder -= toPrint; 
+  } 
+}

+ 62 - 0
optiboot/cores/arduino/Print.h

@@ -0,0 +1,62 @@
+/*
+  Print.h - Base class that provides print() and println()
+  Copyright (c) 2008 David A. Mellis.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef Print_h
+#define Print_h
+
+#include <inttypes.h>
+#include <stdio.h> // for size_t
+
+#define DEC 10
+#define HEX 16
+#define OCT 8
+#define BIN 2
+#define BYTE 0
+
+class Print
+{
+  private:
+    void printNumber(unsigned long, uint8_t);
+    void printFloat(double, uint8_t);
+  public:
+    virtual void write(uint8_t) = 0;
+    virtual void write(const char *str);
+    virtual void write(const uint8_t *buffer, size_t size);
+
+    void print(const char[]);
+    void print(char, int = BYTE);
+    void print(unsigned char, int = BYTE);
+    void print(int, int = DEC);
+    void print(unsigned int, int = DEC);
+    void print(long, int = DEC);
+    void print(unsigned long, int = DEC);
+    void print(double, int = 2);
+
+    void println(const char[]);
+    void println(char, int = BYTE);
+    void println(unsigned char, int = BYTE);
+    void println(int, int = DEC);
+    void println(unsigned int, int = DEC);
+    void println(long, int = DEC);
+    void println(unsigned long, int = DEC);
+    void println(double, int = 2);
+    void println(void);
+};
+
+#endif

+ 515 - 0
optiboot/cores/arduino/Tone.cpp

@@ -0,0 +1,515 @@
+/* Tone.cpp
+
+  A Tone Generator Library
+
+  Written by Brett Hagman
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+Version Modified By Date     Comments
+------- ----------- -------- --------
+0001    B Hagman    09/08/02 Initial coding
+0002    B Hagman    09/08/18 Multiple pins
+0003    B Hagman    09/08/18 Moved initialization from constructor to begin()
+0004    B Hagman    09/09/26 Fixed problems with ATmega8
+0005    B Hagman    09/11/23 Scanned prescalars for best fit on 8 bit timers
+                    09/11/25 Changed pin toggle method to XOR
+                    09/11/25 Fixed timer0 from being excluded
+0006    D Mellis    09/12/29 Replaced objects with functions
+
+*************************************************/
+
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <wiring.h>
+#include <pins_arduino.h>
+
+#if defined(__AVR_ATmega8__)
+#define TCCR2A TCCR2
+#define TCCR2B TCCR2
+#define COM2A1 COM21
+#define COM2A0 COM20
+#define OCR2A OCR2
+#define TIMSK2 TIMSK
+#define OCIE2A OCIE2
+#define TIMER2_COMPA_vect TIMER2_COMP_vect
+#define TIMSK1 TIMSK
+#endif
+
+// timerx_toggle_count:
+//  > 0 - duration specified
+//  = 0 - stopped
+//  < 0 - infinitely (until stop() method called, or new play() called)
+
+#if !defined(__AVR_ATmega8__)
+volatile long timer0_toggle_count;
+volatile uint8_t *timer0_pin_port;
+volatile uint8_t timer0_pin_mask;
+#endif
+
+volatile long timer1_toggle_count;
+volatile uint8_t *timer1_pin_port;
+volatile uint8_t timer1_pin_mask;
+volatile long timer2_toggle_count;
+volatile uint8_t *timer2_pin_port;
+volatile uint8_t timer2_pin_mask;
+
+#if defined(__AVR_ATmega1280__)
+volatile long timer3_toggle_count;
+volatile uint8_t *timer3_pin_port;
+volatile uint8_t timer3_pin_mask;
+volatile long timer4_toggle_count;
+volatile uint8_t *timer4_pin_port;
+volatile uint8_t timer4_pin_mask;
+volatile long timer5_toggle_count;
+volatile uint8_t *timer5_pin_port;
+volatile uint8_t timer5_pin_mask;
+#endif
+
+
+#if defined(__AVR_ATmega1280__)
+
+#define AVAILABLE_TONE_PINS 1
+
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 3, 4, 5, 1, 0 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255, 255, 255, 255 */ };
+
+#elif defined(__AVR_ATmega8__)
+
+#define AVAILABLE_TONE_PINS 1
+
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255 */ };
+
+#else
+
+#define AVAILABLE_TONE_PINS 1
+
+// Leave timer 0 to last.
+const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { 2 /*, 1, 0 */ };
+static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { 255 /*, 255, 255 */ };
+
+#endif
+
+
+
+static int8_t toneBegin(uint8_t _pin)
+{
+  int8_t _timer = -1;
+
+  // if we're already using the pin, the timer should be configured.  
+  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+    if (tone_pins[i] == _pin) {
+      return pgm_read_byte(tone_pin_to_timer_PGM + i);
+    }
+  }
+  
+  // search for an unused timer.
+  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+    if (tone_pins[i] == 255) {
+      tone_pins[i] = _pin;
+      _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
+      break;
+    }
+  }
+  
+  if (_timer != -1)
+  {
+    // Set timer specific stuff
+    // All timers in CTC mode
+    // 8 bit timers will require changing prescalar values,
+    // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar
+    switch (_timer)
+    {
+#if !defined(__AVR_ATmega8__)
+      case 0:
+        // 8 bit timer
+        TCCR0A = 0;
+        TCCR0B = 0;
+        bitWrite(TCCR0A, WGM01, 1);
+        bitWrite(TCCR0B, CS00, 1);
+        timer0_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer0_pin_mask = digitalPinToBitMask(_pin);
+        break;
+#endif
+
+      case 1:
+        // 16 bit timer
+        TCCR1A = 0;
+        TCCR1B = 0;
+        bitWrite(TCCR1B, WGM12, 1);
+        bitWrite(TCCR1B, CS10, 1);
+        timer1_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer1_pin_mask = digitalPinToBitMask(_pin);
+        break;
+      case 2:
+        // 8 bit timer
+        TCCR2A = 0;
+        TCCR2B = 0;
+        bitWrite(TCCR2A, WGM21, 1);
+        bitWrite(TCCR2B, CS20, 1);
+        timer2_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer2_pin_mask = digitalPinToBitMask(_pin);
+        break;
+
+#if defined(__AVR_ATmega1280__)
+      case 3:
+        // 16 bit timer
+        TCCR3A = 0;
+        TCCR3B = 0;
+        bitWrite(TCCR3B, WGM32, 1);
+        bitWrite(TCCR3B, CS30, 1);
+        timer3_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer3_pin_mask = digitalPinToBitMask(_pin);
+        break;
+      case 4:
+        // 16 bit timer
+        TCCR4A = 0;
+        TCCR4B = 0;
+        bitWrite(TCCR4B, WGM42, 1);
+        bitWrite(TCCR4B, CS40, 1);
+        timer4_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer4_pin_mask = digitalPinToBitMask(_pin);
+        break;
+      case 5:
+        // 16 bit timer
+        TCCR5A = 0;
+        TCCR5B = 0;
+        bitWrite(TCCR5B, WGM52, 1);
+        bitWrite(TCCR5B, CS50, 1);
+        timer5_pin_port = portOutputRegister(digitalPinToPort(_pin));
+        timer5_pin_mask = digitalPinToBitMask(_pin);
+        break;
+#endif
+    }
+  }
+
+  return _timer;
+}
+
+
+
+// frequency (in hertz) and duration (in milliseconds).
+
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
+{
+  uint8_t prescalarbits = 0b001;
+  long toggle_count = 0;
+  uint32_t ocr = 0;
+  int8_t _timer;
+
+  _timer = toneBegin(_pin);
+
+  if (_timer >= 0)
+  {
+    // Set the pinMode as OUTPUT
+    pinMode(_pin, OUTPUT);
+    
+    // if we are using an 8 bit timer, scan through prescalars to find the best fit
+    if (_timer == 0 || _timer == 2)
+    {
+      ocr = F_CPU / frequency / 2 - 1;
+      prescalarbits = 0b001;  // ck/1: same for both timers
+      if (ocr > 255)
+      {
+        ocr = F_CPU / frequency / 2 / 8 - 1;
+        prescalarbits = 0b010;  // ck/8: same for both timers
+
+        if (_timer == 2 && ocr > 255)
+        {
+          ocr = F_CPU / frequency / 2 / 32 - 1;
+          prescalarbits = 0b011;
+        }
+
+        if (ocr > 255)
+        {
+          ocr = F_CPU / frequency / 2 / 64 - 1;
+          prescalarbits = _timer == 0 ? 0b011 : 0b100;
+
+          if (_timer == 2 && ocr > 255)
+          {
+            ocr = F_CPU / frequency / 2 / 128 - 1;
+            prescalarbits = 0b101;
+          }
+
+          if (ocr > 255)
+          {
+            ocr = F_CPU / frequency / 2 / 256 - 1;
+            prescalarbits = _timer == 0 ? 0b100 : 0b110;
+            if (ocr > 255)
+            {
+              // can't do any better than /1024
+              ocr = F_CPU / frequency / 2 / 1024 - 1;
+              prescalarbits = _timer == 0 ? 0b101 : 0b111;
+            }
+          }
+        }
+      }
+
+#if !defined(__AVR_ATmega8__)
+      if (_timer == 0)
+        TCCR0B = prescalarbits;
+      else
+#endif
+        TCCR2B = prescalarbits;
+    }
+    else
+    {
+      // two choices for the 16 bit timers: ck/1 or ck/64
+      ocr = F_CPU / frequency / 2 - 1;
+
+      prescalarbits = 0b001;
+      if (ocr > 0xffff)
+      {
+        ocr = F_CPU / frequency / 2 / 64 - 1;
+        prescalarbits = 0b011;
+      }
+
+      if (_timer == 1)
+        TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
+#if defined(__AVR_ATmega1280__)
+      else if (_timer == 3)
+        TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
+      else if (_timer == 4)
+        TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
+      else if (_timer == 5)
+        TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
+#endif
+
+    }
+    
+
+    // Calculate the toggle count
+    if (duration > 0)
+    {
+      toggle_count = 2 * frequency * duration / 1000;
+    }
+    else
+    {
+      toggle_count = -1;
+    }
+
+    // Set the OCR for the given timer,
+    // set the toggle count,
+    // then turn on the interrupts
+    switch (_timer)
+    {
+
+#if !defined(__AVR_ATmega8__)
+      case 0:
+        OCR0A = ocr;
+        timer0_toggle_count = toggle_count;
+        bitWrite(TIMSK0, OCIE0A, 1);
+        break;
+#endif
+
+      case 1:
+        OCR1A = ocr;
+        timer1_toggle_count = toggle_count;
+        bitWrite(TIMSK1, OCIE1A, 1);
+        break;
+      case 2:
+        OCR2A = ocr;
+        timer2_toggle_count = toggle_count;
+        bitWrite(TIMSK2, OCIE2A, 1);
+        break;
+
+#if defined(__AVR_ATmega1280__)
+      case 3:
+        OCR3A = ocr;
+        timer3_toggle_count = toggle_count;
+        bitWrite(TIMSK3, OCIE3A, 1);
+        break;
+      case 4:
+        OCR4A = ocr;
+        timer4_toggle_count = toggle_count;
+        bitWrite(TIMSK4, OCIE4A, 1);
+        break;
+      case 5:
+        OCR5A = ocr;
+        timer5_toggle_count = toggle_count;
+        bitWrite(TIMSK5, OCIE5A, 1);
+        break;
+#endif
+
+    }
+  }
+}
+
+
+void noTone(uint8_t _pin)
+{
+  int8_t _timer = -1;
+  
+  for (int i = 0; i < AVAILABLE_TONE_PINS; i++) {
+    if (tone_pins[i] == _pin) {
+      _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);
+      tone_pins[i] = 255;
+    }
+  }
+  
+  switch (_timer)
+  {
+#if defined(__AVR_ATmega8__)
+    case 1:
+      bitWrite(TIMSK1, OCIE1A, 0);
+      break;
+    case 2:
+      bitWrite(TIMSK2, OCIE2A, 0);
+      break;
+
+#else
+    case 0:
+      TIMSK0 = 0;
+      break;
+    case 1:
+      TIMSK1 = 0;
+      break;
+    case 2:
+      TIMSK2 = 0;
+      break;
+#endif
+
+#if defined(__AVR_ATmega1280__)
+    case 3:
+      TIMSK3 = 0;
+      break;
+    case 4:
+      TIMSK4 = 0;
+      break;
+    case 5:
+      TIMSK5 = 0;
+      break;
+#endif
+  }
+
+  digitalWrite(_pin, 0);
+}
+
+#if 0
+#if !defined(__AVR_ATmega8__)
+ISR(TIMER0_COMPA_vect)
+{
+  if (timer0_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer0_pin_port ^= timer0_pin_mask;
+
+    if (timer0_toggle_count > 0)
+      timer0_toggle_count--;
+  }
+  else
+  {
+    TIMSK0 = 0;   // disable the interrupt
+    *timer0_pin_port &= ~(timer0_pin_mask);  // keep pin low after stop
+  }
+}
+#endif
+
+
+ISR(TIMER1_COMPA_vect)
+{
+  if (timer1_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer1_pin_port ^= timer1_pin_mask;
+
+    if (timer1_toggle_count > 0)
+      timer1_toggle_count--;
+  }
+  else
+  {
+    TIMSK1 = 0;   // disable the interrupt
+    *timer1_pin_port &= ~(timer1_pin_mask);  // keep pin low after stop
+  }
+}
+#endif
+
+
+ISR(TIMER2_COMPA_vect)
+{
+
+  if (timer2_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer2_pin_port ^= timer2_pin_mask;
+
+    if (timer2_toggle_count > 0)
+      timer2_toggle_count--;
+  }
+  else
+  {
+    TIMSK2 = 0;   // disable the interrupt
+    *timer2_pin_port &= ~(timer2_pin_mask);  // keep pin low after stop
+  }
+}
+
+
+
+//#if defined(__AVR_ATmega1280__)
+#if 0
+
+ISR(TIMER3_COMPA_vect)
+{
+  if (timer3_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer3_pin_port ^= timer3_pin_mask;
+
+    if (timer3_toggle_count > 0)
+      timer3_toggle_count--;
+  }
+  else
+  {
+    TIMSK3 = 0;   // disable the interrupt
+    *timer3_pin_port &= ~(timer3_pin_mask);  // keep pin low after stop
+  }
+}
+
+ISR(TIMER4_COMPA_vect)
+{
+  if (timer4_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer4_pin_port ^= timer4_pin_mask;
+
+    if (timer4_toggle_count > 0)
+      timer4_toggle_count--;
+  }
+  else
+  {
+    TIMSK4 = 0;   // disable the interrupt
+    *timer4_pin_port &= ~(timer4_pin_mask);  // keep pin low after stop
+  }
+}
+
+ISR(TIMER5_COMPA_vect)
+{
+  if (timer5_toggle_count != 0)
+  {
+    // toggle the pin
+    *timer5_pin_port ^= timer5_pin_mask;
+
+    if (timer5_toggle_count > 0)
+      timer5_toggle_count--;
+  }
+  else
+  {
+    TIMSK5 = 0;   // disable the interrupt
+    *timer5_pin_port &= ~(timer5_pin_mask);  // keep pin low after stop
+  }
+}
+
+#endif

+ 1 - 0
optiboot/cores/arduino/WConstants.h

@@ -0,0 +1 @@
+#include "wiring.h"

+ 215 - 0
optiboot/cores/arduino/WInterrupts.c

@@ -0,0 +1,215 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+  Part of the Wiring project - http://wiring.uniandes.edu.co
+
+  Copyright (c) 2004-05 Hernando Barragan
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+  
+  Modified 24 November 2006 by David A. Mellis
+*/
+
+#include <inttypes.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include <stdio.h>
+
+#include "WConstants.h"
+#include "wiring_private.h"
+
+volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];
+// volatile static voidFuncPtr twiIntFunc;
+
+#if defined(__AVR_ATmega8__)
+#define EICRA MCUCR
+#define EIMSK GICR
+#endif
+
+void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
+  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+    intFunc[interruptNum] = userFunc;
+    
+    // Configure the interrupt mode (trigger on low input, any change, rising
+    // edge, or falling edge).  The mode constants were chosen to correspond
+    // to the configuration bits in the hardware register, so we simply shift
+    // the mode into place.
+      
+    // Enable the interrupt.
+      
+    switch (interruptNum) {
+#if defined(__AVR_ATmega1280__)
+    case 2:
+      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+      EIMSK |= (1 << INT0);
+      break;
+    case 3:
+      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+      EIMSK |= (1 << INT1);
+      break;
+    case 4:
+      EICRA = (EICRA & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);
+      EIMSK |= (1 << INT2);
+      break;
+    case 5:
+      EICRA = (EICRA & ~((1 << ISC30) | (1 << ISC31))) | (mode << ISC30);
+      EIMSK |= (1 << INT3);
+      break;
+    case 0:
+      EICRB = (EICRB & ~((1 << ISC40) | (1 << ISC41))) | (mode << ISC40);
+      EIMSK |= (1 << INT4);
+      break;
+    case 1:
+      EICRB = (EICRB & ~((1 << ISC50) | (1 << ISC51))) | (mode << ISC50);
+      EIMSK |= (1 << INT5);
+      break;
+    case 6:
+      EICRB = (EICRB & ~((1 << ISC60) | (1 << ISC61))) | (mode << ISC60);
+      EIMSK |= (1 << INT6);
+      break;
+    case 7:
+      EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
+      EIMSK |= (1 << INT7);
+      break;
+#else
+    case 0:
+      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+      EIMSK |= (1 << INT0);
+      break;
+    case 1:
+      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+      EIMSK |= (1 << INT1);
+      break;
+#endif
+    }
+  }
+}
+
+void detachInterrupt(uint8_t interruptNum) {
+  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+    // Disable the interrupt.  (We can't assume that interruptNum is equal
+    // to the number of the EIMSK bit to clear, as this isn't true on the 
+    // ATmega8.  There, INT0 is 6 and INT1 is 7.)
+    switch (interruptNum) {
+#if defined(__AVR_ATmega1280__)
+    case 2:
+      EIMSK &= ~(1 << INT0);
+      break;
+    case 3:
+      EIMSK &= ~(1 << INT1);
+      break;
+    case 4:
+      EIMSK &= ~(1 << INT2);
+      break;
+    case 5:
+      EIMSK &= ~(1 << INT3);
+      break;
+    case 0:
+      EIMSK &= ~(1 << INT4);
+      break;
+    case 1:
+      EIMSK &= ~(1 << INT5);
+      break;
+    case 6:
+      EIMSK &= ~(1 << INT6);
+      break;
+    case 7:
+      EIMSK &= ~(1 << INT7);
+      break;
+#else
+    case 0:
+      EIMSK &= ~(1 << INT0);
+      break;
+    case 1:
+      EIMSK &= ~(1 << INT1);
+      break;
+#endif
+    }
+      
+    intFunc[interruptNum] = 0;
+  }
+}
+
+/*
+void attachInterruptTwi(void (*userFunc)(void) ) {
+  twiIntFunc = userFunc;
+}
+*/
+
+#if defined(__AVR_ATmega1280__)
+
+SIGNAL(INT0_vect) {
+  if(intFunc[EXTERNAL_INT_2])
+    intFunc[EXTERNAL_INT_2]();
+}
+
+SIGNAL(INT1_vect) {
+  if(intFunc[EXTERNAL_INT_3])
+    intFunc[EXTERNAL_INT_3]();
+}
+
+SIGNAL(INT2_vect) {
+  if(intFunc[EXTERNAL_INT_4])
+    intFunc[EXTERNAL_INT_4]();
+}
+
+SIGNAL(INT3_vect) {
+  if(intFunc[EXTERNAL_INT_5])
+    intFunc[EXTERNAL_INT_5]();
+}
+
+SIGNAL(INT4_vect) {
+  if(intFunc[EXTERNAL_INT_0])
+    intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT5_vect) {
+  if(intFunc[EXTERNAL_INT_1])
+    intFunc[EXTERNAL_INT_1]();
+}
+
+SIGNAL(INT6_vect) {
+  if(intFunc[EXTERNAL_INT_6])
+    intFunc[EXTERNAL_INT_6]();
+}
+
+SIGNAL(INT7_vect) {
+  if(intFunc[EXTERNAL_INT_7])
+    intFunc[EXTERNAL_INT_7]();
+}
+
+#else
+
+SIGNAL(INT0_vect) {
+  if(intFunc[EXTERNAL_INT_0])
+    intFunc[EXTERNAL_INT_0]();
+}
+
+SIGNAL(INT1_vect) {
+  if(intFunc[EXTERNAL_INT_1])
+    intFunc[EXTERNAL_INT_1]();
+}
+
+#endif
+
+/*
+SIGNAL(SIG_2WIRE_SERIAL) {
+  if(twiIntFunc)
+    twiIntFunc();
+}
+*/
+

+ 60 - 0
optiboot/cores/arduino/WMath.cpp

@@ -0,0 +1,60 @@
+/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+
+/*
+  Part of the Wiring project - http://wiring.org.co
+  Copyright (c) 2004-06 Hernando Barragan
+  Modified 13 August 2006, David A. Mellis for Arduino - http://www.arduino.cc/
+  
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+  
+  $Id$
+*/
+
+extern "C" {
+  #include "stdlib.h"
+}
+
+void randomSeed(unsigned int seed)
+{
+  if (seed != 0) {
+    srandom(seed);
+  }
+}
+
+long random(long howbig)
+{
+  if (howbig == 0) {
+    return 0;
+  }
+  return random() % howbig;
+}
+
+long random(long howsmall, long howbig)
+{
+  if (howsmall >= howbig) {
+    return howsmall;
+  }
+  long diff = howbig - howsmall;
+  return random(diff) + howsmall;
+}
+
+long map(long x, long in_min, long in_max, long out_min, long out_max)
+{
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+unsigned int makeWord(unsigned int w) { return w; }
+unsigned int makeWord(unsigned char h, unsigned char l) { return (h << 8) | l; }

+ 32 - 0
optiboot/cores/arduino/WProgram.h

@@ -0,0 +1,32 @@
+#ifndef WProgram_h
+#define WProgram_h
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <avr/interrupt.h>
+
+#include "wiring.h"
+
+#ifdef __cplusplus
+#include "HardwareSerial.h"
+
+uint16_t makeWord(uint16_t w);
+uint16_t makeWord(byte h, byte l);
+
+#define word(...) makeWord(__VA_ARGS__)
+
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L);
+
+void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0);
+void noTone(uint8_t _pin);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned int);
+long map(long, long, long, long, long);
+#endif
+
+#endif

+ 3 - 0
optiboot/cores/arduino/_ReadMe.txt

@@ -0,0 +1,3 @@
+Arduino does not currently allow additional hardware directories to share the standard Arduino core. So a copy of the Arduino 18 core is included here. No changes have been made.
+
+Arduino source is from http://arduino.cc

+ 515 - 0
optiboot/cores/arduino/binary.h

@@ -0,0 +1,515 @@
+#ifndef Binary_h
+#define Binary_h
+
+#define B0 0
+#define B00 0
+#define B000 0
+#define B0000 0
+#define B00000 0
+#define B000000 0
+#define B0000000 0
+#define B00000000 0
+#define B1 1
+#define B01 1
+#define B001 1
+#define B0001 1
+#define B00001 1
+#define B000001 1
+#define B0000001 1
+#define B00000001 1
+#define B10 2
+#define B010 2
+#define B0010 2
+#define B00010 2
+#define B000010 2
+#define B0000010 2
+#define B00000010 2
+#define B11 3
+#define B011 3
+#define B0011 3
+#define B00011 3
+#define B000011 3
+#define B0000011 3
+#define B00000011 3
+#define B100 4
+#define B0100 4
+#define B00100 4
+#define B000100 4
+#define B0000100 4
+#define B00000100 4
+#define B101 5
+#define B0101 5
+#define B00101 5
+#define B000101 5
+#define B0000101 5
+#define B00000101 5
+#define B110 6
+#define B0110 6
+#define B00110 6
+#define B000110 6
+#define B0000110 6
+#define B00000110 6
+#define B111 7
+#define B0111 7
+#define B00111 7
+#define B000111 7
+#define B0000111 7
+#define B00000111 7
+#define B1000 8
+#define B01000 8
+#define B001000 8
+#define B0001000 8
+#define B00001000 8
+#define B1001 9
+#define B01001 9
+#define B001001 9
+#define B0001001 9
+#define B00001001 9
+#define B1010 10
+#define B01010 10
+#define B001010 10
+#define B0001010 10
+#define B00001010 10
+#define B1011 11
+#define B01011 11
+#define B001011 11
+#define B0001011 11
+#define B00001011 11
+#define B1100 12
+#define B01100 12
+#define B001100 12
+#define B0001100 12
+#define B00001100 12
+#define B1101 13
+#define B01101 13
+#define B001101 13
+#define B0001101 13
+#define B00001101 13
+#define B1110 14
+#define B01110 14
+#define B001110 14
+#define B0001110 14
+#define B00001110 14
+#define B1111 15
+#define B01111 15
+#define B001111 15
+#define B0001111 15
+#define B00001111 15
+#define B10000 16
+#define B010000 16
+#define B0010000 16
+#define B00010000 16
+#define B10001 17
+#define B010001 17
+#define B0010001 17
+#define B00010001 17
+#define B10010 18
+#define B010010 18
+#define B0010010 18
+#define B00010010 18
+#define B10011 19
+#define B010011 19
+#define B0010011 19
+#define B00010011 19
+#define B10100 20
+#define B010100 20
+#define B0010100 20
+#define B00010100 20
+#define B10101 21
+#define B010101 21
+#define B0010101 21
+#define B00010101 21
+#define B10110 22
+#define B010110 22
+#define B0010110 22
+#define B00010110 22
+#define B10111 23
+#define B010111 23
+#define B0010111 23
+#define B00010111 23
+#define B11000 24
+#define B011000 24
+#define B0011000 24
+#define B00011000 24
+#define B11001 25
+#define B011001 25
+#define B0011001 25
+#define B00011001 25
+#define B11010 26
+#define B011010 26
+#define B0011010 26
+#define B00011010 26
+#define B11011 27
+#define B011011 27
+#define B0011011 27
+#define B00011011 27
+#define B11100 28
+#define B011100 28
+#define B0011100 28
+#define B00011100 28
+#define B11101 29
+#define B011101 29
+#define B0011101 29
+#define B00011101 29
+#define B11110 30
+#define B011110 30
+#define B0011110 30
+#define B00011110 30
+#define B11111 31
+#define B011111 31
+#define B0011111 31
+#define B00011111 31
+#define B100000 32
+#define B0100000 32
+#define B00100000 32
+#define B100001 33
+#define B0100001 33
+#define B00100001 33
+#define B100010 34
+#define B0100010 34
+#define B00100010 34
+#define B100011 35
+#define B0100011 35
+#define B00100011 35
+#define B100100 36
+#define B0100100 36
+#define B00100100 36
+#define B100101 37
+#define B0100101 37
+#define B00100101 37
+#define B100110 38
+#define B0100110 38
+#define B00100110 38
+#define B100111 39
+#define B0100111 39
+#define B00100111 39
+#define B101000 40
+#define B0101000 40
+#define B00101000 40
+#define B101001 41
+#define B0101001 41
+#define B00101001 41
+#define B101010 42
+#define B0101010 42
+#define B00101010 42
+#define B101011 43
+#define B0101011 43
+#define B00101011 43
+#define B101100 44
+#define B0101100 44
+#define B00101100 44
+#define B101101 45
+#define B0101101 45
+#define B00101101 45
+#define B101110 46
+#define B0101110 46
+#define B00101110 46
+#define B101111 47
+#define B0101111 47
+#define B00101111 47
+#define B110000 48
+#define B0110000 48
+#define B00110000 48
+#define B110001 49
+#define B0110001 49
+#define B00110001 49
+#define B110010 50
+#define B0110010 50
+#define B00110010 50
+#define B110011 51
+#define B0110011 51
+#define B00110011 51
+#define B110100 52
+#define B0110100 52
+#define B00110100 52
+#define B110101 53
+#define B0110101 53
+#define B00110101 53
+#define B110110 54
+#define B0110110 54
+#define B00110110 54
+#define B110111 55
+#define B0110111 55
+#define B00110111 55
+#define B111000 56
+#define B0111000 56
+#define B00111000 56
+#define B111001 57
+#define B0111001 57
+#define B00111001 57
+#define B111010 58
+#define B0111010 58
+#define B00111010 58
+#define B111011 59
+#define B0111011 59
+#define B00111011 59
+#define B111100 60
+#define B0111100 60
+#define B00111100 60
+#define B111101 61
+#define B0111101 61
+#define B00111101 61
+#define B111110 62
+#define B0111110 62
+#define B00111110 62
+#define B111111 63
+#define B0111111 63
+#define B00111111 63
+#define B1000000 64
+#define B01000000 64
+#define B1000001 65
+#define B01000001 65
+#define B1000010 66
+#define B01000010 66
+#define B1000011 67
+#define B01000011 67
+#define B1000100 68
+#define B01000100 68
+#define B1000101 69
+#define B01000101 69
+#define B1000110 70
+#define B01000110 70
+#define B1000111 71
+#define B01000111 71
+#define B1001000 72
+#define B01001000 72
+#define B1001001 73
+#define B01001001 73
+#define B1001010 74
+#define B01001010 74
+#define B1001011 75
+#define B01001011 75
+#define B1001100 76
+#define B01001100 76
+#define B1001101 77
+#define B01001101 77
+#define B1001110 78
+#define B01001110 78
+#define B1001111 79
+#define B01001111 79
+#define B1010000 80
+#define B01010000 80
+#define B1010001 81
+#define B01010001 81
+#define B1010010 82
+#define B01010010 82
+#define B1010011 83
+#define B01010011 83
+#define B1010100 84
+#define B01010100 84
+#define B1010101 85
+#define B01010101 85
+#define B1010110 86
+#define B01010110 86
+#define B1010111 87
+#define B01010111 87
+#define B1011000 88
+#define B01011000 88
+#define B1011001 89
+#define B01011001 89
+#define B1011010 90
+#define B01011010 90
+#define B1011011 91
+#define B01011011 91
+#define B1011100 92
+#define B01011100 92
+#define B1011101 93
+#define B01011101 93
+#define B1011110 94
+#define B01011110 94
+#define B1011111 95
+#define B01011111 95
+#define B1100000 96
+#define B01100000 96
+#define B1100001 97
+#define B01100001 97
+#define B1100010 98
+#define B01100010 98
+#define B1100011 99
+#define B01100011 99
+#define B1100100 100
+#define B01100100 100
+#define B1100101 101
+#define B01100101 101
+#define B1100110 102
+#define B01100110 102
+#define B1100111 103
+#define B01100111 103
+#define B1101000 104
+#define B01101000 104
+#define B1101001 105
+#define B01101001 105
+#define B1101010 106
+#define B01101010 106
+#define B1101011 107
+#define B01101011 107
+#define B1101100 108
+#define B01101100 108
+#define B1101101 109
+#define B01101101 109
+#define B1101110 110
+#define B01101110 110
+#define B1101111 111
+#define B01101111 111
+#define B1110000 112
+#define B01110000 112
+#define B1110001 113
+#define B01110001 113
+#define B1110010 114
+#define B01110010 114
+#define B1110011 115
+#define B01110011 115
+#define B1110100 116
+#define B01110100 116
+#define B1110101 117
+#define B01110101 117
+#define B1110110 118
+#define B01110110 118
+#define B1110111 119
+#define B01110111 119
+#define B1111000 120
+#define B01111000 120
+#define B1111001 121
+#define B01111001 121
+#define B1111010 122
+#define B01111010 122
+#define B1111011 123
+#define B01111011 123
+#define B1111100 124
+#define B01111100 124
+#define B1111101 125
+#define B01111101 125
+#define B1111110 126
+#define B01111110 126
+#define B1111111 127
+#define B01111111 127
+#define B10000000 128
+#define B10000001 129
+#define B10000010 130
+#define B10000011 131
+#define B10000100 132
+#define B10000101 133
+#define B10000110 134
+#define B10000111 135
+#define B10001000 136
+#define B10001001 137
+#define B10001010 138
+#define B10001011 139
+#define B10001100 140
+#define B10001101 141
+#define B10001110 142
+#define B10001111 143
+#define B10010000 144
+#define B10010001 145
+#define B10010010 146
+#define B10010011 147
+#define B10010100 148
+#define B10010101 149
+#define B10010110 150
+#define B10010111 151
+#define B10011000 152
+#define B10011001 153
+#define B10011010 154
+#define B10011011 155
+#define B10011100 156
+#define B10011101 157
+#define B10011110 158
+#define B10011111 159
+#define B10100000 160
+#define B10100001 161
+#define B10100010 162
+#define B10100011 163
+#define B10100100 164
+#define B10100101 165
+#define B10100110 166
+#define B10100111 167
+#define B10101000 168
+#define B10101001 169
+#define B10101010 170
+#define B10101011 171
+#define B10101100 172
+#define B10101101 173
+#define B10101110 174
+#define B10101111 175
+#define B10110000 176
+#define B10110001 177
+#define B10110010 178
+#define B10110011 179
+#define B10110100 180
+#define B10110101 181
+#define B10110110 182
+#define B10110111 183
+#define B10111000 184
+#define B10111001 185
+#define B10111010 186
+#define B10111011 187
+#define B10111100 188
+#define B10111101 189
+#define B10111110 190
+#define B10111111 191
+#define B11000000 192
+#define B11000001 193
+#define B11000010 194
+#define B11000011 195
+#define B11000100 196
+#define B11000101 197
+#define B11000110 198
+#define B11000111 199
+#define B11001000 200
+#define B11001001 201
+#define B11001010 202
+#define B11001011 203
+#define B11001100 204
+#define B11001101 205
+#define B11001110 206
+#define B11001111 207
+#define B11010000 208
+#define B11010001 209
+#define B11010010 210
+#define B11010011 211
+#define B11010100 212
+#define B11010101 213
+#define B11010110 214
+#define B11010111 215
+#define B11011000 216
+#define B11011001 217
+#define B11011010 218
+#define B11011011 219
+#define B11011100 220
+#define B11011101 221
+#define B11011110 222
+#define B11011111 223
+#define B11100000 224
+#define B11100001 225
+#define B11100010 226
+#define B11100011 227
+#define B11100100 228
+#define B11100101 229
+#define B11100110 230
+#define B11100111 231
+#define B11101000 232
+#define B11101001 233
+#define B11101010 234
+#define B11101011 235
+#define B11101100 236
+#define B11101101 237
+#define B11101110 238
+#define B11101111 239
+#define B11110000 240
+#define B11110001 241
+#define B11110010 242
+#define B11110011 243
+#define B11110100 244
+#define B11110101 245
+#define B11110110 246
+#define B11110111 247
+#define B11111000 248
+#define B11111001 249
+#define B11111010 250
+#define B11111011 251
+#define B11111100 252
+#define B11111101 253
+#define B11111110 254
+#define B11111111 255
+
+#endif

+ 14 - 0
optiboot/cores/arduino/main.cpp

@@ -0,0 +1,14 @@
+#include <WProgram.h>
+
+int main(void)
+{
+	init();
+
+	setup();
+    
+	for (;;)
+		loop();
+        
+	return 0;
+}
+

+ 469 - 0
optiboot/cores/arduino/pins_arduino.c

@@ -0,0 +1,469 @@
+/*
+  pins_arduino.c - pin definitions for the Arduino board
+  Part of Arduino / Wiring Lite
+
+  Copyright (c) 2005 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: pins_arduino.c 804 2009-12-18 16:05:52Z dmellis $
+*/
+
+#include <avr/io.h>
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+// On the Arduino board, digital pins are also used
+// for the analog output (software PWM).  Analog input
+// pins are a separate set.
+
+// ATMEL ATMEGA8 & 168 / ARDUINO
+//
+//                  +-\/-+
+//            PC6  1|    |28  PC5 (AI 5)
+//      (D 0) PD0  2|    |27  PC4 (AI 4)
+//      (D 1) PD1  3|    |26  PC3 (AI 3)
+//      (D 2) PD2  4|    |25  PC2 (AI 2)
+// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
+//      (D 4) PD4  6|    |23  PC0 (AI 0)
+//            VCC  7|    |22  GND
+//            GND  8|    |21  AREF
+//            PB6  9|    |20  AVCC
+//            PB7 10|    |19  PB5 (D 13)
+// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
+// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
+//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
+//      (D 8) PB0 14|    |15  PB1 (D 9) PWM
+//                  +----+
+//
+// (PWM+ indicates the additional PWM pins on the ATmega168.)
+
+// ATMEL ATMEGA1280 / ARDUINO
+//
+// 0-7 PE0-PE7   works
+// 8-13 PB0-PB5  works
+// 14-21 PA0-PA7 works 
+// 22-29 PH0-PH7 works
+// 30-35 PG5-PG0 works
+// 36-43 PC7-PC0 works
+// 44-51 PJ7-PJ0 works
+// 52-59 PL7-PL0 works
+// 60-67 PD7-PD0 works
+// A0-A7 PF0-PF7
+// A8-A15 PK0-PK7
+
+#define PA 1
+#define PB 2
+#define PC 3
+#define PD 4
+#define PE 5
+#define PF 6
+#define PG 7
+#define PH 8
+#define PJ 10
+#define PK 11
+#define PL 12
+
+#define REPEAT8(x) x, x, x, x, x, x, x, x
+#define BV0TO7 _BV(0), _BV(1), _BV(2), _BV(3), _BV(4), _BV(5), _BV(6), _BV(7)
+#define BV7TO0 _BV(7), _BV(6), _BV(5), _BV(4), _BV(3), _BV(2), _BV(1), _BV(0)
+
+
+#if defined(__AVR_ATmega1280__)
+const uint16_t PROGMEM port_to_mode_PGM[] = {
+	NOT_A_PORT,
+	&DDRA,
+	&DDRB,
+	&DDRC,
+	&DDRD,
+	&DDRE,
+	&DDRF,
+	&DDRG,
+	&DDRH,
+	NOT_A_PORT,
+	&DDRJ,
+	&DDRK,
+	&DDRL,
+};
+
+const uint16_t PROGMEM port_to_output_PGM[] = {
+	NOT_A_PORT,
+	&PORTA,
+	&PORTB,
+	&PORTC,
+	&PORTD,
+	&PORTE,
+	&PORTF,
+	&PORTG,
+	&PORTH,
+	NOT_A_PORT,
+	&PORTJ,
+	&PORTK,
+	&PORTL,
+};
+
+const uint16_t PROGMEM port_to_input_PGM[] = {
+	NOT_A_PIN,
+	&PINA,
+	&PINB,
+	&PINC,
+	&PIND,
+	&PINE,
+	&PINF,
+	&PING,
+	&PINH,
+	NOT_A_PIN,
+	&PINJ,
+	&PINK,
+	&PINL,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
+	// PORTLIST		
+	// -------------------------------------------		
+	PE	, // PE 0 ** 0 ** USART0_RX	
+	PE	, // PE 1 ** 1 ** USART0_TX	
+	PE	, // PE 4 ** 2 ** PWM2	
+	PE	, // PE 5 ** 3 ** PWM3	
+	PG	, // PG 5 ** 4 ** PWM4	
+	PE	, // PE 3 ** 5 ** PWM5	
+	PH	, // PH 3 ** 6 ** PWM6	
+	PH	, // PH 4 ** 7 ** PWM7	
+	PH	, // PH 5 ** 8 ** PWM8	
+	PH	, // PH 6 ** 9 ** PWM9	
+	PB	, // PB 4 ** 10 ** PWM10	
+	PB	, // PB 5 ** 11 ** PWM11	
+	PB	, // PB 6 ** 12 ** PWM12	
+	PB	, // PB 7 ** 13 ** PWM13	
+	PJ	, // PJ 1 ** 14 ** USART3_TX	
+	PJ	, // PJ 0 ** 15 ** USART3_RX	
+	PH	, // PH 1 ** 16 ** USART2_TX	
+	PH	, // PH 0 ** 17 ** USART2_RX	
+	PD	, // PD 3 ** 18 ** USART1_TX	
+	PD	, // PD 2 ** 19 ** USART1_RX	
+	PD	, // PD 1 ** 20 ** I2C_SDA	
+	PD	, // PD 0 ** 21 ** I2C_SCL	
+	PA	, // PA 0 ** 22 ** D22	
+	PA	, // PA 1 ** 23 ** D23	
+	PA	, // PA 2 ** 24 ** D24	
+	PA	, // PA 3 ** 25 ** D25	
+	PA	, // PA 4 ** 26 ** D26	
+	PA	, // PA 5 ** 27 ** D27	
+	PA	, // PA 6 ** 28 ** D28	
+	PA	, // PA 7 ** 29 ** D29	
+	PC	, // PC 7 ** 30 ** D30	
+	PC	, // PC 6 ** 31 ** D31	
+	PC	, // PC 5 ** 32 ** D32	
+	PC	, // PC 4 ** 33 ** D33	
+	PC	, // PC 3 ** 34 ** D34	
+	PC	, // PC 2 ** 35 ** D35	
+	PC	, // PC 1 ** 36 ** D36	
+	PC	, // PC 0 ** 37 ** D37	
+	PD	, // PD 7 ** 38 ** D38	
+	PG	, // PG 2 ** 39 ** D39	
+	PG	, // PG 1 ** 40 ** D40	
+	PG	, // PG 0 ** 41 ** D41	
+	PL	, // PL 7 ** 42 ** D42	
+	PL	, // PL 6 ** 43 ** D43	
+	PL	, // PL 5 ** 44 ** D44	
+	PL	, // PL 4 ** 45 ** D45	
+	PL	, // PL 3 ** 46 ** D46	
+	PL	, // PL 2 ** 47 ** D47	
+	PL	, // PL 1 ** 48 ** D48	
+	PL	, // PL 0 ** 49 ** D49	
+	PB	, // PB 3 ** 50 ** SPI_MISO	
+	PB	, // PB 2 ** 51 ** SPI_MOSI	
+	PB	, // PB 1 ** 52 ** SPI_SCK	
+	PB	, // PB 0 ** 53 ** SPI_SS	
+	PF	, // PF 0 ** 54 ** A0	
+	PF	, // PF 1 ** 55 ** A1	
+	PF	, // PF 2 ** 56 ** A2	
+	PF	, // PF 3 ** 57 ** A3	
+	PF	, // PF 4 ** 58 ** A4	
+	PF	, // PF 5 ** 59 ** A5	
+	PF	, // PF 6 ** 60 ** A6	
+	PF	, // PF 7 ** 61 ** A7	
+	PK	, // PK 0 ** 62 ** A8	
+	PK	, // PK 1 ** 63 ** A9	
+	PK	, // PK 2 ** 64 ** A10	
+	PK	, // PK 3 ** 65 ** A11	
+	PK	, // PK 4 ** 66 ** A12	
+	PK	, // PK 5 ** 67 ** A13	
+	PK	, // PK 6 ** 68 ** A14	
+	PK	, // PK 7 ** 69 ** A15	
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
+	// PIN IN PORT		
+	// -------------------------------------------		
+	_BV( 0 )	, // PE 0 ** 0 ** USART0_RX	
+	_BV( 1 )	, // PE 1 ** 1 ** USART0_TX	
+	_BV( 4 )	, // PE 4 ** 2 ** PWM2	
+	_BV( 5 )	, // PE 5 ** 3 ** PWM3	
+	_BV( 5 )	, // PG 5 ** 4 ** PWM4	
+	_BV( 3 )	, // PE 3 ** 5 ** PWM5	
+	_BV( 3 )	, // PH 3 ** 6 ** PWM6	
+	_BV( 4 )	, // PH 4 ** 7 ** PWM7	
+	_BV( 5 )	, // PH 5 ** 8 ** PWM8	
+	_BV( 6 )	, // PH 6 ** 9 ** PWM9	
+	_BV( 4 )	, // PB 4 ** 10 ** PWM10	
+	_BV( 5 )	, // PB 5 ** 11 ** PWM11	
+	_BV( 6 )	, // PB 6 ** 12 ** PWM12	
+	_BV( 7 )	, // PB 7 ** 13 ** PWM13	
+	_BV( 1 )	, // PJ 1 ** 14 ** USART3_TX	
+	_BV( 0 )	, // PJ 0 ** 15 ** USART3_RX	
+	_BV( 1 )	, // PH 1 ** 16 ** USART2_TX	
+	_BV( 0 )	, // PH 0 ** 17 ** USART2_RX	
+	_BV( 3 )	, // PD 3 ** 18 ** USART1_TX	
+	_BV( 2 )	, // PD 2 ** 19 ** USART1_RX	
+	_BV( 1 )	, // PD 1 ** 20 ** I2C_SDA	
+	_BV( 0 )	, // PD 0 ** 21 ** I2C_SCL	
+	_BV( 0 )	, // PA 0 ** 22 ** D22	
+	_BV( 1 )	, // PA 1 ** 23 ** D23	
+	_BV( 2 )	, // PA 2 ** 24 ** D24	
+	_BV( 3 )	, // PA 3 ** 25 ** D25	
+	_BV( 4 )	, // PA 4 ** 26 ** D26	
+	_BV( 5 )	, // PA 5 ** 27 ** D27	
+	_BV( 6 )	, // PA 6 ** 28 ** D28	
+	_BV( 7 )	, // PA 7 ** 29 ** D29	
+	_BV( 7 )	, // PC 7 ** 30 ** D30	
+	_BV( 6 )	, // PC 6 ** 31 ** D31	
+	_BV( 5 )	, // PC 5 ** 32 ** D32	
+	_BV( 4 )	, // PC 4 ** 33 ** D33	
+	_BV( 3 )	, // PC 3 ** 34 ** D34	
+	_BV( 2 )	, // PC 2 ** 35 ** D35	
+	_BV( 1 )	, // PC 1 ** 36 ** D36	
+	_BV( 0 )	, // PC 0 ** 37 ** D37	
+	_BV( 7 )	, // PD 7 ** 38 ** D38	
+	_BV( 2 )	, // PG 2 ** 39 ** D39	
+	_BV( 1 )	, // PG 1 ** 40 ** D40	
+	_BV( 0 )	, // PG 0 ** 41 ** D41	
+	_BV( 7 )	, // PL 7 ** 42 ** D42	
+	_BV( 6 )	, // PL 6 ** 43 ** D43	
+	_BV( 5 )	, // PL 5 ** 44 ** D44	
+	_BV( 4 )	, // PL 4 ** 45 ** D45	
+	_BV( 3 )	, // PL 3 ** 46 ** D46	
+	_BV( 2 )	, // PL 2 ** 47 ** D47	
+	_BV( 1 )	, // PL 1 ** 48 ** D48	
+	_BV( 0 )	, // PL 0 ** 49 ** D49	
+	_BV( 3 )	, // PB 3 ** 50 ** SPI_MISO	
+	_BV( 2 )	, // PB 2 ** 51 ** SPI_MOSI	
+	_BV( 1 )	, // PB 1 ** 52 ** SPI_SCK	
+	_BV( 0 )	, // PB 0 ** 53 ** SPI_SS	
+	_BV( 0 )	, // PF 0 ** 54 ** A0	
+	_BV( 1 )	, // PF 1 ** 55 ** A1	
+	_BV( 2 )	, // PF 2 ** 56 ** A2	
+	_BV( 3 )	, // PF 3 ** 57 ** A3	
+	_BV( 4 )	, // PF 4 ** 58 ** A4	
+	_BV( 5 )	, // PF 5 ** 59 ** A5	
+	_BV( 6 )	, // PF 6 ** 60 ** A6	
+	_BV( 7 )	, // PF 7 ** 61 ** A7	
+	_BV( 0 )	, // PK 0 ** 62 ** A8	
+	_BV( 1 )	, // PK 1 ** 63 ** A9	
+	_BV( 2 )	, // PK 2 ** 64 ** A10	
+	_BV( 3 )	, // PK 3 ** 65 ** A11	
+	_BV( 4 )	, // PK 4 ** 66 ** A12	
+	_BV( 5 )	, // PK 5 ** 67 ** A13	
+	_BV( 6 )	, // PK 6 ** 68 ** A14	
+	_BV( 7 )	, // PK 7 ** 69 ** A15	
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
+	// TIMERS		
+	// -------------------------------------------		
+	NOT_ON_TIMER	, // PE 0 ** 0 ** USART0_RX	
+	NOT_ON_TIMER	, // PE 1 ** 1 ** USART0_TX	
+	TIMER3B	, // PE 4 ** 2 ** PWM2	
+	TIMER3C	, // PE 5 ** 3 ** PWM3	
+	TIMER0B	, // PG 5 ** 4 ** PWM4	
+	TIMER3A	, // PE 3 ** 5 ** PWM5	
+	TIMER4A	, // PH 3 ** 6 ** PWM6	
+	TIMER4B	, // PH 4 ** 7 ** PWM7	
+	TIMER4C	, // PH 5 ** 8 ** PWM8	
+	TIMER2B	, // PH 6 ** 9 ** PWM9	
+	TIMER2A	, // PB 4 ** 10 ** PWM10	
+	TIMER1A	, // PB 5 ** 11 ** PWM11	
+	TIMER1B	, // PB 6 ** 12 ** PWM12	
+	TIMER0A	, // PB 7 ** 13 ** PWM13	
+	NOT_ON_TIMER	, // PJ 1 ** 14 ** USART3_TX	
+	NOT_ON_TIMER	, // PJ 0 ** 15 ** USART3_RX	
+	NOT_ON_TIMER	, // PH 1 ** 16 ** USART2_TX	
+	NOT_ON_TIMER	, // PH 0 ** 17 ** USART2_RX	
+	NOT_ON_TIMER	, // PD 3 ** 18 ** USART1_TX	
+	NOT_ON_TIMER	, // PD 2 ** 19 ** USART1_RX	
+	NOT_ON_TIMER	, // PD 1 ** 20 ** I2C_SDA	
+	NOT_ON_TIMER	, // PD 0 ** 21 ** I2C_SCL	
+	NOT_ON_TIMER	, // PA 0 ** 22 ** D22	
+	NOT_ON_TIMER	, // PA 1 ** 23 ** D23	
+	NOT_ON_TIMER	, // PA 2 ** 24 ** D24	
+	NOT_ON_TIMER	, // PA 3 ** 25 ** D25	
+	NOT_ON_TIMER	, // PA 4 ** 26 ** D26	
+	NOT_ON_TIMER	, // PA 5 ** 27 ** D27	
+	NOT_ON_TIMER	, // PA 6 ** 28 ** D28	
+	NOT_ON_TIMER	, // PA 7 ** 29 ** D29	
+	NOT_ON_TIMER	, // PC 7 ** 30 ** D30	
+	NOT_ON_TIMER	, // PC 6 ** 31 ** D31	
+	NOT_ON_TIMER	, // PC 5 ** 32 ** D32	
+	NOT_ON_TIMER	, // PC 4 ** 33 ** D33	
+	NOT_ON_TIMER	, // PC 3 ** 34 ** D34	
+	NOT_ON_TIMER	, // PC 2 ** 35 ** D35	
+	NOT_ON_TIMER	, // PC 1 ** 36 ** D36	
+	NOT_ON_TIMER	, // PC 0 ** 37 ** D37	
+	NOT_ON_TIMER	, // PD 7 ** 38 ** D38	
+	NOT_ON_TIMER	, // PG 2 ** 39 ** D39	
+	NOT_ON_TIMER	, // PG 1 ** 40 ** D40	
+	NOT_ON_TIMER	, // PG 0 ** 41 ** D41	
+	NOT_ON_TIMER	, // PL 7 ** 42 ** D42	
+	NOT_ON_TIMER	, // PL 6 ** 43 ** D43	
+	TIMER5C	, // PL 5 ** 44 ** D44	
+	TIMER5B	, // PL 4 ** 45 ** D45	
+	TIMER5A	, // PL 3 ** 46 ** D46	
+	NOT_ON_TIMER	, // PL 2 ** 47 ** D47	
+	NOT_ON_TIMER	, // PL 1 ** 48 ** D48	
+	NOT_ON_TIMER	, // PL 0 ** 49 ** D49	
+	NOT_ON_TIMER	, // PB 3 ** 50 ** SPI_MISO	
+	NOT_ON_TIMER	, // PB 2 ** 51 ** SPI_MOSI	
+	NOT_ON_TIMER	, // PB 1 ** 52 ** SPI_SCK	
+	NOT_ON_TIMER	, // PB 0 ** 53 ** SPI_SS	
+	NOT_ON_TIMER	, // PF 0 ** 54 ** A0	
+	NOT_ON_TIMER	, // PF 1 ** 55 ** A1	
+	NOT_ON_TIMER	, // PF 2 ** 56 ** A2	
+	NOT_ON_TIMER	, // PF 3 ** 57 ** A3	
+	NOT_ON_TIMER	, // PF 4 ** 58 ** A4	
+	NOT_ON_TIMER	, // PF 5 ** 59 ** A5	
+	NOT_ON_TIMER	, // PF 6 ** 60 ** A6	
+	NOT_ON_TIMER	, // PF 7 ** 61 ** A7	
+	NOT_ON_TIMER	, // PK 0 ** 62 ** A8	
+	NOT_ON_TIMER	, // PK 1 ** 63 ** A9	
+	NOT_ON_TIMER	, // PK 2 ** 64 ** A10	
+	NOT_ON_TIMER	, // PK 3 ** 65 ** A11	
+	NOT_ON_TIMER	, // PK 4 ** 66 ** A12	
+	NOT_ON_TIMER	, // PK 5 ** 67 ** A13	
+	NOT_ON_TIMER	, // PK 6 ** 68 ** A14	
+	NOT_ON_TIMER	, // PK 7 ** 69 ** A15	
+};
+#else
+// these arrays map port names (e.g. port B) to the
+// appropriate addresses for various functions (e.g. reading
+// and writing)
+const uint16_t PROGMEM port_to_mode_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&DDRB,
+	&DDRC,
+	&DDRD,
+};
+
+const uint16_t PROGMEM port_to_output_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&PORTB,
+	&PORTC,
+	&PORTD,
+};
+
+const uint16_t PROGMEM port_to_input_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&PINB,
+	&PINC,
+	&PIND,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
+	PD, /* 0 */
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PB, /* 8 */
+	PB,
+	PB,
+	PB,
+	PB,
+	PB,
+	PC, /* 14 */
+	PC,
+	PC,
+	PC,
+	PC,
+	PC,
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
+	_BV(0), /* 0, port D */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+	_BV(6),
+	_BV(7),
+	_BV(0), /* 8, port B */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+	_BV(0), /* 14, port C */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[] = {
+	NOT_ON_TIMER, /* 0 - port D */
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	// on the ATmega168, digital pin 3 has hardware pwm
+#if defined(__AVR_ATmega8__)
+	NOT_ON_TIMER,
+#else
+	TIMER2B,
+#endif
+	NOT_ON_TIMER,
+	// on the ATmega168, digital pins 5 and 6 have hardware pwm
+#if defined(__AVR_ATmega8__)
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+#else
+	TIMER0B,
+	TIMER0A,
+#endif
+	NOT_ON_TIMER,
+	NOT_ON_TIMER, /* 8 - port B */
+	TIMER1A,
+	TIMER1B,
+#if defined(__AVR_ATmega8__)
+	TIMER2,
+#else
+	TIMER2A,
+#endif
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER, /* 14 - port C */
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+};
+#endif

+ 76 - 0
optiboot/cores/arduino/pins_arduino.h

@@ -0,0 +1,76 @@
+/*
+  pins_arduino.h - Pin definition functions for Arduino
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2007 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
+*/
+
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include <avr/pgmspace.h>
+
+#define NOT_A_PIN 0
+#define NOT_A_PORT 0
+
+#define NOT_ON_TIMER 0
+#define TIMER0A 1
+#define TIMER0B 2
+#define TIMER1A 3
+#define TIMER1B 4
+#define TIMER2  5
+#define TIMER2A 6
+#define TIMER2B 7
+
+#define TIMER3A 8
+#define TIMER3B 9
+#define TIMER3C 10
+#define TIMER4A 11
+#define TIMER4B 12
+#define TIMER4C 13
+#define TIMER5A 14
+#define TIMER5B 15
+#define TIMER5C 16
+
+// On the ATmega1280, the addresses of some of the port registers are
+// greater than 255, so we can't store them in uint8_t's.
+extern const uint16_t PROGMEM port_to_mode_PGM[];
+extern const uint16_t PROGMEM port_to_input_PGM[];
+extern const uint16_t PROGMEM port_to_output_PGM[];
+
+extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
+// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[];
+extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
+extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
+
+// Get the bit location within the hardware port of the given virtual pin.
+// This comes from the pins_*.c file for the active board configuration.
+// 
+// These perform slightly better as macros compared to inline functions
+//
+#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
+#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
+#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
+#define analogInPinToBit(P) (P)
+#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
+#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
+#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) )
+
+#endif

+ 238 - 0
optiboot/cores/arduino/wiring.c

@@ -0,0 +1,238 @@
+/*
+  wiring.c - Partial implementation of the Wiring API for the ATmega8.
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.c 808 2009-12-18 17:44:08Z dmellis $
+*/
+
+#include "wiring_private.h"
+
+// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
+// the overflow handler is called every 256 ticks.
+#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
+
+// the whole number of milliseconds per timer0 overflow
+#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
+
+// the fractional number of milliseconds per timer0 overflow. we shift right
+// by three to fit these numbers into a byte. (for the clock speeds we care
+// about - 8 and 16 MHz - this doesn't lose precision.)
+#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
+#define FRACT_MAX (1000 >> 3)
+
+volatile unsigned long timer0_overflow_count = 0;
+volatile unsigned long timer0_millis = 0;
+static unsigned char timer0_fract = 0;
+
+SIGNAL(TIMER0_OVF_vect)
+{
+	// copy these to local variables so they can be stored in registers
+	// (volatile variables must be read from memory on every access)
+	unsigned long m = timer0_millis;
+	unsigned char f = timer0_fract;
+
+	m += MILLIS_INC;
+	f += FRACT_INC;
+	if (f >= FRACT_MAX) {
+		f -= FRACT_MAX;
+		m += 1;
+	}
+
+	timer0_fract = f;
+	timer0_millis = m;
+	timer0_overflow_count++;
+}
+
+unsigned long millis()
+{
+	unsigned long m;
+	uint8_t oldSREG = SREG;
+
+	// disable interrupts while we read timer0_millis or we might get an
+	// inconsistent value (e.g. in the middle of a write to timer0_millis)
+	cli();
+	m = timer0_millis;
+	SREG = oldSREG;
+
+	return m;
+}
+
+unsigned long micros() {
+	unsigned long m;
+	uint8_t oldSREG = SREG, t;
+	
+	cli();
+	m = timer0_overflow_count;
+	t = TCNT0;
+  
+#ifdef TIFR0
+	if ((TIFR0 & _BV(TOV0)) && (t < 255))
+		m++;
+#else
+	if ((TIFR & _BV(TOV0)) && (t < 255))
+		m++;
+#endif
+
+	SREG = oldSREG;
+	
+	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
+}
+
+void delay(unsigned long ms)
+{
+	unsigned long start = millis();
+	
+	while (millis() - start <= ms)
+		;
+}
+
+/* Delay for the given number of microseconds.  Assumes a 8 or 16 MHz clock. */
+void delayMicroseconds(unsigned int us)
+{
+	// calling avrlib's delay_us() function with low values (e.g. 1 or
+	// 2 microseconds) gives delays longer than desired.
+	//delay_us(us);
+
+#if F_CPU >= 16000000L
+	// for the 16 MHz clock on most Arduino boards
+
+	// for a one-microsecond delay, simply return.  the overhead
+	// of the function call yields a delay of approximately 1 1/8 us.
+	if (--us == 0)
+		return;
+
+	// the following loop takes a quarter of a microsecond (4 cycles)
+	// per iteration, so execute it four times for each microsecond of
+	// delay requested.
+	us <<= 2;
+
+	// account for the time taken in the preceeding commands.
+	us -= 2;
+#else
+	// for the 8 MHz internal clock on the ATmega168
+
+	// for a one- or two-microsecond delay, simply return.  the overhead of
+	// the function calls takes more than two microseconds.  can't just
+	// subtract two, since us is unsigned; we'd overflow.
+	if (--us == 0)
+		return;
+	if (--us == 0)
+		return;
+
+	// the following loop takes half of a microsecond (4 cycles)
+	// per iteration, so execute it twice for each microsecond of
+	// delay requested.
+	us <<= 1;
+    
+	// partially compensate for the time taken by the preceeding commands.
+	// we can't subtract any more than this or we'd overflow w/ small delays.
+	us--;
+#endif
+
+	// busy wait
+	__asm__ __volatile__ (
+		"1: sbiw %0,1" "\n\t" // 2 cycles
+		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+	);
+}
+
+void init()
+{
+	// this needs to be called before setup() or some functions won't
+	// work there
+	sei();
+	
+	// on the ATmega168, timer 0 is also used for fast hardware pwm
+	// (using phase-correct PWM would mean that timer 0 overflowed half as often
+	// resulting in different millis() behavior on the ATmega8 and ATmega168)
+#if !defined(__AVR_ATmega8__)
+	sbi(TCCR0A, WGM01);
+	sbi(TCCR0A, WGM00);
+#endif  
+	// set timer 0 prescale factor to 64
+#if defined(__AVR_ATmega8__)
+	sbi(TCCR0, CS01);
+	sbi(TCCR0, CS00);
+#else
+	sbi(TCCR0B, CS01);
+	sbi(TCCR0B, CS00);
+#endif
+	// enable timer 0 overflow interrupt
+#if defined(__AVR_ATmega8__)
+	sbi(TIMSK, TOIE0);
+#else
+	sbi(TIMSK0, TOIE0);
+#endif
+
+	// timers 1 and 2 are used for phase-correct hardware pwm
+	// this is better for motors as it ensures an even waveform
+	// note, however, that fast pwm mode can achieve a frequency of up
+	// 8 MHz (with a 16 MHz clock) at 50% duty cycle
+
+	// set timer 1 prescale factor to 64
+	sbi(TCCR1B, CS11);
+	sbi(TCCR1B, CS10);
+	// put timer 1 in 8-bit phase correct pwm mode
+	sbi(TCCR1A, WGM10);
+
+	// set timer 2 prescale factor to 64
+#if defined(__AVR_ATmega8__)
+	sbi(TCCR2, CS22);
+#else
+	sbi(TCCR2B, CS22);
+#endif
+	// configure timer 2 for phase correct pwm (8-bit)
+#if defined(__AVR_ATmega8__)
+	sbi(TCCR2, WGM20);
+#else
+	sbi(TCCR2A, WGM20);
+#endif
+
+#if defined(__AVR_ATmega1280__)
+	// set timer 3, 4, 5 prescale factor to 64
+	sbi(TCCR3B, CS31);	sbi(TCCR3B, CS30);
+	sbi(TCCR4B, CS41);	sbi(TCCR4B, CS40);
+	sbi(TCCR5B, CS51);	sbi(TCCR5B, CS50);
+	// put timer 3, 4, 5 in 8-bit phase correct pwm mode
+	sbi(TCCR3A, WGM30);
+	sbi(TCCR4A, WGM40);
+	sbi(TCCR5A, WGM50);
+#endif
+
+	// set a2d prescale factor to 128
+	// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
+	// XXX: this will not work properly for other clock speeds, and
+	// this code should use F_CPU to determine the prescale factor.
+	sbi(ADCSRA, ADPS2);
+	sbi(ADCSRA, ADPS1);
+	sbi(ADCSRA, ADPS0);
+
+	// enable a2d conversions
+	sbi(ADCSRA, ADEN);
+
+	// the bootloader connects pins 0 and 1 to the USART; disconnect them
+	// here so they can be used as normal digital i/o; they will be
+	// reconnected in Serial.begin()
+#if defined(__AVR_ATmega8__)
+	UCSRB = 0;
+#else
+	UCSR0B = 0;
+#endif
+}

+ 133 - 0
optiboot/cores/arduino/wiring.h

@@ -0,0 +1,133 @@
+/*
+  wiring.h - Partial implementation of the Wiring API for the ATmega8.
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.h 804 2009-12-18 16:05:52Z dmellis $
+*/
+
+#ifndef Wiring_h
+#define Wiring_h
+
+#include <avr/io.h>
+#include "binary.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#define HIGH 0x1
+#define LOW  0x0
+
+#define INPUT 0x0
+#define OUTPUT 0x1
+
+#define true 0x1
+#define false 0x0
+
+#define PI 3.1415926535897932384626433832795
+#define HALF_PI 1.5707963267948966192313216916398
+#define TWO_PI 6.283185307179586476925286766559
+#define DEG_TO_RAD 0.017453292519943295769236907684886
+#define RAD_TO_DEG 57.295779513082320876798154814105
+
+#define SERIAL  0x0
+#define DISPLAY 0x1
+
+#define LSBFIRST 0
+#define MSBFIRST 1
+
+#define CHANGE 1
+#define FALLING 2
+#define RISING 3
+
+#define INTERNAL 3
+#define DEFAULT 1
+#define EXTERNAL 0
+
+// undefine stdlib's abs if encountered
+#ifdef abs
+#undef abs
+#endif
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+#define abs(x) ((x)>0?(x):-(x))
+#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+#define radians(deg) ((deg)*DEG_TO_RAD)
+#define degrees(rad) ((rad)*RAD_TO_DEG)
+#define sq(x) ((x)*(x))
+
+#define interrupts() sei()
+#define noInterrupts() cli()
+
+#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
+#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
+#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )
+
+#define lowByte(w) ((uint8_t) ((w) & 0xff))
+#define highByte(w) ((uint8_t) ((w) >> 8))
+
+#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
+#define bitSet(value, bit) ((value) |= (1UL << (bit)))
+#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
+#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
+
+typedef unsigned int word;
+
+#define bit(b) (1UL << (b))
+
+typedef uint8_t boolean;
+typedef uint8_t byte;
+
+void init(void);
+
+void pinMode(uint8_t, uint8_t);
+void digitalWrite(uint8_t, uint8_t);
+int digitalRead(uint8_t);
+int analogRead(uint8_t);
+void analogReference(uint8_t mode);
+void analogWrite(uint8_t, int);
+
+void beginSerial(long);
+void serialWrite(unsigned char);
+int serialAvailable(void);
+int serialRead(void);
+void serialFlush(void);
+
+unsigned long millis(void);
+unsigned long micros(void);
+void delay(unsigned long);
+void delayMicroseconds(unsigned int us);
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val);
+
+void attachInterrupt(uint8_t, void (*)(void), int mode);
+void detachInterrupt(uint8_t);
+
+void setup(void);
+void loop(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif

+ 179 - 0
optiboot/cores/arduino/wiring_analog.c

@@ -0,0 +1,179 @@
+/*
+  wiring_analog.c - analog input and output
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+uint8_t analog_reference = DEFAULT;
+
+void analogReference(uint8_t mode)
+{
+	// can't actually set the register here because the default setting
+	// will connect AVCC and the AREF pin, which would cause a short if
+	// there's something connected to AREF.
+	analog_reference = mode;
+}
+
+int analogRead(uint8_t pin)
+{
+	uint8_t low, high;
+
+	// set the analog reference (high two bits of ADMUX) and select the
+	// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
+	// to 0 (the default).
+	ADMUX = (analog_reference << 6) | (pin & 0x07);
+  
+#if defined(__AVR_ATmega1280__)
+	// the MUX5 bit of ADCSRB selects whether we're reading from channels
+	// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
+	ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
+#endif
+
+	// without a delay, we seem to read from the wrong channel
+	//delay(1);
+
+	// start the conversion
+	sbi(ADCSRA, ADSC);
+
+	// ADSC is cleared when the conversion finishes
+	while (bit_is_set(ADCSRA, ADSC));
+
+	// we have to read ADCL first; doing so locks both ADCL
+	// and ADCH until ADCH is read.  reading ADCL second would
+	// cause the results of each conversion to be discarded,
+	// as ADCL and ADCH would be locked when it completed.
+	low = ADCL;
+	high = ADCH;
+
+	// combine the two bytes
+	return (high << 8) | low;
+}
+
+// Right now, PWM output only works on the pins with
+// hardware support.  These are defined in the appropriate
+// pins_*.c file.  For the rest of the pins, we default
+// to digital output.
+void analogWrite(uint8_t pin, int val)
+{
+	// We need to make sure the PWM output is enabled for those pins
+	// that support it, as we turn it off when digitally reading or
+	// writing with them.  Also, make sure the pin is in output mode
+	// for consistenty with Wiring, which doesn't require a pinMode
+	// call for the analog output pins.
+	pinMode(pin, OUTPUT);
+	
+	if (digitalPinToTimer(pin) == TIMER1A) {
+		// connect pwm to pin on timer 1, channel A
+		sbi(TCCR1A, COM1A1);
+		// set pwm duty
+		OCR1A = val;
+	} else if (digitalPinToTimer(pin) == TIMER1B) {
+		// connect pwm to pin on timer 1, channel B
+		sbi(TCCR1A, COM1B1);
+		// set pwm duty
+		OCR1B = val;
+#if defined(__AVR_ATmega8__)
+	} else if (digitalPinToTimer(pin) == TIMER2) {
+		// connect pwm to pin on timer 2, channel B
+		sbi(TCCR2, COM21);
+		// set pwm duty
+		OCR2 = val;
+#else
+	} else if (digitalPinToTimer(pin) == TIMER0A) {
+		if (val == 0) {
+			digitalWrite(pin, LOW);
+		} else {
+			// connect pwm to pin on timer 0, channel A
+			sbi(TCCR0A, COM0A1);
+			// set pwm duty
+			OCR0A = val;      
+		}
+	} else if (digitalPinToTimer(pin) == TIMER0B) {
+		if (val == 0) {
+			digitalWrite(pin, LOW);
+		} else {
+			// connect pwm to pin on timer 0, channel B
+			sbi(TCCR0A, COM0B1);
+			// set pwm duty
+			OCR0B = val;
+		}
+	} else if (digitalPinToTimer(pin) == TIMER2A) {
+		// connect pwm to pin on timer 2, channel A
+		sbi(TCCR2A, COM2A1);
+		// set pwm duty
+		OCR2A = val;	
+	} else if (digitalPinToTimer(pin) == TIMER2B) {
+		// connect pwm to pin on timer 2, channel B
+		sbi(TCCR2A, COM2B1);
+		// set pwm duty
+		OCR2B = val;
+#endif
+#if defined(__AVR_ATmega1280__)
+	// XXX: need to handle other timers here
+	} else if (digitalPinToTimer(pin) == TIMER3A) {
+		// connect pwm to pin on timer 3, channel A
+		sbi(TCCR3A, COM3A1);
+		// set pwm duty
+		OCR3A = val;
+	} else if (digitalPinToTimer(pin) == TIMER3B) {
+		// connect pwm to pin on timer 3, channel B
+		sbi(TCCR3A, COM3B1);
+		// set pwm duty
+		OCR3B = val;
+	} else if (digitalPinToTimer(pin) == TIMER3C) {
+		// connect pwm to pin on timer 3, channel C
+		sbi(TCCR3A, COM3C1);
+		// set pwm duty
+		OCR3C = val;
+	} else if (digitalPinToTimer(pin) == TIMER4A) {
+		// connect pwm to pin on timer 4, channel A
+		sbi(TCCR4A, COM4A1);
+		// set pwm duty
+		OCR4A = val;
+	} else if (digitalPinToTimer(pin) == TIMER4B) {
+		// connect pwm to pin on timer 4, channel B
+		sbi(TCCR4A, COM4B1);
+		// set pwm duty
+		OCR4B = val;
+	} else if (digitalPinToTimer(pin) == TIMER4C) {
+		// connect pwm to pin on timer 4, channel C
+		sbi(TCCR4A, COM4C1);
+		// set pwm duty
+		OCR4C = val;
+	} else if (digitalPinToTimer(pin) == TIMER5A) {
+		// connect pwm to pin on timer 5, channel A
+		sbi(TCCR5A, COM5A1);
+		// set pwm duty
+		OCR5A = val;
+	} else if (digitalPinToTimer(pin) == TIMER5B) {
+		// connect pwm to pin on timer 5, channel B
+		sbi(TCCR5A, COM5B1);
+		// set pwm duty
+		OCR5B = val;
+#endif
+	} else if (val < 128)
+		digitalWrite(pin, LOW);
+	else
+		digitalWrite(pin, HIGH);
+}

+ 111 - 0
optiboot/cores/arduino/wiring_digital.c

@@ -0,0 +1,111 @@
+/*
+  wiring_digital.c - digital input and output functions
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+void pinMode(uint8_t pin, uint8_t mode)
+{
+	uint8_t bit = digitalPinToBitMask(pin);
+	uint8_t port = digitalPinToPort(pin);
+	volatile uint8_t *reg;
+
+	if (port == NOT_A_PIN) return;
+
+	// JWS: can I let the optimizer do this?
+	reg = portModeRegister(port);
+
+	if (mode == INPUT) *reg &= ~bit;
+	else *reg |= bit;
+}
+
+// Forcing this inline keeps the callers from having to push their own stuff
+// on the stack. It is a good performance win and only takes 1 more byte per
+// user than calling. (It will take more bytes on the 168.)
+//
+// But shouldn't this be moved into pinMode? Seems silly to check and do on
+// each digitalread or write.
+//
+static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline));
+static inline void turnOffPWM(uint8_t timer)
+{
+	if (timer == TIMER1A) cbi(TCCR1A, COM1A1);
+	if (timer == TIMER1B) cbi(TCCR1A, COM1B1);
+
+#if defined(__AVR_ATmega8__)
+	if (timer == TIMER2) cbi(TCCR2, COM21);
+#else
+	if (timer == TIMER0A) cbi(TCCR0A, COM0A1);
+	if (timer == TIMER0B) cbi(TCCR0A, COM0B1);
+	if (timer == TIMER2A) cbi(TCCR2A, COM2A1);
+	if (timer == TIMER2B) cbi(TCCR2A, COM2B1);
+#endif
+
+#if defined(__AVR_ATmega1280__)
+	if (timer == TIMER3A) cbi(TCCR3A, COM3A1);
+	if (timer == TIMER3B) cbi(TCCR3A, COM3B1);
+	if (timer == TIMER3C) cbi(TCCR3A, COM3C1);
+	if (timer == TIMER4A) cbi(TCCR4A, COM4A1);
+	if (timer == TIMER4B) cbi(TCCR4A, COM4B1);
+	if (timer == TIMER4C) cbi(TCCR4A, COM4C1);
+	if (timer == TIMER5A) cbi(TCCR5A, COM5A1);
+	if (timer == TIMER5B) cbi(TCCR5A, COM5B1);
+	if (timer == TIMER5C) cbi(TCCR5A, COM5C1);
+#endif
+}
+
+void digitalWrite(uint8_t pin, uint8_t val)
+{
+	uint8_t timer = digitalPinToTimer(pin);
+	uint8_t bit = digitalPinToBitMask(pin);
+	uint8_t port = digitalPinToPort(pin);
+	volatile uint8_t *out;
+
+	if (port == NOT_A_PIN) return;
+
+	// If the pin that support PWM output, we need to turn it off
+	// before doing a digital write.
+	if (timer != NOT_ON_TIMER) turnOffPWM(timer);
+
+	out = portOutputRegister(port);
+
+	if (val == LOW) *out &= ~bit;
+	else *out |= bit;
+}
+
+int digitalRead(uint8_t pin)
+{
+	uint8_t timer = digitalPinToTimer(pin);
+	uint8_t bit = digitalPinToBitMask(pin);
+	uint8_t port = digitalPinToPort(pin);
+
+	if (port == NOT_A_PIN) return LOW;
+
+	// If the pin that support PWM output, we need to turn it off
+	// before getting a digital reading.
+	if (timer != NOT_ON_TIMER) turnOffPWM(timer);
+
+	if (*portInputRegister(port) & bit) return HIGH;
+	return LOW;
+}

+ 68 - 0
optiboot/cores/arduino/wiring_private.h

@@ -0,0 +1,68 @@
+/*
+  wiring_private.h - Internal header file.
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $
+*/
+
+#ifndef WiringPrivate_h
+#define WiringPrivate_h
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/delay.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "wiring.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#ifndef cbi
+#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
+#endif
+#ifndef sbi
+#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
+#endif
+
+#define EXTERNAL_INT_0 0
+#define EXTERNAL_INT_1 1
+#define EXTERNAL_INT_2 2
+#define EXTERNAL_INT_3 3
+#define EXTERNAL_INT_4 4
+#define EXTERNAL_INT_5 5
+#define EXTERNAL_INT_6 6
+#define EXTERNAL_INT_7 7
+
+#if defined(__AVR_ATmega1280__)
+#define EXTERNAL_NUM_INTERRUPTS 8
+#else
+#define EXTERNAL_NUM_INTERRUPTS 2
+#endif
+
+typedef void (*voidFuncPtr)(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif

+ 66 - 0
optiboot/cores/arduino/wiring_pulse.c

@@ -0,0 +1,66 @@
+/*
+  wiring_pulse.c - pulseIn() function
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
+ * or LOW, the type of pulse to measure.  Works on pulses from 2-3 microseconds
+ * to 3 minutes in length, but must be called at least a few dozen microseconds
+ * before the start of the pulse. */
+unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
+{
+	// cache the port and bit of the pin in order to speed up the
+	// pulse width measuring loop and achieve finer resolution.  calling
+	// digitalRead() instead yields much coarser resolution.
+	uint8_t bit = digitalPinToBitMask(pin);
+	uint8_t port = digitalPinToPort(pin);
+	uint8_t stateMask = (state ? bit : 0);
+	unsigned long width = 0; // keep initialization out of time critical area
+	
+	// convert the timeout from microseconds to a number of times through
+	// the initial loop; it takes 16 clock cycles per iteration.
+	unsigned long numloops = 0;
+	unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
+	
+	// wait for any previous pulse to end
+	while ((*portInputRegister(port) & bit) == stateMask)
+		if (numloops++ == maxloops)
+			return 0;
+	
+	// wait for the pulse to start
+	while ((*portInputRegister(port) & bit) != stateMask)
+		if (numloops++ == maxloops)
+			return 0;
+	
+	// wait for the pulse to stop
+	while ((*portInputRegister(port) & bit) == stateMask)
+		width++;
+
+	// convert the reading to microseconds. The loop has been determined
+	// to be 10 clock cycles long and have about 16 clocks between the edge
+	// and the start of the loop. There will be some error introduced by
+	// the interrupt handlers.
+	return clockCyclesToMicroseconds(width * 10 + 16); 
+}

+ 40 - 0
optiboot/cores/arduino/wiring_shift.c

@@ -0,0 +1,40 @@
+/*
+  wiring_shift.c - shiftOut() function
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General
+  Public License along with this library; if not, write to the
+  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+  Boston, MA  02111-1307  USA
+
+  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+#include "wiring_private.h"
+
+void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)  {
+		if (bitOrder == LSBFIRST)
+			digitalWrite(dataPin, !!(val & (1 << i)));
+		else	
+			digitalWrite(dataPin, !!(val & (1 << (7 - i))));
+			
+		digitalWrite(clockPin, HIGH);
+		digitalWrite(clockPin, LOW);		
+	}
+}