diff --git a/AS7/blinklib/blinklib/blinklib.atsln b/AS7/blinklib/blinklib/blinklib.atsln
new file mode 100644
index 00000000..8b333d66
--- /dev/null
+++ b/AS7/blinklib/blinklib/blinklib.atsln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Atmel Studio Solution File, Format Version 11.00
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "blinklib", "blinklib.cppproj", "{1D617D28-32B2-45AB-BA7F-EE884B221598}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|AVR = Debug|AVR
+ Release|AVR = Release|AVR
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1D617D28-32B2-45AB-BA7F-EE884B221598}.Debug|AVR.ActiveCfg = Debug|AVR
+ {1D617D28-32B2-45AB-BA7F-EE884B221598}.Debug|AVR.Build.0 = Debug|AVR
+ {1D617D28-32B2-45AB-BA7F-EE884B221598}.Release|AVR.ActiveCfg = Release|AVR
+ {1D617D28-32B2-45AB-BA7F-EE884B221598}.Release|AVR.Build.0 = Release|AVR
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/AS7/blinklib/blinklib/blinklib.cppproj b/AS7/blinklib/blinklib/blinklib.cppproj
index 2982acac..90e59cf1 100644
--- a/AS7/blinklib/blinklib/blinklib.cppproj
+++ b/AS7/blinklib/blinklib/blinklib.cppproj
@@ -181,6 +181,14 @@
compile
DummySerial.h
+
+ compile
+ gamestat.cpp
+
+
+ compile
+ gamestat.h
+ compile
main.cpp
diff --git a/Getting-started.md b/Getting-started.md
deleted file mode 100644
index 38ce3370..00000000
--- a/Getting-started.md
+++ /dev/null
@@ -1,66 +0,0 @@
-
-## Getting Started
-
-This core requires at least Arduino IDE v1.6.2, where v1.6.5+ is recommended.
-* [Programmers](#programmers)
-* **[How to install](#how-to-install)**
- - [Boards Manager Installation](#boards-manager-installation)
- - [Manual Installation](#manual-installation)
-* **[Getting started](#getting-started)**
-
-* **[Digging deeper](#digging-deeper)**
- - [Hardware Abstraction Layer](#hardware-abstraction-layer)
-
-## Programmers
-
-Since there is no bootloader in a tile, all code must be programmed rather than downloaded.
-
-Each Blink has a standard 6-pin ISP connector. The arrow marks pin #1.
-
-You can use any AVR programmer supported by AVRDUDE and the Arduino IDE.
-
-This one is cheap...
-http://amzn.to/2u5ZHw6
-
-This one is fast and comes with nice cables...
-http://amzn.to/2u5Wo7M
-
-Just connect your programmer and select it in the "Programmers" menu, and connect the 6-pin ISP to the tile. I like to use this pogo pin fixture to make the connections...
-
-https://www.sparkfun.com/products/11591
-
-...but you can also just hold a 6-pin header onto the tile, or solder on a 6-pin header if you want to leave the programmer attached.
-
-If you do not have a programmer, you can also use an Arduino and a couple of wires.
-
-You can then use the "Sketch-Upload to Programmer" menu choice or just press the Play button to compile your code and program it into the connected tile. (Both the menu option and the button do the same thing with a tile.)
-
-## How to install
-Click on the "Download ZIP" button in the upper right corner of this repo on Github...
-
-https://github.com/bigjosh/Move38-Arduino-Platform
-
-You can switch to the `dev` branch if you want to live on the bleeding edge and get new features quickly.
-
-Extract the ZIP file, and move the extracted files to the location "**~/Documents/Arduino/hardware/Move38-manual/avr**". Create the folder if it doesn't exist. This readme file should be located at "**~/Documents/Arduino/hardware/Move38-manual/avr/README.md**" when you are done.
-
-Open Arduino IDE, and a new category in the boards menu called "Move38-manual" will show up.
-
-##### Notes
-
-* We called the "vendor/maintainer" folder `Move38-manual` so that you can also use the boards manager and you will be able to tell the two apart in the boards menu.
-
-* You must manually create the `avr` folder and you must also manually move the files out from this repo into this folder. We could not automatically have the folds inside the repo match the Arduino required folder layout because in in the boards manager, the architecture is in the JSON file rather than the folder structure. Arg.
-
-* The "**~/Documents/Arduino/hardware/Move38-manual/avr**" folder is a Git repo and is also set up for easy editing in Atmel Studio with a solution inside the `\AS7` sub-folder.
-
-* If you want to leave the git repo in a directory that is not inside the Arduino tree (I do), then you can add a directory symlink from the Arduino tree to the repo tree. This repo needs to be at `arduino\hardware\move38\avr` where `arduino` is your Arduino home directory as set in `File->Preferences->Sketchbook Location` in the IDE. You have to manually create `hardware` and then `move38` and then put the `avr` symlink in then. On my windows machine the command for that was `D:\Documents\Arduino\hardware\move38\avr>mklink /D avr "D:\Github\Move38-Arduino-Platform"`
-
-## Helllo Blink!
-
-* Open the **Tools > Board** menu item, and select `Blink` from the `Move38` submenu.
-* Select what kind of programmer you're using under the **Programmers** menu.
-* Select "File->Examples->Examples for Blink->Getting Started" and choose "F-ColorWheel".
-* Hit the Play button.
-
-The IDE should compile the code and program the Blinks tile... and you should see pretty blinking lights!
diff --git a/Layers.md b/Layers.md
deleted file mode 100644
index 7887b605..00000000
--- a/Layers.md
+++ /dev/null
@@ -1,50 +0,0 @@
-## Layers
-
-### 1. Cold power up
-
-This typically only happens when a new battery is installed or when the foreground software locks up.
-
-The chip resets all the ports according to the the datasheet and then jumps to the reset vector, which typically points to the GCC bootstrap code. This code initializes global variables and does a bit of hardware setup.
-
-Here is an example on how to run code before the bootstrap (very esoteric)...
-
-https://github.com/bigjosh/Ognite-firmware/blob/master/Atmel%20Studio/Candle0005.c#L440
-
-### 2. main()
-
-After all the C setup is complete, the bootstrap jumps to the `main()` function. This function is in `cores/blinkcore/main.c`
-
-Here we...
-
-1. Initialize the binks hardware systems and turn them on.
-2. Jump to the `run()` function.
-3. Re-run `run()` forever if it returns.
-
-The blinks `main()` function is weakly defined, so you can make your own if you want to take over before the blinks hardware gets started up.
-
-### 3. run()
-
-Once all the hardware is up and running, then `run()` function takes over. This code lives in `libraries\blinklib\src\blinklib.cpp`.
-
-Here we...
-
-1. Call the user-supplied `setup()` function.
-2. Repeatedly...
- a. Clears the cached `millis()` snapshot
- b. Calls the user-suppled `loop()` function
- c. Atomically updates the values shown on the LEDs to match any changes made in `loop()`
- d. Processes new IR data that has been recieved, and potentially sends IR data.
-
-
-Then `run()` function is weakly defined, so you can override it if you want more control over these.
-
-### 4. `setup()` and `loop()`
-
-These are the idiomatic entry points provided by Arduino sketches.
-
-`setup()` is called once, typically right after a tile has had a battery change.
-
-`loop()` is called at the current frame rate, which is currently about 18 times per second. You `loop()` function should complete before the next frame starts, so should not have any blocking code in it. The tile sleeps for the time between when `loop()` returns and the next frame, so the faster you can complete your work and return from loop, the longer batteries will last.
-
-
-
\ No newline at end of file
diff --git a/Production.MD b/Production.MD
index 24bbbc62..91245bdf 100644
--- a/Production.MD
+++ b/Production.MD
@@ -8,6 +8,10 @@ Each virgin blink needs to be programmed with...
### Fuses
+#### ATMEGA168
+
+The only change from factory default is the fuse that enables jumping to the bootloader on reset (BOOTRST).
+
BOOTSZ = 1024W_1C00
BOOTRST = [X]
RSTDISBL = [ ]
@@ -26,6 +30,28 @@ LOW = 0x62 (valid)
Note that the `high` and `low` fuses are the same as their default values from the factory, but the `extended` fuse must be reprogrammed from the default value.
+#### ATMEGA328
+
+The only change from factory default is the fuse that enables jumping to the bootloader on reset (BOOTRST).
+
+BODLEVEL = DISABLED
+RSTDISBL = [ ]
+DWEN = [ ]
+SPIEN = [X]
+WDTON = [ ]
+EESAVE = [ ]
+BOOTSZ = 2048W_3800
+BOOTRST = [X]
+CKDIV8 = [X]
+CKOUT = [ ]
+SUT_CKSEL = INTRCOSC_8MHZ_6CK_14CK_65MS
+
+EXTENDED = 0xFF (valid)
+HIGH = 0xD8 (valid)
+LOW = 0x62 (valid)
+
+Note that the `extended` and `low` fuses are the same as their default values from the factory, but the `high` fuse must be reprogrammed from the default value.
+
### Bootloader
The bootloader code comes from a different repo and can be found in the [`bootloaders`](/bootloaders) directory here.
@@ -40,7 +66,7 @@ You can minimize the number of production programming steps by combining the app
### Example
-Here is and example command that will program a blink using the `AVRDUDE` utility and the `USBtiny` programmer...
+Here is and example command that will program a `atmega168pb` blink using the `AVRDUDE` utility and the `USBtiny` programmer...
```
avrdude -B 5 -v -patmega168pb -cusbtiny -Uflash:w:SKETCHNAME.ino.with_bootloader.standard.hex:i -Uefuse:w:0xf8:m -u
@@ -64,7 +90,7 @@ avrdude -B 4 -D -v -patmega168pb -cusbtiny -Uflash:w:D-TimerFlashX.ino.with_boot
```
`-D` skips erasing the flash before programming it. If you are programming virgin chips then the flash should be blank.
-`-B` lowered to 4 slightly increases the programmer clock. Some out of spec chips might fall to program at this speed.
+`-B` lowered to 4 slightly increases the programmer clock, which reduces programming time. Note that some units might fail at this increased speed.
Note that these new options are both safe because the verify will fail if anything goes wrong.
diff --git a/README.md b/README.md
index 2a8cb374..54191b7e 100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,65 @@
-# Move38 Blinks for the Arduino IDE
-An Arduino core for the Blinks gaming tile. More info at...
-http://move38.com
+# Blinks Software Development Kit (SDK) for Arduino
-## Roadmap
+This SDK includes all the software and configuration files to tell the Arduino IDE how to download programs in a blink along with some examples you can try out and modify.
-This core requires at least Arduino IDE v1.6.2, where v1.6.5+ is recommended.
-* [Programmers](#programmers)
-* **[How to install](#how-to-install)**
-* **[Getting started](#getting-started)**
+These instructions will get you set up to write your own games for the [Blinks platform](https://move38.com/pages/blinks-collection) using the Arduino IDE.
-Covers installing this repo so that you can write and download code into a Blinks tile using the Arduino IDE.
+Note that you do not need any of this if you just want to *play* blinks games, only if you want to write them.
-Ends with loading a `HelloBlink` program it a tile.
-### Writing games
+## Getting Started
-The best way to start writing games is to work your way though the examples in the "File->Examples->Examples for Blink Tile" menu in the Arduino IDE (after you have installed this repo as described in the Getting Started above).
-
+### Software setup
-### [Service Port](Service Port.MD)
+1. Download and run the latest version of the[ Arduino IDE](https://www.arduino.cc/en/Main/Software#download)
+2. Go into File->Preferences->Settings and add...
+`https://boardsmanager.com/package_move38.com-blinks_index.json`
+...under Additional Boards Manager URLs. If you already have something there, you can use a comma to separate the multiple entries
+3. Go to Tools->Board->Boards Manager and search for "blinks"
+4. Press install on "Blinks by Move38"
+5. Pick "Tools->Board->Move38->blink" from the menus
+5. Go to "File->Example->Getting Started->Button Press" to load an example program
+6. Program the `Button Press` example code into a blink (see below)
-Describes the service port connector on each blink. Lets you add `print` statements to your programs, which can be very helpful during development.
-## How to install
+### Getting your code programmed into a blink
-Click on the "Download ZIP" button in the upper right corner of this repo. Extract the ZIP file, and move the extracted files to the location "**~/Documents/Arduino/hardware/Move38-manual/avr**". Create the folder if it doesn't exist. This readme file should be located at "**~/Documents/Arduino/hardware/Move38-manual/avr/README.md**" when you are done.
+Each blink can hold a game in its on-board flash memory. Once a blink has a game programmed into it, it can also share to other blinks over the IR links.
-Open Arduino IDE, and a new category in the boards menu called "Move38-manual" will show up.
+You will need a programmer, a cable, and a connector to get your code from the Arduino IDE into a blink's flash.
+
+The [Blinks Developer Kit](https://move38.com/products/bare-bones-dev-kit) that includes everything you need to start programming your own games, including a a special blink that connects to an included USB programmer to make downloading your code as easy as pushing the "upload" button in the Ardunio IDE. If you have the dev kit, follow the enclosed instructions to select the correct programmer in the IDE and everything should just work.
+
+But you do not need the dev kit to write your own games. Blinks can be programmed with any Arduino-compatible "AVR ISP" programmer and there are hundreds of these available everywhere. You can even use an[ Arduino UNO board plus a few wires](https://www.arduino.cc/en/Tutorial/ArduinoISP#toc2) to program any blink though the 6-pin In System Programming (ISP) connector inside the battery compartment (the arrow marks pin #1).
-In the future, we'll offer a simplified Arduino Boards Manager install path.
+## What is Arduino?
-### Notes
+The Arduino IDE is an an integrated development environment that makes it easy to write and download code to compatible microcontroller boards - and every blink is an Arduino compatible board.
-* We called the "vendor/maintainer" folder `Move38-manual` so that you can also use the boards manager and you will be able to tell the two apart in the boards menu.
+We write a program in the IDE using Arduino programming language (basically the C/C++) and then we use a programmer to download the compiled program into a blink.
-* You must manually create the `avr` folder and you must also manually move the files out from this repo into this folder. We could not automatically have the folds inside the repo match the Arduino required folder layout because in in the boards manager, the architecture is in the JSON file rather than the folder structure. Arg.
+## The `blinklib` library
-* The "**~/Documents/Arduino/hardware/Move38-manual/avr**" folder is a Git repo and is also set up for easy editing in Atmel Studio with a solution inside the `\AS7` sub-folder.
+When you pick "blink" from the boards menu, you configure the Arduino IDE to automatically include a set of binks-specific functions whenever it compiles your code. You use these functions to set the colors on the blink's LEDs and check for button presses and send messages over the IR links and everything else a blink can do. You can see all the available `blinklib` functions [here](cores/blinklib/blinklib.h).
-### API Layers
+## Serial support
-The blinks hardware can do incredible things, and you can have unfettered access to it at any level you want. This documents describes those layers from bare metal up.
+Each blink also has a built in serial port so you can add `printf` statements to your code and view the resulting output on a computer running a serial terminal program. Again, each blink dev kit includes a cable and a USB serial board to make this plug and play, but you can also connect the wires yourself to any serial port than can accept 3.3 - 5 volt signals. More info on serial [here](Service Port.MD).
+## Making changes to the open source `blinklib` library
+You can make a fork of this repo and then clone it you the machine that you have the Arduino IDE installed on. Then add a symbolic link called `avr` to the top directory of the cloned repo (the directory with this readme in it) to the `Arduino/hardware/move38` directory. So, for example, on my windows machine I made the symbolic link with the commands...
-#### Hardware Abstraction Layer
+```
+d:
+cd D:\Documents\Arduino\hardware
+mkdir move38
+cd move38
+mklink /D avr D:\Github\Move38-Arduino-Platform
+```
-Most programmers will want to use the high level `blinks` API, but if you want to get closer to the hardware you can directly call into the `HAL` (Hardware Abstraction Layer) that the `blinks` API is built on top of. Documentation for this layer is in the [README.md](cores/blinkcore/README.md) in the `cores/blinkscore` folder.
+Quit out of the IDE and reload and you should see a new choice under the `boards` menu.
+
+We are always grateful for pull requests with bug fixes. For new features, best to discuss first [in the forums](https://forum.move38.com/c/softwareresources/9) to see what other think and if anyone is already working on something similar.
+
+###
diff --git a/Tools.md b/Tools.md
deleted file mode 100644
index f0bdaed0..00000000
--- a/Tools.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Tools
-## Programmers
-- Pocket AVR Programmer - [$14.95 on Sparkfun](https://www.sparkfun.com/products/9825)
-- ISP Pogo Adapter - [$9.95 on Sparkfun](https://www.sparkfun.com/products/11591)
-- ISP Pogo Adapter - [$6.50 on Tindie](https://www.tindie.com/products/madworm/tiny-avr-isp-pogo-pin-programming-adapter/)
diff --git a/avrdude.conf b/avrdude.conf
deleted file mode 100644
index efa18979..00000000
--- a/avrdude.conf
+++ /dev/null
@@ -1,2409 +0,0 @@
-# $Id: avrdude.conf.in 1371 2016-02-15 20:15:07Z joerg_wunsch $ -*- text -*-
-#
-# AVRDUDE Configuration File
-#
-# This file contains configuration data used by AVRDUDE which describes
-# the programming hardware pinouts and also provides part definitions.
-# AVRDUDE's "-C" command line option specifies the location of the
-# configuration file. The "-c" option names the programmer configuration
-# which must match one of the entry's "id" parameter. The "-p" option
-# identifies which part AVRDUDE is going to be programming and must match
-# one of the parts' "id" parameter.
-#
-# DO NOT MODIFY THIS FILE. Modifications will be overwritten the next
-# time a "make install" is run. For user-specific additions, use the
-# "-C +filename" commandline option.
-#
-# Possible entry formats are:
-#
-# programmer
-# parent # optional parent
-# id = [, [, ] ...] ; # are quoted strings
-# desc = ; # quoted string
-# type = ; # programmer type, quoted string
-# # supported programmer types can be listed by "-c ?type"
-# connection_type = parallel | serial | usb
-# baudrate = ; # baudrate for avr910-programmer
-# vcc = [, ... ] ; # pin number(s)
-# buff = [, ... ] ; # pin number(s)
-# reset = ; # pin number
-# sck = ; # pin number
-# mosi = ; # pin number
-# miso = ; # pin number
-# errled = ; # pin number
-# rdyled = ; # pin number
-# pgmled = ; # pin number
-# vfyled = ; # pin number
-# usbvid = ; # USB VID (Vendor ID)
-# usbpid = [, ...] # USB PID (Product ID) (1)
-# usbdev = ; # USB interface or other device info
-# usbvendor = ; # USB Vendor Name
-# usbproduct = ; # USB Product Name
-# usbsn = ; # USB Serial Number
-#
-# To invert a bit, use = ~ , the spaces are important.
-# For a pin list all pins must be inverted.
-# A single pin can be specified as usual = ~ , for lists
-# specify it as follows = ~ ( [, ... ] ) .
-#
-# (1) Not all programmer types can process a list of PIDs.
-# ;
-#
-# part
-# id = ; # quoted string
-# desc = ; # quoted string
-# has_jtag = ; # part has JTAG i/f
-# has_debugwire = ; # part has debugWire i/f
-# has_pdi = ; # part has PDI i/f
-# has_tpi = ; # part has TPI i/f
-# devicecode = ; # deprecated, use stk500_devcode
-# stk500_devcode = ; # numeric
-# avr910_devcode = ; # numeric
-# signature = ; # signature bytes
-# usbpid = ; # DFU USB PID
-# chip_erase_delay = ; # micro-seconds
-# reset = dedicated | io;
-# retry_pulse = reset | sck;
-# pgm_enable = ;
-# chip_erase = ;
-# chip_erase_delay = ; # chip erase delay (us)
-# # STK500 parameters (parallel programming IO lines)
-# pagel = ; # pin name in hex, i.e., 0xD7
-# bs2 = ; # pin name in hex, i.e., 0xA0
-# serial = ; # can use serial downloading
-# parallel = ; # can use par. programming
-# # STK500v2 parameters, to be taken from Atmel's XML files
-# timeout = ;
-# stabdelay = ;
-# cmdexedelay = ;
-# synchloops = ;
-# bytedelay = ;
-# pollvalue = ;
-# pollindex = ;
-# predelay = ;
-# postdelay = ;
-# pollmethod = ;
-# mode = ;
-# delay = ;
-# blocksize = ;
-# readsize = ;
-# hvspcmdexedelay = ;
-# # STK500v2 HV programming parameters, from XML
-# pp_controlstack = , , ...; # PP only
-# hvsp_controlstack = , , ...; # HVSP only
-# hventerstabdelay = ;
-# progmodedelay = ; # PP only
-# latchcycles = ;
-# togglevtg = ;
-# poweroffdelay = ;
-# resetdelayms = ;
-# resetdelayus = ;
-# hvleavestabdelay = ;
-# resetdelay = ;
-# synchcycles = ; # HVSP only
-# chiperasepulsewidth = ; # PP only
-# chiperasepolltimeout = ;
-# chiperasetime = ; # HVSP only
-# programfusepulsewidth = ; # PP only
-# programfusepolltimeout = ;
-# programlockpulsewidth = ; # PP only
-# programlockpolltimeout = ;
-# # JTAG ICE mkII parameters, also from XML files
-# allowfullpagebitstream = ;
-# enablepageprogramming = ;
-# idr = ; # IO addr of IDR (OCD) reg.
-# rampz = ; # IO addr of RAMPZ reg.
-# spmcr = ; # mem addr of SPMC[S]R reg.
-# eecr = ; # mem addr of EECR reg.
-# # (only when != 0x3c)
-# is_at90s1200 = ; # AT90S1200 part
-# is_avr32 = ; # AVR32 part
-#
-# memory
-# paged = ; # yes / no
-# size = ; # bytes
-# page_size = ; # bytes
-# num_pages = ; # numeric
-# min_write_delay = ; # micro-seconds
-# max_write_delay = ; # micro-seconds
-# readback_p1 = ; # byte value
-# readback_p2 = ; # byte value
-# pwroff_after_write = ; # yes / no
-# read = ;
-# write = ;
-# read_lo = ;
-# read_hi = ;
-# write_lo = ;
-# write_hi = ;
-# loadpage_lo = ;
-# loadpage_hi = ;
-# writepage = ;
-# ;
-# ;
-#
-# If any of the above parameters are not specified, the default value
-# of 0 is used for numerics or the empty string ("") for string
-# values. If a required parameter is left empty, AVRDUDE will
-# complain.
-#
-# Parts can also inherit parameters from previously defined parts
-# using the following syntax. In this case specified integer and
-# string values override parameter values from the parent part. New
-# memory definitions are added to the definitions inherited from the
-# parent.
-#
-# part parent # quoted string
-# id = ; # quoted string
-#
-# ;
-#
-# NOTES:
-# * 'devicecode' is the device code used by the STK500 (see codes
-# listed below)
-# * Not all memory types will implement all instructions.
-# * AVR Fuse bits and Lock bits are implemented as a type of memory.
-# * Example memory types are:
-# "flash", "eeprom", "fuse", "lfuse" (low fuse), "hfuse" (high
-# fuse), "signature", "calibration", "lock"
-# * The memory type specified on the avrdude command line must match
-# one of the memory types defined for the specified chip.
-# * The pwroff_after_write flag causes avrdude to attempt to
-# power the device off and back on after an unsuccessful write to
-# the affected memory area if VCC programmer pins are defined. If
-# VCC pins are not defined for the programmer, a message
-# indicating that the device needs a power-cycle is printed out.
-# This flag was added to work around a problem with the
-# at90s4433/2333's; see the at90s4433 errata at:
-#
-# http://www.atmel.com/dyn/resources/prod_documents/doc1280.pdf
-#
-# INSTRUCTION FORMATS
-#
-# Instruction formats are specified as a comma seperated list of
-# string values containing information (bit specifiers) about each
-# of the 32 bits of the instruction. Bit specifiers may be one of
-# the following formats:
-#
-# '1' = the bit is always set on input as well as output
-#
-# '0' = the bit is always clear on input as well as output
-#
-# 'x' = the bit is ignored on input and output
-#
-# 'a' = the bit is an address bit, the bit-number matches this bit
-# specifier's position within the current instruction byte
-#
-# 'aN' = the bit is the Nth address bit, bit-number = N, i.e., a12
-# is address bit 12 on input, a0 is address bit 0.
-#
-# 'i' = the bit is an input data bit
-#
-# 'o' = the bit is an output data bit
-#
-# Each instruction must be composed of 32 bit specifiers. The
-# instruction specification closely follows the instruction data
-# provided in Atmel's data sheets for their parts.
-#
-# See below for some examples.
-#
-#
-# The following are STK500 part device codes to use for the
-# "devicecode" field of the part. These came from Atmel's software
-# section avr061.zip which accompanies the application note
-# AVR061 available from:
-#
-# http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf
-#
-
-#define ATTINY10 0x10 /* the _old_ one that never existed! */
-#define ATTINY11 0x11
-#define ATTINY12 0x12
-#define ATTINY15 0x13
-#define ATTINY13 0x14
-
-#define ATTINY22 0x20
-#define ATTINY26 0x21
-#define ATTINY28 0x22
-#define ATTINY2313 0x23
-
-#define AT90S1200 0x33
-
-#define AT90S2313 0x40
-#define AT90S2323 0x41
-#define AT90S2333 0x42
-#define AT90S2343 0x43
-
-#define AT90S4414 0x50
-#define AT90S4433 0x51
-#define AT90S4434 0x52
-#define ATMEGA48 0x59
-
-#define AT90S8515 0x60
-#define AT90S8535 0x61
-#define AT90C8534 0x62
-#define ATMEGA8515 0x63
-#define ATMEGA8535 0x64
-
-#define ATMEGA8 0x70
-#define ATMEGA88 0x73
-#define ATMEGA168 0x86
-
-#define ATMEGA161 0x80
-#define ATMEGA163 0x81
-#define ATMEGA16 0x82
-#define ATMEGA162 0x83
-#define ATMEGA169 0x84
-
-#define ATMEGA323 0x90
-#define ATMEGA32 0x91
-
-#define ATMEGA64 0xA0
-
-#define ATMEGA103 0xB1
-#define ATMEGA128 0xB2
-#define AT90CAN128 0xB3
-#define AT90CAN64 0xB3
-#define AT90CAN32 0xB3
-
-#define AT86RF401 0xD0
-
-#define AT89START 0xE0
-#define AT89S51 0xE0
-#define AT89S52 0xE1
-
-# The following table lists the devices in the original AVR910
-# appnote:
-# |Device |Signature | Code |
-# +-------+----------+------+
-# |tiny12 | 1E 90 05 | 0x55 |
-# |tiny15 | 1E 90 06 | 0x56 |
-# | | | |
-# | S1200 | 1E 90 01 | 0x13 |
-# | | | |
-# | S2313 | 1E 91 01 | 0x20 |
-# | S2323 | 1E 91 02 | 0x48 |
-# | S2333 | 1E 91 05 | 0x34 |
-# | S2343 | 1E 91 03 | 0x4C |
-# | | | |
-# | S4414 | 1E 92 01 | 0x28 |
-# | S4433 | 1E 92 03 | 0x30 |
-# | S4434 | 1E 92 02 | 0x6C |
-# | | | |
-# | S8515 | 1E 93 01 | 0x38 |
-# | S8535 | 1E 93 03 | 0x68 |
-# | | | |
-# |mega32 | 1E 95 01 | 0x72 |
-# |mega83 | 1E 93 05 | 0x65 |
-# |mega103| 1E 97 01 | 0x41 |
-# |mega161| 1E 94 01 | 0x60 |
-# |mega163| 1E 94 02 | 0x64 |
-
-# Appnote AVR109 also has a table of AVR910 device codes, which
-# lists:
-# dev avr910 signature
-# ATmega8 0x77 0x1E 0x93 0x07
-# ATmega8515 0x3B 0x1E 0x93 0x06
-# ATmega8535 0x6A 0x1E 0x93 0x08
-# ATmega16 0x75 0x1E 0x94 0x03
-# ATmega162 0x63 0x1E 0x94 0x04
-# ATmega163 0x66 0x1E 0x94 0x02
-# ATmega169 0x79 0x1E 0x94 0x05
-# ATmega32 0x7F 0x1E 0x95 0x02
-# ATmega323 0x73 0x1E 0x95 0x01
-# ATmega64 0x46 0x1E 0x96 0x02
-# ATmega128 0x44 0x1E 0x97 0x02
-#
-# These codes refer to "BOOT" device codes which are apparently
-# different than standard device codes, for whatever reasons
-# (often one above the standard code).
-
-# There are several extended versions of AVR910 implementations around
-# in the Internet. These add the following codes (only devices that
-# actually exist are listed):
-
-# ATmega8515 0x3A
-# ATmega128 0x43
-# ATmega64 0x45
-# ATtiny26 0x5E
-# ATmega8535 0x69
-# ATmega32 0x72
-# ATmega16 0x74
-# ATmega8 0x76
-# ATmega169 0x78
-
-#
-# Overall avrdude defaults; suitable for ~/.avrduderc
-#
-default_parallel = "@DEFAULT_PAR_PORT@";
-default_serial = "@DEFAULT_SER_PORT@";
-# default_bitclock = 2.5;
-
-# Turn off safemode by default
-#default_safemode = no;
-
-
-#
-# PROGRAMMER DEFINITIONS
-#
-
-# http://wiring.org.co/
-# Basically STK500v2 protocol, with some glue to trigger the
-# bootloader.
-programmer
- id = "wiring";
- desc = "Wiring";
- type = "wiring";
- connection_type = serial;
-;
-
-programmer
- id = "arduino";
- desc = "Arduino";
- type = "arduino";
- connection_type = serial;
-;
-# this will interface with the chips on these programmers:
-#
-# http://real.kiev.ua/old/avreal/en/adapters
-# http://www.amontec.com/jtagkey.shtml, jtagkey-tiny.shtml
-# http://www.olimex.com/dev/arm-usb-ocd.html, arm-usb-tiny.html
-# http://www.ethernut.de/en/hardware/turtelizer/index.html
-# http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html
-# http://dangerousprototypes.com/docs/FT2232_breakout_board
-# http://www.ftdichip.com/Products/Modules/DLPModules.htm,DLP-2232*,DLP-USB1232H
-# http://flashrom.org/FT2232SPI_Programmer
-#
-# The drivers will look for a specific device and use the first one found.
-# If you have mulitple devices, then look for unique information (like SN)
-# And fill that in here.
-#
-# Note that the pin numbers for the main ISP signals (reset, sck,
-# mosi, miso) are fixed and cannot be changed, since they must match
-# the way the Multi-Protocol Synchronous Serial Engine (MPSSE) of
-# these FTDI ICs has been designed.
-
-programmer
- id = "avrftdi";
- desc = "FT2232D based generic programmer";
- type = "avrftdi";
- connection_type = usb;
- usbvid = 0x0403;
- usbpid = 0x6010;
- usbvendor = "";
- usbproduct = "";
- usbdev = "A";
- usbsn = "";
-#ISP-signals - lower ADBUS-Nibble (default)
- reset = 3;
- sck = 0;
- mosi = 1;
- miso = 2;
-#LED SIGNALs - higher ADBUS-Nibble
-# errled = 4;
-# rdyled = 5;
-# pgmled = 6;
-# vfyled = 7;
-#Buffer Signal - ACBUS - Nibble
-# buff = 8;
-;
-# This is an implementation of the above with a buffer IC (74AC244) and
-# 4 LEDs directly attached, all active low.
-programmer
- id = "2232HIO";
- desc = "FT2232H based generic programmer";
- type = "avrftdi";
- connection_type = usb;
- usbvid = 0x0403;
-# Note: This PID is reserved for generic H devices and
-# should be programmed into the EEPROM
-# usbpid = 0x8A48;
- usbpid = 0x6010;
- usbdev = "A";
- usbvendor = "";
- usbproduct = "";
- usbsn = "";
-#ISP-signals
- reset = 3;
- sck = 0;
- mosi = 1;
- miso = 2;
- buff = ~4;
-#LED SIGNALs
- errled = ~ 11;
- rdyled = ~ 14;
- pgmled = ~ 13;
- vfyled = ~ 12;
-;
-
-#The FT4232H can be treated as FT2232H, but it has a different USB
-#device ID of 0x6011.
-programmer parent "avrftdi"
- id = "4232h";
- desc = "FT4232H based generic programmer";
- usbpid = 0x6011;
-;
-
-programmer
- id = "jtagkey";
- desc = "Amontec JTAGKey, JTAGKey-Tiny and JTAGKey2";
- type = "avrftdi";
- connection_type = usb;
- usbvid = 0x0403;
-# Note: This PID is used in all JTAGKey variants
- usbpid = 0xCFF8;
- usbdev = "A";
- usbvendor = "";
- usbproduct = "";
- usbsn = "";
-#ISP-signals => 20 - Pin connector on JTAGKey
- reset = 3; # TMS 7 violet
- sck = 0; # TCK 9 white
- mosi = 1; # TDI 5 green
- miso = 2; # TDO 13 orange
- buff = ~4;
-# VTG VREF 1 brown with red tip
-# GND GND 20 black
-# The colors are on the 20 pin breakout cable
-# from Amontec
-;
-
-# UM232H module from FTDI and Glyn.com.au.
-# See helix.air.net.au for detailed usage information.
-# J1: Connect pin 2 and 3 for USB power.
-# J2: Connect pin 2 and 3 for USB power.
-# J2: Pin 7 is SCK
-# : Pin 8 is MOSI
-# : Pin 9 is MISO
-# : Pin 11 is RST
-# : Pin 6 is ground
-# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get
-# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant.
-programmer
- id = "UM232H";
- desc = "FT232H based module from FTDI and Glyn.com.au";
- type = "avrftdi";
- usbvid = 0x0403;
-# Note: This PID is reserved for generic 232H devices and
-# should be programmed into the EEPROM
- usbpid = 0x6014;
- usbdev = "A";
- usbvendor = "";
- usbproduct = "";
- usbsn = "";
-#ISP-signals
- sck = 0;
- mosi = 1;
- miso = 2;
- reset = 3;
-;
-
-# C232HM module from FTDI and Glyn.com.au.
-# : Orange is SCK
-# : Yellow is MOSI
-# : Green is MISO
-# : Brown is RST
-# : Black is ground
-# Use the -b flag to set the SPI clock rate eg -b 3750000 is the fastest I could get
-# a 16MHz Atmega1280 to program reliably. The 232H is conveniently 5V tolerant.
-programmer
- id = "C232HM";
- desc = "FT232H based module from FTDI and Glyn.com.au";
- type = "avrftdi";
- usbvid = 0x0403;
-# Note: This PID is reserved for generic 232H devices and
-# should be programmed into the EEPROM
- usbpid = 0x6014;
- usbdev = "A";
- usbvendor = "";
- usbproduct = "";
- usbsn = "";
-#ISP-signals
- sck = 0;
- mosi = 1;
- miso = 2;
- reset = 3;
-;
-
-
-# On the adapter you can read "O-Link". On the PCB is printed "OpenJTAG v3.1"
-# You can find it as "OpenJTAG ARM JTAG USB" in the internet.
-# (But there are also several projects called Open JTAG, eg.
-# http://www.openjtag.org, which are completely different.)
-# http://www.100ask.net/shop/english.html (website seems to be outdated)
-# http://item.taobao.com/item.htm?id=1559277013
-# http://www.micro4you.com/store/openjtag-arm-jtag-usb.html (schematics!)
-# some other sources which call it O-Link
-# http://www.andahammer.com/olink/
-# http://www.developmentboard.net/31-o-link-debugger.html
-# http://armwerks.com/catalog/o-link-debugger-copy/
-# or just have a look at ebay ...
-# It is basically the same entry as jtagkey with different usb ids.
-programmer parent "jtagkey"
- id = "o-link";
- desc = "O-Link, OpenJTAG from www.100ask.net";
- usbvid = 0x1457;
- usbpid = 0x5118;
- usbvendor = "www.100ask.net";
- usbproduct = "USB<=>JTAG&RS232";
-;
-
-# http://wiki.openmoko.org/wiki/Debug_Board_v3
-programmer
- id = "openmoko";
- desc = "Openmoko debug board (v3)";
- type = "avrftdi";
- usbvid = 0x1457;
- usbpid = 0x5118;
- usbdev = "A";
- usbvendor = "";
- usbproduct = "";
- usbsn = "";
- reset = 3; # TMS 7
- sck = 0; # TCK 9
- mosi = 1; # TDI 5
- miso = 2; # TDO 13
-;
-
-# Only Rev. A boards.
-# Schematic and user manual: http://www.cs.put.poznan.pl/wswitala/download/pdf/811EVBK.pdf
-programmer
- id = "lm3s811";
- desc = "Luminary Micro LM3S811 Eval Board (Rev. A)";
- type = "avrftdi";
- connection_type = usb;
- usbvid = 0x0403;
- usbpid = 0xbcd9;
- usbvendor = "LMI";
- usbproduct = "LM3S811 Evaluation Board";
- usbdev = "A";
- usbsn = "";
-#ISP-signals - lower ACBUS-Nibble (default)
- reset = 3;
- sck = 0;
- mosi = 1;
- miso = 2;
-# Enable correct buffers
- buff = 7;
-;
-
-# submitted as bug #46020
-programmer
- id = "tumpa";
- desc = "TIAO USB Multi-Protocol Adapter";
- type = "avrftdi";
- connection_type = usb;
- usbvid = 0x0403;
- usbpid = 0x8A98;
- usbdev = "A";
- usbvendor = "TIAO";
- usbproduct = "";
- usbsn = "";
- sck = 0; # TCK 9
- mosi = 1; # TDI 5
- miso = 2; # TDO 13
- reset = 3; # TMS 7
-;
-
-programmer
- id = "avrisp";
- desc = "Atmel AVR ISP";
- type = "stk500";
- connection_type = serial;
-;
-
-programmer
- id = "avrispv2";
- desc = "Atmel AVR ISP V2";
- type = "stk500v2";
- connection_type = serial;
-;
-
-programmer
- id = "avrispmkII";
- desc = "Atmel AVR ISP mkII";
- type = "stk500v2";
- connection_type = usb;
-;
-
-programmer parent "avrispmkII"
- id = "avrisp2";
-;
-
-programmer
- id = "buspirate";
- desc = "The Bus Pirate";
- type = "buspirate";
- connection_type = serial;
-;
-
-programmer
- id = "buspirate_bb";
- desc = "The Bus Pirate (bitbang interface, supports TPI)";
- type = "buspirate_bb";
- connection_type = serial;
- # pins are bits in bitbang byte (numbers are 87654321)
- # 1|POWER|PULLUP|AUX|MOSI|CLK|MISO|CS
- reset = 1;
- sck = 3;
- mosi = 4;
- miso = 2;
- #vcc = 7; This is internally set independent of this setting.
-;
-
-# This is supposed to be the "default" STK500 entry.
-# Attempts to select the correct firmware version
-# by probing for it. Better use one of the entries
-# below instead.
-programmer
- id = "stk500";
- desc = "Atmel STK500";
- type = "stk500generic";
- connection_type = serial;
-;
-
-programmer
- id = "stk500v1";
- desc = "Atmel STK500 Version 1.x firmware";
- type = "stk500";
- connection_type = serial;
-;
-
-programmer
- id = "mib510";
- desc = "Crossbow MIB510 programming board";
- type = "stk500";
- connection_type = serial;
-;
-
-programmer
- id = "stk500v2";
- desc = "Atmel STK500 Version 2.x firmware";
- type = "stk500v2";
- connection_type = serial;
-;
-
-programmer
- id = "stk500pp";
- desc = "Atmel STK500 V2 in parallel programming mode";
- type = "stk500pp";
- connection_type = serial;
-;
-
-programmer
- id = "stk500hvsp";
- desc = "Atmel STK500 V2 in high-voltage serial programming mode";
- type = "stk500hvsp";
- connection_type = serial;
-;
-
-programmer
- id = "stk600";
- desc = "Atmel STK600";
- type = "stk600";
- connection_type = usb;
-;
-
-programmer
- id = "stk600pp";
- desc = "Atmel STK600 in parallel programming mode";
- type = "stk600pp";
- connection_type = usb;
-;
-
-programmer
- id = "stk600hvsp";
- desc = "Atmel STK600 in high-voltage serial programming mode";
- type = "stk600hvsp";
- connection_type = usb;
-;
-
-programmer
- id = "avr910";
- desc = "Atmel Low Cost Serial Programmer";
- type = "avr910";
- connection_type = serial;
-;
-
-programmer
- id = "ft245r";
- desc = "FT245R Synchronous BitBang";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 1; # D1
- sck = 0; # D0
- mosi = 2; # D2
- reset = 4; # D4
-;
-
-programmer
- id = "ft232r";
- desc = "FT232R Synchronous BitBang";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 1; # RxD
- sck = 0; # TxD
- mosi = 2; # RTS
- reset = 4; # DTR
-;
-
-# see http://www.bitwizard.nl/wiki/index.php/FTDI_ATmega
-programmer
- id = "bwmega";
- desc = "BitWizard ftdi_atmega builtin programmer";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 5; # DSR
- sck = 6; # DCD
- mosi = 3; # CTS
- reset = 7; # RI
-;
-
-# see http://www.geocities.jp/arduino_diecimila/bootloader/index_en.html
-# Note: pins are numbered from 1!
-programmer
- id = "arduino-ft232r";
- desc = "Arduino: FT232R connected to ISP";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 3; # CTS X3(1)
- sck = 5; # DSR X3(2)
- mosi = 6; # DCD X3(3)
- reset = 7; # RI X3(4)
-;
-
-# website mentioned above uses this id
-programmer parent "arduino-ft232r"
- id = "diecimila";
- desc = "alias for arduino-ft232r";
-;
-
-# There is a ATmega328P kit PCB called "uncompatino".
-# This board allows ISP via its on-board FT232R.
-# This is designed like Arduino Duemilanove but has no standard ICPS header.
-# Its 4 pairs of pins are shorted to enable ftdi_syncbb.
-# http://akizukidenshi.com/catalog/g/gP-07487/
-# http://akizukidenshi.com/download/ds/akizuki/k6096_manual_20130816.pdf
-programmer
- id = "uncompatino";
- desc = "uncompatino with all pairs of pins shorted";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 3; # cts
- sck = 5; # dsr
- mosi = 6; # dcd
- reset = 7; # ri
-;
-
-# FTDI USB to serial cable TTL-232R-5V with a custom adapter for ICSP
-# http://www.ftdichip.com/Products/Cables/USBTTLSerial.htm
-# http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_TTL-232R_CABLES.pdf
-# For ICSP pinout see for example http://www.atmel.com/images/doc2562.pdf
-# (Figure 1. ISP6PIN header pinout and Table 1. Connections required for ISP ...)
-# TTL-232R GND 1 Black -> ICPS GND (pin 6)
-# TTL-232R CTS 2 Brown -> ICPS MOSI (pin 4)
-# TTL-232R VCC 3 Red -> ICPS VCC (pin 2)
-# TTL-232R TXD 4 Orange -> ICPS RESET (pin 5)
-# TTL-232R RXD 5 Yellow -> ICPS SCK (pin 3)
-# TTL-232R RTS 6 Green -> ICPS MISO (pin 1)
-# Except for VCC and GND, you can connect arbitual pairs as long as
-# the following table is adjusted.
-programmer
- id = "ttl232r";
- desc = "FTDI TTL232R-5V with ICSP adapter";
- type = "ftdi_syncbb";
- connection_type = usb;
- miso = 2; # rts
- sck = 1; # rxd
- mosi = 3; # cts
- reset = 0; # txd
-;
-
-programmer
- id = "usbasp";
- desc = "USBasp, http://www.fischl.de/usbasp/";
- type = "usbasp";
- connection_type = usb;
- usbvid = 0x16C0; # VOTI
- usbpid = 0x05DC; # Obdev's free shared PID
- usbvendor = "www.fischl.de";
- usbproduct = "USBasp";
-
- # following variants are autodetected for id "usbasp"
-
- # original usbasp from fischl.de
- # see above "usbasp"
-
- # old usbasp from fischl.de
- #usbvid = 0x03EB; # ATMEL
- #usbpid = 0xC7B4; # (unoffical) USBasp
- #usbvendor = "www.fischl.de";
- #usbproduct = "USBasp";
-
- # NIBObee (only if -P nibobee is given on command line)
- # see below "nibobee"
-;
-
-programmer
- id = "nibobee";
- desc = "NIBObee";
- type = "usbasp";
- connection_type = usb;
- usbvid = 0x16C0; # VOTI
- usbpid = 0x092F; # NIBObee PID
- usbvendor = "www.nicai-systems.com";
- usbproduct = "NIBObee";
-;
-
-programmer
- id = "usbasp-clone";
- desc = "Any usbasp clone with correct VID/PID";
- type = "usbasp";
- connection_type = usb;
- usbvid = 0x16C0; # VOTI
- usbpid = 0x05DC; # Obdev's free shared PID
- #usbvendor = "";
- #usbproduct = "";
-;
-
-programmer
- id = "usbtiny";
- desc = "USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/";
- type = "usbtiny";
- connection_type = usb;
- usbvid = 0x1781;
- usbpid = 0x0c9f;
-;
-
-programmer
- id = "butterfly";
- desc = "Atmel Butterfly Development Board";
- type = "butterfly";
- connection_type = serial;
-;
-
-programmer
- id = "arduinoisporg";
- desc = "Arduino ISP Programmer";
- type = "usbtiny";
- connection_type = usb;
- usbvid = 0x2A03;
- usbpid = 0x0049;
-;
-
-programmer
- id = "avr109";
- desc = "Atmel AppNote AVR109 Boot Loader";
- type = "butterfly";
- connection_type = serial;
-;
-
-programmer
- id = "avr911";
- desc = "Atmel AppNote AVR911 AVROSP";
- type = "butterfly";
- connection_type = serial;
-;
-
-# suggested in http://forum.mikrokopter.de/topic-post48317.html
-programmer
- id = "mkbutterfly";
- desc = "Mikrokopter.de Butterfly";
- type = "butterfly_mk";
- connection_type = serial;
-;
-
-programmer parent "mkbutterfly"
- id = "butterfly_mk";
-;
-
-programmer
- id = "jtagmkI";
- desc = "Atmel JTAG ICE (mkI)";
- baudrate = 115200; # default is 115200
- type = "jtagmki";
- connection_type = serial;
-;
-
-# easier to type
-programmer parent "jtagmkI"
- id = "jtag1";
-;
-
-# easier to type
-programmer parent "jtag1"
- id = "jtag1slow";
- baudrate = 19200;
-;
-
-# The JTAG ICE mkII has both, serial and USB connectivity. As it is
-# mostly used through USB these days (AVR Studio 5 only supporting it
-# that way), we make connection_type = usb the default. Users are
-# still free to use a serial port with the -P option.
-
-programmer
- id = "jtagmkII";
- desc = "Atmel JTAG ICE mkII";
- baudrate = 19200; # default is 19200
- type = "jtagmkii";
- connection_type = usb;
-;
-
-# easier to type
-programmer parent "jtagmkII"
- id = "jtag2slow";
-;
-
-# JTAG ICE mkII @ 115200 Bd
-programmer parent "jtag2slow"
- id = "jtag2fast";
- baudrate = 115200;
-;
-
-# make the fast one the default, people will love that
-programmer parent "jtag2fast"
- id = "jtag2";
-;
-
-# JTAG ICE mkII in ISP mode
-programmer
- id = "jtag2isp";
- desc = "Atmel JTAG ICE mkII in ISP mode";
- baudrate = 115200;
- type = "jtagmkii_isp";
- connection_type = usb;
-;
-
-# JTAG ICE mkII in debugWire mode
-programmer
- id = "jtag2dw";
- desc = "Atmel JTAG ICE mkII in debugWire mode";
- baudrate = 115200;
- type = "jtagmkii_dw";
- connection_type = usb;
-;
-
-# JTAG ICE mkII in AVR32 mode
-programmer
- id = "jtagmkII_avr32";
- desc = "Atmel JTAG ICE mkII im AVR32 mode";
- baudrate = 115200;
- type = "jtagmkii_avr32";
- connection_type = usb;
-;
-
-# JTAG ICE mkII in AVR32 mode
-programmer
- id = "jtag2avr32";
- desc = "Atmel JTAG ICE mkII im AVR32 mode";
- baudrate = 115200;
- type = "jtagmkii_avr32";
- connection_type = usb;
-;
-
-# JTAG ICE mkII in PDI mode
-programmer
- id = "jtag2pdi";
- desc = "Atmel JTAG ICE mkII PDI mode";
- baudrate = 115200;
- type = "jtagmkii_pdi";
- connection_type = usb;
-;
-
-# AVR Dragon in JTAG mode
-programmer
- id = "dragon_jtag";
- desc = "Atmel AVR Dragon in JTAG mode";
- baudrate = 115200;
- type = "dragon_jtag";
- connection_type = usb;
-;
-
-# AVR Dragon in ISP mode
-programmer
- id = "dragon_isp";
- desc = "Atmel AVR Dragon in ISP mode";
- baudrate = 115200;
- type = "dragon_isp";
- connection_type = usb;
-;
-
-# AVR Dragon in PP mode
-programmer
- id = "dragon_pp";
- desc = "Atmel AVR Dragon in PP mode";
- baudrate = 115200;
- type = "dragon_pp";
- connection_type = usb;
-;
-
-# AVR Dragon in HVSP mode
-programmer
- id = "dragon_hvsp";
- desc = "Atmel AVR Dragon in HVSP mode";
- baudrate = 115200;
- type = "dragon_hvsp";
- connection_type = usb;
-;
-
-# AVR Dragon in debugWire mode
-programmer
- id = "dragon_dw";
- desc = "Atmel AVR Dragon in debugWire mode";
- baudrate = 115200;
- type = "dragon_dw";
- connection_type = usb;
-;
-
-# AVR Dragon in PDI mode
-programmer
- id = "dragon_pdi";
- desc = "Atmel AVR Dragon in PDI mode";
- baudrate = 115200;
- type = "dragon_pdi";
- connection_type = usb;
-;
-
-
-programmer
- id = "xplainedpro";
- desc = "Atmel AVR XplainedPro in JTAG mode";
- type = "jtagice3";
- connection_type = usb;
- usbpid = 0x2111;
-;
-
-
-programmer
- id = "atmelice_pdi";
- desc = "Atmel-ICE (ARM/AVR) in PDI mode";
- type = "jtagice3_pdi";
- connection_type = usb;
- usbpid = 0x2141;
-;
-
-programmer
- id = "atmelice_dw";
- desc = "Atmel-ICE (ARM/AVR) in debugWIRE mode";
- type = "jtagice3_dw";
- connection_type = usb;
- usbpid = 0x2141;
-;
-
-programmer
- id = "atmelice_isp";
- desc = "Atmel-ICE (ARM/AVR) in ISP mode";
- type = "jtagice3_isp";
- connection_type = usb;
- usbpid = 0x2141;
-;
-
-
-programmer
- id = "pavr";
- desc = "Jason Kyle's pAVR Serial Programmer";
- type = "avr910";
- connection_type = serial;
-;
-
-programmer
- id = "pickit2";
- desc = "MicroChip's PICkit2 Programmer";
- type = "pickit2";
- connection_type = usb;
-;
-
-
-programmer
- id = "stk200";
- desc = "STK200";
- type = "par";
- connection_type = parallel;
- buff = 4, 5;
- sck = 6;
- mosi = 7;
- reset = 9;
- miso = 10;
-;
-
-# The programming dongle used by the popular Ponyprog
-# utility. It is almost similar to the STK200 one,
-# except that there is a LED indicating that the
-# programming is currently in progress.
-
-programmer parent "stk200"
- id = "pony-stk200";
- desc = "Pony Prog STK200";
- pgmled = 8;
-;
-
-programmer
- id = "dt006";
- desc = "Dontronics DT006";
- type = "par";
- connection_type = parallel;
- reset = 4;
- sck = 5;
- mosi = 2;
- miso = 11;
-;
-
-programmer parent "dt006"
- id = "bascom";
- desc = "Bascom SAMPLE programming cable";
-;
-
-programmer
- id = "alf";
- desc = "Nightshade ALF-PgmAVR, http://nightshade.homeip.net/";
- type = "par";
- connection_type = parallel;
- vcc = 2, 3, 4, 5;
- buff = 6;
- reset = 7;
- sck = 8;
- mosi = 9;
- miso = 10;
- errled = 1;
- rdyled = 14;
- pgmled = 16;
- vfyled = 17;
-;
-
-programmer
- id = "sp12";
- desc = "Steve Bolt's Programmer";
- type = "par";
- connection_type = parallel;
- vcc = 4,5,6,7,8;
- reset = 3;
- sck = 2;
- mosi = 9;
- miso = 11;
-;
-
-programmer
- id = "picoweb";
- desc = "Picoweb Programming Cable, http://www.picoweb.net/";
- type = "par";
- connection_type = parallel;
- reset = 2;
- sck = 3;
- mosi = 4;
- miso = 13;
-;
-
-programmer
- id = "abcmini";
- desc = "ABCmini Board, aka Dick Smith HOTCHIP";
- type = "par";
- connection_type = parallel;
- reset = 4;
- sck = 3;
- mosi = 2;
- miso = 10;
-;
-
-programmer
- id = "futurlec";
- desc = "Futurlec.com programming cable.";
- type = "par";
- connection_type = parallel;
- reset = 3;
- sck = 2;
- mosi = 1;
- miso = 10;
-;
-
-
-# From the contributor of the "xil" jtag cable:
-# The "vcc" definition isn't really vcc (the cable gets its power from
-# the programming circuit) but is necessary to switch one of the
-# buffer lines (trying to add it to the "buff" lines doesn't work in
-# avrdude versions before 5.5j).
-# With this, TMS connects to RESET, TDI to MOSI, TDO to MISO and TCK
-# to SCK (plus vcc/gnd of course)
-programmer
- id = "xil";
- desc = "Xilinx JTAG cable";
- type = "par";
- connection_type = parallel;
- mosi = 2;
- sck = 3;
- reset = 4;
- buff = 5;
- miso = 13;
- vcc = 6;
-;
-
-
-programmer
- id = "dapa";
- desc = "Direct AVR Parallel Access cable";
- type = "par";
- connection_type = parallel;
- vcc = 3;
- reset = 16;
- sck = 1;
- mosi = 2;
- miso = 11;
-;
-
-programmer
- id = "atisp";
- desc = "AT-ISP V1.1 programming cable for AVR-SDK1 from micro-research.co.th";
- type = "par";
- connection_type = parallel;
- reset = ~6;
- sck = ~8;
- mosi = ~7;
- miso = ~10;
-;
-
-programmer
- id = "ere-isp-avr";
- desc = "ERE ISP-AVR ";
- type = "par";
- connection_type = parallel;
- reset = ~4;
- sck = 3;
- mosi = 2;
- miso = 10;
-;
-
-programmer
- id = "blaster";
- desc = "Altera ByteBlaster";
- type = "par";
- connection_type = parallel;
- sck = 2;
- miso = 11;
- reset = 3;
- mosi = 8;
- buff = 14;
-;
-
-# It is almost same as pony-stk200, except vcc on pin 5 to auto
-# disconnect port (download on http://electropol.free.fr/spip/spip.php?article27)
-programmer parent "pony-stk200"
- id = "frank-stk200";
- desc = "Frank STK200";
- buff = ; # delete buff pin assignment
- vcc = 5;
-;
-
-
-#This programmer bitbangs GPIO lines using the Linux sysfs GPIO interface
-#
-#To enable it set the configuration below to match the GPIO lines connected to the
-#relevant ISP header pins and uncomment the entry definition. In case you don't
-#have the required permissions to edit this system wide config file put the
-#entry in a separate .conf file and use it with -C+.conf
-#on the command line.
-#
-#To check if your avrdude build has support for the linuxgpio programmer compiled in,
-#use -c?type on the command line and look for linuxgpio in the list. If it's not available
-#you need pass the --enable-linuxgpio=yes option to configure and recompile avrdude.
-#
-#programmer
-# id = "linuxgpio";
-# desc = "Use the Linux sysfs interface to bitbang GPIO lines";
-# type = "linuxgpio";
-# reset = ?;
-# sck = ?;
-# mosi = ?;
-# miso = ?;
-#;
-
-# some ultra cheap programmers use bitbanging on the
-# serialport.
-#
-# PC - DB9 - Pins for RS232:
-#
-# GND 5 -- |O
-# | O| <- 9 RI
-# DTR 4 <- |O |
-# | O| <- 8 CTS
-# TXD 3 <- |O |
-# | O| -> 7 RTS
-# RXD 2 -> |O |
-# | O| <- 6 DSR
-# DCD 1 -> |O
-#
-# Using RXD is currently not supported.
-# Using RI is not supported under Win32 but is supported under Posix.
-
-# serial ponyprog design (dasa2 in uisp)
-# reset=!txd sck=rts mosi=dtr miso=cts
-
-programmer
- id = "ponyser";
- desc = "design ponyprog serial, reset=!txd sck=rts mosi=dtr miso=cts";
- type = "serbb";
- connection_type = serial;
- reset = ~3;
- sck = 7;
- mosi = 4;
- miso = 8;
-;
-
-# Same as above, different name
-# reset=!txd sck=rts mosi=dtr miso=cts
-
-programmer parent "ponyser"
- id = "siprog";
- desc = "Lancos SI-Prog ";
-;
-
-# unknown (dasa in uisp)
-# reset=rts sck=dtr mosi=txd miso=cts
-
-programmer
- id = "dasa";
- desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts";
- type = "serbb";
- connection_type = serial;
- reset = 7;
- sck = 4;
- mosi = 3;
- miso = 8;
-;
-
-# unknown (dasa3 in uisp)
-# reset=!dtr sck=rts mosi=txd miso=cts
-
-programmer
- id = "dasa3";
- desc = "serial port banging, reset=!dtr sck=rts mosi=txd miso=cts";
- type = "serbb";
- connection_type = serial;
- reset = ~4;
- sck = 7;
- mosi = 3;
- miso = 8;
-;
-
-# C2N232i (jumper configuration "auto")
-# reset=dtr sck=!rts mosi=!txd miso=!cts
-
-programmer
- id = "c2n232i";
- desc = "serial port banging, reset=dtr sck=!rts mosi=!txd miso=!cts";
- type = "serbb";
- connection_type = serial;
- reset = 4;
- sck = ~7;
- mosi = ~3;
- miso = ~8;
-;
-
-#
-# PART DEFINITIONS
-#
-
-
-#------------------------------------------------------------
-# ATmega8
-#------------------------------------------------------------
-
-part
- id = "m8";
- desc = "ATmega8";
- stk500_devcode = 0x70;
- avr910_devcode = 0x76;
- signature = 0x1e 0x93 0x07;
- pagel = 0xd7;
- bs2 = 0xc2;
- chip_erase_delay = 10000;
- pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
- "x x x x x x x x x x x x x x x x";
-
- chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
- "x x x x x x x x x x x x x x x x";
-
- timeout = 200;
- stabdelay = 100;
- cmdexedelay = 25;
- synchloops = 32;
- bytedelay = 0;
- pollindex = 3;
- pollvalue = 0x53;
- predelay = 1;
- postdelay = 1;
- pollmethod = 0;
-
- pp_controlstack =
- 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
- 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
- 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
- 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
- hventerstabdelay = 100;
- progmodedelay = 0;
- latchcycles = 5;
- togglevtg = 1;
- poweroffdelay = 15;
- resetdelayms = 2;
- resetdelayus = 0;
- hvleavestabdelay = 15;
- resetdelay = 15;
- chiperasepulsewidth = 0;
- chiperasepolltimeout = 10;
- programfusepulsewidth = 0;
- programfusepolltimeout = 5;
- programlockpulsewidth = 0;
- programlockpolltimeout = 5;
-
- memory "eeprom"
- size = 512;
- page_size = 4;
- min_write_delay = 9000;
- max_write_delay = 9000;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read = " 1 0 1 0 0 0 0 0",
- " 0 0 x x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- write = " 1 1 0 0 0 0 0 0",
- " 0 0 x x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- mode = 0x04;
- delay = 20;
- blocksize = 128;
- readsize = 256;
- ;
- memory "flash"
- paged = yes;
- size = 8192;
- page_size = 64;
- num_pages = 128;
- min_write_delay = 4500;
- max_write_delay = 4500;
- readback_p1 = 0xff;
- readback_p2 = 0x00;
- read_lo = " 0 0 1 0 0 0 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- read_hi = " 0 0 1 0 1 0 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- loadpage_lo = " 0 1 0 0 0 0 0 0",
- " 0 0 0 0 x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_hi = " 0 1 0 0 1 0 0 0",
- " 0 0 0 0 x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- writepage = " 0 1 0 0 1 1 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 x x x x x",
- " x x x x x x x x";
-
- mode = 0x21;
- delay = 10;
- blocksize = 64;
- readsize = 256;
- ;
-
- memory "lfuse"
- size = 1;
- min_write_delay = 2000;
- max_write_delay = 2000;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "hfuse"
- size = 1;
- min_write_delay = 2000;
- max_write_delay = 2000;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "efuse"
- size = 0;
- ;
-
- memory "lock"
- size = 1;
- min_write_delay = 2000;
- max_write_delay = 2000;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x x x o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
- "x x x x x x x x 1 1 i i i i i i";
- ;
-
- memory "calibration"
- size = 4;
- read = "0 0 1 1 1 0 0 0 0 0 x x x x x x",
- "0 0 0 0 0 0 a1 a0 o o o o o o o o";
- ;
-
- memory "signature"
- size = 3;
- read = "0 0 1 1 0 0 0 0 x x x x x x x x",
- "x x x x x x a1 a0 o o o o o o o o";
- ;
- ;
-
-
-#------------------------------------------------------------
-# ATmega48
-#------------------------------------------------------------
-
-part
- id = "m48";
- desc = "ATmega48";
- has_debugwire = yes;
- flash_instr = 0xB6, 0x01, 0x11;
- eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
- 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
- 0x99, 0xF9, 0xBB, 0xAF;
- stk500_devcode = 0x59;
-# avr910_devcode = 0x;
- signature = 0x1e 0x92 0x05;
- pagel = 0xd7;
- bs2 = 0xc2;
- chip_erase_delay = 45000;
- pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
- "x x x x x x x x x x x x x x x x";
-
- chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
- "x x x x x x x x x x x x x x x x";
-
- timeout = 200;
- stabdelay = 100;
- cmdexedelay = 25;
- synchloops = 32;
- bytedelay = 0;
- pollindex = 3;
- pollvalue = 0x53;
- predelay = 1;
- postdelay = 1;
- pollmethod = 1;
-
- pp_controlstack =
- 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
- 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
- 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
- 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
- hventerstabdelay = 100;
- progmodedelay = 0;
- latchcycles = 5;
- togglevtg = 1;
- poweroffdelay = 15;
- resetdelayms = 1;
- resetdelayus = 0;
- hvleavestabdelay = 15;
- resetdelay = 15;
- chiperasepulsewidth = 0;
- chiperasepolltimeout = 10;
- programfusepulsewidth = 0;
- programfusepolltimeout = 5;
- programlockpulsewidth = 0;
- programlockpolltimeout = 5;
-
- ocdrev = 1;
-
- memory "eeprom"
- paged = no;
- page_size = 4;
- size = 256;
- min_write_delay = 3600;
- max_write_delay = 3600;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read = " 1 0 1 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- write = " 1 1 0 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_lo = " 1 1 0 0 0 0 0 1",
- " 0 0 0 0 0 0 0 0",
- " 0 0 0 0 0 0 a1 a0",
- " i i i i i i i i";
-
- writepage = " 1 1 0 0 0 0 1 0",
- " 0 0 x x x x x x",
- " a7 a6 a5 a4 a3 a2 0 0",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 20;
- blocksize = 4;
- readsize = 256;
- ;
- memory "flash"
- paged = yes;
- size = 4096;
- page_size = 64;
- num_pages = 64;
- min_write_delay = 4500;
- max_write_delay = 4500;
- readback_p1 = 0x00;
- readback_p2 = 0x00;
- read_lo = " 0 0 1 0 0 0 0 0",
- " 0 0 0 0 0 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- read_hi = " 0 0 1 0 1 0 0 0",
- " 0 0 0 0 0 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- loadpage_lo = " 0 1 0 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_hi = " 0 1 0 0 1 0 0 0",
- " 0 0 0 x x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- writepage = " 0 1 0 0 1 1 0 0",
- " 0 0 0 0 0 a10 a9 a8",
- " a7 a6 a5 x x x x x",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 6;
- blocksize = 64;
- readsize = 256;
- ;
-
- memory "lfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "hfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "efuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
- "x x x x x x x x x x x x x x x i";
- ;
-
- memory "lock"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x x x o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
- "x x x x x x x x 1 1 i i i i i i";
- ;
-
- memory "calibration"
- size = 1;
- read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
- "0 0 0 0 0 0 0 0 o o o o o o o o";
- ;
-
- memory "signature"
- size = 3;
- read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x",
- "x x x x x x a1 a0 o o o o o o o o";
- ;
- ;
-
-#------------------------------------------------------------
-# ATmega48P
-#------------------------------------------------------------
-
-part parent "m48"
- id = "m48p";
- desc = "ATmega48P";
- signature = 0x1e 0x92 0x0a;
-
- ocdrev = 1;
- ;
-
-#------------------------------------------------------------
-# ATmega48PB
-#------------------------------------------------------------
-
-part parent "m48"
- id = "m48pb";
- desc = "ATmega48PB";
- signature = 0x1e 0x92 0x10;
-
- ocdrev = 1;
- ;
-
-#------------------------------------------------------------
-# ATmega88
-#------------------------------------------------------------
-
-part
- id = "m88";
- desc = "ATmega88";
- has_debugwire = yes;
- flash_instr = 0xB6, 0x01, 0x11;
- eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
- 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
- 0x99, 0xF9, 0xBB, 0xAF;
- stk500_devcode = 0x73;
-# avr910_devcode = 0x;
- signature = 0x1e 0x93 0x0a;
- pagel = 0xd7;
- bs2 = 0xc2;
- chip_erase_delay = 9000;
- pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
- "x x x x x x x x x x x x x x x x";
-
- chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
- "x x x x x x x x x x x x x x x x";
-
- timeout = 200;
- stabdelay = 100;
- cmdexedelay = 25;
- synchloops = 32;
- bytedelay = 0;
- pollindex = 3;
- pollvalue = 0x53;
- predelay = 1;
- postdelay = 1;
- pollmethod = 1;
-
- pp_controlstack =
- 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
- 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
- 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
- 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
- hventerstabdelay = 100;
- progmodedelay = 0;
- latchcycles = 5;
- togglevtg = 1;
- poweroffdelay = 15;
- resetdelayms = 1;
- resetdelayus = 0;
- hvleavestabdelay = 15;
- resetdelay = 15;
- chiperasepulsewidth = 0;
- chiperasepolltimeout = 10;
- programfusepulsewidth = 0;
- programfusepolltimeout = 5;
- programlockpulsewidth = 0;
- programlockpolltimeout = 5;
-
- ocdrev = 1;
-
- memory "eeprom"
- paged = no;
- page_size = 4;
- size = 512;
- min_write_delay = 3600;
- max_write_delay = 3600;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read = " 1 0 1 0 0 0 0 0",
- " 0 0 0 x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- write = " 1 1 0 0 0 0 0 0",
- " 0 0 0 x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_lo = " 1 1 0 0 0 0 0 1",
- " 0 0 0 0 0 0 0 0",
- " 0 0 0 0 0 0 a1 a0",
- " i i i i i i i i";
-
- writepage = " 1 1 0 0 0 0 1 0",
- " 0 0 x x x x x a8",
- " a7 a6 a5 a4 a3 a2 0 0",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 20;
- blocksize = 4;
- readsize = 256;
- ;
- memory "flash"
- paged = yes;
- size = 8192;
- page_size = 64;
- num_pages = 128;
- min_write_delay = 4500;
- max_write_delay = 4500;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read_lo = " 0 0 1 0 0 0 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- read_hi = " 0 0 1 0 1 0 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- loadpage_lo = " 0 1 0 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_hi = " 0 1 0 0 1 0 0 0",
- " 0 0 0 x x x x x",
- " x x x a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- writepage = " 0 1 0 0 1 1 0 0",
- " 0 0 0 0 a11 a10 a9 a8",
- " a7 a6 a5 x x x x x",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 6;
- blocksize = 64;
- readsize = 256;
- ;
-
- memory "lfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "hfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "efuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
- "x x x x x x x x x x x x x i i i";
- ;
-
- memory "lock"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x x x o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
- "x x x x x x x x 1 1 i i i i i i";
- ;
-
- memory "calibration"
- size = 1;
- read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
- "0 0 0 0 0 0 0 0 o o o o o o o o";
- ;
-
- memory "signature"
- size = 3;
- read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x",
- "x x x x x x a1 a0 o o o o o o o o";
- ;
- ;
-
-#------------------------------------------------------------
-# ATmega88P
-#------------------------------------------------------------
-
-part parent "m88"
- id = "m88p";
- desc = "ATmega88P";
- signature = 0x1e 0x93 0x0f;
-
- ocdrev = 1;
- ;
-
-#------------------------------------------------------------
-# ATmega88PB
-#------------------------------------------------------------
-
-part parent "m88"
- id = "m88pb";
- desc = "ATmega88PB";
- signature = 0x1e 0x93 0x16;
-
- ocdrev = 1;
- ;
-
-#------------------------------------------------------------
-# ATmega168
-#------------------------------------------------------------
-
-part
- id = "m168";
- desc = "ATmega168";
- has_debugwire = yes;
- flash_instr = 0xB6, 0x01, 0x11;
- eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
- 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
- 0x99, 0xF9, 0xBB, 0xAF;
- stk500_devcode = 0x86;
- # avr910_devcode = 0x;
- signature = 0x1e 0x94 0x06;
- pagel = 0xd7;
- bs2 = 0xc2;
- chip_erase_delay = 9000;
- pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
- "x x x x x x x x x x x x x x x x";
-
- chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
- "x x x x x x x x x x x x x x x x";
-
- timeout = 200;
- stabdelay = 100;
- cmdexedelay = 25;
- synchloops = 32;
- bytedelay = 0;
- pollindex = 3;
- pollvalue = 0x53;
- predelay = 1;
- postdelay = 1;
- pollmethod = 1;
-
- pp_controlstack =
- 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
- 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
- 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
- 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
- hventerstabdelay = 100;
- progmodedelay = 0;
- latchcycles = 5;
- togglevtg = 1;
- poweroffdelay = 15;
- resetdelayms = 1;
- resetdelayus = 0;
- hvleavestabdelay = 15;
- resetdelay = 15;
- chiperasepulsewidth = 0;
- chiperasepolltimeout = 10;
- programfusepulsewidth = 0;
- programfusepolltimeout = 5;
- programlockpulsewidth = 0;
- programlockpolltimeout = 5;
-
- ocdrev = 1;
-
- memory "eeprom"
- paged = no;
- page_size = 4;
- size = 512;
- min_write_delay = 3600;
- max_write_delay = 3600;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read = " 1 0 1 0 0 0 0 0",
- " 0 0 0 x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- write = " 1 1 0 0 0 0 0 0",
- " 0 0 0 x x x x a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_lo = " 1 1 0 0 0 0 0 1",
- " 0 0 0 0 0 0 0 0",
- " 0 0 0 0 0 0 a1 a0",
- " i i i i i i i i";
-
- writepage = " 1 1 0 0 0 0 1 0",
- " 0 0 x x x x x a8",
- " a7 a6 a5 a4 a3 a2 0 0",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 20;
- blocksize = 4;
- readsize = 256;
- ;
-
- memory "flash"
- paged = yes;
- size = 16384;
- page_size = 128;
- num_pages = 128;
- min_write_delay = 4500;
- max_write_delay = 4500;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read_lo = " 0 0 1 0 0 0 0 0",
- " 0 0 0 a12 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- read_hi = " 0 0 1 0 1 0 0 0",
- " 0 0 0 a12 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- loadpage_lo = " 0 1 0 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " x x a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_hi = " 0 1 0 0 1 0 0 0",
- " 0 0 0 x x x x x",
- " x x a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- writepage = " 0 1 0 0 1 1 0 0",
- " 0 0 0 a12 a11 a10 a9 a8",
- " a7 a6 x x x x x x",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 6;
- blocksize = 128;
- readsize = 256;
-
- ;
-
- memory "lfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "hfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "efuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
- "x x x x x x x x x x x x x i i i";
- ;
-
- memory "lock"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x x x o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
- "x x x x x x x x 1 1 i i i i i i";
- ;
-
- memory "calibration"
- size = 1;
- read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
- "0 0 0 0 0 0 0 0 o o o o o o o o";
- ;
-
- memory "signature"
- size = 3;
- read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x",
- "x x x x x x a1 a0 o o o o o o o o";
- ;
-;
-
-#------------------------------------------------------------
-# ATmega168P
-#------------------------------------------------------------
-
-part parent "m168"
- id = "m168p";
- desc = "ATmega168P";
- signature = 0x1e 0x94 0x0b;
-
- ocdrev = 1;
-;
-
-#------------------------------------------------------------
-# ATmega168PB
-#------------------------------------------------------------
-
-part parent "m168"
- id = "m168pb";
- desc = "ATmega168PB";
- signature = 0x1e 0x94 0x15;
-
- ocdrev = 1;
-;
-
-
-#------------------------------------------------------------
-# ATmega328
-#------------------------------------------------------------
-
-part
- id = "m328";
- desc = "ATmega328";
- has_debugwire = yes;
- flash_instr = 0xB6, 0x01, 0x11;
- eeprom_instr = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,
- 0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,
- 0x99, 0xF9, 0xBB, 0xAF;
- stk500_devcode = 0x86;
- # avr910_devcode = 0x;
- signature = 0x1e 0x95 0x14;
- pagel = 0xd7;
- bs2 = 0xc2;
- chip_erase_delay = 9000;
- pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
- "x x x x x x x x x x x x x x x x";
-
- chip_erase = "1 0 1 0 1 1 0 0 1 0 0 x x x x x",
- "x x x x x x x x x x x x x x x x";
-
- timeout = 200;
- stabdelay = 100;
- cmdexedelay = 25;
- synchloops = 32;
- bytedelay = 0;
- pollindex = 3;
- pollvalue = 0x53;
- predelay = 1;
- postdelay = 1;
- pollmethod = 1;
-
- pp_controlstack =
- 0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
- 0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
- 0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
- 0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
- hventerstabdelay = 100;
- progmodedelay = 0;
- latchcycles = 5;
- togglevtg = 1;
- poweroffdelay = 15;
- resetdelayms = 1;
- resetdelayus = 0;
- hvleavestabdelay = 15;
- resetdelay = 15;
- chiperasepulsewidth = 0;
- chiperasepolltimeout = 10;
- programfusepulsewidth = 0;
- programfusepolltimeout = 5;
- programlockpulsewidth = 0;
- programlockpolltimeout = 5;
-
- ocdrev = 1;
-
- memory "eeprom"
- paged = no;
- page_size = 4;
- size = 1024;
- min_write_delay = 3600;
- max_write_delay = 3600;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read = " 1 0 1 0 0 0 0 0",
- " 0 0 0 x x x a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- write = " 1 1 0 0 0 0 0 0",
- " 0 0 0 x x x a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_lo = " 1 1 0 0 0 0 0 1",
- " 0 0 0 0 0 0 0 0",
- " 0 0 0 0 0 0 a1 a0",
- " i i i i i i i i";
-
- writepage = " 1 1 0 0 0 0 1 0",
- " 0 0 x x x x a9 a8",
- " a7 a6 a5 a4 a3 a2 0 0",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 20;
- blocksize = 4;
- readsize = 256;
- ;
-
- memory "flash"
- paged = yes;
- size = 32768;
- page_size = 128;
- num_pages = 256;
- min_write_delay = 4500;
- max_write_delay = 4500;
- readback_p1 = 0xff;
- readback_p2 = 0xff;
- read_lo = " 0 0 1 0 0 0 0 0",
- " 0 0 a13 a12 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- read_hi = " 0 0 1 0 1 0 0 0",
- " 0 0 a13 a12 a11 a10 a9 a8",
- " a7 a6 a5 a4 a3 a2 a1 a0",
- " o o o o o o o o";
-
- loadpage_lo = " 0 1 0 0 0 0 0 0",
- " 0 0 0 x x x x x",
- " x x a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- loadpage_hi = " 0 1 0 0 1 0 0 0",
- " 0 0 0 x x x x x",
- " x x a5 a4 a3 a2 a1 a0",
- " i i i i i i i i";
-
- writepage = " 0 1 0 0 1 1 0 0",
- " 0 0 a13 a12 a11 a10 a9 a8",
- " a7 a6 x x x x x x",
- " x x x x x x x x";
-
- mode = 0x41;
- delay = 6;
- blocksize = 128;
- readsize = 256;
-
- ;
-
- memory "lfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "hfuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
- "x x x x x x x x i i i i i i i i";
- ;
-
- memory "efuse"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
- "x x x x x x x x o o o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
- "x x x x x x x x x x x x x i i i";
- ;
-
- memory "lock"
- size = 1;
- min_write_delay = 4500;
- max_write_delay = 4500;
- read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
- "x x x x x x x x x x o o o o o o";
-
- write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
- "x x x x x x x x 1 1 i i i i i i";
- ;
-
- memory "calibration"
- size = 1;
- read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
- "0 0 0 0 0 0 0 0 o o o o o o o o";
- ;
-
- memory "signature"
- size = 3;
- read = "0 0 1 1 0 0 0 0 0 0 0 x x x x x",
- "x x x x x x a1 a0 o o o o o o o o";
- ;
-;
-
-
-#------------------------------------------------------------
-# ATmega328P
-#------------------------------------------------------------
-
-part parent "m328"
- id = "m328p";
- desc = "ATmega328P";
- signature = 0x1e 0x95 0x0F;
-
- ocdrev = 1;
-;
-
diff --git a/boards.txt b/boards.txt
index d01eb81e..ea0a473d 100644
--- a/boards.txt
+++ b/boards.txt
@@ -6,41 +6,170 @@ menu.cpu=Processor
blink.name=Blink
-blink.vid.0=0x2341
-blink.pid.0=0x0043
-blink.vid.1=0x2341
-blink.pid.1=0x0001
-blink.vid.2=0x2A03
-blink.pid.2=0x0043
-blink.vid.3=0x2341
-blink.pid.3=0x0243
-
blink.upload.tool=avrdude
-blink.upload.protocol=arduino
+
+# IMPORTANT: Do not put a protocol here.
+# If the protocol is `null` then Arduino will fall back and use
+# whatever programmer is selected in Tools->Programmer
# This is the maximum size of a program image. It comes from
-# `blinkbios.h` and is the result of `FLASH_PAGES_PER_IMAGE` * `FLASH_BYTES_PER_PAGE`
-# Used only for printing the "Sketch uses... of program stroage space..." message.
+# Used for printing the "Sketch uses... of program storage space..." message and for moving the program image from base 0x000 "active" game area up to the "built-in" game area.
+# Obnoxiously, the `obj-size` command seems to only be able to take decimal, so 5888=0x1700
+# Must match the `FLASH_GAME_IMAGE_SIZE` in the linker file.
blink.upload.maximum_size=5888
blink.upload.maximum_data_size=1024
blink.upload.speed=115200
-#blink.bootloader.tool=avrdude
-#blink.bootloader.low_fuses=0xFF
-#blink.bootloader.high_fuses=0xDE
-#blink.bootloader.extended_fuses=0xFD
-#blink.bootloader.unlock_bits=0x3F
-#blink.bootloader.lock_bits=0x0F
+# The only fuse that is different from factory default is extended_fuses.
+# BOOTRST=0 (programmed) enables jumping to the bootloader on reset and sets the bootloader
+# BOOTSZ1=0, BOOTSZ0=0 (both programmed) sets bootloader size to 1Kb and is the default.
+
+blink.bootloader.tool=avrdude
+blink.bootloader.low_fuses=0x62
+blink.bootloader.high_fuses=0xDF
+blink.bootloader.extended_fuses=0xf8
-# Note that the folder `bootloaders` seems to be hardcoded into the Ardunio IDE
+# Note that the folder `bootloaders` seems to be hardcoded into the Arduino IDE
-blink.bootloader.file=BlinkBIOS.hex
+blink.bootloader.file=BlinkBIOS-168PB.hex
blink.build.mcu=atmega168pb
blink.build.f_cpu=8000000L
-blink.build.board=AVR_BLINK
+blink.build.board=AVR_BLINK_168
blink.build.core=blinklib
blink.build.variant=standard
+blink.build.linkscript=avr5-atmega168pb.xn
+blink.build.builtinbase=0x1700
+
+##############################################################
+
+blink328.name=Blink328
+
+# This board lets you download code into a 328-based blink, but the code is still limited to the memory sizes
+# of a 168-base blink so any games made with this board will work when downloaded to either kind of blink
+
+blink328.upload.tool=avrdude
+
+# IMPORTANT: Do not put a protocol here.
+# If the protocol is `null` then Arduino will fall back and use
+# whatever programmer is selected in Tools->Programmer
+
+
+# This is the maximum size of a program image. It comes from
+# Used for printing the "Sketch uses... of program storage space..." message and for moving the program image from base 0x000 "active" game area up to the "built-in" game area.
+# Must match the `FLASH_GAME_IMAGE_SIZE` in the linker file.
+# Obnoxiously, the `obj-size` command seems to only be able to take decimal
+blink328.upload.maximum_size=5888
+blink328.upload.maximum_data_size=1024
+blink328.upload.speed=115200
+
+
+# The only fuse that is different from factory default is high_fuses.
+# BOOTRST=0 (programmed) enables jumping to the bootloader on reset and sets the bootloader
+# BOOTSZ1=0, BOOTSZ0=0 (both programmed) sets bootloader size to 2Kb and is the default.
+# WARNING: The datasheet is wrong about where these fuse bit are (at least as of 5/13/21)!
+
+blink328.bootloader.tool=avrdude
+blink328.bootloader.low_fuses=0x62
+blink328.bootloader.high_fuses=0xD8
+blink328.bootloader.extended_fuses=0xff
+
+# Note that the folder `bootloaders` seems to be hardcoded into the Arduino IDE
+
+blink328.bootloader.file=BlinkBIOS-328PB.hex
+
+blink328.build.mcu=atmega328pb
+blink328.build.f_cpu=8000000L
+blink328.build.board=AVR_BLINK_328
+blink328.build.core=blinklib
+blink328.build.variant=standard
+blink328.build.linkscript=avr5-atmega328.xn
+blink328.build.builtinbase=0x3900
##############################################################
+blink328max.name=BlinkMAX
+
+# This board lets you make bigger games that will only work on 328-based blinks.
+# Any game made with this board will not work on or transfer to a 168 blink.
+
+blink328max.upload.tool=avrdude
+
+# IMPORTANT: Do not put a protocol here.
+# If the protocol is `null` then Arduino will fall back and use
+# whatever programmer is selected in Tools->Programmer
+
+
+# This is the maximum size of a program image. It comes from
+# Used for printing the "Sketch uses... of program storage space..." message and for moving the program image from base 0x000 "active" game area up to the "built-in" game area.
+# Must match the `FLASH_GAME_IMAGE_SIZE` in the linker file.
+# Obnoxiously, the `obj-size` command seems to only be able to take decimal
+blink328max.upload.maximum_size=7936
+blink328max.upload.maximum_data_size=2048
+blink328max.upload.speed=115200
+
+
+# The only fuse that is different from factory default is high_fuses.
+# BOOTRST=0 (programmed) enables jumping to the bootloader on reset and sets the bootloader
+# BOOTSZ1=0, BOOTSZ0=0 (both programmed) sets bootloader size to 2Kb and is the default.
+# WARNING: The datasheet is wrong about where these fuse bit are (at least as of 5/13/21)!
+
+blink328max.bootloader.tool=avrdude
+blink328max.bootloader.low_fuses=0x62
+blink328max.bootloader.high_fuses=0xD8
+blink328max.bootloader.extended_fuses=0xff
+
+# Note that the folder `bootloaders` seems to be hardcoded into the Arduino IDE
+
+blink328max.bootloader.file=BlinkBIOS-328PB-MAX.hex
+
+blink328max.build.mcu=atmega328pb
+blink328max.build.f_cpu=8000000L
+blink328max.build.board=AVR_BLINK_328
+blink328max.build.core=blinklib
+blink328max.build.variant=standard
+blink328max.build.linkscript=avr5-atmega328.xn
+blink328max.build.builtinbase=0x3900
+
+blink328nfc.name=BlinkNFC
+
+# This board is a MAX that also includes the NFC bootleader.
+# Any game made with this board will not work on or transfer to a 168 blink.
+
+blink328nfc.upload.tool=avrdude
+
+# IMPORTANT: Do not put a protocol here.
+# If the protocol is `null` then Arduino will fall back and use
+# whatever programmer is selected in Tools->Programmer
+
+
+# This is the maximum size of a program image. It comes from
+# Used for printing the "Sketch uses... of program storage space..." message and for moving the program image from base 0x000 "active" game area up to the "built-in" game area.
+# Must match the `FLASH_GAME_IMAGE_SIZE` in the linker file.
+# Obnoxiously, the `obj-size` command seems to only be able to take decimal
+blink328nfc.upload.maximum_size=7936
+blink328nfc.upload.maximum_data_size=2048
+blink328nfc.upload.speed=115200
+
+
+# The only fuse that is different from factory default is high_fuses.
+# BOOTRST=0 (programmed) enables jumping to the bootloader on reset and sets the bootloader
+# BOOTSZ1=0, BOOTSZ0=0 (both programmed) sets bootloader size to 2Kb and is the default.
+# WARNING: The datasheet is wrong about where these fuse bit are (at least as of 5/13/21)!
+
+blink328nfc.bootloader.tool=avrdude
+blink328nfc.bootloader.low_fuses=0x62
+blink328nfc.bootloader.high_fuses=0xD8
+blink328nfc.bootloader.extended_fuses=0xff
+
+# Note that the folder `bootloaders` seems to be hardcoded into the Arduino IDE
+
+blink328nfc.bootloader.file=BlinkBIOS-328PB-MAX-NFC.hex
+
+blink328nfc.build.mcu=atmega328pb
+blink328nfc.build.f_cpu=8000000L
+blink328nfc.build.board=AVR_BLINK_328
+blink328nfc.build.core=blinklib
+blink328nfc.build.variant=standard
+blink328nfc.build.linkscript=avr5-atmega328.xn
+blink328nfc.build.builtinbase=0x3900
\ No newline at end of file
diff --git a/bootloaders/BlinkBIOS-168PB.hex b/bootloaders/BlinkBIOS-168PB.hex
new file mode 100644
index 00000000..409081b8
--- /dev/null
+++ b/bootloaders/BlinkBIOS-168PB.hex
@@ -0,0 +1,283 @@
+:102E00000AB400FCFDCF90938900809388008AB5B6
+:102E100081608ABD08959B01F894409131015091E1
+:102E2000320160913301709134017894420F531F45
+:102E3000611D711DFC01408351836283738308957A
+:102E4000CF93C62F7AD5882349F08DE55DD58C2F99
+:102E50005BD585E78C1B58D5CF9146C5CF9108959A
+:102E6000CF92DF92FF920F931F93CF93DF93062FA2
+:102E7000F42E152F62D58823F1F08BED45D5CF2D9B
+:102E8000D12F6E0180E2C80ED11C1BEDF9908F2D61
+:102E90003BD51F0DCC16DD06C9F7802F35D582ED49
+:102EA000801B811B31D5DF91CF911F910F91FF9036
+:102EB000DF90CF9019C5DF91CF911F910F91FF90B7
+:102EC000DF90CF900895CF93DF93C0E0D1E0DE0193
+:102ED000EC912E2F229526952695237011968C9194
+:102EE0001197982F9770990F990F922B8695869529
+:102EF0008695E695EF71F0E0EC5BF74CE491ED8799
+:102F0000E92FF0E0EC5BF74CE491EE87E82FF0E07E
+:102F1000EC5BF74CE491EF871296249681E0AC309D
+:102F2000B807B1F6DF91CF910895E0E0F1E011929A
+:102F300082E0EE37F807D8F38091310190913201A9
+:102F4000A0913301B0913401805E9D4EA54FBF4FDB
+:102F50008093360190933701A0933801B0933901E3
+:102F6000B2CFC82FF894E1DFC093280104E00EBF70
+:102F70000FEF0DBF78940C940000EDE4F1E01082A7
+:102F800012AA1092B1011092E30110921502109250
+:102F900047020895F894EEE3F1E01182148216825C
+:102FA0001582128611867894089582E00895FF9222
+:102FB0000F931F93CF93DF93F62E072F142FBDD4BB
+:102FC000882361F087E3A0D4CF2DD02F112321F0E7
+:102FD00089919AD41150FACF87D481E0DF91CF91B3
+:102FE0001F910F91FF900895182FC12FDE63DF739B
+:102FF0008D2F90E08ED52FEF80E792E0215080401A
+:103000009040E1F700C00000B8DF80E090E081D59B
+:103010002FEF80E792E0215080409040E1F700C020
+:103020000000ABDFC15021F080913F0180FFDECF77
+:10303000C6E0C15021F080913F0180FF0CC080911B
+:103040003F0180FFD2CFF89480E18093600088E058
+:1030500080936000FFCF80E090E05BD52FEF80E7AA
+:1030600092E0215080409040E1F700C0000085DFF1
+:1030700080E090E04ED52FEF80E792E02150804035
+:103080009040E1F700C0000078DFD3CF2F923F924D
+:103090004F925F926F927F928F929F92AF92BF9268
+:1030A000CF92DF92EF92FF920F931F93CF93DF9314
+:1030B000CDB7DEB7CD5BD1090FB6F894DEBF0FBE3A
+:1030C000CDBF782ED62EC655DF4F59834883CA5AB6
+:1030D000D04024E0281720F0EE24E394E80E01C04D
+:1030E000E12C35D580E090E014D5D11002C008EB7A
+:1030F00001C00DEF37E0731217C0402F440F440F8B
+:10310000C755DF4F4883C95AD04060E177E2CE010E
+:103110008F559F4F80DEF02E51E0C355DF4F58830F
+:10312000CD5AD0401FE31BC081E090E0072C01C0C6
+:10313000880F0A94EAF7182F10951F7360E070E06B
+:10314000CE018F559F4F67DEC755DF4F1882C95A92
+:10315000D040C355DF4F1882CD5AD040F12CCB550B
+:10316000DF4F188219821A821B82C55AD04012DFA3
+:10317000DD2039F08AE4C255DF4F8883CE5AD04033
+:1031800006C09BE0C255DF4F9883CE5AD040C6554B
+:10319000DF4FE881CA5AD040C954DF4FE883C75B8C
+:1031A000D040C555DF4FF881CB5AD040C854DF4FCF
+:1031B000F883C85BD04082ED8E1B8F1BC255DF4F5A
+:1031C0004881CE5AD040841BC754DF4F8883C95BE7
+:1031D000D040D02E63E0662EC455DF4F1882CC5A03
+:1031E000D040872D90E052E3589F9001599F300DB9
+:1031F0001124F901E35BFE4F1F01AF014D5F5F4FEB
+:10320000CF54DF4F59834883C15BD040F901E05B65
+:10321000FE4FCD54DF4FF983E883C35BD0409C0160
+:10322000220F331FCB54DF4F39832883C55BD04037
+:103230003196C654DF4FF983E883CA5BD0402050F3
+:103240003F4FC155DF4F39832883CF5AD0402E01DD
+:1032500031E8430E511CA201405E5F4FC454DF4F62
+:1032600059834883CC5BD040C355DF4F5881CD5A3A
+:10327000D040552319F0112309F4DBC180913F019F
+:1032800080FDD7C1C355DF4FF881CD5AD040F11131
+:1032900091C0F1018081882309F48CC0CF54DF4FA5
+:1032A000E881F981C15BD04080818B3D09F060C02D
+:1032B000F1018281833209F05BC0C101D5D288233C
+:1032C00009F456C0CD54DF4FE881F981C35BD0408B
+:1032D00081A18F1160C0CB54DF4FE881F981C55BBC
+:1032E000D040E050FF4F818187709F2D9295990FBC
+:1032F000907E892B81838F2D8370A1E0B0E0AC0F8D
+:10330000BD1FF0E28F9FA00DB11D112490E2C654A5
+:10331000DF4FE881F981CA5BD04001900D929A9508
+:10332000E1F78330A1F4BE016F5F7F4FC755DF4FD8
+:103330008881C95AD040D2D3C755DF4F2881C95A96
+:10334000D0402F5FC755DF4F2883C95AD040F39430
+:103350000F1129C0C155DF4FE881F981CF5AD04004
+:103360008081806C808383E08183F02EC12C16C025
+:10337000CF54DF4FE881F981C15BD0408081883E26
+:1033800051F4F1018281823031F4C1016DD2CC243B
+:10339000C394811101C0C12C0F1106C0111104C0CA
+:1033A00061E0600F02C0C12C6F2D872D49DDF10156
+:1033B000108201C0C12CAE2CB12CF2E3FA9D400169
+:1033C000FB9D900C1124F401E35BFE4F8081882368
+:1033D00009F45AC083818D3509F04BC08281833056
+:1033E00009F047C0CF0140D2882309F442C021E050
+:1033F00030E00E2C01C0220F0A94EAF7C455DF4FCB
+:103400004881CC5AD040422BC455DF4F4883CC5A18
+:10341000D040F401E05BFE4FD180C501880F991FB9
+:10342000D016D0F00D1558F420951223FC01E05071
+:10343000FF4F2081206C20832181276009C0FC017F
+:10344000E050FF4F2081206C20832181287F236062
+:1034500021839924939401C0912CFC01E050FF4FEB
+:10346000818187709D2D9295990F907E892B818304
+:1034700001C0912C52E35A9DF0015B9DF00D112487
+:10348000E35BFE4F108201C0912CDF14C0F58D2D3F
+:1034900086958695C755DF4F9881C95AD0408917C0
+:1034A000B8F4E0E2DE9EC0011124D201841995092E
+:1034B000FC01EA0FFB1FE491ED93C454DF4F288118
+:1034C0003981CC5BD0402A173B0791F7A2010BC092
+:1034D0008D2D837041E050E04C0F5D1F30E2839FE3
+:1034E000400D511D11246D2D8E2DBADC68E770E062
+:1034F000CE018B559F4F8FDCD02E43E0642EF89485
+:103500004091310150913201609133017091340149
+:103510007894CB55DF4F88819981AA81BB81C55AA8
+:10352000D04084179507A607B70718F09110BDC0C3
+:103530007CC06110ADC0F8944091310150913201CE
+:1035400060913301709134017894CF55DF4F8881B9
+:103550009981AA81BB81C15AD04084179507A607DB
+:10356000B70748F481E090E00A2C01C0880F0A9464
+:10357000EAF780951823F501EE0FFF1FE050FF4F8B
+:10358000818187708183112309F44FC0212F30E09E
+:1035900045E0E41609F47FC0E394C9010E2C02C093
+:1035A000959587950A94E2F780FFF2CF23E0622E8B
+:1035B0008E2DC3D18823C9F0C255DF4F8881CE5AE2
+:1035C000D040A2D1C954DF4F8881C75BD0409CD185
+:1035D000C854DF4F8881C85BD04096D1C754DF4FB5
+:1035E0008881C95BD04090D17FD1EE2DF0E0EE0F05
+:1035F000FF1FE050FF4F8181886F8183C455DF4FEB
+:103600005881CC5AD040852F90E00E2C02C0959561
+:1036100087950A94E2F780FD40C062E370E0CE0136
+:103620008B559F4FF8DB6A94D02E4DDCCC2009F4EB
+:103630001BCE83E0E82E10E0812F7FD1882329F074
+:1036400088EE62D18AEE60D14FD11F5F1630A1F7AC
+:10365000EA94E110F0CF9EDC0F1122C080E2089FB7
+:1036600080011124E0E0F0E080E090E00E171F07F9
+:1036700029F02491820F911D3196F8CFC655DF4F66
+:10368000E881F981CA5AD040E817F90749F411C016
+:10369000992041F070CFE12C80CF68E770E0BFCF78
+:1036A00083E0A2DC111184CFC0CF662009F443CFA0
+:1036B00062CFC354DF4F0FB6F894DEBF0FBECDBF4D
+:1036C000DF91CF911F910F91FF90EF90DF90CF90FE
+:1036D000BF90AF909F908F907F906F905F904F9032
+:1036E0003F902F900895C82FAB01F89404E00EBFCF
+:1036F0000FEF0DBF789460E0C9DCC73011F481E0B2
+:1037000001C082E02EDC60E070E0E0E0F0E0849157
+:10371000680F711D3196E11587E1F807C1F787E061
+:10372000E2DF14B714BE87EF84BF0FB6F894A895F4
+:1037300080916000886180936000109260000FBEED
+:10374000C0E8C0936100D1E0D09361002FEF80E723
+:1037500092E0215080409040E1F700C00000E5DB9E
+:1037600085B7982F916095BF826085BFC0BF84E800
+:1037700080936400809168008460809368005F9A01
+:10378000729A589A599A269A689A279A699A549AD4
+:10379000529A5E9A5D9A569A559AD0936E0082E03C
+:1037A0008093700076D084B18F6384B987B1806CC8
+:1037B00087B97894B7D1F894C093610010926100F2
+:1037C000789464D111FD9FDF80E0CBDB5FD181E095
+:0837D0008093790298DF08DC08
+:1038000031C00000FDCF0000FBCF0000F9CF000069
+:10381000CECB00000EC100000DC10000EAC10000C7
+:1038200070C10000D3CF000092C10000DBC00000D7
+:103830009FC100000EC10000B8CB0000CCCF00003B
+:10384000D8C10000FFFEFDFBFAF8F5F2EEEAE6E073
+:10385000DAD3CCC3BAB0A5998C7E6F5F4E3B2813E8
+:103860000D09030111245DDFFC012281339690E0F4
+:10387000215018F08191980FFBCF81E0923D09F023
+:1038800080E008952E9870982F9871985C985A98B7
+:1038900008958FEF87BD88BD16BC95B5906895BD1E
+:1038A00095B5906495BD93EA94BD93E29093B00072
+:1038B00090E89093B3008093B4001092B200E1EBD3
+:1038C000F0E080818064808383B5806883BD83B5A8
+:1038D000826083BD83B5816083BD82E085BD8083C6
+:1038E00083B58F7783BD089580EB97E189DAEDE4A6
+:1038F000F1E0118213AA1092B2011092E401109229
+:1039000016021092480208950F931F93CF93DF93EE
+:10391000082FC8E0D0E011E0812F802319F08CE05F
+:1039200096E002C08EED9EE06BDA110F2197A1F7B1
+:10393000DF91CF911F910F910895F89442E3849FF6
+:10394000F0011124E35BFE4F95A5911103C091E0B6
+:10395000918301C090E078949923C1F121E030E097
+:10396000A90102C0440F551F8A95E2F7CA012091B0
+:1039700081002111FCCF98E190938100109280008A
+:10398000109285001092840021E030E0309389008D
+:103990002093880093E0909380002CE036E03093F1
+:1039A000890020938800B19A90916F009260909363
+:1039B0006F0080938A008AB581608ABD89E1809317
+:1039C000810080EB97E11CDA81E0089580E00895A2
+:1039D00085EC80937A0080917A0086FDFCCF8091FF
+:1039E000790008951F920F920FB60F9211248F93B2
+:1039F0009F9380918A0087B983B995E39A95F1F7EF
+:103A0000000083B986B995E09A95F1F7000017B8E0
+:103A100086B90AB400FC03C01092810003C08AB5C5
+:103A20008E7F8ABD9F918F910F900FBE0F901F9038
+:103A3000189518951F920F920FB60F9211248F931D
+:103A400086B5809327018F910F900FBE0F901F9026
+:103A5000189590E8899FF0011124F89483E08093F1
+:103A60005700E895789407B600FCFDCFF89485E000
+:103A700080935700E895789407B600FCFDCFF89442
+:103A800081E180935700E895789408950F931F93F0
+:103A9000CF93DF9300E017E1C0E0D1E0980180E030
+:103AA00090E0F901459154912E5F3F4FF894FC014D
+:103AB0000A01D0935700E895112478940296803833
+:103AC000910579F78C2FC5DFCF5F00581F4FCE329D
+:103AD00029F7DF91CF911F910F910895E0E0F0E079
+:103AE00091E0F894DB012D913D91BD010901909386
+:103AF0005700E895112478943296E038F10589F75B
+:103B0000A8CF81E080930C0180910C018111FCCF42
+:103B1000DAC9E0E0F1E08193919321E0EC30F20723
+:103B2000D1F7EFCF8EE680937C0085EC80937A000E
+:103B30008DE58A95F1F700004BDF4ADF49DF48DF6A
+:103B400010927A008A3710F082E04ECA0895F894F5
+:103B5000E1E3F1E080819181A281B381805E9D4E9D
+:103B6000A54FBF4F85839683A783B0877894089528
+:103B7000EEDFF89480E88093610081E0809361003B
+:103B8000789415BC7FDE1092B10014BC1092B00086
+:103B90006B982FEF80E792E0215080409040E1F752
+:103BA00000C000004F9BFECF2FEF80E792E0215036
+:103BB00080409040E1F700C0000080916D00806877
+:103BC00080936D0085E083BF889580916D008F772D
+:103BD00080936D00F8945DDEDDD97894A3DFF894CE
+:103BE00080E8809361001092610078941092410106
+:103BF00008951F920F920FB60F921124EF92FF9229
+:103C00000F931F932F933F934F935F936F937F93E4
+:103C10008F939F93AF93BF93CF93DF93EF93FF93D4
+:103C200016B1109586B578948C5E96B59817E8F322
+:103C300016B917B985E08A95F1F7000017B816B9DB
+:103C40008091B20087FFB3C0C091350180E28C0F34
+:103C50008D3708F4A9C08091310190913201A09173
+:103C60003301B09134010196A11DB11D8093310142
+:103C700090933201A0933301B09334014091360107
+:103C800050913701609138017091390148175907F7
+:103C90006A077B0708F46CDF80913F0169B1562FFA
+:103CA0005095551F5527551F90913E014091420157
+:103CB0002091430130914401591349C041114150B1
+:103CC00067FD2FC02115310529F02150310911F46C
+:103CD0001092450160914701709148016F5F7F4FDD
+:103CE0007093480160934701613797E1790730F09D
+:103CF0008068109248011092470149C0693B9BE0DF
+:103D0000790710F0806443C0613B744008F43FC001
+:103D10009091460191113BC0826091E090934601E1
+:103D200036C02115310599F12150310981F5909165
+:103D30004501913011F4886007C0923011F4806120
+:103D400003C08062909340011092450120C0411150
+:103D50001DC09091450167FD0BC081609F3F09F038
+:103D60009F5F10924801109247012AE431E007C09A
+:103D700084602115310509F490E01092460190937A
+:103D8000450150933E0144E191E002C044E190E0DE
+:103D900080933F01409342013093440120934301BB
+:103DA0009111D5DE83EA8C0F8093350173C0809129
+:103DB000260190912501C92FD0E0823009F441C03D
+:103DC00028F4882351F08130C9F062C0833009F4AF
+:103DD00045C0843009F451C05BC054DDCC0FDD1FF9
+:103DE000CC0FDD1FC050DF4F8F858F3F29F083E25E
+:103DF0008093B000539A6B9A81E04AC06B989230DE
+:103E000081F030F4992359F0913081F4709A0EC00A
+:103E1000943059F040F0953049F45A9A07C02E9AE0
+:103E200005C02F9A03C0719A01C05C9ACC0FDD1FA8
+:103E3000CC0FDD1FC050DF4F8F858093B40082E030
+:103E400027C08FEF8093B400CC0FDD1FCC0FDD1F98
+:103E5000C050DF4F8D8587BD83E01AC05398809393
+:103E6000B0008FEF87BDCC0FDD1FCC0FDD1FC05022
+:103E7000DF4F8E8588BD84E00BC08FEF88BD9F5FCC
+:103E8000963019F410920C0190E09093250180E097
+:103E900080932601C7E4D2E020E201E09CA5822FB6
+:103EA0008123E22EF12C09F456C08DA59430D8F46C
+:103EB000882309F443C0923010F490E801C090E0E8
+:103EC000282F2695922B80FF42C08A81883248F4A1
+:103ED0008A81FE01E80FF11D93838A818F5F8A83B7
+:103EE00061C01A822BC0973098F5803849F59A81C5
+:103EF000992371F108838B818B3001F58A8184309D
+:103F0000E9F4CE01B1DC8823C9F0809179028111F6
+:103F100015C081E080937902F594E79410E0EE20DB
+:103F200019F0E6941F5FFBCFEC80FD80188260E003
+:103F3000812F0E942017B701812FD5DB80E008C0B8
+:103F40009881911105C09981992359F101C0892F58
+:103F50008DA71CA606C0983018F49F5F9CA701C0CF
+:103F60001DA6E297F594E7942E2D81E0CB31D8077A
+:103F700009F094CFFF91EF91DF91CF91BF91AF9175
+:103F80009F918F917F916F915F914F913F912F9171
+:103F90001F910F91FF90EF900F900FBE0F901F9009
+:083FA00018951A8280E8D4CFC5
+:0400000300003800C1
+:00000001FF
diff --git a/bootloaders/BlinkBIOS-328PB-MAX-NFC.hex b/bootloaders/BlinkBIOS-328PB-MAX-NFC.hex
new file mode 100644
index 00000000..407e263b
--- /dev/null
+++ b/bootloaders/BlinkBIOS-328PB-MAX-NFC.hex
@@ -0,0 +1,401 @@
+:103800000C9432380C9418390C9400380C9400380D
+:103810000C943E300C94693A0C9467380C94A63B97
+:103820000C94EB390C94A2310C94FE390C949A3D13
+:103830000C94693B0C9491390C943C300C94BB3043
+:043840000C94A63B03
+:10600000EDE4F1E0108212AA1092B1011092E301C6
+:106010001092150210924702089520E83EE18EE3A7
+:10602000815089F0F90190E0AF014F5F5F4F6591BA
+:1060300074916F3F7F4FD9F49F5FFA019038A1F7B9
+:1060400020583109EDCF60E088EB20E2829FC0014B
+:10605000112440E050E0E0E0F0E02491420F511DB7
+:1060600031968E179F07C9F787E00E94F2348F326E
+:1060700050F361E088EFE9CF8FE00895FF920F932E
+:106080001F93CF93DF93F62E072F142F0E94CC3847
+:10609000882379F087E30E94B238CF2DD02F1123C7
+:1060A00029F089910E94B2381150F9CF0E94A1388D
+:1060B00081E0DF91CF911F910F91FF900895CF93D1
+:1060C000DF93C0E0D1E0DE01EC912E2F22952695E2
+:1060D0002695237011968C911197982F9770990F90
+:1060E000990F922B869586958695E695EF71F0E04F
+:1060F000EC5BFF48E491ED87E92FF0E0EC5BFF48B3
+:10610000E491EE87E82FF0E0EC5BFF48E491EF8745
+:106110001296249681E0AC30B807B1F6DF91CF91AA
+:106120000895E0E0F1E0119282E0EE37F807D8F34D
+:106130008091310190913201A0913301B0913401ED
+:10614000805E9D4EA54FBF4F8093360190933701DF
+:10615000A0933801B09339010C945F30C82FF894A4
+:106160000E949130C093280108E00EBF0FEF0DBFD1
+:1061700078940C9400000E940F3AF894EEE3F1E05A
+:1061800011821482168215821286118678940895DF
+:106190009B01F8944091310150913201609133019B
+:1061A000709134017894420F531F611D711DFC01E1
+:1061B0004083518362837383089514B714BE87EFBD
+:1061C00084BF0FB6F894A895809160008861809391
+:1061D0006000109260000FBEC0E8C0936100D1E083
+:1061E000D09361002FEF80E792E0215080409040F3
+:1061F000E1F700C000000E94913085B7982F9160B0
+:1062000095BF826085BFC0BF84E8809364008091A1
+:1062100068008460809368005F9A5998519A589AF0
+:106220002FEF80E792E0215080409040E1F700C0DE
+:10623000000080916D00816080936D008091680006
+:10624000846080936800269A689A279A699A549A7B
+:10625000529A5E9A5D9A569A559AD0936E0082E051
+:10626000809370000E94763884B18F6384B987B1BF
+:10627000806C87B90E944F3BC0936100109261000F
+:1062800078940E94AE3911FD0E940D3080E00E948A
+:10629000AE30CF93C62F0E94CC38882369F08DE5AD
+:1062A0000E94B2388C2F0E94B23885E78C1B0E9466
+:1062B000B238CF910C94A138CF910895CF92DF924C
+:1062C000FF920F931F93CF93DF93062FF42E152F7A
+:1062D0000E94CC38882319F18BED0E94B238CF2D63
+:1062E000D12F6E0180E2C80ED11C1BEDF9908F2DCD
+:1062F0000E94B2381F0DCC16DD06C1F7802F0E9418
+:10630000B23882ED801B811B0E94B238DF91CF91A1
+:106310001F910F91FF90DF90CF900C94A138DF91E7
+:10632000CF911F910F91FF90DF90CF9008950AB405
+:1063300000FCFDCF90938900809388008AB581602E
+:106340008ABD08950E94AE3981E0809379020E944F
+:106350000D302F923F924F925F926F927F928F9269
+:106360009F92AF92BF92CF92DF92EF92FF920F93E4
+:106370001F93CF93DF93CDB7DEB7CD5BD1090FB6B7
+:10638000F894DEBF0FBECDBF782ED62EC655DF4F98
+:1063900059834883CA5AD04024E0281720F0EE24BD
+:1063A000E394E80E01C0E12C0E94FE3980E090E009
+:1063B0000E94F439D11002C008EB01C008EF37E0A9
+:1063C000731218C0402F440F440FC755DF4F488346
+:1063D000C95AD04060E177E2CE018F559F4F0E94AD
+:1063E000C830F02E51E0C355DF4F5883CD5AD0400E
+:1063F0001FE31CC081E090E0072C01C0880F0A94C5
+:10640000EAF7182F10951F7360E070E0CE018F55EA
+:106410009F4F0E94C830C755DF4F1882C95AD040DD
+:10642000C355DF4F1882CD5AD040F12CCB55DF4FEA
+:10643000188219821A821B82C55AD0400E94BD3030
+:10644000DD2039F08AE4C255DF4F8883CE5AD04030
+:1064500006C09BE0C255DF4F9883CE5AD040C65548
+:10646000DF4FE881CA5AD040C954DF4FE883C75B89
+:10647000D040C555DF4FF881CB5AD040C854DF4FCC
+:10648000F883C85BD04082ED8E1B8F1BC255DF4F57
+:106490004881CE5AD040841BC754DF4F8883C95BE4
+:1064A000D040D02E63E0662EC455DF4F1882CC5A00
+:1064B000D040872D90E052E3589F9001599F300DB6
+:1064C0001124F901E35BFE4F1F01AF014D5F5F4FE8
+:1064D000CF54DF4F59834883C15BD040F901E05B63
+:1064E000FE4FCD54DF4FF983E883C35BD0409C015E
+:1064F000220F331FCB54DF4F39832883C55BD04035
+:106500003196C654DF4FF983E883CA5BD0402050F0
+:106510003F4FC155DF4F39832883CF5AD0402E01DA
+:1065200031E8430E511CA201405E5F4FC454DF4F5F
+:1065300059834883CC5BD040C355DF4F5881CD5A37
+:10654000D040552319F0112309F4EAC180913F018D
+:1065500080FDE6C1C355DF4FF881CD5AD040F1111F
+:1065600095C0F1018081882309F490C0CF54DF4F9A
+:10657000E881F981C15BD04080818B3D09F062C028
+:10658000F1018281833209F05DC0C1010E94EE3EBB
+:10659000882309F457C0CD54DF4FE881F981C35BEC
+:1065A000D04081A18F1162C0CB54DF4FE881F981C7
+:1065B000C55BD040E050FF4F818187709F2D929541
+:1065C000990F907E892B81838F2D8370A1E0B0E09D
+:1065D000AC0FBD1FF0E28F9FA00DB11D112490E202
+:1065E000C654DF4FE881F981CA5BD04001900D921B
+:1065F0009A95E1F78330A9F4BE016F5F7F4FC755CD
+:10660000DF4F8881C95AD0400E94D739C755DF4F24
+:106610002881C95AD0402F5FC755DF4F2883C95AF8
+:10662000D040F3940F112AC0C155DF4FE881F981A2
+:10663000CF5AD0408081806C808383E08183F02EAC
+:10664000C12C17C0CF54DF4FE881F981C15BD04026
+:106650008081883E59F4F1018281823039F4C10190
+:106660000E94EE3ECC24C394811101C0C12C0F11B5
+:1066700006C0111104C061E0600F02C0C12C6F2D73
+:10668000872D0E944931F101108201C0C12CAE2C2E
+:10669000B12CF2E3FA9D4001FB9D900C1124F40112
+:1066A000E35BFE4F8081882309F45BC083818D35D5
+:1066B00009F04CC08281833009F048C0CF010E94AC
+:1066C000EE3E882309F442C021E030E00E2C01C0E8
+:1066D000220F0A94EAF7C455DF4F4881CC5AD040C4
+:1066E000422BC455DF4F4883CC5AD040F401E05BC5
+:1066F000FE4FD180C501880F991FD016D0F00D151F
+:1067000058F420951223FC01E050FF4F2081206CAB
+:1067100020832181276009C0FC01E050FF4F2081C8
+:10672000206C20832181287F2360218399249394E6
+:1067300001C0912CFC01E050FF4F818187709D2D9D
+:106740009295990F907E892B818301C0912C52E301
+:106750005A9DF0015B9DF00D1124E35BFE4F10820A
+:1067600001C0912CDF14D0F58D2D86958695C755E7
+:10677000DF4F9881C95AD0408917B8F4E0E2DE9E15
+:10678000C0011124D20184199509FC01EA0FFB1FF5
+:10679000E491ED93C454DF4F28813981CC5BD04024
+:1067A0002A173B0791F7A2010BC08D2D837041E0A2
+:1067B00050E04C0F5D1F30E2839F400D511D1124AE
+:1067C0006D2D8E2D0E945E3168E770E0CE018B55F5
+:1067D0009F4F0E94C830D02E43E0642EF894409121
+:1067E00031015091320160913301709134017894FC
+:1067F000CB55DF4F88819981AA81BB81C55AD04092
+:1068000084179507A607B70718F09110CDC083C06D
+:106810006110BAC0F89440913101509132016091F9
+:106820003301709134017894CF55DF4F888199817D
+:10683000AA81BB81C15AD04084179507A607B70724
+:1068400048F481E090E00A2C01C0880F0A94EAF72E
+:1068500080951823F501EE0FFF1FE050FF4F818157
+:1068600087708183112309F456C0212F30E045E061
+:10687000E41609F48CC0E394C9010E2C02C095956E
+:1068800087950A94E2F780FFF2CF23E0622E8E2DE7
+:106890000E94CC388823F1F0C255DF4F8881CE5A50
+:1068A000D0400E94B238C954DF4F8881C75BD040C6
+:1068B0000E94B238C854DF4F8881C85BD0400E9424
+:1068C000B238C754DF4F8881C95BD0400E94B238CC
+:1068D0000E94A138EE2DF0E0EE0FFF1FE050FF4FB9
+:1068E0008181886F8183C455DF4F5881CC5AD04055
+:1068F000852F90E00E2C02C0959587950A94E2F7BB
+:1069000080FD47C062E370E0CE018B559F4F0E942F
+:10691000C8306A94D02E0E945F30CC2009F40CCE8F
+:1069200083E0E82E10E0812F0E94CC38882341F0CC
+:1069300088EE0E94B2388AEE0E94B2380E94A138D6
+:106940001F5F163081F7EA94E110ECCF0E94BD3052
+:106950000F1122C080E2089F80011124E0E0F0E0E6
+:1069600080E090E00E171F0729F02491820F911DFF
+:106970003196F8CFC655DF4FE881F981CA5AD04029
+:10698000E817F90749F414C0992059F063CFE12CB6
+:1069900073CF68E770E0B8CF1092790283E00E946D
+:1069A0000F3A111174CFB7CF662009F433CF52CF0D
+:1069B000C354DF4F0FB6F894DEBF0FBECDBFDF91DB
+:1069C000CF911F910F91FF90EF90DF90CF90BF90EC
+:1069D000AF909F908F907F906F905F904F903F907F
+:1069E0002F900895C82FF89408E00EBF0FEF0DBF49
+:1069F00078940E94A931C73011F481E001C082E08F
+:106A00000E94AE30D82F81E0809379024695C0E095
+:106A1000442319F04695CF5FFBCFFB01048115811C
+:106A2000108260E08C2F0E944931A8016D2F8C2FBD
+:046A30000E94F2349A
+:107000000C9432380C9418390C9400380C940038D5
+:107010000C943E300C94693A0C9467380C94A63B5F
+:107020000C94EB390C94A2310C94FE390C949A3DDB
+:107030000C94693B0C9491390C943C300C94BB300B
+:107040000C94A63BFFFEFDFBFAF8F5F2EEEAE6E053
+:10705000DAD3CCC3BAB0A5998C7E6F5F4E3B2813B0
+:107060000D09030111240E94DD302E9870982F988D
+:1070700071985C985A98089515BC0E943538109202
+:10708000B10014BC1092B0006B98089590E8899FED
+:10709000F001112483E080935700E89507B600FCC7
+:1070A000FDCF85E080935700E89507B600FCFDCF43
+:1070B00081E180935700E895089585EC80937A00EC
+:1070C00080917A0086FDFCCF8091790008951F920F
+:1070D0000F920FB60F9211248F9386B580932701DC
+:1070E0008F910F900FBE0F901F9018958FEF87BD57
+:1070F00088BD16BC95B5906895BD95B5906495BD55
+:1071000093EA94BD93E29093B00090E89093B3001B
+:107110008093B4001092B200E1EBF0E080818064D3
+:10712000808383B5806883BD83B5826083BD83B56A
+:10713000816083BD82E085BD808383B58F7783BD09
+:10714000089580EB97E10E949731EDE4F1E0118220
+:1071500013AA1092B2011092E4011092160210923A
+:10716000480208950F931F93CF93DF93082FC8E031
+:10717000D0E011E0812F802319F08CE096E002C06E
+:107180008EED9EE00E949731110F219799F7DF91C4
+:10719000CF911F910F910895F89442E3849FF001DD
+:1071A0001124E35BFE4F95A5911103C091E09183FB
+:1071B00001C090E078949923C9F121E030E0A90161
+:1071C00002C0440F551F8A95E2F7CA012091810041
+:1071D0002111FCCF98E190938100109280001092D1
+:1071E00085001092840021E030E0309389002093E4
+:1071F000880093E0909380002CE036E03093890083
+:1072000020938800B19A90916F00926090936F00E4
+:1072100080938A008AB581608ABD89E1809381006C
+:1072200080EB97E10E94973181E0089580E0089516
+:10723000AF92BF92CF92DF92EF92FF920F931F9384
+:10724000CF93DF93CDB7DEB78D85813009F03BC09A
+:10725000AE84BF84E888F9886701DD2421E8C2167E
+:10726000D10478F510E0812F90E08C159D0550F445
+:10727000F501E80FF91F60818D5F9D4F0E940A3F65
+:107280001F5FF1CF6E2D82E092E00E940A3F80E006
+:1072900090E000E010E0F801E590F4906E2D0E947F
+:1072A000823D6F2D0E94823D0E5F1F4F01152EE320
+:1072B000120789F7BC0180E092E00E94183F80E04D
+:1072C00003C081E001C08FEFDF91CF911F910F913B
+:1072D000FF90EF90DF90CF90BF90AF900895E0E0E7
+:1072E000F0E091E0DB012D913D91BD01090190930A
+:1072F0005700E89511243296E038F10599F70C947F
+:10730000463890E8899FF001112493E0909357004C
+:10731000E89507B600FCFDCF81E180935700E89522
+:10732000089590E8899FF0011124F89483E08093F8
+:107330005700E895789407B600FCFDCFF89485E0F7
+:1073400080935700E895789407B600FCFDCFF89439
+:1073500081E180935700E895789408950F931F93E7
+:10736000CF93DF9300E019E3C0E0D1E0980180E023
+:1073700090E0F901459154912E5F3F4FF894FC0144
+:107380000A01D0935700E89511247894029680382A
+:10739000910579F78C2F0E949139CF5F00581F4FCC
+:1073A000CE3321F7DF91CF911F910F910895E0E047
+:1073B000F0E091E0F894DB012D913D91BD010901D0
+:1073C00090935700E895112478943296E038F105AF
+:1073D00089F70C94913981E080930C0180910C0124
+:1073E0008111FCCF0C945F30E0E0F1E08193919348
+:1073F00021E0EC30F207D1F70C94EB39F894E1E39B
+:10740000F1E080819181A281B381805E9D4EA54F84
+:10741000BF4F85839683A783B08778940895182FEC
+:10742000C12FDE63DF738D2F90E00E94F4392FEFC0
+:1074300080E792E0215080409040E1F700C00000DA
+:107440000E94003080E090E00E94F4392FEF80E746
+:1074500092E0215080409040E1F700C000000E947F
+:107460000030C15021F080913F0180FFDACFC6E0AB
+:10747000C15021F080913F0180FF0CC080913F01FD
+:1074800080FFCECFF89488E18093600088E08093FD
+:107490006000FFCF80E090E00E94F4392FEF80E79A
+:1074A00092E0215080409040E1F700C000000E942F
+:1074B000003080E090E00E94F4392FEF80E792E006
+:1074C000215080409040E1F700C000000E94003051
+:1074D000CFCF1F920F920FB60F921124CF92DF924F
+:1074E000EF92FF920F931F932F933F934F935F93CE
+:1074F0006F937F938F939F93AF93BF93EF93FF937C
+:10750000CF93DF93CDB7DEB7C658D109DEBFCDBF6D
+:1075100080916D0087FDA3C008E00EBF0FEF0DBF87
+:107520000E943C3880E88093610010926100599A73
+:1075300058988FEC97E00197F1F700C0000086EAB9
+:107540000E94E03D80E20E94CA3D86E00E94CA3D62
+:1075500081E00E94CA3D0E94C13D82E689838BE69C
+:107560008A8383E78B8381E38C8380E092E00E94AF
+:10757000043F9E838D830196E9F082E092E00E94B1
+:10758000FC3E182F6E01F7E0CF0ED11C83E0E82EF1
+:1075900082E0F82E8DEF8E0D811750F4C7010E9406
+:1075A000FC3EF60181936F01FFEFEF1AFF0AF2CF65
+:1075B0001A5F01C016E086EA0E94E03D80E20E9468
+:1075C000CA3D88E00E94CA3DCE0101967C01D82EBA
+:1075D0000F2DF70181917F010E94CA3D1150C9F71B
+:1075E0000E94C13D41E050E066E070E28D2D902F99
+:1075F0000E94E43D0E94353E589A5998882309F12B
+:10760000E12CF12C02E7DD24D394970180E090E097
+:10761000F901459154912E5F3F4FFC010A01D09230
+:107620005700E895112402968038910589F7802F3C
+:107630000E9446380F5FF0E8EF0EF11C003B29F77F
+:1076400001C011E00E9476380E949130DA9A789455
+:10765000111102C00E940D3085E00E940F3ACA57F6
+:10766000DF4F0FB6F894DEBF0FBECDBFDF91CF91D5
+:10767000FF91EF91BF91AF919F918F917F916F910A
+:107680005F914F913F912F911F910F91FF90EF903C
+:10769000DF90CF900F900FBE0F901F9018958EE641
+:1076A00080937C0085EC80937A008DE58A95F1F7D4
+:1076B00000000E945D380E945D380E945D380E9483
+:1076C0005D3810927A008A3718F082E00E940F3AF3
+:1076D00008950E94FE39F89480E88093610081E06B
+:1076E0008093610078940E943C382FEF80E792E00D
+:1076F000215080409040E1F700C000004F9BFECF3A
+:107700002FEF80E792E0215080409040E1F700C0E9
+:10771000000080916D00806880936D0085E083BFDC
+:10772000889580916D008F7780936D00F8940E940A
+:1077300076380E94BD300E944F3B80E88093610004
+:107740001092610078941092410108951F920F9257
+:107750000FB60F921124FF920F931F932F933F9315
+:107760004F935F936F937F938F939F93AF93BF9349
+:10777000CF93DF93EF93FF9316B1109586B578946E
+:107780008C5E96B59817E8F316B917B985E08A9517
+:10779000F1F7000017B816B98091B20087FFB5C0A5
+:1077A000C091350180E28C0F8D3708F4ABC0809119
+:1077B000310190913201A0913301B09134010196D1
+:1077C000A11DB11D8093310190933201A09333012B
+:1077D000B0933401409136015091370160913801E6
+:1077E00070913901481759076A077B0710F40E9406
+:1077F000693B80913F0169B1562F5095551F552720
+:10780000551F90913E0140914201209143013091DA
+:107810004401591349C04111415067FD2FC0211542
+:10782000310529F02150310911F410924501609180
+:107830004701709148016F5F7F4F709348016093DB
+:107840004701613797E1790730F08068109248016D
+:107850001092470149C0693B9BE0790710F08064B2
+:1078600043C0613B744008F43FC0909146019111C0
+:107870003BC0826091E09093460136C021153105EE
+:1078800099F12150310981F590914501913011F420
+:10789000886007C0923011F4806103C080629093C9
+:1078A00040011092450120C041111DC09091450139
+:1078B00067FD0BC081609F3F09F09F5F10924801F8
+:1078C000109247012AE431E007C084602115310598
+:1078D00009F490E0109246019093450150933E01C7
+:1078E00044E191E002C044E190E080933F01409385
+:1078F0004201309344012093430191110E94FE39CB
+:1079000083EA8C0F8093350174C080912601909199
+:107910002501C92FD0E0823009F442C028F4882321
+:1079200051F08130D1F063C0833009F446C0843017
+:1079300009F452C05CC00E943538CC0FDD1FCC0F5B
+:10794000DD1FC050DF4F8F858F3F29F083E280938A
+:10795000B000539A6B9A81E04AC06B98923081F0E4
+:1079600030F4992359F0913081F4709A0EC094301C
+:1079700059F040F0953049F45A9A07C02E9A05C044
+:107980002F9A03C0719A01C05C9ACC0FDD1FCC0FF7
+:10799000DD1FC050DF4F8F858093B40082E027C089
+:1079A0008FEF8093B400CC0FDD1FCC0FDD1FC050D4
+:1079B000DF4F8D8587BD83E01AC053988093B00058
+:1079C0008FEF87BDCC0FDD1FCC0FDD1FC050DF4F09
+:1079D0008E8588BD84E00BC08FEF88BD9F5F963099
+:1079E00019F410920C0190E09093250180E08093AF
+:1079F0002601C7E4D2E000E2FF24F3949CA5802F87
+:107A0000812309F459C08DA59430D8F4882309F452
+:107A100046C0923010F490E801C090E0282F2695DF
+:107A2000922B80FF45C08A81883248F48A81FE010A
+:107A3000E80FF11D93838A818F5F8A8361C01A8268
+:107A40002EC09730B0F5803861F59A81992389F17D
+:107A5000F8828B818B3079F48A81843061F4CE0195
+:107A60000E94EE3E882339F080917902811117C07F
+:107A7000402FBE0112C08B818A3489F48A81843000
+:107A800071F4CE010E94EE3E882349F08091790284
+:107A9000811105C0402FBE0181E00E94023580E0C7
+:107AA00008C09881911105C09981992341F101C0C5
+:107AB000892F8DA71CA606C0983018F49F5F9CA73D
+:107AC00001C01DA6E297069581E0CB31D80709F0E9
+:107AD00095CFFF91EF91DF91CF91BF91AF919F91A2
+:107AE0008F917F916F915F914F913F912F911F9156
+:107AF0000F91FF900F900FBE0F901F9018951A8254
+:107B000080E8D7CF8627682F62956827062E66956E
+:107B100066956025062E669560256770082E892F6C
+:107B2000669507946795902D86270694679590250E
+:107B3000862708951F920F920FB60F9211248F93EC
+:107B40009F9380918A0087B983B995E39A95F1F75D
+:107B5000000083B986B995E09A95F1F7000017B84F
+:107B600086B90AB400FC03C01092810003C08AB534
+:107B70008E7F8ABD9F918F910F900FBE0F901F90A7
+:107B8000189559980000509A0000599A0000509892
+:107B90000000089598E0599887FF02C0509801C0EE
+:107BA000509A0000880F599A000000C0915099F730
+:107BB000599850980000599A000089B18170089531
+:107BC000509A00000C94CA3DEF92FF920F931F93BE
+:107BD000CF93DF937C01162F072FEA0186EA0E94DC
+:107BE000E03D882311F011E038C0802F0E94CA3D8B
+:107BF0008111F9CF812F0E94CA3D8111F4CF59988C
+:107C000050980000599A000087EA0E94E03D182F22
+:107C10008111E9CF2097F9F021975998509828E0E1
+:107C200030E090E880E059980000599A00004899A7
+:107C3000892B969521503109B1F75998000020976A
+:107C400011F4509801C0509A0000599A0000F701B1
+:107C500081937F01DFCF0E94C13D812FDF91CF91C2
+:107C60001F910F91FF90EF9008953F924F925F9276
+:107C70006F927F928F929F92AF92BF92CF92DF923C
+:107C8000EF92FF920F931F93CF93DF93CDB7DEB7A1
+:107C9000C250D1400FB6F894DEBF0FBECDBFA8953D
+:107CA00088E18093600084EC8093600088248A944B
+:107CB000982C412C512C00E010E0E12CF12CCE014D
+:107CC00001965C0189B1982F9170392E80FDFACF11
+:107CD000489BFECF41E050E066E070E2CE018E5F4F
+:107CE0009E4F0E94E43D41E050E067E070E2CE012B
+:107CF0008F5F9E4F0E94E43DCF5FDE4FC880C15032
+:107D0000D140D12CEFEFCE1ADE0AA60168E070E276
+:107D1000C5010E94E43D811131C00115110589F4AE
+:107D2000F4E0CF16D10454F10A8110E0102F00279F
+:107D30008981082B4C80512C542C44248B81482A57
+:107D400017C0B5018E2D0E946F398FEFE81AF80A1F
+:107D50003501F30161913F01C4010E94823D4C0154
+:107D6000C3018A199B098C159D0598F30C191D09EF
+:107D7000A8950115110509F0A5CF03C0332433944C
+:107D800013C0A89588E18093600080E8809360002C
+:107D90004814590449F43E2C1E2D1E3328F4812F1B
+:107DA0000E9481391F5FF9CF832DCE5FDE4F0FB662
+:107DB000F894DEBF0FBECDBFDF91CF911F910F9121
+:107DC000FF90EF90DF90CF90BF90AF909F908F90FB
+:107DD0007F906F905F904F903F900895FC012281BB
+:107DE000339690E0215018F08191980FFBCF81E0FD
+:107DF000923D09F080E00895F999FECF92BD81BDD2
+:107E0000F89A992780B50895A8E1B0E042E050E0E3
+:107E10000C941F3F262FF999FECF1FBA92BD81BD4A
+:107E200020BD0FB6F894FA9AF99A0FBE01960895FC
+:107E30000E940A3F272F0C940B3FDC01CB01FC0171
+:107E4000F999FECF06C0F2BDE1BDF89A319600B4B3
+:0A7E50000D9241505040B8F708951C
+:040000030000700089
+:00000001FF
diff --git a/bootloaders/BlinkBIOS-328PB-MAX.hex b/bootloaders/BlinkBIOS-328PB-MAX.hex
new file mode 100644
index 00000000..bfc8318d
--- /dev/null
+++ b/bootloaders/BlinkBIOS-328PB-MAX.hex
@@ -0,0 +1,321 @@
+:103800000C943B380C9400380C9400380C9400381D
+:103810000C94E2300C9459390C945A390C943C3A7B
+:103820000C94C1390C94B1350C94E9390C943239AB
+:103830000C94FA390C9469390C94E0300C94B63538
+:043840000C943C3A6E
+:106000000AB400FCFDCF90938900809388008AB584
+:1060100081608ABD08959B01F894409131015091AF
+:10602000320160913301709134017894420F531F13
+:10603000611D711DFC014083518362837383089548
+:10604000CF93C62F0E94DC38882369F08DE50E942B
+:10605000C2388C2F0E94C23885E78C1B0E94C23840
+:10606000CF910C94B138CF910895CF92DF92FF92E7
+:106070000F931F93CF93DF93062FF42E152F0E94BB
+:10608000DC38882319F18BED0E94C238CF2DD12F37
+:106090006E0180E2C80ED11C1BEDF9908F2D0E947D
+:1060A000C2381F0DCC16DD06C1F7802F0E94C23802
+:1060B00082ED801B811B0E94C238DF91CF911F911E
+:1060C0000F91FF90DF90CF900C94B138DF91CF917A
+:1060D0001F910F91FF90DF90CF900895CF93DF93A2
+:1060E000C0E0D1E0DE01EC912E2F22952695269579
+:1060F000237011968C911197982F9770990F990F83
+:10610000922B869586958695E695EF71F0E0EC5B8F
+:10611000FF48E491ED87E92FF0E0EC5BFF48E49164
+:10612000EE87E82FF0E0EC5BFF48E491EF871296F2
+:10613000249681E0AC30B807B1F6DF91CF91089595
+:10614000E0E0F1E0119282E0EE37F807D8F38091B9
+:10615000310190913201A0913301B0913401805E00
+:106160009D4EA54FBF4F8093360190933701A0936A
+:106170003801B0933901B2CFC82FF894E1DFC09352
+:10618000280108E00EBF0FEF0DBF78940C940000BB
+:10619000EDE4F1E0108212AA1092B1011092E30135
+:1061A00010921502109247020895F894EEE3F1E080
+:1061B00011821482168215821286118678940895AF
+:1061C00082E00895FF920F931F93CF93DF93F62EF3
+:1061D000072F142FF1D7882361F087E3D3D7CF2D72
+:1061E000D02F112321F08991CDD71150FACFB9D7F3
+:1061F00081E0DF91CF911F910F91FF900895182FAB
+:10620000C12FDE63DF738D2F90E00E94CA392FEF1C
+:1062100080E792E0215080409040E1F700C000000C
+:10622000B7DF80E090E00E94CA392FEF80E792E06C
+:10623000215080409040E1F700C00000A9DFC1502C
+:1062400021F080913F0180FFDCCFC6E0C15021F0FA
+:1062500080913F0180FF0CC080913F0180FFD0CF33
+:10626000F89480E18093600088E080936000FFCF25
+:1062700080E090E00E94CA392FEF80E792E0215041
+:1062800080409040E1F700C0000082DF80E090E0B5
+:106290000E94CA392FEF80E792E021508040904061
+:1062A000E1F700C0000074DFD1CF2F923F924F92F0
+:1062B0005F926F927F928F929F92AF92BF92CF9296
+:1062C000DF92EF92FF920F931F93CF93DF93CDB79F
+:1062D000DEB7C05CD1090FB6F894DEBF0FBECDBFEC
+:1062E000C82EE62EC355DF4F59834883CD5AD04080
+:1062F00024E0281720F0FF24F394F80E01C0F12CBD
+:106300000E94E93980E090E00E94CA39E11002C0A1
+:1063100018EB01C01DEF37E0C3120EC0312E330C55
+:10632000330C60E177E2CE018F559F4F74DED12EA2
+:10633000222423940FE313C081E090E00C2C01C0D1
+:10634000880F0A94EAF7082F00950F7360E070E059
+:10635000CE018F559F4F5FDE312C212CD12CCB5598
+:10636000DF4F188219821A821B82C55AD0401DDF66
+:10637000A0D683E582D6812F87D6211002C08EE475
+:1063800001C082E57AD6EE2039F04DE4CA54DF4FE1
+:106390004883C65BD04006C053E5CA54DF4F5883DC
+:1063A000C65BD040C355DF4F8881CD5AD040CB5417
+:1063B000DF4F8883C55BD040EE2039F09AE4C055AA
+:1063C000DF4F9883C05BD04006C0EBE0C055DF4F85
+:1063D000E883C05BD040C255DF4FF881CE5AD04031
+:1063E000C554DF4FF883CB5BD04082EDC355DF4F00
+:1063F0002881CD5AD040821B8F1BC055DF4F48816A
+:10640000C05BD040841BC454DF4F8883CC5BD0403A
+:10641000E12E53E0C455DF4F5883CC5AD040C155CC
+:10642000DF4F1882CF5AD0408C2D90E0E2E3E89FF6
+:106430009001E99F300D1124A901435B5E4F3A01A1
+:10644000FA013396C954DF4FF983E883C75BD04024
+:10645000A901405B5E4FCF54DF4F59834883C15B36
+:10646000D040FC01EE0FFF1FC754DF4FF983E883D4
+:10647000C95BD0404F5F5F4FC354DF4F59834883A0
+:10648000CD5BD040E050FF4FCD54DF4FF983E88320
+:10649000C35BD0409E012F573F4FC755DF4F398315
+:1064A0002883C95AD040A901405E5F4FC154DF4FD5
+:1064B00059834883CF5BD040222019F0002309F490
+:1064C0001DC180913F0180FD19C1211082C1F301DE
+:1064D0008081882309F47DC1ECD58CE3CED58C2D49
+:1064E000D3D5C954DF4FE881F981C75BD0408081A3
+:1064F0008B3D09F036C1F3018281833209F031C14D
+:10650000C301EFD5882309F42CC188E4B6D5CF5454
+:10651000DF4FE881F981C15BD04081A1B5D5CF546F
+:10652000DF4FE881F981C15BD04081A18D1122C18B
+:106530008BE2A3D5C754DF4FE881F981C95BD04016
+:10654000E050FF4F818187709D2D9295990F907E2D
+:10655000892B81838D2D8370A1E0B0E0AC0FBD1F2E
+:10656000F0E28F9FA00DB11D112490E2C354DF4FC4
+:10657000E881F981CD5BD04001900D929A95E1F7C9
+:10658000833031F4BE016F5F7F4F832DE7D63394A4
+:10659000D3941D110EC1CD54DF4FE881F981C35B47
+:1065A000D0408081806C808383E08183D12EC5556B
+:1065B000DF4F1882CB5AD040011100C17AD58EE34B
+:1065C0005CD58C2D61D584E458D5BB24B394B10E31
+:1065D0008B2D5AD56B2D8C2D33DDF30110824F2C72
+:1065E000512CF2E3F49D5001F59DB00C112495015E
+:1065F000235B3E4F4901F9018081882309F4FFC0E4
+:1066000058D58CE33AD58F2D3FD5F40183818D3554
+:1066100009F0F3C08281833009F0EFC0C40161D575
+:10662000882309F4EAC081E090E04C010F2C01C0FE
+:10663000880C0A94EAF7C155DF4FF881CF5AD04051
+:10664000F829C155DF4FF883CF5AD040F501E05B00
+:10665000FE4FE1808CE411D58E2D16D55201AA0C87
+:10666000BB1CE11608F4C7C01E1508F0B8C0809422
+:106670000821F501E050FF4F8081806C808381818B
+:106680008760818399249394F501E050FF4F8181C5
+:1066900087709E2D9295990F907E892B818322E39E
+:1066A000249DF001259DF00D1124E35BFE4F108227
+:1066B000ED1408F4A6C0F8944091310150913201D4
+:1066C00060913301709134017894CB55DF4F88810C
+:1066D0009981AA81BB81C55AD04084179507A60726
+:1066E000B70708F4D9C0911087C1F8DCC555DF4F52
+:1066F0002881CB5AD040222309F4DECEDAD488E5B3
+:10670000BCD483E0F82E00E0802F56D5882329F0F2
+:1067100088EE38D58AEE36D524D50F5F0630A1F73E
+:10672000FA94F110F0CF41DD1D1161C130E2139FE9
+:10673000A0011124E0E0F0E080E090E04E175F0758
+:1067400029F02491820F911D3196F8CFC355DF4F68
+:1067500048815981CD5AD0404817590709F047C19F
+:1067600054C1C954DF4FE881F981C75BD0408081B3
+:10677000883E31F0C555DF4F1882CB5AD04015C046
+:10678000F30182818230B1F7C301ABD4882391F346
+:1067900090D48CE372D48C2D77D487E66ED4F1E05C
+:1067A000C555DF4FF883CB5AD0401D1509F404CFEF
+:1067B00005C0C555DF4F1882CB5AD0407AD48EE33E
+:1067C0005CD48C2D61D48CE458D48D2D5DD46D2D8A
+:1067D00002CFC555DF4F1882CB5AD04000CF84E49A
+:1067E0004CD4F501E050FF4F8081806C8083818123
+:1067F000887F836046CF912C47CF912C50CF912C2E
+:1068000057CF57D48EE339D48F2D3ED488E435D476
+:106810008E2D3AD48E2D86958695831508F530E217
+:10682000E39EC0011124DE01AF57BF4FC755DF4FB4
+:1068300048815981C95AD040841B950BFC01EA0F4D
+:10684000FB1FE491ED93C154DF4FE881F981CF5BE9
+:10685000D040EA17FB0791F7AE014F575F4F0BC0CF
+:106860008E2D837041E050E04C0F5D1FF0E28F9F52
+:10687000400D511D11246E2D8F2DF7DB68E770E060
+:10688000CE018B559F4FC7DBE12E23E0C455DF4F70
+:106890002883CC5AD0400FCFC455DF4F5881CC5AF3
+:1068A000D040511121C0F8944091310150913201F2
+:1068B00060913301709134017894CF55DF4F888116
+:1068C0009981AA81BB81C15AD04084179507A60738
+:1068D000B70768F481E090E0042C01C0880F0A94A7
+:1068E000EAF78095082303C0992009F482C0F201D9
+:1068F000EE0FFF1FE050FF4F8181877081830023DF
+:1069000009F4F3CE202F30E045E0F41611F0F394B3
+:1069100001C0F12CC9010F2C02C0959587950A94EE
+:10692000E2F780FFF1CF53E0C455DF4F5883CC5AD4
+:10693000D040BFD38EE3A1D38F2DA6D385E49DD3C2
+:10694000CA54DF4F8881C65BD04097D3CB54DF4F0A
+:106950008881C55BD04098D38F2D2ED48823C9F071
+:10696000C055DF4F8881C05BD0400CD4CB54DF4F83
+:106970008881C55BD04006D4C554DF4F8881CB5B8E
+:10698000D04000D4C454DF4F8881CC5BD040FAD3D0
+:10699000E8D3EF2DF0E0EE0FFF1FE050FF4F8181B5
+:1069A000886F8183C155DF4FE881CF5AD0408E2F49
+:1069B00090E00F2C02C0959587950A94E2F780FD30
+:1069C00003C062E370E002C068E770E0CE018B555F
+:1069D0009F4F21DBC455DF4FF881CC5AD040F15096
+:1069E000C455DF4FF883CC5AD040E12E7ECE83E0F1
+:1069F00006DC01119ECF79CEC455DF4F8881CC5A79
+:106A0000D040882309F44FCF72CFC054DF4F0FB668
+:106A1000F894DEBF0FBECDBFDF91CF911F910F91D4
+:106A2000FF90EF90DF90CF90BF90AF909F908F90AE
+:106A30007F906F905F904F903F902F900895C82F58
+:106A4000F89408E00EBF0FEF0DBF78942EDCC7302E
+:106A500011F481E001C082E08FDBD82F81E08093C8
+:106A600079024695C0E0442319F04695CF5FFBCFED
+:106A7000FB0104811581108260E08C2FE1DAA8010E
+:106A80006D2F8C2FDCDF40E050E0E0E0F0E08491FF
+:106A9000480F511D3196E03A8FE1F807C1F761E0E8
+:106AA00087E0CDDF14B714BE87EF84BF0FB6F8942C
+:106AB000A8958091600088618093600010926000CA
+:106AC0000FBEC0E8C0936100D1E0D09361002FEF0A
+:106AD00080E792E0215080409040E1F700C0000044
+:106AE0002FDB85B7982F916095BF826085BFC0BFAF
+:106AF00084E88093640080916800846080936800DB
+:106B00005F9A729A589A599A269A689A279A699A15
+:106B1000549A529A5E9A5D9A569A559AD0936E00FC
+:106B200082E080937000F2D284B18F6384B987B120
+:106B3000806C87B9789437D4F894C0936100109230
+:106B4000610078948091C00082608093C000809141
+:106B5000C10088608093C100D9D311FD94DF80E02B
+:0E6B60000BDBD4D381E0809379028DDF48DB1C
+:107000003AC00000FDCF0000FBCF0000F9CF000028
+:10701000D9C800004EC100004DC100002DC20000C3
+:10702000B0C100009ECD0000D4C100001BC1000013
+:10703000E1C100004EC10000C3C8000097CD0000B0
+:107040001BC20000FFFEFDFBFAF8F5F2EEEAE6E0F7
+:10705000DAD3CCC3BAB0A5998C7E6F5F4E3B2813B0
+:107060000D09030130313233343536373839616236
+:10707000636465660000112415DD9091C00095FFE2
+:10708000FCCF8093C6000895CF93C82FE82FF0E07F
+:1070900084E0F595E7958A95E1F7EC59FF488491EE
+:1070A000ECDFCF70EC2FF0E0EC59FF488491CF91EA
+:1070B000E4CFCF92DF92EF92FF928AE0DEDFC090C2
+:1070C0003101D0903201E0903301F09034018D2DE8
+:1070D000DBDF8C2DD9DF8AE3FF90EF90DF90CF903C
+:1070E000CCCFFC012281339690E0215018F08191A1
+:1070F000980FFBCF81E0923D09F080E008952E9833
+:1071000070982F9871985C985A9808958FEF87BD62
+:1071100088BD16BC95B5906895BD95B5906495BD34
+:1071200093EA94BD93E29093B00090E89093B300FB
+:107130008093B4001092B200E1EBF0E080818064B3
+:10714000808383B5806883BD83B5826083BD83B54A
+:10715000816083BD82E085BD808383B58F7783BDE9
+:10716000089580EB97E10E940030EDE4F1E0118298
+:1071700013AA1092B2011092E4011092160210921A
+:10718000480208950F931F93CF93DF93082FC8E011
+:10719000D0E011E0812F802319F08CE096E002C04E
+:1071A0008EED9EE00E940030110F219799F7DF913C
+:1071B000CF911F910F910895F89442E3849FF001BD
+:1071C0001124E35BFE4F95A5911103C091E09183DB
+:1071D00001C090E078949923C9F121E030E0A90141
+:1071E00002C0440F551F8A95E2F7CA012091810021
+:1071F0002111FCCF98E190938100109280001092B1
+:1072000085001092840021E030E0309389002093C3
+:10721000880093E0909380002CE036E03093890062
+:1072200020938800B19A90916F00926090936F00C4
+:1072300080938A008AB581608ABD89E1809381004C
+:1072400080EB97E10E94003081E0089580E008958E
+:1072500085EC80937A0080917A0086FDFCCF809146
+:10726000790008951F920F920FB60F9211248F93F9
+:107270009F9380918A0087B983B995E39A95F1F736
+:10728000000083B986B995E09A95F1F7000017B828
+:1072900086B90AB400FC03C01092810003C08AB50D
+:1072A0008E7F8ABD9F918F910F900FBE0F901F9080
+:1072B000189518951F920F920FB60F9211248F9365
+:1072C00086B5809327018F910F900FBE0F901F906E
+:1072D000189590E8899FF0011124F89483E0809339
+:1072E0005700E895789407B600FCFDCFF89485E048
+:1072F00080935700E895789407B600FCFDCFF8948A
+:1073000081E180935700E895789408950F931F9337
+:10731000CF93DF9300E019E3C0E0D1E0980180E073
+:1073200090E0F901459154912E5F3F4FF894FC0194
+:107330000A01D0935700E89511247894029680387A
+:10734000910579F78C2FC5DFCF5F00581F4FCF33E2
+:1073500029F7DF91CF911F910F910895E0E0F0E0C0
+:1073600091E0F894DB012D913D91BD0109019093CD
+:107370005700E895112478943296E038F10589F7A2
+:10738000A8CF81E080930C0180910C018111FCCF8A
+:107390000C946E30E0E0F1E08193919321E0EC30C9
+:1073A000F207D1F7EECF8EE680937C0085EC8093D8
+:1073B0007A008DE58A95F1F700004ADF49DF48DF62
+:1073C00047DF10927A008A3718F082E00C94FF3081
+:1073D0000895F894E1E3F1E080819181A281B38185
+:1073E000805E9D4EA54FBF4F85839683A783B08750
+:1073F00078940895EEDFF89480E88093610081E04E
+:1074000080936100789415BC7ADE1092B10014BCB0
+:107410001092B0006B982FEF80E792E021508040EF
+:107420009040E1F700C000004F9BFECF2FEF80E7B8
+:1074300092E0215080409040E1F700C00000809130
+:107440006D00806880936D0085E083BF8895809192
+:107450006D008F7780936D00F89458DE0E94D530D0
+:107460007894A1DFF89480E8809361001092610025
+:1074700078941092410108951F920F920FB60F92C7
+:107480001124FF920F931F932F933F934F935F937A
+:107490006F937F938F939F93AF93BF93CF93DF931C
+:1074A000EF93FF9316B1109586B578948C5E96B5E0
+:1074B0009817E8F316B917B985E08A95F1F7000037
+:1074C00017B816B98091B20087FFB3C0C0913501DB
+:1074D00080E28C0F8D3708F4A9C080913101909122
+:1074E0003201A0913301B09134010196A11DB11D6B
+:1074F0008093310190933201A0933301B093340112
+:1075000040913601509137016091380170913901F5
+:10751000481759076A077B0708F46CDF80913F0121
+:1075200069B1562F5095551F5527551F90913E0113
+:10753000409142012091430130914401591349C0C7
+:107540004111415067FD2FC02115310529F021500F
+:10755000310911F410924501609147017091480181
+:107560006F5F7F4F7093480160934701613797E1E8
+:10757000790730F08068109248011092470149C0A5
+:10758000693B9BE0790710F0806443C0613B744025
+:1075900008F43FC09091460191113BC0826091E098
+:1075A0009093460136C02115310599F121503109DA
+:1075B00081F590914501913011F4886007C09230B7
+:1075C00011F4806103C080629093400110924501E4
+:1075D00020C041111DC09091450167FD0BC0816025
+:1075E0009F3F09F09F5F10924801109247012AE4E3
+:1075F00031E007C084602115310509F490E0109254
+:1076000046019093450150933E0144E191E002C050
+:1076100044E190E080933F01409342013093440164
+:10762000209343019111D5DE83EA8C0F80933501BD
+:1076300073C08091260190912501C92FD0E082303E
+:1076400009F441C028F4882351F08130C9F062C0A8
+:10765000833009F445C0843009F451C05BC04FDD6C
+:10766000CC0FDD1FCC0FDD1FC050DF4F8F858F3F4C
+:1076700029F083E28093B000539A6B9A81E04AC06C
+:107680006B98923081F030F4992359F0913081F465
+:10769000709A0EC0943059F040F0953049F45A9ADF
+:1076A00007C02E9A05C02F9A03C0719A01C05C9A38
+:1076B000CC0FDD1FCC0FDD1FC050DF4F8F858093B7
+:1076C000B40082E027C08FEF8093B400CC0FDD1FA1
+:1076D000CC0FDD1FC050DF4F8D8587BD83E01AC002
+:1076E00053988093B0008FEF87BDCC0FDD1FCC0F78
+:1076F000DD1FC050DF4F8E8588BD84E00BC08FEF4B
+:1077000088BD9F5F963019F410920C0190E0909321
+:10771000250180E080932601C7E4D2E000E2FF2447
+:10772000F3949CA5802F812309F456C08DA5943035
+:10773000D8F4882309F443C0923010F490E801C0D3
+:1077400090E0282F2695922B80FF42C08A818832B4
+:1077500048F48A81FE01E80FF11D93838A818F5FCF
+:107760008A835EC01A822BC0973098F5803849F51D
+:107770009A81992371F1F8828B818B3071F48A811F
+:10778000843059F4CE01ADDC882339F08091790240
+:10779000811115C0402FBE0111C08B818A3479F44C
+:1077A0008A81843061F4CE019CDC882341F0809191
+:1077B0007902811104C0402FBE0181E04ED980E0E2
+:1077C00008C09881911105C09981992341F101C0A8
+:1077D000892F8DA71CA606C0983018F49F5F9CA720
+:1077E00001C01DA6E297069581E0CB31D80709F0CC
+:1077F00098CFFF91EF91DF91CF91BF91AF919F9182
+:107800008F917F916F915F914F913F912F911F9138
+:107810000F91FF900F900FBE0F901F9018951A8236
+:0478200080E8D7CF56
+:040000030000700089
+:00000001FF
diff --git a/bootloaders/BlinkBIOS-328PB.hex b/bootloaders/BlinkBIOS-328PB.hex
new file mode 100644
index 00000000..bfc8318d
--- /dev/null
+++ b/bootloaders/BlinkBIOS-328PB.hex
@@ -0,0 +1,321 @@
+:103800000C943B380C9400380C9400380C9400381D
+:103810000C94E2300C9459390C945A390C943C3A7B
+:103820000C94C1390C94B1350C94E9390C943239AB
+:103830000C94FA390C9469390C94E0300C94B63538
+:043840000C943C3A6E
+:106000000AB400FCFDCF90938900809388008AB584
+:1060100081608ABD08959B01F894409131015091AF
+:10602000320160913301709134017894420F531F13
+:10603000611D711DFC014083518362837383089548
+:10604000CF93C62F0E94DC38882369F08DE50E942B
+:10605000C2388C2F0E94C23885E78C1B0E94C23840
+:10606000CF910C94B138CF910895CF92DF92FF92E7
+:106070000F931F93CF93DF93062FF42E152F0E94BB
+:10608000DC38882319F18BED0E94C238CF2DD12F37
+:106090006E0180E2C80ED11C1BEDF9908F2D0E947D
+:1060A000C2381F0DCC16DD06C1F7802F0E94C23802
+:1060B00082ED801B811B0E94C238DF91CF911F911E
+:1060C0000F91FF90DF90CF900C94B138DF91CF917A
+:1060D0001F910F91FF90DF90CF900895CF93DF93A2
+:1060E000C0E0D1E0DE01EC912E2F22952695269579
+:1060F000237011968C911197982F9770990F990F83
+:10610000922B869586958695E695EF71F0E0EC5B8F
+:10611000FF48E491ED87E92FF0E0EC5BFF48E49164
+:10612000EE87E82FF0E0EC5BFF48E491EF871296F2
+:10613000249681E0AC30B807B1F6DF91CF91089595
+:10614000E0E0F1E0119282E0EE37F807D8F38091B9
+:10615000310190913201A0913301B0913401805E00
+:106160009D4EA54FBF4F8093360190933701A0936A
+:106170003801B0933901B2CFC82FF894E1DFC09352
+:10618000280108E00EBF0FEF0DBF78940C940000BB
+:10619000EDE4F1E0108212AA1092B1011092E30135
+:1061A00010921502109247020895F894EEE3F1E080
+:1061B00011821482168215821286118678940895AF
+:1061C00082E00895FF920F931F93CF93DF93F62EF3
+:1061D000072F142FF1D7882361F087E3D3D7CF2D72
+:1061E000D02F112321F08991CDD71150FACFB9D7F3
+:1061F00081E0DF91CF911F910F91FF900895182FAB
+:10620000C12FDE63DF738D2F90E00E94CA392FEF1C
+:1062100080E792E0215080409040E1F700C000000C
+:10622000B7DF80E090E00E94CA392FEF80E792E06C
+:10623000215080409040E1F700C00000A9DFC1502C
+:1062400021F080913F0180FFDCCFC6E0C15021F0FA
+:1062500080913F0180FF0CC080913F0180FFD0CF33
+:10626000F89480E18093600088E080936000FFCF25
+:1062700080E090E00E94CA392FEF80E792E0215041
+:1062800080409040E1F700C0000082DF80E090E0B5
+:106290000E94CA392FEF80E792E021508040904061
+:1062A000E1F700C0000074DFD1CF2F923F924F92F0
+:1062B0005F926F927F928F929F92AF92BF92CF9296
+:1062C000DF92EF92FF920F931F93CF93DF93CDB79F
+:1062D000DEB7C05CD1090FB6F894DEBF0FBECDBFEC
+:1062E000C82EE62EC355DF4F59834883CD5AD04080
+:1062F00024E0281720F0FF24F394F80E01C0F12CBD
+:106300000E94E93980E090E00E94CA39E11002C0A1
+:1063100018EB01C01DEF37E0C3120EC0312E330C55
+:10632000330C60E177E2CE018F559F4F74DED12EA2
+:10633000222423940FE313C081E090E00C2C01C0D1
+:10634000880F0A94EAF7082F00950F7360E070E059
+:10635000CE018F559F4F5FDE312C212CD12CCB5598
+:10636000DF4F188219821A821B82C55AD0401DDF66
+:10637000A0D683E582D6812F87D6211002C08EE475
+:1063800001C082E57AD6EE2039F04DE4CA54DF4FE1
+:106390004883C65BD04006C053E5CA54DF4F5883DC
+:1063A000C65BD040C355DF4F8881CD5AD040CB5417
+:1063B000DF4F8883C55BD040EE2039F09AE4C055AA
+:1063C000DF4F9883C05BD04006C0EBE0C055DF4F85
+:1063D000E883C05BD040C255DF4FF881CE5AD04031
+:1063E000C554DF4FF883CB5BD04082EDC355DF4F00
+:1063F0002881CD5AD040821B8F1BC055DF4F48816A
+:10640000C05BD040841BC454DF4F8883CC5BD0403A
+:10641000E12E53E0C455DF4F5883CC5AD040C155CC
+:10642000DF4F1882CF5AD0408C2D90E0E2E3E89FF6
+:106430009001E99F300D1124A901435B5E4F3A01A1
+:10644000FA013396C954DF4FF983E883C75BD04024
+:10645000A901405B5E4FCF54DF4F59834883C15B36
+:10646000D040FC01EE0FFF1FC754DF4FF983E883D4
+:10647000C95BD0404F5F5F4FC354DF4F59834883A0
+:10648000CD5BD040E050FF4FCD54DF4FF983E88320
+:10649000C35BD0409E012F573F4FC755DF4F398315
+:1064A0002883C95AD040A901405E5F4FC154DF4FD5
+:1064B00059834883CF5BD040222019F0002309F490
+:1064C0001DC180913F0180FD19C1211082C1F301DE
+:1064D0008081882309F47DC1ECD58CE3CED58C2D49
+:1064E000D3D5C954DF4FE881F981C75BD0408081A3
+:1064F0008B3D09F036C1F3018281833209F031C14D
+:10650000C301EFD5882309F42CC188E4B6D5CF5454
+:10651000DF4FE881F981C15BD04081A1B5D5CF546F
+:10652000DF4FE881F981C15BD04081A18D1122C18B
+:106530008BE2A3D5C754DF4FE881F981C95BD04016
+:10654000E050FF4F818187709D2D9295990F907E2D
+:10655000892B81838D2D8370A1E0B0E0AC0FBD1F2E
+:10656000F0E28F9FA00DB11D112490E2C354DF4FC4
+:10657000E881F981CD5BD04001900D929A95E1F7C9
+:10658000833031F4BE016F5F7F4F832DE7D63394A4
+:10659000D3941D110EC1CD54DF4FE881F981C35B47
+:1065A000D0408081806C808383E08183D12EC5556B
+:1065B000DF4F1882CB5AD040011100C17AD58EE34B
+:1065C0005CD58C2D61D584E458D5BB24B394B10E31
+:1065D0008B2D5AD56B2D8C2D33DDF30110824F2C72
+:1065E000512CF2E3F49D5001F59DB00C112495015E
+:1065F000235B3E4F4901F9018081882309F4FFC0E4
+:1066000058D58CE33AD58F2D3FD5F40183818D3554
+:1066100009F0F3C08281833009F0EFC0C40161D575
+:10662000882309F4EAC081E090E04C010F2C01C0FE
+:10663000880C0A94EAF7C155DF4FF881CF5AD04051
+:10664000F829C155DF4FF883CF5AD040F501E05B00
+:10665000FE4FE1808CE411D58E2D16D55201AA0C87
+:10666000BB1CE11608F4C7C01E1508F0B8C0809422
+:106670000821F501E050FF4F8081806C808381818B
+:106680008760818399249394F501E050FF4F8181C5
+:1066900087709E2D9295990F907E892B818322E39E
+:1066A000249DF001259DF00D1124E35BFE4F108227
+:1066B000ED1408F4A6C0F8944091310150913201D4
+:1066C00060913301709134017894CB55DF4F88810C
+:1066D0009981AA81BB81C55AD04084179507A60726
+:1066E000B70708F4D9C0911087C1F8DCC555DF4F52
+:1066F0002881CB5AD040222309F4DECEDAD488E5B3
+:10670000BCD483E0F82E00E0802F56D5882329F0F2
+:1067100088EE38D58AEE36D524D50F5F0630A1F73E
+:10672000FA94F110F0CF41DD1D1161C130E2139FE9
+:10673000A0011124E0E0F0E080E090E04E175F0758
+:1067400029F02491820F911D3196F8CFC355DF4F68
+:1067500048815981CD5AD0404817590709F047C19F
+:1067600054C1C954DF4FE881F981C75BD0408081B3
+:10677000883E31F0C555DF4F1882CB5AD04015C046
+:10678000F30182818230B1F7C301ABD4882391F346
+:1067900090D48CE372D48C2D77D487E66ED4F1E05C
+:1067A000C555DF4FF883CB5AD0401D1509F404CFEF
+:1067B00005C0C555DF4F1882CB5AD0407AD48EE33E
+:1067C0005CD48C2D61D48CE458D48D2D5DD46D2D8A
+:1067D00002CFC555DF4F1882CB5AD04000CF84E49A
+:1067E0004CD4F501E050FF4F8081806C8083818123
+:1067F000887F836046CF912C47CF912C50CF912C2E
+:1068000057CF57D48EE339D48F2D3ED488E435D476
+:106810008E2D3AD48E2D86958695831508F530E217
+:10682000E39EC0011124DE01AF57BF4FC755DF4FB4
+:1068300048815981C95AD040841B950BFC01EA0F4D
+:10684000FB1FE491ED93C154DF4FE881F981CF5BE9
+:10685000D040EA17FB0791F7AE014F575F4F0BC0CF
+:106860008E2D837041E050E04C0F5D1FF0E28F9F52
+:10687000400D511D11246E2D8F2DF7DB68E770E060
+:10688000CE018B559F4FC7DBE12E23E0C455DF4F70
+:106890002883CC5AD0400FCFC455DF4F5881CC5AF3
+:1068A000D040511121C0F8944091310150913201F2
+:1068B00060913301709134017894CF55DF4F888116
+:1068C0009981AA81BB81C15AD04084179507A60738
+:1068D000B70768F481E090E0042C01C0880F0A94A7
+:1068E000EAF78095082303C0992009F482C0F201D9
+:1068F000EE0FFF1FE050FF4F8181877081830023DF
+:1069000009F4F3CE202F30E045E0F41611F0F394B3
+:1069100001C0F12CC9010F2C02C0959587950A94EE
+:10692000E2F780FFF1CF53E0C455DF4F5883CC5AD4
+:10693000D040BFD38EE3A1D38F2DA6D385E49DD3C2
+:10694000CA54DF4F8881C65BD04097D3CB54DF4F0A
+:106950008881C55BD04098D38F2D2ED48823C9F071
+:10696000C055DF4F8881C05BD0400CD4CB54DF4F83
+:106970008881C55BD04006D4C554DF4F8881CB5B8E
+:10698000D04000D4C454DF4F8881CC5BD040FAD3D0
+:10699000E8D3EF2DF0E0EE0FFF1FE050FF4F8181B5
+:1069A000886F8183C155DF4FE881CF5AD0408E2F49
+:1069B00090E00F2C02C0959587950A94E2F780FD30
+:1069C00003C062E370E002C068E770E0CE018B555F
+:1069D0009F4F21DBC455DF4FF881CC5AD040F15096
+:1069E000C455DF4FF883CC5AD040E12E7ECE83E0F1
+:1069F00006DC01119ECF79CEC455DF4F8881CC5A79
+:106A0000D040882309F44FCF72CFC054DF4F0FB668
+:106A1000F894DEBF0FBECDBFDF91CF911F910F91D4
+:106A2000FF90EF90DF90CF90BF90AF909F908F90AE
+:106A30007F906F905F904F903F902F900895C82F58
+:106A4000F89408E00EBF0FEF0DBF78942EDCC7302E
+:106A500011F481E001C082E08FDBD82F81E08093C8
+:106A600079024695C0E0442319F04695CF5FFBCFED
+:106A7000FB0104811581108260E08C2FE1DAA8010E
+:106A80006D2F8C2FDCDF40E050E0E0E0F0E08491FF
+:106A9000480F511D3196E03A8FE1F807C1F761E0E8
+:106AA00087E0CDDF14B714BE87EF84BF0FB6F8942C
+:106AB000A8958091600088618093600010926000CA
+:106AC0000FBEC0E8C0936100D1E0D09361002FEF0A
+:106AD00080E792E0215080409040E1F700C0000044
+:106AE0002FDB85B7982F916095BF826085BFC0BFAF
+:106AF00084E88093640080916800846080936800DB
+:106B00005F9A729A589A599A269A689A279A699A15
+:106B1000549A529A5E9A5D9A569A559AD0936E00FC
+:106B200082E080937000F2D284B18F6384B987B120
+:106B3000806C87B9789437D4F894C0936100109230
+:106B4000610078948091C00082608093C000809141
+:106B5000C10088608093C100D9D311FD94DF80E02B
+:0E6B60000BDBD4D381E0809379028DDF48DB1C
+:107000003AC00000FDCF0000FBCF0000F9CF000028
+:10701000D9C800004EC100004DC100002DC20000C3
+:10702000B0C100009ECD0000D4C100001BC1000013
+:10703000E1C100004EC10000C3C8000097CD0000B0
+:107040001BC20000FFFEFDFBFAF8F5F2EEEAE6E0F7
+:10705000DAD3CCC3BAB0A5998C7E6F5F4E3B2813B0
+:107060000D09030130313233343536373839616236
+:10707000636465660000112415DD9091C00095FFE2
+:10708000FCCF8093C6000895CF93C82FE82FF0E07F
+:1070900084E0F595E7958A95E1F7EC59FF488491EE
+:1070A000ECDFCF70EC2FF0E0EC59FF488491CF91EA
+:1070B000E4CFCF92DF92EF92FF928AE0DEDFC090C2
+:1070C0003101D0903201E0903301F09034018D2DE8
+:1070D000DBDF8C2DD9DF8AE3FF90EF90DF90CF903C
+:1070E000CCCFFC012281339690E0215018F08191A1
+:1070F000980FFBCF81E0923D09F080E008952E9833
+:1071000070982F9871985C985A9808958FEF87BD62
+:1071100088BD16BC95B5906895BD95B5906495BD34
+:1071200093EA94BD93E29093B00090E89093B300FB
+:107130008093B4001092B200E1EBF0E080818064B3
+:10714000808383B5806883BD83B5826083BD83B54A
+:10715000816083BD82E085BD808383B58F7783BDE9
+:10716000089580EB97E10E940030EDE4F1E0118298
+:1071700013AA1092B2011092E4011092160210921A
+:10718000480208950F931F93CF93DF93082FC8E011
+:10719000D0E011E0812F802319F08CE096E002C04E
+:1071A0008EED9EE00E940030110F219799F7DF913C
+:1071B000CF911F910F910895F89442E3849FF001BD
+:1071C0001124E35BFE4F95A5911103C091E09183DB
+:1071D00001C090E078949923C9F121E030E0A90141
+:1071E00002C0440F551F8A95E2F7CA012091810021
+:1071F0002111FCCF98E190938100109280001092B1
+:1072000085001092840021E030E0309389002093C3
+:10721000880093E0909380002CE036E03093890062
+:1072200020938800B19A90916F00926090936F00C4
+:1072300080938A008AB581608ABD89E1809381004C
+:1072400080EB97E10E94003081E0089580E008958E
+:1072500085EC80937A0080917A0086FDFCCF809146
+:10726000790008951F920F920FB60F9211248F93F9
+:107270009F9380918A0087B983B995E39A95F1F736
+:10728000000083B986B995E09A95F1F7000017B828
+:1072900086B90AB400FC03C01092810003C08AB50D
+:1072A0008E7F8ABD9F918F910F900FBE0F901F9080
+:1072B000189518951F920F920FB60F9211248F9365
+:1072C00086B5809327018F910F900FBE0F901F906E
+:1072D000189590E8899FF0011124F89483E0809339
+:1072E0005700E895789407B600FCFDCFF89485E048
+:1072F00080935700E895789407B600FCFDCFF8948A
+:1073000081E180935700E895789408950F931F9337
+:10731000CF93DF9300E019E3C0E0D1E0980180E073
+:1073200090E0F901459154912E5F3F4FF894FC0194
+:107330000A01D0935700E89511247894029680387A
+:10734000910579F78C2FC5DFCF5F00581F4FCF33E2
+:1073500029F7DF91CF911F910F910895E0E0F0E0C0
+:1073600091E0F894DB012D913D91BD0109019093CD
+:107370005700E895112478943296E038F10589F7A2
+:10738000A8CF81E080930C0180910C018111FCCF8A
+:107390000C946E30E0E0F1E08193919321E0EC30C9
+:1073A000F207D1F7EECF8EE680937C0085EC8093D8
+:1073B0007A008DE58A95F1F700004ADF49DF48DF62
+:1073C00047DF10927A008A3718F082E00C94FF3081
+:1073D0000895F894E1E3F1E080819181A281B38185
+:1073E000805E9D4EA54FBF4F85839683A783B08750
+:1073F00078940895EEDFF89480E88093610081E04E
+:1074000080936100789415BC7ADE1092B10014BCB0
+:107410001092B0006B982FEF80E792E021508040EF
+:107420009040E1F700C000004F9BFECF2FEF80E7B8
+:1074300092E0215080409040E1F700C00000809130
+:107440006D00806880936D0085E083BF8895809192
+:107450006D008F7780936D00F89458DE0E94D530D0
+:107460007894A1DFF89480E8809361001092610025
+:1074700078941092410108951F920F920FB60F92C7
+:107480001124FF920F931F932F933F934F935F937A
+:107490006F937F938F939F93AF93BF93CF93DF931C
+:1074A000EF93FF9316B1109586B578948C5E96B5E0
+:1074B0009817E8F316B917B985E08A95F1F7000037
+:1074C00017B816B98091B20087FFB3C0C0913501DB
+:1074D00080E28C0F8D3708F4A9C080913101909122
+:1074E0003201A0913301B09134010196A11DB11D6B
+:1074F0008093310190933201A0933301B093340112
+:1075000040913601509137016091380170913901F5
+:10751000481759076A077B0708F46CDF80913F0121
+:1075200069B1562F5095551F5527551F90913E0113
+:10753000409142012091430130914401591349C0C7
+:107540004111415067FD2FC02115310529F021500F
+:10755000310911F410924501609147017091480181
+:107560006F5F7F4F7093480160934701613797E1E8
+:10757000790730F08068109248011092470149C0A5
+:10758000693B9BE0790710F0806443C0613B744025
+:1075900008F43FC09091460191113BC0826091E098
+:1075A0009093460136C02115310599F121503109DA
+:1075B00081F590914501913011F4886007C09230B7
+:1075C00011F4806103C080629093400110924501E4
+:1075D00020C041111DC09091450167FD0BC0816025
+:1075E0009F3F09F09F5F10924801109247012AE4E3
+:1075F00031E007C084602115310509F490E0109254
+:1076000046019093450150933E0144E191E002C050
+:1076100044E190E080933F01409342013093440164
+:10762000209343019111D5DE83EA8C0F80933501BD
+:1076300073C08091260190912501C92FD0E082303E
+:1076400009F441C028F4882351F08130C9F062C0A8
+:10765000833009F445C0843009F451C05BC04FDD6C
+:10766000CC0FDD1FCC0FDD1FC050DF4F8F858F3F4C
+:1076700029F083E28093B000539A6B9A81E04AC06C
+:107680006B98923081F030F4992359F0913081F465
+:10769000709A0EC0943059F040F0953049F45A9ADF
+:1076A00007C02E9A05C02F9A03C0719A01C05C9A38
+:1076B000CC0FDD1FCC0FDD1FC050DF4F8F858093B7
+:1076C000B40082E027C08FEF8093B400CC0FDD1FA1
+:1076D000CC0FDD1FC050DF4F8D8587BD83E01AC002
+:1076E00053988093B0008FEF87BDCC0FDD1FCC0F78
+:1076F000DD1FC050DF4F8E8588BD84E00BC08FEF4B
+:1077000088BD9F5F963019F410920C0190E0909321
+:10771000250180E080932601C7E4D2E000E2FF2447
+:10772000F3949CA5802F812309F456C08DA5943035
+:10773000D8F4882309F443C0923010F490E801C0D3
+:1077400090E0282F2695922B80FF42C08A818832B4
+:1077500048F48A81FE01E80FF11D93838A818F5FCF
+:107760008A835EC01A822BC0973098F5803849F51D
+:107770009A81992371F1F8828B818B3071F48A811F
+:10778000843059F4CE01ADDC882339F08091790240
+:10779000811115C0402FBE0111C08B818A3479F44C
+:1077A0008A81843061F4CE019CDC882341F0809191
+:1077B0007902811104C0402FBE0181E04ED980E0E2
+:1077C00008C09881911105C09981992341F101C0A8
+:1077D000892F8DA71CA606C0983018F49F5F9CA720
+:1077E00001C01DA6E297069581E0CB31D80709F0CC
+:1077F00098CFFF91EF91DF91CF91BF91AF919F9182
+:107800008F917F916F915F914F913F912F911F9138
+:107810000F91FF900F900FBE0F901F9018951A8236
+:0478200080E8D7CF56
+:040000030000700089
+:00000001FF
diff --git a/bootloaders/BlinkBIOS.hex b/bootloaders/BlinkBIOS.hex
deleted file mode 100644
index 5fc90dfb..00000000
--- a/bootloaders/BlinkBIOS.hex
+++ /dev/null
@@ -1,280 +0,0 @@
-:102E00000AB400FCFDCF90938900809388008AB5B6
-:102E100081608ABD08959B01F894409131015091E1
-:102E2000320160913301709134017894420F531F45
-:102E3000611D711DFC01408351836283738308957A
-:102E4000CF93C62F7AD5882349F08DE55DD58C2F99
-:102E50005BD585E78C1B58D5CF9146C5CF9108959A
-:102E6000CF92DF92FF920F931F93CF93DF93062FA2
-:102E7000F42E152F62D58823F1F08BED45D5CF2D9B
-:102E8000D12F6E0180E2C80ED11C1BEDF9908F2D61
-:102E90003BD51F0DCC16DD06C9F7802F35D582ED49
-:102EA000801B811B31D5DF91CF911F910F91FF9036
-:102EB000DF90CF9019C5DF91CF911F910F91FF90B7
-:102EC000DF90CF900895CF93DF93C0E0D1E0DE0193
-:102ED000EC912E2F229526952695237011968C9194
-:102EE0001197982F9770990F990F922B8695869529
-:102EF0008695E695EF71F0E0EC5BF74CE491ED8799
-:102F0000E92FF0E0EC5BF74CE491EE87E82FF0E07E
-:102F1000EC5BF74CE491EF871296249681E0AC309D
-:102F2000B807B1F6DF91CF910895E0E0F1E011929A
-:102F300082E0EE37F807D8F38091310190913201A9
-:102F4000A0913301B0913401805E9D4EA54FBF4FDB
-:102F50008093360190933701A0933801B0933901E3
-:102F6000B2CFEDE4F1E0108212AA1092B1011092FA
-:102F7000E30110921502109247020895F894EEE3CF
-:102F8000F1E01182148216821582128611867894DD
-:102F9000089582E00895FF920F931F93CF93DF93DC
-:102FA000F62E072F142FC9D4882361F087E3ACD401
-:102FB000CF2DD02F112321F08991A6D41150FACF13
-:102FC00093D481E0DF91CF911F910F91FF900895ED
-:102FD000182FC12FDE63DF738D2F90E0A7D52FEF61
-:102FE00080E792E0215080409040E1F700C000006F
-:102FF000B8DF80E090E09AD52FEF80E792E0215093
-:1030000080409040E1F700C00000ABDFC15021F0EC
-:1030100080913F0180FFDECFC6E0C15021F080915A
-:103020003F0180FF0CC080913F0180FFD2CFF89418
-:1030300080E18093600088E080936000FFCF80E0B3
-:1030400090E074D52FEF80E792E0215080409040CF
-:10305000E1F700C0000085DF80E090E067D52FEF4A
-:1030600080E792E0215080409040E1F700C00000EE
-:1030700078DFD3CFCF93DF93CDB7DEB7CB5BD1096A
-:103080000FB6F894DEBF0FBECDBFC555DF4F8883A6
-:10309000CB5AD04069D581E08093790280E090E0FE
-:1030A00045D5C555DF4F2881CB5AD0402223F9F0B2
-:1030B000212C312CE0E0F0E08491280E311C319677
-:1030C000E11537E1F307C1F760E177E2CE018F55F3
-:1030D0009F4FA1DE4EE2C655DF4F4883CA5AD0400B
-:1030E0001FE300E088EBF82E96E0B92E43C01DE404
-:1030F000812E11E0912EE12CF12C12E3BE2C1E9DAD
-:1031000060011F9DD00C1124F601E35BFE4F80810E
-:10311000882309F4A9C083818B3009F0A5C082817E
-:10312000843009F0A1C0C4019FD3882309F49CC056
-:10313000F601E05BFE4F2180328001E00E0D06308B
-:1031400019F400E0B5E0BB2E81E090E00B2C01C04B
-:10315000880F0A94EAF7182F10951F7360E070E04B
-:10316000CE018F559F4F57DEC655DF4F1882CA5A82
-:10317000D040F12CCB55DF4F188219821A821B8266
-:10318000C55AD040FBDECB54DF4F2882C55BD04010
-:10319000CA54DF4F3882C65BD04087EC821983194E
-:1031A000C954DF4F8883C75BD04053E0C755DF4F1A
-:1031B0005883C95AD040C455DF4F1882CC5AD040EA
-:1031C0007AEBE72E8B2D90E0E2E3E89F9001E99FF8
-:1031D000300D1124A901435B5E4F3A01FA01339689
-:1031E000C155DF4FF983E883CF5AD040A901405B36
-:1031F0005E4FCF54DF4F59834883C15BD040FC0101
-:10320000EE0FFF1FCD54DF4FF983E883C35BD0403F
-:103210004F5F5F4FC854DF4F59834883C85BD0402E
-:10322000E050FF4FC355DF4FF983E883CD5AD040BC
-:103230002E01F1E84F0E511C9201205E3F4FC65403
-:10324000DF4F39832883CA5BD040C555DF4F3881B3
-:10325000CB5AD040332319F0112309F406C28091D0
-:103260003F0180FF0DC001C23FEFE31AF30A42E3C2
-:10327000840E911C56E0E516F10409F03FCF64CFAF
-:10328000C555DF4F8881CB5AD040811198C0F301DA
-:103290008081882309F493C0C155DF4FE881F9810B
-:1032A000CF5AD04080818B3D09F060C0F30182810C
-:1032B000833209F05BC0C301D7D2882309F456C01A
-:1032C000CF54DF4FE881F981C15BD04081A18F11DC
-:1032D00060C0CD54DF4FE881F981C35BD040E0503E
-:1032E000FF4F818187709F2D9295990F907E892B3A
-:1032F00081838F2D8370A1E0B0E0AC0FBD1FF0E2A1
-:103300008F9FA00DB11D112490E2C854DF4FE881BA
-:10331000F981C85BD04001900D929A95E1F7833016
-:10332000A1F4BE016F5F7F4FC655DF4F8881CA5A37
-:10333000D040E1D3C655DF4F2881CA5AD0402F5F15
-:10334000C655DF4F2883CA5AD040F39438EBF312A6
-:103350002CC0C355DF4FE881F981CD5AD040808120
-:10336000806C808383E08183A12C17C0C155DF4F1F
-:10337000E881F981CF5AD0408081883E51F4F30131
-:103380008281823031F4C3016FD2AA24A3948111C7
-:1033900001C0A12CF8EBFF120CC0111108C069EBA1
-:1033A0008B2D4EDD68EBF62E07C0A12C02C058EB2A
-:1033B000F52E6F2D8B2D44DDF301108201C0A12C61
-:1033C000C02ED12CF2E3FC9D4001FD9D900C1124F8
-:1033D000F401E35BFE4F8081882309F45CC08381A4
-:1033E0008D3509F04DC08281833009F049C0CF018D
-:1033F0003BD2882309F444C021E030E0002E01C014
-:10340000220F0A94EAF7C455DF4F4881CC5AD040C6
-:10341000422BC455DF4F4883CC5AD040F401E05BC7
-:10342000FE4FE180C601880F991F57EB5E15D8F457
-:10343000E9EBEE120BC020951223FC01E050FF4F88
-:103440002081206C20832181276009C0FC01E0508D
-:10345000FF4F2081206C20832181287F23602183DE
-:103460009924939401C0912CFC01E050FF4F81817D
-:1034700087709E2D9295990F907E892B818301C034
-:10348000912C22E32C9DF0012D9DF00D1124E35B86
-:10349000FE4F108201C0912CEF1408F03DC08E2D1C
-:1034A00086958695C655DF4F3881CA5AD040831716
-:1034B000B8F440E2E49EC0011124D20184199509B8
-:1034C000FC01EA0FFB1FE491ED93C654DF4FE88146
-:1034D000F981CA5BD040AE17BF0791F7A2010BC0BC
-:1034E0008E2D837041E050E04C0F5D1FF0E28F9F06
-:1034F000400D511D11246E2D802FB2DC68E770E065
-:10350000CE018B559F4F87DC23E0C755DF4F2883C3
-:10351000C95AD0403AEBE32EF894409131015091D2
-:10352000320160913301709134017894CB55DF4FB3
-:1035300088819981AA81BB81C55AD040841795079B
-:10354000A607B70718F09110CCC08BC0C755DF4F46
-:103550009881C95AD0409111AEC0F8944091310180
-:103560005091320160913301709134017894CF55BC
-:10357000DF4F88819981AA81BB81C15AD0408417CD
-:103580009507A607B70748F481E090E00C2C01C02E
-:10359000880F0A94EAF780951823F601EE0FFF1FB3
-:1035A000E050FF4F818187708183112309F459C056
-:1035B000212F30E00F5F063009F400E0C901002E32
-:1035C00002C0959587950A94E2F780FFF3CF33E028
-:1035D000C755DF4F3883C95AD040802FAED18823DA
-:1035E000A9F08BE091D1CB54DF4F8881C55BD040EF
-:1035F0008BD1CA54DF4F8881C65BD04085D1C95476
-:10360000DF4F8881C75BD0407FD16ED1E02FF0E0E3
-:10361000EE0FFF1FE050FF4F8181886F8183C455FB
-:10362000DF4F4881CC5AD040842F90E0002E02C05A
-:10363000959587950A94E2F780FD40C062E370E0BB
-:10364000CE018B559F4FE7DBC755DF4F5881C95AD5
-:10365000D0405150C755DF4F5883C95AD0408AEBEC
-:10366000E82E31DCAA2009F4F0CD1092790286DC34
-:1036700003E010E0812F61D1882329F088EE44D146
-:103680008AEE42D131D11F5F1630A1F7015089F780
-:1036900088EBF81216C080E090E0E0E0F0E02491C2
-:1036A000820F911D3196E11527E1F207C1F7281627
-:1036B000390639F408C0992089F06FCF68E770E0C7
-:1036C000BFCF83E085DCC555DF4FE881CB5AD040C2
-:1036D000E11102C082E001C081E084D111117DCFEF
-:1036E000C0CFC755DF4FF881C95AD040FF2309F436
-:1036F00034CF53CFF89404E00EBF0FEF0DBF789492
-:10370000B9DC87EF84BF0FB6F894A895809160006C
-:10371000886180936000109260000FBEC0E8C09383
-:103720006100D1E0D09361002FEF80E792E021505B
-:1037300080409040E1F700C00000F7DB85B7982F8C
-:10374000916095BF826085BFC0BF84E880936400AC
-:10375000809168008460809368005F9A729A589A9A
-:10376000599A269A689A279A699A549A529A5E9A0E
-:103770005D9A569A559AD0936E0082E080937000BD
-:1037800088D084B18F6384B987B1806C87B978940D
-:10379000D6D1F894C093610010926100789482D1E0
-:1037A00004B601FE04C08DEF84BF81E0A3DF80E09A
-:0E37B00019D180E09FDF76D181E09CDF09DC3B
-:1038000031C00000FDCF0000FBCF0000F9CF000069
-:10381000C2CB00001AC1000019C10000F7C10000AE
-:103820007DC10000C8CF00009FC10000E7C00000BC
-:10383000ACC100001AC10000ACCB0000BFCF00003B
-:10384000E5C10000FFFEFDFBFAF8F5F2EEEAE6E066
-:10385000DAD3CCC3BAB0A5998C7E6F5F4E3B2813E8
-:103860000D09030111244DDFFC012281339690E004
-:10387000215018F08191980FFBCF81E0923D09F023
-:1038800080E008952E9870982F9871985C985A98B7
-:1038900008958FEF87BD88BD16BC95B5906895BD1E
-:1038A00095B5906495BD93EA94BD93E29093B00072
-:1038B00090E89093B3008093B4001092B200E1EBD3
-:1038C000F0E080818064808383B5806883BD83B5A8
-:1038D000826083BD83B5816083BD82E085BD8083C6
-:1038E00083B58F7783BD089580EB97E189DAEDE4A6
-:1038F000F1E0118213AA1092B2011092E401109229
-:1039000016021092480208950F931F93CF93DF93EE
-:10391000082FC8E0D0E011E0812F802319F08CE05F
-:1039200096E002C08EED9EE06BDA110F2197A1F7B1
-:10393000DF91CF911F910F910895F89442E3849FF6
-:10394000F0011124E35BFE4F95A5911103C091E0B6
-:10395000918301C090E078949923C1F121E030E097
-:10396000A90102C0440F551F8A95E2F7CA012091B0
-:1039700081002111FCCF98E190938100109280008A
-:10398000109285001092840021E030E0309389008D
-:103990002093880093E0909380002CE036E03093F1
-:1039A000890020938800B19A90916F009260909363
-:1039B0006F0080938A008AB581608ABD89E1809317
-:1039C000810080EB97E11CDA81E0089580E00895A2
-:1039D00085EC80937A0080917A0086FDFCCF8091FF
-:1039E00079000895C82FF894A0DAC093280104E064
-:1039F0000EBF0FEF0DBF78940C9400001F920F9232
-:103A00000FB60F9211248F939F9380918A0087B9EC
-:103A100083B995E39A95F1F7000083B986B995E0EB
-:103A20009A95F1F7000017B886B90AB400FC03C0F4
-:103A30001092810003C08AB58E7F8ABD9F918F91BD
-:103A40000F900FBE0F901F90189518951F920F9210
-:103A50000FB60F9211248F9386B5809327018F9113
-:103A60000F900FBE0F901F90189590E8899FF0015E
-:103A70001124F89483E080935700E895789407B672
-:103A800000FCFDCFF89485E080935700E89578948A
-:103A900007B600FCFDCFF89481E180935700E895CC
-:103AA000789408950F931F93CF93DF9310E020E055
-:103AB00037E101E080E090E0E901C80FD91F8038CC
-:103AC000910569F0FE0145915491F894FC010A01B9
-:103AD00000935700E895112478940296EDCF812F3A
-:103AE000C4DF1F5F1E3211F09E01E4CFDF91CF9142
-:103AF0001F910F910895E0E0F0E091E0F894DB0170
-:103B00002D913D91BD01090190935700E895112435
-:103B100078943296E038F10589F7A7CF81E0809359
-:103B20000C0180910C018111FCCFCDC9E0E0F1E0E6
-:103B30008193919321E0EC30F207D1F7EFCF8EE63D
-:103B400080937C0085EC80937A008DE58A95F1F76F
-:103B500000003EDF3DDF3CDF3BDF10927A008A371A
-:103B600010F082E035CA0895F894E1E3F1E0808135
-:103B70009181A281B381805E9D4EA54FBF4F858309
-:103B80009683A783B08778940895EEDFF89480E851
-:103B90008093610081E080936100789415BC72DEAF
-:103BA0001092B10014BC1092B0006B982FEF80E718
-:103BB00092E0215080409040E1F700C000004F9B10
-:103BC000FECF2FEF80E792E0215080409040E1F758
-:103BD00000C0000080916D00806880936D0085E0DA
-:103BE00083BF889580916D008F7780936D00F894E6
-:103BF00050DEC4D97894A3DFF89480E88093610004
-:103C00001092610078941092410108951F920F92D2
-:103C10000FB60F921124EF92FF920F931F932F93E1
-:103C20003F934F935F936F937F938F939F93AF9344
-:103C3000BF93CF93DF93EF93FF9316B1109586B5A3
-:103C400078948C5E96B59817E8F316B917B985E0A5
-:103C50008A95F1F7000017B816B98091B20087FF76
-:103C6000B3C0C091350180E28C0F8D3708F4A9C034
-:103C70008091310190913201A0913301B0913401D2
-:103C80000196A11DB11D8093310190933201A09343
-:103C90003301B09334014091360150913701609166
-:103CA000380170913901481759076A077B0708F4F2
-:103CB0006CDF80913F0169B1562F5095551F5527F4
-:103CC000551F90913E014091420120914301309156
-:103CD0004401591349C04111415067FD2FC02115BE
-:103CE000310529F02150310911F4109245016091FC
-:103CF0004701709148016F5F7F4F70934801609357
-:103D00004701613797E1790730F0806810924801E8
-:103D10001092470149C0693B9BE0790710F080642D
-:103D200043C0613B744008F43FC09091460191113B
-:103D30003BC0826091E09093460136C02115310569
-:103D400099F12150310981F590914501913011F49B
-:103D5000886007C0923011F4806103C08062909344
-:103D600040011092450120C041111DC090914501B4
-:103D700067FD0BC081609F3F09F09F5F1092480173
-:103D8000109247012AE431E007C084602115310513
-:103D900009F490E0109246019093450150933E0142
-:103DA00044E191E002C044E190E080933F01409300
-:103DB000420130934401209343019111D5DE83EAFF
-:103DC0008C0F8093350173C080912601909125015D
-:103DD000C92FD0E0823009F441C028F4882351F083
-:103DE0008130C9F062C0833009F445C0843009F4E1
-:103DF00051C05BC047DDCC0FDD1FCC0FDD1FC050B5
-:103E0000DF4F8F858F3F29F083E28093B000539A74
-:103E10006B9A81E04AC06B98923081F030F499231C
-:103E200059F0913081F4709A0EC0943059F040F0FE
-:103E3000953049F45A9A07C02E9A05C02F9A03C0AC
-:103E4000719A01C05C9ACC0FDD1FCC0FDD1FC050F2
-:103E5000DF4F8F858093B40082E027C08FEF80937F
-:103E6000B400CC0FDD1FCC0FDD1FC050DF4F8D85A0
-:103E700087BD83E01AC053988093B0008FEF87BD51
-:103E8000CC0FDD1FCC0FDD1FC050DF4F8E8588BDEE
-:103E900084E00BC08FEF88BD9F5F963019F41092BD
-:103EA0000C0190E09093250180E080932601C7E407
-:103EB000D2E000E2F12CEE24E3949CA5802F812334
-:103EC00009F43EC08DA59430D0F48823B1F192302E
-:103ED00010F490E801C090E0282F2695922B80FFE7
-:103EE0002BC08A81883248F48A81FE01E80FF11DD7
-:103EF00093838A818F5F8A8338C01A8214C0973077
-:103F0000E0F4803891F49A819923B9F0E8828B81AA
-:103F10008B3049F48A81843031F4CE01A5DC8823CA
-:103F200011F0FF24F39480E008C09881911105C03E
-:103F300099819923C9F001C0892F8DA71CA606C0BD
-:103F4000983018F49F5F9CA701C01DA6E2970695C4
-:103F500081E0CB31D80709F0B0CFFF2041F080914C
-:103F60007902811104C025DC1A8280E8E6CFFF9136
-:103F7000EF91DF91CF91BF91AF919F918F917F9101
-:103F80006F915F914F913F912F911F910F91FF90F2
-:0C3F9000EF900F900FBE0F901F9018953F
-:0400000300003800C1
-:00000001FF
diff --git a/bootloaders/readme.MD b/bootloaders/readme.MD
index 4b36726a..6cfafd8c 100644
--- a/bootloaders/readme.MD
+++ b/bootloaders/readme.MD
@@ -1,13 +1,13 @@
-This folder contains the BlinkBIOS bootloader HEX file. This file is created by the BlinkBIOS repo...
+This folder contains the BlinkBIOS bootloader HEX files. The BlinkBIOS is a hardware abstraction layer that is loaded into the bootloader area of flash.
-https://github.com/bigjosh/Move38-BlinkBIOS
-
-..and then copied here after each compile by an Atmel Studio post-build event. Note that the this bootloader directory is hardcoded into the text of that event.
+The blinkBIOS is an abstraction layer that provides access to the blinks hardware and is defined by the `blinkbios_*.h` files in the `cores/blinklib/shared` directory.
+Ideally we would like to program the BIOS once into each blink when it is manufactured and then only update the application section of the flash thereafter, but unfortunately on this chip the entire flash is always erased on each hardware programming cycle, so we must reprogram the bootloader each time. That is why this HEX file must be included here.
+
This file is used by...
-1. The `upload` and `program` recipes to download a new sketch to a blink. Note that we could make upload only update the actual program and not the BIOS for faster turnaround during development, but I do not want to change this behavior now. The path to the bootloader is hardcoded into the recipes but is relative to the platform folder.
-2. The `Export Binary` function which creates a single HEX file with both the current sketch and the BIOS. In this case, the folder name must be `bootloader` as this is hardcoded into the IDE.
+1. The `program` recipe in `platform.txt` that downloads a new sketch to a blink.
+2. The `Export Binary` function which creates a single HEX file with both the current sketch and the BIOS. Note that this folder must be named `bootloader` as this is hardcoded into the Arduino IDE.
\ No newline at end of file
diff --git a/cores/blinklib/blinklib.cpp b/cores/blinklib/blinklib.cpp
index e2777f5c..d5961c5a 100644
--- a/cores/blinklib/blinklib.cpp
+++ b/cores/blinklib/blinklib.cpp
@@ -599,12 +599,11 @@ static void RX_IRFaces() {
} else { // (packetDataLen>1)
-
-
+
if ( decodedByte == DATAGRAM_SPECIAL_VALUE) {
uint8_t datagramPayloadLen = packetDataLen-2; // We deduct 2 from he length to account for the header byte and the trailing checksum byte
- const uint8_t *datagramPayloadData = packetData+1; // Skip the packet header byte
+ volatile const uint8_t *datagramPayloadData = packetData+1; // Skip the packet header byte
// Long packets are kind of a special case since we do not mark them read immediately
if ( computePacketChecksum( datagramPayloadData , datagramPayloadLen ) == datagramPayloadData[ datagramPayloadLen ] ) { // Run checksum on payload bytes after the header, compare that to the checksum at the end
@@ -615,7 +614,7 @@ static void RX_IRFaces() {
face->inDatagramLen = datagramPayloadLen;
- memcpy( face->inDatagramData , datagramPayloadData , datagramPayloadLen); // Skip the header bytes
+ memcpy( face->inDatagramData , const_cast< const uint8_t *>(datagramPayloadData) , datagramPayloadLen); // Skip the header bytes
}
@@ -1151,9 +1150,22 @@ byte getSerialNumberByte( byte n ) {
// Useful to check is a newer feature is available on this blink.
byte getBlinkbiosVersion() {
- return BLINKBIOS_VERSION_VECTOR();
+ return BLINKBIOS_VERSION_VECTOR() & 3;
+}
+
+// Returns 1 if this is a "MAX" blink. MAX blinks have more memory for programs and code.
+
+uint8_t isMAXblink() {
+ return BLINKBIOS_VERSION_VECTOR() & VERSION_CAPABILITY_BIT_MAX;
}
+// Returns 1 if this is a "NFC" blink. NFC blinks can store game statistics. See saveGameStat() below.
+
+uint8_t isNFCblink() {
+ return BLINKBIOS_VERSION_VECTOR() & VERSION_CAPABILITY_BIT_NFC;
+}
+
+
// Returns 1 if we have slept and woken since last time we checked
// Best to check as last test at the end of loop() so you can
// avoid intermediate display upon waking.
@@ -1328,9 +1340,8 @@ byte sin8_C( byte theta)
// Thanks for the extra 4 bytes of flash gcc!)
void __attribute__((noreturn)) run(void) {
-
+
// TODO: Is this right? Should hasWoke() return true or false on the first check after start up?
-
blinkbios_button_block.wokeFlag = 1; // Clear any old wakes (wokeFlag is cleared to 0 on wake)
updateNow(); // Initialize out internal millis so that when we reset the warm sleep counter it is right, and so setup sees the right millis time
@@ -1339,7 +1350,7 @@ void __attribute__((noreturn)) run(void) {
statckwatcher_init(); // Set up the sentinel byte at the top of RAM used by variables so we can tell if stack clobbered it
setup();
-
+
while (1) {
// Did we blow the stack?
@@ -1389,11 +1400,6 @@ void __attribute__((noreturn)) run(void) {
warm_sleep_cycle();
- // Clear out the press that put us to sleep so we do not see it again
- // Also clear out everything else so we start with a clean slate on waking
-
- blinkbios_button_block.bitflags = 0;
-
} else {
// They let go before we got to 7 seconds, so enter SEED mode! (and never return!)
@@ -1413,10 +1419,6 @@ void __attribute__((noreturn)) run(void) {
warm_sleep_cycle();
- // Clear out the press that put us to sleep so we do not see it again
- // Also clear out everything else so we start with a clean slate on waking
- blinkbios_button_block.bitflags = 0;
-
}
// Capture time snapshot
@@ -1429,6 +1431,10 @@ void __attribute__((noreturn)) run(void) {
viralPostponeWarmSleep();
}
+ // Update the IR RX state
+ // Receive any pending packets
+ RX_IRFaces();
+
cli();
buttonSnapshotDown = blinkbios_button_block.down;
buttonSnapshotBitflags |= blinkbios_button_block.bitflags; // Or any new flags into the ones we got
@@ -1437,10 +1443,6 @@ void __attribute__((noreturn)) run(void) {
sei();
- // Update the IR RX state
- // Receive any pending packets
- RX_IRFaces();
-
loop();
// Update the pixels to match our buffer
diff --git a/cores/blinklib/blinklib.h b/cores/blinklib/blinklib.h
index 95e62002..48cf7ce8 100644
--- a/cores/blinklib/blinklib.h
+++ b/cores/blinklib/blinklib.h
@@ -1,17 +1,9 @@
/*
* blkinklib.h
*
- * This defines a statefull view of the blinks tile interactions with neighbors.
+ * Used for programming blinks by Move38 with the Arduino IDE. More info at move38.com.
*
- * In this view, each tile has a "state" that is represented by a number between 1 and 127.
- * This state value is continuously broadcast on all of its faces.
- * Each tile also remembers the most recently received state value from he neighbor on each of its faces.
- *
- * Note that this library depends on the blinklib library for communications with neighbors. The blinklib
- * IR read functions are not available when using the blinkstate library.
- *
- * Note that the beacon transmissions only occur when the loop() function returns, so it is important
- * that sketches using this model return from loop() frequently.
+ * This file is automatically included by the Arduino IDE when the blinks board type is selected.
*
*/
@@ -32,7 +24,6 @@
*/
// The value of the data sent and received on faces via IR can be between 0 and IR_DATA_VALUE_MAX
-// If you try to send higher than this, the max value will be sent.
#define IR_DATA_VALUE_MAX 63
@@ -55,7 +46,7 @@ byte didValueOnFaceChange( byte face );
byte isValueReceivedOnFaceExpired( byte face );
-// Returns false if their has been a neighbor seen recently on any face, returns true otherwise.
+// Returns false if there has been a neighbor seen recently on any face, returns true otherwise.
bool isAlone();
// Set value that will be continuously broadcast on specified face.
@@ -96,7 +87,7 @@ const byte *getDatagramOnFace( uint8_t face );
// Frees up the buffer holding the datagram data. Do this as soon as possible after you have
// processed the datagram to free up the slot for the next incoming datagram on this face.
// If a new datagram is recieved on a face before markDatagramReadOnFace() is called then
-// the new datagram is siliently discarded.
+// the new datagram is silently discarded.
void markDatagramReadOnFace( uint8_t face );
@@ -122,13 +113,13 @@ void sendDatagramOnFace( const void *data, byte len , byte face );
*/
-// Debounced view of button state. true if the button currently pressed.
+// Debounced view of button state. True if the button currently pressed.
bool buttonDown(void);
// Was the button pressed or lifted since the last time we checked?
// Note that these register the change the instant the button state changes
-// without any delay, so good for latency sensitive cases.
+// without any delay, so good for latency-sensitive cases.
// It is debounced, so the button must have been in the previous state a minimum
// debounce time before a new detection will occur.
@@ -150,16 +141,13 @@ bool buttonDoubleClicked();
bool buttonMultiClicked();
-
// The number of clicks in the longest consecutive valid click cycle since the last time called.
byte buttonClickCount(void);
// Remember that a long press fires while the button is still down
bool buttonLongPressed(void);
-// 6 second press. Note that this will trigger seed mode if the blink is alone so
-// you will only ever see this if blink has neighbors when the button hits the 6 second mark.
-// Remember that a long press fires while the button is still down
+// Remember that a long long press fires while the button is still down
bool buttonLongLongPressed(void);
/*
@@ -186,7 +174,6 @@ typedef pixelColor_t Color;
// R,G,B are all in the domain 0-31
// Here we expose the internal color representation, but it is worth it
// to get the performance and size benefits of static compilation
-// Shame no way to do this right in C/C++
#define MAKECOLOR_5BIT_RGB(r,g,b) (pixelColor_t(r,g,b,1))
@@ -255,10 +242,11 @@ void setFaceColor( byte face, Color newColor );
// Important notes:
// 1) does not increment while sleeping
// 2) is only updated between loop() interations
-// 3) is not monotonic, so always use greater than
+// 3) is monotonic upwards
+// 4) is not continuous, so always use greater than
// and less than rather than equals for comparisons
-// 4) overflows after about 50 days
-// 5) is only accurate to about +/-10%
+// 5) overflows after about 50 days
+// 6) is only accurate to about +/-10%
unsigned long millis(void);
@@ -266,21 +254,21 @@ class Timer {
private:
- uint32_t m_expireTime; // When this timer will expire
+ uint32_t m_expireTime; // When this timer will expire
public:
- Timer() {}; // Timers come into this world pre-expired.
+ Timer() {}; // Timers come into this world pre-expired.
bool isExpired();
uint32_t getRemaining();
- void set( uint32_t ms ); // This time will expire ms milliseconds from now
+ void set( uint32_t ms ); // This time will expire ms milliseconds from now
void add( uint16_t ms );
- void never(void); // Make this timer never expire (unless set())
+ void never(void); // Make this timer never expire (unless set() again)
};
@@ -373,13 +361,19 @@ void setup(void);
void loop();
-
/*
- Some syntactic sugar to make our programs look not so ugly.
+ Use these to find out what your blink is capable of
*/
+// Returns 1 if this is a "MAX" blink. MAX blinks have more memory for programs and code.
+
+uint8_t isMAXblink();
+
+// Returns 1 if this is a "NFC" blink. NFC blinks can store game statistics. See saveGameStat() below.
+
+uint8_t isNFCblink();
// 'Cause C ain't got no iterators and all those FOR loops are too ugly.
diff --git a/cores/blinklib/gamestat.cpp b/cores/blinklib/gamestat.cpp
new file mode 100644
index 00000000..3d95ca67
--- /dev/null
+++ b/cores/blinklib/gamestat.cpp
@@ -0,0 +1,21 @@
+#include
+
+#include
+
+#include
+
+#include "blinklib.h"
+#include "shared/blinkbios_shared_functions.h"
+
+#include "gamestat.h"
+
+uint8_t saveGameStat( const void *gamestatData , uint8_t gameStatLen ) {
+
+ // Check if we are even running on an NFC blink.
+ if (!isNFCblink()) {
+ return 2; // Not an NFC blink failure
+ }
+
+ return BLINKBIOS_MULITPLEX_VECTOR( BLINKBIOS_MULITPLEX_FUNCTION_SAVE_GAMESTAT , gamestatData , gameStatLen );
+
+}
diff --git a/cores/blinklib/gamestat.h b/cores/blinklib/gamestat.h
new file mode 100644
index 00000000..ed325530
--- /dev/null
+++ b/cores/blinklib/gamestat.h
@@ -0,0 +1,13 @@
+// Save a game statistic to be uploaded next time this blink connects to a phone via NFC.
+// The internal format of the stat is up to the game. Whatever you put here will go up to the game stats server
+// and it will decode it. The gamestat can be up to BLINKBOIS_GAMESTAT_DATA_MAXLEN bytes long.
+//
+// Your game must be registered with the good folks at Move38.com for the game stats to actually show up anywhere.
+// This call will be ignored in non-NFC blinks.
+//
+// Returns:
+// 0 on success
+// 1 on failure because passed len greater than max allowed len
+// 2 on failure becuase not an NFC blink
+
+uint8_t saveGameStat( const void *gamestatData , uint8_t gameStatLen );
diff --git a/cores/blinklib/shared/BlinkBIOS.hex b/cores/blinklib/shared/BlinkBIOS.hex
deleted file mode 100644
index ae7fbb2f..00000000
--- a/cores/blinklib/shared/BlinkBIOS.hex
+++ /dev/null
@@ -1,278 +0,0 @@
-:102E00000AB400FCFDCF90938900809388008AB5B6
-:102E100081608ABD08959B01F894409131015091E1
-:102E2000320160913301709134017894420F531F45
-:102E3000611D711DFC01408351836283738308957A
-:102E4000CF93C62F7AD5882349F08DE55DD58C2F99
-:102E50005BD585E78C1B58D5CF9146C5CF9108959A
-:102E6000CF92DF92FF920F931F93CF93DF93062FA2
-:102E7000F42E152F62D58823F1F08BED45D5CF2D9B
-:102E8000D12F6E0180E2C80ED11C1BEDF9908F2D61
-:102E90003BD51F0DCC16DD06C9F7802F35D582ED49
-:102EA000801B811B31D5DF91CF911F910F91FF9036
-:102EB000DF90CF9019C5DF91CF911F910F91FF90B7
-:102EC000DF90CF900895CF93DF93C0E0D1E0DE0193
-:102ED000EC912E2F229526952695237011968C9194
-:102EE0001197982F9770990F990F922B8695869529
-:102EF0008695E695EF71F0E0EC5BF74CE491ED8799
-:102F0000E92FF0E0EC5BF74CE491EE87E82FF0E07E
-:102F1000EC5BF74CE491EF871296249681E0AC309D
-:102F2000B807B1F6DF91CF910895E0E0F1E011929A
-:102F300082E0EE37F807D8F38091310190913201A9
-:102F4000A0913301B0913401805E9D4EA54FBF4FDB
-:102F50008093360190933701A0933801B0933901E3
-:102F6000B2CFEDE4F1E0108212AA1092B1011092FA
-:102F7000E30110921502109247020895F894EEE3CF
-:102F8000F1E01182148216821582128611867894DD
-:102F9000089582E00895FF920F931F93CF93DF93DC
-:102FA000F62E072F142FC9D4882361F087E3ACD401
-:102FB000CF2DD02F112321F08991A6D41150FACF13
-:102FC00093D481E0DF91CF911F910F91FF900895ED
-:102FD000182FC12FDE63DF738D2F90E09ED52FEF6A
-:102FE00080E792E0215080409040E1F700C000006F
-:102FF000B8DF80E090E091D52FEF80E792E021509C
-:1030000080409040E1F700C00000ABDFC15021F0EC
-:1030100080913F0180FFDECFC6E0C15021F080915A
-:103020003F0180FF0CC080913F0180FFD2CFF89418
-:1030300080E18093600088E080936000FFCF80E0B3
-:1030400090E06BD52FEF80E792E0215080409040D8
-:10305000E1F700C0000085DF80E090E05ED52FEF53
-:1030600080E792E0215080409040E1F700C00000EE
-:1030700078DFD3CF14BE0FB6F894A8958091600086
-:10308000886180936000109260000FBEC1E6D0E0BE
-:1030900010E8188301E008838EE680937C0045DF0A
-:1030A00085B7982F916095BF826085BF10BF84E877
-:1030B00080936400E8E6F0E08081846080835F9A1A
-:1030C000729A589A599A269A689A279A699A549A9B
-:1030D000529A5E9A5D9A569A559A00936E0082E0D3
-:1030E00080937000D6D380E0E82E81E0F82EF701BF
-:1030F00000A784B18F6384B987B1806C87B9789455
-:1031000086EC80937A0012D5F8941883188278940C
-:10311000F70110A6BED45CD4CF93DF93CDB7DEB752
-:10312000CB5BD1090FB6F894DEBF0FBECDBFC4553F
-:10313000DF4F8883CC5AD04008D581E08093790254
-:1031400080E090E0EAD4C455DF4F2881CC5AD040CB
-:103150002223F9F0412C512CE0E0F0E08491480E5C
-:10316000511C3196E11537E1F307C1F768E873E1C7
-:10317000CE018F559F4F4FDE4EE2C655DF4F48833D
-:10318000CA5AD0401FE300E088EBF82E96E0B92E33
-:1031900043C01DE4812E11E0912EE12CF12C12E3AD
-:1031A000BE2C1E9D60011F9DD00C1124F601E35B17
-:1031B000FE4F8081882309F4AAC083818B3009F0F7
-:1031C000A6C08281843009F0A2C0C4014DD38823F7
-:1031D00009F49DC0F601E05BFE4F4180528001E0A2
-:1031E0000E0D063019F400E0B5E0BB2E81E090E052
-:1031F0000B2C01C0880F0A94EAF7182F10951F7343
-:1032000060E070E0CE018F559F4F05DEC655DF4F61
-:103210001882CA5AD040F12CCB55DF4F1882198240
-:103220001A821B82C55AD040A9DECB54DF4F488298
-:10323000C55BD040CA54DF4F5882C65BD04087EC94
-:10324000282E24182518C954DF4F2882C75BD04088
-:1032500053E0C755DF4F5883C95AD040C555DF4F9B
-:103260001882CB5AD0407AEBE72E8B2D90E0E2E328
-:10327000E89F9001E99F300D1124A901435B5E4F47
-:103280001A01FA013396C155DF4FF983E883CF5A0B
-:10329000D040A901405B5E4FCF54DF4F5983488334
-:1032A000C15BD040FC01EE0FFF1FCD54DF4FF9830F
-:1032B000E883C35BD0404F5F5F4FC854DF4F5983F3
-:1032C0004883C85BD040E050FF4FC355DF4FF983C0
-:1032D000E883CD5AD0403E01F1E86F0E711C930196
-:1032E000205E3F4FC654DF4F39832883CA5BD040EE
-:1032F000C455DF4F3881CC5AD040332319F0112305
-:1033000009F406C280913F0180FF0DC001C23FEF6A
-:10331000E31AF30A42E3840E911C56E0E516F10429
-:1033200009F03ECF63CFC455DF4F8881CC5AD040DF
-:10333000811198C0F1018081882309F493C0C1559F
-:10334000DF4FE881F981CF5AD04080818B3D09F071
-:1033500060C0F1018281833209F05BC0C10184D277
-:10336000882309F456C0CF54DF4FE881F981C15B4F
-:10337000D04081A18F1160C0CD54DF4FE881F98129
-:10338000C35BD040E050FF4F818187709F2D9295A5
-:10339000990F907E892B81838F2D8370A1E0B0E0FF
-:1033A000AC0FBD1FF0E28F9FA00DB11D112490E264
-:1033B000C854DF4FE881F981C85BD04001900D927D
-:1033C0009A95E1F78330A1F4BE016F5F7F4FC65538
-:1033D000DF4F8881CA5AD04085D3C655DF4F288138
-:1033E000CA5AD0402F5FC655DF4F2883CA5AD040F3
-:1033F000F39438EBF3122CC0C355DF4FE881F98109
-:10340000CD5AD0408081806C808383E08183A12C61
-:1034100017C0C155DF4FE881F981CF5AD040808174
-:10342000883E51F4F1018281823031F4C1011CD215
-:10343000AA24A394811101C0A12CF8EBFF120CC0A7
-:10344000111108C069EB8B2DFBDC68EBF62E07C071
-:10345000A12C02C058EBF52E6F2D8B2DF1DCF10164
-:10346000108201C0A12CC02ED12CF2E3FC9D4001A2
-:10347000FD9D900C1124F401E35BFE4F80818823B5
-:1034800009F45CC083818D3509F04DC082818330A1
-:1034900009F049C0CF01E8D1882309F444C021E0F4
-:1034A00030E0002E01C0220F0A94EAF7C555DF4F25
-:1034B0004881CB5AD040422BC555DF4F4883CB5A69
-:1034C000D040F401E05BFE4FE180C601880F991FF8
-:1034D00057EB5E15D8F4E9EBEE120BC020951223E2
-:1034E000FC01E050FF4F2081206C20832181276068
-:1034F00009C0FC01E050FF4F2081206C2083218116
-:10350000287F236021839924939401C0912CFC018E
-:10351000E050FF4F818187709E2D9295990F907E8C
-:10352000892B818301C0912C22E32C9DF0012D9DDC
-:10353000F00D1124E35BFE4F108201C0912CEF14BB
-:1035400008F03DC08E2D86958695C655DF4F388193
-:10355000CA5AD0408317B8F440E2E49EC001112457
-:10356000D30186199709FC01EA0FFB1FE491ED9343
-:10357000C654DF4FE881F981CA5BD040AE17BF0760
-:1035800091F7A3010BC08E2D837041E050E04C0FEA
-:103590005D1FF0E28F9F400D511D11246E2D802F75
-:1035A0005FDC68E770E0CE018B559F4F34DC23E091
-:1035B000C755DF4F2883C95AD0403AEBE32EF89421
-:1035C0004091310150913201609133017091340189
-:1035D0007894CB55DF4F88819981AA81BB81C55AE8
-:1035E000D04084179507A607B70718F09110C1C0FF
-:1035F0008BC0C755DF4FE881C95AD040E111AEC03A
-:10360000F8944091310150913201609133017091F1
-:1036100034017894CF55DF4F88819981AA81BB818D
-:10362000C15AD04084179507A607B70748F481E030
-:1036300090E00C2C01C0880F0A94EAF780951823BB
-:10364000F601EE0FFF1FE050FF4F818187708183ED
-:10365000112309F459C0212F30E00F5F063009F41F
-:1036600000E0C901002E02C0959587950A94E2F703
-:1036700080FFF3CF33E0C755DF4F3883C95AD040BE
-:10368000802F5BD18823A9F08BE03ED1CB54DF4F54
-:103690008881C55BD04038D1CA54DF4F8881C65B72
-:1036A000D04032D1C954DF4F8881C75BD0402CD184
-:1036B0001BD1E02FF0E0EE0FFF1FE050FF4F8181A4
-:1036C000886F8183C555DF4F4881CB5AD040842F06
-:1036D00090E0002E02C0959587950A94E2F780FD50
-:1036E00040C062E370E0CE018B559F4F94DBC7551D
-:1036F000DF4F5881C95AD0405150C755DF4F5883CA
-:10370000C95AD0408AEBE82EDEDBAA2009F4F0CDBE
-:103710001092790233DC98EBF91226C080E090E039
-:10372000E0E0F0E02491820F911D3196E11527E150
-:10373000F207C1F748165906B9F403E010E0812FEB
-:10374000FCD0882329F088EEDFD08AEEDDD0CCD003
-:103750001F5F1630A1F7015089F73AD1992031F057
-:103760006FCF68E770E0BFCF83E032DC111188CF04
-:10377000CBCFC755DF4FF881C95AD040FF2309F49A
-:103780003FCF5ECFF89404E00EBF0FEF0DBF7894EB
-:0E379000C3DC80E0F7DF7DD181E0F4DF19DCDF
-:1038000031C00000FDCF0000FBCF0000F9CF000069
-:10381000C2CB000011C1000010C10000E9C10000CE
-:1038200074C10000B8CF000090C10000DAC00000F1
-:103830009DC1000011C10000ACCB0000AFCF000063
-:10384000D7C10000FFFEFDFBFAF8F5F2EEEAE6E074
-:10385000DAD3CCC3BAB0A5998C7E6F5F4E3B2813E8
-:103860000D090301112406DCFC012281339690E04E
-:10387000215018F08191980FFBCF81E0923D09F023
-:1038800080E008952E9870982F9871985C985A98B7
-:1038900008958FEF87BD88BD16BC95B5906895BD1E
-:1038A00095B5906495BD93EA94BD93E29093B00072
-:1038B00090E89093B3008093B4001092B200E1EBD3
-:1038C000F0E080818064808383B5806883BD83B5A8
-:1038D000826083BD83B5816083BD82E085BD8083C6
-:1038E00083B58F7783BD089580EB97E189DAEDE4A6
-:1038F000F1E0118213AA1092B2011092E401109229
-:1039000016021092480208950F931F93CF93DF93EE
-:10391000082FC8E0D0E011E0812F802319F08CE05F
-:1039200096E002C08EED9EE06BDA110F2197A1F7B1
-:10393000DF91CF911F910F910895F89442E3849FF6
-:10394000F0011124E35BFE4F95A5911103C091E0B6
-:10395000918301C090E078949923C1F121E030E097
-:10396000A90102C0440F551F8A95E2F7CA012091B0
-:1039700081002111FCCF98E190938100109280008A
-:10398000109285001092840021E030E0309389008D
-:103990002093880093E0909380002CE036E03093F1
-:1039A000890020938800B19A90916F009260909363
-:1039B0006F0080938A008AB581608ABD89E1809317
-:1039C000810080EB97E11CDA81E0089580E00895A2
-:1039D000F894ABDA04E00EBF0FEF0DBF78940C94AF
-:1039E00000001F920F920FB60F9211242F938F9306
-:1039F0009F9390918A0086B1892397B993B92AE160
-:103A00002A95F1F700C093B986B995E09A95F1F738
-:103A1000000017B886B90AB400FC03C010928100F8
-:103A200003C08AB58E7F8ABD9F918F912F910F9091
-:103A30000FBE0F901F90189518951F920F920FB6FA
-:103A40000F9211248F9386B5809327018F910F9049
-:103A50000FBE0F901F90189590E8899FF0011124D8
-:103A6000F89483E080935700E895789407B600FCBB
-:103A7000FDCFF89485E080935700E895789407B6D9
-:103A800000FCFDCFF89481E180935700E89578948D
-:103A900008950F931F93CF93DF9310E020E037E159
-:103AA00001E080E090E0E901C80FD91F803891055E
-:103AB00069F0FE0145915491F894FC010A010093CC
-:103AC0005700E895112478940296EDCF812FC4DF3A
-:103AD0001F5F1E3211F09E01E4CFDF91CF911F9145
-:103AE0000F910895E0E0F0E091E0F894DB012D9172
-:103AF0003D91BD01090190935700E89511247894F8
-:103B00003296E038F10589F7A7CF81E080930C0168
-:103B100080910C018111FCCFD6C9E0E0F1E08193E6
-:103B2000919321E0EC30F207D1F7EFCF00008091C4
-:103B30007A0086FDFCCF8091790096EC90937A0014
-:103B400087FF02C082E044CA0895F894E1E3F1E0FF
-:103B500080819181A281B381805E9D4EA54FBF4F30
-:103B600085839683A783B08778940895F89480E836
-:103B70008093610081E080936100789415BC82DEBF
-:103B80001092B10014BC1092B0006B982FEF80E738
-:103B900092E0215080409040E1F700C000004F9B30
-:103BA000FECF2FEF80E792E0215080409040E1F778
-:103BB00000C0000080916D00806880936D0085E0FA
-:103BC00083BF889580916D008F7780936D0061DE53
-:103BD00086EC80937A00AADFF89480E880936100F5
-:103BE000109261007894CAD9B0DF10924101089513
-:103BF0001F920F920FB60F921124EF92FF920F9324
-:103C00001F932F933F934F935F936F937F938F9364
-:103C10009F93AF93BF93CF93DF93EF93FF9316B12F
-:103C2000109516B917B985E18A95F1F7000095E06E
-:103C30009A95F1F7000017B816B978948091B20000
-:103C400087FFBDC0C091350180E28C0F8D3708F42D
-:103C5000B3C08091310190913201A0913301B091B4
-:103C600034010196A11DB11D809331019093320161
-:103C7000A0933301B0933401409136015091370144
-:103C80006091380170913901481759076A077B071D
-:103C900008F46CDF80913F0169B1562F5095551F94
-:103CA0005527551F90913E014091420120914301BB
-:103CB00030914401591349C04111415067FD2FC053
-:103CC0002115310529F02150310911F410924501D7
-:103CD00060914701709148016F5F7F4F7093480179
-:103CE00060934701613797E1790730F0806810925F
-:103CF00048011092470149C0693B9BE0790710F0E9
-:103D0000806443C0613B744008F43FC09091460119
-:103D100091113BC0826091E09093460136C021151D
-:103D2000310599F12150310981F59091450191308A
-:103D300011F4886007C0923011F4806103C0806282
-:103D4000909340011092450120C041111DC09091F7
-:103D5000450167FD0BC081609F3F09F09F5F109296
-:103D60004801109247012AE431E007C08460211520
-:103D7000310509F490E0109246019093450150936B
-:103D80003E0144E191E002C044E190E080933F01B4
-:103D90004093420130934401209343019111D5DEB9
-:103DA00080912801811106C081E080932801BEDE48
-:103DB0001092280183EA8C0F8093350173C08091A3
-:103DC000260190912501C92FD0E0823009F441C02D
-:103DD00028F4882351F08130C9F062C0833009F49F
-:103DE00045C0843009F451C05BC04CDDCC0FDD1FF1
-:103DF000CC0FDD1FC050DF4F8F858F3F29F083E24E
-:103E00008093B000539A6B9A81E04AC06B989230CD
-:103E100081F030F4992359F0913081F4709A0EC0FA
-:103E2000943059F040F0953049F45A9A07C02E9AD0
-:103E300005C02F9A03C0719A01C05C9ACC0FDD1F98
-:103E4000CC0FDD1FC050DF4F8F858093B40082E020
-:103E500027C08FEF8093B400CC0FDD1FCC0FDD1F88
-:103E6000C050DF4F8D8587BD83E01AC05398809383
-:103E7000B0008FEF87BDCC0FDD1FCC0FDD1FC05012
-:103E8000DF4F8E8588BD84E00BC08FEF88BD9F5FBC
-:103E9000963019F410920C0190E09093250180E087
-:103EA00080932601C7E4D2E000E2F12CEE24E394F3
-:103EB0009CA5802F812309F43EC08DA59430D0F4B9
-:103EC0008823B1F1923010F490E801C090E0282FDF
-:103ED0002695922B80FF2BC08A81883248F48A81F4
-:103EE000FE01E80FF11D93838A818F5F8A8338C0BA
-:103EF0001A8214C09730E0F4803891F49A819923A3
-:103F0000B9F0E8828B818B3049F48A81843031F4B6
-:103F1000CE01AADC882311F0FF24F39480E008C0CE
-:103F20009881911105C099819923C9F001C0892F09
-:103F30008DA71CA606C0983018F49F5F9CA701C0EF
-:103F40001DA6E297069581E0CB31D80709F0B0CFE6
-:103F5000FF2041F080917902811104C01ADC1A829D
-:103F600080E8E6CFFF91EF91DF91CF91BF91AF91C4
-:103F70009F918F917F916F915F914F913F912F9181
-:103F80001F910F91FF90EF900F900FBE0F901F9019
-:023F9000189582
-:0400000300003800C1
-:00000001FF
diff --git a/cores/blinklib/shared/blinkbios_shared_functions.h b/cores/blinklib/shared/blinkbios_shared_functions.h
index 208a9c71..553d6069 100644
--- a/cores/blinklib/shared/blinkbios_shared_functions.h
+++ b/cores/blinklib/shared/blinkbios_shared_functions.h
@@ -7,7 +7,7 @@
// Note: Aesthetically it might seem better to put these function declarations with their functional groups, but ultimately I decided to
// keep them all here in one place to avoid vector collisions. It is not a decision without downside though since a client who, say,
-// only wants the IR send funtion gets polluted with the others as well. :/
+// only wants the IR send function gets polluted with the others as well. :/
// The VECTOR definitions are used on the BIOS side to hook the correct incoming vector.
// The function definitions are used on the caller side to make the actual call to the vector.
@@ -21,22 +21,35 @@
// then the target will return back to the original caller. Cool right? The optimizer will even put the target function at
// the vector jump address if it has no other callers, saving a jmp.
+// We use unused interrupt vectors to link between the user and BIOS code since they are at a known place.
+// The links are defined as symbols like `boot_vectorX` where X is the number of the unused vector we are taking.
+// In the BIOS project, these appear in the vector table in `startup.S`.
+// IN the user mode projects, these appear in the linkscript and are hard coded to the correct address (based at the bootloader vtable).
+
+// These are just prototypes so gcc knows what args to pass. The linker will resolve it to a jump to the address.
+
#ifndef BLINKBIOS_SHARED_FUCNTIONS_H_
#define BLINKBIOS_SHARED_FUCNTIONS_H_
+
+// Implements up to 256 BIOS functions. Make sure to check capabilities for `MAX` before calling (not implemented in non-MAX blinks, no room).
+// Returns 0xff if function is not implemented.
+
+// Save gamestat data to EEPROM. BLINKBIOS_MULITPLEX_VECTOR( BLINKBIOS_MULITPLEX_FUNCTION_SAVE_GAMESTAT , const uint8_t *buffer , uint16_t buffer_len )
+// Returns 0 on success, 1=if len>BLINKBOIS_GAMESTAT_MAXLEN
+#define BLINKBIOS_MULITPLEX_FUNCTION_SAVE_GAMESTAT 0x01
+#define BLINKBOIS_GAMESTAT_DATA_MAXLEN 128 // Max length of gamestat data that can be written
+
+#define BLINKBIOS_MULITPLEX_VECTOR boot_vector1
+
+extern "C" uint8_t BLINKBIOS_MULITPLEX_VECTOR( uint8_t function, ... ) __attribute__((used)) __attribute__((noinline));
+
+
// Send a user data packet
// See what we did here - we do a naked jump into vector_4, which is a jump to the `uint8_t ir_send_userdata( uint8_t face, const uint8_t *data , uint8_t len )` function
// it all works out because the params happened to be in the same registers because of the AVR C calling convention.
// When compiling the BIOS with LTO, it even puts the send packet function right at the target of the vector.
-// We use unused inetrrupt vectors to link between the user and BIOS code since they are at a known place.
-// The links are defined as symbols like `boot_vectorX` where X is the number of the unused vector we are taking.
-// In the BIOS project, these appear in the vector table in `startup.S`.
-// IN the user mode projects, these appear in the linkscript and are hard coded to the correct addressed (based at the bootloader vtable at 0x3800).
-
-// boot_vector4 is defined in the linkerscript and points to the boot loader's interrupt vector 4 at address 0x3810
-// This is just a prototype so gcc knows what args to pass. The linker will resolve it to a jump to the address.
-
#define BLINKBIOS_IRDATA_SEND_PACKET_VECTOR boot_vector4 // This lands at base + 4 bytes per vector * 4th vector (init is at 0) = 0x10
extern "C" uint8_t BLINKBIOS_IRDATA_SEND_PACKET_VECTOR( uint8_t face, const uint8_t *data , uint8_t len ) __attribute__((used)) __attribute__((noinline));
@@ -82,6 +95,10 @@ extern "C" void BLINKBIOS_WRITE_FLASH_PAGE_VECTOR(uint8_t page) __attribute__((u
// Returns the version of the blinksbios present
+// Upper bits indicate capabilities
+
+#define VERSION_CAPABILITY_BIT_MAX (_BV(2))
+#define VERSION_CAPABILITY_BIT_NFC (_BV(3))
#define BLINKBIOS_VERSION_VECTOR boot_vector14
diff --git a/cores/blinklib/shared/readme.MD b/cores/blinklib/shared/readme.MD
index 57b28276..2d5d3e90 100644
--- a/cores/blinklib/shared/readme.MD
+++ b/cores/blinklib/shared/readme.MD
@@ -1,14 +1,10 @@
Do not manually change these files!
-They come from the `blinkbios` project...
+They come from the `blinkbios` and must travel as a coherent set.
-https://github.com/Move38/Move38-BlinkBIOS
-
-...and must travel as a coherent set.
-
-`BlinkBIOS.hex` contains the compiled image of the BlinkBIOS code. It is loaded in upper flash and takes care of lots of common hardware tasks so that individual games do not need duplicated code.
-
-We program this file every time download a sketch. We also set the `BOOTRST` fuse so that the chip will jump to the bootload section rather than address 0x000 on RESET. Both of these happen in the `AVRDUDE` the recipes in `platform.txt`.
+`bootloader/BlinkBIOS.hex` contains the compiled image of the BlinkBIOS code. It is loaded in upper flash and takes care of lots of common hardware tasks so that individual games do not need duplicated code.
To be able to successfully talk to the BIOS code, the blink user code must be compiled against the matching header files.
-
\ No newline at end of file
+
+All communications between user code the bios happens though the shared memory blocks defined in these headers. Fields marked as bios-volatile can be updated in background by the bios.
+
diff --git a/howto-release.md b/howto-release.md
new file mode 100644
index 00000000..ef9a2451
--- /dev/null
+++ b/howto-release.md
@@ -0,0 +1,24 @@
+Blinks are supported under the Arduino IDE as a "custom" board package. If you just want to develop software for the blinks platform, the easiest way is to let the Arduino IDE handle installing and updating this custom board package. The IDE finds custom board package using the URLs set in `File->Preferences->Additional Board Manager URLs`. Unfortunately it is not just as easy as putting the actual updated package at that URL (it should be, or at least have that file contains a list of URLS to packages). The IDE package file format requires obnoxious redundant data to also be encoded in that file. This HOWTO decribes how to create or update the package file pointed to by one of these URLs to point to a release of this repo.
+
+# How to push a release to the Arduino boards manager
+
+1. Zip up the contents of this repo, with the base path starting with `/Move38-Arduino-Platform`.
+
+ * You can save a lot of space by not including the `.git` folder, which is not needed for deployment.
+ * You can save a tiny bit of room by removing this file, which is not needed for deployment. :)
+2. Create a new release on Github with an incremented version number.
+3. Add the new ZIP file to this release.
+4. Update the `package_move38.com-blinks_index.json` file to reflect this new ZIP.
+
+ 1. The URL should point to this new ZIP file. I like point to the blob in the github release.
+ 2. The size must be precise to the byte. You can get the size by inspecting the properties of the file or doing `dir` on a Windows command line.
+ 3. You can get the SHA256 checksum by uploading the file [here](https://emn178.github.io/online-tools/sha256_checksum.html) or running this command...
+`certutil -hashfile "Move38-Arduino-Platform-main.zip" SHA256`
+...from a Windows command line.
+
+5. Put the updated `package_move38.com-blinks_index.json` at the URL that people will then add to their Arduino IDE under `File->Preferences->Additional Board Manager URLs`.
+
+ * The current canonical URL for in the Move38.com documentation is `https://boardsmanager.com/package_move38.com-blinks_index.json`, which is currently controlled by [me](https://josh.com/contact.html).
+ * I also like to put the matching package JSON file into the release with the ZIP file as a reference, but it is not used for anything.
+
+Once the package file at the conanical URL is updated, new users will get the updated release and existing users will be prompted to update next time they use the Arduino IDE (or they can manually get the update from inside the board manager window).
diff --git a/libraries/Examples04/examples/BareMetalSerialDemo/BareMetalSerialDemo.ino b/libraries/Examples04/examples/BareMetalSerialDemo/BareMetalSerialDemo.ino
new file mode 100644
index 00000000..8bc05e00
--- /dev/null
+++ b/libraries/Examples04/examples/BareMetalSerialDemo/BareMetalSerialDemo.ino
@@ -0,0 +1,81 @@
+// Bare metal serial for blinks by Move38.com
+
+// An example showing how to output serial chars using as little as
+// one word of flash to initialize and one additional word for each char sent.
+
+// This can be handy when you are looking for a bug but are very short on flash memory.
+// Note that you would use this technique _instead_ of the normal `Serial.h`.
+
+// Note that these functions can only output bytes so you can not do something like `print(x)`. Instead, you can do something like `SERIAL_TX('L')` and
+// then if you see `L` come up in the serial monitor you know that line got hit. Using a few of these, you can trace the path your code is taking.
+// You can also do tricks like `SERIAL_TX(x+'0')` which will print the value of `x` as long as it is between 0 and 9. If you need to check larger values,
+// you will need to use a different serial termial that lets you see raw data (Arduino serial monitor can not do this). Then you can do something like
+// `SERIAL_TX(b)` and see what value the byte `x` is beteween 0 and 255. You can also then do `SERIAL_TX(w>>8);SERIAL_TX(w&0xff);` to see the value of
+// the word in `w` (you do need to do a bit of math!).
+
+// To use:
+// 1. Put the `SERIAL_ENABLE_500KBS()` function somewhere in your code (probably at the top of `setup()`. This enables the serial trasnmitter at the default baud rate of 500Kbs.
+// 2. Optionally call the `SERIAL_2X_SPEED()` function. This will increase the serial speed to 1Mbs (as used by the normal blinks serial support) at the cost of an additional word of flash memory.
+// 3. Call the `SERIAL_TX_BLIND()` and/or `SERIAL_TX_BLIND()` functions in your code to write a byte to the serial port.
+
+// The `SERIAL_TX_BLIND()` function writes blindly to the serial buffer so if you call it 3 times in a row faster than it can write the first two
+// bytes out the serial port, then the third byte will be lost. At 1Mbs, the serial port sends a byte every 9 cycles, so even if you do only
+// a tiny bit of work between calls then you are likely going to be safe. The actual write to the buffer only (and always) takes a single cycle.
+
+// The `SERIAL_TX()` function will check to make sure the previously writen byte is no longer in the buffer (it has started actually transmitting)
+// before writing this new byte, so this new byte will always be sent out the serial port. The cost of this extra check is up to 18 cycles and
+// 6 additional words of flash memory per use.
+
+// Some defines for hardware register and bit locations. Humans can ignore these.
+
+#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
+
+#define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr) // "special function register definitions look like C variables or simple constants" - https://www.nongnu.org/avr-libc/user-manual/group__avr__sfr__notes.html
+#define UCSR0B _SFR_MEM8(0xC1) // "USART Control and Status Register 0 B" - DS40001909A-page 224
+#define TXEN0 3 // "Transmitter Enable 0" - DS40001909A-page 225
+#define UCSR0A _SFR_MEM8(0xC0) // "USART Control and Status Register 0 A" - DS40001909A-page 223
+#define U2X0 1 // "Double the USART Transmission Speed"- DS40001909A-page 224
+#define UDR0 _SFR_MEM8(0xC6) // "USART I/O Data Register 0" - DS40001909A-page 222
+#define UDRE0 5 // "USART Data Register Empty" - DS40001909A-page 223
+
+// Usable functions. You need to call the enable function at leat once (probably in 'setup()') and then you can use either or both
+// of the write funtions any time after.
+
+// Enable serial port transmitter (disables digital mode on T pin). Uses default speed of 500Kbps. Must be called first.
+#define SERIAL_ENABLE_500KBS() (UCSR0B = 1<
+#include "Serial.h"
+
+
+struct loc {
+ byte ring; // How far away from the center? Center is 0. First ring (6 tiles) is 1.
+ byte step; // How far from the radial? In line with the center face is 1, counts clockwise until next radial. (I know- I should have started at 0)
+ byte face; // Which compass heading? Heading 0 is on radial away from center, counts clockwise.
+};
+
+struct boarder {
+ loc source;
+ loc target;
+};
+
+
+// lotmap is used two ways
+// first, a sending tile will look for the location of its sending face to find out what code to send.
+// second, a recieving tile will look up the code it gets to find the location of the face the code was recieved on.
+// The code is the index in this array just becuase that is convievent.
+
+// Note that the firest ring in numbered 0 and the first face is numbered 0, but the first step in each ring is 1.
+// It should be numbered 0 for consistancy, but when I first draw the map I started at 1 and too late to redo now. :/
+
+const PROGMEM boarder boarder_map[] = {
+
+ /*
+
+ // Ring 0 only has one tile - the center tile. It is special since all 6 of its
+ // faces touch effectively the same target face becuase of the 6-fold symetry around it.
+ // Note this is the only place where a destination loc is used more than once
+
+ // As a knod to practicallity, we will special case out the sends on the center tile to
+ // save 5 symbols.
+
+ // *** Ring 0
+
+ {{ 0 , 1 , 0 } , { 1 , 1 , 3 } },
+ {{ 0 , 1 , 1 } , { 1 , 1 , 3 } },
+ {{ 0 , 1 , 2 } , { 1 , 1 , 3 } },
+ {{ 0 , 1 , 3 } , { 1 , 1 , 3 } },
+ {{ 0 , 1 , 4 } , { 1 , 1 , 3 } },
+ {{ 0 , 1 , 5 } , { 1 , 1 , 3 } },
+
+ */
+
+ {{ 0 , 0 , 0 } , { 1 , 1 , 3 } }, // Use special value {0,0,0} for all ring 0 faces.
+ // Only used by special case code when we are the center
+
+ // Ring 1 is also special because any tile in this ring is guaranteed to be touching
+ // the center, so it will always know that it is at ring 1 without any other inputs,
+ // so all other tiles that touch ring 1 tiles (except the center) do not send anything to them,
+ // and of course they do not need to send anything to the center since it knows it is the center
+ // by definition.
+
+ // **** Ring 1
+ // ** Step 1 (Radial - all tiles in this ring are on a radial)
+
+ { { 1 , 1, 0} , { 2 , 1 , 3} },
+ { { 1 , 1, 1} , { 2 , 2 , 4} },
+ // Face 2 touches 1.1 in ring 1, so no need to send anything
+ // Face 3 touches the center, so no need to send anything
+ // Face 4 touches 1.1 in ring 1 (on the symetric adjacent radial), so no need to send anything
+ { { 1 , 1, 5} , { 2 , 2, 3} },
+
+ // **** Ring 2
+ // ** Step 1 (Radial)
+
+ { { 2 , 1, 0} , { 3 , 1, 3} },
+ { { 2 , 1, 1} , { 3 , 2, 4} },
+ { { 2 , 1, 2} , { 2 , 2, 5} },
+ // This face touches a ring 1 tile, which always touches the center, so no need to send anything
+ { { 2 , 1, 4} , { 2 , 2, 2} }, // Wrap to next radial
+ { { 2 , 1, 5} , { 3 , 3, 3} }, // Wrap to next radial
+
+ // ** Step 2
+
+ { { 2 , 2, 0} , { 3 , 2, 3} },
+ { { 2 , 2, 1} , { 3 , 3, 4} },
+ { { 2 , 2, 2} , { 2 , 1, 4} }, // Wrap to next radial
+ // This face touches a ring 1 tile, which always touchs the center, so no need to send anything
+ // This face touches a ring 1 tile, which always touchs the center, so no need to send anything
+ { { 2 , 2, 5} , { 2 , 1, 2} },
+
+
+ // **** Ring 3
+ // ** Step 1 (Radial)
+
+ { { 3 , 1, 0} , { 4 , 1, 3} },
+ { { 3 , 1, 1} , { 4 , 2, 4} },
+ { { 3 , 1, 2} , { 3 , 2, 5} },
+ { { 3 , 1, 3} , { 2 , 1, 0} },
+ { { 3 , 1, 4} , { 3 , 3, 2} }, // Wrap to next radial
+ { { 3 , 1, 5} , { 4 , 4, 3} }, // Wrap to next radial
+
+ // ** Step 2
+
+ { { 3 , 2, 0} , { 4 , 2, 3} },
+ { { 3 , 2, 1} , { 4 , 3, 4} },
+ { { 3 , 2, 2} , { 3 , 3, 5} },
+ { { 3 , 2, 3} , { 2 , 2, 3} },
+ { { 3 , 2, 4} , { 2 , 1, 1} },
+ { { 3 , 2, 5} , { 3 , 1, 2} },
+
+ // Step 3
+
+ { { 3 , 3, 0} , { 4 , 3, 3} },
+ { { 3 , 3, 1} , { 4 , 4, 4} },
+ { { 3 , 3, 2} , { 3 , 1, 4} }, // Wrap to next radial
+ { { 3 , 3, 3} , { 2 , 1, 5} }, // Wrap to next radial
+ { { 3 , 3, 4} , { 2 , 2, 1} },
+ { { 3 , 3, 5} , { 3 , 2, 2} },
+
+
+ // **** Ring 4
+ // ** Step 1 (Radial)
+
+ { { 4 , 1, 0} , { 5 , 1, 3} },
+ { { 4 , 1, 1} , { 5 , 2, 4} },
+ { { 4 , 1, 2} , { 4 , 2, 5} },
+ { { 4 , 1, 3} , { 3 , 1, 0} },
+ { { 4 , 1, 4} , { 4 , 4, 2} }, // Wrap to next radial
+ { { 4 , 1, 5} , { 5 , 5, 3} }, // Wrap to next radial
+
+ // ** Step 2
+
+ { { 4 , 2, 0} , { 5 , 2, 3} },
+ { { 4 , 2, 1} , { 5 , 3, 4} },
+ { { 4 , 2, 2} , { 4 , 3, 5} },
+ { { 4 , 2, 3} , { 3 , 2, 0} },
+ { { 4 , 2, 4} , { 3 , 1, 1} },
+ { { 4 , 2, 5} , { 4 , 1, 2} },
+
+ // ** Step 3
+
+ { { 4 , 3, 0} , { 5 , 3, 3} },
+ { { 4 , 3, 1} , { 5 , 4, 4} },
+ { { 4 , 3, 2} , { 4 , 4, 5} },
+ { { 4 , 3, 3} , { 3 , 3, 0} },
+ { { 4 , 3, 4} , { 3 , 2, 1} },
+ { { 4 , 3, 5} , { 4 , 2, 2} },
+
+ // ** Step 4
+
+ { { 4 , 4, 0} , { 5 , 4, 3} },
+ { { 4 , 4, 1} , { 5 , 5, 4} },
+ { { 4 , 4, 2} , { 4 , 1, 4} }, // Wrap
+ { { 4 , 4, 3} , { 3 , 1, 5} }, // Wrap
+ { { 4 , 4, 4} , { 3 , 3, 1} },
+ { { 4 , 4, 5} , { 4 , 3, 2} },
+
+};
+
+
+const byte IR_IDLE_VALUE = IR_DATA_VALUE_MAX; // A value we send when we do not have a code to send either
+ // becuase there is no center or becuase we have reached the egde
+
+// Should be PROGMEM
+
+const Color ringcolors[] = { WHITE , BLUE , GREEN , RED , YELLOW, CYAN };
+
+
+// Find what code to send on a given face if we know our location
+// Linear search for simplicty. Remebr that the index in the boarder_map[] array
+// corresponds to the code for that enrty.
+
+const byte lookupCodeToSend( byte ring , byte step , byte face ) {
+
+ for( byte i =0; i < COUNT_OF( boarder_map ) ; i++ ) {
+
+ loc l;
+
+ // Read from progmem
+ memcpy_P( &l , &boarder_map[i].source, sizeof(loc)) ;
+
+ if ( l.ring == ring && l.step == step && l.face == face ) {
+ return i;
+ }
+
+
+ }
+
+ // Not found in map
+
+ return IR_IDLE_VALUE;
+
+}
+
+// Return the `loc` struct for a ggiven code
+
+loc readTargetFromBoarderMap( byte index ) {
+ loc r;
+ memcpy_P( &r , &boarder_map[index].target , sizeof( loc ) );
+ return r;
+}
+
+
+void setup() {
+ // Function intentionally left blank
+}
+
+const byte NO_PARENT_FACE = FACE_COUNT ; // Signals that we do not currently have a parent
+
+byte parent_face=NO_PARENT_FACE;
+
+Timer lockout_timer; // This prevents us from forming packet loops by giving changes time to die out.
+ // Remember that timers init to expired state
+
+
+// where are we? Only valid when `parent_face != FACE_COUNT`
+// Remember this is always relative to parent_face
+
+loc us;
+
+const int LOCKOUT_TIMER_MS = 250; // This should be long enough for very large loops, but short enough to be unnoticable
+
+
+void loop() {
+
+ if (buttonDown()) {
+
+ // I am the center blink!
+
+ FOREACH_FACE(f) {
+
+ // This is the hack where we explicity send a special "I am center" code rather than using the locmap (see notes in locmap)
+ // We picked 0,0,0 in the boarder_map above for this special code.
+
+ setValueSentOnFace( lookupCodeToSend(0,0,0) , f );
+
+ }
+
+ // This stuff is to reset everything clean for when the button is released....
+
+ parent_face = NO_PARENT_FACE;
+
+ lockout_timer.set(LOCKOUT_TIMER_MS);
+
+ setColor( ringcolors[0] ); // We are ring 0
+
+ // That's all for the center blink!
+
+ } else {
+
+ // I am not the center blink!
+
+ if (parent_face == NO_PARENT_FACE ) { // If we have no parent, then look for one
+
+ if (lockout_timer.isExpired()) { // ...but only if we are not on lockout
+
+ FOREACH_FACE(f) {
+
+ if (!isValueReceivedOnFaceExpired(f) ) {
+
+ byte ir_data = getLastValueReceivedOnFace(f);
+
+ if (ir_data != IR_IDLE_VALUE) {
+
+ // Found a parent!
+
+ parent_face = f;
+
+ // Look up our location based on what we got
+
+ if ( ir_data < COUNT_OF( boarder_map ) ) {
+
+ // We got a location record telling us where we are in the world
+ // Remeber that the face is relative to parent_face
+
+ us = readTargetFromBoarderMap( ir_data );
+
+ }
+ }
+ }
+ }
+ }
+
+ } else {
+
+ // Make sure our parent is still there and good
+
+ if (isValueReceivedOnFaceExpired(parent_face) || ( getLastValueReceivedOnFace(parent_face ) == IR_IDLE_VALUE) ) {
+
+ // We had a parent, but our parent is now gone
+
+ parent_face = NO_PARENT_FACE;
+
+ setValueSentOnAllFaces( IR_IDLE_VALUE ); // Propigate the no-parentness to everyone resets viraly
+
+ lockout_timer.set(LOCKOUT_TIMER_MS); // Wait this long before accepting a new parent to prevent a loop
+
+ }
+
+ }
+
+
+ if (parent_face == NO_PARENT_FACE ) {
+
+ setColor( OFF );
+
+ } else {
+
+ setColor( ringcolors[ us.ring ] );
+
+ }
+
+ // Set our output values relative to our north
+
+ FOREACH_FACE(f) {
+
+ if (parent_face==NO_PARENT_FACE || f == parent_face ) {
+
+ // If we have no parent or this face is our parent face, then send idle
+ // We avoid sending back anything real on parent face to help avoid loops
+
+ setValueSentOnFace( IR_IDLE_VALUE , f );
+
+ } else {
+
+ // All transmitted faces are relative to the outward center face as face 0 so
+ // we need to use our parent_face to translate that to our internal face number.
+ // So if we got a target face of 0 on our face 0, then everything matches, but if we
+ // got a target face 1 on our face 0 then when we send, we must make sure we send
+ // the boarder_map entry for face 1 on our face 0.
+
+ // Normalized face is the face in the global boarder_map to use for this local face f
+ // remember that parent_face is the local face where we recieved the message
+
+ // So `us.face` is the global face number for the local face `parent_face`
+
+ // This actually does not change except when we get a new parent, but let's compute it here for clarity
+
+ byte global_face_number_of_local_face_0 = (( FACE_COUNT + us.face) - parent_face ) % FACE_COUNT ;
+
+ // This is now easy
+
+ byte global_face_number_of_local_face_f = (global_face_number_of_local_face_0 + f) % FACE_COUNT;
+
+
+ byte code = lookupCodeToSend( us.ring , us.step , global_face_number_of_local_face_f );
+
+ setValueSentOnFace( code , f );
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/libraries/Examples05/Firefly/Firefly.ino b/libraries/Examples04/examples/Firefly/Firefly.ino
similarity index 100%
rename from libraries/Examples05/Firefly/Firefly.ino
rename to libraries/Examples04/examples/Firefly/Firefly.ino
diff --git a/libraries/Examples05/HardwareSleepDemo/HardwareSleepDemo.ino b/libraries/Examples04/examples/HardwareSleepDemo/HardwareSleepDemo.ino
similarity index 100%
rename from libraries/Examples05/HardwareSleepDemo/HardwareSleepDemo.ino
rename to libraries/Examples04/examples/HardwareSleepDemo/HardwareSleepDemo.ino
diff --git a/libraries/Examples04/examples/SuperColor/SuperColor.ino b/libraries/Examples04/examples/SuperColor/SuperColor.ino
new file mode 100644
index 00000000..fb912a76
--- /dev/null
+++ b/libraries/Examples04/examples/SuperColor/SuperColor.ino
@@ -0,0 +1,222 @@
+// SuperColor Demo
+// This is a HACK showing how to get superbright colors.
+// How to play:
+// Push the button to make the color temporarily superbright, double click to rotate through the colors
+// green, red, and yellow. Note that you will only see yellow with a very strong battery since otherwise
+// the red LED will lower the battery voltage so that the green can not fully turn on.
+// How it works:
+// Normally a blink cycles though each of the 3 different LED colors (red,green,blue) on each pixel as it refreshes the display.
+// This means that if a pixel is only RED, then it is off 2/3 of the time while the GREEN and BLUE values are being shown(1).
+// In this demo, we disable the normal scanning function and then go straight to the hardware to manually just turn on the the RED
+// LED sequentially on each pixel. This makes the color noticably brighter since the RED LED is on for a much higher precentage of the time.
+
+// (1) it is actually off 4/5th of the time since two times slots are needed to charge the chrge pump for the blue LED.
+
+
+// These two header files come from Atmel and define the constants (registers, etc) for the ATMEGA hardware
+
+#include "sfr_defs.h"
+#include "iom168pb.h"
+
+// Common Anodes - We drive these to HIGH in sequence to select each pixel.
+
+#define PIXEL0_PORT PORTB
+#define PIXEL0_DDR DDRB
+#define PIXEL0_BIT 6
+
+#define PIXEL1_PORT PORTE
+#define PIXEL1_DDR DDRE
+#define PIXEL1_BIT 0
+
+#define PIXEL2_PORT PORTB
+#define PIXEL2_DDR DDRB
+#define PIXEL2_BIT 7
+
+#define PIXEL3_PORT PORTE
+#define PIXEL3_DDR DDRE
+#define PIXEL3_BIT 1
+
+#define PIXEL4_PORT PORTD
+#define PIXEL4_DDR DDRD
+#define PIXEL4_BIT 4
+
+#define PIXEL5_PORT PORTD
+#define PIXEL5_DDR DDRD
+#define PIXEL5_BIT 2
+
+// RGB Sinks - We drive these cathodes low to light the selected color (note that BLUE has a charge pump on it so more complicated)
+
+#define LED_R_PORT PORTD
+#define LED_R_DDR DDRD
+#define LED_R_BIT 6
+
+#define LED_G_PORT PORTD
+#define LED_G_DDR DDRD
+#define LED_G_BIT 5
+
+#define LED_B_PORT PORTD
+#define LED_B_DDR DDRD
+#define LED_B_BIT 3
+
+// Bit manipulation macros
+#define SBI(x,b) (x|= (1< file."
+#endif
+
+/* Registers and associated bit numbers */
+
+#define PINB _SFR_IO8(0x03)
+#define PINB7 7
+#define PINB6 6
+#define PINB5 5
+#define PINB4 4
+#define PINB3 3
+#define PINB2 2
+#define PINB1 1
+#define PINB0 0
+
+#define DDRB _SFR_IO8(0x04)
+#define DDRB7 7
+// Inserted "DDB7" from "DDRB7" due to compatibility
+#define DDB7 7
+#define DDRB6 6
+// Inserted "DDB6" from "DDRB6" due to compatibility
+#define DDB6 6
+#define DDRB5 5
+// Inserted "DDB5" from "DDRB5" due to compatibility
+#define DDB5 5
+#define DDRB4 4
+// Inserted "DDB4" from "DDRB4" due to compatibility
+#define DDB4 4
+#define DDRB3 3
+// Inserted "DDB3" from "DDRB3" due to compatibility
+#define DDB3 3
+#define DDRB2 2
+// Inserted "DDB2" from "DDRB2" due to compatibility
+#define DDB2 2
+#define DDRB1 1
+// Inserted "DDB1" from "DDRB1" due to compatibility
+#define DDB1 1
+#define DDRB0 0
+// Inserted "DDB0" from "DDRB0" due to compatibility
+#define DDB0 0
+
+#define PORTB _SFR_IO8(0x05)
+#define PORTB7 7
+#define PORTB6 6
+#define PORTB5 5
+#define PORTB4 4
+#define PORTB3 3
+#define PORTB2 2
+#define PORTB1 1
+#define PORTB0 0
+
+#define PINC _SFR_IO8(0x06)
+#define PINC6 6
+#define PINC5 5
+#define PINC4 4
+#define PINC3 3
+#define PINC2 2
+#define PINC1 1
+#define PINC0 0
+
+#define DDRC _SFR_IO8(0x07)
+#define DDRC6 6
+// Inserted "DDC6" from "DDRC6" due to compatibility
+#define DDC6 6
+#define DDRC5 5
+// Inserted "DDC5" from "DDRC5" due to compatibility
+#define DDC5 5
+#define DDRC4 4
+// Inserted "DDC4" from "DDRC4" due to compatibility
+#define DDC4 4
+#define DDRC3 3
+// Inserted "DDC3" from "DDRC3" due to compatibility
+#define DDC3 3
+#define DDRC2 2
+// Inserted "DDC2" from "DDRC2" due to compatibility
+#define DDC2 2
+#define DDRC1 1
+// Inserted "DDC1" from "DDRC1" due to compatibility
+#define DDC1 1
+#define DDRC0 0
+// Inserted "DDC0" from "DDRC0" due to compatibility
+#define DDC0 0
+
+#define PORTC _SFR_IO8(0x08)
+#define PORTC6 6
+#define PORTC5 5
+#define PORTC4 4
+#define PORTC3 3
+#define PORTC2 2
+#define PORTC1 1
+#define PORTC0 0
+
+#define PIND _SFR_IO8(0x09)
+#define PIND7 7
+#define PIND6 6
+#define PIND5 5
+#define PIND4 4
+#define PIND3 3
+#define PIND2 2
+#define PIND1 1
+#define PIND0 0
+
+#define DDRD _SFR_IO8(0x0A)
+#define DDRD7 7
+// Inserted "DDD7" from "DDRD7" due to compatibility
+#define DDD7 7
+#define DDRD6 6
+// Inserted "DDD6" from "DDRD6" due to compatibility
+#define DDD6 6
+#define DDRD5 5
+// Inserted "DDD5" from "DDRD5" due to compatibility
+#define DDD5 5
+#define DDRD4 4
+// Inserted "DDD4" from "DDRD4" due to compatibility
+#define DDD4 4
+#define DDRD3 3
+// Inserted "DDD3" from "DDRD3" due to compatibility
+#define DDD3 3
+#define DDRD2 2
+// Inserted "DDD2" from "DDRD2" due to compatibility
+#define DDD2 2
+#define DDRD1 1
+// Inserted "DDD1" from "DDRD1" due to compatibility
+#define DDD1 1
+#define DDRD0 0
+// Inserted "DDD0" from "DDRD0" due to compatibility
+#define DDD0 0
+
+#define PORTD _SFR_IO8(0x0B)
+#define PORTD7 7
+#define PORTD6 6
+#define PORTD5 5
+#define PORTD4 4
+#define PORTD3 3
+#define PORTD2 2
+#define PORTD1 1
+#define PORTD0 0
+
+#define PINE _SFR_IO8(0x0C)
+#define PINE3 3
+#define PINE2 2
+#define PINE1 1
+#define PINE0 0
+
+#define DDRE _SFR_IO8(0x0D)
+#define DDRE3 3
+// Inserted "DDE3" from "DDRE3" due to compatibility
+#define DDE3 3
+#define DDRE2 2
+// Inserted "DDE2" from "DDRE2" due to compatibility
+#define DDE2 2
+#define DDRE1 1
+// Inserted "DDE1" from "DDRE1" due to compatibility
+#define DDE1 1
+#define DDRE0 0
+// Inserted "DDE0" from "DDRE0" due to compatibility
+#define DDE0 0
+
+#define PORTE _SFR_IO8(0x0E)
+#define PORTE3 3
+#define PORTE2 2
+#define PORTE1 1
+#define PORTE0 0
+
+/* Reserved [0x0F..0x14] */
+
+#define TIFR0 _SFR_IO8(0x15)
+#define TOV0 0
+#define OCF0A 1
+#define OCF0B 2
+
+#define TIFR1 _SFR_IO8(0x16)
+#define TOV1 0
+#define OCF1A 1
+#define OCF1B 2
+#define ICF1 5
+
+#define TIFR2 _SFR_IO8(0x17)
+#define TOV2 0
+#define OCF2A 1
+#define OCF2B 2
+
+/* Reserved [0x18..0x1A] */
+
+#define PCIFR _SFR_IO8(0x1B)
+#define PCIF0 0
+#define PCIF1 1
+#define PCIF2 2
+
+#define EIFR _SFR_IO8(0x1C)
+#define INTF0 0
+#define INTF1 1
+
+#define EIMSK _SFR_IO8(0x1D)
+#define INT0 0
+#define INT1 1
+
+#define GPIOR0 _SFR_IO8(0x1E)
+
+#define EECR _SFR_IO8(0x1F)
+#define EERE 0
+#define EEPE 1
+#define EEMPE 2
+#define EERIE 3
+#define EEPM0 4
+#define EEPM1 5
+
+#define EEDR _SFR_IO8(0x20)
+
+/* Combine EEARL and EEARH */
+#define EEAR _SFR_IO16(0x21)
+
+#define EEARL _SFR_IO8(0x21)
+#define EEARH _SFR_IO8(0x22)
+
+#define GTCCR _SFR_IO8(0x23)
+#define PSRSYNC 0
+#define TSM 7
+#define PSRASY 1
+
+#define TCCR0A _SFR_IO8(0x24)
+#define WGM00 0
+#define WGM01 1
+#define COM0B0 4
+#define COM0B1 5
+#define COM0A0 6
+#define COM0A1 7
+
+#define TCCR0B _SFR_IO8(0x25)
+#define CS00 0
+#define CS01 1
+#define CS02 2
+#define WGM02 3
+#define FOC0B 6
+#define FOC0A 7
+
+#define TCNT0 _SFR_IO8(0x26)
+
+#define OCR0A _SFR_IO8(0x27)
+
+#define OCR0B _SFR_IO8(0x28)
+
+/* Reserved [0x29] */
+
+#define GPIOR1 _SFR_IO8(0x2A)
+
+#define GPIOR2 _SFR_IO8(0x2B)
+
+#define SPCR _SFR_IO8(0x2C)
+#define SPR0 0
+#define SPR1 1
+#define CPHA 2
+#define CPOL 3
+#define MSTR 4
+#define DORD 5
+#define SPE 6
+#define SPIE 7
+
+#define SPSR _SFR_IO8(0x2D)
+#define SPI2X 0
+#define WCOL 6
+#define SPIF 7
+
+#define SPDR _SFR_IO8(0x2E)
+
+#define ACSRB _SFR_IO8(0x2F)
+#define ACOE 0
+
+#define ACSR _SFR_IO8(0x30)
+#define ACIS0 0
+#define ACIS1 1
+#define ACIC 2
+#define ACIE 3
+#define ACI 4
+#define ACO 5
+#define ACBG 6
+#define ACD 7
+
+/* Reserved [0x31..0x32] */
+
+#define SMCR _SFR_IO8(0x33)
+#define SE 0
+#define SM0 1
+#define SM1 2
+#define SM2 3
+
+#define MCUSR _SFR_IO8(0x34)
+#define PORF 0
+#define EXTRF 1
+#define BORF 2
+#define WDRF 3
+
+#define MCUCR _SFR_IO8(0x35)
+#define IVCE 0
+#define IVSEL 1
+#define PUD 4
+#define BODSE 5
+#define BODS 6
+
+/* Reserved [0x36] */
+
+#define SPMCSR _SFR_IO8(0x37)
+#define SPMEN 0
+#define PGERS 1
+#define PGWRT 2
+#define BLBSET 3
+#define RWWSRE 4
+#define SIGRD 5
+#define RWWSB 6
+#define SPMIE 7
+
+/* Reserved [0x38..0x3C] */
+
+/* SP [0x3D..0x3E] */
+
+/* SREG [0x3F] */
+
+#define WDTCSR _SFR_MEM8(0x60)
+#define WDE 3
+#define WDCE 4
+#define WDP0 0
+#define WDP1 1
+#define WDP2 2
+#define WDP3 5
+#define WDIE 6
+#define WDIF 7
+
+#define CLKPR _SFR_MEM8(0x61)
+#define CLKPS0 0
+#define CLKPS1 1
+#define CLKPS2 2
+#define CLKPS3 3
+#define CLKPCE 7
+
+/* Reserved [0x62..0x63] */
+
+#define PRR _SFR_MEM8(0x64)
+#define PRADC 0
+#define PRUSART0 1
+#define PRSPI 2
+#define PRTIM1 3
+#define PRTIM0 5
+#define PRTIM2 6
+#define PRTWI 7
+
+#define __AVR_HAVE_PRR ((1<
+ 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. */
+
+/* avr/sfr_defs.h - macros for accessing AVR special function registers */
+
+/* $Id$ */
+
+#ifndef _AVR_SFR_DEFS_H_
+#define _AVR_SFR_DEFS_H_ 1
+
+/** \defgroup avr_sfr_notes Additional notes from
+ \ingroup avr_sfr
+
+ The \c file is included by all of the \c
+ files, which use macros defined here to make the special function register
+ definitions look like C variables or simple constants, depending on the
+ _SFR_ASM_COMPAT define. Some examples from \c to
+ show how to define such macros:
+
+\code
+#define PORTA _SFR_IO8(0x02)
+#define EEAR _SFR_IO16(0x21)
+#define UDR0 _SFR_MEM8(0xC6)
+#define TCNT3 _SFR_MEM16(0x94)
+#define CANIDT _SFR_MEM32(0xF0)
+\endcode
+
+ If \c _SFR_ASM_COMPAT is not defined, C programs can use names like
+ PORTA directly in C expressions (also on the left side of
+ assignment operators) and GCC will do the right thing (use short I/O
+ instructions if possible). The \c __SFR_OFFSET definition is not used in
+ any way in this case.
+
+ Define \c _SFR_ASM_COMPAT as 1 to make these names work as simple constants
+ (addresses of the I/O registers). This is necessary when included in
+ preprocessed assembler (*.S) source files, so it is done automatically if
+ \c __ASSEMBLER__ is defined. By default, all addresses are defined as if
+ they were memory addresses (used in \c lds/sts instructions). To use these
+ addresses in \c in/out instructions, you must subtract 0x20 from them.
+
+ For more backwards compatibility, insert the following at the start of your
+ old assembler source file:
+
+\code
+#define __SFR_OFFSET 0
+\endcode
+
+ This automatically subtracts 0x20 from I/O space addresses, but it's a
+ hack, so it is recommended to change your source: wrap such addresses in
+ macros defined here, as shown below. After this is done, the
+ __SFR_OFFSET definition is no longer necessary and can be removed.
+
+ Real example - this code could be used in a boot loader that is portable
+ between devices with \c SPMCR at different addresses.
+
+\verbatim
+: #define SPMCR _SFR_IO8(0x37)
+: #define SPMCR _SFR_MEM8(0x68)
+\endverbatim
+
+\code
+#if _SFR_IO_REG_P(SPMCR)
+ out _SFR_IO_ADDR(SPMCR), r24
+#else
+ sts _SFR_MEM_ADDR(SPMCR), r24
+#endif
+\endcode
+
+ You can use the \c in/out/cbi/sbi/sbic/sbis instructions, without the
+ _SFR_IO_REG_P test, if you know that the register is in the I/O
+ space (as with \c SREG, for example). If it isn't, the assembler will
+ complain (I/O address out of range 0...0x3f), so this should be fairly
+ safe.
+
+ If you do not define \c __SFR_OFFSET (so it will be 0x20 by default), all
+ special register addresses are defined as memory addresses (so \c SREG is
+ 0x5f), and (if code size and speed are not important, and you don't like
+ the ugly \#if above) you can always use lds/sts to access them. But, this
+ will not work if __SFR_OFFSET != 0x20, so use a different macro
+ (defined only if __SFR_OFFSET == 0x20) for safety:
+
+\code
+ sts _SFR_ADDR(SPMCR), r24
+\endcode
+
+ In C programs, all 3 combinations of \c _SFR_ASM_COMPAT and
+ __SFR_OFFSET are supported - the \c _SFR_ADDR(SPMCR) macro can be
+ used to get the address of the \c SPMCR register (0x57 or 0x68 depending on
+ device). */
+
+#ifdef __ASSEMBLER__
+#define _SFR_ASM_COMPAT 1
+#elif !defined(_SFR_ASM_COMPAT)
+#define _SFR_ASM_COMPAT 0
+#endif
+
+#ifndef __ASSEMBLER__
+/* These only work in C programs. */
+#include
+
+#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
+#define _MMIO_WORD(mem_addr) (*(volatile uint16_t *)(mem_addr))
+#define _MMIO_DWORD(mem_addr) (*(volatile uint32_t *)(mem_addr))
+#endif
+
+#if _SFR_ASM_COMPAT
+
+#ifndef __SFR_OFFSET
+/* Define as 0 before including this file for compatibility with old asm
+ sources that don't subtract __SFR_OFFSET from symbolic I/O addresses. */
+# if __AVR_ARCH__ >= 100
+# define __SFR_OFFSET 0x00
+# else
+# define __SFR_OFFSET 0x20
+# endif
+#endif
+
+#if (__SFR_OFFSET != 0) && (__SFR_OFFSET != 0x20)
+#error "__SFR_OFFSET must be 0 or 0x20"
+#endif
+
+#define _SFR_MEM8(mem_addr) (mem_addr)
+#define _SFR_MEM16(mem_addr) (mem_addr)
+#define _SFR_MEM32(mem_addr) (mem_addr)
+#define _SFR_IO8(io_addr) ((io_addr) + __SFR_OFFSET)
+#define _SFR_IO16(io_addr) ((io_addr) + __SFR_OFFSET)
+
+#define _SFR_IO_ADDR(sfr) ((sfr) - __SFR_OFFSET)
+#define _SFR_MEM_ADDR(sfr) (sfr)
+#define _SFR_IO_REG_P(sfr) ((sfr) < 0x40 + __SFR_OFFSET)
+
+#if (__SFR_OFFSET == 0x20)
+/* No need to use ?: operator, so works in assembler too. */
+#define _SFR_ADDR(sfr) _SFR_MEM_ADDR(sfr)
+#elif !defined(__ASSEMBLER__)
+#define _SFR_ADDR(sfr) (_SFR_IO_REG_P(sfr) ? (_SFR_IO_ADDR(sfr) + 0x20) : _SFR_MEM_ADDR(sfr))
+#endif
+
+#else /* !_SFR_ASM_COMPAT */
+
+#ifndef __SFR_OFFSET
+# if __AVR_ARCH__ >= 100
+# define __SFR_OFFSET 0x00
+# else
+# define __SFR_OFFSET 0x20
+# endif
+#endif
+
+#define _SFR_MEM8(mem_addr) _MMIO_BYTE(mem_addr)
+#define _SFR_MEM16(mem_addr) _MMIO_WORD(mem_addr)
+#define _SFR_MEM32(mem_addr) _MMIO_DWORD(mem_addr)
+#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET)
+#define _SFR_IO16(io_addr) _MMIO_WORD((io_addr) + __SFR_OFFSET)
+
+#define _SFR_MEM_ADDR(sfr) ((uint16_t) &(sfr))
+#define _SFR_IO_ADDR(sfr) (_SFR_MEM_ADDR(sfr) - __SFR_OFFSET)
+#define _SFR_IO_REG_P(sfr) (_SFR_MEM_ADDR(sfr) < 0x40 + __SFR_OFFSET)
+
+#define _SFR_ADDR(sfr) _SFR_MEM_ADDR(sfr)
+
+#endif /* !_SFR_ASM_COMPAT */
+
+#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
+#define _SFR_WORD(sfr) _MMIO_WORD(_SFR_ADDR(sfr))
+#define _SFR_DWORD(sfr) _MMIO_DWORD(_SFR_ADDR(sfr))
+
+/** \name Bit manipulation */
+
+/*@{*/
+/** \def _BV
+ \ingroup avr_sfr
+
+ \code #include \endcode
+
+ Converts a bit number into a byte value.
+
+ \note The bit shift is performed by the compiler which then inserts the
+ result into the code. Thus, there is no run-time overhead when using
+ _BV(). */
+
+#define _BV(bit) (1 << (bit))
+
+/*@}*/
+
+#ifndef _VECTOR
+#define _VECTOR(N) __vector_ ## N
+#endif
+
+#ifndef __ASSEMBLER__
+
+
+/** \name IO register bit manipulation */
+
+/*@{*/
+
+
+
+/** \def bit_is_set
+ \ingroup avr_sfr
+
+ \code #include \endcode
+
+ Test whether bit \c bit in IO register \c sfr is set.
+ This will return a 0 if the bit is clear, and non-zero
+ if the bit is set. */
+
+#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
+
+/** \def bit_is_clear
+ \ingroup avr_sfr
+
+ \code #include \endcode
+
+ Test whether bit \c bit in IO register \c sfr is clear.
+ This will return non-zero if the bit is clear, and a 0
+ if the bit is set. */
+
+#define bit_is_clear(sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
+
+/** \def loop_until_bit_is_set
+ \ingroup avr_sfr
+
+ \code #include \endcode
+
+ Wait until bit \c bit in IO register \c sfr is set. */
+
+#define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
+
+/** \def loop_until_bit_is_clear
+ \ingroup avr_sfr
+
+ \code #include \endcode
+
+ Wait until bit \c bit in IO register \c sfr is clear. */
+
+#define loop_until_bit_is_clear(sfr, bit) do { } while (bit_is_set(sfr, bit))
+
+/*@}*/
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* _SFR_DEFS_H_ */
diff --git a/libraries/Examples04/examples/TheNorthFace/TheNorthFace.ino b/libraries/Examples04/examples/TheNorthFace/TheNorthFace.ino
new file mode 100644
index 00000000..edf1673c
--- /dev/null
+++ b/libraries/Examples04/examples/TheNorthFace/TheNorthFace.ino
@@ -0,0 +1,146 @@
+// Demo showing how to coordinate a global compass direction across a group of blinks.
+
+// Each blink normally shows its own north face (face #0) in blue
+// Pressing the button on a blink makes it the "center" and all the other
+// connected blinks will sync to its "north" and show that in green.
+
+// Each tile (starting with the center) sends out the compass angle on each face,
+// so the center blink would send angle 0 on its face 0. When a tile recieves a
+// compass angle from a parent, it uses it to compute which one of its own faces
+// is pointing north, and then uses that to send a correct global angle to its children.
+// For example, if a tiel recieves an angle 0 on a face, then it knows the opsite face is
+// pointing north (angle 0).
+
+
+void setup() {
+ // Function intentionally left blank
+}
+
+const byte NO_PARENT_FACE = FACE_COUNT ; // Signals that we do not currently have a parent
+
+byte parent_face=NO_PARENT_FACE;
+
+Timer lockout_timer; // This prevents us from forming packet loops by giving changes time to die out.
+ // Remember that timers init to expired state
+
+byte the_north_face; // Which one of our faces is pointing north? Only valid when parent_face != NO_PARENT_FACE
+
+const byte IR_IDLE_VALUE = IR_DATA_VALUE_MAX; // A value we send when we do not know which way is north
+
+const int LOCKOUT_TIMER_MS = 250; // This should be long enough for very large loops, but short enough to be unnoticable
+
+
+void loop() {
+
+ setColor( OFF );
+
+ if (buttonDown()) {
+
+ // I am the center blink!
+
+ FOREACH_FACE(f) {
+
+ // Since by definition my face 0 is north, I can just send my face number
+ setValueSentOnFace( f , f );
+
+ }
+
+ // This stuff is to reset everything clean for when the button is released....
+
+ parent_face = NO_PARENT_FACE;
+
+ lockout_timer.set(LOCKOUT_TIMER_MS);
+
+ //setColor(dim(WHITE,128));
+
+ setColorOnFace( BLUE , 0 );
+
+ // That's all for the center blink!
+
+ } else {
+
+ // I am not the center blink!
+
+ if (parent_face == NO_PARENT_FACE ) { // If we have no parent, then look for one
+
+ if (lockout_timer.isExpired()) { // ...but only if we are not on lockout
+
+ FOREACH_FACE(f) {
+
+ if (!isValueReceivedOnFaceExpired(f) && (getLastValueReceivedOnFace(f) != IR_IDLE_VALUE) ) {
+
+ // Found a parent!
+
+ parent_face = f;
+
+ // Compute the oposite face of the one we are reading from
+
+ byte our_oposite_face = (f + (FACE_COUNT/2) ) % FACE_COUNT;
+
+ // Grab the compass heading from the parent face we are facing
+ // (this is also compass heading of our oposite face)
+
+ byte parent_face_heading = getLastValueReceivedOnFace(f);
+
+ // Ok, so now we know that `our_oposite_face` has a heading of `parent_face_heading`.
+
+ // Compute which face is our north face from that
+
+ the_north_face = ( (our_oposite_face + FACE_COUNT) - parent_face_heading) % FACE_COUNT; // This +FACE_COUNT is to keep it positive
+
+ // I guess we could break here, but breaks are ugly so instead we will keep looking
+ // and use whatever the highest face with a parent that we find.
+
+ }
+ }
+ }
+
+ } else {
+
+ // Make sure our parent is still there and good
+
+ if (isValueReceivedOnFaceExpired(parent_face) || ( getLastValueReceivedOnFace(parent_face ) == IR_IDLE_VALUE) ) {
+
+ // We had a parent, but our parent is now gone
+
+ parent_face = NO_PARENT_FACE;
+
+ setValueSentOnAllFaces( IR_IDLE_VALUE ); // Propigate the no-parentness to everyone resets viraly
+
+ lockout_timer.set(LOCKOUT_TIMER_MS); // Wait this long before accepting a new parent to prevent a loop
+
+ }
+
+ }
+
+
+ if (parent_face != NO_PARENT_FACE) {
+ // We are synced to a remote center, so show the global north in green
+ setColorOnFace( GREEN , the_north_face );
+ } else {
+ // Show our local north
+ setColorOnFace( BLUE , 0 );
+ }
+
+ // Set our output values relative to our north
+
+ FOREACH_FACE(f) {
+
+ if (parent_face==NO_PARENT_FACE || f == parent_face ) {
+
+ setValueSentOnFace( IR_IDLE_VALUE , f );
+
+ } else {
+
+ // Map directions onto our face indexes.
+ // (It was surpsringly hard for my brain to wrap around this simple formula!)
+
+ setValueSentOnFace( ((f + FACE_COUNT) - the_north_face) % FACE_COUNT , f );
+
+ }
+
+ }
+
+ }
+
+}
diff --git a/libraries/Examples04/library.properties b/libraries/Examples04/library.properties
index cacdf902..b5ff6061 100644
--- a/libraries/Examples04/library.properties
+++ b/libraries/Examples04/library.properties
@@ -1,4 +1,4 @@
-name=04. Getting Testy
+name=04. Getting Funky
version=1.0
author=Move38.com
maintainer=Move38.com
diff --git a/libraries/Examples05/dummy.hpp b/libraries/Examples05/dummy.hpp
deleted file mode 100644
index 27d87ca5..00000000
--- a/libraries/Examples05/dummy.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- Copyright (c) 2015 Atmel Corp./Thibaut VIARD. 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
-*/
-
-/*
- * Workaround dummy file to obtain the examples present in the IDE menu File->Examples
- */
diff --git a/libraries/Examples05/library.properties b/libraries/Examples05/library.properties
deleted file mode 100644
index 185c84c4..00000000
--- a/libraries/Examples05/library.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-name=05. Getting Funky
-version=1.0
-author=Move38.com
-maintainer=Move38.com
-sentence=See something blink
-paragraph=
-category=Other
-url=https://github.com/bigjosh/Move38-Arduino-Platform
-architectures=avr
-types=Arduino
diff --git a/linkscripts/avr5.xn b/linkscripts/avr5-atmega168pb.xn
similarity index 99%
rename from linkscripts/avr5.xn
rename to linkscripts/avr5-atmega168pb.xn
index dd355e94..9b6fdb5a 100644
--- a/linkscripts/avr5.xn
+++ b/linkscripts/avr5-atmega168pb.xn
@@ -42,7 +42,7 @@ __USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? _
MEMORY
{
- text (rx) : ORIGIN = 0, LENGTH = 0x1700
+ text (rx) : ORIGIN = 0, LENGTH = 0x1710
data (rw!x) : ORIGIN = 0x800100, LENGTH = 0x400
eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__
fuse (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__
diff --git a/linkscripts/avr5-atmega328.xn b/linkscripts/avr5-atmega328.xn
new file mode 100644
index 00000000..9ce07b1b
--- /dev/null
+++ b/linkscripts/avr5-atmega328.xn
@@ -0,0 +1,370 @@
+/* Script for -n: mix text and data on same page */
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:5)
+
+/* I have no idea where these DATA length numbers come from, but they are clearly wrong */
+/* I overwrite them with the correct values in the MEMORY declarations */
+
+__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 0x1600;
+__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xffa0;
+__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K;
+__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K;
+__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K;
+__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K;
+__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K;
+
+/* When changing the size of the text section, you must also update */
+/* `blink.upload.maximum_size` in boards.txt for the Arduinio IDE to */
+/* Show the correct `Sketch uses x bytes...` after compilization. */
+
+/* The TEXT length reflects the maximum size of the built-in game in the flash */
+/* This is defined by the bootloader code in the BlinkBIOS project. */
+/* Remember that there is the built-in game at the base of flash, then the */
+/* current active game, then the BIOS at the top of flash. */
+
+/* The DATA length comes right frm the datasheets. While SRAM nominally starts at */
+/* 0x60, the first 160 bytes are IO registers so not really allocatable. To be clean */
+/* I start the data region where usable RAM really starts. The LENGTH if 0x0400 comes */
+/* straight from the datasheets (1,024 dec bytes). */
+
+/* When changing the size of the text section, you must also update */
+/* `blink.upload.maximum_size` in boards.txt for the Arduinio IDE to */
+/* show the correct `Sketch uses x bytes...` after compilization. */
+
+/* When changing the size of the data section, you must also update */
+/* `blink.upload.maximum_data_size` in boards.txt for the Arduinio IDE to */
+/* show the correct `Global variables use...` after compilization. */
+
+
+MEMORY
+{
+ text (rx) : ORIGIN = 0, LENGTH = 0x2700
+ tamptable (rx): ORIGIN = 0x3800 , LENGTH = 0x100
+ data (rw!x) : ORIGIN = 0x800100, LENGTH = 0x400
+ eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__
+ fuse (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__
+ lock (rw!x) : ORIGIN = 0x830000, LENGTH = __LOCK_REGION_LENGTH__
+ signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__
+ user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__
+}
+
+ENTRY(__vectors)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ /* Internal text space or external memory. */
+ .text :
+ {
+ *(.vectors)
+ KEEP(*(.vectors))
+ /* For data that needs to reside in the lower 64k of progmem. */
+ *(.progmem.gcc*)
+ /* PR 13812: Placing the trampolines here gives a better chance
+ that they will be in range of the code that uses them. */
+ . = ALIGN(2);
+ __trampolines_start = . ;
+ /* The jump trampolines for the 16-bit limited relocs will reside here. */
+ *(.trampolines)
+ *(.trampolines*)
+ __trampolines_end = . ;
+ /* avr-libc expects these data to reside in lower 64K. */
+ *libprintf_flt.a:*(.progmem.data)
+ *libc.a:*(.progmem.data)
+ *(.progmem*)
+ . = ALIGN(2);
+ /* For future tablejump instruction arrays for 3 byte pc devices.
+ We don't relax jump/call instructions within these sections. */
+ *(.jumptables)
+ *(.jumptables*)
+ /* For code that needs to reside in the lower 128k progmem. */
+ *(.lowtext)
+ *(.lowtext*)
+ __ctors_start = . ;
+ *(.ctors)
+ __ctors_end = . ;
+ __dtors_start = . ;
+ *(.dtors)
+ __dtors_end = . ;
+ KEEP(SORT(*)(.ctors))
+ KEEP(SORT(*)(.dtors))
+ /* From this point on, we don't bother about wether the insns are
+ below or above the 16 bits boundary. */
+ *(.init0) /* Start here after reset. */
+ KEEP (*(.init0))
+ *(.init1)
+ KEEP (*(.init1))
+ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
+ KEEP (*(.init2))
+ *(.init3)
+ KEEP (*(.init3))
+ *(.init4) /* Initialize data and BSS. */
+ KEEP (*(.init4))
+ *(.init5)
+ KEEP (*(.init5))
+ *(.init6) /* C++ constructors. */
+ KEEP (*(.init6))
+ *(.init7)
+ KEEP (*(.init7))
+ *(.init8)
+ KEEP (*(.init8))
+ *(.init9) /* Call main(). */
+ KEEP (*(.init9))
+ *(.text)
+ . = ALIGN(2);
+ *(.text.*)
+ . = ALIGN(2);
+ *(.fini9) /* _exit() starts here. */
+ KEEP (*(.fini9))
+ *(.fini8)
+ KEEP (*(.fini8))
+ *(.fini7)
+ KEEP (*(.fini7))
+ *(.fini6) /* C++ destructors. */
+ KEEP (*(.fini6))
+ *(.fini5)
+ KEEP (*(.fini5))
+ *(.fini4)
+ KEEP (*(.fini4))
+ *(.fini3)
+ KEEP (*(.fini3))
+ *(.fini2)
+ KEEP (*(.fini2))
+ *(.fini1)
+ KEEP (*(.fini1))
+ *(.fini0) /* Infinite loop after program termination. */
+ KEEP (*(.fini0))
+ _etext = . ;
+
+ } > text
+
+
+ /* These are our link to the boot loader */
+ /* We can jump to these to call the appropriate function */
+ /* Thay always live at the fixed address 0x3800 regardless of chip */
+
+ boot_reset = 0x3800;
+ boot_vector1 = 0x3804;
+ boot_vector2 = 0x3808;
+ boot_vector3 = 0x380c;
+ boot_vector4 = 0x3810;
+ boot_vector5 = 0x3814;
+ boot_vector6 = 0x3818;
+ boot_vector7 = 0x381c;
+ boot_vector8 = 0x3820;
+ boot_vector9 = 0x3824;
+ boot_vector10 = 0x3828;
+ boot_vector11 = 0x382c;
+ boot_vector12 = 0x3830;
+ boot_vector13 = 0x3834;
+ boot_vector14 = 0x3838;
+ boot_vector15 = 0x383c;
+
+
+ /* The NOLOAD makes it not show in in the HEX file */
+
+ .bss 0x0800100 (NOLOAD) : AT (ADDR (.bss))
+ {
+
+ /* Here are the data blocks that are shared with the BlinkBIOS. They *must* be at */ /* fixed addreses at the base of SRAM, so they must come first here. They also */
+ /* must *not* get zeroed out, so the bss_start *must* come after them. */
+
+ *(.ipcram1)
+ KEEP( *(.ipcram1) )
+ *(.ipcram2)
+ KEEP( *(.ipcram2) )
+ *(.ipcram3)
+ KEEP( *(.ipcram3) )
+ *(.ipcram4)
+ KEEP( *(.ipcram4) )
+ *(.ipcram5)
+ KEEP( *(.ipcram5) )
+
+ /*
+ This __bss_start is used by the startup code to clear the bss to 0's
+ We put it below the ipcram so those do NOT get cleared. We are luckly
+ this happens to work since we can not change the base of `data` .
+
+ We also can not aparently make a new memory region called something sensical like
+ `ram` becuase it seems like several tools have the name `data` hard coded.
+ Something reports the error `data not found` if we compile in Arduino IDE
+ with the ram region called `ram`.
+ */
+
+ PROVIDE (__bss_start = .) ;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ PROVIDE (__bss_end = .) ;
+ } > data
+
+ /*
+
+ We have to rename .data to .datax becuase the .data is hardcoded in the "special devices"
+ file in gcc so it gets fixed at 0x800100, but we want it to float so it can come behind the bss
+
+ */
+
+ .datax :
+ {
+ PROVIDE (__data_start = .) ;
+ *(.data)
+ *(.data*)
+ *(.gnu.linkonce.d*)
+ *(.rodata) /* We need to include .rodata here if gcc is used */
+ *(.rodata*) /* with -fdata-sections. */
+ *(.gnu.linkonce.r*)
+ . = ALIGN(2);
+ _edata = . ;
+ PROVIDE (__data_end = .) ;
+ } > data AT> text
+
+ __data_load_start = LOADADDR(.datax);
+ __data_load_end = __data_load_start + SIZEOF(.datax);
+
+ /* Global data not cleared after reset. */
+ .noinit ADDR(.datax) + SIZEOF (.datax) : AT (ADDR (.noinit))
+ {
+ PROVIDE (__noinit_start = .) ;
+ *(.noinit*)
+ PROVIDE (__noinit_end = .) ;
+ _end = . ;
+ PROVIDE (__heap_start = .) ;
+ } > data
+
+ .stackwatcher (NOLOAD) :
+
+ {
+ /* This comes at the very end of the data section, so will be */
+ /* the first thing clobbered by a blown stack. We can put a special value */
+ /* here and if it gets clobbered then we know we blew the stack. */
+ *.(.stackwatcher*)
+
+ } > data
+
+
+ .eeprom :
+ {
+ /* See .data above... */
+ KEEP(*(.eeprom*))
+ __eeprom_end = . ;
+ } > eeprom
+ .fuse :
+ {
+ KEEP(*(.fuse))
+ KEEP(*(.lfuse))
+ KEEP(*(.hfuse))
+ KEEP(*(.efuse))
+ } > fuse
+ .lock :
+ {
+ KEEP(*(.lock*))
+ } > lock
+ .signature :
+ {
+ KEEP(*(.signature*))
+ } > signature
+ .user_signatures :
+ {
+ KEEP(*(.user_signatures*))
+ } > user_signatures
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF Extension. */
+ .debug_macro 0 : { *(.debug_macro) }
+}
diff --git a/linkscripts/avr5-atmega328max.xn b/linkscripts/avr5-atmega328max.xn
new file mode 100644
index 00000000..3f59b773
--- /dev/null
+++ b/linkscripts/avr5-atmega328max.xn
@@ -0,0 +1,368 @@
+/* Script for -n: mix text and data on same page */
+/* Copyright (C) 2014-2015 Free Software Foundation, Inc.
+ Copying and distribution of this script, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. */
+OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
+OUTPUT_ARCH(avr:5)
+
+/* I have no idea where these DATA length numbers come from, but they are clearly wrong */
+/* I overwrite them with the correct values in the MEMORY declarations */
+
+__TEXT_REGION_LENGTH__ = DEFINED(__TEXT_REGION_LENGTH__) ? __TEXT_REGION_LENGTH__ : 0x1600;
+__DATA_REGION_LENGTH__ = DEFINED(__DATA_REGION_LENGTH__) ? __DATA_REGION_LENGTH__ : 0xffa0;
+__EEPROM_REGION_LENGTH__ = DEFINED(__EEPROM_REGION_LENGTH__) ? __EEPROM_REGION_LENGTH__ : 64K;
+__FUSE_REGION_LENGTH__ = DEFINED(__FUSE_REGION_LENGTH__) ? __FUSE_REGION_LENGTH__ : 1K;
+__LOCK_REGION_LENGTH__ = DEFINED(__LOCK_REGION_LENGTH__) ? __LOCK_REGION_LENGTH__ : 1K;
+__SIGNATURE_REGION_LENGTH__ = DEFINED(__SIGNATURE_REGION_LENGTH__) ? __SIGNATURE_REGION_LENGTH__ : 1K;
+__USER_SIGNATURE_REGION_LENGTH__ = DEFINED(__USER_SIGNATURE_REGION_LENGTH__) ? __USER_SIGNATURE_REGION_LENGTH__ : 1K;
+
+/* When changing the size of the text section, you must also update */
+/* `blink.upload.maximum_size` in boards.txt for the Arduinio IDE to */
+/* Show the correct `Sketch uses x bytes...` after compilization. */
+
+/* The TEXT length reflects the maximum size of the built-in game in the flash */
+/* This is defined by the bootloader code in the BlinkBIOS project. */
+/* Remember that there is the built-in game at the base of flash, then the */
+/* current active game, then the BIOS at the top of flash. */
+
+/* The DATA length comes right frm the datasheets. While SRAM nominally starts at */
+/* 0x60, the first 160 bytes are IO registers so not really allocatable. To be clean */
+/* I start the data region where usable RAM really starts. The LENGTH if 0x0400 comes */
+/* straight from the datasheets (1,024 dec bytes). */
+
+/* When changing the size of the text section, you must also update */
+/* `blink.upload.maximum_size` in boards.txt for the Arduinio IDE to */
+/* show the correct `Sketch uses x bytes...` after compilization. */
+
+/* When changing the size of the data section, you must also update */
+/* `blink.upload.maximum_data_size` in boards.txt for the Arduinio IDE to */
+/* show the correct `Global variables use...` after compilization. */
+
+
+MEMORY
+{
+ text (rx) : ORIGIN = 0, LENGTH = 0x3800
+ data (rw!x) : ORIGIN = 0x800100, LENGTH = 0x800
+ eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__
+ fuse (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__
+ lock (rw!x) : ORIGIN = 0x830000, LENGTH = __LOCK_REGION_LENGTH__
+ signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__
+ user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__
+}
+
+ENTRY(__vectors)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ /* Internal text space or external memory. */
+ .text :
+ {
+ *(.vectors)
+ KEEP(*(.vectors))
+ /* For data that needs to reside in the lower 64k of progmem. */
+ *(.progmem.gcc*)
+ /* PR 13812: Placing the trampolines here gives a better chance
+ that they will be in range of the code that uses them. */
+ . = ALIGN(2);
+ __trampolines_start = . ;
+ /* The jump trampolines for the 16-bit limited relocs will reside here. */
+ *(.trampolines)
+ *(.trampolines*)
+ __trampolines_end = . ;
+ /* avr-libc expects these data to reside in lower 64K. */
+ *libprintf_flt.a:*(.progmem.data)
+ *libc.a:*(.progmem.data)
+ *(.progmem*)
+ . = ALIGN(2);
+ /* For future tablejump instruction arrays for 3 byte pc devices.
+ We don't relax jump/call instructions within these sections. */
+ *(.jumptables)
+ *(.jumptables*)
+ /* For code that needs to reside in the lower 128k progmem. */
+ *(.lowtext)
+ *(.lowtext*)
+ __ctors_start = . ;
+ *(.ctors)
+ __ctors_end = . ;
+ __dtors_start = . ;
+ *(.dtors)
+ __dtors_end = . ;
+ KEEP(SORT(*)(.ctors))
+ KEEP(SORT(*)(.dtors))
+ /* From this point on, we don't bother about wether the insns are
+ below or above the 16 bits boundary. */
+ *(.init0) /* Start here after reset. */
+ KEEP (*(.init0))
+ *(.init1)
+ KEEP (*(.init1))
+ *(.init2) /* Clear __zero_reg__, set up stack pointer. */
+ KEEP (*(.init2))
+ *(.init3)
+ KEEP (*(.init3))
+ *(.init4) /* Initialize data and BSS. */
+ KEEP (*(.init4))
+ *(.init5)
+ KEEP (*(.init5))
+ *(.init6) /* C++ constructors. */
+ KEEP (*(.init6))
+ *(.init7)
+ KEEP (*(.init7))
+ *(.init8)
+ KEEP (*(.init8))
+ *(.init9) /* Call main(). */
+ KEEP (*(.init9))
+ *(.text)
+ . = ALIGN(2);
+ *(.text.*)
+ . = ALIGN(2);
+ *(.fini9) /* _exit() starts here. */
+ KEEP (*(.fini9))
+ *(.fini8)
+ KEEP (*(.fini8))
+ *(.fini7)
+ KEEP (*(.fini7))
+ *(.fini6) /* C++ destructors. */
+ KEEP (*(.fini6))
+ *(.fini5)
+ KEEP (*(.fini5))
+ *(.fini4)
+ KEEP (*(.fini4))
+ *(.fini3)
+ KEEP (*(.fini3))
+ *(.fini2)
+ KEEP (*(.fini2))
+ *(.fini1)
+ KEEP (*(.fini1))
+ *(.fini0) /* Infinite loop after program termination. */
+ KEEP (*(.fini0))
+ _etext = . ;
+
+ } > text
+
+
+ /* These are our link to the boot loader */
+ /* We can jump to these to call the appropriate function */
+
+ boot_reset = 0x7000;
+ boot_vector1 = 0x7004;
+ boot_vector2 = 0x7008;
+ boot_vector3 = 0x700c;
+ boot_vector4 = 0x7010;
+ boot_vector5 = 0x7014;
+ boot_vector6 = 0x7018;
+ boot_vector7 = 0x701c;
+ boot_vector8 = 0x7020;
+ boot_vector9 = 0x7024;
+ boot_vector10 = 0x7028;
+ boot_vector11 = 0x702c;
+ boot_vector12 = 0x7030;
+ boot_vector13 = 0x7034;
+ boot_vector14 = 0x7038;
+ boot_vector15 = 0x703c;
+
+
+ /* The NOLOAD makes it not show in in the HEX file */
+
+ .bss 0x0800100 (NOLOAD) : AT (ADDR (.bss))
+ {
+
+ /* Here are the data blocks that are shared with the BlinkBIOS. They *must* be at */ /* fixed addreses at the base of SRAM, so they must come first here. They also */
+ /* must *not* get zeroed out, so the bss_start *must* come after them. */
+
+ *(.ipcram1)
+ KEEP( *(.ipcram1) )
+ *(.ipcram2)
+ KEEP( *(.ipcram2) )
+ *(.ipcram3)
+ KEEP( *(.ipcram3) )
+ *(.ipcram4)
+ KEEP( *(.ipcram4) )
+ *(.ipcram5)
+ KEEP( *(.ipcram5) )
+
+ /*
+ This __bss_start is used by the startup code to clear the bss to 0's
+ We put it below the ipcram so those do NOT get cleared. We are luckly
+ this happens to work since we can not change the base of `data` .
+
+ We also can not aparently make a new memory region called something sensical like
+ `ram` becuase it seems like several tools have the name `data` hard coded.
+ Something reports the error `data not found` if we compile in Arduino IDE
+ with the ram region called `ram`.
+ */
+
+ PROVIDE (__bss_start = .) ;
+ *(.bss)
+ *(.bss*)
+ *(COMMON)
+ PROVIDE (__bss_end = .) ;
+ } > data
+
+ /*
+
+ We have to rename .data to .datax becuase the .data is hardcoded in the "special devices"
+ file in gcc so it gets fixed at 0x800100, but we want it to float so it can come behind the bss
+
+ */
+
+ .datax :
+ {
+ PROVIDE (__data_start = .) ;
+ *(.data)
+ *(.data*)
+ *(.gnu.linkonce.d*)
+ *(.rodata) /* We need to include .rodata here if gcc is used */
+ *(.rodata*) /* with -fdata-sections. */
+ *(.gnu.linkonce.r*)
+ . = ALIGN(2);
+ _edata = . ;
+ PROVIDE (__data_end = .) ;
+ } > data AT> text
+
+ __data_load_start = LOADADDR(.datax);
+ __data_load_end = __data_load_start + SIZEOF(.datax);
+
+ /* Global data not cleared after reset. */
+ .noinit ADDR(.datax) + SIZEOF (.datax) : AT (ADDR (.noinit))
+ {
+ PROVIDE (__noinit_start = .) ;
+ *(.noinit*)
+ PROVIDE (__noinit_end = .) ;
+ _end = . ;
+ PROVIDE (__heap_start = .) ;
+ } > data
+
+ .stackwatcher (NOLOAD) :
+
+ {
+ /* This comes at the very end of the data section, so will be */
+ /* the first thing clobbered by a blown stack. We can put a special value */
+ /* here and if it gets clobbered then we know we blew the stack. */
+ *.(.stackwatcher*)
+
+ } > data
+
+
+ .eeprom :
+ {
+ /* See .data above... */
+ KEEP(*(.eeprom*))
+ __eeprom_end = . ;
+ } > eeprom
+ .fuse :
+ {
+ KEEP(*(.fuse))
+ KEEP(*(.lfuse))
+ KEEP(*(.hfuse))
+ KEEP(*(.efuse))
+ } > fuse
+ .lock :
+ {
+ KEEP(*(.lock*))
+ } > lock
+ .signature :
+ {
+ KEEP(*(.signature*))
+ } > signature
+ .user_signatures :
+ {
+ KEEP(*(.user_signatures*))
+ } > user_signatures
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .note.gnu.build-id : { *(.note.gnu.build-id) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF Extension. */
+ .debug_macro 0 : { *(.debug_macro) }
+}
diff --git a/linkscripts/readme.MD b/linkscripts/readme.MD
index 665f0e95..9cdec356 100644
--- a/linkscripts/readme.MD
+++ b/linkscripts/readme.MD
@@ -1,51 +1,16 @@
-We use a shared data block for communication between the bootloader code and the foreground game. This lets us load that stuff once rather than having to include it in every game image.
-
-The shared memory block lives at a fixed location at the bottom of RAM.
-
-We need a custom link script so we can force that block to this known location.
-
-The linker scripts here were copied from...
-
-C:\Program Files (x86)\Arduino\hardware\tools\avr\avr\lib\ldscripts
-
-...which seems to be hardcoded into `gcc`.
-
-We add a new group of sections called `ipcram1`-`ipcram9` which hold the shared memory block.
-
-Note also that we mark these sections as `KEEP`, but they still seem to get garbage collected if not referenced, so we should make sure to reference them in the foreground code or else the foreground will put variables here and overwrite the bootloader's info.
-
-We had to make a new `.dataX` segment because the origin of the normal `.data` segment seems to be hardcoded into the "specific device" file in gcc...
+## Custom linker scripts
-https://electronics.stackexchange.com/questions/408115/how-does-avr-gcc-linker-know-to-put-the-datasection-at-0x800100-rather-than
+### Code
-It is ok, becuase the new script is much cleaner than the stock one, and also moves the `bss` segment down so that both the `ipcram` memory and the normal static variables can all be initialized to `0` in one big block. Note that we only want to zero out the `ipcram` in the BIOS startup, so the linker script for user programs will put the `bss` start above here.
+We want user code to be org'ed at 0x000. Duing the build cycle we will move it up to the "build-in game area" of the flash where it lives until the blink repowers or the user wants to seed the local game, at which time it is coped down to 0x0000 by the BIOS and then jumpped into.
-Another hard won discovery is that if you put anything into .bss, it seems to output the whole thing to the HEX file. We fix this by adding `(NOLOAD)` to the segment. Phew.
+We also need the Arduino code to know where the bootloader starts so it can call the BIOS vectors. These vectors are named "boot_vect_X" and are hard coded to come at the start of the bootloader section.
-To get Arduino use this custom script, we edit the `platform.txt` to have...
+## Data
-```
-recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-verbose -Wl,--script="{{build.core}/linkerscripts/avr5.xn" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
-```
-
-But it is better to pre-compile this BIOS code into a HEX file and then have the Arduino code blindly flash it using AVRDUDE during the download. To compile in AS7, we have to add this to the `Toolchain->Linker->Misc->Linker flags`...
-
-`-Wl,--script="../../../src/linkscripts/avr5.xn"`
-
-The `-Wl,` means "pass the next arg to the linker and the `--script=` [specifies the linker script](ftp://ftp.gnu.org/pub/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_2.html#SEC3). This sucks that we have to hard code the `avr5` in there but I think the mapping from MCU to those `avrX` code is hardcoded into gcc.
-
-
-To put a variable into this new section, we use...
-
-```
-byte __attribute__((section ("ipcram1"))) counter=0;
-```
-
-More info:
-https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
+We use a shared data block for communication between the bootloader code and the foreground game. This lets us load that stuff once rather than having to include it in every game image.
-### Stack Overflow Detector
+The shared memory block lives at a fixed location at the bottom of RAM using the `ipcram` sections.
-We put the input section `.stackwatcher` after all the other stuff in the `data` memory section. We can then have the code put a special value here and periodically check that value to see if it changed. Since the stack grows down from the top of RAM, it will hit this first and so if anything here changes then we know that the stack got too big and overwrote it.
+We must also update the size of the `data` section to match the RAM available on each chip.
-
\ No newline at end of file
diff --git a/package_move38.com-blinks_index.json b/package_move38.com-blinks_index.json
index 06ec6baa..2072c9ca 100644
--- a/package_move38.com-blinks_index.json
+++ b/package_move38.com-blinks_index.json
@@ -11,64 +11,37 @@
},
"platforms": [
{
- "name": "Blinks",
+ "name": "Blinks by Move38.com",
"architecture": "avr",
- "version": "1.0.0",
+ "version": "1.3.1",
"category": "Contributed",
"help": {
"online": "https://github.com/bigjosh/Move38-Arduino-Platform"
},
- "url": "https://janedeveloper.github.io/myboard/myboard-1.0.0.zip",
- "archiveFileName": "myboard-1.0.0.zip",
- "checksum": "SHA-256:ec3ff8a1dc96d3ba6f432b9b837a35fd4174a34b3d2927de1d51010e8b94f9f1",
- "size": "15005",
+ "url": "https://github.com/bigjosh/Move38-Arduino-Platform/releases/download/1.3.1/Move38-Arduino-Platform-main.zip",
+ "archiveFileName": "Move38-Arduino-Platform-main.zip",
+ "checksum": "SHA-256:8a54e56a099c92ab7afd4d1aacd14bc14db2660de4460fd1c61f9144a86ee9e0",
+ "size": "5544617",
"boards": [
- {"name": "Blinks Tile"},
- ],
+ {"name": "Blinks by Move38.com"}
+ ],
+
"toolsDependencies": [
{
"packager": "arduino",
"name": "avr-gcc",
- "version": "4.8.1-arduino5"
+ "version": "7.3.0-atmel3.6.1-arduino5"
},
{
"packager": "arduino",
"name": "avrdude",
- "version": "6.0.1-arduino5"
+ "version": "6.3.0-arduino17"
}
]
- },
- {
- "name": "My Board",
- "architecture": "avr",
- "version": "1.0.1",
- "category": "Contributed",
- "help": {
- "online": "http://janedeveloper.org/forum/myboard"
- },
- "url": "https://janedeveloper.github.io/myboard/myboard-1.0.1.zip",
- "archiveFileName": "myboard-1.0.1.zip",
- "checksum": "SHA-256:9c86ee28a7ce9fe33e8b07ec643316131e0031b0d22e63bb398902a5fdadbca9",
- "size": "15125",
- "boards": [
- {"name": "My Board"},
- {"name": "My Board Pro"}
- ],
- "toolsDependencies": [
- {
- "packager": "arduino",
- "name": "avr-gcc",
- "version": "4.8.1-arduino5"
- },
- {
- "packager": "arduino",
- "name": "avrdude",
- "version": "6.0.1-arduino5"
- }
- ]
- }
+ }
],
- "tools":[]
+ "tools":[
+ ]
}
]
}
\ No newline at end of file
diff --git a/platform.txt b/platform.txt
index 455cab93..bc723203 100644
--- a/platform.txt
+++ b/platform.txt
@@ -6,7 +6,7 @@
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification
name=Move38
-version=1.1.1
+version=1.1.5
# AVR compile variables
# ---------------------
@@ -34,19 +34,18 @@ compiler.ar.flags=rcs
compiler.objcopy.cmd=avr-objcopy
compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
+compiler.objcopy.bin.flags=-O binary --remove-section=bss
# We need to explicitly remove .BSS from the hex file since the linker inexplicably includes .bss in .text
# when we include .ipcram in .bss.
-# This 0x1700 is is the physical start address of the `built-in` program image area. This is
+# We must move the image to the physical start address of the `built-in` program image area. This is
# defined in the blinkbios as `FLASH_BUILTIN_IMAGE_START_ADDRESS`.
# If you change this, then you must also update the LENGTH of the TEXT
# area in the MEMORY section of linkscripts/avr5.xn to match.
# Finally you must also update `blink.upload.maximum_size` in boards.txt
# so that the Arduino IDE reports the correct values for program size after a compile.
-# Also remember that AVR flash memory is 16 bits wide so this number
-# is 1/2 what you expect it to be if you are thinking in bytes.
-compiler.elf2hex.flags=--change-addresses 0x1700 -O ihex -R .eepromm
+compiler.elf2hex.flags=--change-addresses {build.builtinbase} -O ihex -R .eepromm
compiler.elf2hex.cmd=avr-objcopy
compiler.ldflags=
compiler.size.cmd=avr-size
@@ -62,6 +61,7 @@ compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
+compiler.objcopy.bin.extra_flags=
# AVR compile patterns
# --------------------
@@ -81,10 +81,7 @@ archive_file_path={build.path}/{archive_file}
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects
-#recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -Wl,--script={runtime.platform.path}/linkscripts/avr5.xn -Wl,-nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
-#recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -Wl,--print-gc-sections -Wl,--script={runtime.platform.path}/linkscripts/avr5.xn -Wl,-Map,{build.path}/out.map -nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
-# Ok, I know that hard-coded path to the startup.S.o is ugly, but it took me a full day to figure out that the startup file can not be inside the archive and now I just need it to works so don't judge me.
-recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -T "{runtime.platform.path}/linkscripts/avr5.xn" -nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -T "{runtime.platform.path}/linkscripts/{build.linkscript}" -nostartfiles -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
## Create output files (.eep and .hex)
recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep"
@@ -93,6 +90,7 @@ recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf
## Save hex
recipe.output.tmp_file={build.project_name}.hex
recipe.output.save_file={build.project_name}.{build.variant}.hex
+recipe.hooks.savehex.postsavehex.1.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.bin.flags} {compiler.objcopy.bin.extra_flags} "{build.path}/{build.project_name}.elf" "{sketch_path}/{build.project_name}.bin"
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
@@ -116,23 +114,18 @@ tools.avrdude.config.path={path}/etc/avrdude.conf
tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
+# Note that because `protocol` is not set in boards.txt, all uploads go to the `program` recipe- even when the upload button is pressed.
+# So you can ignore this section, it is never used.
+
tools.avrdude.upload.params.verbose=-v
tools.avrdude.upload.params.quiet=-q -q
# tools.avrdude.upload.verify is needed for backwards compatibility with IDE 1.6.8 or older, IDE 1.6.9 or newer overrides this value
tools.avrdude.upload.verify=
tools.avrdude.upload.params.noverify=-V
-# We replace the upload pattern with the program pattern because for now blinks code comes via programmer,
-# so putting this here lets us push the convenient "Upload" button rather than having to do the "Via Programmer" menu pick.
-# The -B 5 speeds up the clock to 200KHz which is the fastest we can go with the currently programmed 1MHz MCU clock at startup
-#Note that this used to be set to 250KHz but I found two different blinks that would not program at this speed
-
-# The second -U:flash programs the BlinkBIOS image into the bootlader are of the flash (check out the BlinkBIOS project for more info)
-# The -U:efuse programs the extended fuse to enable BOOTRST. This makes the chip jump to the bootloader area (with BlinkBIOS) on reset rather than 0x0000
-# The -u means "don't change the fuses back to what they were when we started". Silly, yes.
-# The -cusbtiny is hardcoded in there becuase the {protocol} does not seem to work with the upload event
-tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" -B 5 {upload.verbose} {upload.verify} -p{build.mcu} -cusbtiny "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" "-Uefuse:w:0xf8:m" -u
-#tools.avrdude.upload.pattern="{cmd.path}" "-C{config.path}" {upload.verbose} {upload.verify} -p{build.mcu} -c{upload.protocol} "-P{serial.port}" -b{upload.speed} -D "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{build.core}/bootloader/XXXbin/blinkboot.hex:i"
+# blink does not use a serial bootloader, so we never want to use this recipe. Luckily by setting `protocol` to nothing, the IDE will always use the `program` recipe
+# We put the little error bug text in here just incase this ever changes at least we will know what happened.
+tools.avrdude.upload.pattern="echo ERROR_TELL_JOSH_UPLOAD_WAS_CALLED"
tools.avrdude.program.params.verbose=-v
tools.avrdude.program.params.quiet=-q -q
@@ -140,22 +133,27 @@ tools.avrdude.program.params.quiet=-q -q
tools.avrdude.program.verify=
tools.avrdude.program.params.noverify=-V
-# This just makes the "Upload via programmer" menu option work and do the same thing as the Upload button
+# Note that because `protocol` is not set in boards.txt, all uploads go here - even when the upload button is pressed.
+# Note that we must program both the user code and the BIOS every time because all of flash memory is erased by AVRDUDE anytime you program any of it.
+# Note that we do not reprogram the fuses every time because the fuses are not erased on each cycle. You can use the "Program bootloader" function to program the fuses if they ever get messed up.
# The -B 5 speeds up the clock to 200KHz which is the fastest we can go with the currently programmed 1MHz MCU clock at startup
-#Note that this used to be set to 250KHz but I found two different blinks that would not program at this speed
-tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" -B 5 {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" -u
+# Note that this used to be set to 250KHz but I found two different blinks that would not program at this speed
+
+tools.avrdude.program.pattern="{cmd.path}" "-C{config.path}" -B 5 {program.verbose} {program.verify} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{build.path}/{build.project_name}.hex:i" "-Uflash:w:{runtime.platform.path}/bootloaders/{bootloader.file}:i" -u
+
+# Burn bootloader will program the fuses. Should never really need to do this since they are programmed at the factory, but maybe if the fuses get messed up you can fix them?
+
+# Apparently need these... https://forum.arduino.cc/t/solved-bootloader-from-arudino-ide-with-avrispmkii-fails/333367/11?u=bigjosh2
tools.avrdude.erase.params.verbose=-v
tools.avrdude.erase.params.quiet=-q -q
-tools.avrdude.erase.pattern="{cmd.path}" "-C{config.path}" {erase.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m
+tools.avrdude.erase.pattern=""
tools.avrdude.bootloader.params.verbose=-v
tools.avrdude.bootloader.params.quiet=-q -q
-tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} "-Uflash:w:{runtime.platform.path}/bootloaders/BlinkBIOS.hex:i" "-Uefuse:w:0xf8:m" -u
+tools.avrdude.bootloader.pattern="{cmd.path}" "-C{config.path}" {bootloader.verbose} -p{build.mcu} -c{protocol} {program.extra_params} -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m
-tools.avrdude_remote.upload.pattern=/usr/bin/run-avrdude /tmp/sketch.hex {upload.verbose} -p{build.mcu}
-tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port {upload.network.port} -sketch "{build.path}/{build.project_name}.hex" -upload {upload.network.endpoint_upload} -sync {upload.network.endpoint_sync} -reset {upload.network.endpoint_reset} -sync_exp {upload.network.sync_return}
# USB Default Flags
# Default blank usb manufacturer will be filled in at compile time
diff --git a/programmers.txt b/programmers.txt
index e57404ea..a14f3914 100644
--- a/programmers.txt
+++ b/programmers.txt
@@ -22,7 +22,6 @@ arduinoisp.protocol=arduinoisp
arduinoisp.program.tool=avrdude
arduinoisp.program.extra_params=
-
usbasp.name=Blinks USBasp
usbasp.communication=usb
usbasp.protocol=usbasp