Browse Source

Oops! Add missing files to repo for Luminet, Sanguino and Mega

cathedrow 15 years ago
parent
commit
a65fe8e957
68 changed files with 9731 additions and 0 deletions
  1. 848 0
      optiboot/bootloaders/optiboot/boot.h
  2. 34 0
      optiboot/bootloaders/optiboot/optiboot_atmega1280.hex
  3. 533 0
      optiboot/bootloaders/optiboot/optiboot_atmega1280.lst
  4. 32 0
      optiboot/bootloaders/optiboot/optiboot_atmega644p.hex
  5. 525 0
      optiboot/bootloaders/optiboot/optiboot_atmega644p.lst
  6. 42 0
      optiboot/bootloaders/optiboot/optiboot_luminet.hex
  7. 608 0
      optiboot/bootloaders/optiboot/optiboot_luminet.lst
  8. 69 0
      optiboot/bootloaders/optiboot/pin_defs.h
  9. 39 0
      optiboot/bootloaders/optiboot/stk500.h
  10. 149 0
      optiboot/cores/luminet/COM.c
  11. 70 0
      optiboot/cores/luminet/COM.h
  12. 361 0
      optiboot/cores/luminet/COMasm.S
  13. 62 0
      optiboot/cores/luminet/HardwareSerial.cpp
  14. 41 0
      optiboot/cores/luminet/HardwareSerial.h
  15. 14 0
      optiboot/cores/luminet/LEDExtensions.c
  16. 17 0
      optiboot/cores/luminet/LEDExtensions.h
  17. 253 0
      optiboot/cores/luminet/Makefile
  18. 213 0
      optiboot/cores/luminet/Print.cpp
  19. 59 0
      optiboot/cores/luminet/Print.h
  20. 1 0
      optiboot/cores/luminet/WConstants.h
  21. 106 0
      optiboot/cores/luminet/WInterrupts.c
  22. 60 0
      optiboot/cores/luminet/WMath.cpp
  23. 37 0
      optiboot/cores/luminet/WProgram.h
  24. 515 0
      optiboot/cores/luminet/binary.h
  25. 304 0
      optiboot/cores/luminet/bynase.c
  26. 30 0
      optiboot/cores/luminet/bynase.h
  27. BIN
      optiboot/cores/luminet/cmd.exe.lnk
  28. 72 0
      optiboot/cores/luminet/digitalWriteASM.S
  29. 6 0
      optiboot/cores/luminet/fastDigital.c
  30. 20 0
      optiboot/cores/luminet/fastDigital.h
  31. 152 0
      optiboot/cores/luminet/luminet.h
  32. 39 0
      optiboot/cores/luminet/main.cxx
  33. 154 0
      optiboot/cores/luminet/pins_arduino.c
  34. 65 0
      optiboot/cores/luminet/pins_arduino.h
  35. 268 0
      optiboot/cores/luminet/topology.c
  36. 26 0
      optiboot/cores/luminet/topology.h
  37. 224 0
      optiboot/cores/luminet/wiring.c
  38. 134 0
      optiboot/cores/luminet/wiring.h
  39. 184 0
      optiboot/cores/luminet/wiring_analog.c
  40. 93 0
      optiboot/cores/luminet/wiring_digital.c
  41. 58 0
      optiboot/cores/luminet/wiring_private.h
  42. 66 0
      optiboot/cores/luminet/wiring_pulse.c
  43. 135 0
      optiboot/cores/luminet/wiring_serial.c
  44. 40 0
      optiboot/cores/luminet/wiring_shift.c
  45. 67 0
      optiboot/cores/sanguino/HardwareSerial.cpp
  46. 47 0
      optiboot/cores/sanguino/HardwareSerial.h
  47. 243 0
      optiboot/cores/sanguino/Makefile
  48. 203 0
      optiboot/cores/sanguino/Print.cpp
  49. 59 0
      optiboot/cores/sanguino/Print.h
  50. 515 0
      optiboot/cores/sanguino/Tone.cpp
  51. 1 0
      optiboot/cores/sanguino/WConstants.h
  52. 87 0
      optiboot/cores/sanguino/WInterrupts.c
  53. 60 0
      optiboot/cores/sanguino/WMath.cpp
  54. 29 0
      optiboot/cores/sanguino/WProgram.h
  55. 5 0
      optiboot/cores/sanguino/_ReadMe.txt
  56. 515 0
      optiboot/cores/sanguino/binary.h
  57. 14 0
      optiboot/cores/sanguino/main.cpp
  58. 12 0
      optiboot/cores/sanguino/main.cxx
  59. 200 0
      optiboot/cores/sanguino/pins_arduino.c
  60. 65 0
      optiboot/cores/sanguino/pins_arduino.h
  61. 203 0
      optiboot/cores/sanguino/wiring.c
  62. 133 0
      optiboot/cores/sanguino/wiring.h
  63. 116 0
      optiboot/cores/sanguino/wiring_analog.c
  64. 95 0
      optiboot/cores/sanguino/wiring_digital.c
  65. 60 0
      optiboot/cores/sanguino/wiring_private.h
  66. 66 0
      optiboot/cores/sanguino/wiring_pulse.c
  67. 138 0
      optiboot/cores/sanguino/wiring_serial.c
  68. 40 0
      optiboot/cores/sanguino/wiring_shift.c

+ 848 - 0
optiboot/bootloaders/optiboot/boot.h

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

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

@@ -0,0 +1,34 @@
+:020000021000EC
+:10FC000085E08093810082E08093C00088E180934A
+:10FC1000C10086E08093C20080E18093C40084B775
+:10FC200014BE81FFCFD08DE0C7D0279A86E020E3B5
+:10FC30003CEF91E0309385002093840096BBB09B0D
+:10FC4000FECF1F9AA8958150A9F7DD24D394A5E093
+:10FC5000EA2EF1E1FF2EA3D0813419F481E0BDD06A
+:10FC60008CC0823411F484E103C0853419F485E03A
+:10FC7000B4D08AC08535A9F492D0082F10E08FD077
+:10FC800090E0982F8827802B912B292F221F222745
+:10FC9000221F2BBF880F991F9093010480930004AB
+:10FCA00072C0863529F484E098D080E070D06CC0B2
+:10FCB000843609F03FC07BD0E0910004F09101044C
+:10FCC00083E087BFE895C0E0D2E069D08993809156
+:10FCD00002048150809302048823B9F778D007B6D4
+:10FCE00000FCFDCF4091000450910104A0E0B2E07F
+:10FCF0002C9130E011968C91119790E0982F8827E5
+:10FD0000822B932B1296FA010C01D7BEE895112491
+:10FD10004E5F5F4FF3E0A030BF0751F7E091000462
+:10FD2000F0910104E7BEE89507B600FCFDCFF7BEF1
+:10FD3000E8952AC08437D1F43AD049D0E091000444
+:10FD4000F0910104E6918E2F22D0809100049091D1
+:10FD500001040196909301048093000480910204B1
+:10FD6000815080930204882349F70EC0853739F407
+:10FD70002ED08EE10CD087E90AD083E097CF813571
+:10FD800011F488E019D023D080E101D064CF982FFE
+:10FD90008091C00085FFFCCF9093C6000895A89580
+:10FDA0008091C00087FFFCCF8091C6000895F7DFE7
+:10FDB000F6DF80930204F3CFE0E6F0E098E1908371
+:10FDC0008083089580E0F8DFEE27FF270994E7DFBE
+:10FDD000803209F0F7DF84E1DACF1F93182FDFDFDD
+:0AFDE0001150E9F7F4DF1F910895B8
+:040000031000FC00ED
+:00000001FF

+ 533 - 0
optiboot/bootloaders/optiboot/optiboot_atmega1280.lst

