/*
- isp.c - part of USBasp
-
- Autor..........: Thomas Fischl <tfischl@gmx.de>
- Description....: Provides functions for communication/programming
- over ISP interface
- Licence........: GNU GPL v2 (see Readme.txt)
- Creation Date..: 2005-02-23
- Last change....: 2007-07-23
-*/
+ * isp.c - part of USBasp
+ *
+ * Autor..........: Thomas Fischl <tfischl@gmx.de>
+ * Description....: Provides functions for communication/programming
+ * over ISP interface
+ * Licence........: GNU GPL v2 (see Readme.txt)
+ * Creation Date..: 2005-02-23
+ * Last change....: 2009-02-28
+ */
#include <avr/io.h>
#include "isp.h"
#include "clock.h"
+#include "usbasp.h"
#define spiHWdisable() SPCR = 0
-void spiHWenable() {
+uchar sck_sw_delay;
+uchar sck_spcr;
+uchar sck_spsr;
- /* enable SPI, master, 375kHz SCK */
- SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
- SPSR = (1 << SPI2X);
+void spiHWenable() {
+ SPCR = sck_spcr;
+ SPSR = sck_spsr;
}
void ispSetSCKOption(uchar option) {
- if (option == 0) {
-
- /* use software spi */
- ispTransmit = ispTransmit_sw;
- // spiHWdisable();
-
- } else {
-
- /* use hardware spi */
- ispTransmit = ispTransmit_hw;
-
- }
+ if (option == USBASP_ISP_SCK_AUTO)
+ option = USBASP_ISP_SCK_375;
+
+ if (option >= USBASP_ISP_SCK_93_75) {
+ ispTransmit = ispTransmit_hw;
+ sck_spsr = 0;
+
+ switch (option) {
+
+ case USBASP_ISP_SCK_1500:
+ /* enable SPI, master, 1.5MHz, XTAL/8 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+ sck_spsr = (1 << SPI2X);
+ case USBASP_ISP_SCK_750:
+ /* enable SPI, master, 750kHz, XTAL/16 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+ break;
+ case USBASP_ISP_SCK_375:
+ default:
+ /* enable SPI, master, 375kHz, XTAL/32 (default) */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+ sck_spsr = (1 << SPI2X);
+ break;
+ case USBASP_ISP_SCK_187_5:
+ /* enable SPI, master, 187.5kHz XTAL/64 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+ break;
+ case USBASP_ISP_SCK_93_75:
+ /* enable SPI, master, 93.75kHz XTAL/128 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+ break;
+ }
+
+ } else {
+ ispTransmit = ispTransmit_sw;
+ switch (option) {
+
+ case USBASP_ISP_SCK_32:
+ sck_sw_delay = 3;
+
+ break;
+ case USBASP_ISP_SCK_16:
+ sck_sw_delay = 6;
+
+ break;
+ case USBASP_ISP_SCK_8:
+ sck_sw_delay = 12;
+
+ break;
+ case USBASP_ISP_SCK_4:
+ sck_sw_delay = 24;
+
+ break;
+ case USBASP_ISP_SCK_2:
+ sck_sw_delay = 48;
+
+ break;
+ case USBASP_ISP_SCK_1:
+ sck_sw_delay = 96;
+
+ break;
+ case USBASP_ISP_SCK_0_5:
+ sck_sw_delay = 192;
+
+ break;
+ }
+ }
}
void ispDelay() {
- uint8_t starttime = TIMERVALUE;
- while ((uint8_t) (TIMERVALUE - starttime) < 12) { }
+ uint8_t starttime = TIMERVALUE;
+ while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) {
+ }
}
void ispConnect() {
- /* all ISP pins are inputs before */
- /* now set output pins */
- ISP_DDR |= (1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI);
+ /* all ISP pins are inputs before */
+ /* now set output pins */
+ ISP_DDR |= (1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI);
- /* reset device */
- ISP_OUT &= ~(1 << ISP_RST); /* RST low */
- ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
+ /* reset device */
+ ISP_OUT &= ~(1 << ISP_RST); /* RST low */
+ ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
- /* positive reset pulse > 2 SCK (target) */
- ispDelay();
- ISP_OUT |= (1 << ISP_RST); /* RST high */
- ispDelay();
- ISP_OUT &= ~(1 << ISP_RST); /* RST low */
+ /* positive reset pulse > 2 SCK (target) */
+ ispDelay();
+ ISP_OUT |= (1 << ISP_RST); /* RST high */
+ ispDelay();
+ ISP_OUT &= ~(1 << ISP_RST); /* RST low */
- if (ispTransmit == ispTransmit_hw) {
- spiHWenable();
- }
+ if (ispTransmit == ispTransmit_hw) {
+ spiHWenable();
+ }
}
void ispDisconnect() {
- /* set all ISP pins inputs */
- ISP_DDR &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI));
- /* switch pullups off */
- ISP_OUT &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI));
+ /* set all ISP pins inputs */
+ ISP_DDR &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI));
+ /* switch pullups off */
+ ISP_OUT &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI));
- /* disable hardware SPI */
- spiHWdisable();
+ /* disable hardware SPI */
+ spiHWdisable();
}
uchar ispTransmit_sw(uchar send_byte) {
- uchar rec_byte = 0;
- uchar i;
- for (i = 0; i < 8; i++) {
-
- /* set MSB to MOSI-pin */
- if ((send_byte & 0x80) != 0) {
- ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */
- } else {
- ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */
- }
- /* shift to next bit */
- send_byte = send_byte << 1;
-
- /* receive data */
- rec_byte = rec_byte << 1;
- if ((ISP_IN & (1 << ISP_MISO)) != 0) {
- rec_byte++;
- }
-
- /* pulse SCK */
- ISP_OUT |= (1 << ISP_SCK); /* SCK high */
- ispDelay();
- ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
- ispDelay();
- }
-
- return rec_byte;
+ uchar rec_byte = 0;
+ uchar i;
+ for (i = 0; i < 8; i++) {
+
+ /* set MSB to MOSI-pin */
+ if ((send_byte & 0x80) != 0) {
+ ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */
+ } else {
+ ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */
+ }
+ /* shift to next bit */
+ send_byte = send_byte << 1;
+
+ /* receive data */
+ rec_byte = rec_byte << 1;
+ if ((ISP_IN & (1 << ISP_MISO)) != 0) {
+ rec_byte++;
+ }
+
+ /* pulse SCK */
+ ISP_OUT |= (1 << ISP_SCK); /* SCK high */
+ ispDelay();
+ ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
+ ispDelay();
+ }
+
+ return rec_byte;
}
uchar ispTransmit_hw(uchar send_byte) {
- SPDR = send_byte;
+ SPDR = send_byte;
- while (!(SPSR & (1 << SPIF)));
- return SPDR;
+ while (!(SPSR & (1 << SPIF)))
+ ;
+ return SPDR;
}
uchar ispEnterProgrammingMode() {
- uchar check;
- uchar count = 32;
+ uchar check;
+ uchar count = 32;
- while (count--) {
- ispTransmit(0xAC);
- ispTransmit(0x53);
- check = ispTransmit(0);
- ispTransmit(0);
+ while (count--) {
+ ispTransmit(0xAC);
+ ispTransmit(0x53);
+ check = ispTransmit(0);
+ ispTransmit(0);
- if (check == 0x53) {
- return 0;
- }
+ if (check == 0x53) {
+ return 0;
+ }
- spiHWdisable();
+ spiHWdisable();
- /* pulse SCK */
- ISP_OUT |= (1 << ISP_SCK); /* SCK high */
- ispDelay();
- ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
- ispDelay();
+ /* pulse SCK */
+ ISP_OUT |= (1 << ISP_SCK); /* SCK high */
+ ispDelay();
+ ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
+ ispDelay();
- if (ispTransmit == ispTransmit_hw) {
- spiHWenable();
- }
+ if (ispTransmit == ispTransmit_hw) {
+ spiHWenable();
+ }
- }
+ }
- return 1; /* error: device dosn't answer */
+ return 1; /* error: device dosn't answer */
}
uchar ispReadFlash(unsigned long address) {
- ispTransmit(0x20 | ((address & 1) << 3));
- ispTransmit(address >> 9);
- ispTransmit(address >> 1);
- return ispTransmit(0);
+ ispTransmit(0x20 | ((address & 1) << 3));
+ ispTransmit(address >> 9);
+ ispTransmit(address >> 1);
+ return ispTransmit(0);
}
-
uchar ispWriteFlash(unsigned long address, uchar data, uchar pollmode) {
- /* 0xFF is value after chip erase, so skip programming
- if (data == 0xFF) {
- return 0;
- }
- */
-
- ispTransmit(0x40 | ((address & 1) << 3));
- ispTransmit(address >> 9);
- ispTransmit(address >> 1);
- ispTransmit(data);
-
- if (pollmode == 0)
- return 0;
-
- if (data == 0x7F) {
- clockWait(15); /* wait 4,8 ms */
- return 0;
- } else {
-
- /* polling flash */
- uchar retries = 30;
- uint8_t starttime = TIMERVALUE;
- while (retries != 0) {
- if (ispReadFlash(address) != 0x7F) {
- return 0;
- };
-
- if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) {
- starttime = TIMERVALUE;
- retries --;
- }
-
- }
- return 1; /* error */
- }
+ /* 0xFF is value after chip erase, so skip programming
+ if (data == 0xFF) {
+ return 0;
+ }
+ */
+
+ ispTransmit(0x40 | ((address & 1) << 3));
+ ispTransmit(address >> 9);
+ ispTransmit(address >> 1);
+ ispTransmit(data);
+
+ if (pollmode == 0)
+ return 0;
+
+ if (data == 0x7F) {
+ clockWait(15); /* wait 4,8 ms */
+ return 0;
+ } else {
+
+ /* polling flash */
+ uchar retries = 30;
+ uint8_t starttime = TIMERVALUE;
+ while (retries != 0) {
+ if (ispReadFlash(address) != 0x7F) {
+ return 0;
+ };
+
+ if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) {
+ starttime = TIMERVALUE;
+ retries--;
+ }
+
+ }
+ return 1; /* error */
+ }
}
-
uchar ispFlushPage(unsigned long address, uchar pollvalue) {
- ispTransmit(0x4C);
- ispTransmit(address >> 9);
- ispTransmit(address >> 1);
- ispTransmit(0);
-
+ ispTransmit(0x4C);
+ ispTransmit(address >> 9);
+ ispTransmit(address >> 1);
+ ispTransmit(0);
- if (pollvalue == 0xFF) {
- clockWait(15);
- return 0;
- } else {
+ if (pollvalue == 0xFF) {
+ clockWait(15);
+ return 0;
+ } else {
- /* polling flash */
- uchar retries = 30;
- uint8_t starttime = TIMERVALUE;
+ /* polling flash */
+ uchar retries = 30;
+ uint8_t starttime = TIMERVALUE;
- while (retries != 0) {
- if (ispReadFlash(address) != 0xFF) {
- return 0;
- };
+ while (retries != 0) {
+ if (ispReadFlash(address) != 0xFF) {
+ return 0;
+ };
- if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) {
- starttime = TIMERVALUE;
- retries --;
- }
+ if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) {
+ starttime = TIMERVALUE;
+ retries--;
+ }
- }
+ }
- return 1; /* error */
- }
+ return 1; /* error */
+ }
}
-
uchar ispReadEEPROM(unsigned int address) {
- ispTransmit(0xA0);
- ispTransmit(address >> 8);
- ispTransmit(address);
- return ispTransmit(0);
+ ispTransmit(0xA0);
+ ispTransmit(address >> 8);
+ ispTransmit(address);
+ return ispTransmit(0);
}
-
uchar ispWriteEEPROM(unsigned int address, uchar data) {
- ispTransmit(0xC0);
- ispTransmit(address >> 8);
- ispTransmit(address);
- ispTransmit(data);
+ ispTransmit(0xC0);
+ ispTransmit(address >> 8);
+ ispTransmit(address);
+ ispTransmit(data);
- clockWait(30); // wait 9,6 ms
+ clockWait(30); // wait 9,6 ms
- return 0;
- /*
- if (data == 0xFF) {
- clockWait(30); // wait 9,6 ms
- return 0;
- } else {
-
- // polling eeprom
- uchar retries = 30; // about 9,6 ms
- uint8_t starttime = TIMERVALUE;
-
- while (retries != 0) {
- if (ispReadEEPROM(address) != 0xFF) {
return 0;
- };
-
- if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) {
- starttime = TIMERVALUE;
- retries --;
- }
-
- }
- return 1; // error
- }
- */
-
}