Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

much improved Arduino ISP sketch!

  • Loading branch information...
commit 8e3ba20d6ff1be2eac501f71e7a60c1bc20dd401 1 parent be12ee6
@ladyada ladyada authored
Showing with 348 additions and 206 deletions.
  1. +348 −206 ArduinoISP2.pde
View
554 ArduinoISP2.pde
@@ -6,9 +6,10 @@
// 13: SCK
// Put an LED (with resistor) on the following pins:
-// 8: Error - Lights up if something goes wrong (use red if that makes sense)
-// 7: Programming - In communication with the slave
-// 6: Heartbeat - shows the programmer is running
+// 8: Error - Lights up if something goes wrong (use red if that makes sense)
+// A0: Programming - In communication with the slave
+// 6: Heartbeat - shows the programmer is running (removed, see notes below)
+// Optional - Piezo speaker on pin A3
//
// October 2009 by David A. Mellis
// - Added support for the read signature command
@@ -23,36 +24,92 @@
// - 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
+//
+// March 2012 - William Phelps
+// modify to work with Arduino IDE 1.0 which has a shorter serial port receive buffer
+// getEOP() now gets entire request before avrisp() is called to process it
+// Serial.print((char) xxx) changed to Serial.write(xxx)
+// uint8_t changed to byte
+// added support for Piezo speaker
+// moved Pmode LED to A0
+// removed "heartbeat" on pin 6, added short blip of ERROR LED instead
+// Why is it that PROG_FLASH and PROG_DATA don't actually do anything???
+// Tested with Arduino IDE 22 and 1.0
+// IDE 22 - 5148 bytes
+// IDE 1.0 - 5524 bytes!
#include "pins_arduino.h" // defines SS,MOSI,MISO,SCK
#define RESET SS
#define LED_ERR 8
#define LED_PMODE A0
-#define LED_HB 6
+//#define LED_HB 6
+#define PIEZO A3
#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...
+const byte STK_OK = 0x10;
+const byte STK_FAILED = 0x11;
+const byte STK_UNKNOWN = 0x12;
+const byte STK_INSYNC = 0x14;
+const byte STK_NOSYNC = 0x15;
+const byte CRC_EOP = 0x20; //ok it is a space...
+
+const byte STK_GET_SYNC = 0x30;
+const byte STK_GET_SIGNON = 0x31;
+const byte STK_GET_PARM = 0x41;
+const byte STK_SET_PARM = 0x42;
+const byte STK_SET_PARM_EXT = 0x45;
+const byte STK_PMODE_START = 0x50;
+const byte STK_PMODE_END = 0x51;
+const byte STK_SET_ADDR = 0x55;
+const byte STK_UNIVERSAL = 0x56;
+const byte STK_PROG_FLASH = 0x60;
+const byte STK_PROG_DATA = 0x61;
+const byte STK_PROG_PAGE = 0x64;
+const byte STK_READ_PAGE = 0x74;
+const byte STK_READ_SIGN = 0x75;
+
+//// TONES ==========================================
+//// Start by defining the relationship between
+//// note, period, & frequency.
+//#define c 3830 // 261 Hz
+//#define d 3400 // 294 Hz
+//#define e 3038 // 329 Hz
+//#define f 2864 // 349 Hz
+//#define g 2550 // 392 Hz
+//#define a 2272 // 440 Hz
+//#define b 2028 // 493 Hz
+//#define C 1912 // 523 Hz
+
+//void pulse(int pin, int times);
-void pulse(int pin, int times);
+int error=0;
+int pmode=0;
+// address for reading and writing, set by STK_SET_ADDR command
+int _addr;
+byte _buffer[256]; // serial port buffer
+int pBuffer = 0; // buffer pointer
+int iBuffer = 0; // buffer index
+byte buff[256]; // temporary buffer
+boolean EOP_SEEN = false;
void setup() {
Serial.begin(19200);
+ pinMode(PIEZO, OUTPUT);
+ beep(1700, 40);
+ EOP_SEEN = false;
+ iBuffer = pBuffer = 0;
+
pinMode(LED_PMODE, OUTPUT);
pulse(LED_PMODE, 2);
pinMode(LED_ERR, OUTPUT);
pulse(LED_ERR, 2);
- pinMode(LED_HB, OUTPUT);
- pulse(LED_HB, 2);
+// pinMode(LED_HB, OUTPUT);
+// pulse(LED_HB, 2);
pinMode(9, OUTPUT);
// setup high freq PWM on pin 9 (timer 1)
@@ -64,22 +121,16 @@ void setup() {
TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // no clock prescale
}
-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;
+ byte devicecode;
+ byte revision;
+ byte progtype;
+ byte parmode;
+ byte polling;
+ byte selftimed;
+ byte lockbytes;
+ byte fusebytes;
int flashpoll;
int eeprompoll;
int pagesize;
@@ -90,56 +141,123 @@ 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);
-}
+// this provides a heartbeat on pin 6, so you can tell the software is running.
+//byte hbval=128;
+//int8_t hbdelta=4;
+//void heartbeat() {
+//// if (hbval > 192) hbdelta = -hbdelta;
+//// if (hbval < 32) hbdelta = -hbdelta;
+// if (hbval > 250) hbdelta = -hbdelta;
+// if (hbval < 10) hbdelta = -hbdelta;
+// hbval += hbdelta;
+// analogWrite(LED_HB, hbval);
+// delay(20);
+//}
+void getEOP() {
+ int minL = 0;
+ byte avrch = 0;
+ byte bl = 0;
+ while (!EOP_SEEN) {
+ while (Serial.available()>0) {
+ byte ch = Serial.read();
+ _buffer[iBuffer] = ch;
+ iBuffer = (++iBuffer)%256; // increment and wrap
+ if (iBuffer == 1) avrch = ch; // save command
+ if ((avrch == STK_PROG_PAGE) && (iBuffer==3)) {
+ minL = 256*_buffer[1] + _buffer[2] + 4;
+ }
+ if ((iBuffer>minL) && (ch == CRC_EOP)) {
+ EOP_SEEN = true;
+ }
+ }
+ if (!EOP_SEEN) {
+// heartbeat(); // light the heartbeat LED
+ if (bl == 100) {
+ pulse(LED_ERR,1,10); // blink the red LED
+ bl = 0;
+ }
+ bl++;
+ delay(10);
+ }
+ }
+}
+
+// serialEvent not used so sketch would be compatible with older IDE versions
+//void serialEvent() {
+// int minL = 0;
+// byte avrch = 0;
+// while (Serial.available()>0)
+// {
+// byte ch = Serial.read();
+// _buffer[iBuffer] = ch;
+// iBuffer = (++iBuffer)%256; // increment and wrap
+// if (iBuffer == 1) avrch = ch; // save command
+// if ((avrch == STK_PROG_PAGE) && (iBuffer==3)) {
+// minL = 256*_buffer[1] + _buffer[2] + 4;
+// }
+// if ((iBuffer>minL) && (ch == CRC_EOP)) {
+// EOP_SEEN = true;
+// }
+// }
+//}
void loop(void) {
// is pmode active?
- if (pmode) digitalWrite(LED_PMODE, HIGH);
- else digitalWrite(LED_PMODE, LOW);
+// if (pmode) digitalWrite(LED_PMODE, HIGH);
+// else digitalWrite(LED_PMODE, LOW);
+ digitalWrite(LED_PMODE, LOW);
// is there an error?
if (error) digitalWrite(LED_ERR, HIGH);
else digitalWrite(LED_ERR, LOW);
+
+ getEOP();
- // light the heartbeat LED
- heartbeat();
- if (Serial.available()) {
+ // have we received a complete request? (ends with CRC_EOP)
+ if (EOP_SEEN) {
+ digitalWrite(LED_PMODE, HIGH);
+ EOP_SEEN = false;
avrisp();
+ iBuffer = pBuffer = 0; // restart buffer
}
+
}
-uint8_t getch() {
- while(!Serial.available());
- return Serial.read();
+byte getch() {
+ if (pBuffer == iBuffer) { // spin until data available ???
+ pulse(LED_ERR, 1);
+ beep(1700, 20);
+ error++;
+ return -1;
+ }
+ byte ch = _buffer[pBuffer]; // get next char
+ pBuffer = (++pBuffer)%256; // increment and wrap
+ return ch;
}
+
void readbytes(int n) {
for (int x = 0; x < n; x++) {
- buff[x] = Serial.read();
+ buff[x] = getch();
}
}
-#define PTIME 30
-void pulse(int pin, int times) {
+//#define PTIME 20
+void pulse(int pin, int times, int ptime) {
do {
digitalWrite(pin, HIGH);
- delay(PTIME);
+ delay(ptime);
digitalWrite(pin, LOW);
- delay(PTIME);
+ delay(ptime);
+ times--;
}
- while (times--);
+ while (times > 0);
+}
+void pulse(int pin, int times) {
+ pulse(pin, times, 50);
}
void spi_init() {
- uint8_t x;
+ byte x;
SPCR = 0x53;
x=SPSR;
x=SPDR;
@@ -151,16 +269,16 @@ void spi_wait() {
while (!(SPSR & (1 << SPIF)));
}
-uint8_t spi_send(uint8_t b) {
- uint8_t reply;
+byte spi_send(byte b) {
+ byte reply;
SPDR=b;
spi_wait();
reply = SPDR;
return reply;
}
-uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
- uint8_t n;
+byte spi_transaction(byte a, byte b, byte c, byte d) {
+ byte n;
spi_send(a);
n=spi_send(b);
//if (n != a) error = -1;
@@ -168,28 +286,32 @@ uint8_t spi_transaction(uint8_t a, uint8_t b, uint8_t c, uint8_t d) {
return spi_send(d);
}
-void empty_reply() {
- if (CRC_EOP == getch()) {
- Serial.print((char)STK_INSYNC);
- Serial.print((char)STK_OK);
+void replyOK() {
+// if (EOP_SEEN == true) {
+ if (CRC_EOP == getch()) { // EOP should be next char
+ Serial.write(STK_INSYNC);
+ Serial.write(STK_OK);
}
else {
- Serial.print((char)STK_NOSYNC);
+ pulse(LED_ERR, 2);
+ Serial.write(STK_NOSYNC);
+ error++;
}
}
-void breply(uint8_t b) {
- if (CRC_EOP == getch()) {
- Serial.print((char)STK_INSYNC);
- Serial.print((char)b);
- Serial.print((char)STK_OK);
+void breply(byte b) {
+ if (CRC_EOP == getch()) { // EOP should be next char
+ Serial.write(STK_INSYNC);
+ Serial.write(b);
+ Serial.write(STK_OK);
}
else {
- Serial.print((char)STK_NOSYNC);
+ Serial.write(STK_NOSYNC);
+ error++;
}
}
-void get_version(uint8_t c) {
+void get_parameter(byte c) {
switch(c) {
case 0x80:
breply(HWVER);
@@ -261,21 +383,18 @@ void end_pmode() {
}
void universal() {
- int w;
- uint8_t ch;
-
- for (w = 0; w < 4; w++) {
- buff[w] = getch();
- }
+// int w;
+ byte ch;
+// for (w = 0; w < 4; w++) {
+// buff[w] = getch();
+// }
+ readbytes(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 flash(byte hilo, int addr, byte data) {
+ spi_transaction(0x40+8*hilo, addr>>8 & 0xFF, addr & 0xFF, data);
}
void commit(int addr) {
spi_transaction(0x4C, (addr >> 8) & 0xFF, addr & 0xFF, 0);
@@ -283,65 +402,78 @@ void commit(int addr) {
//#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;
+ if (param.pagesize == 32) return addr & 0xFFFFFFF0;
+ if (param.pagesize == 64) return addr & 0xFFFFFFE0;
+ if (param.pagesize == 128) return addr & 0xFFFFFFC0;
+ if (param.pagesize == 256) return addr & 0xFFFFFF80;
+ return addr;
}
-uint8_t write_flash(int length) {
- if (param.pagesize < 1) return STK_FAILED;
+byte write_flash(int length) {
+ if (param.pagesize < 1) {
+ return STK_FAILED;
+ }
//if (param.pagesize != 64) return STK_FAILED;
- int page = current_page(here);
+ int page = current_page(_addr);
int x = 0;
while (x < length) {
- if (page != current_page(here)) {
+ if (page != current_page(_addr)) {
commit(page);
- page = current_page(here);
+ page = current_page(_addr);
}
- flash(LOW, here, buff[x++]);
- flash(HIGH, here, buff[x++]);
- here++;
+ flash(LOW, _addr, buff[x++]);
+ flash(HIGH, _addr, buff[x++]);
+ _addr++;
}
-
commit(page);
-
return STK_OK;
}
-uint8_t write_eeprom(int length) {
+byte write_eeprom(int length) {
// here is a word address, so we use here*2
// this writes byte-by-byte,
// page writing may be faster (4 bytes at a time)
for (int x = 0; x < length; x++) {
- spi_transaction(0xC0, 0x00, here*2+x, buff[x]);
+ spi_transaction(0xC0, 0x00, _addr*2+x, buff[x]);
delay(45);
}
return STK_OK;
}
void program_page() {
- char result = (char) STK_FAILED;
+ byte result = STK_FAILED;
int length = 256 * getch() + getch();
if (length > 256) {
- Serial.print((char) STK_FAILED);
+ Serial.write(STK_FAILED);
+ error++;
return;
}
- char memtype = getch();
- for (int x = 0; x < length; x++) {
- buff[x] = getch();
- }
+ char memtype = (char)getch();
+// for (int x = 0; x < length; x++) {
+// buff[x] = getch();
+// }
+ readbytes(length);
if (CRC_EOP == getch()) {
- Serial.print((char) STK_INSYNC);
- if (memtype == 'F') result = (char)write_flash(length);
- if (memtype == 'E') result = (char)write_eeprom(length);
- Serial.print(result);
+ Serial.write(STK_INSYNC);
+ switch (memtype) {
+ case 'E':
+ result = (byte)write_eeprom(length);
+ break;
+ case 'F':
+ result = (byte)write_flash(length);
+ break;
+ }
+ Serial.write(result);
+ if (result != STK_OK) {
+ error++;
+ }
}
else {
- Serial.print((char) STK_NOSYNC);
+ Serial.write(STK_NOSYNC);
+ error++;
}
}
-uint8_t flash_read(uint8_t hilo, int addr) {
+
+byte flash_read(byte hilo, int addr) {
return spi_transaction(0x20 + hilo * 8,
(addr >> 8) & 0xFF,
addr & 0xFF,
@@ -350,11 +482,11 @@ uint8_t flash_read(uint8_t hilo, int addr) {
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++;
+ byte low = flash_read(LOW, _addr);
+ Serial.write( low);
+ byte high = flash_read(HIGH, _addr);
+ Serial.write( high);
+ _addr++;
}
return STK_OK;
}
@@ -362,40 +494,41 @@ char flash_read_page(int length) {
char eeprom_read_page(int length) {
// here again we have a word address
for (int x = 0; x < length; x++) {
- uint8_t ee = spi_transaction(0xA0, 0x00, here*2+x, 0xFF);
- Serial.print((char) ee);
+ byte ee = spi_transaction(0xA0, 0x00, _addr*2+x, 0xFF);
+ Serial.write( ee);
}
return STK_OK;
}
void read_page() {
- char result = (char)STK_FAILED;
+ byte result = (byte)STK_FAILED;
int length = 256 * getch() + getch();
char memtype = getch();
if (CRC_EOP != getch()) {
- Serial.print((char) STK_NOSYNC);
+ Serial.write(STK_NOSYNC);
return;
}
- Serial.print((char) STK_INSYNC);
+ Serial.write(STK_INSYNC);
if (memtype == 'F') result = flash_read_page(length);
if (memtype == 'E') result = eeprom_read_page(length);
- Serial.print(result);
+ Serial.write(result);
return;
}
void read_signature() {
if (CRC_EOP != getch()) {
- Serial.print((char) STK_NOSYNC);
+ Serial.write(STK_NOSYNC);
+ error++;
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);
+ Serial.write(STK_INSYNC);
+ byte high = spi_transaction(0x30, 0x00, 0x00, 0x00);
+ Serial.write(high);
+ byte middle = spi_transaction(0x30, 0x00, 0x01, 0x00);
+ Serial.write(middle);
+ byte low = spi_transaction(0x30, 0x00, 0x02, 0x00);
+ Serial.write(low);
+ Serial.write(STK_OK);
}
//////////////////////////////////////////
//////////////////////////////////////////
@@ -403,85 +536,94 @@ void read_signature() {
////////////////////////////////////
////////////////////////////////////
-int avrisp() {
- uint8_t data, low, high;
- uint8_t ch = getch();
- switch (ch) {
- case '0': // signon
- empty_reply();
- break;
- case '1':
- if (getch() == CRC_EOP) {
- Serial.print((char) STK_INSYNC);
- Serial.print("AVR ISP");
- Serial.print((char) STK_OK);
- }
- break;
- case 'A':
- get_version(getch());
- break;
- case 'B':
- readbytes(20);
- set_parameters();
- empty_reply();
- break;
- case 'E': // extended parameters - ignore for now
- readbytes(5);
- empty_reply();
- break;
-
- case 'P':
- start_pmode();
- empty_reply();
- break;
- case 'U':
- here = getch() + 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
- read_page();
- break;
-
- case 'V':
- universal();
- break;
- case 'Q':
- error=0;
- end_pmode();
- empty_reply();
- break;
-
- case 0x75: //STK_READ_SIGN
- read_signature();
- break;
-
- // expecting a command, not CRC_EOP
- // this is how we can get back in sync
- case CRC_EOP:
- Serial.print((char) STK_NOSYNC);
- break;
-
- // anything else we will return STK_UNKNOWN
- default:
- if (CRC_EOP == getch())
- Serial.print((char)STK_UNKNOWN);
- else
- Serial.print((char)STK_NOSYNC);
+int avrisp() {
+ byte data, low, high;
+ byte avrch = getch();
+ switch (avrch) {
+ case STK_GET_SYNC: // get in sync
+ replyOK();
+ break;
+ case STK_GET_SIGNON: // get sign on
+ if (getch() == CRC_EOP) {
+ Serial.write(STK_INSYNC);
+ Serial.write("AVR ISP");
+ Serial.write(STK_OK);
+ }
+ break;
+ case STK_GET_PARM: // 0x41
+ get_parameter(getch());
+ break;
+ case STK_SET_PARM: // 0x42
+ readbytes(20);
+ set_parameters();
+ replyOK();
+ break;
+ case STK_SET_PARM_EXT: // extended parameters - ignore for now
+ readbytes(5);
+ replyOK();
+ break;
+ case STK_PMODE_START: // 0x50
+ beep(2272, 20);
+ start_pmode();
+ replyOK();
+ break;
+ case STK_PMODE_END: //0x51
+ beep(1912, 50);
+ error=0;
+ end_pmode();
+ replyOK();
+ break;
+ case STK_SET_ADDR: // 0x55
+ _addr = getch() + 256 * getch();
+ replyOK();
+ break;
+ case STK_UNIVERSAL: //UNIVERSAL 0x56
+ universal();
+ break;
+ case STK_PROG_FLASH: //STK_PROG_FLASH ???
+ low = getch();
+ high = getch();
+ replyOK();
+ break;
+ case STK_PROG_DATA: //STK_PROG_DATA ???
+ data = getch();
+ replyOK();
+ break;
+ case STK_PROG_PAGE: //STK_PROG_PAGE
+// beep(1912, 20);
+ program_page();
+ break;
+ case STK_READ_PAGE: //STK_READ_PAGE
+ read_page();
+ break;
+ case STK_READ_SIGN: //STK_READ_SIGN
+ read_signature();
+ break;
+ // expecting a command, not CRC_EOP
+ // this is how we can get back in sync
+ case CRC_EOP:
+ Serial.write(STK_NOSYNC);
+ break;
+ // anything else we will return STK_UNKNOWN
+ default:
+ if (CRC_EOP == getch())
+ Serial.write(STK_UNKNOWN);
+ else
+ Serial.write(STK_NOSYNC);
}
}
+// beep without using PWM
+void beep(int tone, long duration){
+ long elapsed = 0;
+ while (elapsed < (duration * 10000)) {
+ digitalWrite(PIEZO, HIGH);
+ delayMicroseconds(tone / 2);
+ digitalWrite(PIEZO, LOW);
+ delayMicroseconds(tone / 2);
+ // Keep track of how long we pulsed
+ elapsed += tone;
+ }
+}
+
Please sign in to comment.
Something went wrong with that request. Please try again.