From 81c6167ed0fce5eea03a20f76e73e5ef5d769fa3 Mon Sep 17 00:00:00 2001 From: Arnav Gupta Date: Sat, 20 Sep 2014 03:34:09 +0530 Subject: [PATCH] add mega and due compatible ArduinoISP sketches The example present does not work with either Arduino Mega 2560 or Arduino Due Tested this https://raw.githubusercontent.com/rsbohn/ArduinoISP/master/ArduinoISP/ArduinoISP.ino to work perfectly to turn Mega into a stk500v1 programmer And tested this https://raw.githubusercontent.com/PeterVH/ArduinoISP/due/ArduinoISP/ArduinoISP.ino to be compatible with Due to turn it into a stk500v1 programmer. (using the native port) Signed-off-by: Arnav Gupta --- .../examples/11.ArduinoISP/DueISP/DueISP.ino | 678 ++++++++++++++++++ .../11.ArduinoISP/MegaISP/MegaISP.ino | 541 ++++++++++++++ .../UnoISP/UnoISP.ino} | 0 3 files changed, 1219 insertions(+) create mode 100644 build/shared/examples/11.ArduinoISP/DueISP/DueISP.ino create mode 100644 build/shared/examples/11.ArduinoISP/MegaISP/MegaISP.ino rename build/shared/examples/{ArduinoISP/ArduinoISP.ino => 11.ArduinoISP/UnoISP/UnoISP.ino} (100%) diff --git a/build/shared/examples/11.ArduinoISP/DueISP/DueISP.ino b/build/shared/examples/11.ArduinoISP/DueISP/DueISP.ino new file mode 100644 index 00000000000..b2253804014 --- /dev/null +++ b/build/shared/examples/11.ArduinoISP/DueISP/DueISP.ino @@ -0,0 +1,678 @@ +// ArduinoISP version 04m3 +// Copyright (c) 2008-2011 Randall Bohn +// If you require a license, see +// http://www.opensource.org/licenses/bsd-license.php +// +// This sketch turns the Arduino into a AVRISP +// using the following arduino pins: +// If using with Arduino Due, connect PC to Native port +// +// pin name: not-mega: mega(1280 and 2560) +// slave reset: 10: 53 +// MOSI: 11: 51 +// MISO: 12: 50 +// SCK: 13: (std LED) 52 +// +// Put an LED (with resistor) on the following pins: +// 9: Heartbeat - shows the programmer is running +// 8: Error - Lights up if something goes wrong (use red if that makes sense) +// 7: Programming - In communication with the slave +// +// 23 July 2011 Randall Bohn +// -Address Arduino issue 509 :: Portability of ArduinoISP +// http://code.google.com/p/arduino/issues/detail?id=509 +// +// October 2010 by Randall Bohn +// - Write to EEPROM > 256 bytes +// - Better use of LEDs: +// -- Flash LED_PMODE on each flash commit +// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress) +// -- Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync. +// - Use pins_arduino.h (should also work on Arduino Mega) +// +// October 2009 by David A. Mellis +// - Added support for the read signature command +// +// February 2009 by Randall Bohn +// - Added support for writing to EEPROM (what took so long?) +// Windows users should consider WinAVR's avrdude instead of the +// avrdude included with Arduino software. +// +// January 2008 by Randall Bohn +// - Thanks to Amplificar for helping me with the STK500 protocol +// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader +// - The SPI functions herein were developed for the AVR910_ARD programmer +// - More information at http://code.google.com/p/mega-isp + + +// versions need to be above Atmel programmer to avoid fw update attempts +#define HWVER 2 +#define SWMAJ 1 +#define SWMIN 18 + + +#define BAUDRATE 19200 +//#define BAUDRATE 38400 +//#define BAUDRATE 115200 + +// create clock on digital 9 using pwm (timer1), LED_HB must move +//#define LADYADA_CLOCK + +#define RESETDELAY 0 + +// uncomment if you want to have debug traces +// (needs a separate uart so works only on Sanguino, Leonardo, Due...) +//#define TRACES + +// following settings have different defaults on SAM vs. AVR + +#ifdef __SAM3X8E__ + +// Select uart to use for programming and debugging: +#define SERIAL_PRG SerialUSB +#define SERIAL_DBG Serial + +// comment USE_HARDWARE_SPI to use bitbang spi +// use bitbang to make it work with very slow attiny2313 +// #define USE_HARDWARE_SPI + +#else + +// Select uart to use for programming and debugging: +#define SERIAL_PRG Serial +#define SERIAL_DBG Serial1 + +// comment USE_HARDWARE_SPI to use bitbang spi +// use bitbang to make it work with very slow attiny2313 +#define USE_HARDWARE_SPI + +#endif + +/////////////////////////////////////////////// +// ideally won't need to edit below here // +/////////////////////////////////////////////// + + + +#ifdef USE_HARDWARE_SPI +#include "SPI.h" + +#ifdef __AVR__ // this would better go into SPI lib +#define SPI_CLOCK_DIV_MAX SPI_CLOCK_DIV128 +#else +#define SPI_CLOCK_DIV_MAX 255 +#endif + +#endif + +#include "pins_arduino.h" +#define PIN_RESET SS +#define PIN_SCK SCK +#define PIN_MOSI MOSI +#define PIN_MISO MISO + +#define LED_HB 9 +#define LED_ERR 8 +#define LED_PMODE 7 +#define PROG_FLICKER true + + + +#ifdef LADYADA_CLOCK +#ifndef __AVR__ +#error "Not yet implemented for non AVR's." +#endif +// needs timer1 PWM +#define CLOCK_PIN 9 +#undef LED_HB +#define LED_HB 6 +#endif + +#ifdef TRACES +#define TRACE_BEGIN(baud) SERIAL_DBG.begin(baud) +#define TRACE(x) SERIAL_DBG.print(x) +#define TRACELN(x) SERIAL_DBG.println(x) +#define TRACE2(x, format) SERIAL_DBG.print(x, format) +#define TRACE2LN(x, format) SERIAL_DBG.println(x, format) +#else +#define TRACE_BEGIN(baud) +#define TRACE(x) +#define TRACELN(x) +#define TRACE2(x, format) +#define TRACE2LN(x, format) +#endif + + +// STK Definitions +#define STK_OK 0x10 +#define STK_FAILED 0x11 +#define STK_UNKNOWN 0x12 +#define STK_INSYNC 0x14 +#define STK_NOSYNC 0x15 +#define CRC_EOP 0x20 //ok it is a space... + +void pulse(uint8_t pin, uint8_t times); + +#ifndef USE_HARDWARE_SPI + +class BitBangedSPI { +public: + + void begin() { + pinMode(PIN_MISO, INPUT); + pinMode(PIN_RESET, OUTPUT); + pinMode(PIN_SCK, OUTPUT); + pinMode(PIN_MOSI, OUTPUT); + } + + void end() {} + + uint8_t transfer (uint8_t b) { + for (unsigned int i = 0; i < 8; ++i) { + digitalWrite(PIN_MOSI, b & 0x80); + digitalWrite(PIN_SCK, HIGH); + b = (b << 1) | digitalRead(PIN_MISO); + digitalWrite(PIN_SCK, LOW); // slow pulse + } + return b; + } +}; + +static BitBangedSPI SPI; + +#endif + +void setup(void) { + SERIAL_PRG.begin(BAUDRATE); + +#ifdef USE_HARDWARE_SPI + SPI.setDataMode(0); + SPI.setBitOrder(MSBFIRST); + // Clock Div can be 2,4,8,16,32,64, or 128 + SPI.setClockDivider(SPI_CLOCK_DIV_MAX); +#endif + + pinMode(LED_PMODE, OUTPUT); + pulse(LED_PMODE, 2); + pinMode(LED_ERR, OUTPUT); + pulse(LED_ERR, 2); + pinMode(LED_HB, OUTPUT); + pulse(LED_HB, 2); + +#ifdef LADYADA_CLOCK + // setup high freq PWM (timer 1) + pinMode(CLOCK_PIN, OUTPUT); + uint8_t sreg = SREG; + cli(); // disable interrupts to access TCNT1, OCR1A,B + // 50% duty cycle -> 8 MHz + OCR1A = 0; + ICR1 = 1; + // OC1A output, fast PWM + TCCR1A = _BV(WGM11) | _BV(COM1A1); + TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // no clock prescale + SREG = sreg; // restore interrupts +#endif + + TRACE_BEGIN(115200); + TRACELN("*** setup ***"); +} + +uint8_t error=0; +uint8_t pmode=0; +uint8_t buff[256]; // global block storage +// address for reading and writing, set by 'U' command +uint16_t here; + +// get multi-byte Big Endian values +#define beget16(addr) ((uint16_t)*(addr) << 8 | (uint16_t)*((addr)+1) ) +#define beget32(a) ((uint32_t)beget16(a) << 16 | (uint32_t)beget16((a)+2) ) + +struct param { + uint8_t devicecode; + uint8_t revision; + uint8_t progtype; + uint8_t parmode; + uint8_t polling; + uint8_t selftimed; + uint8_t lockbytes; + uint8_t fusebytes; + uint8_t flashpoll; + //uint8_t ignored; + uint16_t eeprompoll; + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; +} param; + + +// this provides a heartbeat, so you can tell the software is running. +uint8_t hbval=128; +int8_t hbdelta=8; +unsigned long hbprev=0; +void heartbeat(void) { + if (hbval > 192 || hbval < 32) hbdelta = -hbdelta; + hbval += hbdelta; + while (millis()-hbprev < 40); // wait a bit if came back too soon + analogWrite(LED_HB, hbval); + hbprev=millis(); +} + + +void loop(void) { + // is pmode active? + if (pmode) digitalWrite(LED_PMODE, HIGH); + else digitalWrite(LED_PMODE, LOW); + + // is there an error? + if (error) digitalWrite(LED_ERR, HIGH); + else digitalWrite(LED_ERR, LOW); + + // light the heartbeat LED + heartbeat(); + + if (SERIAL_PRG.available()) { + avrisp(); + } +} + + +uint8_t getch(void) { + while(!SERIAL_PRG.available()); + return SERIAL_PRG.read(); +} +void fill(unsigned n) { + for (unsigned x = 0; x < n; x++) { + buff[x] = getch(); + } +} + +#define PTIME 30 +void pulse(uint8_t pin, uint8_t times) { + do { + digitalWrite(pin, HIGH); + delay(PTIME); + digitalWrite(pin, LOW); + delay(PTIME); + } + while (times--); +} + +void prog_lamp(uint8_t state) { + if (PROG_FLICKER) + digitalWrite(LED_PMODE, state); +} + +uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + SPI.transfer(a); + SPI.transfer(b); + SPI.transfer(c); + return SPI.transfer(d); +} + + +void empty_reply(void) { + if (CRC_EOP == getch()) { + SERIAL_PRG.print((char)STK_INSYNC); + SERIAL_PRG.print((char)STK_OK); + } + else { + error++; + SERIAL_PRG.print((char)STK_NOSYNC); + } +} + +void breply(uint8_t b) { + if (CRC_EOP == getch()) { + SERIAL_PRG.print((char)STK_INSYNC); + SERIAL_PRG.print((char)b); + SERIAL_PRG.print((char)STK_OK); + } + else { + error++; + SERIAL_PRG.print((char)STK_NOSYNC); + } +} + +void get_version(uint8_t c) { + switch(c) { + case 0x80: + breply(HWVER); + break; + case 0x81: + breply(SWMAJ); + break; + case 0x82: + breply(SWMIN); + break; + case 0x93: + breply('S'); // serial programmer + break; + default: + breply(0); + } +} + +void set_parameters(void) { + // call this after reading paramter packet into buff[] + param.devicecode = buff[0]; + param.revision = buff[1]; + param.progtype = buff[2]; + param.parmode = buff[3]; + param.polling = buff[4]; + param.selftimed = buff[5]; + param.lockbytes = buff[6]; + param.fusebytes = buff[7]; + param.flashpoll = buff[8]; + // ignore buff[9] (= buff[8]) + // following are 16 bits (big endian) + param.eeprompoll = beget16(&buff[10]); + param.pagesize = beget16(&buff[12]); + param.eepromsize = beget16(&buff[14]); + // 32 bits flashsize (big endian) + param.flashsize = beget32(&buff[16]); +} + +void start_pmode(void) { + pmode = 1; + + // reset target before driving SCK or MOSI + digitalWrite(PIN_RESET, LOW); + digitalWrite(PIN_SCK, LOW); + digitalWrite(PIN_MOSI, HIGH); + + pinMode(PIN_MISO, INPUT); + pinMode(PIN_RESET, OUTPUT); // PIN_RESET not always SS: Leonardo, Due... + SPI.begin(); // now SS, MOSI and SCK are output + + // See datasheets: "SERIAL_PRG Programming Algorithm": + delay(5); // choosen arbitrarilly + // pulse RESET high after SCK is low + digitalWrite(PIN_RESET, HIGH); + delay(1); // must be minimum 2 CPU clock cycles + digitalWrite(PIN_RESET, LOW); + delay(50); // minimum 20 ms + if (RESETDELAY) delay(RESETDELAY); + spi_transaction(0xAC, 0x53, 0x00, 0x00); +} + +void end_pmode(void) { + SPI.end(); + pinMode(PIN_MOSI, INPUT); + pinMode(PIN_SCK, INPUT); + pinMode(PIN_RESET, INPUT); + pmode = 0; +} + +void universal(void) { + uint8_t ch; + fill(4); + ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); + breply(ch); +} + +#define flash_write_cmd(hilo, addr, data) \ + spi_transaction(0x40|((hilo)<<3), (addr)>>8 & 0xFF, (addr) & 0xFF, (data)) + +#define flash_read_cmd(hilo, addr) \ + spi_transaction(0x20|((hilo)<<3), (addr)>>8 & 0xFF, (addr) & 0xFF, 0) + + +void commit(uint16_t addr) { + if (PROG_FLICKER) prog_lamp(LOW); + spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); + if (PROG_FLICKER) { + delay(PTIME); + prog_lamp(HIGH); + } +} + +uint16_t current_page(uint16_t addr) { + if (param.pagesize == 32) return here & 0xFFF0; + if (param.pagesize == 64) return here & 0xFFE0; + if (param.pagesize == 128) return here & 0xFFC0; + if (param.pagesize == 256) return here & 0xFF80; + return here; +} + + +void write_flash(unsigned length) { + fill(length); + if (CRC_EOP == getch()) { + SERIAL_PRG.print((char) STK_INSYNC); + SERIAL_PRG.print((char) write_flash_pages(length)); + } + else { + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + } +} + +uint8_t write_flash_pages(unsigned length) { + unsigned x = 0; + uint16_t page = current_page(here); + while (x < length) { + if (page != current_page(here)) { + commit(page); + page = current_page(here); + } + flash_write_cmd(LOW, here, buff[x++]); + flash_write_cmd(HIGH, here, buff[x++]); + here++; + } + + commit(page); + + return STK_OK; +} + +#define EECHUNK (32) +uint8_t write_eeprom(unsigned length) { + // here is a word address, get the byte address + uint16_t start = here << 1; + if (length > param.eepromsize) { + error++; + return STK_FAILED; + } + while (length > EECHUNK) { + write_eeprom_chunk(start, EECHUNK); + start += EECHUNK; + length -= EECHUNK; + } + write_eeprom_chunk(start, length); + return STK_OK; +} +// write (length) bytes, (start) is a byte address +uint8_t write_eeprom_chunk(uint16_t addr, unsigned length) { + // this writes byte-by-byte, + // page writing may be faster (4 bytes at a time) + fill(length); + prog_lamp(LOW); + for (unsigned x = 0; x < length; x++, addr++) { + spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]); + delay(45); + } + prog_lamp(HIGH); + return STK_OK; +} + +void program_page(void) { + char result = (char) STK_FAILED; + unsigned length = getch()<<8; + length |= getch(); + char memtype = getch(); + // flash memory @here, (length) bytes + if (memtype == 'F') { + write_flash(length); + return; + } + if (memtype == 'E') { + result = (char)write_eeprom(length); + if (CRC_EOP == getch()) { + SERIAL_PRG.print((char) STK_INSYNC); + SERIAL_PRG.print(result); + } + else { + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + } + return; + } + SERIAL_PRG.print((char)STK_FAILED); +} + +char flash_read_page(unsigned length) { + for (unsigned x = 0; x < length; x+=2) { + char ch; + ch = flash_read_cmd(LOW, here); + SERIAL_PRG.print(ch); + ch = flash_read_cmd(HIGH, here); + SERIAL_PRG.print(ch); + here++; + } + return STK_OK; +} + +char eeprom_read_page(unsigned length) { + // here again we have a word address + uint16_t addr = here << 1; + for (unsigned x = 0; x < length; x++, addr++) { + uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); + SERIAL_PRG.print((char) ee); + } + return STK_OK; +} + +void read_page(void) { + char result = (char)STK_FAILED; + unsigned length = getch() << 8; + length |= getch(); + char memtype = getch(); + if (CRC_EOP != getch()) { + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + return; + } + SERIAL_PRG.print((char) STK_INSYNC); + if (memtype == 'F') result = flash_read_page(length); + if (memtype == 'E') result = eeprom_read_page(length); + SERIAL_PRG.print(result); +} + +void read_signature(void) { + if (CRC_EOP != getch()) { + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + return; + } + SERIAL_PRG.print((char) STK_INSYNC); + char ch; + ch = spi_transaction(0x30, 0x00, 0x00, 0x00); + SERIAL_PRG.print(ch); + ch = spi_transaction(0x30, 0x00, 0x01, 0x00); + SERIAL_PRG.print(ch); + ch = spi_transaction(0x30, 0x00, 0x02, 0x00); + SERIAL_PRG.print(ch); + SERIAL_PRG.print((char) STK_OK); +} +////////////////////////////////////////// +////////////////////////////////////////// + + + +//////////////////////////////////// +//////////////////////////////////// +void avrisp(void) { + uint8_t data, low, high; + uint8_t ch = getch(); + TRACE("> "); + TRACELN((char) ch); + switch (ch) { + case '0': // signon + error = 0; + empty_reply(); + break; + case '1': + if (getch() == CRC_EOP) { + SERIAL_PRG.print((char) STK_INSYNC); + SERIAL_PRG.print("AVR ISP"); + SERIAL_PRG.print((char) STK_OK); + } else { + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + } + break; + case 'A': + get_version(getch()); + break; + case 'B': + fill(20); + set_parameters(); + empty_reply(); + break; + case 'E': // extended parameters - ignore for now + fill(5); + empty_reply(); + break; + + case 'P': + if (pmode) { + pulse(LED_ERR, 3); + } else { + start_pmode(); + } + empty_reply(); + break; + case 'U': // set address (word) + here = getch(); + here |= getch()<<8; + empty_reply(); + break; + + case 0x60: //STK_PROG_FLASH + low = getch(); + high = getch(); + empty_reply(); + break; + case 0x61: //STK_PROG_DATA + data = getch(); + empty_reply(); + break; + + case 0x64: //STK_PROG_PAGE + program_page(); + break; + + case 0x74: //STK_READ_PAGE 't' + read_page(); + break; + + case 'V': //0x56 + universal(); + break; + case 'Q': //0x51 + error=0; + end_pmode(); + empty_reply(); + break; + + case 0x75: //STK_READ_SIGN 'u' + read_signature(); + break; + + // expecting a command, not CRC_EOP + // this is how we can get back in sync + case CRC_EOP: + error++; + SERIAL_PRG.print((char) STK_NOSYNC); + break; + + // anything else we will return STK_UNKNOWN + default: + error++; + if (CRC_EOP == getch()) + SERIAL_PRG.print((char)STK_UNKNOWN); + else + SERIAL_PRG.print((char)STK_NOSYNC); + } +} + diff --git a/build/shared/examples/11.ArduinoISP/MegaISP/MegaISP.ino b/build/shared/examples/11.ArduinoISP/MegaISP/MegaISP.ino new file mode 100644 index 00000000000..a807bfa8865 --- /dev/null +++ b/build/shared/examples/11.ArduinoISP/MegaISP/MegaISP.ino @@ -0,0 +1,541 @@ +// ArduinoISP version 04m3 +// Copyright (c) 2008-2011 Randall Bohn +// If you require a license, see +// http://www.opensource.org/licenses/bsd-license.php +// +// This sketch turns the Arduino into a AVRISP +// using the following arduino pins: +// +// pin name: not-mega: mega(1280 and 2560) +// slave reset: 10: 53 +// MOSI: 11: 51 +// MISO: 12: 50 +// SCK: 13: 52 +// +// Put an LED (with resistor) on the following pins: +// 9: Heartbeat - shows the programmer is running +// 8: Error - Lights up if something goes wrong (use red if that makes sense) +// 7: Programming - In communication with the slave +// +// 23 July 2011 Randall Bohn +// -Address Arduino issue 509 :: Portability of ArduinoISP +// http://code.google.com/p/arduino/issues/detail?id=509 +// +// October 2010 by Randall Bohn +// - Write to EEPROM > 256 bytes +// - Better use of LEDs: +// -- Flash LED_PMODE on each flash commit +// -- Flash LED_PMODE while writing EEPROM (both give visual feedback of writing progress) +// - Light LED_ERR whenever we hit a STK_NOSYNC. Turn it off when back in sync. +// - Use pins_arduino.h (should also work on Arduino Mega) +// +// October 2009 by David A. Mellis +// - Added support for the read signature command +// +// February 2009 by Randall Bohn +// - Added support for writing to EEPROM (what took so long?) +// Windows users should consider WinAVR's avrdude instead of the +// avrdude included with Arduino software. +// +// January 2008 by Randall Bohn +// - Thanks to Amplificar for helping me with the STK500 protocol +// - The AVRISP/STK500 (mk I) protocol is used in the arduino bootloader +// - The SPI functions herein were developed for the AVR910_ARD programmer +// - More information at http://code.google.com/p/mega-isp + +#include "SPI.h" +#include "pins_arduino.h" +#define RESET SS + +#define LED_HB 9 +#define LED_ERR 8 +#define LED_PMODE 7 +#define PROG_FLICKER true + +#define HWVER 2 +#define SWMAJ 1 +#define SWMIN 18 + +// STK Definitions +#define STK_OK 0x10 +#define STK_FAILED 0x11 +#define STK_UNKNOWN 0x12 +#define STK_INSYNC 0x14 +#define STK_NOSYNC 0x15 +#define CRC_EOP 0x20 //ok it is a space... + +void pulse(int pin, int times); + +void setup() { + Serial.begin(9600); + SPI.setDataMode(0); + SPI.setBitOrder(MSBFIRST); + // Clock Div can be 2,4,8,16,32,64, or 128 + SPI.setClockDivider(SPI_CLOCK_DIV128); + pinMode(LED_PMODE, OUTPUT); + pulse(LED_PMODE, 2); + pinMode(LED_ERR, OUTPUT); + pulse(LED_ERR, 2); + pinMode(LED_HB, OUTPUT); + pulse(LED_HB, 2); + +} + +int error=0; +int pmode=0; +// address for reading and writing, set by 'U' command +int here; +uint8_t buff[256]; // global block storage + +#define beget16(addr) (*addr * 256 + *(addr+1) ) +typedef struct param { + uint8_t devicecode; + uint8_t revision; + uint8_t progtype; + uint8_t parmode; + uint8_t polling; + uint8_t selftimed; + uint8_t lockbytes; + uint8_t fusebytes; + uint8_t flashpoll; + uint16_t eeprompoll; + uint16_t pagesize; + uint16_t eepromsize; + uint32_t flashsize; +} +parameter; + +parameter param; + +// this provides a heartbeat on pin 9, so you can tell the software is running. +uint8_t hbval=128; +int8_t hbdelta=8; +void heartbeat() { + if (hbval > 192) hbdelta = -hbdelta; + if (hbval < 32) hbdelta = -hbdelta; + hbval += hbdelta; + analogWrite(LED_HB, hbval); + delay(40); +} + + +void loop(void) { + // is pmode active? + if (pmode) digitalWrite(LED_PMODE, HIGH); + else digitalWrite(LED_PMODE, LOW); + // is there an error? + if (error) digitalWrite(LED_ERR, HIGH); + else digitalWrite(LED_ERR, LOW); + + // light the heartbeat LED + heartbeat(); + if (Serial.available()) { + avrisp(); + } +} + +uint8_t getch() { + while(!Serial.available()); + return Serial.read(); +} +void fill(int n) { + for (int x = 0; x < n; x++) { + buff[x] = getch(); + } +} + +#define PTIME 30 +void pulse(int pin, int times) { + do { + digitalWrite(pin, HIGH); + delay(PTIME); + digitalWrite(pin, LOW); + delay(PTIME); + } + while (times--); +} + +void prog_lamp(int state) { + if (PROG_FLICKER) + digitalWrite(LED_PMODE, state); +} + +uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { + uint8_t n; + SPI.transfer(a); + n=SPI.transfer(b); + //if (n != a) error = -1; + n=SPI.transfer(c); + return SPI.transfer(d); +} + +void empty_reply() { + if (CRC_EOP == getch()) { + Serial.print((char)STK_INSYNC); + Serial.print((char)STK_OK); + } + else { + error++; + Serial.print((char)STK_NOSYNC); + } +} + +void breply(uint8_t b) { + if (CRC_EOP == getch()) { + Serial.print((char)STK_INSYNC); + Serial.print((char)b); + Serial.print((char)STK_OK); + } + else { + error++; + Serial.print((char)STK_NOSYNC); + } +} + +void get_version(uint8_t c) { + switch(c) { + case 0x80: + breply(HWVER); + break; + case 0x81: + breply(SWMAJ); + break; + case 0x82: + breply(SWMIN); + break; + case 0x93: + breply('S'); // serial programmer + break; + default: + breply(0); + } +} + +void set_parameters() { + // call this after reading paramter packet into buff[] + param.devicecode = buff[0]; + param.revision = buff[1]; + param.progtype = buff[2]; + param.parmode = buff[3]; + param.polling = buff[4]; + param.selftimed = buff[5]; + param.lockbytes = buff[6]; + param.fusebytes = buff[7]; + param.flashpoll = buff[8]; + // ignore buff[9] (= buff[8]) + // following are 16 bits (big endian) + param.eeprompoll = beget16(&buff[10]); + param.pagesize = beget16(&buff[12]); + param.eepromsize = beget16(&buff[14]); + + // 32 bits flashsize (big endian) + param.flashsize = buff[16] * 0x01000000 + + buff[17] * 0x00010000 + + buff[18] * 0x00000100 + + buff[19]; + +} + +void start_pmode() { + SPI.begin(); + digitalWrite(RESET, HIGH); + pinMode(RESET, OUTPUT); + digitalWrite(SCK, LOW); + delay(20); + digitalWrite(RESET, LOW); + spi_transaction(0xAC, 0x53, 0x00, 0x00); + pmode = 1; +} + +void end_pmode() { + SPI.end(); + digitalWrite(RESET, HIGH); + pinMode(RESET, INPUT); + pmode = 0; +} + +void universal() { + int w; + uint8_t ch; + + fill(4); + ch = spi_transaction(buff[0], buff[1], buff[2], buff[3]); + breply(ch); +} + +void flash(uint8_t hilo, int addr, uint8_t data) { + spi_transaction(0x40+8*hilo, + addr>>8 & 0xFF, + addr & 0xFF, + data); +} +void commit(int addr) { + if (PROG_FLICKER) prog_lamp(LOW); + spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0); + if (PROG_FLICKER) { + delay(PTIME); + prog_lamp(HIGH); + } +} + +//#define _current_page(x) (here & 0xFFFFE0) +int current_page(int addr) { + if (param.pagesize == 32) return here & 0xFFFFFFF0; + if (param.pagesize == 64) return here & 0xFFFFFFE0; + if (param.pagesize == 128) return here & 0xFFFFFFC0; + if (param.pagesize == 256) return here & 0xFFFFFF80; + return here; +} + + +void write_flash(int length) { + fill(length); + if (CRC_EOP == getch()) { + Serial.print((char) STK_INSYNC); + Serial.print((char) write_flash_pages(length)); + } + else { + error++; + Serial.print((char) STK_NOSYNC); + } +} + +uint8_t write_flash_pages(int length) { + int x = 0; + int page = current_page(here); + while (x < length) { + if (page != current_page(here)) { + commit(page); + page = current_page(here); + } + flash(LOW, here, buff[x++]); + flash(HIGH, here, buff[x++]); + here++; + } + + commit(page); + + return STK_OK; +} + +#define EECHUNK (32) +uint8_t write_eeprom(int length) { + // here is a word address, get the byte address + int start = here * 2; + int remaining = length; + if (length > param.eepromsize) { + error++; + return STK_FAILED; + } + while (remaining > EECHUNK) { + write_eeprom_chunk(start, EECHUNK); + start += EECHUNK; + remaining -= EECHUNK; + } + write_eeprom_chunk(start, remaining); + return STK_OK; +} +// write (length) bytes, (start) is a byte address +uint8_t write_eeprom_chunk(int start, int length) { + // this writes byte-by-byte, + // page writing may be faster (4 bytes at a time) + fill(length); + prog_lamp(LOW); + for (int x = 0; x < length; x++) { + int addr = start+x; + spi_transaction(0xC0, (addr>>8) & 0xFF, addr & 0xFF, buff[x]); + delay(45); + } + prog_lamp(HIGH); + return STK_OK; +} + +void program_page() { + char result = (char) STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + // flash memory @here, (length) bytes + if (memtype == 'F') { + write_flash(length); + return; + } + if (memtype == 'E') { + result = (char)write_eeprom(length); + if (CRC_EOP == getch()) { + Serial.print((char) STK_INSYNC); + Serial.print(result); + } + else { + error++; + Serial.print((char) STK_NOSYNC); + } + return; + } + Serial.print((char)STK_FAILED); + return; +} + +uint8_t flash_read(uint8_t hilo, int addr) { + return spi_transaction(0x20 + hilo * 8, + (addr >> 8) & 0xFF, + addr & 0xFF, + 0); +} + +char flash_read_page(int length) { + for (int x = 0; x < length; x+=2) { + uint8_t low = flash_read(LOW, here); + Serial.print((char) low); + uint8_t high = flash_read(HIGH, here); + Serial.print((char) high); + here++; + } + return STK_OK; +} + +char eeprom_read_page(int length) { + // here again we have a word address + int start = here * 2; + for (int x = 0; x < length; x++) { + int addr = start + x; + uint8_t ee = spi_transaction(0xA0, (addr >> 8) & 0xFF, addr & 0xFF, 0xFF); + Serial.print((char) ee); + } + return STK_OK; +} + +void read_page() { + char result = (char)STK_FAILED; + int length = 256 * getch(); + length += getch(); + char memtype = getch(); + if (CRC_EOP != getch()) { + error++; + Serial.print((char) STK_NOSYNC); + return; + } + Serial.print((char) STK_INSYNC); + if (memtype == 'F') result = flash_read_page(length); + if (memtype == 'E') result = eeprom_read_page(length); + Serial.print(result); + return; +} + +void read_signature() { + if (CRC_EOP != getch()) { + error++; + Serial.print((char) STK_NOSYNC); + return; + } + Serial.print((char) STK_INSYNC); + uint8_t high = spi_transaction(0x30, 0x00, 0x00, 0x00); + Serial.print((char) high); + uint8_t middle = spi_transaction(0x30, 0x00, 0x01, 0x00); + Serial.print((char) middle); + uint8_t low = spi_transaction(0x30, 0x00, 0x02, 0x00); + Serial.print((char) low); + Serial.print((char) STK_OK); +} +////////////////////////////////////////// +////////////////////////////////////////// + + +//////////////////////////////////// +//////////////////////////////////// +int avrisp() { + uint8_t data, low, high; + uint8_t ch = getch(); + switch (ch) { + case '0': // signon + error = 0; + empty_reply(); + break; + case '1': + if (getch() == CRC_EOP) { + Serial.print((char) STK_INSYNC); + Serial.print("AVR ISP"); + Serial.print((char) STK_OK); + } else { + error++; + Serial.print((char) STK_NOSYNC); + } + break; + case 'A': + get_version(getch()); + break; + case 'B': + fill(20); + set_parameters(); + empty_reply(); + break; + case 'E': // extended parameters - ignore for now + fill(5); + empty_reply(); + break; + + case 'P': + if (pmode) { + pulse(LED_ERR, 3); + } else { + start_pmode(); + } + empty_reply(); + break; + case 'U': // set address (word) + here = getch(); + here += 256 * getch(); + empty_reply(); + break; + + case 0x60: //STK_PROG_FLASH + low = getch(); + high = getch(); + empty_reply(); + break; + case 0x61: //STK_PROG_DATA + data = getch(); + empty_reply(); + break; + + case 0x64: //STK_PROG_PAGE + program_page(); + break; + + case 0x74: //STK_READ_PAGE 't' + read_page(); + break; + + case 'V': //0x56 + universal(); + break; + case 'Q': //0x51 + error=0; + end_pmode(); + empty_reply(); + break; + + case 0x75: //STK_READ_SIGN 'u' + read_signature(); + break; + + // expecting a command, not CRC_EOP + // this is how we can get back in sync + case CRC_EOP: + error++; + Serial.print((char) STK_NOSYNC); + break; + + // anything else we will return STK_UNKNOWN + default: + error++; + if (CRC_EOP == getch()) + Serial.print((char)STK_UNKNOWN); + else + Serial.print((char)STK_NOSYNC); + } +} + + + + diff --git a/build/shared/examples/ArduinoISP/ArduinoISP.ino b/build/shared/examples/11.ArduinoISP/UnoISP/UnoISP.ino similarity index 100% rename from build/shared/examples/ArduinoISP/ArduinoISP.ino rename to build/shared/examples/11.ArduinoISP/UnoISP/UnoISP.ino