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;