aboutsummaryrefslogtreecommitdiffstats
path: root/Projects/AVRISP_Programmer/AVRISP_Programmer.c
diff options
context:
space:
mode:
Diffstat (limited to 'Projects/AVRISP_Programmer/AVRISP_Programmer.c')
-rw-r--r--Projects/AVRISP_Programmer/AVRISP_Programmer.c763
1 files changed, 0 insertions, 763 deletions
diff --git a/Projects/AVRISP_Programmer/AVRISP_Programmer.c b/Projects/AVRISP_Programmer/AVRISP_Programmer.c
deleted file mode 100644
index 58593670e..000000000
--- a/Projects/AVRISP_Programmer/AVRISP_Programmer.c
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- LUFA Library
- Copyright (C) Dean Camera, 2009.
-
- dean [at] fourwalledcubicle [dot] com
- www.fourwalledcubicle.com
-*/
-
-/*
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
- AVR ISP Programmer code Copyright 2009 Opendous Inc. (www.opendous.org)
- For more info and usage instructions for this firmware, visit:
- http://code.google.com/p/avropendous/wiki/AVR_ISP_Programmer
-
- Note that this firmware is designed to work with AVRdude:
- http://savannah.nongnu.org/projects/avrdude
- But should work with other software that supports the AVR910 ISP
- programmer or STK200 hardware.
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the name of the author not be used in
- advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- The author disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall the author be liable for any
- special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
-*/
-
-/*
- Usage:
- avrdude -vv -F -P COM7 -c avr910 -p t261
- Note -F flag which overrides signature check and enables programming
- of any "In-System Programmable via SPI Port" AVR MCU. Part number,
- t261, should be set to your target device.
- avrdude -vv -F -P COM7 -c avr910 -p t261 -U flash:w:PROG.hex
- PROG.hex is the hex file to program your t261 AVR with
- avrdude -vv -F -P COM7 -b 115200 -c avr910 -p t261 -U flash:w:test.hex
- The -b 115200 sets the SPI clock to 62.5kHz from the default 125kHz and may
- work when the default programming speed fails.
- AVROSP.exe -dATtiny261 -cCOM7 -rf
- AVRosp is the Open Source AVR ISP Programming Software available from Atmel.com
-
- Note: on Linux systems, COM7 should be replaced with someting like /dev/ttyACM0
- You can determine this value by running dmesg after plugging in the device
- Note: you must RESET the programmer after each use (AVRdude session).
-
- Note: If you experience errors with older devices, try changing the DELAY defines
-
- MISO, MOSI, and SCK are connected directly from the AVRopendous board
- to the pin of the same functionality on the target. RESET pin on the target
- can be connected either to SS (PB0), or PC2. Do not have any other pins
- connected - especially HWB pin, to avoid unintentional behaviour.
-
- AVR910 functionality was overlayed on USBtoSerial functionality.
- Keep this in mind when looking over the code.
- Default target speed is 125kHz and corresponds to 19200 baud, which
- is the default setting for AVRdude.
-
- Changing "Baud-Rate" will change the SPI speed. Defualt SPI clock speed
- is 8Mhz / 4 = 2MHz. 8Mhz is the device clock speed. This is the setting at
- 9600 baud. The following is a table of baud-rate vs. SPI Speed that will result
- 9600 = 2Mhz
- 14400 = 1MHz
- 19200 = 125kHz (AVRdude Default)
- 38400 = 250kHz
- 57600 = 500kHz
- 115200 = 62.5kHz
-
- Before running, you will need to install the INF file that
- is located in the project directory. This will enable
- Windows to use its inbuilt CDC drivers, negating the need
- for special Windows drivers for the device. To install,
- right-click the .INF file and choose the Install option.
-*/
-
-/* TODO: - fix the requirement that a RESET must be performed after each session, which
- is only an issue under Windows. Everything works fine under Linux
-*/
-
-#include "AVRISP_Programmer.h"
-
-/* Project Tags, for reading out using the ButtLoad project */
-BUTTLOADTAG(ProjName, "LUFA AVR910 ISP Programmer");
-BUTTLOADTAG(BuildTime, __TIME__);
-BUTTLOADTAG(BuildDate, __DATE__);
-BUTTLOADTAG(LUFAVersion, "LUFA V" LUFA_VERSION_STRING);
-
-
-#define RESETPORT PORTB
-#define RESETPIN PB0
-#define RESETPORT2 PORTC
-#define RESETPIN2 PC2
-#define CR_HEX '\r'
-
-#define DELAY_VERYSHORT 0x01
-#define DELAY_SHORT 0x02
-#define DELAY_MEDIUM 0x03
-#define DELAY_LONG 0x05
-#define DELAY_MULTIPLE 0x02
-
-
-/* AVR Device Codes - Can have a maximum of 14 but can be any you want.
- Note that these are completely irrelevent. If AVRdude supports a device,
- then that device is programmable. Use -F switch to ignore device codes. */
-#define AVRDEVCODE01 0x55 /* ATtiny12 */
-#define AVRDEVCODE02 0x56 /* ATtiny15 */
-#define AVRDEVCODE03 0x5E /* ATtiny261 */
-#define AVRDEVCODE04 0x76 /* ATmega8 */
-#define AVRDEVCODE05 0x74 /* ATmega16 */
-#define AVRDEVCODE06 0x72 /* ATmega32 */
-#define AVRDEVCODE07 0x45 /* ATmega64 */
-#define AVRDEVCODE08 0x74 /* ATmega644 */
-#define AVRDEVCODE09 0x43 /* ATmega128 */
-#define AVRDEVCODE10 0x63 /* ATmega162 */
-#define AVRDEVCODE11 0x78 /* ATmega169 */
-#define AVRDEVCODE12 0x6C /* AT90S4434 */
-#define AVRDEVCODE13 0x38 /* AT90S8515A */
-#define AVRDEVCODE14 0x65 /* AT90S8555 */
-
-
-/* Scheduler Task List */
-TASK_LIST
-{
- { Task: USB_USBTask , TaskStatus: TASK_STOP },
- { Task: CDC_Task , TaskStatus: TASK_STOP },
-};
-
-/* Globals: */
-/** Contains the current baud rate and other settings of the virtual serial port.
- *
- These values are set by the host via a class-specific request, and the physical USART should be reconfigured to match the
- new settings each time they are changed by the host.
- */
-CDC_Line_Coding_t LineCoding = { BaudRateBPS: 9600,
- CharFormat: OneStopBit,
- ParityType: Parity_None,
- DataBits: 8 };
-
-/** Ring (circular) buffer to hold the RX data - data from the host to the attached device on the serial port. */
-RingBuff_t Rx_Buffer;
-
-/** Ring (circular) buffer to hold the TX data - data from the attached device on the serial port to the host. */
-RingBuff_t Tx_Buffer;
-
-/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */
-volatile bool Transmitting = false;
-
-/* some global variables used throughout */
-uint16_t currAddress = 0;
-
-/** Main program entry point. This routine configures the hardware required by the application, then
- starts the scheduler to run the application tasks.
- */
-int main(void)
-{
- /* Disable watchdog if enabled by bootloader/fuses */
- MCUSR &= ~(1 << WDRF);
- wdt_disable();
-
- /* Disable clock division */
- clock_prescale_set(clock_div_1);
-
- /* Hardware Initialization */
- LEDs_Init();
- ReconfigureSPI();
-
- DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
- // PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)
- PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
- DDRD = 0;
- PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin
- // Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)
- DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);
- PORTB |= (1 << PB0);
- // make sure DataFlash devices to not interfere - deselect them by setting PE0 and PE1 HIGH:
- PORTE = 0xFF;
- DDRE = 0xFF;
-
- /* Ringbuffer Initialization */
- Buffer_Initialize(&Rx_Buffer);
- Buffer_Initialize(&Tx_Buffer);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-
- /* Initialize Scheduler so that it can be used */
- Scheduler_Init();
-
- /* Initialize USB Subsystem */
- USB_Init();
-
- /* Scheduling - routine never returns, so put this last in the main function */
- Scheduler_Start();
-}
-
-/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
- starts the library USB task to begin the enumeration and USB management process.
- */
-EVENT_HANDLER(USB_Connect)
-{
- /* Start USB management task */
- Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
-
- /* Indicate USB enumerating */
- UpdateStatus(Status_USBEnumerating);
-}
-
-/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
- the status LEDs and stops the USB management and CDC management tasks.
- */
-EVENT_HANDLER(USB_Disconnect)
-{
- /* Stop running CDC and USB management tasks */
- Scheduler_SetTaskMode(CDC_Task, TASK_STOP);
- Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
-
- /* Indicate USB not ready */
- UpdateStatus(Status_USBNotReady);
-}
-
-/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
- of the USB device after enumeration - the device endpoints are configured and the CDC management task started.
- */
-EVENT_HANDLER(USB_ConfigurationChanged)
-{
- /* Setup CDC Notification, Rx and Tx Endpoints */
- Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
- ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
- ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
- ENDPOINT_BANK_SINGLE);
-
- /* Indicate USB connected and ready */
- UpdateStatus(Status_USBReady);
-
- /* Start CDC task */
- Scheduler_SetTaskMode(CDC_Task, TASK_RUN);
-}
-
-/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
- control requests that are not handled internally by the USB library (including the CDC control commands,
- which are all issued via the control endpoint), so that they can be handled appropriately for the application.
- */
-EVENT_HANDLER(USB_UnhandledControlPacket)
-{
- uint8_t* LineCodingData = (uint8_t*)&LineCoding;
-
- /* Process CDC specific control requests */
- switch (bRequest)
- {
- case REQ_GetLineEncoding:
- if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSetupReceived();
-
- /* Write the line coding data to the control endpoint */
- Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
-
- /* Finalize the stream transfer to send the last packet or clear the host abort */
- Endpoint_ClearSetupOUT();
- }
-
- break;
- case REQ_SetLineEncoding:
- if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSetupReceived();
-
- /* Read the line coding data in from the host into the global struct */
- Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
-
- /* Finalize the stream transfer to clear the last packet from the host */
- Endpoint_ClearSetupIN();
-
- /* Reconfigure the USART with the new settings */
- ReconfigureSPI();
- }
-
- break;
- case REQ_SetControlLineState:
- if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
- {
- /* Acknowledge the SETUP packet, ready for data transfer */
- Endpoint_ClearSetupReceived();
-
- /* Acknowledge status stage */
- while (!(Endpoint_IsSetupINReady()));
- Endpoint_ClearSetupIN();
- }
-
- break;
- }
-}
-
-/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */
-TASK(CDC_Task)
-{
- if (USB_IsConnected)
- {
- /* Select the Serial Rx Endpoint */
- Endpoint_SelectEndpoint(CDC_RX_EPNUM);
-
- if (Endpoint_ReadWriteAllowed())
- {
- /* Read the received data endpoint into the transmission buffer */
- while (Endpoint_BytesInEndpoint())
- {
- /* Wait until the buffer has space for a new character */
- while (!((BUFF_STATICSIZE - Rx_Buffer.Elements)));
-
- /* Store each character from the endpoint */
- Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
-
- /* Run the given command once enough data is available. */
- if (Rx_Buffer.Elements)
- {
- const uint8_t ZeroDataByteCommands[] = {'P', 'a', 'm', 'R', 'd', 'e', 'L', 's', 't', 'S', 'V', 'v', 'p', 'F'};
- const uint8_t OneDataByteCommands[] = {'T', 'c', 'C', 'D', 'l', 'f', 'x', 'y'};
- const uint8_t TwoDataByteCommands[] = {'A', 'Z'};
- const uint8_t ThreeDataByteCommands[] = {':'};
- const uint8_t FourDataByteCommands[] = {'.'};
-
- const struct
- {
- const uint8_t TotalCommands;
- const uint8_t* CommandBytes;
- } AVR910Commands[] = {{sizeof(ZeroDataByteCommands), ZeroDataByteCommands},
- {sizeof(OneDataByteCommands), OneDataByteCommands},
- {sizeof(TwoDataByteCommands), TwoDataByteCommands},
- {sizeof(ThreeDataByteCommands), ThreeDataByteCommands},
- {sizeof(FourDataByteCommands), FourDataByteCommands}};
-
- /* Determine the data length of the issued command */
- uint8_t CommandDataLength = (Rx_Buffer.Elements - 1);
-
- /* Loop through each of the possible command bytes allowable from the given command data length */
- for (uint8_t CurrentCommand = 0; CurrentCommand < AVR910Commands[CommandDataLength].TotalCommands; CurrentCommand++)
- {
- /* If issues command matches an allowable command, process it */
- if (Buffer_PeekElement(&Rx_Buffer) == AVR910Commands[CommandDataLength].CommandBytes[CurrentCommand])
- processHostSPIRequest();
- }
- }
- }
-
- /* Clear the endpoint buffer */
- Endpoint_ClearCurrentBank();
- }
-
- /* Select the Serial Tx Endpoint */
- Endpoint_SelectEndpoint(CDC_TX_EPNUM);
-
- /* Check if the Tx buffer contains anything to be sent to the host */
- if (Tx_Buffer.Elements)
- {
- /* Wait until Serial Tx Endpoint Ready for Read/Write */
- while (!(Endpoint_ReadWriteAllowed()));
-
- /* Check before sending the data if the endpoint is completely full */
- bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
-
- /* Write the transmission buffer contents to the received data endpoint */
- while (Tx_Buffer.Elements && (Endpoint_BytesInEndpoint() < CDC_TXRX_EPSIZE))
- Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
-
- /* Send the data */
- Endpoint_ClearCurrentBank();
-
- /* If a full endpoint was sent, we need to send an empty packet afterwards to terminate the transfer */
- if (IsFull)
- {
- /* Wait until Serial Tx Endpoint Ready for Read/Write */
- while (!(Endpoint_ReadWriteAllowed()));
-
- /* Send an empty packet to terminate the transfer */
- Endpoint_ClearCurrentBank();
- }
- }
- }
-}
-
-/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
- * log to a serial port, or anything else that is suitable for status updates.
- *
- * \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum
- */
-void UpdateStatus(uint8_t CurrentStatus)
-{
- uint8_t LEDMask = LEDS_NO_LEDS;
-
- /* Set the LED mask to the appropriate LED mask based on the given status code */
- switch (CurrentStatus)
- {
- case Status_USBNotReady:
- LEDMask = (LEDS_LED1);
- break;
- case Status_USBEnumerating:
- LEDMask = (LEDS_LED1 | LEDS_LED2);
- break;
- case Status_USBReady:
- LEDMask = (LEDS_LED2 | LEDS_LED4);
- break;
- }
-
- /* Set the board LEDs to the new LED mask */
- LEDs_SetAllLEDs(LEDMask);
-}
-
-/** Reconfigures SPI to match the current serial port settings issued by the host. */
-void ReconfigureSPI(void)
-{
- uint8_t SPCRmask = (1 << SPE) | (1 << MSTR); // always enable SPI as Master
- uint8_t SPSRmask = 0;
-
- /* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */
- /* For SPI, determine whether format is LSB or MSB */
- if (LineCoding.CharFormat == TwoStopBits) {
- SPCRmask |= (1 << DORD);
- } else if (LineCoding.CharFormat == OneStopBit) {
- SPCRmask |= (0 << DORD);
- }
-
- /* Determine data size - 5, 6, 7, or 8 bits are supported */
- /* Changing line coding changes SPI Mode
- CPOL=0, CPHA=0 Sample (Rising) Setup (Falling) SPI-Mode0 == 8 bits line coding
- CPOL=0, CPHA=1 Setup (Rising) Sample (Falling) SPI-Mode1 == 7 bits line coding
- CPOL=1, CPHA=0 Sample (Falling) Setup (Rising) SPI-Mode2 == 6 bits line coding
- CPOL=1, CPHA=1 Setup (Falling) Sample (Rising) SPI-Mode3 == 5 bits line coding
- */
- if (LineCoding.DataBits == 5) {
- SPCRmask |= ((1 << CPOL) | (1 << CPHA));
- } else if (LineCoding.DataBits == 6) {
- SPCRmask |= ((1 << CPOL) | (0 << CPHA));
- } else if (LineCoding.DataBits == 7) {
- SPCRmask |= ((0 << CPOL) | (1 << CPHA));
- } else if (LineCoding.DataBits == 8) {
- SPCRmask |= ((0 << CPOL) | (0 << CPHA));
- }
-
-
- /* Set the USART baud rate register to the desired baud rate value */
- /* also alter the SPI speed via value of baud rate */
- if (LineCoding.BaudRateBPS == 9600) { // 2Mhz SPI (Fosc / 4)
- SPCRmask |= ((0 << SPR1) | (0 << SPR0));
- SPSRmask |= (0 << SPI2X);
- } else if (LineCoding.BaudRateBPS == 14400) { // 1Mhz SPI (Fosc / 8)
- SPCRmask |= ((0 << SPR1) | (1 << SPR0));
- SPSRmask |= (1 << SPI2X);
- } else if (LineCoding.BaudRateBPS == 57600) { // 500kHz SPI (Fosc / 16)
- SPCRmask |= ((0 << SPR1) | (1 << SPR0));
- SPSRmask |= (0 << SPI2X);
- } else if (LineCoding.BaudRateBPS == 38400) { // 250kHz SPI (Fosc / 32)
- SPCRmask |= ((1 << SPR1) | (0 << SPR0));
- SPSRmask |= (1 << SPI2X);
- } else if (LineCoding.BaudRateBPS == 19200) { // 125kHz SPI (Fosc / 64)
- SPCRmask |= ((1 << SPR1) | (0 << SPR0));
- SPSRmask |= (0 << SPI2X);
- } else if (LineCoding.BaudRateBPS == 115200) { // 62.5kHz SPI (Fosc / 128)
- SPCRmask |= ((1 << SPR1) | (1 << SPR0));
- SPSRmask |= (0 << SPI2X);
- }
-
- SPCR = SPCRmask;
- SPSR = SPSRmask;
-}
-
-
-/* process data according to AVR910 protocol */
-void processHostSPIRequest(void) {
-
- uint8_t readByte1 = 0;
- uint8_t readByte2 = 0;
- uint8_t readByte3 = 0;
- uint8_t readByte4 = 0;
- uint8_t firstByte = 0;
-
- /* Taken from a90isp_ver23.asm:
- +-------------+------------+------+
- ;* Commands | Host writes | Host reads | |
- ;* -------- +-----+-------+------+-----+ |
- ;* | ID | data | data | | Note |
- ;* +-----------------------------------+-----+-------+------+-----+------+
- ;* | Enter programming mode | 'P' | | | 13d | 1 |
- ;* | Report autoincrement address | 'a' | | | 'Y' | |
- ;* | Set address | 'A' | ah al | | 13d | 2 |
- ;* | Write program memory, low byte | 'c' | dd | | 13d | 3 |
- ;* | Write program memory, high byte | 'C' | dd | | 13d | 3 |
- ;* | Issue Page Write | 'm' | | | 13d | |
- ;* | Read program memory | 'R' | |dd(dd)| | 4 |
- ;* | Write data memory | 'D' | dd | | 13d | |
- ;* | Read data memory | 'd' | | dd | | |
- ;* | Chip erase | 'e' | | | 13d | |
- ;* | Write lock bits | 'l' | dd | | 13d | |
- ;* | Write fuse bits | 'f' | dd | | 13d | 11 |
- ;* | Read fuse and lock bits | 'F' | | dd | | 11 |
- ;* | Leave programming mode | 'L' | | | 13d | 5 |
- ;* | Select device type | 'T' | dd | | 13d | 6 |
- ;* | Read signature bytes | 's' | | 3*dd | | |
- ;* | Return supported device codes | 't' | | n*dd | 00d | 7 |
- ;* | Return software identifier | 'S' | | s[7] | | 8 |
- ;* | Return sofware version | 'V' | |dd dd | | 9 |
- ;* | Return hardware version | 'v' | |dd dd | | 9 |
- ;* | Return programmer type | 'p' | | dd | | 10 |
- ;* | Set LED | 'x' | dd | | 13d | 12 |
- ;* | Clear LED | 'y' | dd | | 13d | 12 |
- ;* | Universial command | ':' | 3*dd | dd | 13d | |
- ;* | New universal command | '.' | 4*dd | dd | 13d | |
- ;* | Special test command | 'Z' | 2*dd | dd | | |
- */
-
- firstByte = Buffer_GetElement(&Rx_Buffer);
- Buffer_Initialize(&Tx_Buffer); // make sure the buffer is clear before proceeding
-
- if (firstByte == 'P') { // enter Programming mode
- // enable SPI -- already done
- // enter programming mode on target:
- //PORTB = 0; // set clock to zero
- RESETPORT = (1 << RESETPIN); // set RESET pin on target to 1
- RESETPORT2 = (1 << RESETPIN2);
- _delay_ms(DELAY_SHORT);
- //RESETPORT = (RESETPORT & ~(1 << RESETPIN)); // set RESET pin on target to 0 - Active
- RESETPORT = 0x00;
- RESETPORT2 = 0;
- _delay_ms(DELAY_SHORT);
- SPI_SendByte(0xAC);
- SPI_SendByte(0x53);
- SPI_SendByte(0x00);
- SPI_SendByte(0x00);
- _delay_ms(DELAY_VERYSHORT);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'T') { // Select device type
- Buffer_GetElement(&Rx_Buffer); // set device type
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'a') { // Report autoincrement address
- Buffer_StoreElement(&Tx_Buffer, 'Y'); // return 'Y' - Auto-increment enabled
-
- } else if (firstByte == 'A') { //Load Address
- // get two bytes over serial and set currAddress to them
- readByte1 = Buffer_GetElement(&Rx_Buffer); // high byte
- readByte2 = Buffer_GetElement(&Rx_Buffer); // low byte
- currAddress = (readByte1 << 8) | (readByte2);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'c') { // Write program memory, low byte
- // send 4 bytes over SPI; 0x40, then Address High Byte, then Low, then data
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- SPI_SendByte(0x40);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- SPI_SendByte(readByte1); // data
- _delay_ms(DELAY_MEDIUM); // certain MCUs require a delay of about 24585 cycles
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'C') { // Write program memory, high byte
- // send 4 bytes over SPI; 0x48, then Address High Byte, then Low, then data
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- SPI_SendByte(0x48);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- SPI_SendByte(readByte1); // data
- currAddress++; // increment currAddress
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'm') { // Write Program Memory Page
- // send 4 bytes over SPI; 0x4c, then Address High Byte, then Low, then 0x00
- SPI_SendByte(0x4C);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- SPI_SendByte(0x00);
- _delay_ms(DELAY_LONG);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'R') { // Read Program Memory
- // send 4 bytes over SPI; 0x28, then Address High Byte, then Low, then send back read data from 4th byte over serial
- SPI_SendByte(0x28);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- readByte1 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- // send 4 bytes over SPI; 0x20, then Address High Byte, then Low, then send back read data from 4th byte over serial
- SPI_SendByte(0x20);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- readByte2 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte2);
- currAddress++; // increment currAddress
-
- } else if (firstByte == 'D') { // Write Data Memory
- // send 4 bytes over SPI; 0xc0, then Address High Byte, then Low, then data
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- SPI_SendByte(0xC0);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- SPI_SendByte(readByte1); // data
- _delay_ms(DELAY_MEDIUM);
- currAddress++; // increment currAddress
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'd') { // Read Data Memory
- // send 4 bytes over SPI; 0xa0, then Address High Byte, then Low, then send back read data from 4th byte over serial
- SPI_SendByte(0xA0);
- SPI_SendByte((currAddress >> 8)); // high byte
- SPI_SendByte((currAddress)); // low byte
- readByte1 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- currAddress++; // increment currAddress
-
- } else if (firstByte == 'e') { // erase the target device
- // send 4 bytes over SPI; 0xac, 0x80, 0x04, 0x00
- SPI_SendByte(0xAC);
- SPI_SendByte(0x80);
- SPI_SendByte(0x04);
- SPI_SendByte(0x00);
- _delay_ms(DELAY_LONG);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'l') { // write lock bits
- // send 4 bytes over SPI; 0xac, [andi s_data 0x06], 0xe0, 0x00
- readByte1 = Buffer_GetElement(&Rx_Buffer); // read in lock bits data
- SPI_SendByte(0xAC);
- SPI_SendByte(((0x06 & readByte1) | 0xE0)); // TODO - is this correct???
- SPI_SendByte(0x00);
- SPI_SendByte(0x00);
- _delay_ms(DELAY_MEDIUM);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'f') { // write fuse bits
- // ignore this command, but need to remove data from the receive buffer
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'L') { // leave programming mode
- RESETPORT |= (1 << RESETPIN); // set RESET pin on target to 1
- RESETPORT2 |= (1 << RESETPIN2); // set RESET pin on target to 1
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 's') { // Read signature bytes
- // send 4 bytes over SPI; 0x30, 0x00, 0x02, read and send last byte over serial
- SPI_SendByte(0x30);
- SPI_SendByte(0x00);
- SPI_SendByte(0x02);
- readByte1 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- SPI_SendByte(0x30);
- SPI_SendByte(0x00);
- SPI_SendByte(0x01);
- readByte1 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- SPI_SendByte(0x30);
- SPI_SendByte(0x00);
- SPI_SendByte(0x00);
- readByte1 = SPI_TransferByte(0x00); // read in data
- Buffer_StoreElement(&Tx_Buffer, readByte1);
-
- } else if (firstByte == 't') { // Return supported device codes
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE01);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE02);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE03);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE04);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE05);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE06);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE07);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE08);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE09);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE10);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE11);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE12);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE13);
- Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE14);
- Buffer_StoreElement(&Tx_Buffer, 0x00);
-
- } else if (firstByte == 'S') { // Return software identifier
- // return string[7] with "AVR ISP"
- Buffer_StoreElement(&Tx_Buffer, 'A');
- Buffer_StoreElement(&Tx_Buffer, 'V');
- Buffer_StoreElement(&Tx_Buffer, 'R');
- Buffer_StoreElement(&Tx_Buffer, 0x20);
- Buffer_StoreElement(&Tx_Buffer, 'I');
- Buffer_StoreElement(&Tx_Buffer, 'S');
- Buffer_StoreElement(&Tx_Buffer, 'P');
-
- } else if (firstByte == 'V') { // Return sofware version
- //return two bytes, software Major then Minor
- Buffer_StoreElement(&Tx_Buffer, '2');
- Buffer_StoreElement(&Tx_Buffer, '3');
-
- } else if (firstByte == 'v') { // Return hardware version
- //return two bytes, hardware Major then Minor
- Buffer_StoreElement(&Tx_Buffer, ('1'));
- Buffer_StoreElement(&Tx_Buffer, ('0'));
-
- } else if (firstByte == 'p') { // Return programmer type
- // return 'S' for Serial Programmer
- Buffer_StoreElement(&Tx_Buffer, 'S');
-
- } else if (firstByte == 'x') { // set LED
- // ignore this command, but need to remove data from the receive buffer
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'y') { // clear LED
- // ignore this command, but need to remove data from the receive buffer
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == ':') { // Universal Command
- // get 3 bytes over serial
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- readByte2 = Buffer_GetElement(&Rx_Buffer);
- readByte3 = Buffer_GetElement(&Rx_Buffer);
- SPI_SendByte(readByte1);
- SPI_SendByte(readByte2);
- SPI_SendByte(readByte3);
- readByte1 = SPI_TransferByte(0x00);
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- _delay_ms(DELAY_MEDIUM);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == '.') { // New Universal Command
- // get 4 bytes over serial
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- readByte2 = Buffer_GetElement(&Rx_Buffer);
- readByte3 = Buffer_GetElement(&Rx_Buffer);
- readByte4 = Buffer_GetElement(&Rx_Buffer);
- SPI_SendByte(readByte1);
- SPI_SendByte(readByte2);
- SPI_SendByte(readByte3);
- readByte1 = SPI_TransferByte(readByte4);
- Buffer_StoreElement(&Tx_Buffer, readByte1);
- _delay_ms(DELAY_MEDIUM);
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
-
- } else if (firstByte == 'Z') { // Special test command
- // do nothing, but need to remove data from the receive buffer
- readByte1 = Buffer_GetElement(&Rx_Buffer);
- readByte2 = Buffer_GetElement(&Rx_Buffer);
-
- } else {
- // do nothing, but need to return with a carriage return
- Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
- }
-}
-