From c56dd578b8eecdee41d6368fc27960b2df403ea4 Mon Sep 17 00:00:00 2001 From: Mark Denkert Date: Tue, 22 Jan 2013 23:03:21 -0600 Subject: [PATCH 1/3] New mode in 4.1, and fixes for Arduino IDE 1.0.3 Added medium mode, lowered brightness of low to a more appropriate level. Changed "shaked" to "shaken". Moved Arduino sketches to separate folders as Arduino IDE 1.0.3 requires. Shaking the Flex while in Knobbing mode now jumps to Dazzle mode. --- .gitattributes | 22 + README.md | 86 +- hardware/hexbright/boards.txt | 44 +- .../hexbright/bootloader/ATmegaBOOT_168.c | 2108 ++++++++--------- .../bootloader/ATmegaBOOT_168_hexbright.hex | 250 +- hardware/hexbright/bootloader/Makefile | 476 ++-- hexbright4.ino => hexbright4/hexbright4.ino | 10 +- hexbright4_1/hexbright4_1.ino | 404 ++++ .../hexbright_demo_dazzle.ino | 2 +- .../hexbright_demo_fades.ino | 2 +- .../hexbright_demo_momentary.ino | 2 +- .../hexbright_demo_morse.ino | 2 +- .../hexbright_demo_taps.ino | 2 +- .../hexbright_factory.ino | 2 +- libraries/readme.txt | 1 + 15 files changed, 1921 insertions(+), 1492 deletions(-) create mode 100644 .gitattributes rename hexbright4.ino => hexbright4/hexbright4.ino (98%) mode change 100755 => 100644 create mode 100644 hexbright4_1/hexbright4_1.ino rename hexbright_demo_dazzle.ino => hexbright_demo_dazzle/hexbright_demo_dazzle.ino (99%) mode change 100755 => 100644 rename hexbright_demo_fades.ino => hexbright_demo_fades/hexbright_demo_fades.ino (99%) mode change 100755 => 100644 rename hexbright_demo_momentary.ino => hexbright_demo_momentary/hexbright_demo_momentary.ino (99%) mode change 100755 => 100644 rename hexbright_demo_morse.ino => hexbright_demo_morse/hexbright_demo_morse.ino (99%) mode change 100755 => 100644 rename hexbright_demo_taps.ino => hexbright_demo_taps/hexbright_demo_taps.ino (99%) rename hexbright_factory.ino => hexbright_factory/hexbright_factory.ino (99%) mode change 100755 => 100644 create mode 100644 libraries/readme.txt diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/README.md b/README.md index 15abb13..0dd51e7 100755 --- a/README.md +++ b/README.md @@ -1,43 +1,43 @@ -HexBright Demo Code -======================= - -hexbright_factory ------------------ -This is the software that ships with the Hexbright Flex. Button presses cycle -through off, low, medium, and high modes. Hold down the button while off for -blinky mode. - -hexbright4 ---------------------- -Fancier than the factory program, but designed for everyday usability. Button -presses cycle through off, low and high modes. Hold the light horizontally, -hold the button down, and rotate about the long axis clockwise to increase -brightness, and counter-clockwise to decrease brightness- the brightness sticks -when you let go of the button. While holding the button down, give the light a -firm tap to change to blinky mode, and another to change to dazzle mode. - -hexbright_demo_morse --------------------- -Flashes out a message in morse code every time you press the button. Nothing -else. The message and speed are easy to change- you can see and change both -in the first lines of code. - -hexbright_demo_taps -------------------- -Hold the button down, and with your other hand firmly tap on the light. Tap -some more times, and let go of the button. The exact sequence of taps will -be recorded and then played back as flashes until you press the button again -to turn off. - -hexbright_demo_momentary ------------------------- -Light turns on only while the button is being held down. That's it. - -hexbright_demo_dazzle ---------------------- -Light runs in dazzle mode only as long as the button is being held down. - -hexbright_demo_fades --------------------- -Hold the button down, and light fades up and down. Let go, and it holds the -current brightness. Another press to turn off. +HexBright Demo Code +======================= + +hexbright_factory +----------------- +This is the software that ships with the Hexbright Flex. Button presses cycle +through off, low, medium, and high modes. Hold down the button while off for +blinky mode. + +hexbright4 +--------------------- +Fancier than the factory program, but designed for everyday usability. Button +presses cycle through off, low and high modes. Hold the light horizontally, +hold the button down, and rotate about the long axis clockwise to increase +brightness, and counter-clockwise to decrease brightness- the brightness sticks +when you let go of the button. While holding the button down, give the light a +firm tap to change to blinky mode, and another to change to dazzle mode. + +hexbright_demo_morse +-------------------- +Flashes out a message in morse code every time you press the button. Nothing +else. The message and speed are easy to change- you can see and change both +in the first lines of code. + +hexbright_demo_taps +------------------- +Hold the button down, and with your other hand firmly tap on the light. Tap +some more times, and let go of the button. The exact sequence of taps will +be recorded and then played back as flashes until you press the button again +to turn off. + +hexbright_demo_momentary +------------------------ +Light turns on only while the button is being held down. That's it. + +hexbright_demo_dazzle +--------------------- +Light runs in dazzle mode only as long as the button is being held down. + +hexbright_demo_fades +-------------------- +Hold the button down, and light fades up and down. Let go, and it holds the +current brightness. Another press to turn off. diff --git a/hardware/hexbright/boards.txt b/hardware/hexbright/boards.txt index 0959952..d09e566 100755 --- a/hardware/hexbright/boards.txt +++ b/hardware/hexbright/boards.txt @@ -1,22 +1,22 @@ -############################################################## - -hexbright.name=Hexbright - -hexbright.upload.protocol=arduino -hexbright.upload.maximum_size=14336 -hexbright.upload.speed=19200 - -hexbright.bootloader.low_fuses=0xe2 -hexbright.bootloader.high_fuses=0xdd -hexbright.bootloader.extended_fuses=0x00 -hexbright.bootloader.path=atmega -hexbright.bootloader.file=ATmegaBOOT_168_hexbright.hex -hexbright.bootloader.unlock_bits=0x3F -hexbright.bootloader.lock_bits=0x0F - -hexbright.build.mcu=atmega168 -hexbright.build.f_cpu=8000000L -hexbright.build.core=arduino:arduino -hexbright.build.variant=arduino:standard - - +############################################################## + +hexbright.name=Hexbright + +hexbright.upload.protocol=arduino +hexbright.upload.maximum_size=14336 +hexbright.upload.speed=19200 + +hexbright.bootloader.low_fuses=0xe2 +hexbright.bootloader.high_fuses=0xdd +hexbright.bootloader.extended_fuses=0x00 +hexbright.bootloader.path=atmega +hexbright.bootloader.file=ATmegaBOOT_168_hexbright.hex +hexbright.bootloader.unlock_bits=0x3F +hexbright.bootloader.lock_bits=0x0F + +hexbright.build.mcu=atmega168 +hexbright.build.f_cpu=8000000L +hexbright.build.core=arduino:arduino +hexbright.build.variant=arduino:standard + + diff --git a/hardware/hexbright/bootloader/ATmegaBOOT_168.c b/hardware/hexbright/bootloader/ATmegaBOOT_168.c index 2b9fefa..e8c3fb8 100755 --- a/hardware/hexbright/bootloader/ATmegaBOOT_168.c +++ b/hardware/hexbright/bootloader/ATmegaBOOT_168.c @@ -1,1054 +1,1054 @@ -/**********************************************************/ -/* Serial Bootloader for Atmel megaAVR Controllers */ -/* */ -/* tested with ATmega8, ATmega128 and ATmega168 */ -/* should work with other mega's, see code for details */ -/* */ -/* ATmegaBOOT.c */ -/* */ -/* */ -/* 20090308: integrated Mega changes into main bootloader */ -/* source by D. Mellis */ -/* 20080930: hacked for Arduino Mega (with the 1280 */ -/* processor, backwards compatible) */ -/* by D. Cuartielles */ -/* 20070626: hacked for Arduino Diecimila (which auto- */ -/* resets when a USB connection is made to it) */ -/* by D. Mellis */ -/* 20060802: hacked for Arduino by D. Cuartielles */ -/* based on a previous hack by D. Mellis */ -/* and D. Cuartielles */ -/* */ -/* Monitor and debug functions were added to the original */ -/* code by Dr. Erik Lins, chip45.com. (See below) */ -/* */ -/* Thanks to Karl Pitrich for fixing a bootloader pin */ -/* problem and more informative LED blinking! */ -/* */ -/* For the latest version see: */ -/* http://www.chip45.com/ */ -/* */ -/* ------------------------------------------------------ */ -/* */ -/* based on stk500boot.c */ -/* Copyright (c) 2003, Jason P. Kyle */ -/* All rights reserved. */ -/* see avr1.org for original file and information */ -/* */ -/* This program is free software; you can redistribute it */ -/* and/or modify it under the terms of the GNU General */ -/* Public License as published by the Free Software */ -/* Foundation; either version 2 of the License, or */ -/* (at your option) any later version. */ -/* */ -/* This program is distributed in the hope that it will */ -/* be useful, but WITHOUT ANY WARRANTY; without even the */ -/* implied warranty of MERCHANTABILITY or FITNESS FOR A */ -/* PARTICULAR PURPOSE. See the GNU General Public */ -/* License for more details. */ -/* */ -/* You should have received a copy of the GNU General */ -/* Public License along with this program; if not, write */ -/* to the Free Software Foundation, Inc., */ -/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* */ -/* Licence can be viewed at */ -/* http://www.fsf.org/licenses/gpl.txt */ -/* */ -/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */ -/* m8515,m8535. ATmega161 has a very small boot block so */ -/* isn't supported. */ -/* */ -/* Tested with m168 */ -/**********************************************************/ - -/* $Id$ */ - - -/* some includes */ -#include -#include -#include -#include -#include -#include - -/* the current avr-libc eeprom functions do not support the ATmega168 */ -/* own eeprom write/read functions are used instead */ -#if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__) -#include -#endif - -/* Use the F_CPU defined in Makefile */ - -/* 20060803: hacked by DojoCorp */ -/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */ -/* set the waiting time for the bootloader */ -/* get this from the Makefile instead */ -/* #define MAX_TIME_COUNT (F_CPU>>4) */ - -/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */ -#define MAX_ERROR_COUNT 5 - -/* set the UART baud rate */ -/* 20060803: hacked by DojoCorp */ -//#define BAUD_RATE 115200 -#ifndef BAUD_RATE -#define BAUD_RATE 19200 -#endif - - -/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ -/* never allow AVR Studio to do an update !!!! */ -#define HW_VER 0x02 -#define SW_MAJOR 0x01 -#define SW_MINOR 0x10 - - -/* Adjust to suit whatever pin your hardware uses to enter the bootloader */ -/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */ -/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */ -/* BL0... means UART0, BL1... means UART1 */ -#ifdef __AVR_ATmega128__ -#define BL_DDR DDRF -#define BL_PORT PORTF -#define BL_PIN PINF -#define BL0 PINF7 -#define BL1 PINF6 -#elif defined __AVR_ATmega1280__ -/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/ -#else -/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */ -#define BL_DDR DDRD -#define BL_PORT PORTD -#define BL_PIN PIND -#define BL PIND6 -#endif - - -/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */ -/* if monitor functions are included, LED goes on after monitor was entered */ -#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__ -/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */ -#define LED_DDR DDRB -#define LED_PORT PORTB -#define LED_PIN PINB -#define LED PINB7 -#else -/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */ -/* other boards like e.g. Crumb8, Crumb168 are using PB2 */ -#define LED_DDR DDRB -#define LED_PORT PORTB -#define LED_PIN PINB -#define LED PINB5 -#endif - - -/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */ -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) -#define MONITOR 1 -#endif - - -/* define various device id's */ -/* manufacturer byte is always the same */ -#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :( - -#if defined __AVR_ATmega1280__ -#define SIG2 0x97 -#define SIG3 0x03 -#define PAGE_SIZE 0x80U //128 words - -#elif defined __AVR_ATmega1281__ -#define SIG2 0x97 -#define SIG3 0x04 -#define PAGE_SIZE 0x80U //128 words - -#elif defined __AVR_ATmega128__ -#define SIG2 0x97 -#define SIG3 0x02 -#define PAGE_SIZE 0x80U //128 words - -#elif defined __AVR_ATmega64__ -#define SIG2 0x96 -#define SIG3 0x02 -#define PAGE_SIZE 0x80U //128 words - -#elif defined __AVR_ATmega32__ -#define SIG2 0x95 -#define SIG3 0x02 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega16__ -#define SIG2 0x94 -#define SIG3 0x03 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega8__ -#define SIG2 0x93 -#define SIG3 0x07 -#define PAGE_SIZE 0x20U //32 words - -#elif defined __AVR_ATmega88__ -#define SIG2 0x93 -#define SIG3 0x0a -#define PAGE_SIZE 0x20U //32 words - -#elif defined __AVR_ATmega168__ -#define SIG2 0x94 -#define SIG3 0x06 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega328P__ -#define SIG2 0x95 -#define SIG3 0x0F -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega162__ -#define SIG2 0x94 -#define SIG3 0x04 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega163__ -#define SIG2 0x94 -#define SIG3 0x02 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega169__ -#define SIG2 0x94 -#define SIG3 0x05 -#define PAGE_SIZE 0x40U //64 words - -#elif defined __AVR_ATmega8515__ -#define SIG2 0x93 -#define SIG3 0x06 -#define PAGE_SIZE 0x20U //32 words - -#elif defined __AVR_ATmega8535__ -#define SIG2 0x93 -#define SIG3 0x08 -#define PAGE_SIZE 0x20U //32 words -#endif - - -/* function prototypes */ -void putch(char); -char getch(void); -void getNch(uint8_t); -void byte_response(uint8_t); -void nothing_response(void); -char gethex(void); -void puthex(char); -void flash_led(uint8_t); - -/* some variables */ -union address_union { - uint16_t word; - uint8_t byte[2]; -} address; - -union length_union { - uint16_t word; - uint8_t byte[2]; -} length; - -struct flags_struct { - unsigned eeprom : 1; - unsigned rampz : 1; -} flags; - -uint8_t buff[256]; -uint8_t address_high; - -uint8_t pagesz=0x80; - -uint8_t i; -uint8_t bootuart = 0; - -uint8_t error_count = 0; - -void (*app_start)(void) = 0x0000; - - -/* main program starts here */ -int main(void) -{ - uint8_t ch,ch2; - uint16_t w; - -#ifdef WATCHDOG_MODS - ch = MCUSR; - MCUSR = 0; - - WDTCSR |= _BV(WDCE) | _BV(WDE); - WDTCSR = 0; - - // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot. - if (! (ch & _BV(EXTRF))) // if its a not an external reset... - app_start(); // skip bootloader -#else - asm volatile("nop\n\t"); -#endif - - /* set pin direction for bootloader pin and enable pullup */ - /* for ATmega128, two pins need to be initialized */ -#ifdef __AVR_ATmega128__ - BL_DDR &= ~_BV(BL0); - BL_DDR &= ~_BV(BL1); - BL_PORT |= _BV(BL0); - BL_PORT |= _BV(BL1); -#else - /* We run the bootloader regardless of the state of this pin. Thus, don't - put it in a different state than the other pins. --DAM, 070709 - This also applies to Arduino Mega -- DC, 080930 - BL_DDR &= ~_BV(BL); - BL_PORT |= _BV(BL); - */ -#endif - - -#ifdef __AVR_ATmega128__ - /* check which UART should be used for booting */ - if(bit_is_clear(BL_PIN, BL0)) { - bootuart = 1; - } - else if(bit_is_clear(BL_PIN, BL1)) { - bootuart = 2; - } -#endif - -#if defined __AVR_ATmega1280__ - /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */ - /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */ - bootuart = 1; -#endif - - /* check if flash is programmed already, if not start bootloader anyway */ - if(pgm_read_byte_near(0x0000) != 0xFF) { - -#ifdef __AVR_ATmega128__ - /* no UART was selected, start application */ - if(!bootuart) { - app_start(); - } -#else - /* check if bootloader pin is set low */ - /* we don't start this part neither for the m8, nor m168 */ - //if(bit_is_set(BL_PIN, BL)) { - // app_start(); - // } -#endif - } - -#ifdef __AVR_ATmega128__ - /* no bootuart was selected, default to uart 0 */ - if(!bootuart) { - bootuart = 1; - } -#endif - - - /* initialize UART(s) depending on CPU defined */ -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - if(bootuart == 1) { - UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); - UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; - UCSR0A = 0x00; - UCSR0C = 0x06; - UCSR0B = _BV(TXEN0)|_BV(RXEN0); - } - if(bootuart == 2) { - UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); - UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; - UCSR1A = 0x00; - UCSR1C = 0x06; - UCSR1B = _BV(TXEN1)|_BV(RXEN1); - } -#elif defined __AVR_ATmega163__ - UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); - UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8; - UCSRA = 0x00; - UCSRB = _BV(TXEN)|_BV(RXEN); -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - -#ifdef DOUBLE_SPEED - UCSR0A = (1<> 8; -#else - UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); - UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; -#endif - - UCSR0B = (1<>8; // set baud rate - UBRRL = (((F_CPU/BAUD_RATE)/16)-1); - UCSRB = (1<> 8; - UCSRA = 0x00; - UCSRC = 0x06; - UCSRB = _BV(TXEN)|_BV(RXEN); -#endif - -#if defined __AVR_ATmega1280__ - /* Enable internal pull-up resistor on pin D0 (RX), in order - to supress line noise that prevents the bootloader from - timing out (DAM: 20070509) */ - /* feature added to the Arduino Mega --DC: 080930 */ - DDRE &= ~_BV(PINE0); - PORTE |= _BV(PINE0); -#endif - - - /* set LED pin as output */ - LED_DDR |= _BV(LED); - - - /* flash onboard LED to signal entering of bootloader */ -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - // 4x for UART0, 5x for UART1 - flash_led(NUM_LED_FLASHES + bootuart); -#else - flash_led(NUM_LED_FLASHES); -#endif - - /* 20050803: by DojoCorp, this is one of the parts provoking the - system to stop listening, cancelled from the original */ - //putch('\0'); - - /* forever loop */ - for (;;) { - - /* get character from UART */ - ch = getch(); - - /* A bunch of if...else if... gives smaller code than switch...case ! */ - - /* Hello is anyone home ? */ - if(ch=='0') { - nothing_response(); - } - - - /* Request programmer ID */ - /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */ - /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */ - else if(ch=='1') { - if (getch() == ' ') { - putch(0x14); - putch('A'); - putch('V'); - putch('R'); - putch(' '); - putch('I'); - putch('S'); - putch('P'); - putch(0x10); - } else { - if (++error_count == MAX_ERROR_COUNT) - app_start(); - } - } - - - /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */ - else if(ch=='@') { - ch2 = getch(); - if (ch2>0x85) getch(); - nothing_response(); - } - - - /* AVR ISP/STK500 board requests */ - else if(ch=='A') { - ch2 = getch(); - if(ch2==0x80) byte_response(HW_VER); // Hardware version - else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version - else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version - else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56 - else byte_response(0x00); // Covers various unnecessary responses we don't care about - } - - - /* Device Parameters DON'T CARE, DEVICE IS FIXED */ - else if(ch=='B') { - getNch(20); - nothing_response(); - } - - - /* Parallel programming stuff DON'T CARE */ - else if(ch=='E') { - getNch(5); - nothing_response(); - } - - - /* P: Enter programming mode */ - /* R: Erase device, don't care as we will erase one page at a time anyway. */ - else if(ch=='P' || ch=='R') { - nothing_response(); - } - - - /* Leave programming mode */ - else if(ch=='Q') { - nothing_response(); -#ifdef WATCHDOG_MODS - // autoreset via watchdog (sneaky!) - WDTCSR = _BV(WDE); - while (1); // 16 ms -#endif - } - - - /* Set address, little endian. EEPROM in bytes, FLASH in words */ - /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */ - /* This might explain why little endian was used here, big endian used everywhere else. */ - else if(ch=='U') { - address.byte[0] = getch(); - address.byte[1] = getch(); - nothing_response(); - } - - - /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */ - else if(ch=='V') { - if (getch() == 0x30) { - getch(); - ch = getch(); - getch(); - if (ch == 0) { - byte_response(SIG1); - } else if (ch == 1) { - byte_response(SIG2); - } else { - byte_response(SIG3); - } - } else { - getNch(3); - byte_response(0x00); - } - } - - - /* Write memory, length is big endian and is in bytes */ - else if(ch=='d') { - length.byte[1] = getch(); - length.byte[0] = getch(); - flags.eeprom = 0; - if (getch() == 'E') flags.eeprom = 1; - for (w=0;w127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME - else address_high = 0x00; -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) - RAMPZ = address_high; -#endif - address.word = address.word << 1; //address * 2 -> byte location - /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */ - if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes - cli(); //Disable interrupts, just to be sure -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) - while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete -#else - while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete -#endif - asm volatile( - "clr r17 \n\t" //page_word_count - "lds r30,address \n\t" //Address of FLASH location (in bytes) - "lds r31,address+1 \n\t" - "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM - "ldi r29,hi8(buff) \n\t" - "lds r24,length \n\t" //Length of data to be written (in bytes) - "lds r25,length+1 \n\t" - "length_loop: \n\t" //Main loop, repeat for number of words in block - "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page - "brne no_page_erase \n\t" - "wait_spm1: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm1 \n\t" - "ldi r16,0x03 \n\t" //Erase page pointed to by Z - "sts %0,r16 \n\t" - "spm \n\t" -#ifdef __AVR_ATmega163__ - ".word 0xFFFF \n\t" - "nop \n\t" -#endif - "wait_spm2: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm2 \n\t" - - "ldi r16,0x11 \n\t" //Re-enable RWW section - "sts %0,r16 \n\t" - "spm \n\t" -#ifdef __AVR_ATmega163__ - ".word 0xFFFF \n\t" - "nop \n\t" -#endif - "no_page_erase: \n\t" - "ld r0,Y+ \n\t" //Write 2 bytes into page buffer - "ld r1,Y+ \n\t" - - "wait_spm3: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm3 \n\t" - "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer - "sts %0,r16 \n\t" - "spm \n\t" - - "inc r17 \n\t" //page_word_count++ - "cpi r17,%1 \n\t" - "brlo same_page \n\t" //Still same page in FLASH - "write_page: \n\t" - "clr r17 \n\t" //New page, write current one first - "wait_spm4: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm4 \n\t" -#ifdef __AVR_ATmega163__ - "andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write -#endif - "ldi r16,0x05 \n\t" //Write page pointed to by Z - "sts %0,r16 \n\t" - "spm \n\t" -#ifdef __AVR_ATmega163__ - ".word 0xFFFF \n\t" - "nop \n\t" - "ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write) -#endif - "wait_spm5: \n\t" - "lds r16,%0 \n\t" //Wait for previous spm to complete - "andi r16,1 \n\t" - "cpi r16,1 \n\t" - "breq wait_spm5 \n\t" - "ldi r16,0x11 \n\t" //Re-enable RWW section - "sts %0,r16 \n\t" - "spm \n\t" -#ifdef __AVR_ATmega163__ - ".word 0xFFFF \n\t" - "nop \n\t" -#endif - "same_page: \n\t" - "adiw r30,2 \n\t" //Next word in FLASH - "sbiw r24,2 \n\t" //length-2 - "breq final_write \n\t" //Finished - "rjmp length_loop \n\t" - "final_write: \n\t" - "cpi r17,0 \n\t" - "breq block_done \n\t" - "adiw r24,2 \n\t" //length+2, fool above check on length after short page write - "rjmp write_page \n\t" - "block_done: \n\t" - "clr __zero_reg__ \n\t" //restore zero register -#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ || __AVR_ATmega1281__ - : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" -#else - : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" -#endif - ); - /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */ - /* exit the bootloader without a power cycle anyhow */ - } - putch(0x14); - putch(0x10); - } else { - if (++error_count == MAX_ERROR_COUNT) - app_start(); - } - } - - - /* Read memory block mode, length is big endian. */ - else if(ch=='t') { - length.byte[1] = getch(); - length.byte[0] = getch(); -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME - else flags.rampz = 0; -#endif - address.word = address.word << 1; // address * 2 -> byte location - if (getch() == 'E') flags.eeprom = 1; - else flags.eeprom = 0; - if (getch() == ' ') { // Command terminator - putch(0x14); - for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay - if (flags.eeprom) { // Byte access EEPROM read -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - while(EECR & (1<= 'a') { - return (a - 'a' + 0x0a); - } else if(a >= '0') { - return(a - '0'); - } - return a; -} - - -char gethex(void) { - return (gethexnib() << 4) + gethexnib(); -} - - -void puthex(char ch) { - char ah; - - ah = ch >> 4; - if(ah >= 0x0a) { - ah = ah - 0x0a + 'a'; - } else { - ah += '0'; - } - - ch &= 0x0f; - if(ch >= 0x0a) { - ch = ch - 0x0a + 'a'; - } else { - ch += '0'; - } - - putch(ah); - putch(ch); -} - - -void putch(char ch) -{ -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - if(bootuart == 1) { - while (!(UCSR0A & _BV(UDRE0))); - UDR0 = ch; - } - else if (bootuart == 2) { - while (!(UCSR1A & _BV(UDRE1))); - UDR1 = ch; - } -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - while (!(UCSR0A & _BV(UDRE0))); - UDR0 = ch; -#else - /* m8,16,32,169,8515,8535,163 */ - while (!(UCSRA & _BV(UDRE))); - UDR = ch; -#endif -} - - -char getch(void) -{ -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - uint32_t count = 0; - if(bootuart == 1) { - while(!(UCSR0A & _BV(RXC0))) { - /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ - /* HACKME:: here is a good place to count times*/ - count++; - if (count > MAX_TIME_COUNT) - app_start(); - } - - return UDR0; - } - else if(bootuart == 2) { - while(!(UCSR1A & _BV(RXC1))) { - /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ - /* HACKME:: here is a good place to count times*/ - count++; - if (count > MAX_TIME_COUNT) - app_start(); - } - - return UDR1; - } - return 0; -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - uint32_t count = 0; - while(!(UCSR0A & _BV(RXC0))){ - /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ - /* HACKME:: here is a good place to count times*/ - count++; - if (count > MAX_TIME_COUNT) - app_start(); - } - return UDR0; -#else - /* m8,16,32,169,8515,8535,163 */ - uint32_t count = 0; - while(!(UCSRA & _BV(RXC))){ - /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ - /* HACKME:: here is a good place to count times*/ - count++; - if (count > MAX_TIME_COUNT) - app_start(); - } - return UDR; -#endif -} - - -void getNch(uint8_t count) -{ - while(count--) { -#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) - if(bootuart == 1) { - while(!(UCSR0A & _BV(RXC0))); - UDR0; - } - else if(bootuart == 2) { - while(!(UCSR1A & _BV(RXC1))); - UDR1; - } -#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) - getch(); -#else - /* m8,16,32,169,8515,8535,163 */ - /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ - //while(!(UCSRA & _BV(RXC))); - //UDR; - getch(); // need to handle time out -#endif - } -} - - -void byte_response(uint8_t val) -{ - if (getch() == ' ') { - putch(0x14); - putch(val); - putch(0x10); - } else { - if (++error_count == MAX_ERROR_COUNT) - app_start(); - } -} - - -void nothing_response(void) -{ - if (getch() == ' ') { - putch(0x14); - putch(0x10); - } else { - if (++error_count == MAX_ERROR_COUNT) - app_start(); - } -} - -void flash_led(uint8_t count) -{ - while (count--) { - LED_PORT |= _BV(LED); - _delay_ms(100); - LED_PORT &= ~_BV(LED); - _delay_ms(100); - } -} - - -/* end of file ATmegaBOOT.c */ +/**********************************************************/ +/* Serial Bootloader for Atmel megaAVR Controllers */ +/* */ +/* tested with ATmega8, ATmega128 and ATmega168 */ +/* should work with other mega's, see code for details */ +/* */ +/* ATmegaBOOT.c */ +/* */ +/* */ +/* 20090308: integrated Mega changes into main bootloader */ +/* source by D. Mellis */ +/* 20080930: hacked for Arduino Mega (with the 1280 */ +/* processor, backwards compatible) */ +/* by D. Cuartielles */ +/* 20070626: hacked for Arduino Diecimila (which auto- */ +/* resets when a USB connection is made to it) */ +/* by D. Mellis */ +/* 20060802: hacked for Arduino by D. Cuartielles */ +/* based on a previous hack by D. Mellis */ +/* and D. Cuartielles */ +/* */ +/* Monitor and debug functions were added to the original */ +/* code by Dr. Erik Lins, chip45.com. (See below) */ +/* */ +/* Thanks to Karl Pitrich for fixing a bootloader pin */ +/* problem and more informative LED blinking! */ +/* */ +/* For the latest version see: */ +/* http://www.chip45.com/ */ +/* */ +/* ------------------------------------------------------ */ +/* */ +/* based on stk500boot.c */ +/* Copyright (c) 2003, Jason P. Kyle */ +/* All rights reserved. */ +/* see avr1.org for original file and information */ +/* */ +/* This program is free software; you can redistribute it */ +/* and/or modify it under the terms of the GNU General */ +/* Public License as published by the Free Software */ +/* Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will */ +/* be useful, but WITHOUT ANY WARRANTY; without even the */ +/* implied warranty of MERCHANTABILITY or FITNESS FOR A */ +/* PARTICULAR PURPOSE. See the GNU General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU General */ +/* Public License along with this program; if not, write */ +/* to the Free Software Foundation, Inc., */ +/* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* */ +/* Licence can be viewed at */ +/* http://www.fsf.org/licenses/gpl.txt */ +/* */ +/* Target = Atmel AVR m128,m64,m32,m16,m8,m162,m163,m169, */ +/* m8515,m8535. ATmega161 has a very small boot block so */ +/* isn't supported. */ +/* */ +/* Tested with m168 */ +/**********************************************************/ + +/* $Id$ */ + + +/* some includes */ +#include +#include +#include +#include +#include +#include + +/* the current avr-libc eeprom functions do not support the ATmega168 */ +/* own eeprom write/read functions are used instead */ +#if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__) +#include +#endif + +/* Use the F_CPU defined in Makefile */ + +/* 20060803: hacked by DojoCorp */ +/* 20070626: hacked by David A. Mellis to decrease waiting time for auto-reset */ +/* set the waiting time for the bootloader */ +/* get this from the Makefile instead */ +/* #define MAX_TIME_COUNT (F_CPU>>4) */ + +/* 20070707: hacked by David A. Mellis - after this many errors give up and launch application */ +#define MAX_ERROR_COUNT 5 + +/* set the UART baud rate */ +/* 20060803: hacked by DojoCorp */ +//#define BAUD_RATE 115200 +#ifndef BAUD_RATE +#define BAUD_RATE 19200 +#endif + + +/* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ +/* never allow AVR Studio to do an update !!!! */ +#define HW_VER 0x02 +#define SW_MAJOR 0x01 +#define SW_MINOR 0x10 + + +/* Adjust to suit whatever pin your hardware uses to enter the bootloader */ +/* ATmega128 has two UARTS so two pins are used to enter bootloader and select UART */ +/* ATmega1280 has four UARTS, but for Arduino Mega, we will only use RXD0 to get code */ +/* BL0... means UART0, BL1... means UART1 */ +#ifdef __AVR_ATmega128__ +#define BL_DDR DDRF +#define BL_PORT PORTF +#define BL_PIN PINF +#define BL0 PINF7 +#define BL1 PINF6 +#elif defined __AVR_ATmega1280__ +/* we just don't do anything for the MEGA and enter bootloader on reset anyway*/ +#else +/* other ATmegas have only one UART, so only one pin is defined to enter bootloader */ +#define BL_DDR DDRD +#define BL_PORT PORTD +#define BL_PIN PIND +#define BL PIND6 +#endif + + +/* onboard LED is used to indicate, that the bootloader was entered (3x flashing) */ +/* if monitor functions are included, LED goes on after monitor was entered */ +#if defined __AVR_ATmega128__ || defined __AVR_ATmega1280__ +/* Onboard LED is connected to pin PB7 (e.g. Crumb128, PROBOmega128, Savvy128, Arduino Mega) */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB7 +#else +/* Onboard LED is connected to pin PB5 in Arduino NG, Diecimila, and Duomilanuove */ +/* other boards like e.g. Crumb8, Crumb168 are using PB2 */ +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN PINB +#define LED PINB5 +#endif + + +/* monitor functions will only be compiled when using ATmega128, due to bootblock size constraints */ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) +#define MONITOR 1 +#endif + + +/* define various device id's */ +/* manufacturer byte is always the same */ +#define SIG1 0x1E // Yep, Atmel is the only manufacturer of AVR micros. Single source :( + +#if defined __AVR_ATmega1280__ +#define SIG2 0x97 +#define SIG3 0x03 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega1281__ +#define SIG2 0x97 +#define SIG3 0x04 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega128__ +#define SIG2 0x97 +#define SIG3 0x02 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega64__ +#define SIG2 0x96 +#define SIG3 0x02 +#define PAGE_SIZE 0x80U //128 words + +#elif defined __AVR_ATmega32__ +#define SIG2 0x95 +#define SIG3 0x02 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega16__ +#define SIG2 0x94 +#define SIG3 0x03 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega8__ +#define SIG2 0x93 +#define SIG3 0x07 +#define PAGE_SIZE 0x20U //32 words + +#elif defined __AVR_ATmega88__ +#define SIG2 0x93 +#define SIG3 0x0a +#define PAGE_SIZE 0x20U //32 words + +#elif defined __AVR_ATmega168__ +#define SIG2 0x94 +#define SIG3 0x06 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega328P__ +#define SIG2 0x95 +#define SIG3 0x0F +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega162__ +#define SIG2 0x94 +#define SIG3 0x04 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega163__ +#define SIG2 0x94 +#define SIG3 0x02 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega169__ +#define SIG2 0x94 +#define SIG3 0x05 +#define PAGE_SIZE 0x40U //64 words + +#elif defined __AVR_ATmega8515__ +#define SIG2 0x93 +#define SIG3 0x06 +#define PAGE_SIZE 0x20U //32 words + +#elif defined __AVR_ATmega8535__ +#define SIG2 0x93 +#define SIG3 0x08 +#define PAGE_SIZE 0x20U //32 words +#endif + + +/* function prototypes */ +void putch(char); +char getch(void); +void getNch(uint8_t); +void byte_response(uint8_t); +void nothing_response(void); +char gethex(void); +void puthex(char); +void flash_led(uint8_t); + +/* some variables */ +union address_union { + uint16_t word; + uint8_t byte[2]; +} address; + +union length_union { + uint16_t word; + uint8_t byte[2]; +} length; + +struct flags_struct { + unsigned eeprom : 1; + unsigned rampz : 1; +} flags; + +uint8_t buff[256]; +uint8_t address_high; + +uint8_t pagesz=0x80; + +uint8_t i; +uint8_t bootuart = 0; + +uint8_t error_count = 0; + +void (*app_start)(void) = 0x0000; + + +/* main program starts here */ +int main(void) +{ + uint8_t ch,ch2; + uint16_t w; + +#ifdef WATCHDOG_MODS + ch = MCUSR; + MCUSR = 0; + + WDTCSR |= _BV(WDCE) | _BV(WDE); + WDTCSR = 0; + + // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot. + if (! (ch & _BV(EXTRF))) // if its a not an external reset... + app_start(); // skip bootloader +#else + asm volatile("nop\n\t"); +#endif + + /* set pin direction for bootloader pin and enable pullup */ + /* for ATmega128, two pins need to be initialized */ +#ifdef __AVR_ATmega128__ + BL_DDR &= ~_BV(BL0); + BL_DDR &= ~_BV(BL1); + BL_PORT |= _BV(BL0); + BL_PORT |= _BV(BL1); +#else + /* We run the bootloader regardless of the state of this pin. Thus, don't + put it in a different state than the other pins. --DAM, 070709 + This also applies to Arduino Mega -- DC, 080930 + BL_DDR &= ~_BV(BL); + BL_PORT |= _BV(BL); + */ +#endif + + +#ifdef __AVR_ATmega128__ + /* check which UART should be used for booting */ + if(bit_is_clear(BL_PIN, BL0)) { + bootuart = 1; + } + else if(bit_is_clear(BL_PIN, BL1)) { + bootuart = 2; + } +#endif + +#if defined __AVR_ATmega1280__ + /* the mega1280 chip has four serial ports ... we could eventually use any of them, or not? */ + /* however, we don't wanna confuse people, to avoid making a mess, we will stick to RXD0, TXD0 */ + bootuart = 1; +#endif + + /* check if flash is programmed already, if not start bootloader anyway */ + if(pgm_read_byte_near(0x0000) != 0xFF) { + +#ifdef __AVR_ATmega128__ + /* no UART was selected, start application */ + if(!bootuart) { + app_start(); + } +#else + /* check if bootloader pin is set low */ + /* we don't start this part neither for the m8, nor m168 */ + //if(bit_is_set(BL_PIN, BL)) { + // app_start(); + // } +#endif + } + +#ifdef __AVR_ATmega128__ + /* no bootuart was selected, default to uart 0 */ + if(!bootuart) { + bootuart = 1; + } +#endif + + + /* initialize UART(s) depending on CPU defined */ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + if(bootuart == 1) { + UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); + UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; + UCSR0A = 0x00; + UCSR0C = 0x06; + UCSR0B = _BV(TXEN0)|_BV(RXEN0); + } + if(bootuart == 2) { + UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); + UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; + UCSR1A = 0x00; + UCSR1C = 0x06; + UCSR1B = _BV(TXEN1)|_BV(RXEN1); + } +#elif defined __AVR_ATmega163__ + UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); + UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8; + UCSRA = 0x00; + UCSRB = _BV(TXEN)|_BV(RXEN); +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) + +#ifdef DOUBLE_SPEED + UCSR0A = (1<> 8; +#else + UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); + UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; +#endif + + UCSR0B = (1<>8; // set baud rate + UBRRL = (((F_CPU/BAUD_RATE)/16)-1); + UCSRB = (1<> 8; + UCSRA = 0x00; + UCSRC = 0x06; + UCSRB = _BV(TXEN)|_BV(RXEN); +#endif + +#if defined __AVR_ATmega1280__ + /* Enable internal pull-up resistor on pin D0 (RX), in order + to supress line noise that prevents the bootloader from + timing out (DAM: 20070509) */ + /* feature added to the Arduino Mega --DC: 080930 */ + DDRE &= ~_BV(PINE0); + PORTE |= _BV(PINE0); +#endif + + + /* set LED pin as output */ + LED_DDR |= _BV(LED); + + + /* flash onboard LED to signal entering of bootloader */ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + // 4x for UART0, 5x for UART1 + flash_led(NUM_LED_FLASHES + bootuart); +#else + flash_led(NUM_LED_FLASHES); +#endif + + /* 20050803: by DojoCorp, this is one of the parts provoking the + system to stop listening, cancelled from the original */ + //putch('\0'); + + /* forever loop */ + for (;;) { + + /* get character from UART */ + ch = getch(); + + /* A bunch of if...else if... gives smaller code than switch...case ! */ + + /* Hello is anyone home ? */ + if(ch=='0') { + nothing_response(); + } + + + /* Request programmer ID */ + /* Not using PROGMEM string due to boot block in m128 being beyond 64kB boundry */ + /* Would need to selectively manipulate RAMPZ, and it's only 9 characters anyway so who cares. */ + else if(ch=='1') { + if (getch() == ' ') { + putch(0x14); + putch('A'); + putch('V'); + putch('R'); + putch(' '); + putch('I'); + putch('S'); + putch('P'); + putch(0x10); + } else { + if (++error_count == MAX_ERROR_COUNT) + app_start(); + } + } + + + /* AVR ISP/STK500 board commands DON'T CARE so default nothing_response */ + else if(ch=='@') { + ch2 = getch(); + if (ch2>0x85) getch(); + nothing_response(); + } + + + /* AVR ISP/STK500 board requests */ + else if(ch=='A') { + ch2 = getch(); + if(ch2==0x80) byte_response(HW_VER); // Hardware version + else if(ch2==0x81) byte_response(SW_MAJOR); // Software major version + else if(ch2==0x82) byte_response(SW_MINOR); // Software minor version + else if(ch2==0x98) byte_response(0x03); // Unknown but seems to be required by avr studio 3.56 + else byte_response(0x00); // Covers various unnecessary responses we don't care about + } + + + /* Device Parameters DON'T CARE, DEVICE IS FIXED */ + else if(ch=='B') { + getNch(20); + nothing_response(); + } + + + /* Parallel programming stuff DON'T CARE */ + else if(ch=='E') { + getNch(5); + nothing_response(); + } + + + /* P: Enter programming mode */ + /* R: Erase device, don't care as we will erase one page at a time anyway. */ + else if(ch=='P' || ch=='R') { + nothing_response(); + } + + + /* Leave programming mode */ + else if(ch=='Q') { + nothing_response(); +#ifdef WATCHDOG_MODS + // autoreset via watchdog (sneaky!) + WDTCSR = _BV(WDE); + while (1); // 16 ms +#endif + } + + + /* Set address, little endian. EEPROM in bytes, FLASH in words */ + /* Perhaps extra address bytes may be added in future to support > 128kB FLASH. */ + /* This might explain why little endian was used here, big endian used everywhere else. */ + else if(ch=='U') { + address.byte[0] = getch(); + address.byte[1] = getch(); + nothing_response(); + } + + + /* Universal SPI programming command, disabled. Would be used for fuses and lock bits. */ + else if(ch=='V') { + if (getch() == 0x30) { + getch(); + ch = getch(); + getch(); + if (ch == 0) { + byte_response(SIG1); + } else if (ch == 1) { + byte_response(SIG2); + } else { + byte_response(SIG3); + } + } else { + getNch(3); + byte_response(0x00); + } + } + + + /* Write memory, length is big endian and is in bytes */ + else if(ch=='d') { + length.byte[1] = getch(); + length.byte[0] = getch(); + flags.eeprom = 0; + if (getch() == 'E') flags.eeprom = 1; + for (w=0;w127) address_high = 0x01; //Only possible with m128, m256 will need 3rd address byte. FIXME + else address_high = 0x00; +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) + RAMPZ = address_high; +#endif + address.word = address.word << 1; //address * 2 -> byte location + /* if ((length.byte[0] & 0x01) == 0x01) length.word++; //Even up an odd number of bytes */ + if ((length.byte[0] & 0x01)) length.word++; //Even up an odd number of bytes + cli(); //Disable interrupts, just to be sure +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) + while(bit_is_set(EECR,EEPE)); //Wait for previous EEPROM writes to complete +#else + while(bit_is_set(EECR,EEWE)); //Wait for previous EEPROM writes to complete +#endif + asm volatile( + "clr r17 \n\t" //page_word_count + "lds r30,address \n\t" //Address of FLASH location (in bytes) + "lds r31,address+1 \n\t" + "ldi r28,lo8(buff) \n\t" //Start of buffer array in RAM + "ldi r29,hi8(buff) \n\t" + "lds r24,length \n\t" //Length of data to be written (in bytes) + "lds r25,length+1 \n\t" + "length_loop: \n\t" //Main loop, repeat for number of words in block + "cpi r17,0x00 \n\t" //If page_word_count=0 then erase page + "brne no_page_erase \n\t" + "wait_spm1: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm1 \n\t" + "ldi r16,0x03 \n\t" //Erase page pointed to by Z + "sts %0,r16 \n\t" + "spm \n\t" +#ifdef __AVR_ATmega163__ + ".word 0xFFFF \n\t" + "nop \n\t" +#endif + "wait_spm2: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm2 \n\t" + + "ldi r16,0x11 \n\t" //Re-enable RWW section + "sts %0,r16 \n\t" + "spm \n\t" +#ifdef __AVR_ATmega163__ + ".word 0xFFFF \n\t" + "nop \n\t" +#endif + "no_page_erase: \n\t" + "ld r0,Y+ \n\t" //Write 2 bytes into page buffer + "ld r1,Y+ \n\t" + + "wait_spm3: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm3 \n\t" + "ldi r16,0x01 \n\t" //Load r0,r1 into FLASH page buffer + "sts %0,r16 \n\t" + "spm \n\t" + + "inc r17 \n\t" //page_word_count++ + "cpi r17,%1 \n\t" + "brlo same_page \n\t" //Still same page in FLASH + "write_page: \n\t" + "clr r17 \n\t" //New page, write current one first + "wait_spm4: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm4 \n\t" +#ifdef __AVR_ATmega163__ + "andi r30,0x80 \n\t" // m163 requires Z6:Z1 to be zero during page write +#endif + "ldi r16,0x05 \n\t" //Write page pointed to by Z + "sts %0,r16 \n\t" + "spm \n\t" +#ifdef __AVR_ATmega163__ + ".word 0xFFFF \n\t" + "nop \n\t" + "ori r30,0x7E \n\t" // recover Z6:Z1 state after page write (had to be zero during write) +#endif + "wait_spm5: \n\t" + "lds r16,%0 \n\t" //Wait for previous spm to complete + "andi r16,1 \n\t" + "cpi r16,1 \n\t" + "breq wait_spm5 \n\t" + "ldi r16,0x11 \n\t" //Re-enable RWW section + "sts %0,r16 \n\t" + "spm \n\t" +#ifdef __AVR_ATmega163__ + ".word 0xFFFF \n\t" + "nop \n\t" +#endif + "same_page: \n\t" + "adiw r30,2 \n\t" //Next word in FLASH + "sbiw r24,2 \n\t" //length-2 + "breq final_write \n\t" //Finished + "rjmp length_loop \n\t" + "final_write: \n\t" + "cpi r17,0 \n\t" + "breq block_done \n\t" + "adiw r24,2 \n\t" //length+2, fool above check on length after short page write + "rjmp write_page \n\t" + "block_done: \n\t" + "clr __zero_reg__ \n\t" //restore zero register +#if defined __AVR_ATmega168__ || __AVR_ATmega328P__ || __AVR_ATmega128__ || __AVR_ATmega1280__ || __AVR_ATmega1281__ + : "=m" (SPMCSR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" +#else + : "=m" (SPMCR) : "M" (PAGE_SIZE) : "r0","r16","r17","r24","r25","r28","r29","r30","r31" +#endif + ); + /* Should really add a wait for RWW section to be enabled, don't actually need it since we never */ + /* exit the bootloader without a power cycle anyhow */ + } + putch(0x14); + putch(0x10); + } else { + if (++error_count == MAX_ERROR_COUNT) + app_start(); + } + } + + + /* Read memory block mode, length is big endian. */ + else if(ch=='t') { + length.byte[1] = getch(); + length.byte[0] = getch(); +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + if (address.word>0x7FFF) flags.rampz = 1; // No go with m256, FIXME + else flags.rampz = 0; +#endif + address.word = address.word << 1; // address * 2 -> byte location + if (getch() == 'E') flags.eeprom = 1; + else flags.eeprom = 0; + if (getch() == ' ') { // Command terminator + putch(0x14); + for (w=0;w < length.word;w++) { // Can handle odd and even lengths okay + if (flags.eeprom) { // Byte access EEPROM read +#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) + while(EECR & (1<= 'a') { + return (a - 'a' + 0x0a); + } else if(a >= '0') { + return(a - '0'); + } + return a; +} + + +char gethex(void) { + return (gethexnib() << 4) + gethexnib(); +} + + +void puthex(char ch) { + char ah; + + ah = ch >> 4; + if(ah >= 0x0a) { + ah = ah - 0x0a + 'a'; + } else { + ah += '0'; + } + + ch &= 0x0f; + if(ch >= 0x0a) { + ch = ch - 0x0a + 'a'; + } else { + ch += '0'; + } + + putch(ah); + putch(ch); +} + + +void putch(char ch) +{ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + if(bootuart == 1) { + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = ch; + } + else if (bootuart == 2) { + while (!(UCSR1A & _BV(UDRE1))); + UDR1 = ch; + } +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) + while (!(UCSR0A & _BV(UDRE0))); + UDR0 = ch; +#else + /* m8,16,32,169,8515,8535,163 */ + while (!(UCSRA & _BV(UDRE))); + UDR = ch; +#endif +} + + +char getch(void) +{ +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + uint32_t count = 0; + if(bootuart == 1) { + while(!(UCSR0A & _BV(RXC0))) { + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + + return UDR0; + } + else if(bootuart == 2) { + while(!(UCSR1A & _BV(RXC1))) { + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + + return UDR1; + } + return 0; +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) + uint32_t count = 0; + while(!(UCSR0A & _BV(RXC0))){ + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + return UDR0; +#else + /* m8,16,32,169,8515,8535,163 */ + uint32_t count = 0; + while(!(UCSRA & _BV(RXC))){ + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + /* HACKME:: here is a good place to count times*/ + count++; + if (count > MAX_TIME_COUNT) + app_start(); + } + return UDR; +#endif +} + + +void getNch(uint8_t count) +{ + while(count--) { +#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) + if(bootuart == 1) { + while(!(UCSR0A & _BV(RXC0))); + UDR0; + } + else if(bootuart == 2) { + while(!(UCSR1A & _BV(RXC1))); + UDR1; + } +#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) + getch(); +#else + /* m8,16,32,169,8515,8535,163 */ + /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ + //while(!(UCSRA & _BV(RXC))); + //UDR; + getch(); // need to handle time out +#endif + } +} + + +void byte_response(uint8_t val) +{ + if (getch() == ' ') { + putch(0x14); + putch(val); + putch(0x10); + } else { + if (++error_count == MAX_ERROR_COUNT) + app_start(); + } +} + + +void nothing_response(void) +{ + if (getch() == ' ') { + putch(0x14); + putch(0x10); + } else { + if (++error_count == MAX_ERROR_COUNT) + app_start(); + } +} + +void flash_led(uint8_t count) +{ + while (count--) { + LED_PORT |= _BV(LED); + _delay_ms(100); + LED_PORT &= ~_BV(LED); + _delay_ms(100); + } +} + + +/* end of file ATmegaBOOT.c */ diff --git a/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex b/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex index f471b71..a5e20c9 100755 --- a/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex +++ b/hardware/hexbright/bootloader/ATmegaBOOT_168_hexbright.hex @@ -1,125 +1,125 @@ -:103800000C94341C0C94511C0C94511C0C94511CA1 -:103810000C94511C0C94511C0C94511C0C94511C74 -:103820000C94511C0C94511C0C94511C0C94511C64 -:103830000C94511C0C94511C0C94511C0C94511C54 -:103840000C94511C0C94511C0C94511C0C94511C44 -:103850000C94511C0C94511C0C94511C0C94511C34 -:103860000C94511C0C94511C11241FBECFEFD4E0BA -:10387000DEBFCDBF11E0A0E0B1E0E8E9FFE302C0A8 -:1038800005900D92A230B107D9F712E0A2E0B1E0A5 -:1038900001C01D92AD30B107E1F70E942D1D0C94BF -:1038A000CA1F0C94001C982F959595959595959504 -:1038B000905D8F708A307CF0282F295A8091C0004B -:1038C00085FFFCCF9093C6008091C00085FFFCCFA0 -:1038D0002093C6000895282F205DF0CF982F809167 -:1038E000C00085FFFCCF9093C6000895EF92FF9231 -:1038F0000F931F93EE24FF2487018091C00087FD62 -:1039000017C00894E11CF11C011D111D81E2E8168D -:1039100081EAF80687E0080780E0180770F3E09175 -:103920000401F091050109958091C00087FFE9CF5E -:103930008091C6001F910F91FF90EF9008950E9413 -:10394000761C982F8091C00085FFFCCF9093C60015 -:1039500091362CF490330CF09053892F089597559D -:10396000892F08951F930E949F1C182F0E949F1C4F -:103970001295107F810F1F9108951F93182F882390 -:1039800021F00E94761C1150E1F71F9108951F93BA -:10399000182F0E94761C803249F0809103018F5FBE -:1039A000809303018530C1F01F9108958091C0007C -:1039B00085FFFCCF84E18093C6008091C00085FF25 -:1039C000FCCF1093C6008091C00085FFFCCF80E142 -:1039D0008093C6001F910895E0910401F0910501C4 -:1039E00009951F9108950E94761C803241F08091C4 -:1039F00003018F5F80930301853081F008958091EA -:103A0000C00085FFFCCF84E18093C6008091C00098 -:103A100085FFFCCF80E18093C6000895E09104010A -:103A2000F09105010995089548EC50E08823A1F034 -:103A30002D9A28EE33E0FA013197F1F7215030400A -:103A4000D1F72D9828EE33E0FA013197F1F72150A4 -:103A50003040D1F7815061F708953F924F925F92C5 -:103A60006F927F928F929F92AF92BF92CF92DF928E -:103A7000EF92FF920F931F93CF93DF9394B714BEEF -:103A8000809160008861809360001092600091FFD7 -:103A900007C289E18093C4001092C50088E1809339 -:103AA000C10086E08093C2005098589A259A80E021 -:103AB0000E94141D44E1F42E3EE1E32E24E9D22EAF -:103AC00096E0C92E80E1B82EAA24A39401E4902E9A -:103AD00016E5812EB2E57B2EA0E26A2EF9E45F2E78 -:103AE000E3E54E2E70E5372E0E94761C8033B9F147 -:103AF0008133C1F1803409F470C0813409F477C096 -:103B0000823409F486C0853409F489C0803539F1DE -:103B1000823529F1813509F4A2C1853509F485C0C2 -:103B2000863509F48DC0843609F42EC1843709F432 -:103B3000C1C0853709F490C0863709F466C080910A -:103B400003018F5F80930301853071F6E0910401DA -:103B5000F091050109950E94761C803349F60E9478 -:103B6000F31CC2CF0E94761C803249F78091C000BE -:103B700085FFFCCFF092C6008091C00085FFFCCF8E -:103B80009092C6008091C00085FFFCCF8092C60055 -:103B90008091C00085FFFCCF7092C6008091C0006C -:103BA00085FFFCCF6092C6008091C00085FFFCCFEE -:103BB0005092C6008091C00085FFFCCF4092C600A5 -:103BC0008091C00085FFFCCF3092C6008091C0007C -:103BD00085FFFCCFB092C60087CF0E94761C863846 -:103BE00008F4BDCF0E94761C0E94F31C7DCF0E947A -:103BF000761C803809F45AC0813809F453C08238E1 -:103C000009F433C1883909F449C080E00E94C71C17 -:103C10006BCF84E10E94BD1C0E94F31C65CF85E040 -:103C20000E94BD1C0E94F31C5FCF0E94761C8093F3 -:103C300006010E94761C809307010E94F31C54CF5A -:103C40000E94761C803309F414C183E00E94BD1CDD -:103C500080E00E94C71C48CF0E94761C803209F089 -:103C60006ECF8091C00085FFFCCFF092C60080919E -:103C7000C00085FFFCCFE092C6008091C00085FFA8 -:103C8000FCCFD092C6008091C00085FFFCCFC092CF -:103C9000C6008091C00085FFFCCF9CCF83E00E94CE -:103CA000C71C22CF81E00E94C71C1ECF82E00E9469 -:103CB000C71C1ACF0E94761C809309020E94761CB2 -:103CC000809308028091060190910701880F991F47 -:103CD00090930701809306010E94761C853409F4B5 -:103CE000D9C080910C028E7F80930C020E94761CBA -:103CF000803209F0F9CE8091C00085FFFCCFF092B0 -:103D0000C600009108021091090201151105B9F1D0 -:103D100080910C02B82FB170A82FA695A170E091E8 -:103D20000601F09107019F012F5F3F4FB90140E06D -:103D300050E0BB23A9F4AA2339F494918091C000E8 -:103D400085FFFCCF9093C6004F5F5F4FCB0101967C -:103D5000F9014017510778F4BC012F5F3F4FE9CFBD -:103D6000F999FECFF2BDE1BDF89A90B58091C000FF -:103D700085FFFCCFE7CF7093070160930601809128 -:103D8000C00085FFFCCF26CF0E94761C80930902DD -:103D90000E94761C8093080280910C028E7F809393 -:103DA0000C020E94761C853429F480910C028160FB -:103DB00080930C028091080290910902892B89F06E -:103DC00000E010E00E94761CF801E85FFE4F80835F -:103DD0000F5F1F4F80910802909109020817190781 -:103DE00088F30E94761C803209F0A9CE80910C02E3 -:103DF00080FF5CC04091060150910701440F551FA0 -:103E000050930701409306016091080270910902E6 -:103E100061157105C9F0E8E0F1E09A01DB01AE0F30 -:103E2000BF1FF999FECF32BD21BD819180BDFA9AA5 -:103E3000F99A2F5F3F4FEA17FB0799F7460F571F75 -:103E400050930701409306018091C00085FFFCCF8D -:103E5000F092C6008091C00085FFFCCFBBCE0E94CF -:103E6000F31C88E080936000FFCF80E10E94C71CB4 -:103E70003BCE0E94761C0E94761C182F0E94761C56 -:103E8000112309F483C0113009F47CC086E00E943C -:103E9000C71C2ACE80910C02816080930C0226CF31 -:103EA000E0910401F09105010995F3CD809107019E -:103EB0008823880F880B8A2180930B02809106014A -:103EC00090910701880F991F909307018093060135 -:103ED0008091080280FF09C0809108029091090238 -:103EE00001969093090280930802F894F999FECF05 -:103EF0001127E0910601F0910701C8E0D1E080911F -:103F0000080290910902103091F40091570001705D -:103F10000130D9F303E000935700E8950091570072 -:103F200001700130D9F301E100935700E895099041 -:103F300019900091570001700130D9F301E000930E -:103F40005700E8951395103498F011270091570009 -:103F500001700130D9F305E000935700E895009116 -:103F6000570001700130D9F301E100935700E89543 -:103F70003296029709F0C7CF103011F00296E5CFC4 -:103F8000112462CF84E90E94C71CAECD8EE10E944D -:083F9000C71CAACDF894FFCF75 -:023F98008000A7 -:0400000300003800C1 -:00000001FF +:103800000C94341C0C94511C0C94511C0C94511CA1 +:103810000C94511C0C94511C0C94511C0C94511C74 +:103820000C94511C0C94511C0C94511C0C94511C64 +:103830000C94511C0C94511C0C94511C0C94511C54 +:103840000C94511C0C94511C0C94511C0C94511C44 +:103850000C94511C0C94511C0C94511C0C94511C34 +:103860000C94511C0C94511C11241FBECFEFD4E0BA +:10387000DEBFCDBF11E0A0E0B1E0E8E9FFE302C0A8 +:1038800005900D92A230B107D9F712E0A2E0B1E0A5 +:1038900001C01D92AD30B107E1F70E942D1D0C94BF +:1038A000CA1F0C94001C982F959595959595959504 +:1038B000905D8F708A307CF0282F295A8091C0004B +:1038C00085FFFCCF9093C6008091C00085FFFCCFA0 +:1038D0002093C6000895282F205DF0CF982F809167 +:1038E000C00085FFFCCF9093C6000895EF92FF9231 +:1038F0000F931F93EE24FF2487018091C00087FD62 +:1039000017C00894E11CF11C011D111D81E2E8168D +:1039100081EAF80687E0080780E0180770F3E09175 +:103920000401F091050109958091C00087FFE9CF5E +:103930008091C6001F910F91FF90EF9008950E9413 +:10394000761C982F8091C00085FFFCCF9093C60015 +:1039500091362CF490330CF09053892F089597559D +:10396000892F08951F930E949F1C182F0E949F1C4F +:103970001295107F810F1F9108951F93182F882390 +:1039800021F00E94761C1150E1F71F9108951F93BA +:10399000182F0E94761C803249F0809103018F5FBE +:1039A000809303018530C1F01F9108958091C0007C +:1039B00085FFFCCF84E18093C6008091C00085FF25 +:1039C000FCCF1093C6008091C00085FFFCCF80E142 +:1039D0008093C6001F910895E0910401F0910501C4 +:1039E00009951F9108950E94761C803241F08091C4 +:1039F00003018F5F80930301853081F008958091EA +:103A0000C00085FFFCCF84E18093C6008091C00098 +:103A100085FFFCCF80E18093C6000895E09104010A +:103A2000F09105010995089548EC50E08823A1F034 +:103A30002D9A28EE33E0FA013197F1F7215030400A +:103A4000D1F72D9828EE33E0FA013197F1F72150A4 +:103A50003040D1F7815061F708953F924F925F92C5 +:103A60006F927F928F929F92AF92BF92CF92DF928E +:103A7000EF92FF920F931F93CF93DF9394B714BEEF +:103A8000809160008861809360001092600091FFD7 +:103A900007C289E18093C4001092C50088E1809339 +:103AA000C10086E08093C2005098589A259A80E021 +:103AB0000E94141D44E1F42E3EE1E32E24E9D22EAF +:103AC00096E0C92E80E1B82EAA24A39401E4902E9A +:103AD00016E5812EB2E57B2EA0E26A2EF9E45F2E78 +:103AE000E3E54E2E70E5372E0E94761C8033B9F147 +:103AF0008133C1F1803409F470C0813409F477C096 +:103B0000823409F486C0853409F489C0803539F1DE +:103B1000823529F1813509F4A2C1853509F485C0C2 +:103B2000863509F48DC0843609F42EC1843709F432 +:103B3000C1C0853709F490C0863709F466C080910A +:103B400003018F5F80930301853071F6E0910401DA +:103B5000F091050109950E94761C803349F60E9478 +:103B6000F31CC2CF0E94761C803249F78091C000BE +:103B700085FFFCCFF092C6008091C00085FFFCCF8E +:103B80009092C6008091C00085FFFCCF8092C60055 +:103B90008091C00085FFFCCF7092C6008091C0006C +:103BA00085FFFCCF6092C6008091C00085FFFCCFEE +:103BB0005092C6008091C00085FFFCCF4092C600A5 +:103BC0008091C00085FFFCCF3092C6008091C0007C +:103BD00085FFFCCFB092C60087CF0E94761C863846 +:103BE00008F4BDCF0E94761C0E94F31C7DCF0E947A +:103BF000761C803809F45AC0813809F453C08238E1 +:103C000009F433C1883909F449C080E00E94C71C17 +:103C10006BCF84E10E94BD1C0E94F31C65CF85E040 +:103C20000E94BD1C0E94F31C5FCF0E94761C8093F3 +:103C300006010E94761C809307010E94F31C54CF5A +:103C40000E94761C803309F414C183E00E94BD1CDD +:103C500080E00E94C71C48CF0E94761C803209F089 +:103C60006ECF8091C00085FFFCCFF092C60080919E +:103C7000C00085FFFCCFE092C6008091C00085FFA8 +:103C8000FCCFD092C6008091C00085FFFCCFC092CF +:103C9000C6008091C00085FFFCCF9CCF83E00E94CE +:103CA000C71C22CF81E00E94C71C1ECF82E00E9469 +:103CB000C71C1ACF0E94761C809309020E94761CB2 +:103CC000809308028091060190910701880F991F47 +:103CD00090930701809306010E94761C853409F4B5 +:103CE000D9C080910C028E7F80930C020E94761CBA +:103CF000803209F0F9CE8091C00085FFFCCFF092B0 +:103D0000C600009108021091090201151105B9F1D0 +:103D100080910C02B82FB170A82FA695A170E091E8 +:103D20000601F09107019F012F5F3F4FB90140E06D +:103D300050E0BB23A9F4AA2339F494918091C000E8 +:103D400085FFFCCF9093C6004F5F5F4FCB0101967C +:103D5000F9014017510778F4BC012F5F3F4FE9CFBD +:103D6000F999FECFF2BDE1BDF89A90B58091C000FF +:103D700085FFFCCFE7CF7093070160930601809128 +:103D8000C00085FFFCCF26CF0E94761C80930902DD +:103D90000E94761C8093080280910C028E7F809393 +:103DA0000C020E94761C853429F480910C028160FB +:103DB00080930C028091080290910902892B89F06E +:103DC00000E010E00E94761CF801E85FFE4F80835F +:103DD0000F5F1F4F80910802909109020817190781 +:103DE00088F30E94761C803209F0A9CE80910C02E3 +:103DF00080FF5CC04091060150910701440F551FA0 +:103E000050930701409306016091080270910902E6 +:103E100061157105C9F0E8E0F1E09A01DB01AE0F30 +:103E2000BF1FF999FECF32BD21BD819180BDFA9AA5 +:103E3000F99A2F5F3F4FEA17FB0799F7460F571F75 +:103E400050930701409306018091C00085FFFCCF8D +:103E5000F092C6008091C00085FFFCCFBBCE0E94CF +:103E6000F31C88E080936000FFCF80E10E94C71CB4 +:103E70003BCE0E94761C0E94761C182F0E94761C56 +:103E8000112309F483C0113009F47CC086E00E943C +:103E9000C71C2ACE80910C02816080930C0226CF31 +:103EA000E0910401F09105010995F3CD809107019E +:103EB0008823880F880B8A2180930B02809106014A +:103EC00090910701880F991F909307018093060135 +:103ED0008091080280FF09C0809108029091090238 +:103EE00001969093090280930802F894F999FECF05 +:103EF0001127E0910601F0910701C8E0D1E080911F +:103F0000080290910902103091F40091570001705D +:103F10000130D9F303E000935700E8950091570072 +:103F200001700130D9F301E100935700E895099041 +:103F300019900091570001700130D9F301E000930E +:103F40005700E8951395103498F011270091570009 +:103F500001700130D9F305E000935700E895009116 +:103F6000570001700130D9F301E100935700E89543 +:103F70003296029709F0C7CF103011F00296E5CFC4 +:103F8000112462CF84E90E94C71CAECD8EE10E944D +:083F9000C71CAACDF894FFCF75 +:023F98008000A7 +:0400000300003800C1 +:00000001FF diff --git a/hardware/hexbright/bootloader/Makefile b/hardware/hexbright/bootloader/Makefile index 29dcbbf..56d024b 100755 --- a/hardware/hexbright/bootloader/Makefile +++ b/hardware/hexbright/bootloader/Makefile @@ -1,238 +1,238 @@ -# Makefile for ATmegaBOOT -# E.Lins, 18.7.2005 -# $Id$ -# -# Instructions -# -# To make bootloader .hex file: -# make diecimila -# make lilypad -# make ng -# etc... -# -# To burn bootloader .hex file: -# make diecimila_isp -# make lilypad_isp -# make ng_isp -# etc... - -# program name should not be changed... -PROGRAM = ATmegaBOOT_168 - -# enter the parameters for the avrdude isp tool -#ISPTOOL = stk500v2 -ISPTOOL = usbtiny -ISPPORT = usb -ISPSPEED = -b 115200 - -MCU_TARGET = atmega168 -LDSECTION = --section-start=.text=0x3800 - -# the efuse should really be 0xf8; since, however, only the lower -# three bits of that byte are used on the atmega168, avrdude gets -# confused if you specify 1's for the higher bits, see: -# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/ -# -# similarly, the lock bits should be 0xff instead of 0x3f (to -# unlock the bootloader section) and 0xcf instead of 0x0f (to -# lock it), but since the high two bits of the lock byte are -# unused, avrdude would get confused. - -ISPFUSES = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ --e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m -ISPFLASH = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ --U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m - -STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" -STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ --lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt -STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt - - -OBJ = $(PROGRAM).o -OPTIMIZE = -O2 - -DEFS = -LIBS = - -CC = avr-gcc - -# Override is only needed by avr-lib build system. - -override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) -override LDFLAGS = -Wl,$(LDSECTION) -#override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION) - -OBJCOPY = avr-objcopy -OBJDUMP = avr-objdump - -all: - -lilypad: TARGET = lilypad -lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' -lilypad: AVR_FREQ = 8000000L -lilypad: $(PROGRAM)_lilypad.hex - -lilypad_isp: lilypad -lilypad_isp: TARGET = lilypad -lilypad_isp: HFUSE = DD -lilypad_isp: LFUSE = E2 -lilypad_isp: EFUSE = 00 -lilypad_isp: isp - -lilypad_resonator: TARGET = lilypad_resonator -lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3' -lilypad_resonator: AVR_FREQ = 8000000L -lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex - -lilypad_resonator_isp: lilypad_resonator -lilypad_resonator_isp: TARGET = lilypad_resonator -lilypad_resonator_isp: HFUSE = DD -lilypad_resonator_isp: LFUSE = C6 -lilypad_resonator_isp: EFUSE = 00 -lilypad_resonator_isp: isp - -pro8: TARGET = pro_8MHz -pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' -pro8: AVR_FREQ = 8000000L -pro8: $(PROGRAM)_pro_8MHz.hex - -pro8_isp: pro8 -pro8_isp: TARGET = pro_8MHz -pro8_isp: HFUSE = DD -pro8_isp: LFUSE = C6 -pro8_isp: EFUSE = 00 -pro8_isp: isp - -pro16: TARGET = pro_16MHz -pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' -pro16: AVR_FREQ = 16000000L -pro16: $(PROGRAM)_pro_16MHz.hex - -pro16_isp: pro16 -pro16_isp: TARGET = pro_16MHz -pro16_isp: HFUSE = DD -pro16_isp: LFUSE = C6 -pro16_isp: EFUSE = 00 -pro16_isp: isp - -pro20: TARGET = pro_20mhz -pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' -pro20: AVR_FREQ = 20000000L -pro20: $(PROGRAM)_pro_20mhz.hex - -pro20_isp: pro20 -pro20_isp: TARGET = pro_20mhz -pro20_isp: HFUSE = DD -pro20_isp: LFUSE = C6 -pro20_isp: EFUSE = 00 -pro20_isp: isp - -diecimila: TARGET = diecimila -diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -diecimila: AVR_FREQ = 16000000L -diecimila: $(PROGRAM)_diecimila.hex - -diecimila_isp: diecimila -diecimila_isp: TARGET = diecimila -diecimila_isp: HFUSE = DD -diecimila_isp: LFUSE = FF -diecimila_isp: EFUSE = 00 -diecimila_isp: isp - -hexbright: TARGET = hexbright -hexbright: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' '-DWATCHDOG_MODS' -hexbright: AVR_FREQ = 8000000L -hexbright: $(PROGRAM)_hexbright.hex - -hexbright_isp: hexbright -hexbright_isp: TARGET = hexbright -hexbright_isp: MCU_TARGET = atmega168pa -hexbright_isp: HFUSE = DD -hexbright_isp: LFUSE = FF -hexbright_isp: EFUSE = 00 -hexbright_isp: isp - -ng: TARGET = ng -ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' -ng: AVR_FREQ = 16000000L -ng: $(PROGRAM)_ng.hex - -ng_isp: ng -ng_isp: TARGET = ng -ng_isp: HFUSE = DD -ng_isp: LFUSE = FF -ng_isp: EFUSE = 00 -ng_isp: isp - -atmega328: TARGET = atmega328 -atmega328: MCU_TARGET = atmega328p -atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -atmega328: AVR_FREQ = 16000000L -atmega328: LDSECTION = --section-start=.text=0x7800 -atmega328: $(PROGRAM)_atmega328.hex - -atmega328_isp: atmega328 -atmega328_isp: TARGET = atmega328 -atmega328_isp: MCU_TARGET = atmega328p -atmega328_isp: HFUSE = DA -atmega328_isp: LFUSE = FF -atmega328_isp: EFUSE = 05 -atmega328_isp: isp - -atmega328_pro8: TARGET = atmega328_pro_8MHz -atmega328_pro8: MCU_TARGET = atmega328p -atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -DDOUBLE_SPEED -atmega328_pro8: AVR_FREQ = 8000000L -atmega328_pro8: LDSECTION = --section-start=.text=0x7800 -atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex - -atmega328_pro8_isp: atmega328_pro8 -atmega328_pro8_isp: TARGET = atmega328_pro_8MHz -atmega328_pro8_isp: MCU_TARGET = atmega328p -atmega328_pro8_isp: HFUSE = DA -atmega328_pro8_isp: LFUSE = FF -atmega328_pro8_isp: EFUSE = 05 -atmega328_pro8_isp: isp - -mega: TARGET = atmega1280 -mega: MCU_TARGET = atmega1280 -mega: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' -DBAUD_RATE=57600 -mega: AVR_FREQ = 16000000L -mega: LDSECTION = --section-start=.text=0x1F000 -mega: $(PROGRAM)_atmega1280.hex - -mega_isp: mega -mega_isp: TARGET = atmega1280 -mega_isp: MCU_TARGET = atmega1280 -mega_isp: HFUSE = DA -mega_isp: LFUSE = FF -mega_isp: EFUSE = F5 -mega_isp: isp - -isp: $(TARGET) - $(ISPFUSES) - $(ISPFLASH) - -isp-stk500: $(PROGRAM)_$(TARGET).hex - $(STK500-1) - $(STK500-2) - -%.elf: $(OBJ) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) - -clean: - rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex - -%.lst: %.elf - $(OBJDUMP) -h -S $< > $@ - -%.hex: %.elf - $(OBJCOPY) -j .text -j .data -O ihex $< $@ - -%.srec: %.elf - $(OBJCOPY) -j .text -j .data -O srec $< $@ - -%.bin: %.elf - $(OBJCOPY) -j .text -j .data -O binary $< $@ - +# Makefile for ATmegaBOOT +# E.Lins, 18.7.2005 +# $Id$ +# +# Instructions +# +# To make bootloader .hex file: +# make diecimila +# make lilypad +# make ng +# etc... +# +# To burn bootloader .hex file: +# make diecimila_isp +# make lilypad_isp +# make ng_isp +# etc... + +# program name should not be changed... +PROGRAM = ATmegaBOOT_168 + +# enter the parameters for the avrdude isp tool +#ISPTOOL = stk500v2 +ISPTOOL = usbtiny +ISPPORT = usb +ISPSPEED = -b 115200 + +MCU_TARGET = atmega168 +LDSECTION = --section-start=.text=0x3800 + +# the efuse should really be 0xf8; since, however, only the lower +# three bits of that byte are used on the atmega168, avrdude gets +# confused if you specify 1's for the higher bits, see: +# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/ +# +# similarly, the lock bits should be 0xff instead of 0x3f (to +# unlock the bootloader section) and 0xcf instead of 0x0f (to +# lock it), but since the high two bits of the lock byte are +# unused, avrdude would get confused. + +ISPFUSES = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ +-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m +ISPFLASH = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ +-U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m + +STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" +STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ +-lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt +STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt + + +OBJ = $(PROGRAM).o +OPTIMIZE = -O2 + +DEFS = +LIBS = + +CC = avr-gcc + +# Override is only needed by avr-lib build system. + +override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) +override LDFLAGS = -Wl,$(LDSECTION) +#override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION) + +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump + +all: + +lilypad: TARGET = lilypad +lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' +lilypad: AVR_FREQ = 8000000L +lilypad: $(PROGRAM)_lilypad.hex + +lilypad_isp: lilypad +lilypad_isp: TARGET = lilypad +lilypad_isp: HFUSE = DD +lilypad_isp: LFUSE = E2 +lilypad_isp: EFUSE = 00 +lilypad_isp: isp + +lilypad_resonator: TARGET = lilypad_resonator +lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3' +lilypad_resonator: AVR_FREQ = 8000000L +lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex + +lilypad_resonator_isp: lilypad_resonator +lilypad_resonator_isp: TARGET = lilypad_resonator +lilypad_resonator_isp: HFUSE = DD +lilypad_resonator_isp: LFUSE = C6 +lilypad_resonator_isp: EFUSE = 00 +lilypad_resonator_isp: isp + +pro8: TARGET = pro_8MHz +pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' +pro8: AVR_FREQ = 8000000L +pro8: $(PROGRAM)_pro_8MHz.hex + +pro8_isp: pro8 +pro8_isp: TARGET = pro_8MHz +pro8_isp: HFUSE = DD +pro8_isp: LFUSE = C6 +pro8_isp: EFUSE = 00 +pro8_isp: isp + +pro16: TARGET = pro_16MHz +pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' +pro16: AVR_FREQ = 16000000L +pro16: $(PROGRAM)_pro_16MHz.hex + +pro16_isp: pro16 +pro16_isp: TARGET = pro_16MHz +pro16_isp: HFUSE = DD +pro16_isp: LFUSE = C6 +pro16_isp: EFUSE = 00 +pro16_isp: isp + +pro20: TARGET = pro_20mhz +pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' +pro20: AVR_FREQ = 20000000L +pro20: $(PROGRAM)_pro_20mhz.hex + +pro20_isp: pro20 +pro20_isp: TARGET = pro_20mhz +pro20_isp: HFUSE = DD +pro20_isp: LFUSE = C6 +pro20_isp: EFUSE = 00 +pro20_isp: isp + +diecimila: TARGET = diecimila +diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' +diecimila: AVR_FREQ = 16000000L +diecimila: $(PROGRAM)_diecimila.hex + +diecimila_isp: diecimila +diecimila_isp: TARGET = diecimila +diecimila_isp: HFUSE = DD +diecimila_isp: LFUSE = FF +diecimila_isp: EFUSE = 00 +diecimila_isp: isp + +hexbright: TARGET = hexbright +hexbright: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' '-DWATCHDOG_MODS' +hexbright: AVR_FREQ = 8000000L +hexbright: $(PROGRAM)_hexbright.hex + +hexbright_isp: hexbright +hexbright_isp: TARGET = hexbright +hexbright_isp: MCU_TARGET = atmega168pa +hexbright_isp: HFUSE = DD +hexbright_isp: LFUSE = FF +hexbright_isp: EFUSE = 00 +hexbright_isp: isp + +ng: TARGET = ng +ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' +ng: AVR_FREQ = 16000000L +ng: $(PROGRAM)_ng.hex + +ng_isp: ng +ng_isp: TARGET = ng +ng_isp: HFUSE = DD +ng_isp: LFUSE = FF +ng_isp: EFUSE = 00 +ng_isp: isp + +atmega328: TARGET = atmega328 +atmega328: MCU_TARGET = atmega328p +atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 +atmega328: AVR_FREQ = 16000000L +atmega328: LDSECTION = --section-start=.text=0x7800 +atmega328: $(PROGRAM)_atmega328.hex + +atmega328_isp: atmega328 +atmega328_isp: TARGET = atmega328 +atmega328_isp: MCU_TARGET = atmega328p +atmega328_isp: HFUSE = DA +atmega328_isp: LFUSE = FF +atmega328_isp: EFUSE = 05 +atmega328_isp: isp + +atmega328_pro8: TARGET = atmega328_pro_8MHz +atmega328_pro8: MCU_TARGET = atmega328p +atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -DDOUBLE_SPEED +atmega328_pro8: AVR_FREQ = 8000000L +atmega328_pro8: LDSECTION = --section-start=.text=0x7800 +atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex + +atmega328_pro8_isp: atmega328_pro8 +atmega328_pro8_isp: TARGET = atmega328_pro_8MHz +atmega328_pro8_isp: MCU_TARGET = atmega328p +atmega328_pro8_isp: HFUSE = DA +atmega328_pro8_isp: LFUSE = FF +atmega328_pro8_isp: EFUSE = 05 +atmega328_pro8_isp: isp + +mega: TARGET = atmega1280 +mega: MCU_TARGET = atmega1280 +mega: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' -DBAUD_RATE=57600 +mega: AVR_FREQ = 16000000L +mega: LDSECTION = --section-start=.text=0x1F000 +mega: $(PROGRAM)_atmega1280.hex + +mega_isp: mega +mega_isp: TARGET = atmega1280 +mega_isp: MCU_TARGET = atmega1280 +mega_isp: HFUSE = DA +mega_isp: LFUSE = FF +mega_isp: EFUSE = F5 +mega_isp: isp + +isp: $(TARGET) + $(ISPFUSES) + $(ISPFLASH) + +isp-stk500: $(PROGRAM)_$(TARGET).hex + $(STK500-1) + $(STK500-2) + +%.elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.srec: %.elf + $(OBJCOPY) -j .text -j .data -O srec $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + diff --git a/hexbright4.ino b/hexbright4/hexbright4.ino old mode 100755 new mode 100644 similarity index 98% rename from hexbright4.ino rename to hexbright4/hexbright4.ino index 1c78f6d..6eb0a83 --- a/hexbright4.ino +++ b/hexbright4/hexbright4.ino @@ -158,7 +158,7 @@ void loop() } // Check if the accelerometer wants to interrupt - byte tapped = 0, shaked = 0; + byte tapped = 0, shaken = 0; if (!digitalRead(DPIN_ACC_INT)) { Wire.beginTransmission(ACC_ADDRESS); @@ -172,10 +172,10 @@ void loop() lastAccTime = time; tapped = !!(tilt & 0x20); - shaked = !!(tilt & 0x80); + shaken = !!(tilt & 0x80); if (tapped) Serial.println("Tap!"); - if (shaked) Serial.println("Shake!"); + if (shaken) Serial.println("Shake!"); } } @@ -257,6 +257,8 @@ void loop() case MODE_KNOBBING: if (btnDown && !newBtnDown) // Button released newMode = MODE_KNOBBED; + if (btnDown && newBtnDown && shaken) + newMode = MODE_DAZZLING_PREVIEW; if (btnDown && newBtnDown && tapped) newMode = MODE_BLINKING_PREVIEW; break; @@ -385,4 +387,4 @@ float readAccelAngleXZ() readAccel(acc); return atan2(acc[0], acc[2]); } - + diff --git a/hexbright4_1/hexbright4_1.ino b/hexbright4_1/hexbright4_1.ino new file mode 100644 index 0000000..99fd244 --- /dev/null +++ b/hexbright4_1/hexbright4_1.ino @@ -0,0 +1,404 @@ +/* Test firmware for HexBright + +Notes: + Requires Arduino 1.0.1! + +*/ + +#include +#include + +// Settings +#define OVERTEMP 315 +// Constants +#define ACC_ADDRESS 0x4C +#define ACC_REG_XOUT 0 +#define ACC_REG_YOUT 1 +#define ACC_REG_ZOUT 2 +#define ACC_REG_TILT 3 +#define ACC_REG_INTS 6 +#define ACC_REG_MODE 7 +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PGOOD 7 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +#define DPIN_ACC_INT 3 +#define APIN_TEMP 0 +#define APIN_CHARGE 3 +// Interrupts +#define INT_SW 0 +#define INT_ACC 1 +// Modes +#define MODE_POWERUP 0 +#define MODE_OFF 1 +#define MODE_LOW 2 +#define MODE_MED 3 +#define MODE_HIGH 4 +#define MODE_KNOBBING 5 +#define MODE_KNOBBED 6 +#define MODE_BLINKING 7 +#define MODE_BLINKING_PREVIEW 8 +#define MODE_DAZZLING 9 +#define MODE_DAZZLING_PREVIEW 10 + +// State +byte mode = 0; +unsigned long btnTime = 0; +boolean btnDown = false; + + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or (more likely) the user is pressing the + // power button. We need to pull up the enable pin of + // the regulator very soon so we don't lose power. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); +// pinMode(DPIN_PWR, OUTPUT); +// digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + pinMode(DPIN_ACC_INT, INPUT); + pinMode(DPIN_PGOOD, INPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_ACC_INT, HIGH); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + // Configure accelerometer + byte config[] = { + ACC_REG_INTS, // First register (see next line) + 0xE4, // Interrupts: shakes, taps + 0x00, // Mode: not enabled yet + 0x00, // Sample rate: 120 Hz + 0x0F, // Tap threshold + 0x10 // Tap debounce samples + }; + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(config, sizeof(config)); + Wire.endTransmission(); + + // Enable accelerometer + byte enable[] = {ACC_REG_MODE, 0x01}; // Mode: active! + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(enable, sizeof(enable)); + Wire.endTransmission(); + + btnTime = millis(); + btnDown = digitalRead(DPIN_RLED_SW); + mode = MODE_OFF; + + Serial.println("Powered up!"); +} + +void loop() +{ + static unsigned long lastTime, lastTempTime, lastAccTime; + static float lastKnobAngle, knob; + static byte blink; + unsigned long time = millis(); + + // Blink the indicator LED now and then + digitalWrite(DPIN_GLED, (time&0x03FF)?LOW:HIGH); + + // Check the serial port + if (Serial.available()) + { + char c = Serial.read(); + switch (c) + { + case 's': + { + int temperature = analogRead(APIN_TEMP); + Serial.print("Temperature = "); + Serial.println(temperature); + + char accel[3]; + readAccel(accel); + Serial.print("Acceleration = "); + Serial.print(accel[0], DEC); + Serial.print(", "); + Serial.print(accel[1], DEC); + Serial.print(", "); + Serial.println(accel[2], DEC); + + byte pgood = digitalRead(DPIN_PGOOD); + Serial.print("LED driver power good = "); + Serial.println(pgood?"Yes":"No"); + } + break; + } + } + + // Check the temperature sensor + if (time-lastTempTime > 1000) + { + lastTempTime = time; + int temperature = analogRead(APIN_TEMP); + Serial.print("Temperature = "); + Serial.println(temperature); + if (temperature > OVERTEMP) + { + Serial.println("Overheat shutdown!"); + mode = MODE_OFF; + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + digitalWrite(DPIN_PWR, LOW); + } + } + + // Check if the accelerometer wants to interrupt + byte tapped = 0, shaken = 0; + if (!digitalRead(DPIN_ACC_INT)) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_TILT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 1); // This one stops. + byte tilt = Wire.read(); + + if (time-lastAccTime > 500) + { + lastAccTime = time; + + tapped = !!(tilt & 0x20); + shaken = !!(tilt & 0x80); + + if (tapped) Serial.println("Tap!"); + if (shaken) Serial.println("Shake!"); + } + } + + // Do whatever this mode does + switch (mode) + { + case MODE_KNOBBING: + { + if (time-lastTime < 100) break; + lastTime = time; + + float angle = readAccelAngleXZ(); + float change = angle - lastKnobAngle; + lastKnobAngle = angle; + if (change > PI) change -= 2.0*PI; + if (change < -PI) change += 2.0*PI; + knob += -change * 40.0; + if (knob < 0) knob = 0; + if (knob > 255) knob = 255; + + // Make apparent brightness changes linear by squaring the + // value and dividing back down into range. This gives us + // a gamma correction of 2.0, which is close enough. + byte bright = (long)(knob * knob) >> 8; + // Avoid ever appearing off in this mode! + if (bright < 8) bright = 8; + analogWrite(DPIN_DRV_EN, bright); + + Serial.print("Ang = "); + Serial.print(angle); + Serial.print("\tChange = "); + Serial.print(change); + Serial.print("\tKnob = "); + Serial.print(knob); + Serial.print("\tBright = "); + Serial.println(bright); + } + break; + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + if (time-lastTime < 250) break; + lastTime = time; + + blink = !blink; + digitalWrite(DPIN_DRV_EN, blink); + break; + case MODE_DAZZLING: + case MODE_DAZZLING_PREVIEW: + if (time-lastTime < 10) break; + lastTime = time; + + digitalWrite(DPIN_DRV_EN, random(4)<1); + break; + } + + // Check for mode changes + byte newMode = mode; + byte newBtnDown = digitalRead(DPIN_RLED_SW); + switch (mode) + { + case MODE_OFF: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_LOW; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_LOW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_MED; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_MED: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_HIGH; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_HIGH: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_KNOBBING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_KNOBBED; + if (btnDown && newBtnDown && shaken) + newMode = MODE_DAZZLING_PREVIEW; + if (btnDown && newBtnDown && tapped) + newMode = MODE_BLINKING_PREVIEW; + break; + case MODE_KNOBBED: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_KNOBBING; + break; + case MODE_BLINKING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_BLINKING_PREVIEW; + break; + case MODE_BLINKING_PREVIEW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_BLINKING; + if (btnDown && newBtnDown && tapped) + newMode = MODE_DAZZLING_PREVIEW; + break; + case MODE_DAZZLING: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>500) // Held + newMode = MODE_DAZZLING_PREVIEW; + break; + case MODE_DAZZLING_PREVIEW: + if (btnDown && !newBtnDown) // Button released + newMode = MODE_DAZZLING; + if (btnDown && newBtnDown && tapped) + newMode = MODE_BLINKING_PREVIEW; + break; + } + + // Do the mode transitions + if (newMode != mode) + { + switch (newMode) + { + case MODE_OFF: + Serial.println("Mode = off"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + break; + case MODE_LOW: + Serial.println("Mode = low"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 64); + break; + case MODE_MED: + Serial.println("Mode = medium"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW ); + analogWrite(DPIN_DRV_EN, 127); + break; + case MODE_HIGH: + Serial.println("Mode = high"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH ); + analogWrite(DPIN_DRV_EN, 127); + break; + case MODE_KNOBBING: + Serial.println("Mode = knobbing"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + lastKnobAngle = readAccelAngleXZ(); + knob = (mode==MODE_OFF) ? 0 : 255; + break; + case MODE_KNOBBED: + Serial.println("Mode = knobbed"); + break; + case MODE_BLINKING: + case MODE_BLINKING_PREVIEW: + Serial.println("Mode = blinking"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + break; + case MODE_DAZZLING: + case MODE_DAZZLING_PREVIEW: + Serial.println("Mode = dazzling"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + } + + mode = newMode; + } + + // Remember button state so we can detect transitions + if (newBtnDown != btnDown) + { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} + +void readAccel(char *acc) +{ + while (1) + { + Wire.beginTransmission(ACC_ADDRESS); + Wire.write(ACC_REG_XOUT); + Wire.endTransmission(false); // End, but do not stop! + Wire.requestFrom(ACC_ADDRESS, 3); // This one stops. + + for (int i = 0; i < 3; i++) + { + if (!Wire.available()) + continue; + acc[i] = Wire.read(); + if (acc[i] & 0x40) // Indicates failed read; redo! + continue; + if (acc[i] & 0x20) // Sign-extend + acc[i] |= 0xC0; + } + break; + } +} + +float readAccelAngleXZ() +{ + char acc[3]; + readAccel(acc); + return atan2(acc[0], acc[2]); +} + diff --git a/hexbright_demo_dazzle.ino b/hexbright_demo_dazzle/hexbright_demo_dazzle.ino old mode 100755 new mode 100644 similarity index 99% rename from hexbright_demo_dazzle.ino rename to hexbright_demo_dazzle/hexbright_demo_dazzle.ino index 5b193fd..2b95749 --- a/hexbright_demo_dazzle.ino +++ b/hexbright_demo_dazzle/hexbright_demo_dazzle.ino @@ -46,4 +46,4 @@ void loop() else digitalWrite(DPIN_DRV_EN, LOW); } - + diff --git a/hexbright_demo_fades.ino b/hexbright_demo_fades/hexbright_demo_fades.ino old mode 100755 new mode 100644 similarity index 99% rename from hexbright_demo_fades.ino rename to hexbright_demo_fades/hexbright_demo_fades.ino index c05da9e..b9e4051 --- a/hexbright_demo_fades.ino +++ b/hexbright_demo_fades/hexbright_demo_fades.ino @@ -93,4 +93,4 @@ void loop() delay(50); } } - + diff --git a/hexbright_demo_momentary.ino b/hexbright_demo_momentary/hexbright_demo_momentary.ino old mode 100755 new mode 100644 similarity index 99% rename from hexbright_demo_momentary.ino rename to hexbright_demo_momentary/hexbright_demo_momentary.ino index 268bd46..6185d3c --- a/hexbright_demo_momentary.ino +++ b/hexbright_demo_momentary/hexbright_demo_momentary.ino @@ -38,4 +38,4 @@ void loop() else digitalWrite(DPIN_DRV_EN, LOW); } - + diff --git a/hexbright_demo_morse.ino b/hexbright_demo_morse/hexbright_demo_morse.ino old mode 100755 new mode 100644 similarity index 99% rename from hexbright_demo_morse.ino rename to hexbright_demo_morse/hexbright_demo_morse.ino index 86aca40..9695501 --- a/hexbright_demo_morse.ino +++ b/hexbright_demo_morse/hexbright_demo_morse.ino @@ -134,4 +134,4 @@ void loop() // This won't work on USB power. digitalWrite(DPIN_PWR, LOW); } - + diff --git a/hexbright_demo_taps.ino b/hexbright_demo_taps/hexbright_demo_taps.ino similarity index 99% rename from hexbright_demo_taps.ino rename to hexbright_demo_taps/hexbright_demo_taps.ino index 272e64e..479a8ac 100644 --- a/hexbright_demo_taps.ino +++ b/hexbright_demo_taps/hexbright_demo_taps.ino @@ -171,4 +171,4 @@ void loop() break; } } - + diff --git a/hexbright_factory.ino b/hexbright_factory/hexbright_factory.ino old mode 100755 new mode 100644 similarity index 99% rename from hexbright_factory.ino rename to hexbright_factory/hexbright_factory.ino index 8a6a8db..b1c6b51 --- a/hexbright_factory.ino +++ b/hexbright_factory/hexbright_factory.ino @@ -203,4 +203,4 @@ void loop() delay(50); } } - + diff --git a/libraries/readme.txt b/libraries/readme.txt new file mode 100644 index 0000000..a8f1390 --- /dev/null +++ b/libraries/readme.txt @@ -0,0 +1 @@ +For information on installing libraries, see: http://arduino.cc/en/Guide/Libraries From 36d0336a428e86ded7d48e908e24bc693011dd6f Mon Sep 17 00:00:00 2001 From: Mark Denkert Date: Tue, 22 Jan 2013 23:37:46 -0600 Subject: [PATCH 2/3] Added instructions for new mode and transistion. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0dd51e7..8947c2b 100755 --- a/README.md +++ b/README.md @@ -7,14 +7,14 @@ This is the software that ships with the Hexbright Flex. Button presses cycle through off, low, medium, and high modes. Hold down the button while off for blinky mode. -hexbright4 +hexbright4.1 --------------------- Fancier than the factory program, but designed for everyday usability. Button -presses cycle through off, low and high modes. Hold the light horizontally, +presses cycle through off, low, medium and high modes. Hold the light horizontally, hold the button down, and rotate about the long axis clockwise to increase brightness, and counter-clockwise to decrease brightness- the brightness sticks when you let go of the button. While holding the button down, give the light a -firm tap to change to blinky mode, and another to change to dazzle mode. +firm tap to change to blinky mode, and another to change to dazzle mode, or shake it! hexbright_demo_morse -------------------- From 5f147d7c5a314385eef7f7bb8622b5dd5a378b34 Mon Sep 17 00:00:00 2001 From: Mark Denkert Date: Wed, 23 Jan 2013 21:25:27 -0600 Subject: [PATCH 3/3] Added dazzle instead of blink Replaced blink with dazzle in the factory firmware. --- .../hexbright_factory_dazzle.ino | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 hexbright_factory_dazzle/hexbright_factory_dazzle.ino diff --git a/hexbright_factory_dazzle/hexbright_factory_dazzle.ino b/hexbright_factory_dazzle/hexbright_factory_dazzle.ino new file mode 100644 index 0000000..c21aabe --- /dev/null +++ b/hexbright_factory_dazzle/hexbright_factory_dazzle.ino @@ -0,0 +1,208 @@ +/* + + Factory firmware for HexBright FLEX + v2.4 Dec 6, 2012 + +*/ + +#include +#include + +// Settings +#define OVERTEMP 340 +// Pin assignments +#define DPIN_RLED_SW 2 +#define DPIN_GLED 5 +#define DPIN_PWR 8 +#define DPIN_DRV_MODE 9 +#define DPIN_DRV_EN 10 +#define APIN_TEMP 0 +#define APIN_CHARGE 3 +// Modes +#define MODE_OFF 0 +#define MODE_LOW 1 +#define MODE_MED 2 +#define MODE_HIGH 3 +#define MODE_DAZZLE 4 + +// State +byte mode = 0; +unsigned long btnTime = 0; +boolean btnDown = false; + + +void setup() +{ + // We just powered on! That means either we got plugged + // into USB, or the user is pressing the power button. + pinMode(DPIN_PWR, INPUT); + digitalWrite(DPIN_PWR, LOW); + + // Initialize GPIO + pinMode(DPIN_RLED_SW, INPUT); + pinMode(DPIN_GLED, OUTPUT); + pinMode(DPIN_DRV_MODE, OUTPUT); + pinMode(DPIN_DRV_EN, OUTPUT); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + + // Initialize serial busses + Serial.begin(9600); + Wire.begin(); + + btnTime = millis(); + btnDown = digitalRead(DPIN_RLED_SW); + mode = MODE_OFF; + + Serial.println("Powered up!"); +} + +void loop() +{ + static unsigned long lastTempTime, lastTime; + unsigned long time = millis(); + + // Check the state of the charge controller + int chargeState = analogRead(APIN_CHARGE); + if (chargeState < 128) // Low - charging + { + digitalWrite(DPIN_GLED, (time&0x0100)?LOW:HIGH); + } + else if (chargeState > 768) // High - charged + { + digitalWrite(DPIN_GLED, HIGH); + } + else // Hi-Z - shutdown + { + digitalWrite(DPIN_GLED, LOW); + } + + // Check the temperature sensor + if (time-lastTempTime > 1000) + { + lastTempTime = time; + int temperature = analogRead(APIN_TEMP); + Serial.print("Temp: "); + Serial.println(temperature); + if (temperature > OVERTEMP && mode != MODE_OFF) + { + Serial.println("Overheating!"); + + for (int i = 0; i < 6; i++) + { + digitalWrite(DPIN_DRV_MODE, LOW); + delay(100); + digitalWrite(DPIN_DRV_MODE, HIGH); + delay(100); + } + digitalWrite(DPIN_DRV_MODE, LOW); + + mode = MODE_LOW; + } + } + + // Do whatever this mode does + switch (mode) + { + case MODE_DAZZLE: + if (time-lastTime < 10) break; + lastTime = time; + + digitalWrite(DPIN_DRV_EN, random(4)<1); + break; + } + + // Periodically pull down the button's pin, since + // in certain hardware revisions it can float. + pinMode(DPIN_RLED_SW, OUTPUT); + pinMode(DPIN_RLED_SW, INPUT); + + // Check for mode changes + byte newMode = mode; + byte newBtnDown = digitalRead(DPIN_RLED_SW); + switch (mode) + { + case MODE_OFF: + if (btnDown && !newBtnDown && (time-btnTime)>20) + newMode = MODE_LOW; + if (btnDown && newBtnDown && (time-btnTime)>250) + newMode = MODE_DAZZLE; + break; + case MODE_LOW: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_MED; + if (btnDown && newBtnDown && (time-btnTime)>250) + newMode = MODE_DAZZLE; + break; + case MODE_MED: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_HIGH; + if (btnDown && newBtnDown && (time-btnTime)>250) + newMode = MODE_DAZZLE; + break; + case MODE_HIGH: + if (btnDown && !newBtnDown && (time-btnTime)>50) + newMode = MODE_OFF; + if (btnDown && newBtnDown && (time-btnTime)>250) + newMode = MODE_DAZZLE; + break; + case MODE_DAZZLE: + // This mode exists just to ignore this button release. + if (btnDown && !newBtnDown) + newMode = MODE_OFF; + break; + } + + // Do the mode transitions + if (newMode != mode) + { + switch (newMode) + { + case MODE_OFF: + Serial.println("Mode = off"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, LOW); + digitalWrite(DPIN_DRV_MODE, LOW); + digitalWrite(DPIN_DRV_EN, LOW); + break; + case MODE_LOW: + Serial.println("Mode = low"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 64); + break; + case MODE_MED: + Serial.println("Mode = medium"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, LOW); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_HIGH: + Serial.println("Mode = high"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + analogWrite(DPIN_DRV_EN, 255); + break; + case MODE_DAZZLE: + Serial.println("Mode = dazzling"); + pinMode(DPIN_PWR, OUTPUT); + digitalWrite(DPIN_PWR, HIGH); + digitalWrite(DPIN_DRV_MODE, HIGH); + break; + } + + mode = newMode; + } + + // Remember button state so we can detect transitions + if (newBtnDown != btnDown) + { + btnTime = time; + btnDown = newBtnDown; + delay(50); + } +} +