@@ -0,0 +1,533 @@
+
+optiboot_atmega1280.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001ea  0001fc00  0001fc00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  0000023e  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 0000006a  00000000  00000000  00000266  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   00000277  00000000  00000000  000002d0  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 000001a1  00000000  00000000  00000547  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003eb  00000000  00000000  000006e8  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000ad4  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    00000135  00000000  00000000  00000b64  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001b1  00000000  00000000  00000c99  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000e4a  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+0001fc00 <main>:
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+   1fc00:	85 e0       	ldi	r24, 0x05	; 5
+   1fc02:	80 93 81 00 	sts	0x0081, r24
+#if LED_START_FLASHES > 0
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+#endif
+#ifndef SOFT_UART
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+   1fc06:	82 e0       	ldi	r24, 0x02	; 2
+   1fc08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+   1fc0c:	88 e1       	ldi	r24, 0x18	; 24
+   1fc0e:	80 93 c1 00 	sts	0x00C1, r24
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+   1fc12:	86 e0       	ldi	r24, 0x06	; 6
+   1fc14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+   1fc18:	80 e1       	ldi	r24, 0x10	; 16
+   1fc1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+   1fc1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+   1fc20:	14 be       	out	0x34, r1	; 52
+  if (!(ch & _BV(EXTRF))) appStart();
+   1fc22:	81 ff       	sbrs	r24, 1
+   1fc24:	cf d0       	rcall	.+414    	; 0x1fdc4 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(WATCHDOG_500MS);
+   1fc26:	8d e0       	ldi	r24, 0x0D	; 13
+   1fc28:	c7 d0       	rcall	.+398    	; 0x1fdb8 <watchdogConfig>
+
+  /* Set LED pin as output */
+  LED_DDR |= _BV(LED);
+   1fc2a:	27 9a       	sbi	0x04, 7	; 4
+   1fc2c:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+   1fc2e:	20 e3       	ldi	r18, 0x30	; 48
+   1fc30:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+   1fc32:	91 e0       	ldi	r25, 0x01	; 1
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+   1fc34:	30 93 85 00 	sts	0x0085, r19
+   1fc38:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+   1fc3c:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+   1fc3e:	b0 9b       	sbis	0x16, 0	; 22
+   1fc40:	fe cf       	rjmp	.-4      	; 0x1fc3e <main+0x3e>
+    LED_PIN |= _BV(LED);
+   1fc42:	1f 9a       	sbi	0x03, 7	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+   1fc44:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
+    while(!(TIFR1 & _BV(TOV1)));
+    LED_PIN |= _BV(LED);
+    watchdogReset();
+  } while (--count);
+   1fc46:	81 50       	subi	r24, 0x01	; 1
+   1fc48:	a9 f7       	brne	.-22     	; 0x1fc34 <main+0x34>
+    /* 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);
+   1fc4a:	dd 24       	eor	r13, r13
+   1fc4c:	d3 94       	inc	r13
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+   1fc4e:	a5 e0       	ldi	r26, 0x05	; 5
+   1fc50:	ea 2e       	mov	r14, r26
+      boot_spm_busy_wait();
+
+#if defined(RWWSRE)
+      // Reenable read access to flash
+      boot_rww_enable();
+   1fc52:	f1 e1       	ldi	r31, 0x11	; 17
+   1fc54:	ff 2e       	mov	r15, r31
+#endif
+
+  /* Forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+   1fc56:	a3 d0       	rcall	.+326    	; 0x1fd9e <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+   1fc58:	81 34       	cpi	r24, 0x41	; 65
+   1fc5a:	19 f4       	brne	.+6      	; 0x1fc62 <main+0x62>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+   1fc5c:	81 e0       	ldi	r24, 0x01	; 1
+   1fc5e:	bd d0       	rcall	.+378    	; 0x1fdda <verifySpace+0xc>
+   1fc60:	8c c0       	rjmp	.+280    	; 0x1fd7a <main+0x17a>
+      putch(0x03);
+    }
+    else if(ch == STK_SET_DEVICE) {
+   1fc62:	82 34       	cpi	r24, 0x42	; 66
+   1fc64:	11 f4       	brne	.+4      	; 0x1fc6a <main+0x6a>
+      // SET DEVICE is ignored
+      getNch(20);
+   1fc66:	84 e1       	ldi	r24, 0x14	; 20
+   1fc68:	03 c0       	rjmp	.+6      	; 0x1fc70 <main+0x70>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+   1fc6a:	85 34       	cpi	r24, 0x45	; 69
+   1fc6c:	19 f4       	brne	.+6      	; 0x1fc74 <main+0x74>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+   1fc6e:	85 e0       	ldi	r24, 0x05	; 5
+   1fc70:	b4 d0       	rcall	.+360    	; 0x1fdda <verifySpace+0xc>
+   1fc72:	8a c0       	rjmp	.+276    	; 0x1fd88 <main+0x188>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+   1fc74:	85 35       	cpi	r24, 0x55	; 85
+   1fc76:	a9 f4       	brne	.+42     	; 0x1fca2 <main+0xa2>
+      // LOAD ADDRESS
+      uint16_t newAddress;
+      newAddress = getch();
+   1fc78:	92 d0       	rcall	.+292    	; 0x1fd9e <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
+   1fc7a:	08 2f       	mov	r16, r24
+   1fc7c:	10 e0       	ldi	r17, 0x00	; 0
+   1fc7e:	8f d0       	rcall	.+286    	; 0x1fd9e <getch>
+   1fc80:	90 e0       	ldi	r25, 0x00	; 0
+   1fc82:	98 2f       	mov	r25, r24
+   1fc84:	88 27       	eor	r24, r24
+   1fc86:	80 2b       	or	r24, r16
+   1fc88:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+   1fc8a:	29 2f       	mov	r18, r25
+   1fc8c:	22 1f       	adc	r18, r18
+   1fc8e:	22 27       	eor	r18, r18
+   1fc90:	22 1f       	adc	r18, r18
+   1fc92:	2b bf       	out	0x3b, r18	; 59
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+   1fc94:	88 0f       	add	r24, r24
+   1fc96:	99 1f       	adc	r25, r25
+      address = newAddress;
+   1fc98:	90 93 01 04 	sts	0x0401, r25
+   1fc9c:	80 93 00 04 	sts	0x0400, r24
+   1fca0:	72 c0       	rjmp	.+228    	; 0x1fd86 <main+0x186>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+   1fca2:	86 35       	cpi	r24, 0x56	; 86
+   1fca4:	29 f4       	brne	.+10     	; 0x1fcb0 <main+0xb0>
+      // UNIVERSAL command is ignored
+      getNch(4);
+   1fca6:	84 e0       	ldi	r24, 0x04	; 4
+   1fca8:	98 d0       	rcall	.+304    	; 0x1fdda <verifySpace+0xc>
+      putch(0x00);
+   1fcaa:	80 e0       	ldi	r24, 0x00	; 0
+   1fcac:	70 d0       	rcall	.+224    	; 0x1fd8e <putch>
+   1fcae:	6c c0       	rjmp	.+216    	; 0x1fd88 <main+0x188>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+   1fcb0:	84 36       	cpi	r24, 0x64	; 100
+   1fcb2:	09 f0       	breq	.+2      	; 0x1fcb6 <main+0xb6>
+   1fcb4:	3f c0       	rjmp	.+126    	; 0x1fd34 <main+0x134>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+
+      getLen();
+   1fcb6:	7b d0       	rcall	.+246    	; 0x1fdae <getLen>
+
+      // Immediately start page erase - this will 4.5ms
+      __boot_page_erase_short((uint16_t)(void*)address);
+   1fcb8:	e0 91 00 04 	lds	r30, 0x0400
+   1fcbc:	f0 91 01 04 	lds	r31, 0x0401
+   1fcc0:	83 e0       	ldi	r24, 0x03	; 3
+   1fcc2:	87 bf       	out	0x37, r24	; 55
+   1fcc4:	e8 95       	spm
+   1fcc6:	c0 e0       	ldi	r28, 0x00	; 0
+   1fcc8:	d2 e0       	ldi	r29, 0x02	; 2
+      
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+   1fcca:	69 d0       	rcall	.+210    	; 0x1fd9e <getch>
+   1fccc:	89 93       	st	Y+, r24
+      while (--length);
+   1fcce:	80 91 02 04 	lds	r24, 0x0402
+   1fcd2:	81 50       	subi	r24, 0x01	; 1
+   1fcd4:	80 93 02 04 	sts	0x0402, r24
+   1fcd8:	88 23       	and	r24, r24
+   1fcda:	b9 f7       	brne	.-18     	; 0x1fcca <main+0xca>
+
+      // Read command terminator, start reply
+      verifySpace();
+   1fcdc:	78 d0       	rcall	.+240    	; 0x1fdce <verifySpace>
+      
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+   1fcde:	07 b6       	in	r0, 0x37	; 55
+   1fce0:	00 fc       	sbrc	r0, 0
+   1fce2:	fd cf       	rjmp	.-6      	; 0x1fcde <main+0xde>
+      }
+#endif
+
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+   1fce4:	40 91 00 04 	lds	r20, 0x0400
+   1fce8:	50 91 01 04 	lds	r21, 0x0401
+   1fcec:	a0 e0       	ldi	r26, 0x00	; 0
+   1fcee:	b2 e0       	ldi	r27, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+   1fcf0:	2c 91       	ld	r18, X
+   1fcf2:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+   1fcf4:	11 96       	adiw	r26, 0x01	; 1
+   1fcf6:	8c 91       	ld	r24, X
+   1fcf8:	11 97       	sbiw	r26, 0x01	; 1
+   1fcfa:	90 e0       	ldi	r25, 0x00	; 0
+   1fcfc:	98 2f       	mov	r25, r24
+   1fcfe:	88 27       	eor	r24, r24
+   1fd00:	82 2b       	or	r24, r18
+   1fd02:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+   1fd04:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+   1fd06:	fa 01       	movw	r30, r20
+   1fd08:	0c 01       	movw	r0, r24
+   1fd0a:	d7 be       	out	0x37, r13	; 55
+   1fd0c:	e8 95       	spm
+   1fd0e:	11 24       	eor	r1, r1
+        addrPtr += 2;
+   1fd10:	4e 5f       	subi	r20, 0xFE	; 254
+   1fd12:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+   1fd14:	f3 e0       	ldi	r31, 0x03	; 3
+   1fd16:	a0 30       	cpi	r26, 0x00	; 0
+   1fd18:	bf 07       	cpc	r27, r31
+   1fd1a:	51 f7       	brne	.-44     	; 0x1fcf0 <main+0xf0>
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+   1fd1c:	e0 91 00 04 	lds	r30, 0x0400
+   1fd20:	f0 91 01 04 	lds	r31, 0x0401
+   1fd24:	e7 be       	out	0x37, r14	; 55
+   1fd26:	e8 95       	spm
+      boot_spm_busy_wait();
+   1fd28:	07 b6       	in	r0, 0x37	; 55
+   1fd2a:	00 fc       	sbrc	r0, 0
+   1fd2c:	fd cf       	rjmp	.-6      	; 0x1fd28 <main+0x128>
+
+#if defined(RWWSRE)
+      // Reenable read access to flash
+      boot_rww_enable();
+   1fd2e:	f7 be       	out	0x37, r15	; 55
+   1fd30:	e8 95       	spm
+   1fd32:	2a c0       	rjmp	.+84     	; 0x1fd88 <main+0x188>
+#endif
+
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+   1fd34:	84 37       	cpi	r24, 0x74	; 116
+   1fd36:	d1 f4       	brne	.+52     	; 0x1fd6c <main+0x16c>
+      // READ PAGE - we only read flash
+      getLen();
+   1fd38:	3a d0       	rcall	.+116    	; 0x1fdae <getLen>
+      verifySpace();
+   1fd3a:	49 d0       	rcall	.+146    	; 0x1fdce <verifySpace>
+#ifdef __AVR_ATmega1280__
+//      do putch(pgm_read_byte_near(address++));
+//      while (--length);
+      do {
+        uint8_t result;
+        __asm__ ("elpm %0,Z\n":"=r"(result):"z"(address));
+   1fd3c:	e0 91 00 04 	lds	r30, 0x0400
+   1fd40:	f0 91 01 04 	lds	r31, 0x0401
+   1fd44:	e6 91       	elpm	r30, Z+
+        putch(result);
+   1fd46:	8e 2f       	mov	r24, r30
+   1fd48:	22 d0       	rcall	.+68     	; 0x1fd8e <putch>
+        address++;
+   1fd4a:	80 91 00 04 	lds	r24, 0x0400
+   1fd4e:	90 91 01 04 	lds	r25, 0x0401
+   1fd52:	01 96       	adiw	r24, 0x01	; 1
+   1fd54:	90 93 01 04 	sts	0x0401, r25
+   1fd58:	80 93 00 04 	sts	0x0400, r24
+      }
+      while (--length);
+   1fd5c:	80 91 02 04 	lds	r24, 0x0402
+   1fd60:	81 50       	subi	r24, 0x01	; 1
+   1fd62:	80 93 02 04 	sts	0x0402, r24
+   1fd66:	88 23       	and	r24, r24
+   1fd68:	49 f7       	brne	.-46     	; 0x1fd3c <main+0x13c>
+   1fd6a:	0e c0       	rjmp	.+28     	; 0x1fd88 <main+0x188>
+#endif
+#endif
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+   1fd6c:	85 37       	cpi	r24, 0x75	; 117
+   1fd6e:	39 f4       	brne	.+14     	; 0x1fd7e <main+0x17e>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+   1fd70:	2e d0       	rcall	.+92     	; 0x1fdce <verifySpace>
+      putch(SIGNATURE_0);
+   1fd72:	8e e1       	ldi	r24, 0x1E	; 30
+   1fd74:	0c d0       	rcall	.+24     	; 0x1fd8e <putch>
+      putch(SIGNATURE_1);
+   1fd76:	87 e9       	ldi	r24, 0x97	; 151
+   1fd78:	0a d0       	rcall	.+20     	; 0x1fd8e <putch>
+      putch(SIGNATURE_2);
+   1fd7a:	83 e0       	ldi	r24, 0x03	; 3
+   1fd7c:	97 cf       	rjmp	.-210    	; 0x1fcac <main+0xac>
+    }
+    else if (ch == 'Q') {
+   1fd7e:	81 35       	cpi	r24, 0x51	; 81
+   1fd80:	11 f4       	brne	.+4      	; 0x1fd86 <main+0x186>
+      // Adaboot no-wait mod
+      watchdogConfig(WATCHDOG_16MS);
+   1fd82:	88 e0       	ldi	r24, 0x08	; 8
+   1fd84:	19 d0       	rcall	.+50     	; 0x1fdb8 <watchdogConfig>
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+   1fd86:	23 d0       	rcall	.+70     	; 0x1fdce <verifySpace>
+    }
+    putch(STK_OK);
+   1fd88:	80 e1       	ldi	r24, 0x10	; 16
+   1fd8a:	01 d0       	rcall	.+2      	; 0x1fd8e <putch>
+   1fd8c:	64 cf       	rjmp	.-312    	; 0x1fc56 <main+0x56>
+
+0001fd8e <putch>:
+  }
+}
+
+void putch(char ch) {
+   1fd8e:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
+  while (!(UCSR0A & _BV(UDRE0)));
+   1fd90:	80 91 c0 00 	lds	r24, 0x00C0
+   1fd94:	85 ff       	sbrs	r24, 5
+   1fd96:	fc cf       	rjmp	.-8      	; 0x1fd90 <putch+0x2>
+  UDR0 = ch;
+   1fd98:	90 93 c6 00 	sts	0x00C6, r25
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
+}
+   1fd9c:	08 95       	ret
+
+0001fd9e <getch>:
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+   1fd9e:	a8 95       	wdr
+      [uartBit] "I" (UART_RX_BIT)
+    :
+      "r25"
+);
+#else
+  while(!(UCSR0A & _BV(RXC0)));
+   1fda0:	80 91 c0 00 	lds	r24, 0x00C0
+   1fda4:	87 ff       	sbrs	r24, 7
+   1fda6:	fc cf       	rjmp	.-8      	; 0x1fda0 <getch+0x2>
+  ch = UDR0;
+   1fda8:	80 91 c6 00 	lds	r24, 0x00C6
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
+
+  return ch;
+}
+   1fdac:	08 95       	ret
+
+0001fdae <getLen>:
+  } while (--count);
+}
+#endif
+
+uint8_t getLen() {
+  getch();
+   1fdae:	f7 df       	rcall	.-18     	; 0x1fd9e <getch>
+  length = getch();
+   1fdb0:	f6 df       	rcall	.-20     	; 0x1fd9e <getch>
+   1fdb2:	80 93 02 04 	sts	0x0402, r24
+  return getch();
+}
+   1fdb6:	f3 cf       	rjmp	.-26     	; 0x1fd9e <getch>
+
+0001fdb8 <watchdogConfig>:
+    "wdr\n"
+  );
+}
+
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+   1fdb8:	e0 e6       	ldi	r30, 0x60	; 96
+   1fdba:	f0 e0       	ldi	r31, 0x00	; 0
+   1fdbc:	98 e1       	ldi	r25, 0x18	; 24
+   1fdbe:	90 83       	st	Z, r25
+  WDTCSR = x;
+   1fdc0:	80 83       	st	Z, r24
+}
+   1fdc2:	08 95       	ret
+
+0001fdc4 <appStart>:
+
+void appStart() {
+  watchdogConfig(WATCHDOG_OFF);
+   1fdc4:	80 e0       	ldi	r24, 0x00	; 0
+   1fdc6:	f8 df       	rcall	.-16     	; 0x1fdb8 <watchdogConfig>
+  __asm__ __volatile__ (
+   1fdc8:	ee 27       	eor	r30, r30
+   1fdca:	ff 27       	eor	r31, r31
+   1fdcc:	09 94       	ijmp
+
+0001fdce <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+   1fdce:	e7 df       	rcall	.-50     	; 0x1fd9e <getch>
+   1fdd0:	80 32       	cpi	r24, 0x20	; 32
+   1fdd2:	09 f0       	breq	.+2      	; 0x1fdd6 <verifySpace+0x8>
+   1fdd4:	f7 df       	rcall	.-18     	; 0x1fdc4 <appStart>
+  putch(STK_INSYNC);
+   1fdd6:	84 e1       	ldi	r24, 0x14	; 20
+}
+   1fdd8:	da cf       	rjmp	.-76     	; 0x1fd8e <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
+}
+#endif
+
+void getNch(uint8_t count) {
+   1fdda:	1f 93       	push	r17
+   1fddc:	18 2f       	mov	r17, r24
+
+0001fdde <getNch>:
+  do getch(); while (--count);
+   1fdde:	df df       	rcall	.-66     	; 0x1fd9e <getch>
+   1fde0:	11 50       	subi	r17, 0x01	; 1
+   1fde2:	e9 f7       	brne	.-6      	; 0x1fdde <getNch>
+  verifySpace();
+   1fde4:	f4 df       	rcall	.-24     	; 0x1fdce <verifySpace>
+}
+   1fde6:	1f 91       	pop	r17
+   1fde8:	08 95       	ret

+ 32 - 0
optiboot/bootloaders/optiboot/optiboot_atmega644p.hex

@@ -0,0 +1,32 @@
+:10FC000085E08093810082E08093C00088E180934A
+:10FC1000C10086E08093C20080E18093C40084B775
+:10FC200014BE81FFC8D08DE0C0D0209A86E020E3CA
+:10FC30003CEF91E0309385002093840096BBB09B0D
+:10FC4000FECF189AA8958150A9F7DD24D394A5E09A
+:10FC5000FA2EF1E1EF2E9CD0813421F481E0B6D070
+:10FC600083E020C0823411F484E103C0853419F4A8
+:10FC700085E0ACD082C0853581F48AD0082F10E0B1
+:10FC800087D090E0982F8827802B912B880F991F81
+:10FC900090930103809300036FC0863529F484E0BC
+:10FCA00095D080E06DD069C0843609F03FC078D02F
+:10FCB000E0910003F091010383E087BFE895C0E085
+:10FCC000D1E066D089938091020381508093020332
+:10FCD0008823B9F775D007B600FCFDCF409100032B
+:10FCE00050910103A0E0B1E02C9130E011968C918D
+:10FCF000119790E0982F8827822B932B1296FA0168
+:10FD00000C01D7BEE89511244E5F5F4FF2E0A030A2
+:10FD1000BF0751F7E0910003F0910103F7BEE895AA
+:10FD200007B600FCFDCFE7BEE89527C08437B9F4DD
+:10FD300037D046D0E0910003F09101033196F09363
+:10FD40000103E09300033197E4918E2F19D0809145
+:10FD50000203815080930203882361F70EC0853728
+:10FD600039F42ED08EE10CD086E90AD08AE09ACF01
+:10FD7000813511F488E019D023D080E101D06BCF18
+:10FD8000982F8091C00085FFFCCF9093C600089506
+:10FD9000A8958091C00087FFFCCF8091C600089590
+:10FDA000F7DFF6DF80930203F3CFE0E6F0E098E1BF
+:10FDB00090838083089580E0F8DFEE27FF27099481
+:10FDC000E7DF803209F0F7DF84E1DACF1F93182FE5
+:0CFDD000DFDF1150E9F7F4DF1F91089508
+:040000030000FC00FD
+:00000001FF

+ 525 - 0
optiboot/bootloaders/optiboot/optiboot_atmega644p.lst

@@ -0,0 +1,525 @@
+
+optiboot_atmega644p.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         000001dc  0000fc00  0000fc00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  00000230  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 0000006a  00000000  00000000  00000258  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   00000283  00000000  00000000  000002c2  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 000001ae  00000000  00000000  00000545  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   000003db  00000000  00000000  000006f3  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  00000090  00000000  00000000  00000ad0  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    00000140  00000000  00000000  00000b60  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    000001d1  00000000  00000000  00000ca0  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000068  00000000  00000000  00000e71  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+0000fc00 <main>:
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+    fc00:	85 e0       	ldi	r24, 0x05	; 5
+    fc02:	80 93 81 00 	sts	0x0081, r24
+#if LED_START_FLASHES > 0
+  // Set up Timer 1 for timeout counter
+  TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
+#endif
+#ifndef SOFT_UART
+  UCSR0A = _BV(U2X0); //Double speed mode USART0
+    fc06:	82 e0       	ldi	r24, 0x02	; 2
+    fc08:	80 93 c0 00 	sts	0x00C0, r24
+  UCSR0B = _BV(RXEN0) | _BV(TXEN0);
+    fc0c:	88 e1       	ldi	r24, 0x18	; 24
+    fc0e:	80 93 c1 00 	sts	0x00C1, r24
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+    fc12:	86 e0       	ldi	r24, 0x06	; 6
+    fc14:	80 93 c2 00 	sts	0x00C2, r24
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+    fc18:	80 e1       	ldi	r24, 0x10	; 16
+    fc1a:	80 93 c4 00 	sts	0x00C4, r24
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    fc1e:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    fc20:	14 be       	out	0x34, r1	; 52
+  if (!(ch & _BV(EXTRF))) appStart();
+    fc22:	81 ff       	sbrs	r24, 1
+    fc24:	c8 d0       	rcall	.+400    	; 0xfdb6 <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(WATCHDOG_500MS);
+    fc26:	8d e0       	ldi	r24, 0x0D	; 13
+    fc28:	c0 d0       	rcall	.+384    	; 0xfdaa <watchdogConfig>
+
+  /* Set LED pin as output */
+  LED_DDR |= _BV(LED);
+    fc2a:	20 9a       	sbi	0x04, 0	; 4
+    fc2c:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    fc2e:	20 e3       	ldi	r18, 0x30	; 48
+    fc30:	3c ef       	ldi	r19, 0xFC	; 252
+    TIFR1 = _BV(TOV1);
+    fc32:	91 e0       	ldi	r25, 0x01	; 1
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    fc34:	30 93 85 00 	sts	0x0085, r19
+    fc38:	20 93 84 00 	sts	0x0084, r18
+    TIFR1 = _BV(TOV1);
+    fc3c:	96 bb       	out	0x16, r25	; 22
+    while(!(TIFR1 & _BV(TOV1)));
+    fc3e:	b0 9b       	sbis	0x16, 0	; 22
+    fc40:	fe cf       	rjmp	.-4      	; 0xfc3e <main+0x3e>
+    LED_PIN |= _BV(LED);
+    fc42:	18 9a       	sbi	0x03, 0	; 3
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    fc44:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
+    while(!(TIFR1 & _BV(TOV1)));
+    LED_PIN |= _BV(LED);
+    watchdogReset();
+  } while (--count);
+    fc46:	81 50       	subi	r24, 0x01	; 1
+    fc48:	a9 f7       	brne	.-22     	; 0xfc34 <main+0x34>
+    /* 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);
+    fc4a:	dd 24       	eor	r13, r13
+    fc4c:	d3 94       	inc	r13
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+    fc4e:	a5 e0       	ldi	r26, 0x05	; 5
+    fc50:	fa 2e       	mov	r15, r26
+      boot_spm_busy_wait();
+
+#if defined(RWWSRE)
+      // Reenable read access to flash
+      boot_rww_enable();
+    fc52:	f1 e1       	ldi	r31, 0x11	; 17
+    fc54:	ef 2e       	mov	r14, r31
+#endif
+
+  /* Forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    fc56:	9c d0       	rcall	.+312    	; 0xfd90 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    fc58:	81 34       	cpi	r24, 0x41	; 65
+    fc5a:	21 f4       	brne	.+8      	; 0xfc64 <main+0x64>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    fc5c:	81 e0       	ldi	r24, 0x01	; 1
+    fc5e:	b6 d0       	rcall	.+364    	; 0xfdcc <verifySpace+0xc>
+      putch(0x03);
+    fc60:	83 e0       	ldi	r24, 0x03	; 3
+    fc62:	20 c0       	rjmp	.+64     	; 0xfca4 <main+0xa4>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    fc64:	82 34       	cpi	r24, 0x42	; 66
+    fc66:	11 f4       	brne	.+4      	; 0xfc6c <main+0x6c>
+      // SET DEVICE is ignored
+      getNch(20);
+    fc68:	84 e1       	ldi	r24, 0x14	; 20
+    fc6a:	03 c0       	rjmp	.+6      	; 0xfc72 <main+0x72>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    fc6c:	85 34       	cpi	r24, 0x45	; 69
+    fc6e:	19 f4       	brne	.+6      	; 0xfc76 <main+0x76>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    fc70:	85 e0       	ldi	r24, 0x05	; 5
+    fc72:	ac d0       	rcall	.+344    	; 0xfdcc <verifySpace+0xc>
+    fc74:	82 c0       	rjmp	.+260    	; 0xfd7a <main+0x17a>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    fc76:	85 35       	cpi	r24, 0x55	; 85
+    fc78:	81 f4       	brne	.+32     	; 0xfc9a <main+0x9a>
+      // LOAD ADDRESS
+      uint16_t newAddress;
+      newAddress = getch();
+    fc7a:	8a d0       	rcall	.+276    	; 0xfd90 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
+    fc7c:	08 2f       	mov	r16, r24
+    fc7e:	10 e0       	ldi	r17, 0x00	; 0
+    fc80:	87 d0       	rcall	.+270    	; 0xfd90 <getch>
+    fc82:	90 e0       	ldi	r25, 0x00	; 0
+    fc84:	98 2f       	mov	r25, r24
+    fc86:	88 27       	eor	r24, r24
+    fc88:	80 2b       	or	r24, r16
+    fc8a:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    fc8c:	88 0f       	add	r24, r24
+    fc8e:	99 1f       	adc	r25, r25
+      address = newAddress;
+    fc90:	90 93 01 03 	sts	0x0301, r25
+    fc94:	80 93 00 03 	sts	0x0300, r24
+    fc98:	6f c0       	rjmp	.+222    	; 0xfd78 <main+0x178>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    fc9a:	86 35       	cpi	r24, 0x56	; 86
+    fc9c:	29 f4       	brne	.+10     	; 0xfca8 <main+0xa8>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    fc9e:	84 e0       	ldi	r24, 0x04	; 4
+    fca0:	95 d0       	rcall	.+298    	; 0xfdcc <verifySpace+0xc>
+      putch(0x00);
+    fca2:	80 e0       	ldi	r24, 0x00	; 0
+    fca4:	6d d0       	rcall	.+218    	; 0xfd80 <putch>
+    fca6:	69 c0       	rjmp	.+210    	; 0xfd7a <main+0x17a>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    fca8:	84 36       	cpi	r24, 0x64	; 100
+    fcaa:	09 f0       	breq	.+2      	; 0xfcae <main+0xae>
+    fcac:	3f c0       	rjmp	.+126    	; 0xfd2c <main+0x12c>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+
+      getLen();
+    fcae:	78 d0       	rcall	.+240    	; 0xfda0 <getLen>
+
+      // Immediately start page erase - this will 4.5ms
+      __boot_page_erase_short((uint16_t)(void*)address);
+    fcb0:	e0 91 00 03 	lds	r30, 0x0300
+    fcb4:	f0 91 01 03 	lds	r31, 0x0301
+    fcb8:	83 e0       	ldi	r24, 0x03	; 3
+    fcba:	87 bf       	out	0x37, r24	; 55
+    fcbc:	e8 95       	spm
+    fcbe:	c0 e0       	ldi	r28, 0x00	; 0
+    fcc0:	d1 e0       	ldi	r29, 0x01	; 1
+      
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    fcc2:	66 d0       	rcall	.+204    	; 0xfd90 <getch>
+    fcc4:	89 93       	st	Y+, r24
+      while (--length);
+    fcc6:	80 91 02 03 	lds	r24, 0x0302
+    fcca:	81 50       	subi	r24, 0x01	; 1
+    fccc:	80 93 02 03 	sts	0x0302, r24
+    fcd0:	88 23       	and	r24, r24
+    fcd2:	b9 f7       	brne	.-18     	; 0xfcc2 <main+0xc2>
+
+      // Read command terminator, start reply
+      verifySpace();
+    fcd4:	75 d0       	rcall	.+234    	; 0xfdc0 <verifySpace>
+      
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    fcd6:	07 b6       	in	r0, 0x37	; 55
+    fcd8:	00 fc       	sbrc	r0, 0
+    fcda:	fd cf       	rjmp	.-6      	; 0xfcd6 <main+0xd6>
+      }
+#endif
+
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    fcdc:	40 91 00 03 	lds	r20, 0x0300
+    fce0:	50 91 01 03 	lds	r21, 0x0301
+    fce4:	a0 e0       	ldi	r26, 0x00	; 0
+    fce6:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    fce8:	2c 91       	ld	r18, X
+    fcea:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    fcec:	11 96       	adiw	r26, 0x01	; 1
+    fcee:	8c 91       	ld	r24, X
+    fcf0:	11 97       	sbiw	r26, 0x01	; 1
+    fcf2:	90 e0       	ldi	r25, 0x00	; 0
+    fcf4:	98 2f       	mov	r25, r24
+    fcf6:	88 27       	eor	r24, r24
+    fcf8:	82 2b       	or	r24, r18
+    fcfa:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+    fcfc:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    fcfe:	fa 01       	movw	r30, r20
+    fd00:	0c 01       	movw	r0, r24
+    fd02:	d7 be       	out	0x37, r13	; 55
+    fd04:	e8 95       	spm
+    fd06:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    fd08:	4e 5f       	subi	r20, 0xFE	; 254
+    fd0a:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    fd0c:	f2 e0       	ldi	r31, 0x02	; 2
+    fd0e:	a0 30       	cpi	r26, 0x00	; 0
+    fd10:	bf 07       	cpc	r27, r31
+    fd12:	51 f7       	brne	.-44     	; 0xfce8 <main+0xe8>
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+    fd14:	e0 91 00 03 	lds	r30, 0x0300
+    fd18:	f0 91 01 03 	lds	r31, 0x0301
+    fd1c:	f7 be       	out	0x37, r15	; 55
+    fd1e:	e8 95       	spm
+      boot_spm_busy_wait();
+    fd20:	07 b6       	in	r0, 0x37	; 55
+    fd22:	00 fc       	sbrc	r0, 0
+    fd24:	fd cf       	rjmp	.-6      	; 0xfd20 <main+0x120>
+
+#if defined(RWWSRE)
+      // Reenable read access to flash
+      boot_rww_enable();
+    fd26:	e7 be       	out	0x37, r14	; 55
+    fd28:	e8 95       	spm
+    fd2a:	27 c0       	rjmp	.+78     	; 0xfd7a <main+0x17a>
+#endif
+
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    fd2c:	84 37       	cpi	r24, 0x74	; 116
+    fd2e:	b9 f4       	brne	.+46     	; 0xfd5e <main+0x15e>
+      // READ PAGE - we only read flash
+      getLen();
+    fd30:	37 d0       	rcall	.+110    	; 0xfda0 <getLen>
+      verifySpace();
+    fd32:	46 d0       	rcall	.+140    	; 0xfdc0 <verifySpace>
+        putch(result);
+        address++;
+      }
+      while (--length);
+#else
+      do putch(pgm_read_byte_near(address++));
+    fd34:	e0 91 00 03 	lds	r30, 0x0300
+    fd38:	f0 91 01 03 	lds	r31, 0x0301
+    fd3c:	31 96       	adiw	r30, 0x01	; 1
+    fd3e:	f0 93 01 03 	sts	0x0301, r31
+    fd42:	e0 93 00 03 	sts	0x0300, r30
+    fd46:	31 97       	sbiw	r30, 0x01	; 1
+    fd48:	e4 91       	lpm	r30, Z+
+    fd4a:	8e 2f       	mov	r24, r30
+    fd4c:	19 d0       	rcall	.+50     	; 0xfd80 <putch>
+      while (--length);
+    fd4e:	80 91 02 03 	lds	r24, 0x0302
+    fd52:	81 50       	subi	r24, 0x01	; 1
+    fd54:	80 93 02 03 	sts	0x0302, r24
+    fd58:	88 23       	and	r24, r24
+    fd5a:	61 f7       	brne	.-40     	; 0xfd34 <main+0x134>
+    fd5c:	0e c0       	rjmp	.+28     	; 0xfd7a <main+0x17a>
+#endif
+#endif
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    fd5e:	85 37       	cpi	r24, 0x75	; 117
+    fd60:	39 f4       	brne	.+14     	; 0xfd70 <main+0x170>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    fd62:	2e d0       	rcall	.+92     	; 0xfdc0 <verifySpace>
+      putch(SIGNATURE_0);
+    fd64:	8e e1       	ldi	r24, 0x1E	; 30
+    fd66:	0c d0       	rcall	.+24     	; 0xfd80 <putch>
+      putch(SIGNATURE_1);
+    fd68:	86 e9       	ldi	r24, 0x96	; 150
+    fd6a:	0a d0       	rcall	.+20     	; 0xfd80 <putch>
+      putch(SIGNATURE_2);
+    fd6c:	8a e0       	ldi	r24, 0x0A	; 10
+    fd6e:	9a cf       	rjmp	.-204    	; 0xfca4 <main+0xa4>
+    }
+    else if (ch == 'Q') {
+    fd70:	81 35       	cpi	r24, 0x51	; 81
+    fd72:	11 f4       	brne	.+4      	; 0xfd78 <main+0x178>
+      // Adaboot no-wait mod
+      watchdogConfig(WATCHDOG_16MS);
+    fd74:	88 e0       	ldi	r24, 0x08	; 8
+    fd76:	19 d0       	rcall	.+50     	; 0xfdaa <watchdogConfig>
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    fd78:	23 d0       	rcall	.+70     	; 0xfdc0 <verifySpace>
+    }
+    putch(STK_OK);
+    fd7a:	80 e1       	ldi	r24, 0x10	; 16
+    fd7c:	01 d0       	rcall	.+2      	; 0xfd80 <putch>
+    fd7e:	6b cf       	rjmp	.-298    	; 0xfc56 <main+0x56>
+
+0000fd80 <putch>:
+  }
+}
+
+void putch(char ch) {
+    fd80:	98 2f       	mov	r25, r24
+#ifndef SOFT_UART
+  while (!(UCSR0A & _BV(UDRE0)));
+    fd82:	80 91 c0 00 	lds	r24, 0x00C0
+    fd86:	85 ff       	sbrs	r24, 5
+    fd88:	fc cf       	rjmp	.-8      	; 0xfd82 <putch+0x2>
+  UDR0 = ch;
+    fd8a:	90 93 c6 00 	sts	0x00C6, r25
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
+}
+    fd8e:	08 95       	ret
+
+0000fd90 <getch>:
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    fd90:	a8 95       	wdr
+      [uartBit] "I" (UART_RX_BIT)
+    :
+      "r25"
+);
+#else
+  while(!(UCSR0A & _BV(RXC0)));
+    fd92:	80 91 c0 00 	lds	r24, 0x00C0
+    fd96:	87 ff       	sbrs	r24, 7
+    fd98:	fc cf       	rjmp	.-8      	; 0xfd92 <getch+0x2>
+  ch = UDR0;
+    fd9a:	80 91 c6 00 	lds	r24, 0x00C6
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
+
+  return ch;
+}
+    fd9e:	08 95       	ret
+
+0000fda0 <getLen>:
+  } while (--count);
+}
+#endif
+
+uint8_t getLen() {
+  getch();
+    fda0:	f7 df       	rcall	.-18     	; 0xfd90 <getch>
+  length = getch();
+    fda2:	f6 df       	rcall	.-20     	; 0xfd90 <getch>
+    fda4:	80 93 02 03 	sts	0x0302, r24
+  return getch();
+}
+    fda8:	f3 cf       	rjmp	.-26     	; 0xfd90 <getch>
+
+0000fdaa <watchdogConfig>:
+    "wdr\n"
+  );
+}
+
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    fdaa:	e0 e6       	ldi	r30, 0x60	; 96
+    fdac:	f0 e0       	ldi	r31, 0x00	; 0
+    fdae:	98 e1       	ldi	r25, 0x18	; 24
+    fdb0:	90 83       	st	Z, r25
+  WDTCSR = x;
+    fdb2:	80 83       	st	Z, r24
+}
+    fdb4:	08 95       	ret
+
+0000fdb6 <appStart>:
+
+void appStart() {
+  watchdogConfig(WATCHDOG_OFF);
+    fdb6:	80 e0       	ldi	r24, 0x00	; 0
+    fdb8:	f8 df       	rcall	.-16     	; 0xfdaa <watchdogConfig>
+  __asm__ __volatile__ (
+    fdba:	ee 27       	eor	r30, r30
+    fdbc:	ff 27       	eor	r31, r31
+    fdbe:	09 94       	ijmp
+
+0000fdc0 <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    fdc0:	e7 df       	rcall	.-50     	; 0xfd90 <getch>
+    fdc2:	80 32       	cpi	r24, 0x20	; 32
+    fdc4:	09 f0       	breq	.+2      	; 0xfdc8 <verifySpace+0x8>
+    fdc6:	f7 df       	rcall	.-18     	; 0xfdb6 <appStart>
+  putch(STK_INSYNC);
+    fdc8:	84 e1       	ldi	r24, 0x14	; 20
+}
+    fdca:	da cf       	rjmp	.-76     	; 0xfd80 <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
+}
+#endif
+
+void getNch(uint8_t count) {
+    fdcc:	1f 93       	push	r17
+    fdce:	18 2f       	mov	r17, r24
+
+0000fdd0 <getNch>:
+  do getch(); while (--count);
+    fdd0:	df df       	rcall	.-66     	; 0xfd90 <getch>
+    fdd2:	11 50       	subi	r17, 0x01	; 1
+    fdd4:	e9 f7       	brne	.-6      	; 0xfdd0 <getNch>
+  verifySpace();
+    fdd6:	f4 df       	rcall	.-24     	; 0xfdc0 <verifySpace>
+}
+    fdd8:	1f 91       	pop	r17
+    fdda:	08 95       	ret

+ 42 - 0
optiboot/bootloaders/optiboot/optiboot_luminet.hex

@@ -0,0 +1,42 @@
+:101D000085E08EBD84B714BE81FF20D18DE01AD14D
+:101D1000D49AD29A86E023EC3FEF91E03DBD2CBDF2
+:101D20009BB9589BFECFCC9AA8958150B9F7DD247A
+:101D3000D39485E0C82E0FE7F02E1EECE12EE9D0FB
+:101D4000813421F481E00DD183E020C0823411F48C
+:101D500084E103C0853419F485E003D1C8C085351A
+:101D600081F4D7D0082F10E0D4D090E0982F8827A6
+:101D7000802B912B880F991F909381018093800174
+:101D8000B5C0863529F484E0ECD080E0B3D0AFC094
+:101D9000843609F06BC0D1D0E0918001F0918101CF
+:101DA00083E087BFE895C0E0D1E0B3D0899380910C
+:101DB00082018150809382018823B9F7CCD007B685
+:101DC00000FCFDCF8091800190918101892B41F52C
+:101DD000809100012091010130E0322F222790E014
+:101DE000282B392B309385012093840140910801E1
+:101DF0008091090190E0982F882750E0842B952B43
+:101E000090938701809386012450304020930801ED
+:101E1000232F332720930901F0920001E092010162
+:101E20004091800150918101A0E0B1E02C9130E01F
+:101E300011968C91119790E0982F8827822B932BE5
+:101E40001296FA010C01D7BEE89511244E5F5F4F40
+:101E5000F1E0A034BF0751F7E0918001F0918101DA
+:101E6000C7BEE89507B600FCFDCF41C0843789F5B1
+:101E700064D071D0E0918001F0918101309719F424
+:101E80002091840113C0E130F10519F420918501FE
+:101E90000DC0E830F10519F42091860107C0E93042
+:101EA000F10519F42091870101C0249180918001EE
+:101EB0009091810101969093810180938001822FFE
+:101EC00019D080918201815080938201882391F6FC
+:101ED0000EC0853739F43FD08EE10CD083E90AD0AB
+:101EE0008CE054CF813511F488E02CD034D080E1DF
+:101EF00001D025CF2AE030E08095089410F4DA98DC
+:101F000002C0DA9A000015D014D086952A95B1F750
+:101F10000895A89529E030E0CB99FECF0AD009D0EA
+:101F200008D08894CB9908942A9511F08795F7CF1B
+:101F300008959EE09A95F1F70895EBDFEADF80932C
+:101F40008201E7CF98E191BD81BD089580E0FADF7D
+:101F5000E4E0FF270994DDDF803209F0F7DF84E158
+:101F6000C9CF1F93182FD5DF1150E9F7F4DF1F9168
+:021F70000895D2
+:0400000300001D00DC
+:00000001FF

+ 608 - 0
optiboot/bootloaders/optiboot/optiboot_luminet.lst

@@ -0,0 +1,608 @@
+
+optiboot_luminet.elf:     file format elf32-avr
+
+Sections:
+Idx Name          Size      VMA       LMA       File off  Algn
+  0 .text         00000272  00001d00  00001d00  00000054  2**1
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
+  1 .debug_aranges 00000028  00000000  00000000  000002c6  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  2 .debug_pubnames 00000078  00000000  00000000  000002ee  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  3 .debug_info   000002a3  00000000  00000000  00000366  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  4 .debug_abbrev 000001ac  00000000  00000000  00000609  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  5 .debug_line   0000043d  00000000  00000000  000007b5  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  6 .debug_frame  000000a0  00000000  00000000  00000bf4  2**2
+                  CONTENTS, READONLY, DEBUGGING
+  7 .debug_str    0000014f  00000000  00000000  00000c94  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  8 .debug_loc    00000194  00000000  00000000  00000de3  2**0
+                  CONTENTS, READONLY, DEBUGGING
+  9 .debug_ranges 00000088  00000000  00000000  00000f77  2**0
+                  CONTENTS, READONLY, DEBUGGING
+
+Disassembly of section .text:
+
+00001d00 <main>:
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+    1d00:	85 e0       	ldi	r24, 0x05	; 5
+    1d02:	8e bd       	out	0x2e, r24	; 46
+  UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
+  UBRR0L = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
+#endif
+
+  // Adaboot no-wait mod
+  ch = MCUSR;
+    1d04:	84 b7       	in	r24, 0x34	; 52
+  MCUSR = 0;
+    1d06:	14 be       	out	0x34, r1	; 52
+  if (!(ch & _BV(EXTRF))) appStart();
+    1d08:	81 ff       	sbrs	r24, 1
+    1d0a:	20 d1       	rcall	.+576    	; 0x1f4c <appStart>
+
+  // Set up watchdog to trigger after 500ms
+  watchdogConfig(WATCHDOG_500MS);
+    1d0c:	8d e0       	ldi	r24, 0x0D	; 13
+    1d0e:	1a d1       	rcall	.+564    	; 0x1f44 <watchdogConfig>
+
+  /* Set LED pin as output */
+  LED_DDR |= _BV(LED);
+    1d10:	d4 9a       	sbi	0x1a, 4	; 26
+
+#ifdef SOFT_UART
+  /* Set TX pin as output */
+  UART_DDR |= _BV(UART_TX_BIT);
+    1d12:	d2 9a       	sbi	0x1a, 2	; 26
+    1d14:	86 e0       	ldi	r24, 0x06	; 6
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    1d16:	23 ec       	ldi	r18, 0xC3	; 195
+    1d18:	3f ef       	ldi	r19, 0xFF	; 255
+    TIFR1 = _BV(TOV1);
+    1d1a:	91 e0       	ldi	r25, 0x01	; 1
+}
+
+#if LED_START_FLASHES > 0
+void flash_led(uint8_t count) {
+  do {
+    TCNT1 = -(F_CPU/(1024*16));
+    1d1c:	3d bd       	out	0x2d, r19	; 45
+    1d1e:	2c bd       	out	0x2c, r18	; 44
+    TIFR1 = _BV(TOV1);
+    1d20:	9b b9       	out	0x0b, r25	; 11
+    while(!(TIFR1 & _BV(TOV1)));
+    1d22:	58 9b       	sbis	0x0b, 0	; 11
+    1d24:	fe cf       	rjmp	.-4      	; 0x1d22 <main+0x22>
+    LED_PIN |= _BV(LED);
+    1d26:	cc 9a       	sbi	0x19, 4	; 25
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    1d28:	a8 95       	wdr
+    TCNT1 = -(F_CPU/(1024*16));
+    TIFR1 = _BV(TOV1);
+    while(!(TIFR1 & _BV(TOV1)));
+    LED_PIN |= _BV(LED);
+    watchdogReset();
+  } while (--count);
+    1d2a:	81 50       	subi	r24, 0x01	; 1
+    1d2c:	b9 f7       	brne	.-18     	; 0x1d1c <main+0x1c>
+    /* 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);
+    1d2e:	dd 24       	eor	r13, r13
+    1d30:	d3 94       	inc	r13
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+        addrPtr += 2;
+      } while (--ch);
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+    1d32:	85 e0       	ldi	r24, 0x05	; 5
+    1d34:	c8 2e       	mov	r12, r24
+        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
+        buff[8] = vect & 0xff;
+        buff[9] = vect >> 8;
+
+        // Add jump to bootloader at RESET vector
+        buff[0] = 0x7f;
+    1d36:	0f e7       	ldi	r16, 0x7F	; 127
+    1d38:	f0 2e       	mov	r15, r16
+        buff[1] = 0xce; // rjmp 0x1d00 instruction
+    1d3a:	1e ec       	ldi	r17, 0xCE	; 206
+    1d3c:	e1 2e       	mov	r14, r17
+#endif
+
+  /* Forever loop */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+    1d3e:	e9 d0       	rcall	.+466    	; 0x1f12 <getch>
+
+    if(ch == STK_GET_PARAMETER) {
+    1d40:	81 34       	cpi	r24, 0x41	; 65
+    1d42:	21 f4       	brne	.+8      	; 0x1d4c <main+0x4c>
+      // GET PARAMETER returns a generic 0x03 reply - enough to keep Avrdude happy
+      getNch(1);
+    1d44:	81 e0       	ldi	r24, 0x01	; 1
+    1d46:	0d d1       	rcall	.+538    	; 0x1f62 <verifySpace+0xc>
+      putch(0x03);
+    1d48:	83 e0       	ldi	r24, 0x03	; 3
+    1d4a:	20 c0       	rjmp	.+64     	; 0x1d8c <main+0x8c>
+    }
+    else if(ch == STK_SET_DEVICE) {
+    1d4c:	82 34       	cpi	r24, 0x42	; 66
+    1d4e:	11 f4       	brne	.+4      	; 0x1d54 <main+0x54>
+      // SET DEVICE is ignored
+      getNch(20);
+    1d50:	84 e1       	ldi	r24, 0x14	; 20
+    1d52:	03 c0       	rjmp	.+6      	; 0x1d5a <main+0x5a>
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+    1d54:	85 34       	cpi	r24, 0x45	; 69
+    1d56:	19 f4       	brne	.+6      	; 0x1d5e <main+0x5e>
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    1d58:	85 e0       	ldi	r24, 0x05	; 5
+    1d5a:	03 d1       	rcall	.+518    	; 0x1f62 <verifySpace+0xc>
+    1d5c:	c8 c0       	rjmp	.+400    	; 0x1eee <main+0x1ee>
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+    1d5e:	85 35       	cpi	r24, 0x55	; 85
+    1d60:	81 f4       	brne	.+32     	; 0x1d82 <main+0x82>
+      // LOAD ADDRESS
+      uint16_t newAddress;
+      newAddress = getch();
+    1d62:	d7 d0       	rcall	.+430    	; 0x1f12 <getch>
+      newAddress = (newAddress & 0xff) | (getch() << 8);
+    1d64:	08 2f       	mov	r16, r24
+    1d66:	10 e0       	ldi	r17, 0x00	; 0
+    1d68:	d4 d0       	rcall	.+424    	; 0x1f12 <getch>
+    1d6a:	90 e0       	ldi	r25, 0x00	; 0
+    1d6c:	98 2f       	mov	r25, r24
+    1d6e:	88 27       	eor	r24, r24
+    1d70:	80 2b       	or	r24, r16
+    1d72:	91 2b       	or	r25, r17
+#ifdef RAMPZ
+      // Transfer top bit to RAMPZ
+      RAMPZ = (newAddress & 0x8000) ? 1 : 0;
+#endif
+      newAddress += newAddress; // Convert from word address to byte address
+    1d74:	88 0f       	add	r24, r24
+    1d76:	99 1f       	adc	r25, r25
+      address = newAddress;
+    1d78:	90 93 81 01 	sts	0x0181, r25
+    1d7c:	80 93 80 01 	sts	0x0180, r24
+    1d80:	b5 c0       	rjmp	.+362    	; 0x1eec <main+0x1ec>
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+    1d82:	86 35       	cpi	r24, 0x56	; 86
+    1d84:	29 f4       	brne	.+10     	; 0x1d90 <main+0x90>
+      // UNIVERSAL command is ignored
+      getNch(4);
+    1d86:	84 e0       	ldi	r24, 0x04	; 4
+    1d88:	ec d0       	rcall	.+472    	; 0x1f62 <verifySpace+0xc>
+      putch(0x00);
+    1d8a:	80 e0       	ldi	r24, 0x00	; 0
+    1d8c:	b3 d0       	rcall	.+358    	; 0x1ef4 <putch>
+    1d8e:	af c0       	rjmp	.+350    	; 0x1eee <main+0x1ee>
+    }
+    /* Write memory, length is big endian and is in bytes  */
+    else if(ch == STK_PROG_PAGE) {
+    1d90:	84 36       	cpi	r24, 0x64	; 100
+    1d92:	09 f0       	breq	.+2      	; 0x1d96 <main+0x96>
+    1d94:	6b c0       	rjmp	.+214    	; 0x1e6c <main+0x16c>
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t *bufPtr;
+      uint16_t addrPtr;
+
+      getLen();
+    1d96:	d1 d0       	rcall	.+418    	; 0x1f3a <getLen>
+
+      // Immediately start page erase - this will 4.5ms
+      __boot_page_erase_short((uint16_t)(void*)address);
+    1d98:	e0 91 80 01 	lds	r30, 0x0180
+    1d9c:	f0 91 81 01 	lds	r31, 0x0181
+    1da0:	83 e0       	ldi	r24, 0x03	; 3
+    1da2:	87 bf       	out	0x37, r24	; 55
+    1da4:	e8 95       	spm
+    1da6:	c0 e0       	ldi	r28, 0x00	; 0
+    1da8:	d1 e0       	ldi	r29, 0x01	; 1
+      
+      // While that is going on, read in page contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+    1daa:	b3 d0       	rcall	.+358    	; 0x1f12 <getch>
+    1dac:	89 93       	st	Y+, r24
+      while (--length);
+    1dae:	80 91 82 01 	lds	r24, 0x0182
+    1db2:	81 50       	subi	r24, 0x01	; 1
+    1db4:	80 93 82 01 	sts	0x0182, r24
+    1db8:	88 23       	and	r24, r24
+    1dba:	b9 f7       	brne	.-18     	; 0x1daa <main+0xaa>
+
+      // Read command terminator, start reply
+      verifySpace();
+    1dbc:	cc d0       	rcall	.+408    	; 0x1f56 <verifySpace>
+      
+      // If only a partial page is to be programmed, the erase might not be complete.
+      // So check that here
+      boot_spm_busy_wait();
+    1dbe:	07 b6       	in	r0, 0x37	; 55
+    1dc0:	00 fc       	sbrc	r0, 0
+    1dc2:	fd cf       	rjmp	.-6      	; 0x1dbe <main+0xbe>
+
+#ifdef VIRTUAL_BOOT_PARTITION
+      if ((uint16_t)(void*)address == 0) {
+    1dc4:	80 91 80 01 	lds	r24, 0x0180
+    1dc8:	90 91 81 01 	lds	r25, 0x0181
+    1dcc:	89 2b       	or	r24, r25
+    1dce:	41 f5       	brne	.+80     	; 0x1e20 <main+0x120>
+        // This is the reset vector page. We need to live-patch the code so the
+        // bootloader runs.
+        //
+        // Move RESET vector to WDT vector
+        uint16_t vect = buff[0] | (buff[1]<<8);
+    1dd0:	80 91 00 01 	lds	r24, 0x0100
+    1dd4:	20 91 01 01 	lds	r18, 0x0101
+    1dd8:	30 e0       	ldi	r19, 0x00	; 0
+    1dda:	32 2f       	mov	r19, r18
+    1ddc:	22 27       	eor	r18, r18
+    1dde:	90 e0       	ldi	r25, 0x00	; 0
+    1de0:	28 2b       	or	r18, r24
+    1de2:	39 2b       	or	r19, r25
+        rstVect = vect;
+    1de4:	30 93 85 01 	sts	0x0185, r19
+    1de8:	20 93 84 01 	sts	0x0184, r18
+        wdtVect = buff[8] | (buff[9]<<8);
+    1dec:	40 91 08 01 	lds	r20, 0x0108
+    1df0:	80 91 09 01 	lds	r24, 0x0109
+    1df4:	90 e0       	ldi	r25, 0x00	; 0
+    1df6:	98 2f       	mov	r25, r24
+    1df8:	88 27       	eor	r24, r24
+    1dfa:	50 e0       	ldi	r21, 0x00	; 0
+    1dfc:	84 2b       	or	r24, r20
+    1dfe:	95 2b       	or	r25, r21
+    1e00:	90 93 87 01 	sts	0x0187, r25
+    1e04:	80 93 86 01 	sts	0x0186, r24
+        vect -= 4; // Instruction is a relative jump (rjmp), so recalculate.
+    1e08:	24 50       	subi	r18, 0x04	; 4
+    1e0a:	30 40       	sbci	r19, 0x00	; 0
+        buff[8] = vect & 0xff;
+    1e0c:	20 93 08 01 	sts	0x0108, r18
+        buff[9] = vect >> 8;
+    1e10:	23 2f       	mov	r18, r19
+    1e12:	33 27       	eor	r19, r19
+    1e14:	20 93 09 01 	sts	0x0109, r18
+
+        // Add jump to bootloader at RESET vector
+        buff[0] = 0x7f;
+    1e18:	f0 92 00 01 	sts	0x0100, r15
+        buff[1] = 0xce; // rjmp 0x1d00 instruction
+    1e1c:	e0 92 01 01 	sts	0x0101, r14
+      }
+#endif
+
+      // Copy buffer into programming buffer
+      bufPtr = buff;
+      addrPtr = (uint16_t)(void*)address;
+    1e20:	40 91 80 01 	lds	r20, 0x0180
+    1e24:	50 91 81 01 	lds	r21, 0x0181
+    1e28:	a0 e0       	ldi	r26, 0x00	; 0
+    1e2a:	b1 e0       	ldi	r27, 0x01	; 1
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+    1e2c:	2c 91       	ld	r18, X
+    1e2e:	30 e0       	ldi	r19, 0x00	; 0
+        a |= (*bufPtr++) << 8;
+    1e30:	11 96       	adiw	r26, 0x01	; 1
+    1e32:	8c 91       	ld	r24, X
+    1e34:	11 97       	sbiw	r26, 0x01	; 1
+    1e36:	90 e0       	ldi	r25, 0x00	; 0
+    1e38:	98 2f       	mov	r25, r24
+    1e3a:	88 27       	eor	r24, r24
+    1e3c:	82 2b       	or	r24, r18
+    1e3e:	93 2b       	or	r25, r19
+#define rstVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+4))
+#define wdtVect (*(uint16_t*)(RAMSTART+SPM_PAGESIZE*2+6))
+#endif
+
+/* main program starts here */
+int main(void) {
+    1e40:	12 96       	adiw	r26, 0x02	; 2
+      ch = SPM_PAGESIZE / 2;
+      do {
+        uint16_t a;
+        a = *bufPtr++;
+        a |= (*bufPtr++) << 8;
+        __boot_page_fill_short((uint16_t)(void*)addrPtr,a);
+    1e42:	fa 01       	movw	r30, r20
+    1e44:	0c 01       	movw	r0, r24
+    1e46:	d7 be       	out	0x37, r13	; 55
+    1e48:	e8 95       	spm
+    1e4a:	11 24       	eor	r1, r1
+        addrPtr += 2;
+    1e4c:	4e 5f       	subi	r20, 0xFE	; 254
+    1e4e:	5f 4f       	sbci	r21, 0xFF	; 255
+      } while (--ch);
+    1e50:	f1 e0       	ldi	r31, 0x01	; 1
+    1e52:	a0 34       	cpi	r26, 0x40	; 64
+    1e54:	bf 07       	cpc	r27, r31
+    1e56:	51 f7       	brne	.-44     	; 0x1e2c <main+0x12c>
+      
+      // Write from programming buffer
+      __boot_page_write_short((uint16_t)(void*)address);
+    1e58:	e0 91 80 01 	lds	r30, 0x0180
+    1e5c:	f0 91 81 01 	lds	r31, 0x0181
+    1e60:	c7 be       	out	0x37, r12	; 55
+    1e62:	e8 95       	spm
+      boot_spm_busy_wait();
+    1e64:	07 b6       	in	r0, 0x37	; 55
+    1e66:	00 fc       	sbrc	r0, 0
+    1e68:	fd cf       	rjmp	.-6      	; 0x1e64 <main+0x164>
+    1e6a:	41 c0       	rjmp	.+130    	; 0x1eee <main+0x1ee>
+      boot_rww_enable();
+#endif
+
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+    1e6c:	84 37       	cpi	r24, 0x74	; 116
+    1e6e:	89 f5       	brne	.+98     	; 0x1ed2 <main+0x1d2>
+      // READ PAGE - we only read flash
+      getLen();
+    1e70:	64 d0       	rcall	.+200    	; 0x1f3a <getLen>
+      verifySpace();
+    1e72:	71 d0       	rcall	.+226    	; 0x1f56 <verifySpace>
+#ifdef VIRTUAL_BOOT_PARTITION
+      do {
+        // Undo vector patch in bottom page so verify passes
+        if (address == 0)       ch=rstVect & 0xff;
+    1e74:	e0 91 80 01 	lds	r30, 0x0180
+    1e78:	f0 91 81 01 	lds	r31, 0x0181
+    1e7c:	30 97       	sbiw	r30, 0x00	; 0
+    1e7e:	19 f4       	brne	.+6      	; 0x1e86 <main+0x186>
+    1e80:	20 91 84 01 	lds	r18, 0x0184
+    1e84:	13 c0       	rjmp	.+38     	; 0x1eac <main+0x1ac>
+        else if (address == 1)  ch=rstVect >> 8;
+    1e86:	e1 30       	cpi	r30, 0x01	; 1
+    1e88:	f1 05       	cpc	r31, r1
+    1e8a:	19 f4       	brne	.+6      	; 0x1e92 <main+0x192>
+    1e8c:	20 91 85 01 	lds	r18, 0x0185
+    1e90:	0d c0       	rjmp	.+26     	; 0x1eac <main+0x1ac>
+        else if (address == 8)  ch=wdtVect & 0xff;
+    1e92:	e8 30       	cpi	r30, 0x08	; 8
+    1e94:	f1 05       	cpc	r31, r1
+    1e96:	19 f4       	brne	.+6      	; 0x1e9e <main+0x19e>
+    1e98:	20 91 86 01 	lds	r18, 0x0186
+    1e9c:	07 c0       	rjmp	.+14     	; 0x1eac <main+0x1ac>
+        else if (address == 9) ch=wdtVect >> 8;
+    1e9e:	e9 30       	cpi	r30, 0x09	; 9
+    1ea0:	f1 05       	cpc	r31, r1
+    1ea2:	19 f4       	brne	.+6      	; 0x1eaa <main+0x1aa>
+    1ea4:	20 91 87 01 	lds	r18, 0x0187
+    1ea8:	01 c0       	rjmp	.+2      	; 0x1eac <main+0x1ac>
+        else ch = pgm_read_byte_near(address);
+    1eaa:	24 91       	lpm	r18, Z+
+        address++;
+    1eac:	80 91 80 01 	lds	r24, 0x0180
+    1eb0:	90 91 81 01 	lds	r25, 0x0181
+    1eb4:	01 96       	adiw	r24, 0x01	; 1
+    1eb6:	90 93 81 01 	sts	0x0181, r25
+    1eba:	80 93 80 01 	sts	0x0180, r24
+        putch(ch);
+    1ebe:	82 2f       	mov	r24, r18
+    1ec0:	19 d0       	rcall	.+50     	; 0x1ef4 <putch>
+      } while (--length);
+    1ec2:	80 91 82 01 	lds	r24, 0x0182
+    1ec6:	81 50       	subi	r24, 0x01	; 1
+    1ec8:	80 93 82 01 	sts	0x0182, r24
+    1ecc:	88 23       	and	r24, r24
+    1ece:	91 f6       	brne	.-92     	; 0x1e74 <main+0x174>
+    1ed0:	0e c0       	rjmp	.+28     	; 0x1eee <main+0x1ee>
+#endif
+#endif
+    }
+
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+    1ed2:	85 37       	cpi	r24, 0x75	; 117
+    1ed4:	39 f4       	brne	.+14     	; 0x1ee4 <main+0x1e4>
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+    1ed6:	3f d0       	rcall	.+126    	; 0x1f56 <verifySpace>
+      putch(SIGNATURE_0);
+    1ed8:	8e e1       	ldi	r24, 0x1E	; 30
+    1eda:	0c d0       	rcall	.+24     	; 0x1ef4 <putch>
+      putch(SIGNATURE_1);
+    1edc:	83 e9       	ldi	r24, 0x93	; 147
+    1ede:	0a d0       	rcall	.+20     	; 0x1ef4 <putch>
+      putch(SIGNATURE_2);
+    1ee0:	8c e0       	ldi	r24, 0x0C	; 12
+    1ee2:	54 cf       	rjmp	.-344    	; 0x1d8c <main+0x8c>
+    }
+    else if (ch == 'Q') {
+    1ee4:	81 35       	cpi	r24, 0x51	; 81
+    1ee6:	11 f4       	brne	.+4      	; 0x1eec <main+0x1ec>
+      // Adaboot no-wait mod
+      watchdogConfig(WATCHDOG_16MS);
+    1ee8:	88 e0       	ldi	r24, 0x08	; 8
+    1eea:	2c d0       	rcall	.+88     	; 0x1f44 <watchdogConfig>
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    1eec:	34 d0       	rcall	.+104    	; 0x1f56 <verifySpace>
+    }
+    putch(STK_OK);
+    1eee:	80 e1       	ldi	r24, 0x10	; 16
+    1ef0:	01 d0       	rcall	.+2      	; 0x1ef4 <putch>
+    1ef2:	25 cf       	rjmp	.-438    	; 0x1d3e <main+0x3e>
+
+00001ef4 <putch>:
+void putch(char ch) {
+#ifndef SOFT_UART
+  while (!(UCSR0A & _BV(UDRE0)));
+  UDR0 = ch;
+#else
+  __asm__ __volatile__ (
+    1ef4:	2a e0       	ldi	r18, 0x0A	; 10
+    1ef6:	30 e0       	ldi	r19, 0x00	; 0
+    1ef8:	80 95       	com	r24
+    1efa:	08 94       	sec
+    1efc:	10 f4       	brcc	.+4      	; 0x1f02 <putch+0xe>
+    1efe:	da 98       	cbi	0x1b, 2	; 27
+    1f00:	02 c0       	rjmp	.+4      	; 0x1f06 <putch+0x12>
+    1f02:	da 9a       	sbi	0x1b, 2	; 27
+    1f04:	00 00       	nop
+    1f06:	15 d0       	rcall	.+42     	; 0x1f32 <uartDelay>
+    1f08:	14 d0       	rcall	.+40     	; 0x1f32 <uartDelay>
+    1f0a:	86 95       	lsr	r24
+    1f0c:	2a 95       	dec	r18
+    1f0e:	b1 f7       	brne	.-20     	; 0x1efc <putch+0x8>
+      [uartBit] "I" (UART_TX_BIT)
+    :
+      "r25"
+  );
+#endif
+}
+    1f10:	08 95       	ret
+
+00001f12 <getch>:
+  return getch();
+}
+
+// Watchdog functions. These are only safe with interrupts turned off.
+void watchdogReset() {
+  __asm__ __volatile__ (
+    1f12:	a8 95       	wdr
+#ifdef LED_DATA_FLASH
+  LED_PIN |= _BV(LED);
+#endif
+
+  return ch;
+}
+    1f14:	29 e0       	ldi	r18, 0x09	; 9
+    1f16:	30 e0       	ldi	r19, 0x00	; 0
+    1f18:	cb 99       	sbic	0x19, 3	; 25
+    1f1a:	fe cf       	rjmp	.-4      	; 0x1f18 <getch+0x6>
+    1f1c:	0a d0       	rcall	.+20     	; 0x1f32 <uartDelay>
+    1f1e:	09 d0       	rcall	.+18     	; 0x1f32 <uartDelay>
+    1f20:	08 d0       	rcall	.+16     	; 0x1f32 <uartDelay>
+    1f22:	88 94       	clc
+    1f24:	cb 99       	sbic	0x19, 3	; 25
+    1f26:	08 94       	sec
+    1f28:	2a 95       	dec	r18
+    1f2a:	11 f0       	breq	.+4      	; 0x1f30 <getch+0x1e>
+    1f2c:	87 95       	ror	r24
+    1f2e:	f7 cf       	rjmp	.-18     	; 0x1f1e <getch+0xc>
+    1f30:	08 95       	ret
+
+00001f32 <uartDelay>:
+#if UART_B_VALUE > 255
+#error Baud rate too slow for soft UART
+#endif
+
+void uartDelay() {
+  __asm__ __volatile__ (
+    1f32:	9e e0       	ldi	r25, 0x0E	; 14
+    1f34:	9a 95       	dec	r25
+    1f36:	f1 f7       	brne	.-4      	; 0x1f34 <uartDelay+0x2>
+    1f38:	08 95       	ret
+
+00001f3a <getLen>:
+  } while (--count);
+}
+#endif
+
+uint8_t getLen() {
+  getch();
+    1f3a:	eb df       	rcall	.-42     	; 0x1f12 <getch>
+  length = getch();
+    1f3c:	ea df       	rcall	.-44     	; 0x1f12 <getch>
+    1f3e:	80 93 82 01 	sts	0x0182, r24
+  return getch();
+}
+    1f42:	e7 cf       	rjmp	.-50     	; 0x1f12 <getch>
+
+00001f44 <watchdogConfig>:
+    "wdr\n"
+  );
+}
+
+void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+    1f44:	98 e1       	ldi	r25, 0x18	; 24
+    1f46:	91 bd       	out	0x21, r25	; 33
+  WDTCSR = x;
+    1f48:	81 bd       	out	0x21, r24	; 33
+}
+    1f4a:	08 95       	ret
+
+00001f4c <appStart>:
+
+void appStart() {
+  watchdogConfig(WATCHDOG_OFF);
+    1f4c:	80 e0       	ldi	r24, 0x00	; 0
+    1f4e:	fa df       	rcall	.-12     	; 0x1f44 <watchdogConfig>
+  __asm__ __volatile__ (
+    1f50:	e4 e0       	ldi	r30, 0x04	; 4
+    1f52:	ff 27       	eor	r31, r31
+    1f54:	09 94       	ijmp
+
+00001f56 <verifySpace>:
+  do getch(); while (--count);
+  verifySpace();
+}
+
+void verifySpace() {
+  if (getch() != CRC_EOP) appStart();
+    1f56:	dd df       	rcall	.-70     	; 0x1f12 <getch>
+    1f58:	80 32       	cpi	r24, 0x20	; 32
+    1f5a:	09 f0       	breq	.+2      	; 0x1f5e <verifySpace+0x8>
+    1f5c:	f7 df       	rcall	.-18     	; 0x1f4c <appStart>
+  putch(STK_INSYNC);
+    1f5e:	84 e1       	ldi	r24, 0x14	; 20
+}
+    1f60:	c9 cf       	rjmp	.-110    	; 0x1ef4 <putch>
+    ::[count] "M" (UART_B_VALUE)
+  );
+}
+#endif
+
+void getNch(uint8_t count) {
+    1f62:	1f 93       	push	r17
+    1f64:	18 2f       	mov	r17, r24
+
+00001f66 <getNch>:
+  do getch(); while (--count);
+    1f66:	d5 df       	rcall	.-86     	; 0x1f12 <getch>
+    1f68:	11 50       	subi	r17, 0x01	; 1
+    1f6a:	e9 f7       	brne	.-6      	; 0x1f66 <getNch>
+  verifySpace();
+    1f6c:	f4 df       	rcall	.-24     	; 0x1f56 <verifySpace>
+}
+    1f6e:	1f 91       	pop	r17
+    1f70:	08 95       	ret

