From 190a4b87e848eb9b8c57eed63354c7309076c448 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Mon, 29 Oct 2007 18:03:02 +0000 Subject: [PATCH] Submitted by : Patch #6233: Add support for USBtinyISP programmer * usbtiny.c: New file. * usbtiny.h: (Ditto.) * Makefile.am: Include usbtiny into the build. * avrdude.conf.in: (Ditto.) * config_gram.y: (Ditto.) * lexer.l: (Ditto.) * avrdude.1: Document the usbtiny support. * doc/avrdude.texi: (Ditto.) git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk/avrdude@749 81a1dc3b-b13d-400b-aceb-764788c761c2 --- ChangeLog | 13 ++ Makefile.am | 2 + NEWS | 1 + avrdude.1 | 12 +- avrdude.conf.in | 6 + config_gram.y | 8 + doc/avrdude.texi | 3 + lexer.l | 1 + usbtiny.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++ usbtiny.h | 76 ++++++++ 10 files changed, 600 insertions(+), 6 deletions(-) create mode 100644 usbtiny.c create mode 100644 usbtiny.h diff --git a/ChangeLog b/ChangeLog index d511c5dd..94f5df8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-10-29 Joerg Wunsch + + Submitted by : + Patch #6233: Add support for USBtinyISP programmer + * usbtiny.c: New file. + * usbtiny.h: (Ditto.) + * Makefile.am: Include usbtiny into the build. + * avrdude.conf.in: (Ditto.) + * config_gram.y: (Ditto.) + * lexer.l: (Ditto.) + * avrdude.1: Document the usbtiny support. + * doc/avrdude.texi: (Ditto.) + 2007-10-29 Joerg Wunsch * doc/avrdude.texi: Sort list of supported programmers into diff --git a/Makefile.am b/Makefile.am index 9f4b32e9..094c177d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -138,6 +138,8 @@ libavrdude_a_SOURCES = \ usbasp.h \ usbdevs.h \ usb_libusb.c \ + usbtiny.h \ + usbtiny.c \ update.h \ update.c diff --git a/NEWS b/NEWS index 61915c5c..d9cadb44 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ Approximate change log for AVRDUDE by version. ---------------------------------------------------------------------- Current: + * Add support for the USBtinyISP programmer (patch #6233) Version 5.4: diff --git a/avrdude.1 b/avrdude.1 index 2abb1ca6..cb56e8e0 100644 --- a/avrdude.1 +++ b/avrdude.1 @@ -1,6 +1,6 @@ .\" .\" avrdude - A Downloader/Uploader for AVR device programmers -.\" Copyright (C) 2001, 2002, 2003, 2005, 2006 Joerg Wunsch +.\" Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 Joerg Wunsch .\" .\" 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 @@ -19,7 +19,7 @@ .\" .\" $Id$ .\" -.Dd DATE October 26, 2006 +.Dd DATE October 29, 2007 .Os .Dt AVRDUDE 1 .Sh NAME @@ -127,11 +127,11 @@ frequency, so the .Fl B Ar bitclock option might be required to achieve a stable ISP communication. .Pp -The USBasp ISP adapter is also supported, provided +The USBasp ISP and USBtinyISP adapters are also supported, provided .Nm avrdude has been compiled with libusb support. -It features a simple firwmare-only USB implementation, running on -an ATmega8 (or ATmega88). +They both feature simple firwmare-only USB implementations, running on +an ATmega8 (or ATmega88), or ATtiny2313, respectively. .Pp Input files can be provided, and output files can be written in different file formats, such as raw binary files containing the data @@ -817,6 +817,6 @@ option) requires a prior chip erase. This is an inherent feature of the way JTAG EEPROM programming works. This also applies to the STK500 in parallel programming mode. .Pp -The USBasp driver does not offer any option to distinguish multiple +The USBasp and USBtinyISP drivers do not offer any option to distinguish multiple devices connected simultaneously, so effectively only a single device is supported. diff --git a/avrdude.conf.in b/avrdude.conf.in index 8d6acd23..556d9bad 100644 --- a/avrdude.conf.in +++ b/avrdude.conf.in @@ -377,6 +377,12 @@ programmer type = usbasp; ; +programmer + id = "usbtiny"; + desc = "USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/"; + type = usbtiny; +; + programmer id = "butterfly"; desc = "Atmel Butterfly Development Board"; diff --git a/config_gram.y b/config_gram.y index 6eb3dd20..d75cfd72 100644 --- a/config_gram.y +++ b/config_gram.y @@ -42,6 +42,7 @@ #include "avr910.h" #include "butterfly.h" #include "usbasp.h" +#include "usbtiny.h" #include "avr.h" #include "jtagmkI.h" #include "jtagmkII.h" @@ -136,6 +137,7 @@ static int parse_cmdbits(OPCODE * op); %token K_STK500GENERIC %token K_AVR910 %token K_USBASP +%token K_USBTINY %token K_BUTTERFLY %token K_TYPE %token K_VCC @@ -421,6 +423,12 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_USBTINY { + { + usbtiny_initpgm(current_prog); + } + } | + K_TYPE TKN_EQUAL K_BUTTERFLY { { butterfly_initpgm(current_prog); diff --git a/doc/avrdude.texi b/doc/avrdude.texi index eaadf6d7..4a8f1e51 100644 --- a/doc/avrdude.texi +++ b/doc/avrdude.texi @@ -462,6 +462,9 @@ Atmel STK500, running a version 2.x firmware @item @code{usbasp} @tab USBasp,@* @url{http://www.fischl.de/usbasp/} +@item @code{usbtiny} @tab +USBtiny simple USB programmer,@* +@url{http://www.ladyada.net/make/usbtinyisp/} @item @code{xil} @tab Xilinx JTAG cable @end multitable diff --git a/lexer.l b/lexer.l index a1b38a14..c23a0856 100644 --- a/lexer.l +++ b/lexer.l @@ -120,6 +120,7 @@ allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; } avr910 { yylval=NULL; return K_AVR910; } avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; } usbasp { yylval=NULL; return K_USBASP; } +usbtiny { yylval=NULL; return K_USBTINY; } bank_size { yylval=NULL; return K_PAGE_SIZE; } banked { yylval=NULL; return K_PAGED; } baudrate { yylval=NULL; return K_BAUDRATE; } diff --git a/usbtiny.c b/usbtiny.c new file mode 100644 index 00000000..edf1322f --- /dev/null +++ b/usbtiny.c @@ -0,0 +1,484 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2007 Dick Streefland, adapted for 5.4 by Limor Fried + * + * 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 + */ + +/* + * Driver for "usbtiny"-type programmers + * Please see http://www.xs4all.nl/~dicks/avr/usbtiny/ + * and http://www.ladyada.net/make/usbtinyisp/ + * For example schematics and detailed documentation + */ + +#include "ac_cfg.h" + +#include +#include +#include +#include +#include +#include + +#include "avrdude.h" +#include "avr.h" +#include "pgm.h" +#include "usbtiny.h" + +#if defined(HAVE_LIBUSB) // we use LIBUSB to talk to the board +#include + +typedef unsigned int uint_t; +typedef unsigned long ulong_t; + +extern int avr_write_byte_default ( PROGRAMMER* pgm, AVRPART* p, + AVRMEM* mem, ulong_t addr, + unsigned char data ); +static usb_dev_handle* usb_handle; +static int sck_period; +static int chunk_size; + + +// ---------------------------------------------------------------------- + +// Wrapper for simple usb_control_msg messages +static int usb_control (unsigned int requestid, unsigned int val, unsigned int index ) +{ + int nbytes; + nbytes = usb_control_msg( usb_handle, + USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, // 2 bytes each of data + NULL, 0, // no data buffer in control messge + USB_TIMEOUT ); // default timeout + if(nbytes < 0){ + fprintf(stderr, "%s: error: usbtiny_transmit: %s\n", progname, usb_strerror()); + exit(1); + } + + return nbytes; +} + +// Wrapper for simple usb_control_msg messages to receive data from programmer +static int usb_in (unsigned int requestid, unsigned int val, unsigned int index, + unsigned char* buffer, int buflen, int bitclk ) +{ + int nbytes; + int timeout; + + // calculate the amout of time we expect the process to take by + // figuring the bit-clock time and buffer size and adding to the standard USB timeout. + timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; + + nbytes = usb_control_msg( usb_handle, + USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, + (char *)buffer, buflen, + timeout); + if (nbytes != buflen) { + fprintf(stderr, "%s: error: usbtiny_receive: %s (expected %d, got %d)\n", + progname, usb_strerror(), buflen, nbytes); + exit(1); + } + + return nbytes; +} + +// Wrapper for simple usb_control_msg messages to send data to programmer +static int usb_out (unsigned int requestid, unsigned int val, unsigned int index, + unsigned char* buffer, int buflen, int bitclk ) +{ + int nbytes; + int timeout; + + // calculate the amout of time we expect the process to take by + // figuring the bit-clock time and buffer size and adding to the standard USB timeout. + timeout = USB_TIMEOUT + (buflen * bitclk) / 1000; + + nbytes = usb_control_msg( usb_handle, + USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + requestid, + val, index, + (char *)buffer, buflen, + timeout); + if (nbytes != buflen) { + fprintf(stderr, "%s: error: usbtiny_send: %s (expected %d, got %d)\n", + progname, usb_strerror(), buflen, nbytes); + exit(1); + } + + return nbytes; +} + +// Sometimes we just need to know the SPI command for the part to perform +// a function. Here we wrap this request for an operation so that we +// can just specify the part and operation and it'll do the right stuff +// to get the information from AvrDude and send to the USBtiny +static int usbtiny_avr_op (PROGRAMMER * pgm, AVRPART * p, + int op, + unsigned char res[4]) +{ + unsigned char cmd[4]; + + if (p->op[op] == NULL) { + fprintf( stderr, "Operation %d not defined for this chip!\n", op ); + return -1; + } + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(p->op[op], cmd); + + return pgm->cmd(pgm, cmd, res); +} + +// ---------------------------------------------------------------------- + +/* Find a device with the correct VID/PID match for USBtiny */ + +static int usbtiny_open(PROGRAMMER* pgm, char* name) +{ + struct usb_bus *bus; + struct usb_device *dev = 0; + + usb_init(); // initialize the libusb system + usb_find_busses(); // have libusb scan all the usb busses available + usb_find_devices(); // have libusb scan all the usb devices available + + usb_handle = NULL; + + // now we iterate through all the busses and devices + for ( bus = usb_busses; bus; bus = bus->next ) { + for ( dev = bus->devices; dev; dev = dev->next ) { + if (dev->descriptor.idVendor == USBTINY_VENDOR + && dev->descriptor.idProduct == USBTINY_PRODUCT ) { // found match? + + usb_handle = usb_open(dev); // attempt to connect to device + + // wrong permissions or something? + if (!usb_handle) { + fprintf(stderr, "%s: Warning: cannot open USB device: %s\n", + progname, usb_strerror()); + continue; + } + } + } + } + + if (!usb_handle) { + fprintf( stderr, "%s: Error: Could not find USBtiny device (0x%x/0x%x)\n", + progname, USBTINY_VENDOR, USBTINY_PRODUCT ); + exit(1); + } + + return 0; // If we got here, we must have found a good USB device +} + +/* Clean up the handle for the usbtiny */ +static void usbtiny_close ( PROGRAMMER* pgm ) +{ + if (! usb_handle) { + return; // not a valid handle, bail! + } + usb_close(usb_handle); // ask libusb to clean up + usb_handle = NULL; +} + +/* A simple calculator function determines the maximum size of data we can + shove through a USB connection without getting errors */ +static void usbtiny_set_chunk_size (int period) +{ + chunk_size = CHUNK_SIZE; // start with the maximum (default) + while (chunk_size > 8 && period > 16) { + // Reduce the chunk size for a slow SCK to reduce + // the maximum time of a single USB transfer. + chunk_size >>= 1; + period >>= 1; + } +} + +/* Given a SCK bit-clock speed (in useconds) we verify its an OK speed and tell the + USBtiny to update itself to the new frequency */ +static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v) +{ + sck_period = (int)(v * 1e6 + 0.5); // convert from us to 'int', the 0.5 is for rounding up + + // Make sure its not 0, as that will confuse the usbtiny + if (sck_period < SCK_MIN) + sck_period = SCK_MIN; + + // We can't go slower, due to the byte-size of the clock variable + if (sck_period > SCK_MAX) + sck_period = SCK_MAX; + + printf( "%s: Setting SCK period to %d usec\n", progname, sck_period ); + + // send the command to the usbtiny device. + usb_control(USBTINY_POWERUP, sck_period, RESET_LOW); // MEME: for at90's fix resetstate? + + // with the new speed, we'll have to update how much data we send per usb transfer + usbtiny_set_chunk_size(sck_period); + return 0; +} + + +static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p ) +{ + unsigned char res[4]; // store the response from usbtinyisp + + // Check for bit-clock and tell the usbtiny to adjust itself + if (pgm->bitclock > 0.0) { + // -B option specified: convert to valid range for sck_period + usbtiny_set_sck_period(pgm, pgm->bitclock); + } else { + // -B option not specified: use default + sck_period = SCK_DEFAULT; + if (verbose) { + printf( "%s: Using SCK period of %d usec\n", + progname, sck_period ); + } + usb_control( USBTINY_POWERUP, sck_period, RESET_LOW ); + usbtiny_set_chunk_size(sck_period); + } + + // Let the device wake up. + usleep(50000); + + // Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?) + if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) { + // no response, RESET and try again + usb_control(USBTINY_POWERUP, sck_period, RESET_HIGH); + usb_control(USBTINY_POWERUP, sck_period, RESET_LOW); + usleep(50000); + if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) { + // give up + return -1; + } + } + return 0; +} + +/* Tell the USBtiny to release the output pins, etc */ +static void usbtiny_powerdown(PROGRAMMER * pgm) +{ + if (!usb_handle) { + return; // wasn't connected in the first place + } + usb_control(USBTINY_POWERDOWN, 0, 0); // Send USB control command to device +} + +/* Send a 4-byte SPI command to the USBtinyISP for execution + This procedure is used by higher-level Avrdude procedures */ +static int usbtiny_cmd(PROGRAMMER * pgm, unsigned char cmd[4], unsigned char res[4]) +{ + int nbytes; + + // Make sure its empty so we don't read previous calls if it fails + memset(res, '\0', sizeof(res) ); + + nbytes = usb_in( USBTINY_SPI, + (cmd[1] << 8) | cmd[0], // convert to 16-bit words + (cmd[3] << 8) | cmd[2], // " + res, sizeof(res), 8 * sck_period ); + if (verbose > 1) { + // print out the data we sent and received + printf( "CMD: [%02x %02x %02x %02x] [%02x %02x %02x %02x]\n", + cmd[0], cmd[1], cmd[2], cmd[3], + res[0], res[1], res[2], res[3] ); + } + return ((nbytes == sizeof(res)) && // should have read 4 bytes + res[2] == cmd[1]); // AVR's do a delayed-echo thing +} + +/* Send the chip-erase command */ +static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p) +{ + unsigned char res[4]; + + if (p->op[AVR_OP_CHIP_ERASE] == NULL) { + fprintf(stderr, "Chip erase instruction not defined for part \"%s\"\n", + p->desc); + return -1; + } + + // get the command for erasing this chip and transmit to avrdude + if (! usbtiny_avr_op( pgm, p, AVR_OP_CHIP_ERASE, res )) { + return -1; + } + usleep( p->chip_erase_delay ); + + // prepare for further instruction + pgm->initialize(pgm, p); + + return 0; +} + +// These are required functions but don't actually do anything +static void usbtiny_enable ( PROGRAMMER* pgm ) {} + +static void usbtiny_disable ( PROGRAMMER* pgm ) {} + + +/* To speed up programming and reading, we do a 'chunked' read. + * We request just the data itself and the USBtiny uses the SPI function + * given to read in the data. Much faster than sending a 4-byte SPI request + * per byte +*/ +static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m, + int page_size, int n_bytes ) +{ + int i; + int chunk; + int function; + + + // First determine what we're doing + if (strcmp( m->desc, "flash" ) == 0) { + function = USBTINY_FLASH_READ; + } else { + function = USBTINY_EEPROM_READ; + } + + for (i = 0; i < n_bytes; i += chunk) { + chunk = chunk_size; // start with the maximum chunk size possible + + // If we want to xmit less than a chunk, thats OK + if (chunk > n_bytes-i) + chunk = n_bytes - i; + + // Send the chunk of data to the USBtiny with the function we want + // to perform + usb_in(function, // EEPROM or flash + 0, // delay between SPI commands + i, // index + m->buf + i, // pointer to where we store data + chunk, // number of bytes + 32 * sck_period); // each byte gets turned into a 4-byte SPI cmd + // usb_in() multiplies this per byte. + + // Tell avrdude how we're doing to provide user feedback + report_progress(i + chunk, n_bytes, NULL ); + } + + return n_bytes; +} + +/* To speed up programming and reading, we do a 'chunked' write. + * We send just the data itself and the USBtiny uses the SPI function + * given to write the data. Much faster than sending a 4-byte SPI request + * per byte. +*/ +static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, + int page_size, int n_bytes) +{ + int i; + int chunk; // Size of data to write at once + int next; + int function; // which SPI command to use + int delay; // delay required between SPI commands + + // First determine what we're doing + if (strcmp( m->desc, "flash" ) == 0) { + function = USBTINY_FLASH_WRITE; + } else { + function = USBTINY_EEPROM_WRITE; + } + + delay = 0; + if (! m->paged) { + // Does this chip not support paged writes? + i = (m->readback[1] << 8) | m->readback[0]; + usb_control( USBTINY_POLL_BYTES, i, 0 ); + delay = m->max_write_delay; + } + + for (i=0; i < n_bytes; i=next) { + // start with the max chunk size + chunk = chunk_size; + + // we can only write a page at a time anyways + if (m->paged && chunk > page_size) + chunk = page_size; + + // if there's less data remaining than one chunk + if (chunk > n_bytes-i) + chunk = n_bytes - i; + + usb_out(function, // Flash or EEPROM + delay, // How much to wait between each byte + i, // Index of data + m->buf + i, // Pointer to data + chunk, // Number of bytes to write + 32 * sck_period + delay // each byte gets turned into a + // 4-byte SPI cmd usb_in() multiplies + // this per byte. Then add the cmd-delay + ); + + next = i + chunk; // Calculate what address we're at now + if (m->paged + && ((next % page_size) == 0 || next == n_bytes) ) { + // If we're at a page boundary, send the SPI command to flush it. + avr_write_page(pgm, p, m, (unsigned long) i); + } + + report_progress( next, n_bytes, NULL ); + } + return n_bytes; +} + +extern void usbtiny_initpgm ( PROGRAMMER* pgm ) +{ + strcpy(pgm->type, "USBtiny"); + + /* Mandatory Functions */ + pgm->initialize = usbtiny_initialize; + pgm->enable = usbtiny_enable; + pgm->disable = usbtiny_disable; + pgm->program_enable = NULL; + pgm->chip_erase = usbtiny_chip_erase; + pgm->cmd = usbtiny_cmd; + pgm->open = usbtiny_open; + pgm->close = usbtiny_close; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; + + /* Optional Functions */ + pgm->powerup = NULL; + pgm->powerdown = usbtiny_powerdown; + pgm->paged_load = usbtiny_paged_load; + pgm->paged_write = usbtiny_paged_write; + pgm->set_sck_period = usbtiny_set_sck_period; +} + +#else /* !HAVE_LIBUSB */ + +// Give a proper error if we were not compiled with libusb + +static int usbtiny_nousb_open(struct programmer_t *pgm, char * name) +{ + fprintf(stderr, "%s: error: no usb support. Please compile again with libusb installed.\n", + progname); + + exit(1); +} + +void usbtiny_initpgm(PROGRAMMER * pgm) +{ + strcpy(pgm->type, "usbtiny"); + + pgm->open = usbtiny_nousb_open; +} + +#endif /* HAVE_LIBUSB */ diff --git a/usbtiny.h b/usbtiny.h new file mode 100644 index 00000000..77f9a42e --- /dev/null +++ b/usbtiny.h @@ -0,0 +1,76 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2007 Limor Fried + * + * 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 + */ + + +#ifndef usbtiny_h +#define usbtiny_h + +#include "avrpart.h" + +// these are specifically assigned to USBtiny, +// if you need your own VID and PIDs you can get them for cheap from +// www.mecanique.co.uk so please don't reuse these. Thanks! +#define USBTINY_VENDOR 0x1781 +#define USBTINY_PRODUCT 0x0C9F + +// Generic requests to the USBtiny +#define USBTINY_ECHO 0 // echo test +#define USBTINY_READ 1 // read byte (wIndex:address) +#define USBTINY_WRITE 2 // write byte (wIndex:address, wValue:value) +#define USBTINY_CLR 3 // clear bit (wIndex:address, wValue:bitno) +#define USBTINY_SET 4 // set bit (wIndex:address, wValue:bitno) + +// Programming requests +#define USBTINY_POWERUP 5 // apply power (wValue:SCK-period, wIndex:RESET) +#define USBTINY_POWERDOWN 6 // remove power from chip +#define USBTINY_SPI 7 // issue SPI command (wValue:c1c0, wIndex:c3c2) +#define USBTINY_POLL_BYTES 8 // set poll bytes for write (wValue:p1p2) +#define USBTINY_FLASH_READ 9 // read flash (wIndex:address) +#define USBTINY_FLASH_WRITE 10 // write flash (wIndex:address, wValue:timeout) +#define USBTINY_EEPROM_READ 11 // read eeprom (wIndex:address) +#define USBTINY_EEPROM_WRITE 12 // write eeprom (wIndex:address, wValue:timeout) + + + +// Flags to indicate how to set RESET on power up +#define RESET_LOW 0 +#define RESET_HIGH 1 + +// The SCK speed can be set by avrdude, to allow programming of slow-clocked parts +#define SCK_MIN 1 // usec delay (target clock >= 4 MHz) +#define SCK_MAX 250 // usec (target clock >= 16 KHz) +#define SCK_DEFAULT 10 // usec (target clock >= 0.4 MHz) + +// How much data, max, do we want to send in one USB packet? +#define CHUNK_SIZE 128 // must be power of 2 less than 256 + +// The default USB Timeout +#define USB_TIMEOUT 500 // msec + +#ifdef __cplusplus +extern "C" { +#endif + +void usbtiny_initpgm (PROGRAMMER * pgm); + +#ifdef __cplusplus +} +#endif + +#endif /* usbtiny_h */