2 * isp.c - part of USBasp
4 * Autor..........: Thomas Fischl <tfischl@gmx.de>
5 * Description....: Provides functions for communication/programming
7 * Licence........: GNU GPL v2 (see Readme.txt)
8 * Creation Date..: 2005-02-23
9 * Last change....: 2010-01-19
17 #define spiHWdisable() SPCR = 0
29 void ispSetSCKOption(uchar option
) {
31 if (option
== USBASP_ISP_SCK_AUTO
)
32 option
= USBASP_ISP_SCK_375
;
34 if (option
>= USBASP_ISP_SCK_93_75
) {
35 ispTransmit
= ispTransmit_hw
;
37 sck_sw_delay
= 1; /* force RST#/SCK pulse for 320us */
41 case USBASP_ISP_SCK_1500
:
42 /* enable SPI, master, 1.5MHz, XTAL/8 */
43 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
44 sck_spsr
= (1 << SPI2X
);
45 case USBASP_ISP_SCK_750
:
46 /* enable SPI, master, 750kHz, XTAL/16 */
47 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
49 case USBASP_ISP_SCK_375
:
51 /* enable SPI, master, 375kHz, XTAL/32 (default) */
52 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
53 sck_spsr
= (1 << SPI2X
);
55 case USBASP_ISP_SCK_187_5
:
56 /* enable SPI, master, 187.5kHz XTAL/64 */
57 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
59 case USBASP_ISP_SCK_93_75
:
60 /* enable SPI, master, 93.75kHz XTAL/128 */
61 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
) | (1 << SPR0
);
66 ispTransmit
= ispTransmit_sw
;
69 case USBASP_ISP_SCK_32
:
73 case USBASP_ISP_SCK_16
:
77 case USBASP_ISP_SCK_8
:
81 case USBASP_ISP_SCK_4
:
85 case USBASP_ISP_SCK_2
:
89 case USBASP_ISP_SCK_1
:
93 case USBASP_ISP_SCK_0_5
:
103 uint8_t starttime
= TIMERVALUE
;
104 while ((uint8_t) (TIMERVALUE
- starttime
) < sck_sw_delay
) {
110 /* all ISP pins are inputs before */
111 /* now set output pins */
112 ISP_DDR
|= (1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
);
115 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
116 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
118 /* positive reset pulse > 2 SCK (target) */
120 ISP_OUT
|= (1 << ISP_RST
); /* RST high */
122 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
124 if (ispTransmit
== ispTransmit_hw
) {
128 /* Initial extended address value */
132 void ispDisconnect() {
134 /* set all ISP pins inputs */
135 ISP_DDR
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
136 /* switch pullups off */
137 ISP_OUT
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
139 /* disable hardware SPI */
143 uchar
ispTransmit_sw(uchar send_byte
) {
147 for (i
= 0; i
< 8; i
++) {
149 /* set MSB to MOSI-pin */
150 if ((send_byte
& 0x80) != 0) {
151 ISP_OUT
|= (1 << ISP_MOSI
); /* MOSI high */
153 ISP_OUT
&= ~(1 << ISP_MOSI
); /* MOSI low */
155 /* shift to next bit */
156 send_byte
= send_byte
<< 1;
159 rec_byte
= rec_byte
<< 1;
160 if ((ISP_IN
& (1 << ISP_MISO
)) != 0) {
165 ISP_OUT
|= (1 << ISP_SCK
); /* SCK high */
167 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
174 uchar
ispTransmit_hw(uchar send_byte
) {
177 while (!(SPSR
& (1 << SPIF
)))
182 uchar
ispEnterProgrammingMode() {
189 check
= ispTransmit(0);
200 ISP_OUT
|= (1 << ISP_RST
); /* RST high */
202 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
205 if (ispTransmit
== ispTransmit_hw
) {
211 return 1; /* error: device dosn't answer */
214 static void ispUpdateExtended(unsigned long address
)
218 curr_hiaddr
= (address
>> 17);
220 /* check if extended address byte is changed */
221 if(isp_hiaddr
!= curr_hiaddr
)
223 isp_hiaddr
= curr_hiaddr
;
224 /* Load Extended Address byte */
227 ispTransmit(isp_hiaddr
);
232 uchar
ispReadFlash(unsigned long address
) {
234 ispUpdateExtended(address
);
236 ispTransmit(0x20 | ((address
& 1) << 3));
237 ispTransmit(address
>> 9);
238 ispTransmit(address
>> 1);
239 return ispTransmit(0);
242 uchar
ispWriteFlash(unsigned long address
, uchar data
, uchar pollmode
) {
244 /* 0xFF is value after chip erase, so skip programming
250 ispUpdateExtended(address
);
252 ispTransmit(0x40 | ((address
& 1) << 3));
253 ispTransmit(address
>> 9);
254 ispTransmit(address
>> 1);
261 clockWait(15); /* wait 4,8 ms */
267 uint8_t starttime
= TIMERVALUE
;
268 while (retries
!= 0) {
269 if (ispReadFlash(address
) != 0x7F) {
273 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
274 starttime
= TIMERVALUE
;
279 return 1; /* error */
284 uchar
ispFlushPage(unsigned long address
, uchar pollvalue
) {
286 ispUpdateExtended(address
);
289 ispTransmit(address
>> 9);
290 ispTransmit(address
>> 1);
293 if (pollvalue
== 0xFF) {
300 uint8_t starttime
= TIMERVALUE
;
302 while (retries
!= 0) {
303 if (ispReadFlash(address
) != 0xFF) {
307 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
308 starttime
= TIMERVALUE
;
314 return 1; /* error */
319 uchar
ispReadEEPROM(unsigned int address
) {
321 ispTransmit(address
>> 8);
322 ispTransmit(address
);
323 return ispTransmit(0);
326 uchar
ispWriteEEPROM(unsigned int address
, uchar data
) {
329 ispTransmit(address
>> 8);
330 ispTransmit(address
);
333 clockWait(30); // wait 9,6 ms