1 Instructions for converting the LUFA USBtoSerial Demo to an AVR ISP Programmer.
2 By Opendous Inc., Copyright under the Creative Commons Attribution License:
3 http://creativecommons.org/licenses/by/3.0/
5 1) Start with the LUFA/Demos/USBtoSerial firmware.
6 - rename USBtoSerial.c, USBtoSerial.h, and USBtoSerial.aps to
8 - edit AVRISP_Programmer.aps and rename all instances of "USBtoSerial" to
10 - copy AVRISP_Programmer.txt from an older version of AVRISP_Programmer
12 2) Edit makefile by changing TARGET from "USBtoSerial" to "AVRISP_Programmer"
14 3) Edit AVRISP_Programmer.h:
15 - change ifdef _USB_TO_SERIAL_H to _AVRISP_PROGRAMMER_H_
16 - rename ReconfigureUSART(void) to ReconfigureSPI(void)
17 - add void processHostSPIRequest(void); & void delay_ms(uint8_t dly);
18 - replace the define for Serial.h with one for SPI.h:
19 #include <libs/LUFA/Drivers/AT90USBXXX/SPI.h>
21 4) Make alterations to Descriptors.c
22 - change manufacturer string to "www.AVRopendous.org", length=19
23 - change product string to "LUFA-Based AVR ISP Programmer", length=29
25 5) Edit Ringbuff.h to enable the Peek Command: #define BUFF_USEPEEK
27 6) Edit AVRISP_Programmer.c:
28 - change #include "USBtoSerial.h" to #include "AVRISP_Programmer.h"
29 - change BUTTLOADTAG(ProjName to "LUFA AVR910 ISP Programmer"
30 - in main(), rename ReconfigureUSART() to Reconfigure();
31 - in EVENT_HANDLER(USB_UnhandledControlPacket), rename ReconfigureUSART
32 - delete the ISRs: ISR(USART1_RX_vect) & ISR(USART1_TX_vect)
33 - delete ReconfigureUSART(void)
34 - add void ReconfigureSPI(void), void processHostSPIRequest(void),
35 and void delay_ms(uint8_t dly) from a previous version
36 - add Timer1 and SPI initialization code to main():
37 /* Hardware Initialization */
41 DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
42 // PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)
43 PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
45 PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin
46 // Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)
47 DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);
50 // initialize Timer1 for use in delay function
52 //TCCR1B = (1 << CS10); // no prescaling, use CLK
53 TCCR1B = ((1 << CS12) | (1 << CS10)); // prescale by CLK/1024
54 // 8MHz/1024 = 7813 ticks per second --> ~8 ticks per millisecond (ms)
55 timerval = TCNT1; // start timer1
57 - In TASK(CDC_Task) in the
58 if (USB_IsConnected) {
59 if (Endpoint_ReadWriteAllowed()) {
60 while (Endpoint_BytesInEndpoint()) {
62 structure, after Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte()):
64 /* Each time there is an element, check which comand should be
65 run and if enough data is available to run that command.
66 There are 1-byte, 2-byte, 3-byte, 4-byte commands, and 5-byte commands
67 Remember that the "which command" byte counts as 1 */
68 if (Rx_Buffer.Elements == 0) {
69 // do nothing, wait for data
71 tempByte = Buffer_PeekElement(&Rx_Buffer); // peek at first element
73 /* make sure the issued command and associated data are all ready */
74 if (Rx_Buffer.Elements == 1) { // zero data byte command
75 if ((tempByte == 'P') | (tempByte == 'a') | (tempByte == 'm') |
76 (tempByte == 'R') | (tempByte == 'd') | (tempByte == 'e') |
77 (tempByte == 'L') | (tempByte == 's') | (tempByte == 't') |
78 (tempByte == 'S') | (tempByte == 'V') | (tempByte == 'v') |
79 (tempByte == 'p') | (tempByte == 'F')) {
80 processHostSPIRequest(); // command has enough data, process it
82 } else if (Rx_Buffer.Elements == 2) { // one data byte command
83 if ((tempByte == 'T') | (tempByte == 'c') | (tempByte == 'C') |
84 (tempByte == 'D') | (tempByte == 'l') | (tempByte == 'f') |
85 (tempByte == 'x') | (tempByte == 'y')) {
86 processHostSPIRequest(); // command has enough data, process it
88 } else if (Rx_Buffer.Elements == 3) { // two data byte command
89 if ((tempByte == 'A') | (tempByte == 'Z')) {
90 processHostSPIRequest(); // command has enough data, process it
92 } else if (Rx_Buffer.Elements == 4) { // three data byte command
93 if ((tempByte == ':')) {
94 processHostSPIRequest(); // command has enough data, process it
96 } else if (Rx_Buffer.Elements == 5) { // four data byte command
97 if ((tempByte == '.')) {
98 processHostSPIRequest(); // command has enough data, process it
105 - need to add code to flush the buffer. Change:
106 /* Check if Rx buffer contains data */
107 if (Rx_Buffer.Elements)
109 /* Initiate the transmission of the buffer contents if USART idle*/
113 Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
117 /* Check if Rx buffer contains data */
118 if (Rx_Buffer.Elements)
120 /* Initiate the transmission of the buffer contents if USART idle*/
124 /* The following flushes the receive buffer to prepare for new
125 data and commands. Need to flush the buffer as the command
126 byte which is peeked above needs to be dealt with, otherwise
127 the command bytes will overflow the buffer eventually */
128 //Buffer_GetElement(&Rx_Buffer); // also works
129 Buffer_Initialize(&Rx_Buffer);
133 - need to add the following defines and globals:
134 #define RESETPORT PORTB
136 #define RESETPORT2 PORTC
137 #define RESETPIN2 PC2
140 #define DELAY_VERYSHORT 0x01
141 #define DELAY_SHORT 0x02
142 #define DELAY_MEDIUM 0x03
143 #define DELAY_LONG 0x05
144 #define DELAY_MULTIPLE 0x04
146 /* AVR Device Codes - Can have a maximum of 14 but can be any you want.
147 Note that these are completely irrelevent. If AVRdude supports a
148 device, then that device is programmable. Use -F switch to ignore
150 #define AVRDEVCODE01 0x55 /* ATtiny12 */
151 #define AVRDEVCODE02 0x56 /* ATtiny15 */
152 #define AVRDEVCODE03 0x5E /* ATtiny261 */
153 #define AVRDEVCODE04 0x76 /* ATmega8 */
154 #define AVRDEVCODE05 0x74 /* ATmega16 */
155 #define AVRDEVCODE06 0x72 /* ATmega32 */
156 #define AVRDEVCODE07 0x45 /* ATmega64 */
157 #define AVRDEVCODE08 0x74 /* ATmega644 */
158 #define AVRDEVCODE09 0x43 /* ATmega128 */
159 #define AVRDEVCODE10 0x63 /* ATmega162 */
160 #define AVRDEVCODE11 0x78 /* ATmega169 */
161 #define AVRDEVCODE12 0x6C /* AT90S4434 */
162 #define AVRDEVCODE13 0x38 /* AT90S8515A */
163 #define AVRDEVCODE14 0x65 /* AT90S8555 */
165 /* some global variables used throughout */
166 uint8_t tempIOreg = 0;
167 uint8_t tempIOreg2 = 0;
168 uint8_t tempIOreg3 = 0;
169 uint8_t tempIOreg4 = 0;
170 uint8_t dataWidth = 0;
171 uint8_t firstRun = 1;
172 uint8_t deviceCode = 0;
173 uint8_t tempByte = 0;
174 uint16_t currAddress = 0;
175 uint16_t timerval = 0;