--- /dev/null
+Instructions for converting the LUFA USBtoSerial Demo to an AVR ISP Programmer.\r
+By Opendous Inc., Copyright under the Creative Commons Attribution License:\r
+http://creativecommons.org/licenses/by/3.0/\r
+\r
+1) Start with the LUFA/Demos/USBtoSerial firmware.\r
+ - rename USBtoSerial.c, USBtoSerial.h, and USBtoSerial.aps to\r
+ AVRISP_Programmer.*\r
+ - edit AVRISP_Programmer.aps and rename all instances of "USBtoSerial" to\r
+ "AVRISP_Programmer"\r
+ - copy AVRISP_Programmer.txt from an older version of AVRISP_Programmer\r
+\r
+2) Edit makefile by changing TARGET from "USBtoSerial" to "AVRISP_Programmer"\r
+\r
+3) Edit AVRISP_Programmer.h:\r
+ - change ifdef _USB_TO_SERIAL_H to _AVRISP_PROGRAMMER_H_\r
+ - rename ReconfigureUSART(void) to ReconfigureSPI(void)\r
+ - add void processHostSPIRequest(void); & void delay_ms(uint8_t dly);\r
+ - replace the define for Serial.h with one for SPI.h:\r
+ #include <libs/LUFA/Drivers/AT90USBXXX/SPI.h>\r
+\r
+4) Make alterations to Descriptors.c\r
+ - change manufacturer string to "www.AVRopendous.org", length=19\r
+ - change product string to "LUFA-Based AVR ISP Programmer", length=29\r
+\r
+5) Edit Ringbuff.h to enable the Peek Command: #define BUFF_USEPEEK\r
+\r
+6) Edit AVRISP_Programmer.c:\r
+ - change #include "USBtoSerial.h" to #include "AVRISP_Programmer.h"\r
+ - change BUTTLOADTAG(ProjName to "LUFA AVR910 ISP Programmer"\r
+ - in main(), rename ReconfigureUSART() to Reconfigure();\r
+ - in EVENT_HANDLER(USB_UnhandledControlPacket), rename ReconfigureUSART\r
+ - delete the ISRs: ISR(USART1_RX_vect) & ISR(USART1_TX_vect)\r
+ - delete ReconfigureUSART(void)\r
+ - add void ReconfigureSPI(void), void processHostSPIRequest(void),\r
+ and void delay_ms(uint8_t dly) from a previous version\r
+ - add Timer1 and SPI initialization code to main():\r
+ /* Hardware Initialization */\r
+ //LEDs_Init();\r
+ DDRB = 0;\r
+ PORTB = 0;\r
+ DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
+ // PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)\r
+ PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
+ DDRD = 0;\r
+ PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin\r
+ // Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)\r
+ DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);\r
+ PORTB |= (1 << PB0);\r
+\r
+ // initialize Timer1 for use in delay function\r
+ TCCR1A = 0;\r
+ //TCCR1B = (1 << CS10); // no prescaling, use CLK\r
+ TCCR1B = ((1 << CS12) | (1 << CS10)); // prescale by CLK/1024\r
+ // 8MHz/1024 = 7813 ticks per second --> ~8 ticks per millisecond (ms)\r
+ timerval = TCNT1; // start timer1\r
+\r
+ - In TASK(CDC_Task) in the\r
+ if (USB_IsConnected) {\r
+ if (Endpoint_ReadWriteAllowed()) {\r
+ while (Endpoint_BytesInEndpoint()) {\r
+ ...\r
+ structure, after Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte()):\r
+\r
+ /* Each time there is an element, check which comand should be\r
+ run and if enough data is available to run that command.\r
+ There are 1-byte, 2-byte, 3-byte, 4-byte commands, and 5-byte commands\r
+ Remember that the "which command" byte counts as 1 */\r
+ if (Rx_Buffer.Elements == 0) {\r
+ // do nothing, wait for data\r
+ } else {\r
+ tempByte = Buffer_PeekElement(&Rx_Buffer); // peek at first element\r
+\r
+ /* make sure the issued command and associated data are all ready */\r
+ if (Rx_Buffer.Elements == 1) { // zero data byte command\r
+ if ((tempByte == 'P') | (tempByte == 'a') | (tempByte == 'm') |\r
+ (tempByte == 'R') | (tempByte == 'd') | (tempByte == 'e') |\r
+ (tempByte == 'L') | (tempByte == 's') | (tempByte == 't') | \r
+ (tempByte == 'S') | (tempByte == 'V') | (tempByte == 'v') |\r
+ (tempByte == 'p') | (tempByte == 'F')) {\r
+ processHostSPIRequest(); // command has enough data, process it\r
+ }\r
+ } else if (Rx_Buffer.Elements == 2) { // one data byte command\r
+ if ((tempByte == 'T') | (tempByte == 'c') | (tempByte == 'C') |\r
+ (tempByte == 'D') | (tempByte == 'l') | (tempByte == 'f') |\r
+ (tempByte == 'x') | (tempByte == 'y')) {\r
+ processHostSPIRequest(); // command has enough data, process it\r
+ }\r
+ } else if (Rx_Buffer.Elements == 3) { // two data byte command\r
+ if ((tempByte == 'A') | (tempByte == 'Z')) {\r
+ processHostSPIRequest(); // command has enough data, process it\r
+ }\r
+ } else if (Rx_Buffer.Elements == 4) { // three data byte command\r
+ if ((tempByte == ':')) {\r
+ processHostSPIRequest(); // command has enough data, process it\r
+ }\r
+ } else if (Rx_Buffer.Elements == 5) { // four data byte command\r
+ if ((tempByte == '.')) {\r
+ processHostSPIRequest(); // command has enough data, process it\r
+ }\r
+ } else {\r
+ // do nothing\r
+ }\r
+ }\r
+\r
+ - need to add code to flush the buffer. Change:\r
+ /* Check if Rx buffer contains data */\r
+ if (Rx_Buffer.Elements)\r
+ {\r
+ /* Initiate the transmission of the buffer contents if USART idle*/\r
+ if (!(Transmitting))\r
+ {\r
+ Transmitting = true;\r
+ Serial_TxByte(Buffer_GetElement(&Rx_Buffer));\r
+ }\r
+ }\r
+ To:\r
+ /* Check if Rx buffer contains data */\r
+ if (Rx_Buffer.Elements)\r
+ {\r
+ /* Initiate the transmission of the buffer contents if USART idle*/\r
+ if (!(Transmitting))\r
+ {\r
+ Transmitting = true;\r
+ /* The following flushes the receive buffer to prepare for new\r
+ data and commands. Need to flush the buffer as the command\r
+ byte which is peeked above needs to be dealt with, otherwise\r
+ the command bytes will overflow the buffer eventually */\r
+ //Buffer_GetElement(&Rx_Buffer); // also works\r
+ Buffer_Initialize(&Rx_Buffer);\r
+ }\r
+ }\r
+\r
+ - need to add the following defines and globals:\r
+ #define RESETPORT PORTB\r
+ #define RESETPIN PB0\r
+ #define RESETPORT2 PORTC\r
+ #define RESETPIN2 PC2\r
+ #define CR_HEX '\r'\r
+\r
+ #define DELAY_VERYSHORT 0x01\r
+ #define DELAY_SHORT 0x02\r
+ #define DELAY_MEDIUM 0x03\r
+ #define DELAY_LONG 0x05\r
+ #define DELAY_MULTIPLE 0x04\r
+\r
+ /* AVR Device Codes - Can have a maximum of 14 but can be any you want.\r
+ Note that these are completely irrelevent. If AVRdude supports a\r
+ device, then that device is programmable. Use -F switch to ignore\r
+ device codes. */\r
+ #define AVRDEVCODE01 0x55 /* ATtiny12 */\r
+ #define AVRDEVCODE02 0x56 /* ATtiny15 */\r
+ #define AVRDEVCODE03 0x5E /* ATtiny261 */\r
+ #define AVRDEVCODE04 0x76 /* ATmega8 */\r
+ #define AVRDEVCODE05 0x74 /* ATmega16 */\r
+ #define AVRDEVCODE06 0x72 /* ATmega32 */\r
+ #define AVRDEVCODE07 0x45 /* ATmega64 */\r
+ #define AVRDEVCODE08 0x74 /* ATmega644 */\r
+ #define AVRDEVCODE09 0x43 /* ATmega128 */\r
+ #define AVRDEVCODE10 0x63 /* ATmega162 */\r
+ #define AVRDEVCODE11 0x78 /* ATmega169 */\r
+ #define AVRDEVCODE12 0x6C /* AT90S4434 */\r
+ #define AVRDEVCODE13 0x38 /* AT90S8515A */\r
+ #define AVRDEVCODE14 0x65 /* AT90S8555 */\r
+\r
+ /* some global variables used throughout */\r
+ uint8_t tempIOreg = 0;\r
+ uint8_t tempIOreg2 = 0;\r
+ uint8_t tempIOreg3 = 0;\r
+ uint8_t tempIOreg4 = 0;\r
+ uint8_t dataWidth = 0;\r
+ uint8_t firstRun = 1;\r
+ uint8_t deviceCode = 0;\r
+ uint8_t tempByte = 0;\r
+ uint16_t currAddress = 0;\r
+ uint16_t timerval = 0;\r
+\r