* over ISP interface
* Licence........: GNU GPL v2 (see Readme.txt)
* Creation Date..: 2005-02-23
- * Last change....: 2009-02-28
+ * Last change....: 2010-01-19
*/
#include <avr/io.h>
#define spiHWdisable() SPCR = 0
uchar sck_sw_delay;
+uchar sck_sw_delay_loops;
uchar sck_spcr;
uchar sck_spsr;
+uchar isp_hiaddr;
void spiHWenable() {
SPCR = sck_spcr;
if (option == USBASP_ISP_SCK_AUTO)
option = USBASP_ISP_SCK_375;
- if (option >= USBASP_ISP_SCK_93_75) {
+ if (((F_CPU <= 12000000) && (option >= USBASP_ISP_SCK_93_75))
+ || ((F_CPU > 12000000) && (option >= USBASP_ISP_SCK_187_5))) {
ispTransmit = ispTransmit_hw;
sck_spsr = 0;
+ sck_sw_delay = 1; /* force RST#/SCK pulse for 320us */
+ sck_sw_delay_loops = 1;
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);
+# if (F_CPU <= 12000000)
+ /* enable SPI, master, 1.5MHz, XTAL/8 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+ sck_spsr = (1 << SPI2X);
+# else
+ /* enable SPI, master, ~1.1MHz, XTAL/16 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+# endif
+ break;
case USBASP_ISP_SCK_750:
- /* enable SPI, master, 750kHz, XTAL/16 */
- sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+# if (F_CPU <= 12000000)
+ /* enable SPI, master, 750kHz, XTAL/16 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
+# else
+ /* enable SPI, master, ~531kHz, XTAL/32 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+ sck_spsr = (1 << SPI2X);
+# endif
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);
+# if (F_CPU <= 12000000)
+ /* enable SPI, master, 375kHz, XTAL/32 (default) */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+ sck_spsr = (1 << SPI2X);
+# else
+ /* enable SPI, master, ~265.6kHz XTAL/64 (default) */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+# endif
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);
+# if (F_CPU <= 12000000)
+ /* enable SPI, master, 187.5kHz XTAL/64 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1);
+# else
+ /* enable SPI, master, ~132.81kHz XTAL/128 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+# endif
break;
+# if (F_CPU <= 12000000)
+ case USBASP_ISP_SCK_93_75:
+ /* enable SPI, master, 93.75kHz XTAL/128 */
+ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0);
+ break;
+# endif
}
} else {
ispTransmit = ispTransmit_sw;
+ sck_sw_delay_loops = 1;
+
switch (option) {
+# if (F_CPU > 12000000)
+ case USBASP_ISP_SCK_93_75:
+ sck_sw_delay = 2;
+
+ break;
+# endif
case USBASP_ISP_SCK_32:
- sck_sw_delay = 3;
+ sck_sw_delay = ((3 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_16:
- sck_sw_delay = 6;
+ sck_sw_delay = ((6 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_8:
- sck_sw_delay = 12;
+ sck_sw_delay = ((12 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_4:
- sck_sw_delay = 24;
+ sck_sw_delay = ((24 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_2:
- sck_sw_delay = 48;
+ sck_sw_delay = ((48 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_1:
- sck_sw_delay = 96;
+ sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12);
break;
case USBASP_ISP_SCK_0_5:
- sck_sw_delay = 192;
+ sck_sw_delay = ((96 * (F_CPU/1000000L) + 11) / 12);
+ sck_sw_delay_loops = 2;
break;
}
void ispDelay() {
uint8_t starttime = TIMERVALUE;
- while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) {
+ uint8_t loops = sck_sw_delay_loops;
+
+ while (loops--) {
+ while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) {
+ }
}
}
if (ispTransmit == ispTransmit_hw) {
spiHWenable();
}
+
+ /* Initial extended address value */
+ isp_hiaddr = 0;
}
void ispDisconnect() {
spiHWdisable();
- /* pulse SCK */
- ISP_OUT |= (1 << ISP_SCK); /* SCK high */
+ /* pulse RST */
ispDelay();
- ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */
+ ISP_OUT |= (1 << ISP_RST); /* RST high */
+ ispDelay();
+ ISP_OUT &= ~(1 << ISP_RST); /* RST low */
ispDelay();
if (ispTransmit == ispTransmit_hw) {
return 1; /* error: device dosn't answer */
}
+static void ispUpdateExtended(unsigned long address)
+{
+ uchar curr_hiaddr;
+
+ curr_hiaddr = (address >> 17);
+
+ /* check if extended address byte is changed */
+ if(isp_hiaddr != curr_hiaddr)
+ {
+ isp_hiaddr = curr_hiaddr;
+ /* Load Extended Address byte */
+ ispTransmit(0x4D);
+ ispTransmit(0x00);
+ ispTransmit(isp_hiaddr);
+ ispTransmit(0x00);
+ }
+}
+
uchar ispReadFlash(unsigned long address) {
+
+ ispUpdateExtended(address);
+
ispTransmit(0x20 | ((address & 1) << 3));
ispTransmit(address >> 9);
ispTransmit(address >> 1);
}
*/
+ ispUpdateExtended(address);
+
ispTransmit(0x40 | ((address & 1) << 3));
ispTransmit(address >> 9);
ispTransmit(address >> 1);
}
uchar ispFlushPage(unsigned long address, uchar pollvalue) {
+
+ ispUpdateExtended(address);
+
ispTransmit(0x4C);
ispTransmit(address >> 9);
ispTransmit(address >> 1);