+ 69 - 0
optiboot/bootloaders/optiboot/pin_defs.h

@@ -0,0 +1,69 @@
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
+/* 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
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTD
+#define UART_PIN    PIND
+#define UART_DDR    DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/* Luminet support */
+#if defined(__AVR_ATtiny84__)
+/* Red LED is connected to pin PA4 */ 
+#define LED_DDR     DDRA
+#define LED_PORT    PORTA
+#define LED_PIN     PINA
+#define LED         PINA4
+/* Ports for soft UART - left port only for now. TX/RX on PA2/PA3 */
+#ifdef SOFT_UART
+#define UART_PORT   PORTA
+#define UART_PIN    PINA
+#define UART_DDR    DDRA
+#define UART_TX_BIT 2
+#define UART_RX_BIT 3
+#endif
+#endif
+
+/* Sanguino support */
+#if defined(__AVR_ATmega644P__)
+/* Onboard LED is connected to pin PB0 on Sanguino */ 
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED         PINB0
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTD
+#define UART_PIN    PIND
+#define UART_DDR    DDRD
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif
+
+/* Mega support */
+#if defined(__AVR_ATmega1280__)
+/* Onboard LED is connected to pin PB7 on Arduino Mega */ 
+#define LED_DDR     DDRB
+#define LED_PORT    PORTB
+#define LED_PIN     PINB
+#define LED         PINB7
+
+/* Ports for soft UART */
+#ifdef SOFT_UART
+#define UART_PORT   PORTE
+#define UART_PIN    PINE
+#define UART_DDR    DDRE
+#define UART_TX_BIT 1
+#define UART_RX_BIT 0
+#endif
+#endif

