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....: 2009-02-28
17 #define spiHWdisable() SPCR = 0
28 void ispSetSCKOption(uchar option
) {
30 if (option
== USBASP_ISP_SCK_AUTO
)
31 option
= USBASP_ISP_SCK_375
;
33 if (option
>= USBASP_ISP_SCK_93_75
) {
34 ispTransmit
= ispTransmit_hw
;
39 case USBASP_ISP_SCK_1500
:
40 /* enable SPI, master, 1.5MHz, XTAL/8 */
41 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
42 sck_spsr
= (1 << SPI2X
);
43 case USBASP_ISP_SCK_750
:
44 /* enable SPI, master, 750kHz, XTAL/16 */
45 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
47 case USBASP_ISP_SCK_375
:
49 /* enable SPI, master, 375kHz, XTAL/32 (default) */
50 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
51 sck_spsr
= (1 << SPI2X
);
53 case USBASP_ISP_SCK_187_5
:
54 /* enable SPI, master, 187.5kHz XTAL/64 */
55 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
57 case USBASP_ISP_SCK_93_75
:
58 /* enable SPI, master, 93.75kHz XTAL/128 */
59 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
) | (1 << SPR0
);
64 ispTransmit
= ispTransmit_sw
;
67 case USBASP_ISP_SCK_32
:
71 case USBASP_ISP_SCK_16
:
75 case USBASP_ISP_SCK_8
:
79 case USBASP_ISP_SCK_4
:
83 case USBASP_ISP_SCK_2
:
87 case USBASP_ISP_SCK_1
:
91 case USBASP_ISP_SCK_0_5
:
101 uint8_t starttime
= TIMERVALUE
;
102 while ((uint8_t) (TIMERVALUE
- starttime
) < sck_sw_delay
) {
108 /* all ISP pins are inputs before */
109 /* now set output pins */
110 ISP_DDR
|= (1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
);
113 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
114 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
116 /* positive reset pulse > 2 SCK (target) */
118 ISP_OUT
|= (1 << ISP_RST
); /* RST high */
120 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
122 if (ispTransmit
== ispTransmit_hw
) {
127 void ispDisconnect() {
129 /* set all ISP pins inputs */
130 ISP_DDR
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
131 /* switch pullups off */
132 ISP_OUT
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
134 /* disable hardware SPI */
138 uchar
ispTransmit_sw(uchar send_byte
) {
142 for (i
= 0; i
< 8; i
++) {
144 /* set MSB to MOSI-pin */
145 if ((send_byte
& 0x80) != 0) {
146 ISP_OUT
|= (1 << ISP_MOSI
); /* MOSI high */
148 ISP_OUT
&= ~(1 << ISP_MOSI
); /* MOSI low */
150 /* shift to next bit */
151 send_byte
= send_byte
<< 1;
154 rec_byte
= rec_byte
<< 1;
155 if ((ISP_IN
& (1 << ISP_MISO
)) != 0) {
160 ISP_OUT
|= (1 << ISP_SCK
); /* SCK high */
162 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
169 uchar
ispTransmit_hw(uchar send_byte
) {
172 while (!(SPSR
& (1 << SPIF
)))
177 uchar
ispEnterProgrammingMode() {
184 check
= ispTransmit(0);
194 ISP_OUT
|= (1 << ISP_SCK
); /* SCK high */
196 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
199 if (ispTransmit
== ispTransmit_hw
) {
205 return 1; /* error: device dosn't answer */
208 uchar
ispReadFlash(unsigned long address
) {
209 ispTransmit(0x20 | ((address
& 1) << 3));
210 ispTransmit(address
>> 9);
211 ispTransmit(address
>> 1);
212 return ispTransmit(0);
215 uchar
ispWriteFlash(unsigned long address
, uchar data
, uchar pollmode
) {
217 /* 0xFF is value after chip erase, so skip programming
223 ispTransmit(0x40 | ((address
& 1) << 3));
224 ispTransmit(address
>> 9);
225 ispTransmit(address
>> 1);
232 clockWait(15); /* wait 4,8 ms */
238 uint8_t starttime
= TIMERVALUE
;
239 while (retries
!= 0) {
240 if (ispReadFlash(address
) != 0x7F) {
244 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
245 starttime
= TIMERVALUE
;
250 return 1; /* error */
255 uchar
ispFlushPage(unsigned long address
, uchar pollvalue
) {
257 ispTransmit(address
>> 9);
258 ispTransmit(address
>> 1);
261 if (pollvalue
== 0xFF) {
268 uint8_t starttime
= TIMERVALUE
;
270 while (retries
!= 0) {
271 if (ispReadFlash(address
) != 0xFF) {
275 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
276 starttime
= TIMERVALUE
;
282 return 1; /* error */
287 uchar
ispReadEEPROM(unsigned int address
) {
289 ispTransmit(address
>> 8);
290 ispTransmit(address
);
291 return ispTransmit(0);
294 uchar
ispWriteEEPROM(unsigned int address
, uchar data
) {
297 ispTransmit(address
>> 8);
298 ispTransmit(address
);
301 clockWait(30); // wait 9,6 ms