+ 39 - 0
optiboot/bootloaders/optiboot/stk500.h

@@ -0,0 +1,39 @@
+/* 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'

+ 149 - 0
optiboot/cores/luminet/COM.c

@@ -0,0 +1,149 @@
+#include "COM.h"
+
+//void (*startBootloader)( void ) = (void *)BOOTADR;  // pointer to the bootloader start address
+
+void COM_init(void)
+{
+	uint8_t sreg = SREG;
+	cli();
+	COM_initASM();
+	SREG = sreg;
+}
+
+void LEFT_putc(uint8_t c)
+{
+	uint8_t sreg = SREG;
+	cli();
+	LEFT_putcASM(c);
+	SREG = sreg;
+}
+
+uint8_t LEFT_getc(void)
+{
+	uint8_t ret;
+	uint8_t sreg = SREG;
+	cli();
+	ret = LEFT_getcASM();
+	SREG = sreg;
+	return ret;
+}
+
+void RIGHT_putc(uint8_t c)
+{
+	uint8_t sreg = SREG;
+	cli();
+	RIGHT_putcASM(c);
+	SREG = sreg;
+}
+
+uint8_t RIGHT_getc(void)
+{
+	uint8_t ret;
+	uint8_t sreg = SREG;
+	cli();
+	ret = RIGHT_getcASM();
+	SREG = sreg;
+	return ret;
+}
+
+void UP_putc(uint8_t c)
+{
+	uint8_t sreg = SREG;
+	cli();
+	UP_putcASM(c);
+	SREG = sreg;
+}
+
+uint8_t UP_getc(void)
+{
+	uint8_t ret;
+	uint8_t sreg = SREG;
+	cli();
+	ret = UP_getcASM();
+	SREG = sreg;
+	return ret;
+}
+
+void DOWN_putc(uint8_t c)
+{
+	uint8_t sreg = SREG;
+	cli();
+	DOWN_putcASM(c);
+	SREG = sreg;
+}
+
+uint8_t DOWN_getc(void)
+{
+	uint8_t ret;
+	uint8_t sreg = SREG;
+	cli();
+	ret = DOWN_getcASM();
+	SREG = sreg;
+	return ret;
+}
+
+//destination: WEST, EAST, NORTH, SOUTH
+//c: char to be send
+void COM_putc(uint8_t destination, uint8_t c)
+{
+	void (*ptr) (uint8_t data);
+	
+	if(destination == WEST)
+	{
+		ptr = LEFT_putc;
+	}
+	else if(destination == EAST)
+	{
+		ptr = RIGHT_putc;
+	}
+	else if(destination == NORTH)
+	{
+		ptr = UP_putc;
+	}
+	else if(destination == SOUTH)
+	{
+		ptr = DOWN_putc;
+	}
+	
+	ptr(c);
+}
+
+//source: WEST, EAST, NORTH, SOUTH
+uint8_t COM_getc(uint8_t source)
+{
+	uint8_t c;
+	uint8_t d;
+	
+	uint8_t (*ptr) (void);
+	
+	if(source == WEST)
+	{
+		ptr = LEFT_getc;
+	}
+	else if(source == EAST)
+	{
+		ptr = RIGHT_getc;
+	}
+	else if(source == NORTH)
+	{
+		ptr = UP_getc;
+	}
+	else if(source == SOUTH)
+	{
+		ptr = DOWN_getc;
+	}
+	
+	c = ptr();
+	if(c == 0xF0)
+	{
+		d = ptr();
+		return d;
+	}
+	else if(c == 0xA0)
+	{
+		//startBootloader();
+	}
+	
+	return 0x00;
+}
+

+ 70 - 0
optiboot/cores/luminet/COM.h

@@ -0,0 +1,70 @@
+#ifndef _COM_H_
+#define _COM_H_
+
+#include "WProgram.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include <util/delay_basic.h>
+
+
+
+#define WEST 0
+#define EAST 1
+#define NORTH 2
+#define SOUTH 3
+
+#ifndef BOOTADR
+#define BOOTADR 0x1A00
+#endif
+
+
+void COM_init(void);
+
+//destination: WEST, EAST, NORTH, SOUTH
+//c: char to be send
+void COM_putc(uint8_t destination, uint8_t c);
+
+//source: WEST, EAST, NORTH, SOUTH
+uint8_t COM_getc(uint8_t source);
+
+void LEFT_putc(uint8_t c);//DO NOT USE!
+uint8_t LEFT_getc(void);//DO NOT USE!
+
+void RIGHT_putc(uint8_t c);//DO NOT USE!
+uint8_t RIGHT_getc(void);//DO NOT USE!
+
+void UP_putc(uint8_t c);//DO NOT USE!
+uint8_t UP_getc(void);//DO NOT USE!
+
+void DOWN_putc(uint8_t c);//DO NOT USE!
+uint8_t DOWN_getc(void);//DO NOT USE!
+
+
+//DO NOT USE THESE FUNCTIONS:
+//use them only in the bootloader code
+
+
+extern void COM_initASM(void);
+
+extern void LEFT_putcASM(uint8_t c);//DO NOT USE!
+extern uint8_t LEFT_getcASM(void);//DO NOT USE!
+
+extern void RIGHT_putcASM(uint8_t c);//DO NOT USE!
+extern uint8_t RIGHT_getcASM(void);//DO NOT USE!
+
+extern void UP_putcASM(uint8_t c);//DO NOT USE!
+extern uint8_t UP_getcASM(void);//DO NOT USE!
+
+extern void DOWN_putcASM(uint8_t c);//DO NOT USE!
+extern uint8_t DOWN_getcASM(void);//DO NOT USE!
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /* _COM_H_ */

+ 361 - 0
optiboot/cores/luminet/COMasm.S

@@ -0,0 +1,361 @@
+#include <avr/io.h>
+
+#define	LEFT_TXDDR DDRA
+#define	LEFT_TXPORT PORTA
+#define LEFT_TXPINNumber  PA2			
+		
+#define	LEFT_RXDDR  DDRA
+#define	LEFT_RXPORT PORTA
+#define	LEFT_RXPIN  PINA
+#define	LEFT_RXPINNumber PA3			
+
+#define	RIGHT_TXDDR DDRB
+#define	RIGHT_TXPORT PORTB
+#define RIGHT_TXPINNumber  PB1			
+		
+#define	RIGHT_RXDDR  DDRB
+#define	RIGHT_RXPORT PORTB
+#define	RIGHT_RXPIN  PINB
+#define	RIGHT_RXPINNumber PB0			
+	
+
+#define	UP_TXDDR DDRB
+#define	UP_TXPORT PORTB
+#define UP_TXPINNumber  PB2			
+		
+#define	UP_RXDDR  DDRA
+#define	UP_RXPORT PORTA
+#define	UP_RXPIN  PINA
+#define	UP_RXPINNumber PA7
+
+#define	DOWN_TXDDR DDRA
+#define	DOWN_TXPORT PORTA
+#define DOWN_TXPINNumber  PA1			
+		
+#define	DOWN_RXDDR  DDRA
+#define	DOWN_RXPORT PORTA
+#define	DOWN_RXPIN  PINA
+#define	DOWN_RXPINNumber PA0			
+
+;***** Global register variables
+
+;bit counter
+#define	bitcnt r16
+
+;temporary storage register
+#define	temp r17
+
+
+
+;***************************************************************************
+;*
+;* uart_initASM
+;*
+.global COM_initASM
+.func COM_initASM
+COM_initASM:		
+	sbi _SFR_IO_ADDR(LEFT_TXDDR),LEFT_TXPINNumber
+	sbi _SFR_IO_ADDR(LEFT_TXPORT),LEFT_TXPINNumber
+	cbi _SFR_IO_ADDR(LEFT_RXDDR),LEFT_RXPINNumber
+	
+	sbi _SFR_IO_ADDR(RIGHT_TXDDR),RIGHT_TXPINNumber
+	sbi _SFR_IO_ADDR(RIGHT_TXPORT),RIGHT_TXPINNumber
+	cbi _SFR_IO_ADDR(RIGHT_RXDDR),RIGHT_RXPINNumber
+	
+	sbi _SFR_IO_ADDR(UP_TXDDR),UP_TXPINNumber
+	sbi _SFR_IO_ADDR(UP_TXPORT),UP_TXPINNumber
+	cbi _SFR_IO_ADDR(UP_RXDDR),UP_RXPINNumber
+	
+	sbi _SFR_IO_ADDR(DOWN_TXDDR),DOWN_TXPINNumber
+	sbi _SFR_IO_ADDR(DOWN_TXPORT),DOWN_TXPINNumber
+	cbi _SFR_IO_ADDR(DOWN_RXDDR),DOWN_RXPINNumber
+	
+	ret		
+.endfunc
+
+
+;***************************************************************************
+;*
+;* LEFT_putcASM
+;*
+.global LEFT_putcASM
+.func LEFT_putcASM
+LEFT_putcASM:	
+	ldi	bitcnt,10	;put 10 bits (start+stop+payload
+	com	r24		;Inverte everything
+	sec			;Start bit
+
+LEFT_putchar0:	
+	brcc	LEFT_putchar1	;If carry set
+	cbi	_SFR_IO_ADDR(LEFT_TXPORT),LEFT_TXPINNumber	;    send a '0'
+	rjmp	LEFT_putchar2	;else	
+
+LEFT_putchar1:	
+	sbi	_SFR_IO_ADDR(LEFT_TXPORT),LEFT_TXPINNumber	;    send a '1'
+	nop
+
+LEFT_putchar2:	
+	rcall UART_delay	;One bit delay
+	rcall UART_delay
+	lsr	r24		;Get next bit
+	dec	bitcnt		;If not all bit sent
+	brne	LEFT_putchar0	;   send next
+				;else
+	ret			;   return
+.endfunc
+
+;***************************************************************************
+;*
+;* LEFT_getcASM
+.global LEFT_getcASM
+.func LEFT_getcASM
+LEFT_getcASM:	
+	ldi 	bitcnt,9	;8 data bit + 1 stop bit
+
+LEFT_getchar1:	
+	sbic 	_SFR_IO_ADDR(LEFT_RXPIN),LEFT_RXPINNumber	;Wait for start bit
+	rjmp 	LEFT_getchar1
+	rcall UART_delay	;0.5 bit delay
+
+LEFT_getchar2:	
+	rcall UART_delay	;1 bit delay
+	rcall UART_delay		
+	clc			;clear carry
+	sbic 	_SFR_IO_ADDR(LEFT_RXPIN),LEFT_RXPINNumber	;if RX pin high
+	sec			;
+	dec 	bitcnt		;If bit is stop bit
+	breq 	LEFT_getchar3	;   return
+				;else
+	ror 	r24		;   shift bit into Rxbyte
+	rjmp 	LEFT_getchar2	;   go get next
+
+LEFT_getchar3:	
+	ret
+.endfunc
+
+
+
+
+
+;***************************************************************************
+;*
+;* RIGHT_putcASM
+;*
+.global RIGHT_putcASM
+.func RIGHT_putcASM
+RIGHT_putcASM:	
+	ldi	bitcnt,10	;put 10 bits (start+stop+payload
+	com	r24		;Inverte everything
+	sec			;Start bit
+
+RIGHT_putchar0:	
+	brcc	RIGHT_putchar1	;If carry set
+	cbi	_SFR_IO_ADDR(RIGHT_TXPORT),RIGHT_TXPINNumber	;    send a '0'
+	rjmp	RIGHT_putchar2	;else	
+
+RIGHT_putchar1:	
+	sbi	_SFR_IO_ADDR(RIGHT_TXPORT),RIGHT_TXPINNumber	;    send a '1'
+	nop
+
+RIGHT_putchar2:	
+	rcall UART_delay	;One bit delay
+	rcall UART_delay
+	lsr	r24		;Get next bit
+	dec	bitcnt		;If not all bit sent
+	brne	RIGHT_putchar0	;   send next
+				;else
+	ret			;   return
+.endfunc
+
+;***************************************************************************
+;*
+;* RIGHT_getcASM
+.global RIGHT_getcASM
+.func RIGHT_getcASM
+RIGHT_getcASM:	
+	ldi 	bitcnt,9	;8 data bit + 1 stop bit
+
+RIGHT_getchar1:	
+	sbic 	_SFR_IO_ADDR(RIGHT_RXPIN),RIGHT_RXPINNumber	;Wait for start bit
+	rjmp 	RIGHT_getchar1
+	rcall UART_delay	;0.5 bit delay
+
+RIGHT_getchar2:	
+	rcall UART_delay	;1 bit delay
+	rcall UART_delay		
+	clc			;clear carry
+	sbic 	_SFR_IO_ADDR(RIGHT_RXPIN),RIGHT_RXPINNumber	;if RX pin high
+	sec			;
+	dec 	bitcnt		;If bit is stop bit
+	breq 	RIGHT_getchar3	;   return
+				;else
+	ror 	r24		;   shift bit into Rxbyte
+	rjmp 	RIGHT_getchar2	;   go get next
+
+RIGHT_getchar3:	
+	ret
+.endfunc
+
+
+
+
+
+;***************************************************************************
+;*
+;* UP_putcASM
+;*
+.global UP_putcASM
+.func UP_putcASM
+UP_putcASM:	
+	ldi	bitcnt,10	;put 10 bits (start+stop+payload
+	com	r24		;Inverte everything
+	sec			;Start bit
+
+UP_putchar0:	
+	brcc	UP_putchar1	;If carry set
+	cbi	_SFR_IO_ADDR(UP_TXPORT),UP_TXPINNumber	;    send a '0'
+	rjmp	UP_putchar2	;else	
+
+UP_putchar1:	
+	sbi	_SFR_IO_ADDR(UP_TXPORT),UP_TXPINNumber	;    send a '1'
+	nop
+
+UP_putchar2:	
+	rcall UART_delay	;One bit delay
+	rcall UART_delay
+	lsr	r24		;Get next bit
+	dec	bitcnt		;If not all bit sent
+	brne	UP_putchar0	;   send next
+				;else
+	ret			;   return
+.endfunc
+
+;***************************************************************************
+;*
+;* UP_getcASM
+.global UP_getcASM
+.func UP_getcASM
+UP_getcASM:	
+	ldi 	bitcnt,9	;8 data bit + 1 stop bit
+
+UP_getchar1:	
+	sbic 	_SFR_IO_ADDR(UP_RXPIN),UP_RXPINNumber	;Wait for start bit
+	rjmp 	UP_getchar1
+	rcall UART_delay	;0.5 bit delay
+
+UP_getchar2:	
+	rcall UART_delay	;1 bit delay
+	rcall UART_delay		
+	clc			;clear carry
+	sbic 	_SFR_IO_ADDR(UP_RXPIN),UP_RXPINNumber	;if RX pin high
+	sec			;
+	dec 	bitcnt		;If bit is stop bit
+	breq 	UP_getchar3	;   return
+				;else
+	ror 	r24		;   shift bit into Rxbyte
+	rjmp 	UP_getchar2	;   go get next
+
+UP_getchar3:	
+	ret
+.endfunc
+
+
+
+;***************************************************************************
+;*
+;* DOWN_putcASM
+;*
+.global DOWN_putcASM
+.func DOWN_putcASM
+DOWN_putcASM:	
+	ldi	bitcnt,10	;put 10 bits (start+stop+payload
+	com	r24		;Inverte everything
+	sec			;Start bit
+
+DOWN_putchar0:	
+	brcc	DOWN_putchar1	;If carry set
+	cbi	_SFR_IO_ADDR(DOWN_TXPORT),DOWN_TXPINNumber	;    send a '0'
+	rjmp	DOWN_putchar2	;else	
+
+DOWN_putchar1:	
+	sbi	_SFR_IO_ADDR(DOWN_TXPORT),DOWN_TXPINNumber	;    send a '1'
+	nop
+
+DOWN_putchar2:	
+	rcall UART_delay	;One bit delay
+	rcall UART_delay
+	lsr	r24		;Get next bit
+	dec	bitcnt		;If not all bit sent
+	brne	DOWN_putchar0	;   send next
+				;else
+	ret			;   return
+.endfunc
+
+;***************************************************************************
+;*
+;* DOWN_getc
+.global DOWN_getcASM
+.func DOWN_getcASM
+DOWN_getcASM:	
+	ldi 	bitcnt,9	;8 data bit + 1 stop bit
+
+DOWN_getchar1:	
+	sbic 	_SFR_IO_ADDR(DOWN_RXPIN),DOWN_RXPINNumber	;Wait for start bit
+	rjmp 	DOWN_getchar1
+	rcall UART_delay	;0.5 bit delay
+
+DOWN_getchar2:	
+	rcall UART_delay	;1 bit delay
+	rcall UART_delay		
+	clc			;clear carry
+	sbic 	_SFR_IO_ADDR(DOWN_RXPIN),DOWN_RXPINNumber	;if RX pin high
+	sec			;
+	dec 	bitcnt		;If bit is stop bit
+	breq 	DOWN_getchar3	;   return
+				;else
+	ror 	r24		;   shift bit into Rxbyte
+	rjmp 	DOWN_getchar2	;   go get next
+
+DOWN_getchar3:	
+	ret
+.endfunc
+
+
+;***************************************************************************
+;*
+;* "UART_delay"
+;***************************************************************************
+; Some b values: 	(See also table in Appnote documentation)
+;
+; 1 MHz crystal:
+;   9600 bps - b=14
+;  19200 bps - b=5
+;  28800 bps - b=2
+;
+; 2 MHz crystal:
+;  19200 bps - b=14
+;  28800 bps - b=8
+;  57600 bps - b=2
+
+; 4 MHz crystal:
+;  19200 bps - b=31
+;  28800 bps - b=19
+;  57600 bps - b=8
+; 115200 bps - b=2
+
+;.equ	b	=31	;19200 bps @ 4 MHz crystal
+b	=14	;9600 bps @ 1 MHz crystal
+;b	=8	;115000 bps @ 8 MHz crystal
+	
+
+
+UART_delay:	
+	ldi	temp,b
+UART_delay1:	
+	dec	temp
+	brne	UART_delay1
+	ret
+
+
+
+

+ 62 - 0
optiboot/cores/luminet/HardwareSerial.cpp

@@ -0,0 +1,62 @@
+/*
+  HarwareSerial.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 "HardwareSerial.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void HardwareSerial::begin(long speed)
+{
+  beginSerial(speed);
+}
+
+uint8_t HardwareSerial::available(void)
+{
+  return serialAvailable();
+}
+
+int HardwareSerial::read(void)
+{
+  return serialRead();
+}
+
+void HardwareSerial::flush()
+{
+  serialFlush();
+}
+
+void HardwareSerial::write(uint8_t b) {
+  serialWrite(b);
+}
+
+void HardwareSerial::selectDirection(uint8_t b) {
+  selectDirectionSerial(b);
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+HardwareSerial Serial = HardwareSerial();
+

+ 41 - 0
optiboot/cores/luminet/HardwareSerial.h

@@ -0,0 +1,41 @@
+/*
+  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"
+
+class HardwareSerial : public Print
+{
+  public:
+    void begin(long);
+    uint8_t available(void);
+    int read(void);
+    void flush(void);
+    virtual void write(uint8_t);
+    void selectDirection(uint8_t);
+};
+
+extern HardwareSerial Serial;
+
+#endif
+

+ 14 - 0
optiboot/cores/luminet/LEDExtensions.c

@@ -0,0 +1,14 @@
+#include "LEDExtensions.h"
+
+
+void setRGB(uint8_t r, uint8_t g, uint8_t b)
+{
+	bynase_registerPin(8, BYNASE_OUTPUT);
+	bynase_registerPin(9, BYNASE_OUTPUT);
+	bynase_registerPin(10, BYNASE_OUTPUT);
+
+	bynase_write(8, r);
+	bynase_write(9, g);
+	bynase_write(10, b);	
+	
+}

+ 17 - 0
optiboot/cores/luminet/LEDExtensions.h

@@ -0,0 +1,17 @@
+#ifndef _LEDEXTENSIONS_H
+#define _LEDEXTENSIONS_H
+
+#include "WProgram.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+void setRGB(uint8_t r, uint8_t g, uint8_t b);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif

+ 253 - 0
optiboot/cores/luminet/Makefile

@@ -0,0 +1,253 @@
+# Arduino 0011 Makefile
+# Arduino adaptation by mellis, eighthave, oli.keller
+#
+# This makefile allows you to build sketches from the command line
+# without the Arduino environment (or Java).
+#
+# Detailed instructions for using the makefile:
+#
+#  1. Copy this file into the folder with your sketch. There should be a
+#     file with the same name as the folder and with the extension .pde
+#     (e.g. foo.pde in the foo/ folder).
+#
+#  2. Modify the line containg "INSTALL_DIR" to point to the directory that
+#     contains the Arduino installation (for example, under Mac OS X, this
+#     might be /Applications/arduino-0012).
+#
+#  3. Modify the line containing "PORT" to refer to the filename
+#     representing the USB or serial connection to your Arduino board
+#     (e.g. PORT = /dev/tty.USB0).  If the exact name of this file
+#     changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*).
+#
+#  4. Set the line containing "MCU" to match your board's processor. 
+#     Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
+#     or Diecimila have the atmega168.  If you're using a LilyPad Arduino,
+#     change F_CPU to 8000000.
+#
+#  5. At the command line, change to the directory containing your
+#     program's file and the makefile.
+#
+#  6. Type "make" and press enter to compile/verify your program.
+#
+#  7. Type "make upload", reset your Arduino board, and press enter to
+#     upload your program to the Arduino board.
+#
+# $Id$
+
+TARGET = $(notdir $(CURDIR))
+INSTALL_DIR = E:/arduino_trunk/build/windows/work
+PORT = COM1
+UPLOAD_RATE = 19200
+AVRDUDE_PROGRAMMER = stk500v2
+MCU = attiny84
+F_CPU = 1000000
+
+############################################################################
+# Below here nothing should be changed...
+
+ARDUINO = $(INSTALL_DIR)/hardware/cores/luminet
+AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin
+SRC = $(ARDUINO)/topology.c $(ARDUINO)/bynase.c $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \
+$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \
+$(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \
+$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c \
+CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp 
+FORMAT = ihex
+
+
+# Name of this Makefile (used for "make depend").
+MAKEFILE = Makefile
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+
+OPT = s
+
+# Place -D or -U options here
+CDEFS = -DF_CPU=$(F_CPU)
+CXXDEFS = -DF_CPU=$(F_CPU)
+
+# Place -I options here
+CINCS = -I$(ARDUINO)
+CXXINCS = -I$(ARDUINO)
+
+# Compiler flag to set the C Standard level.
+# c89   - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99   - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+CDEBUG = -g$(DEBUG)
+CWARN = -Wall -Wstrict-prototypes
+CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
+
+CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
+CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT)
+#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 
+LDFLAGS = -lm
+
+
+# Programming support using avrdude. Settings and variables.
+AVRDUDE_PORT = $(PORT)
+AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
+AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf \
+-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
+-b $(UPLOAD_RATE)
+
+# Program settings
+CC = $(AVR_TOOLS_PATH)/avr-gcc
+CXX = $(AVR_TOOLS_PATH)/avr-g++
+OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy
+OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump
+AR  = $(AVR_TOOLS_PATH)/avr-ar
+SIZE = $(AVR_TOOLS_PATH)/avr-size
+NM = $(AVR_TOOLS_PATH)/avr-nm
+AVRDUDE = $(AVR_TOOLS_PATH)/avrdude
+REMOVE = rm -f
+MV = mv -f
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) 
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
+ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+# Default target.
+all: applet_files build sizeafter
+
+build: elf hex lss sym
+
+applet_files: $(TARGET).pde
+	# Here is the "preprocessing".
+	# It creates a .cpp file based with the same name as the .pde file.
+	# On top of the new .cpp file comes the WProgram.h header.
+	# At the end there is a generic main() function attached.
+	# Then the .cpp file will be compiled. Errors during compile will
+	# refer to this new, automatically generated, file. 
+	# Not the original .pde file you actually edit...
+	test -d applet || mkdir applet
+	echo '#include "WProgram.h"' > applet/$(TARGET).cpp
+	cat $(TARGET).pde >> applet/$(TARGET).cpp
+	cat $(ARDUINO)/main.cxx >> applet/$(TARGET).cpp
+
+elf: applet/$(TARGET).elf
+hex: applet/$(TARGET).hex
+eep: applet/$(TARGET).eep
+lss: applet/$(TARGET).lss 
+sym: applet/$(TARGET).sym
+
+# Program the device.  
+upload: applet/$(TARGET).hex
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
+
+
+	# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex
+ELFSIZE = $(SIZE)  applet/$(TARGET).elf
+sizebefore:
+	@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
+
+sizeafter:
+	@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000 
+
+
+coff: applet/$(TARGET).elf
+	$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof
+
+
+.SUFFIXES: .elf .hex .eep .lss .sym
+
+.elf.hex:
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+.elf.eep:
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+	--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+.elf.lss:
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+.elf.sym:
+	$(NM) -n $< > $@
+	
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+	$(NM) -n $< > $@
+
+
+	# Link: create ELF output file from library.
+applet/$(TARGET).elf: $(TARGET).pde applet/core.a 
+	$(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS)
+
+applet/core.a: $(OBJ)
+	@for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done
+
+
+
+# Compile: create object files from C++ source files.
+.cpp.o:
+	$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ 
+
+# Compile: create object files from C source files.
+.c.o:
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
+
+
+# Compile: create assembler files from C source files.
+.c.s:
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+.S.o:
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean:
+	$(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \
+	applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \
+	$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
+
+depend:
+	if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
+	then \
+		sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
+			$(MAKEFILE).$$$$ && \
+		$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
+	fi
+	echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
+		>> $(MAKEFILE); \
+	$(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
+
+.PHONY:	all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter

+ 213 - 0
optiboot/cores/luminet/Print.cpp

@@ -0,0 +1,213 @@
+/*
+ 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 <inttypes.h>
+#include <math.h>
+#include <avr/delay.h>
+#include "wiring.h"
+
+#include "Print.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void Print::print(uint8_t b)
+{
+  this->write(b);
+  _delay_loop_2(50);//short delay helps the line to recover (become IDLE)
+}
+
+void Print::print(char c)
+{
+  print((byte) c);
+}
+
+void Print::print(const char c[])
+{
+  uint8_t volatile len = strlen(c);
+  for(uint8_t z=0; z<len; z++)
+  {
+    print((uint8_t) c[z]);
+  }
+}
+
+void Print::print(int n)
+{
+  print((long) n);
+}
+
+void Print::print(unsigned int n)
+{
+  print((unsigned long) n);
+}
+
+void Print::print(long n)
+{
+  if (n < 0) {
+    print('-');
+    n = -n;
+  }
+  printNumber(n, 10);
+}
+
+void Print::print(unsigned long n)
+{
+  printNumber(n, 10);
+}
+
+void Print::print(long n, int base)
+{
+  if (base == 0)
+    print((char) n);
+  else if (base == DEC)
+    print((long) n);
+  else
+    printNumber(n, base);
+}
+
+void Print::print(double n)
+{
+  printFloat(n, 2);
+}
+
+void Print::println(void)
+{
+  print((uint8_t) '\r');
+  print((uint8_t) '\n');  
+}
+
+void Print::println(char c)
+{
+  print(c);
+  println();  
+}
+
+void Print::println(const char c[])
+{
+  uint8_t volatile len = strlen(c);
+  for(uint8_t z=0; z<len; z++)
+  {
+    print((uint8_t) c[z]);
+  }
+  print((uint8_t) '\r');
+  print((uint8_t) '\n');  
+}
+
+void Print::println(uint8_t b)
+{
+  print(b);
+  println();
+}
+
+void Print::println(int n)
+{
+  print(n);
+  println();
+}
+
+void Print::println(unsigned int n)
+{
+  print(n);
+  println();
+}
+
+void Print::println(long n)
+{
+  print(n);
+  println();  
+}
+
+void Print::println(unsigned long n)
+{
+  print(n);
+  println();  
+}
+
+void Print::println(long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(double n)
+{
+  print(n);
+  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; 
+  } 
+}

+ 59 - 0
optiboot/cores/luminet/Print.h

@@ -0,0 +1,59 @@
+/*
+  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>
+
+#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);
+    void print(char);
+    void print(const char[]);
+    void print(uint8_t);
+    void print(int);
+    void print(unsigned int);
+    void print(long);
+    void print(unsigned long);
+    void print(long, int);
+    void print(double);
+    void println(void);
+    void println(char);
+    void println(const char[]);
+    void println(uint8_t);
+    void println(int);
+    void println(unsigned int);
+    void println(long);
+    void println(unsigned long);
+    void println(long, int);
+    void println(double);
+};
+
+#endif

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

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

+ 106 - 0
optiboot/cores/luminet/WInterrupts.c

@@ -0,0 +1,106 @@
+/* -*- 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;
+
+
+#define EICRA MCUCR
+#define EIMSK GICR
+
+
+void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
+	
+	/*
+  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+    intFunc[interruptNum] = userFunc;
+    
+    if (interruptNum == 0) {
+      // 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.
+      EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
+      
+      // Enable the interrupt.
+      EIMSK |= (1 << INT0);
+    } else {
+      EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10);
+      EIMSK |= (1 << INT1);
+    }
+  }
+  */
+}
+
+void detachInterrupt(uint8_t interruptNum) {
+	/*
+  if(interruptNum < EXTERNAL_NUM_INTERRUPTS) {
+    if (interruptNum == 0)
+      // Disable the interrupt.
+      EIMSK &= ~(1 << INT0);
+    else
+      EIMSK &= ~(1 << INT1);
+      
+    intFunc[interruptNum] = 0;
+  }
+  */
+}
+
+/*
+void attachInterruptTwi(void (*userFunc)(void) ) {
+  twiIntFunc = userFunc;
+}
+*/
+
+/*
+SIGNAL(INT0_vect) {
+  if(intFunc[EXTERNAL_INT_0])
+    intFunc[EXTERNAL_INT_0]();
+}
+*/
+
+/*
+SIGNAL(INT1_vect) {
+  if(intFunc[EXTERNAL_INT_1])
+    intFunc[EXTERNAL_INT_1]();
+}
+*/
+
+/*
+SIGNAL(SIG_2WIRE_SERIAL) {
+  if(twiIntFunc)
+    twiIntFunc();
+}
+*/
+

+ 60 - 0
optiboot/cores/luminet/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; }

+ 37 - 0
optiboot/cores/luminet/WProgram.h

@@ -0,0 +1,37 @@
+#ifndef WProgram_h
+#define WProgram_h
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include <avr/interrupt.h>
+
+#include "topology.h"
+#include "bynase.h"
+#include "LEDExtensions.h"
+#include "COM.h"
+
+#include "wiring.h"
+
+uint8_t mainconnections;
+
+
+#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);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned int);
+long map(long, long, long, long, long);
+#endif
+
+#endif

+ 515 - 0
optiboot/cores/luminet/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

+ 304 - 0
optiboot/cores/luminet/bynase.c

@@ -0,0 +1,304 @@
+#include "bynase.h"
+#include <avr/io.h>
+
+//number of samples simple_byin should take
+#define NUMBER_OF_SAMPLES 200
+
+#define NUMBER_OF_BYNASE_PINS 19
+
+uint8_t outPinsA;//Arduino Pins 7..0
+uint8_t outPinsB;//Arduino Pins 15..8
+uint8_t outPinsC;//Arduino Pins 19..16
+
+uint8_t inPinsA;//Arduino Pins 7..0
+uint8_t inPinsB;//Arduino Pins 15..8
+uint8_t inPinsC;//Arduino Pins 19..16
+
+uint8_t byval_out[NUMBER_OF_BYNASE_PINS];//byvals for up to 19 output pins
+uint8_t byval_in[NUMBER_OF_BYNASE_PINS];//byvals for up to 19 input pins
+
+uint16_t total_in[NUMBER_OF_BYNASE_PINS];
+uint8_t count_in[NUMBER_OF_BYNASE_PINS];
+
+uint8_t timerSpeed;
+
+uint8_t byrandValue;//for random
+
+
+uint8_t byrand(void)
+{
+ uint8_t v = byrandValue++;
+ uint8_t r = 0;
+ uint8_t q = 255;
+ while(q) {
+ r = (r << 1) | (v & 1);
+ v >>= 1;
+ q >>= 1;
+ }
+ return r;
+}
+
+void _byin(uint8_t pinNumber)
+{
+	if(pinNumber < 8)
+	{
+		if(! (inPinsA & (1 <<(pinNumber))) )
+		{
+			return;//pin is not registered for bynase output
+		}
+	}
+	else if(pinNumber < 15)
+	{
+		if(! (inPinsB & (1 <<(pinNumber-8))) )
+		{
+			return;//pin is not registered for bynase output
+		}
+	}
+	else
+	{
+		if(! (inPinsC & (1 <<(pinNumber-15))) )
+		{
+			return;//pin is not registered for bynase output
+		}
+	}
+	
+	count_in[pinNumber]++;
+	if(count_in[pinNumber] >= NUMBER_OF_SAMPLES)
+	{
+		byval_in[pinNumber] = (total_in[pinNumber] * 100) / count_in[pinNumber];
+		count_in[pinNumber] = 0;
+		total_in[pinNumber] = 0;
+	}
+	else
+	{
+		if(digitalRead(pinNumber) == HIGH)
+		{
+			total_in[pinNumber]++;
+		}
+		
+	}	
+}
+
+void byin(void) 
+{
+	uint8_t z;
+	for(z=0; z<NUMBER_OF_BYNASE_PINS; z++)
+	{
+		_byin(z);
+	}
+}
+
+void _byout(uint8_t pinNumber, uint8_t random_value) 
+{
+	if(pinNumber < 8)
+	{
+		if(! (outPinsA & (1 <<pinNumber)) )
+		{
+			return;//pin is not registered for bynase input
+		}
+	}
+	else if(pinNumber < 15)
+	{
+		if(! (outPinsB & (1 <<(pinNumber-8))) )
+		{
+			return;//pin is not registered for bynase input
+		}
+	}
+	else
+	{
+		if(! (outPinsC & (1 <<(pinNumber-15))) )
+		{
+			return;//pin is not registered for bynase input
+		}
+	}
+	
+	
+	if (byval_out[pinNumber] >= random_value) 
+	{
+		digitalWrite(pinNumber, HIGH);
+	} 
+	else 
+	{
+		digitalWrite(pinNumber, LOW);
+	}
+}
+
+void byout(void) 
+{
+	uint8_t random_value;//only one random value for all ports
+	random_value = ((byrand() % 99)+1);//random value between 1 and 100
+	uint8_t z;
+	for(z=0; z<NUMBER_OF_BYNASE_PINS; z++)
+	{
+		_byout(z, random_value);
+	}
+	
+}
+
+void bynase_init(uint8_t speed)
+{
+	uint8_t z;
+	uint8_t oldSREG = SREG;
+	
+	if(timerSpeed != speed)
+	{
+		for(z=0; z<NUMBER_OF_BYNASE_PINS; z++)
+		{
+			byval_out[z] = 0;
+			byval_in[z] = 0;
+			total_in[z] = 0;
+			count_in[z] = 0;
+		}
+		timerSpeed = speed;
+		
+		cli();	
+		//INIT TIMER1
+		TCCR1A = 0x00;
+	  TCCR1B = 0b00000001; //no prescaler
+	  TIMSK1 = 0b00000001;//enable timer overflow interrupt
+	  
+	 // byrandValue=0;
+		
+		// reenable interrupts.
+		SREG = oldSREG;
+	}
+}
+
+void bynase_write(uint8_t pinNumber, uint8_t value)
+{
+	byval_out[pinNumber] = value;
+}
+
+
+uint8_t bynase_read(uint8_t pinNumber)
+{
+	
+	return byval_in[pinNumber];
+}
+
+
+
+void bynase_registerPin(uint8_t pinNumber, uint8_t mode)
+{
+	if(pinNumber > (NUMBER_OF_BYNASE_PINS-1))
+	{
+		return;
+	}
+	
+	if(mode == BYNASE_INPUT)
+	{
+		pinMode(pinNumber, INPUT);
+		digitalWrite(pinNumber, LOW);		
+
+		if(pinNumber < 8)
+		{
+			inPinsA |= (1<<pinNumber);
+			outPinsA &= (uint8_t)~(1<<pinNumber);
+		}
+		else if(pinNumber < 15)
+		{
+			inPinsB |= (1<<(pinNumber-8));
+			outPinsB &= (uint8_t)~(1<<(pinNumber-8));
+		}
+		else
+		{
+			inPinsC |= (1<<(pinNumber-15));
+			outPinsC &= (uint8_t)~(1<<(pinNumber-15));
+		}
+		
+	}
+	else if(mode == BYNASE_OUTPUT)
+	{
+		pinMode(pinNumber, OUTPUT);
+		digitalWrite(pinNumber, LOW);
+		
+		if(pinNumber < 8)
+		{
+			outPinsA |= (1<<pinNumber);
+			inPinsA &= (uint8_t)~(1<<pinNumber);
+		}
+		else if(pinNumber < 15)
+		{
+			outPinsB |= (1<<(pinNumber-8));
+			inPinsB &= (uint8_t)~(1<<(pinNumber-8));
+		}
+		else
+		{
+			outPinsC |= (1<<(pinNumber-15));
+			inPinsC &= (uint8_t)~(1<<(pinNumber-15));
+		}
+		
+		
+	}
+	else if(mode == BYNASE_BOTH)
+	{
+		if(pinNumber < 8)
+		{
+			outPinsA |= (1<<pinNumber);
+			inPinsA |= (1<<pinNumber);
+		}
+		else if(pinNumber < 15)
+		{
+			outPinsB |= (1<<(pinNumber-8));
+			inPinsB |= (1<<(pinNumber-8));
+		}
+		else
+		{
+			outPinsC |= (1<<(pinNumber-15));
+			inPinsC |= (1<<(pinNumber-15));
+		}
+	}
+	
+	else if(mode == BYNASE_NONE)
+	{
+		if(pinNumber < 8)
+		{
+			inPinsA &= (uint8_t)~(1<<pinNumber);
+			outPinsA &= (uint8_t)~(1<<pinNumber);
+		}
+		else if(pinNumber < 15)
+		{
+			inPinsB &= (uint8_t)~(1<<(pinNumber-8));
+			outPinsB &= (uint8_t)~(1<<(pinNumber-8));
+		}
+		else
+		{
+			inPinsC &= (uint8_t)~(1<<(pinNumber-15));
+			outPinsC &= (uint8_t)~(1<<(pinNumber-15));
+		}
+	}
+}
+
+void bynase_unregisterPin(uint8_t pinNumber)
+{
+	bynase_registerPin(pinNumber, BYNASE_NONE);
+}
+
+#if defined (__AVR_ATtiny84__)
+ISR(TIM1_OVF_vect)
+#elif defined(__AVR_ATmega8__)
+ISR(TIMER1_OVF_vect)
+#elif defined (__AVR_ATmega168__)
+ISR(TIMER1_OVF_vect)
+#elif defined (__AVR_ATmega328P__)
+ISR(TIMER1_OVF_vect)
+#endif
+{
+	uint8_t oldSREG = SREG;
+	cli();
+	if( (inPinsA | inPinsB | inPinsC) >0)
+	{
+		byin();
+	}
+	
+	if( (outPinsA |outPinsB | outPinsC) >0)
+	{
+		byout();
+	}
+	
+	TCNT1 = 0xFFFF - (255-timerSpeed);//count 255-timerspeed times from now on at 1Mhz 
+	TIFR1 = 0xFF;//clear all pending interrups for timer1
+	
+	// reenable interrupts.
+	SREG = oldSREG;
+}

+ 30 - 0
optiboot/cores/luminet/bynase.h

@@ -0,0 +1,30 @@
+#ifndef _BYNASE_H
+#define _BYNASE_H
+
+
+#include "WProgram.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+
+#define BYNASE_INPUT 0
+#define BYNASE_OUTPUT 1
+#define BYNASE_BOTH 2
+#define BYNASE_NONE 3
+
+void bynase_init(uint8_t speed);
+void byout(void);
+void byin(void);
+void bynase_write(uint8_t, uint8_t);
+uint8_t bynase_read(uint8_t);
+void bynase_registerPin(uint8_t pinNumber, uint8_t mode);
+void bynase_unregisterPin(uint8_t pinNumber);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif

BIN
optiboot/cores/luminet/cmd.exe.lnk


+ 72 - 0
optiboot/cores/luminet/digitalWriteASM.S

@@ -0,0 +1,72 @@
+#include <avr/io.h>
+
+#define	temp r17
+#define	temptwo r16
+#define pin r24
+#define value r22
+
+;***************************************************************************
+;*
+;* digitalWriteASM
+;* r24 is pin
+;* r22 is value
+;*
+.global digitalWriteASM
+.func digitalWriteASM
+digitalWriteASM:
+	ldi temptwo,0
+calcpin:
+	cpi pin,0
+	brne notPinZero
+	ldi pin,11
+notPinZero:
+	cpi pin,4
+	brlt isPortB
+isPortA:
+	subi pin,4
+	rjmp endcalcpin
+isPortB:
+	ldi temptwo,1
+	ldi temp,3
+	sub temp,pin
+	mov pin,temp
+endcalcpin:
+	nop
+calcmask:
+	ldi temp,1
+	cpi pin,0
+	breq endcalcmask
+shiftLeft:
+	lsl temp
+	dec pin
+	brne shiftLeft
+endcalcmask:
+	cpi temptwo,1
+	brne doitForA
+doitForB:
+	in temptwo, PORTB
+	cpi value,1
+	brne doandb
+	OR temptwo, temp
+	rjmp setb
+doandb:
+	com temp
+	AND temptwo,temp
+setb:
+	sts PORTB, temptwo
+	rjmp enddigitalwrite
+doitForA:
+	in temptwo, PORTA
+	cpi value,1
+	brne doanda
+	OR temptwo, temp
+	rjmp seta
+doanda:
+	com temp
+	AND temptwo,temp
+seta:
+	sts PORTA, temptwo
+enddigitalwrite:
+	ret
+.endfunc
+

+ 6 - 0
optiboot/cores/luminet/fastDigital.c

@@ -0,0 +1,6 @@
+#include "fastDigital.h"
+
+void fastDigitalWrite(uint8_t pin, uint8_t value)
+{
+	digitalWriteASM(pin, value);
+}

+ 20 - 0
optiboot/cores/luminet/fastDigital.h

@@ -0,0 +1,20 @@
+#ifndef _ASSEMBLERTEST_H_
+#define _ASSEMBLERTEST_H_
+
+#include "WProgram.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+extern void digitalWriteASM(uint8_t pin, uint8_t value);
+
+void fastDigitalWrite(uint8_t pin, uint8_t value);
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif /* _ASSEMBLERTEST_H_ */

+ 152 - 0
optiboot/cores/luminet/luminet.h

@@ -0,0 +1,152 @@
+#ifndef _LUMINET_H_
+#define _LUMINET_H_
+
+
+//#define IS_VECTOR_NODE 1
+
+//#define VECTOR_MESSAGE 0x04
+
+#define EEPROM_VECTOR_ADDRESS 228
+
+#include <avr/io.h>
+#include <avr/boot.h>
+#include <avr/pgmspace.h>
+#include <avr/interrupt.h>
+#include <util/delay_basic.h>
+
+
+//define this if you want to see the result of the topologyscan (blinking for each SNEW direction)
+#define SHOW_TOPOLOGY_RESULT 1
+
+#define MAX_PAGENUMBER 87
+
+#define PAYLOAD_FLASH_ADDRESS 0
+
+///////MAGIC KEYS
+#define START 0xA0
+#define RESET 0xA1
+#define DATA 0xB0
+#define RETRANSMISSION 0xB1
+#define END 0xC0
+
+#define RED_ON (PORTA  |= (1 << RED_LED) ) 
+#define RED_ON (PORTA  |= (1 << RED_LED) ) 
+#define GREEN_ON (PORTA  |= (1 << GREEN_LED) )
+#define BLUE_ON (PORTA  |= (1 << BLUE_LED) )
+
+#define RED_OFF (PORTA  &= ~(1 << RED_LED) ) 
+#define GREEN_OFF (PORTA  &= ~(1 << GREEN_LED) )
+#define BLUE_OFF (PORTA  &= ~(1 << BLUE_LED) )
+
+#define RED   (1<<PA4)
+#define GREEN (1<<PA5)
+#define BLUE  (1<<PA6)
+#define WHITE (RED | GREEN | BLUE)
+
+#define RED_LED PA4
+#define GREEN_LED PA5
+#define BLUE_LED PA6
+
+#define RED_ON (PORTA  |= (1 << RED_LED) ) 
+#define RED_ON (PORTA  |= (1 << RED_LED) ) 
+#define GREEN_ON (PORTA  |= (1 << GREEN_LED) )
+#define BLUE_ON (PORTA  |= (1 << BLUE_LED) )
+#define WHITE_ON (PORTA |= WHITE)
+
+#define RED_OFF (PORTA  &= ~(1 << RED_LED) ) 
+#define GREEN_OFF (PORTA  &= ~(1 << GREEN_LED) )
+#define BLUE_OFF (PORTA  &= ~(1 << BLUE_LED) )
+#define WHITE_OFF (PORTA &= ~WHITE)
+
+
+#define WEST 0
+#define EAST 1
+#define NORTH 2
+#define SOUTH 3
+#define DESTINATION_WEST 0
+#define DESTINATION_EAST 1
+#define DESTINATION_NORTH 2
+#define DESTINATION_SOUTH 3
+#define DESTINATION_GREEN 4
+#define DESTINATION_RED 5
+#define DESTINATION_BLUE 6
+
+
+#ifndef BOOTADR
+#define BOOTADR 0x1600
+#endif
+
+#define	LEFT_TXDDR DDRA
+#define	LEFT_TXPORT PORTA
+#define	LEFT_TXPIN PINA
+#define LEFT_TXPINNumber  PA2			
+		
+#define	LEFT_RXDDR  DDRA
+#define	LEFT_RXPORT PORTA
+#define	LEFT_RXPIN  PINA
+#define	LEFT_RXPINNumber PA3			
+
+#define	RIGHT_TXDDR DDRB
+#define	RIGHT_TXPORT PORTB
+#define	RIGHT_TXPIN PINB
+#define RIGHT_TXPINNumber  PB1			
+		
+#define	RIGHT_RXDDR  DDRB
+#define	RIGHT_RXPORT PORTB
+#define	RIGHT_RXPIN  PINB
+#define	RIGHT_RXPINNumber PB0			
+	
+
+#define	UP_TXDDR DDRB
+#define	UP_TXPORT PORTB
+#define	UP_TXPIN PINB
+#define UP_TXPINNumber  PB2			
+		
+#define	UP_RXDDR  DDRA
+#define	UP_RXPORT PORTA
+#define	UP_RXPIN  PINA
+#define	UP_RXPINNumber PA7
+
+#define	DOWN_TXDDR DDRA
+#define	DOWN_TXPORT PORTA
+#define	DOWN_TXPIN PINA
+#define DOWN_TXPINNumber  PA1			
+		
+#define	DOWN_RXDDR  DDRA
+#define	DOWN_RXPORT PORTA
+#define	DOWN_RXPIN  PINA
+#define	DOWN_RXPINNumber PA0			
+
+#define NORTH_TX (1<<PB2)
+#define NORTH_RX (1<<PA7)
+#define EAST_TX  (1<<PB1)
+#define EAST_RX  (1<<PB0)
+#define SOUTH_TX (1<<PA1)
+#define SOUTH_RX (1<<PA0)
+#define WEST_TX  (1<<PA2)
+#define WEST_RX  (1<<PA3)
+
+#define NORTH_LOW (PORTB &= ~NORTH_TX)
+#define  EAST_LOW (PORTB &= ~EAST_TX)
+#define SOUTH_LOW (PORTA &= ~SOUTH_TX)
+#define  WEST_LOW (PORTA &= ~WEST_TX)
+
+#define NORTH_HIGH (PORTB |= NORTH_TX)
+#define  EAST_HIGH (PORTB |= EAST_TX)
+#define SOUTH_HIGH (PORTA |= SOUTH_TX)
+#define  WEST_HIGH (PORTA |= WEST_TX)
+
+#define GET_NORTH (PINA & NORTH_RX)
+#define GET_EAST  (PINB & EAST_RX)
+#define GET_SOUTH (PINA & SOUTH_RX)
+#define GET_WEST  (PINA & WEST_RX)
+
+#define NORTH_PULLUP (PORTA |= NORTH_RX)
+#define EAST_PULLUP (PORTB |= EAST_RX)
+#define SOUTH_PULLUP (PORTA |= SOUTH_RX)
+#define WEST_PULLUP (PORTA |= WEST_RX)
+
+
+
+#endif
+

+ 39 - 0
optiboot/cores/luminet/main.cxx

@@ -0,0 +1,39 @@
+//void (*startBootloader)( void ) = (void(*)(void))(0x1600);
+
+
+
+
+int main(void)
+{
+	//startBootloader();
+	
+	
+	mainconnections = 0;
+	topology_scan(&mainconnections);//luminet needs to perform topology scan at the beginning of every payload
+	
+	//cli();
+	//CLKPR = (1 << CLKPCE);
+	//CLKPR = 0x00;//8MHz
+	
+		if(mainconnections >= 16)
+		{
+			//startBootloader();
+				__asm__ __volatile
+			 (
+			      "ldi r30,0x00"  "\n\t"
+			      "ldi r31,0x0b"  "\n\t"
+			      "icall" "\n\t"
+			 );
+		}
+	
+		
+	init();
+
+	setup();
+    
+	for (;;)
+		loop();
+        
+	return 0;
+}
+

+ 154 - 0
optiboot/cores/luminet/pins_arduino.c

@@ -0,0 +1,154 @@
+/*
+  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 522 2008-11-01 22:06:13Z mellis $
+*/
+
+#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.
+
+
+
+
+
+// Luminet board
+//                *   *
+//                D0  D1
+//						VCC PA7 PB2 GND
+//             |   |   |   |
+//             |   |   |   |
+//    VCC---                   ---VCC
+//D7  PA3---                   ---PB1  D2
+//D6  PA2---                   ---PB0  D3
+//    GND---                   ---GND
+//             |   |   |   |
+//             |   |   |   |
+//            VCC PA1 PA0 GND
+//                D5  D4
+//
+// red   led:   PA4 (d8) -- pin available if jumper is not connected
+// green led: * PA5 (d9)  -- pin available if jumper is not connected
+// blue  led: * PA6 (d10)  -- pin available if jumper is not connected
+// reset:       PB3 (d11)
+//
+// * indicates the PWM pins on the attiny84
+
+#define PA 2
+#define PB 3
+
+
+// these arrays map port names (e.g. port B) to the
+// appropriate addresses for various functions (e.g. reading
+// and writing)
+const uint8_t PROGMEM port_to_mode_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&DDRA,
+	&DDRB,
+};
+
+const uint8_t PROGMEM port_to_output_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&PORTA,
+	&PORTB,
+};
+
+const uint8_t PROGMEM port_to_input_PGM[] = {
+	NOT_A_PORT,
+	NOT_A_PORT,
+	&PINA,
+	&PINB,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
+	PA, /* 0 */
+	PB,
+	PB,
+	PB,
+	PA,
+	PA,
+	PA,
+	PA,
+	PA, /* 8 */
+	PA,
+	PA,
+	PB,
+	PA,
+	PA,
+	PA, /* 14 */
+	PA,
+	PA,
+	PA,
+	PA,
+	PA,
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = {
+	_BV(7), /* 0, port D */
+	_BV(2),
+	_BV(1),
+	_BV(0),
+	_BV(0),
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4), /* 8 */
+	_BV(5),
+	_BV(6),
+	_BV(3),
+	_BV(4),
+	_BV(6),
+	_BV(0), /* 14 */
+	_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,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	NOT_ON_TIMER, /* 8 - port B */
+	NOT_ON_TIMER,
+	NOT_ON_TIMER,
+	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,
+};
+

+ 65 - 0
optiboot/cores/luminet/pins_arduino.h

@@ -0,0 +1,65 @@
+/*
+  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
+
+extern const uint8_t PROGMEM port_to_mode_PGM[];
+extern const uint8_t PROGMEM port_to_input_PGM[];
+extern const uint8_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_byte( port_to_output_PGM + (P))) )
+#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) )
+#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) )
+
+#endif

+ 268 - 0
optiboot/cores/luminet/topology.c

@@ -0,0 +1,268 @@
+#include "topology.h"
+
+//#define BOOTADR 0x1600
+
+
+#ifndef EEPROM_VECTOR_ADDRESS
+#define EEPROM_VECTOR_ADDRESS 228
+#endif
+
+//void (*startBootloader)( void ) = (void *)BOOTADR;  // pointer to the bootloader start address
+
+//performs a topology scan and vector detection 
+//returns: connections variable: SNEWSNEW - first nibble is vector path, second nibble is connection indicator
+//this function only returns connections if no vector node is present
+//otherwise it loops forever, sending the vector_message
+void topology_scan(uint8_t *connections)
+{
+
+	uint16_t z;
+	//uint8_t connections;//bit7..0: SNEWSNEW - first nibble says: vector present, second says: normal neighbour present
+	
+	uint8_t c;
+	uint8_t d;
+	
+	uint8_t r;
+	
+	uint8_t destination;
+	
+	uint8_t address = EEPROM_VECTOR_ADDRESS;
+	
+	void (*ptr_putc) (uint8_t data);
+	uint8_t (*ptr_getc) (void);
+	
+	//CLKPR = 0x80;//set CLKPCE bit -> next step: set prescaler
+	//CLKPR = 0x02;//prescaler=2 --> 2MHz
+		
+	*connections = 0;
+
+	//activate outputs, rise pull-ups. set outputs to high level
+	DDRA = 0x76;
+	PORTA = 0x89;
+	DDRB= 0x06;
+	PORTB = 0x01;
+	
+	//OUTPUTS TO LOW
+	PORTA &= (uint8_t)~(0x06);
+	PORTB &= (uint8_t)~(0x06);
+	
+	
+	//say that the cable is ok, before we have a burning man...
+	RED_ON;
+	
+	
+  
+
+		
+		_delay_loop_2(62510); // 250ms
+   
+   
+   for(z=0;z<250;z++)//check for connections
+   {
+		if(! (PINA & (1<<PA3) ) )
+		{	
+			*connections |= (1 << WEST);
+		}
+		
+		if(! (PINA & (1<<PA7) ) )
+		{	
+			*connections |= (1 << NORTH);
+		}
+		
+		if(! (PINA & (1<<PA0) ) )
+		{	
+			*connections |= (1 << SOUTH);
+		}
+		
+		if(! (PINB & (1<<PB0) ) )
+		{	
+			*connections |= (1 << EAST);
+		}
+		_delay_loop_2(250); //1ms
+	}//loop: 250*1ms = 250ms
+
+   _delay_loop_2(62510); // 250ms
+	   
+	//OUTPUTS NOW HAVE BEEN LOW FOR 3*250ms = 750ms
+		
+		
+		#ifdef IS_VECTOR_NODE
+		//OUTPUTS TO LOW
+		PORTA &= (uint8_t)~(0x06);
+		PORTB &= (uint8_t)~(0x06);
+	#else 
+		//OUTPUTS HIGH
+		PORTA |= (0x06);
+		PORTB |= (0x06);
+		
+	#endif
+
+	   _delay_loop_2(62510); // 250ms
+	   _delay_loop_2(62510); // 250ms
+	   
+	   
+	   
+	#ifndef IS_VECTOR_NODE   
+	   	
+	   	for(z=0; z<500; z++)
+	   {
+		
+			if(! (PINA & (1<<PA3) ) )
+			{	
+				if(*connections & (1 << WEST) )
+				{
+					//REMAINING OUTPUTS TO LOW
+					PORTA &= (uint8_t)~(0x02);
+					PORTB &= (uint8_t)~(0x06);				
+					*connections |= (16 << WEST);
+				}
+			}
+			if(! (PINA & (1<<PA7) ) )
+			{	
+				if(*connections & (1 << NORTH) )
+				{			
+					//REMAINING OUTPUTS TO LOW
+					PORTA &= (uint8_t)~(0x06);
+					PORTB &= (uint8_t)~(0x02);
+					*connections |= (16 << NORTH);
+				}
+			}
+			if(! (PINA & (1<<PA0) ) )
+			{	
+				if(*connections & (1 << SOUTH) )
+				{				
+					//REMAINING OUTPUTS TO LOW
+					PORTA &= (uint8_t)~(0x04);
+					PORTB &= (uint8_t)~(0x06);					
+					*connections |= (16 << SOUTH);
+				}
+			}
+			if(! (PINB & (1<<PB0) ) )
+			{	
+				if(*connections & (1 << EAST) )
+				{							
+					//REMAINING OUTPUTS TO LOW
+					PORTA &= (uint8_t)~(0x06);
+					PORTB &= (uint8_t)~(0x04);
+					*connections |= (16 << EAST);
+				}
+			}
+		
+			_delay_loop_2(250); // 1ms
+		}
+		
+		
+		//only one vector path allowed
+		if(*connections & (16 << WEST) )
+		{
+			*connections &= (uint8_t)~(16 << SOUTH);
+			*connections &= (uint8_t)~(16 << NORTH);
+			*connections &= (uint8_t)~(16 << EAST);
+		}
+		else if(*connections & (16 << NORTH) )
+		{
+			*connections &= (uint8_t)~(16 << SOUTH);
+			*connections &= (uint8_t)~(16 << WEST);
+			*connections &= (uint8_t)~(16 << EAST);
+		}
+		else if(*connections & (16 << SOUTH) )
+		{
+			*connections &= (uint8_t)~(16 << NORTH);
+			*connections &= (uint8_t)~(16 << WEST);
+			*connections &= (uint8_t)~(16 << EAST);
+		}
+		else if(*connections & (16 << EAST) )
+		{
+			*connections &= (uint8_t)~(16 << SOUTH);
+			*connections &= (uint8_t)~(16 << WEST);
+			*connections &= (uint8_t)~(16 << NORTH);
+		}
+	   	
+		#else
+	   //Vector node does not loop so we have to add the 500ms loop duration here
+	   _delay_loop_2(62510); // 250ms
+	   _delay_loop_2(62510); // 250ms
+
+	#endif
+	
+	RED_OFF;
+	GREEN_OFF;
+	BLUE_OFF;
+
+		
+	   _delay_loop_2(62510); // 250ms
+	   _delay_loop_2(62510); // 250ms
+
+	//tx lines now have been HIGH (normal node) / LOW (vector node) for 1500ms
+
+		//tx lines high again
+		PORTA |= (0x06);
+		PORTB |= (0x06);
+			
+		_delay_loop_2(62510); // 250ms
+			
+		
+#ifdef SHOW_TOPOLOGY_RESULT
+		//show the result of the topology scan by blinking LEDs
+		for(z=0;z<4;z++)
+		{
+			if(*connections & (16 << z) )
+			{
+				BLUE_ON;//a connection to a node on the vector path
+				
+			}
+			else if(*connections & (1 << z) )
+			{
+				GREEN_ON;//a simple connection to another node
+			}
+			else
+			{
+				RED_ON;//no connection in this direction
+			}
+			
+			_delay_loop_2(62510); // 250ms
+			_delay_loop_2(62510); // 250ms
+			RED_OFF;
+			GREEN_OFF;
+			BLUE_OFF;
+		   _delay_loop_2(62510); // 250ms
+		   _delay_loop_2(62510); // 250ms
+		   	
+		}
+#endif
+	
+	//function only returns connections if no vector node is present
+	//otherwise it starts the bootloader
+	
+
+	eeprom_write_byte(address, *connections);//write vector message to eeprom
+	_delay_loop_2(400);
+	
+	if(*connections >=16)
+	{
+		cli();
+		//startBootloader();
+		//asm("call 0x1600");
+	}
+		
+
+
+
+}
+
+//If a vector is present, it sends a message to the vector path. This message is a single byte
+//the byte is stored in the eeprom at address 228 and returned by this function
+/*
+uint8_t topology_getVectorMessage(void)
+{
+	uint8_t *address = EEPROM_VECTOR_ADDRESS; //adress to read from
+	uint8_t data;
+	data = eeprom_read_byte(address);
+	return data;
+	
+	
+	
+
+
+}
+*/

+ 26 - 0
optiboot/cores/luminet/topology.h

@@ -0,0 +1,26 @@
+#ifndef _TOPOLOGY_H
+#define _TOPOLOGY_H
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+
+#include "luminet.h"
+
+
+//performs a topology scan and vector detection 
+//returns: connections variable: SNEWSNEW - first nibble is vector path, second nibble is connection indicator
+//example: 01000001 means: a vector path is in the north and so I have two connections: one in the West and one (the vector path connection) in the North
+void topology_scan(uint8_t*);
+
+//If a vector is present, it sends a message to the vector path. This message is a single byte
+//the byte is stored in the eeprom at address 228 and returned by this function
+//uint8_t topology_getVectorMessage(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
+

+ 224 - 0
optiboot/cores/luminet/wiring.c

@@ -0,0 +1,224 @@
+/*
+  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 539 2008-12-23 00:17:14Z mellis $
+*/
+
+#include "wiring_private.h"
+
+volatile unsigned long timer0_overflow_count = 0;
+volatile unsigned long timer0_clock_cycles = 0;
+volatile unsigned long timer0_millis = 0;
+
+//SIGNAL(TIM0_OVF_vect)
+ISR(TIM0_OVF_vect)
+{
+	timer0_overflow_count++;
+	// timer 0 prescale factor is 64 and the timer overflows at 256
+	timer0_clock_cycles += 64UL * 256UL;
+	while (timer0_clock_cycles > clockCyclesPerMicrosecond() * 1000UL) {
+		timer0_clock_cycles -= clockCyclesPerMicrosecond() * 1000UL;
+		timer0_millis++;
+	}
+}
+
+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 the timer0_millis++)
+	cli();
+	m = timer0_millis;
+	SREG = oldSREG;
+	
+	return m;
+}
+
+unsigned long micros() {
+	unsigned long m, t;
+	uint8_t oldSREG = SREG;
+	
+	cli();	
+	t = TCNT0;
+  
+#ifdef TIFR0
+	if ((TIFR0 & _BV(TOV0)) && (t == 0))
+		t = 256;
+#else
+	if ((TIFR & _BV(TOV0)) && (t == 0))
+		t = 256;
+#endif
+
+	m = timer0_overflow_count;
+	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. 
+ * Disables interrupts, which will disrupt the millis() function if used
+ * too frequently. */
+void delayMicroseconds(unsigned int us)
+{
+	uint8_t oldSREG;
+
+	// 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
+
+	// disable interrupts, otherwise the timer 0 overflow interrupt that
+	// tracks milliseconds will make us delay longer than we want.
+	oldSREG = SREG;
+	cli();
+
+	// busy wait
+	__asm__ __volatile__ (
+		"1: sbiw %0,1" "\n\t" // 2 cycles
+		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+	);
+
+	// reenable interrupts.
+	SREG = oldSREG;
+}
+
+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
+*/
+
+	// 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);
+	//luminet runs at 1MHz -> prescaler 8 for 125kHz
+	ADCSRA = ( (1 << ADPS1) | (1 << ADPS0) );
+
+	// enable a2d conversions
+	ADCSRA |= (1 << 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
+*/
+}

+ 134 - 0
optiboot/cores/luminet/wiring.h

@@ -0,0 +1,134 @@
+/*
+  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 534 2008-11-26 14:14:59Z mellis $
+*/
+
+#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.14159265
+#define HALF_PI 1.57079
+#define TWO_PI 6.283185
+#define DEG_TO_RAD 0.01745329
+#define RAD_TO_DEG 57.2957786
+
+#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) ((w) & 0xff)
+#define highByte(w) ((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) (1 << (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);
+void selectDirectionSerial(uint8_t);
+
+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

+ 184 - 0
optiboot/cores/luminet/wiring_analog.c

@@ -0,0 +1,184 @@
+/*
+  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 "bynase.h"
+
+#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;
+}
+
+/*
+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;
+}
+*/
+
+
+int analogRead(uint8_t pin)
+{
+	uint8_t low, high;
+	
+	
+	ADMUX = pin;
+	
+	if(pin == 0b100010)//temperature sensor
+	{
+		ADMUX |= 0x80; //enable 1,1V reference voltage
+	}
+	
+	// without a delay, we seem to read from the wrong channel
+	//_delay_loop_2(10000);
+
+	// start the first conversion
+	ADCSRA |= (1 << ADSC);
+
+	// ADSC is cleared when the conversion finishes
+	while (ADCSRA & (1 << ADSC))
+	{
+		asm volatile("nop");
+	}
+
+	// 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;
+	
+	//the first conversion should not be used...
+	
+	
+	/*
+	// start the second 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;
+	*/
+	
+	
+	
+	if(pin == 0b100010)//temperature sensor
+	{
+		ADMUX &= (uint8_t)~(0x80); //use VCC as reference voltage
+	}
+
+	// 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(val > 255)
+	{
+		val = _map(val, 0, 1023, 0, 100);
+	}
+	else
+	{
+  	val = _map(val, 0, 255, 0, 100);
+  }
+  */
+  
+	//luminet uses bynase for analog output. pwm is not used!
+	bynase_init(200);
+	bynase_registerPin(pin, BYNASE_OUTPUT);
+	bynase_write(pin, val);
+	
+	
+	/*
+	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;
+	} 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 (val < 128)
+		digitalWrite(pin, LOW);
+	else
+		digitalWrite(pin, HIGH);
+	*/
+	
+	
+	
+
+
+	
+		
+}

+ 93 - 0
optiboot/cores/luminet/wiring_digital.c

@@ -0,0 +1,93 @@
+/*
+  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 &= (uint8_t)~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);//timer1 used for bynase on luminet
+	//if (timer == TIMER1B) cbi(TCCR1A, COM1B1);//timer1 used for bynase on luminet
+	if (timer == TIMER0A) cbi(TCCR0A, COM0A1);
+	if (timer == TIMER0B) cbi(TCCR0A, COM0B1);
+	
+}
+
+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 &= (uint8_t)~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;
+}

+ 58 - 0
optiboot/cores/luminet/wiring_private.h

@@ -0,0 +1,58 @@
+/*
+  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_NUM_INTERRUPTS 2
+
+typedef void (*voidFuncPtr)(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif

+ 66 - 0
optiboot/cores/luminet/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); 
+}

+ 135 - 0
optiboot/cores/luminet/wiring_serial.c

@@ -0,0 +1,135 @@
+/*
+  wiring_serial.c - serial 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 "COM.h"
+#include "wiring_private.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//NOT SUPPORTED
+
+//unsigned char rx_buffer[RX_BUFFER_SIZE];//NOT SUPPORTED
+
+//int rx_buffer_head = 0;//NOT SUPPORTED
+//int rx_buffer_tail = 0;//NOT SUPPORTED
+
+///////////////////////////////////////////////////////////////////
+/// Luminet does not support hardware serial
+///////////////////////////////////////////////////////////////////
+
+	void (*ptr_putc) (uint8_t data);
+	uint8_t (*ptr_getc) (void);
+
+
+void beginSerial(long baud)
+{
+ //baud NOT SUPPORTED... always 9600baud at 1MHz
+ ptr_putc = LEFT_putc;
+ ptr_getc = LEFT_getc;
+ COM_init();
+}
+
+void selectDirectionSerial(uint8_t direction)
+{
+	if(direction == WEST)
+	{
+		ptr_putc = LEFT_putc;
+ 		ptr_getc = LEFT_getc;
+	}
+	else if(direction == EAST)
+	{
+		ptr_putc = RIGHT_putc;
+ 		ptr_getc = RIGHT_getc;
+	}
+	else if(direction == NORTH)
+	{
+		ptr_putc = UP_putc;
+ 		ptr_getc = UP_getc;
+	}
+	else if(direction == SOUTH)
+	{
+		ptr_putc = DOWN_putc;
+ 		ptr_getc = DOWN_getc;
+	}
+	
+}
+
+void serialWrite(unsigned char c)
+{
+	//NOT SUPPORTED
+	ptr_putc(c);
+}
+
+int serialAvailable()
+{
+	//NOT SUPPORTED
+	return 1;
+}
+
+int serialRead()
+{
+	//NOT SUPPORTED
+	return ptr_getc();
+}
+
+void serialFlush()
+{
+	// 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;
+}
+
+/*
+//NOT SUPPORTED
+
+#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
+
+	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[rx_buffer_head] = c;
+		rx_buffer_head = i;
+	}
+}
+*/

+ 40 - 0
optiboot/cores/luminet/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);		
+	}
+}

+ 67 - 0
optiboot/cores/sanguino/HardwareSerial.cpp

@@ -0,0 +1,67 @@
+/*
+  HarwareSerial.cpp - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+  
+  Modified 23 November 2006 by David A. Mellis
+  Modified 29 January 2009, Marius Kintel for Sanguino - http://www.sanguino.cc/
+*/
+
+#include "WProgram.h"
+
+#include "wiring.h"
+#include "HardwareSerial.h"
+
+// Constructors ////////////////////////////////////////////////////////////////
+
+HardwareSerial::HardwareSerial(uint8_t uart)
+  :_uart(uart)
+{
+}
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void HardwareSerial::begin(long speed)
+{
+  beginSerial(_uart, speed);
+}
+
+uint8_t HardwareSerial::available(void)
+{
+  return serialAvailable(_uart);
+}
+
+int HardwareSerial::read(void)
+{
+  return serialRead(_uart);
+}
+
+void HardwareSerial::flush()
+{
+  serialFlush(_uart);
+}
+
+void HardwareSerial::write(uint8_t b) {
+  serialWrite(_uart, b);
+}
+
+// Preinstantiate Objects //////////////////////////////////////////////////////
+
+HardwareSerial Serial = HardwareSerial(0);
+
+#if defined(__AVR_ATmega644P__)
+HardwareSerial Serial1 = HardwareSerial(1);
+#endif

+ 47 - 0
optiboot/cores/sanguino/HardwareSerial.h

@@ -0,0 +1,47 @@
+/*
+  HardwareSerial.h - Hardware serial library for Wiring
+  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.
+  Modified 29 January 2009, Marius Kintel for Sanguino - http://www.sanguino.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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef HardwareSerial_h
+#define HardwareSerial_h
+
+#include <inttypes.h>
+
+#include "Print.h"
+
+class HardwareSerial : public Print
+{
+ private:
+  uint8_t _uart;
+ public:
+  HardwareSerial(uint8_t uart);
+  void begin(long);
+  uint8_t available(void);
+  int read(void);
+  void flush(void);
+  virtual void write(uint8_t);
+};
+
+extern HardwareSerial Serial;
+
+#if defined(__AVR_ATmega644P__)
+extern HardwareSerial Serial1;
+#endif
+
+#endif

+ 243 - 0
optiboot/cores/sanguino/Makefile

@@ -0,0 +1,243 @@
+# Arduino 0011 Makefile
+# Arduino adaptation by mellis, eighthave, oli.keller
+#
+# This makefile allows you to build sketches from the command line
+# without the Arduino environment (or Java).
+#
+# Detailed instructions for using the makefile:
+#
+#  1. Copy this file into the folder with your sketch. There should be a
+#     file with the same name as the folder and with the extension .pde
+#     (e.g. foo.pde in the foo/ folder).
+#
+#  2. Modify the line containg "INSTALL_DIR" to point to the directory that
+#     contains the Arduino installation (for example, under Mac OS X, this
+#     might be /Applications/arduino-0012).
+#
+#  3. Modify the line containing "PORT" to refer to the filename
+#     representing the USB or serial connection to your Arduino board
+#     (e.g. PORT = /dev/tty.USB0).  If the exact name of this file
+#     changes, you can use * as a wildcard (e.g. PORT = /dev/tty.usb*).
+#
+#  4. Set the line containing "MCU" to match your board's processor. 
+#     Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
+#     or Diecimila have the atmega168.  If you're using a LilyPad Arduino,
+#     change F_CPU to 8000000.
+#
+#  5. At the command line, change to the directory containing your
+#     program's file and the makefile.
+#
+#  6. Type "make" and press enter to compile/verify your program.
+#
+#  7. Type "make upload", reset your Arduino board, and press enter to
+#     upload your program to the Arduino board.
+#
+# $Id$
+
+TARGET = $(notdir $(CURDIR))
+INSTALL_DIR = /Users/dmellis/Source/arduino/trunk/build/macosx/build/work
+PORT = /dev/tty.usb*
+UPLOAD_RATE = 19200
+AVRDUDE_PROGRAMMER = stk500v1
+MCU = atmega168
+F_CPU = 16000000
+
+############################################################################
+# Below here nothing should be changed...
+
+ARDUINO = $(INSTALL_DIR)/hardware/cores/arduino
+AVR_TOOLS_PATH = $(INSTALL_DIR)/hardware/tools/avr/bin
+SRC =  $(ARDUINO)/pins_arduino.c $(ARDUINO)/wiring.c \
+$(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \
+$(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_serial.c \
+$(ARDUINO)/wiring_shift.c $(ARDUINO)/WInterrupts.c
+CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp
+FORMAT = ihex
+
+
+# Name of this Makefile (used for "make depend").
+MAKEFILE = Makefile
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+
+OPT = s
+
+# Place -D or -U options here
+CDEFS = -DF_CPU=$(F_CPU)
+CXXDEFS = -DF_CPU=$(F_CPU)
+
+# Place -I options here
+CINCS = -I$(ARDUINO)
+CXXINCS = -I$(ARDUINO)
+
+# Compiler flag to set the C Standard level.
+# c89   - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99   - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+CDEBUG = -g$(DEBUG)
+CWARN = -Wall -Wstrict-prototypes
+CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
+
+CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
+CXXFLAGS = $(CDEFS) $(CINCS) -O$(OPT)
+#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 
+LDFLAGS = -lm
+
+
+# Programming support using avrdude. Settings and variables.
+AVRDUDE_PORT = $(PORT)
+AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
+AVRDUDE_FLAGS = -V -F -C $(INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf \
+-p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
+-b $(UPLOAD_RATE)
+
+# Program settings
+CC = $(AVR_TOOLS_PATH)/avr-gcc
+CXX = $(AVR_TOOLS_PATH)/avr-g++
+OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy
+OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump
+AR  = $(AVR_TOOLS_PATH)/avr-ar
+SIZE = $(AVR_TOOLS_PATH)/avr-size
+NM = $(AVR_TOOLS_PATH)/avr-nm
+AVRDUDE = $(AVR_TOOLS_PATH)/avrdude
+REMOVE = rm -f
+MV = mv -f
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) 
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
+ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+# Default target.
+all: applet_files build sizeafter
+
+build: elf hex 
+
+applet_files: $(TARGET).pde
+	# Here is the "preprocessing".
+	# It creates a .cpp file based with the same name as the .pde file.
+	# On top of the new .cpp file comes the WProgram.h header.
+	# At the end there is a generic main() function attached.
+	# Then the .cpp file will be compiled. Errors during compile will
+	# refer to this new, automatically generated, file. 
+	# Not the original .pde file you actually edit...
+	test -d applet || mkdir applet
+	echo '#include "WProgram.h"' > applet/$(TARGET).cpp
+	cat $(TARGET).pde >> applet/$(TARGET).cpp
+	cat $(ARDUINO)/main.cxx >> applet/$(TARGET).cpp
+
+elf: applet/$(TARGET).elf
+hex: applet/$(TARGET).hex
+eep: applet/$(TARGET).eep
+lss: applet/$(TARGET).lss 
+sym: applet/$(TARGET).sym
+
+# Program the device.  
+upload: applet/$(TARGET).hex
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
+
+
+	# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex
+ELFSIZE = $(SIZE)  applet/$(TARGET).elf
+sizebefore:
+	@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
+
+sizeafter:
+	@if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000 
+
+
+coff: applet/$(TARGET).elf
+	$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+	$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf $(TARGET).cof
+
+
+.SUFFIXES: .elf .hex .eep .lss .sym
+
+.elf.hex:
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+.elf.eep:
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+	--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+.elf.lss:
+	$(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+.elf.sym:
+	$(NM) -n $< > $@
+
+	# Link: create ELF output file from library.
+applet/$(TARGET).elf: $(TARGET).pde applet/core.a 
+	$(CC) $(ALL_CFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS)
+
+applet/core.a: $(OBJ)
+	@for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done
+
+
+
+# Compile: create object files from C++ source files.
+.cpp.o:
+	$(CXX) -c $(ALL_CXXFLAGS) $< -o $@ 
+
+# Compile: create object files from C source files.
+.c.o:
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
+
+
+# Compile: create assembler files from C source files.
+.c.s:
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+.S.o:
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean:
+	$(REMOVE) applet/$(TARGET).hex applet/$(TARGET).eep applet/$(TARGET).cof applet/$(TARGET).elf \
+	applet/$(TARGET).map applet/$(TARGET).sym applet/$(TARGET).lss applet/core.a \
+	$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
+
+depend:
+	if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
+	then \
+		sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
+			$(MAKEFILE).$$$$ && \
+		$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
+	fi
+	echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
+		>> $(MAKEFILE); \
+	$(CC) -M -mmcu=$(MCU) $(CDEFS) $(CINCS) $(SRC) $(ASRC) >> $(MAKEFILE)
+
+.PHONY:	all build elf hex eep lss sym program coff extcoff clean depend applet_files sizebefore sizeafter

+ 203 - 0
optiboot/cores/sanguino/Print.cpp

@@ -0,0 +1,203 @@
+/*
+ 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 <inttypes.h>
+#include <math.h>
+#include "wiring.h"
+
+#include "Print.h"
+
+// Public Methods //////////////////////////////////////////////////////////////
+
+void Print::print(uint8_t b)
+{
+  this->write(b);
+}
+
+void Print::print(char c)
+{
+  print((byte) c);
+}
+
+void Print::print(const char c[])
+{
+  while (*c)
+    print(*c++);
+}
+
+void Print::print(int n)
+{
+  print((long) n);
+}
+
+void Print::print(unsigned int n)
+{
+  print((unsigned long) n);
+}
+
+void Print::print(long n)
+{
+  if (n < 0) {
+    print('-');
+    n = -n;
+  }
+  printNumber(n, 10);
+}
+
+void Print::print(unsigned long n)
+{
+  printNumber(n, 10);
+}
+
+void Print::print(long n, int base)
+{
+  if (base == 0)
+    print((char) n);
+  else if (base == 10)
+    print(n);
+  else
+    printNumber(n, base);
+}
+
+void Print::print(double n)
+{
+  printFloat(n, 2);
+}
+
+void Print::println(void)
+{
+  print('\r');
+  print('\n');  
+}
+
+void Print::println(char c)
+{
+  print(c);
+  println();  
+}
+
+void Print::println(const char c[])
+{
+  print(c);
+  println();
+}
+
+void Print::println(uint8_t b)
+{
+  print(b);
+  println();
+}
+
+void Print::println(int n)
+{
+  print(n);
+  println();
+}
+
+void Print::println(unsigned int n)
+{
+  print(n);
+  println();
+}
+
+void Print::println(long n)
+{
+  print(n);
+  println();  
+}
+
+void Print::println(unsigned long n)
+{
+  print(n);
+  println();  
+}
+
+void Print::println(long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Print::println(double n)
+{
+  print(n);
+  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; 
+  } 
+}

+ 59 - 0
optiboot/cores/sanguino/Print.h

@@ -0,0 +1,59 @@
+/*
+  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>
+
+#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);
+    void print(char);
+    void print(const char[]);
+    void print(uint8_t);
+    void print(int);
+    void print(unsigned int);
+    void print(long);
+    void print(unsigned long);
+    void print(long, int);
+    void print(double);
+    void println(void);
+    void println(char);
+    void println(const char[]);
+    void println(uint8_t);
+    void println(int);
+    void println(unsigned int);
+    void println(long);
+    void println(unsigned long);
+    void println(long, int);
+    void println(double);
+};
+
+#endif

+ 515 - 0
optiboot/cores/sanguino/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/sanguino/WConstants.h

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

+ 87 - 0
optiboot/cores/sanguino/WInterrupts.c

@@ -0,0 +1,87 @@
+/* -*- 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;
+
+void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
+{
+	if(interruptNum < EXTERNAL_NUM_INTERRUPTS)
+	{
+		intFunc[interruptNum] = userFunc;
+
+		//clear the config for the change settings
+		EICRA &= ~(B00000011 << (interruptNum * 2));
+
+		//set our mode.
+		EICRA |= (mode << (interruptNum * 2));
+
+		// Enable the interrupt.
+		EIMSK |= (1 << interruptNum);
+	}
+}
+
+void detachInterrupt(uint8_t interruptNum)
+{
+	if(interruptNum < EXTERNAL_NUM_INTERRUPTS)
+	{
+		// Disable the interrupt.
+		EIMSK &= ~(1 << interruptNum);
+
+		intFunc[interruptNum] = 0;
+	}
+}
+
+ISR(INT0_vect) {
+  if(intFunc[EXTERNAL_INT_0])
+    intFunc[EXTERNAL_INT_0]();
+}
+
+ISR(INT1_vect) {
+  if(intFunc[EXTERNAL_INT_1])
+    intFunc[EXTERNAL_INT_1]();
+}
+
+ISR(INT2_vect) {
+  if(intFunc[EXTERNAL_INT_2])
+    intFunc[EXTERNAL_INT_2]();
+}
+
+/*
+SIGNAL(SIG_2WIRE_SERIAL) {
+  if(twiIntFunc)
+    twiIntFunc();
+}
+*/
+

+ 60 - 0
optiboot/cores/sanguino/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; }

+ 29 - 0
optiboot/cores/sanguino/WProgram.h

@@ -0,0 +1,29 @@
+#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);
+
+// WMath prototypes
+long random(long);
+long random(long, long);
+void randomSeed(unsigned int);
+long map(long, long, long, long, long);
+#endif
+
+#endif

+ 5 - 0
optiboot/cores/sanguino/_ReadMe.txt

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

+ 515 - 0
optiboot/cores/sanguino/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/sanguino/main.cpp

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

+ 12 - 0
optiboot/cores/sanguino/main.cxx

@@ -0,0 +1,12 @@
+int main(void)
+{
+	init();
+
+	setup();
+    
+	for (;;)
+		loop();
+        
+	return 0;
+}
+

+ 200 - 0
optiboot/cores/sanguino/pins_arduino.c

@@ -0,0 +1,200 @@
+/*
+  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 254 2007-04-20 23:17:38Z mellis $
+*/
+
+#include <avr/io.h>
+#include "wiring_private.h"
+#include "pins_arduino.h"
+
+// On the Sanguino board, digital pins are also used
+// for the analog output (software PWM).  Analog input
+// pins are a separate set.
+
+// ATMEL ATMEGA644P / SANGUINO
+//
+//                   +---\/---+
+//  INT0 (D 0) PB0  1|        |40  PA0 (AI 0 / D31)
+//  INT1 (D 1) PB1  2|        |39  PA1 (AI 1 / D30)
+//  INT2 (D 2) PB2  3|        |38  PA2 (AI 2 / D29)
+//   PWM (D 3) PB3  4|        |37  PA3 (AI 3 / D28)
+//   PWM (D 4) PB4  5|        |36  PA4 (AI 4 / D27)
+//  MOSI (D 5) PB5  6|        |35  PA5 (AI 5 / D26)
+//  MISO (D 6) PB6  7|        |34  PA6 (AI 6 / D25)
+//   SCK (D 7) PB7  8|        |33  PA7 (AI 7 / D24)
+//             RST  9|        |32  AREF
+//             VCC 10|        |31  GND 
+//             GND 11|        |30  AVCC
+//           XTAL2 12|        |29  PC7 (D 23)
+//           XTAL1 13|        |28  PC6 (D 22)
+//  RX0 (D 8)  PD0 14|        |27  PC5 (D 21) TDI
+//  TX0 (D 9)  PD1 15|        |26  PC4 (D 20) TDO
+//  RX1 (D 10) PD2 16|        |25  PC3 (D 19) TMS
+//  TX1 (D 11) PD3 17|        |24  PC2 (D 18) TCK
+//  PWM (D 12) PD4 18|        |23  PC1 (D 17) SDA
+//  PWM (D 13) PD5 19|        |22  PC0 (D 16) SCL
+//  PWM (D 14) PD6 20|        |21  PD7 (D 15) PWM
+//                   +--------+
+//
+
+#define PA 1
+#define PB 2
+#define PC 3
+#define PD 4
+
+// these arrays map port names (e.g. port B) to the
+// appropriate addresses for various functions (e.g. reading
+// and writing)
+const uint8_t PROGMEM port_to_mode_PGM[] =
+{
+	NOT_A_PORT,
+    &DDRA,
+	&DDRB,
+	&DDRC,
+	&DDRD,
+};
+
+const uint8_t PROGMEM port_to_output_PGM[] =
+{
+	NOT_A_PORT,
+	&PORTA,
+	&PORTB,
+	&PORTC,
+	&PORTD,
+};
+
+const uint8_t PROGMEM port_to_input_PGM[] =
+{
+	NOT_A_PORT,
+	&PINA,
+	&PINB,
+	&PINC,
+	&PIND,
+};
+
+const uint8_t PROGMEM digital_pin_to_port_PGM[] =
+{
+	PB, /* 0 */
+	PB,
+	PB,
+	PB,
+	PB,
+	PB,
+	PB,
+	PB,
+	PD, /* 8 */
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PD,
+	PC, /* 16 */
+	PC,
+	PC,
+	PC,
+	PC,
+	PC,
+   	PC,
+	PC,
+	PA, /* 24 */
+	PA,
+	PA,
+	PA,
+	PA,
+	PA,
+	PA,
+	PA  /* 31 */
+};
+
+const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
+{
+	_BV(0), /* 0, port B */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+	_BV(6),
+	_BV(7),
+	_BV(0), /* 8, port D */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+	_BV(6),
+	_BV(7),
+	_BV(0), /* 16, port C */
+	_BV(1),
+	_BV(2),
+	_BV(3),
+	_BV(4),
+	_BV(5),
+	_BV(6),
+	_BV(7),
+	_BV(7), /* 24, port A */
+	_BV(6),
+	_BV(5),
+	_BV(4),
+	_BV(3),
+	_BV(2),
+	_BV(1),
+	_BV(0)
+};
+
+const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
+{
+	NOT_ON_TIMER, 	/* 0  - PB0 */
+	NOT_ON_TIMER, 	/* 1  - PB1 */
+	NOT_ON_TIMER, 	/* 2  - PB2 */
+	TIMER0A,     	/* 3  - PB3 */
+	TIMER0B, 		/* 4  - PB4 */
+	NOT_ON_TIMER, 	/* 5  - PB5 */
+	NOT_ON_TIMER, 	/* 6  - PB6 */
+	NOT_ON_TIMER,	/* 7  - PB7 */
+	NOT_ON_TIMER, 	/* 8  - PD0 */
+	NOT_ON_TIMER, 	/* 9  - PD1 */
+	NOT_ON_TIMER, 	/* 10 - PD2 */
+	NOT_ON_TIMER, 	/* 11 - PD3 */
+	TIMER1B,     	/* 12 - PD4 */
+	TIMER1A,     	/* 13 - PD5 */
+	TIMER2B,     	/* 14 - PD6 */
+	TIMER2A,     	/* 15 - PD7 */
+	NOT_ON_TIMER, 	/* 16 - PC0 */
+	NOT_ON_TIMER,   /* 17 - PC1 */
+	NOT_ON_TIMER,   /* 18 - PC2 */
+	NOT_ON_TIMER,   /* 19 - PC3 */
+	NOT_ON_TIMER,   /* 20 - PC4 */
+	NOT_ON_TIMER,   /* 21 - PC5 */
+	NOT_ON_TIMER,   /* 22 - PC6 */
+	NOT_ON_TIMER,   /* 23 - PC7 */
+	NOT_ON_TIMER,   /* 24 - PA0 */
+	NOT_ON_TIMER,   /* 25 - PA1 */
+	NOT_ON_TIMER,   /* 26 - PA2 */
+	NOT_ON_TIMER,   /* 27 - PA3 */
+	NOT_ON_TIMER,   /* 28 - PA4 */
+	NOT_ON_TIMER,   /* 29 - PA5 */
+	NOT_ON_TIMER,   /* 30 - PA6 */
+	NOT_ON_TIMER   /* 31 - PA7 */
+};

+ 65 - 0
optiboot/cores/sanguino/pins_arduino.h

@@ -0,0 +1,65 @@
+/*
+  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
+
+extern const uint8_t PROGMEM port_to_mode_PGM[];
+extern const uint8_t PROGMEM port_to_input_PGM[];
+extern const uint8_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_byte( port_to_output_PGM + (P))) )
+#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_input_PGM + (P))) )
+#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_byte( port_to_mode_PGM + (P))) )
+
+#endif

+ 203 - 0
optiboot/cores/sanguino/wiring.c

@@ -0,0 +1,203 @@
+/*
+  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 388 2008-03-08 22:05:23Z mellis $
+*/
+
+#include "wiring_private.h"
+
+volatile unsigned long timer0_overflow_count = 0;
+volatile unsigned long timer0_clock_cycles = 0;
+volatile unsigned long timer0_millis = 0;
+
+SIGNAL(TIMER0_OVF_vect)
+{
+	timer0_overflow_count++;
+	// timer 0 prescale factor is 64 and the timer overflows at 256
+	timer0_clock_cycles += 64UL * 256UL;
+	while (timer0_clock_cycles > clockCyclesPerMicrosecond() * 1000UL) {
+		timer0_clock_cycles -= clockCyclesPerMicrosecond() * 1000UL;
+		timer0_millis++;
+	}
+}
+
+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 the timer0_millis++)
+	cli();
+	m = timer0_millis;
+	SREG = oldSREG;
+	
+	return m;
+}
+
+unsigned long micros() {
+	unsigned long m, t;
+	uint8_t oldSREG = SREG;
+	
+	cli();	
+	t = TCNT0;
+  
+#ifdef TIFR0
+	if ((TIFR0 & _BV(TOV0)) && (t == 0))
+		t = 256;
+#else
+	if ((TIFR & _BV(TOV0)) && (t == 0))
+		t = 256;
+#endif
+
+	m = timer0_overflow_count;
+	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. 
+ * Disables interrupts, which will disrupt the millis() function if used
+ * too frequently. */
+void delayMicroseconds(unsigned int us)
+{
+	uint8_t oldSREG;
+
+	// 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
+
+	// disable interrupts, otherwise the timer 0 overflow interrupt that
+	// tracks milliseconds will make us delay longer than we want.
+	oldSREG = SREG;
+	cli();
+
+	// busy wait
+	__asm__ __volatile__ (
+		"1: sbiw %0,1" "\n\t" // 2 cycles
+		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
+	);
+
+	// reenable interrupts.
+	SREG = oldSREG;
+}
+
+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)
+	sbi(TCCR0A, WGM01);
+	sbi(TCCR0A, WGM00);
+
+	// set timer 0 prescale factor to 64
+	sbi(TCCR0B, CS01);
+	sbi(TCCR0B, CS00);
+
+	// enable timer 0 overflow interrupt
+	sbi(TIMSK0, TOIE0);
+
+	// 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
+	sbi(TCCR2B, CS22);
+
+	// configure timer 2 for phase correct pwm (8-bit)
+	sbi(TCCR2A, WGM20);
+
+	// 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()
+	UCSR0B = 0;
+	#if defined(__AVR_ATmega644P__)
+	//TODO: test to see if disabling this helps?
+	//UCSR1B = 0;
+	#endif
+}

+ 133 - 0
optiboot/cores/sanguino/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 387 2008-03-08 21:30:00Z mellis $
+*/
+
+#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.14159265
+#define HALF_PI 1.57079
+#define TWO_PI 6.283185
+#define DEG_TO_RAD 0.01745329
+#define RAD_TO_DEG 57.2957786
+
+#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) ((w) & 0xff)
+#define highByte(w) ((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) (1 << (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(uint8_t, long);
+void serialWrite(uint8_t, unsigned char);
+int serialAvailable(uint8_t);
+int serialRead(uint8_t);
+void serialFlush(uint8_t);
+
+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

+ 116 - 0
optiboot/cores/sanguino/wiring_analog.c

@@ -0,0 +1,116 @@
+/*
+  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, ch = analogInPinToBit(pin);
+
+	// 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).
+	// the final AND is to clear the pos/neg reference bits
+	ADMUX = ((analog_reference << 6) | (pin & 0x0f)) & B11000111;
+
+	// 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;
+	} else if (digitalPinToTimer(pin) == TIMER0A) {
+		// connect pwm to pin on timer 0, channel A
+		sbi(TCCR0A, COM0A1);
+		// set pwm duty
+		OCR0A = val;	
+	} else if (digitalPinToTimer(pin) == TIMER0B) {
+		// 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;
+	} else if (val < 128)
+	//fail semi-intelligently
+		digitalWrite(pin, LOW);
+	else
+		digitalWrite(pin, HIGH);
+}

+ 95 - 0
optiboot/cores/sanguino/wiring_digital.c

@@ -0,0 +1,95 @@
+/*
+  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 == TIMER0A) cbi(TCCR0A, COM0A1);
+	if (timer == TIMER0B) cbi(TCCR0A, COM0B1);
+	if (timer == TIMER1A) cbi(TCCR1A, COM1A1);
+	if (timer == TIMER1B) cbi(TCCR1A, COM1B1);
+	if (timer == TIMER2A) cbi(TCCR2A, COM2A1);
+	if (timer == TIMER2B) cbi(TCCR2A, COM2B1);
+}
+
+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;
+}

+ 60 - 0
optiboot/cores/sanguino/wiring_private.h

@@ -0,0 +1,60 @@
+/*
+  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/signal.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_NUM_INTERRUPTS 3
+
+typedef void (*voidFuncPtr)(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif

+ 66 - 0
optiboot/cores/sanguino/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); 
+}

+ 138 - 0
optiboot/cores/sanguino/wiring_serial.c

@@ -0,0 +1,138 @@
+/*
+  wiring_serial.c - serial functions.
+  Part of Arduino - http://www.arduino.cc/
+
+  Copyright (c) 2005-2006 David A. Mellis
+  Modified 29 January 2009, Marius Kintel for Sanguino - http://www.sanguino.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: wiring.c 248 2007-02-03 15:36:30Z mellis $
+*/
+
+
+#include "wiring_private.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
+
+#if defined(__AVR_ATmega644P__)
+unsigned char rx_buffer[2][RX_BUFFER_SIZE];
+int rx_buffer_head[2] = {0, 0};
+int rx_buffer_tail[2] = {0, 0};
+#else
+unsigned char rx_buffer[1][RX_BUFFER_SIZE];
+int rx_buffer_head[1] = {0};
+int rx_buffer_tail[1] = {0};
+#endif
+
+
+#define BEGIN_SERIAL(uart_, baud_) \
+{ \
+    UBRR##uart_##H = ((F_CPU / 16 + baud / 2) / baud - 1) >> 8; \
+    UBRR##uart_##L = ((F_CPU / 16 + baud / 2) / baud - 1); \
+    \
+    /* reset config for UART */ \
+    UCSR##uart_##A = 0; \
+    UCSR##uart_##B = 0; \
+    UCSR##uart_##C = 0; \
+    \
+    /* enable rx and tx */ \
+    sbi(UCSR##uart_##B, RXEN##uart_);\
+    sbi(UCSR##uart_##B, TXEN##uart_);\
+    \
+    /* enable interrupt on complete reception of a byte */ \
+    sbi(UCSR##uart_##B, RXCIE##uart_); \
+    UCSR##uart_##C = _BV(UCSZ##uart_##1)|_BV(UCSZ##uart_##0); \
+    /* defaults to 8-bit, no parity, 1 stop bit */ \
+}
+
+void beginSerial(uint8_t uart, long baud)
+{
+  if (uart == 0) BEGIN_SERIAL(0, baud)
+#if defined(__AVR_ATmega644P__)
+  else BEGIN_SERIAL(1, baud)
+#endif
+}
+
+#define SERIAL_WRITE(uart_, c_) \
+    while (!(UCSR##uart_##A & (1 << UDRE##uart_))) \
+      ; \
+    UDR##uart_ = c
+
+void serialWrite(uint8_t uart, unsigned char c)
+{
+  if (uart == 0) {
+    SERIAL_WRITE(0, c);
+  }
+#if defined(__AVR_ATmega644P__)
+  else {
+    SERIAL_WRITE(1, c);
+  }
+#endif
+}
+
+int serialAvailable(uint8_t uart)
+{
+  return (RX_BUFFER_SIZE + rx_buffer_head[uart] - rx_buffer_tail[uart]) % RX_BUFFER_SIZE;
+}
+
+int serialRead(uint8_t uart)
+{
+  // if the head isn't ahead of the tail, we don't have any characters
+  if (rx_buffer_head[uart] == rx_buffer_tail[uart]) {
+    return -1;
+  } else {
+    unsigned char c = rx_buffer[uart][rx_buffer_tail[uart]];
+    rx_buffer_tail[uart] = (rx_buffer_tail[uart] + 1) % RX_BUFFER_SIZE;
+    return c;
+  }
+}
+
+void serialFlush(uint8_t uart)
+{
+  // 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[uart] = rx_buffer_tail[uart];
+}
+
+#define UART_ISR(uart_) \
+ISR(USART##uart_##_RX_vect) \
+{ \
+  unsigned char c = UDR##uart_; \
+  \
+  int i = (rx_buffer_head[uart_] + 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[uart_]) { \
+    rx_buffer[uart_][rx_buffer_head[uart_]] = c; \
+    rx_buffer_head[uart_] = i; \
+  } \
+}
+
+UART_ISR(0)
+#if defined(__AVR_ATmega644P__) 
+UART_ISR(1)
+#endif

+ 40 - 0
optiboot/cores/sanguino/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);		
+	}
+}