main.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn 0 .text 000010d4 00000000 00000000 00000094 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 00000002 00800060 000010d4 00001168 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .bss 00000048 00800062 00800062 0000116a 2**1 ALLOC 3 .stab 000006cc 00000000 00000000 0000116c 2**2 CONTENTS, READONLY, DEBUGGING 4 .stabstr 00000085 00000000 00000000 00001838 2**0 CONTENTS, READONLY, DEBUGGING 5 .debug_aranges 000000c0 00000000 00000000 000018c0 2**3 CONTENTS, READONLY, DEBUGGING 6 .debug_pubnames 0000033d 00000000 00000000 00001980 2**0 CONTENTS, READONLY, DEBUGGING 7 .debug_info 000010c7 00000000 00000000 00001cbd 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_abbrev 000005a3 00000000 00000000 00002d84 2**0 CONTENTS, READONLY, DEBUGGING 9 .debug_line 000012d5 00000000 00000000 00003327 2**0 CONTENTS, READONLY, DEBUGGING 10 .debug_frame 00000190 00000000 00000000 000045fc 2**2 CONTENTS, READONLY, DEBUGGING 11 .debug_str 000005a9 00000000 00000000 0000478c 2**0 CONTENTS, READONLY, DEBUGGING 12 .debug_loc 00000979 00000000 00000000 00004d35 2**0 CONTENTS, READONLY, DEBUGGING 13 .debug_pubtypes 000000de 00000000 00000000 000056ae 2**0 CONTENTS, READONLY, DEBUGGING 14 .debug_ranges 00000118 00000000 00000000 0000578c 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 3b c0 rjmp .+118 ; 0x78 <__ctors_end> 2: 39 c7 rjmp .+3698 ; 0xe76 <__vector_1> 4: 54 c0 rjmp .+168 ; 0xae <__bad_interrupt> 6: 53 c0 rjmp .+166 ; 0xae <__bad_interrupt> 8: 52 c0 rjmp .+164 ; 0xae <__bad_interrupt> a: 51 c0 rjmp .+162 ; 0xae <__bad_interrupt> c: 50 c0 rjmp .+160 ; 0xae <__bad_interrupt> e: 4f c0 rjmp .+158 ; 0xae <__bad_interrupt> 10: 4e c0 rjmp .+156 ; 0xae <__bad_interrupt> 12: 4d c0 rjmp .+154 ; 0xae <__bad_interrupt> 14: 4c c0 rjmp .+152 ; 0xae <__bad_interrupt> 16: 4b c0 rjmp .+150 ; 0xae <__bad_interrupt> 18: 4a c0 rjmp .+148 ; 0xae <__bad_interrupt> 1a: 49 c0 rjmp .+146 ; 0xae <__bad_interrupt> 1c: 48 c0 rjmp .+144 ; 0xae <__bad_interrupt> 1e: 47 c0 rjmp .+142 ; 0xae <__bad_interrupt> 20: 46 c0 rjmp .+140 ; 0xae <__bad_interrupt> 22: 45 c0 rjmp .+138 ; 0xae <__bad_interrupt> 24: 44 c0 rjmp .+136 ; 0xae <__bad_interrupt> 00000026 : 26: 04 03 09 04 .... 0000002a : 2a: 1c 03 77 00 77 00 77 00 2e 00 66 00 69 00 73 00 ..w.w.w...f.i.s. 3a: 63 00 68 00 6c 00 2e 00 64 00 65 00 c.h.l...d.e. 00000046 : 46: 0e 03 55 00 53 00 42 00 61 00 73 00 70 00 ..U.S.B.a.s.p. 00000054 : 54: 12 01 10 01 ff 00 00 08 c0 16 dc 05 04 01 01 02 ................ 64: 00 01 .. 00000066 : 66: 09 02 12 00 01 01 00 80 19 09 04 00 00 00 00 00 ................ ... 00000078 <__ctors_end>: 78: 11 24 eor r1, r1 7a: 1f be out 0x3f, r1 ; 63 7c: cf e5 ldi r28, 0x5F ; 95 7e: d4 e0 ldi r29, 0x04 ; 4 80: de bf out 0x3e, r29 ; 62 82: cd bf out 0x3d, r28 ; 61 00000084 <__do_copy_data>: 84: 10 e0 ldi r17, 0x00 ; 0 86: a0 e6 ldi r26, 0x60 ; 96 88: b0 e0 ldi r27, 0x00 ; 0 8a: e4 ed ldi r30, 0xD4 ; 212 8c: f0 e1 ldi r31, 0x10 ; 16 8e: 02 c0 rjmp .+4 ; 0x94 <__do_copy_data+0x10> 90: 05 90 lpm r0, Z+ 92: 0d 92 st X+, r0 94: a2 36 cpi r26, 0x62 ; 98 96: b1 07 cpc r27, r17 98: d9 f7 brne .-10 ; 0x90 <__do_copy_data+0xc> 0000009a <__do_clear_bss>: 9a: 10 e0 ldi r17, 0x00 ; 0 9c: a2 e6 ldi r26, 0x62 ; 98 9e: b0 e0 ldi r27, 0x00 ; 0 a0: 01 c0 rjmp .+2 ; 0xa4 <.do_clear_bss_start> 000000a2 <.do_clear_bss_loop>: a2: 1d 92 st X+, r1 000000a4 <.do_clear_bss_start>: a4: aa 3a cpi r26, 0xAA ; 170 a6: b1 07 cpc r27, r17 a8: e1 f7 brne .-8 ; 0xa2 <.do_clear_bss_loop> aa: 33 d5 rcall .+2662 ; 0xb12
ac: 11 c8 rjmp .-4062 ; 0xfffff0d0 <__eeprom_end+0xff7ef0d0> 000000ae <__bad_interrupt>: ae: a8 cf rjmp .-176 ; 0x0 <__vectors> 000000b0 : /* wait time * 320 us */ void clockWait(uint8_t time) { uint8_t i; for (i = 0; i < time; i++) { b0: 90 e0 ldi r25, 0x00 ; 0 b2: 06 c0 rjmp .+12 ; 0xc0 uint8_t starttime = TIMERVALUE; b4: 32 b7 in r19, 0x32 ; 50 while ((uint8_t) (TIMERVALUE - starttime) < CLOCK_T_320us) { b6: 22 b7 in r18, 0x32 ; 50 b8: 23 1b sub r18, r19 ba: 2c 33 cpi r18, 0x3C ; 60 bc: e0 f3 brcs .-8 ; 0xb6 /* wait time * 320 us */ void clockWait(uint8_t time) { uint8_t i; for (i = 0; i < time; i++) { be: 9f 5f subi r25, 0xFF ; 255 c0: 98 17 cp r25, r24 c2: c0 f3 brcs .-16 ; 0xb4 uint8_t starttime = TIMERVALUE; while ((uint8_t) (TIMERVALUE - starttime) < CLOCK_T_320us) { } } } c4: 08 95 ret 000000c6 : return rec_byte; } uchar ispTransmit_hw(uchar send_byte) { SPDR = send_byte; c6: 8f b9 out 0x0f, r24 ; 15 while (!(SPSR & (1 << SPIF))) c8: 77 9b sbis 0x0e, 7 ; 14 ca: fe cf rjmp .-4 ; 0xc8 ; return SPDR; cc: 8f b1 in r24, 0x0f ; 15 } ce: 08 95 ret 000000d0 : static void ispUpdateExtended(unsigned long address) { uchar curr_hiaddr; curr_hiaddr = (address >> 17); d0: 21 e1 ldi r18, 0x11 ; 17 d2: 96 95 lsr r25 d4: 87 95 ror r24 d6: 77 95 ror r23 d8: 67 95 ror r22 da: 2a 95 dec r18 dc: d1 f7 brne .-12 ; 0xd2 /* check if extended address byte is changed */ if(isp_hiaddr != curr_hiaddr) de: 20 91 7c 00 lds r18, 0x007C e2: 26 17 cp r18, r22 e4: d9 f0 breq .+54 ; 0x11c { isp_hiaddr = curr_hiaddr; e6: 60 93 7c 00 sts 0x007C, r22 /* Load Extended Address byte */ ispTransmit(0x4D); ea: e0 91 79 00 lds r30, 0x0079 ee: f0 91 7a 00 lds r31, 0x007A f2: 8d e4 ldi r24, 0x4D ; 77 f4: 09 95 icall ispTransmit(0x00); f6: e0 91 79 00 lds r30, 0x0079 fa: f0 91 7a 00 lds r31, 0x007A fe: 80 e0 ldi r24, 0x00 ; 0 100: 09 95 icall ispTransmit(isp_hiaddr); 102: e0 91 79 00 lds r30, 0x0079 106: f0 91 7a 00 lds r31, 0x007A 10a: 80 91 7c 00 lds r24, 0x007C 10e: 09 95 icall ispTransmit(0x00); 110: e0 91 79 00 lds r30, 0x0079 114: f0 91 7a 00 lds r31, 0x007A 118: 80 e0 ldi r24, 0x00 ; 0 11a: 09 95 icall 11c: 08 95 ret 0000011e : uchar sck_spcr; uchar sck_spsr; uchar isp_hiaddr; void spiHWenable() { SPCR = sck_spcr; 11e: 80 91 7b 00 lds r24, 0x007B 122: 8d b9 out 0x0d, r24 ; 13 SPSR = sck_spsr; 124: 80 91 78 00 lds r24, 0x0078 128: 8e b9 out 0x0e, r24 ; 14 } 12a: 08 95 ret 0000012c : void ispSetSCKOption(uchar option) { if (option == USBASP_ISP_SCK_AUTO) 12c: 88 23 and r24, r24 12e: 19 f0 breq .+6 ; 0x136 option = USBASP_ISP_SCK_375; if (option >= USBASP_ISP_SCK_93_75) { 130: 88 30 cpi r24, 0x08 ; 8 132: 48 f1 brcs .+82 ; 0x186 134: 01 c0 rjmp .+2 ; 0x138 } void ispSetSCKOption(uchar option) { if (option == USBASP_ISP_SCK_AUTO) option = USBASP_ISP_SCK_375; 136: 8a e0 ldi r24, 0x0A ; 10 if (option >= USBASP_ISP_SCK_93_75) { ispTransmit = ispTransmit_hw; 138: 23 e6 ldi r18, 0x63 ; 99 13a: 30 e0 ldi r19, 0x00 ; 0 13c: 30 93 7a 00 sts 0x007A, r19 140: 20 93 79 00 sts 0x0079, r18 sck_spsr = 0; 144: 10 92 78 00 sts 0x0078, r1 sck_sw_delay = 1; /* force RST#/SCK pulse for 320us */ 148: 91 e0 ldi r25, 0x01 ; 1 14a: 90 93 7d 00 sts 0x007D, r25 switch (option) { 14e: 89 30 cpi r24, 0x09 ; 9 150: a1 f0 breq .+40 ; 0x17a 152: 8a 30 cpi r24, 0x0A ; 10 154: 18 f4 brcc .+6 ; 0x15c 156: 88 30 cpi r24, 0x08 ; 8 158: 49 f4 brne .+18 ; 0x16c 15a: 11 c0 rjmp .+34 ; 0x17e 15c: 8b 30 cpi r24, 0x0B ; 11 15e: 21 f0 breq .+8 ; 0x168 160: 8c 30 cpi r24, 0x0C ; 12 162: 21 f4 brne .+8 ; 0x16c case USBASP_ISP_SCK_1500: /* enable SPI, master, 1.5MHz, XTAL/8 */ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); sck_spsr = (1 << SPI2X); 164: 90 93 78 00 sts 0x0078, r25 case USBASP_ISP_SCK_750: /* enable SPI, master, 750kHz, XTAL/16 */ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR0); 168: 81 e5 ldi r24, 0x51 ; 81 16a: 0a c0 rjmp .+20 ; 0x180 break; case USBASP_ISP_SCK_375: default: /* enable SPI, master, 375kHz, XTAL/32 (default) */ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); 16c: 82 e5 ldi r24, 0x52 ; 82 16e: 80 93 7b 00 sts 0x007B, r24 sck_spsr = (1 << SPI2X); 172: 81 e0 ldi r24, 0x01 ; 1 174: 80 93 78 00 sts 0x0078, r24 break; 178: 08 95 ret case USBASP_ISP_SCK_187_5: /* enable SPI, master, 187.5kHz XTAL/64 */ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1); 17a: 82 e5 ldi r24, 0x52 ; 82 17c: 01 c0 rjmp .+2 ; 0x180 break; case USBASP_ISP_SCK_93_75: /* enable SPI, master, 93.75kHz XTAL/128 */ sck_spcr = (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); 17e: 83 e5 ldi r24, 0x53 ; 83 180: 80 93 7b 00 sts 0x007B, r24 break; 184: 08 95 ret } } else { ispTransmit = ispTransmit_sw; 186: 2e ee ldi r18, 0xEE ; 238 188: 30 e0 ldi r19, 0x00 ; 0 18a: 30 93 7a 00 sts 0x007A, r19 18e: 20 93 79 00 sts 0x0079, r18 switch (option) { 192: 84 30 cpi r24, 0x04 ; 4 194: 89 f0 breq .+34 ; 0x1b8 196: 85 30 cpi r24, 0x05 ; 5 198: 28 f4 brcc .+10 ; 0x1a4 19a: 82 30 cpi r24, 0x02 ; 2 19c: 89 f0 breq .+34 ; 0x1c0 19e: 83 30 cpi r24, 0x03 ; 3 1a0: 89 f4 brne .+34 ; 0x1c4 1a2: 0c c0 rjmp .+24 ; 0x1bc 1a4: 86 30 cpi r24, 0x06 ; 6 1a6: 79 f0 breq .+30 ; 0x1c6 1a8: 86 30 cpi r24, 0x06 ; 6 1aa: 20 f0 brcs .+8 ; 0x1b4 1ac: 87 30 cpi r24, 0x07 ; 7 1ae: 51 f4 brne .+20 ; 0x1c4 case USBASP_ISP_SCK_32: sck_sw_delay = 3; 1b0: 83 e0 ldi r24, 0x03 ; 3 1b2: 09 c0 rjmp .+18 ; 0x1c6 case USBASP_ISP_SCK_16: sck_sw_delay = 6; break; case USBASP_ISP_SCK_8: sck_sw_delay = 12; 1b4: 8c e0 ldi r24, 0x0C ; 12 1b6: 07 c0 rjmp .+14 ; 0x1c6 break; case USBASP_ISP_SCK_4: sck_sw_delay = 24; 1b8: 88 e1 ldi r24, 0x18 ; 24 1ba: 05 c0 rjmp .+10 ; 0x1c6 break; case USBASP_ISP_SCK_2: sck_sw_delay = 48; 1bc: 80 e3 ldi r24, 0x30 ; 48 1be: 03 c0 rjmp .+6 ; 0x1c6 break; case USBASP_ISP_SCK_1: sck_sw_delay = 96; 1c0: 80 e6 ldi r24, 0x60 ; 96 1c2: 01 c0 rjmp .+2 ; 0x1c6 break; case USBASP_ISP_SCK_0_5: sck_sw_delay = 192; 1c4: 80 ec ldi r24, 0xC0 ; 192 1c6: 80 93 7d 00 sts 0x007D, r24 1ca: 08 95 ret 000001cc : } } void ispDelay() { uint8_t starttime = TIMERVALUE; 1cc: 22 b7 in r18, 0x32 ; 50 while ((uint8_t) (TIMERVALUE - starttime) < sck_sw_delay) { 1ce: 90 91 7d 00 lds r25, 0x007D 1d2: 82 b7 in r24, 0x32 ; 50 1d4: 82 1b sub r24, r18 1d6: 89 17 cp r24, r25 1d8: e0 f3 brcs .-8 ; 0x1d2 } } 1da: 08 95 ret 000001dc : /* disable hardware SPI */ spiHWdisable(); } uchar ispTransmit_sw(uchar send_byte) { 1dc: 0f 93 push r16 1de: 1f 93 push r17 1e0: df 93 push r29 1e2: cf 93 push r28 1e4: 0f 92 push r0 1e6: cd b7 in r28, 0x3d ; 61 1e8: de b7 in r29, 0x3e ; 62 1ea: 08 e0 ldi r16, 0x08 ; 8 uchar rec_byte = 0; 1ec: 10 e0 ldi r17, 0x00 ; 0 uchar i; for (i = 0; i < 8; i++) { /* set MSB to MOSI-pin */ if ((send_byte & 0x80) != 0) { 1ee: 87 ff sbrs r24, 7 1f0: 02 c0 rjmp .+4 ; 0x1f6 ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */ 1f2: c3 9a sbi 0x18, 3 ; 24 1f4: 01 c0 rjmp .+2 ; 0x1f8 } else { ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */ 1f6: c3 98 cbi 0x18, 3 ; 24 } /* shift to next bit */ send_byte = send_byte << 1; /* receive data */ rec_byte = rec_byte << 1; 1f8: 11 0f add r17, r17 if ((ISP_IN & (1 << ISP_MISO)) != 0) { 1fa: b4 99 sbic 0x16, 4 ; 22 rec_byte++; 1fc: 1f 5f subi r17, 0xFF ; 255 } /* pulse SCK */ ISP_OUT |= (1 << ISP_SCK); /* SCK high */ 1fe: c5 9a sbi 0x18, 5 ; 24 ispDelay(); 200: 89 83 std Y+1, r24 ; 0x01 202: e4 df rcall .-56 ; 0x1cc ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ 204: c5 98 cbi 0x18, 5 ; 24 ispDelay(); 206: e2 df rcall .-60 ; 0x1cc 208: 01 50 subi r16, 0x01 ; 1 uchar ispTransmit_sw(uchar send_byte) { uchar rec_byte = 0; uchar i; for (i = 0; i < 8; i++) { 20a: 89 81 ldd r24, Y+1 ; 0x01 20c: 00 23 and r16, r16 20e: 11 f0 breq .+4 ; 0x214 ISP_OUT |= (1 << ISP_MOSI); /* MOSI high */ } else { ISP_OUT &= ~(1 << ISP_MOSI); /* MOSI low */ } /* shift to next bit */ send_byte = send_byte << 1; 210: 88 0f add r24, r24 212: ed cf rjmp .-38 ; 0x1ee ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ ispDelay(); } return rec_byte; } 214: 81 2f mov r24, r17 216: 0f 90 pop r0 218: cf 91 pop r28 21a: df 91 pop r29 21c: 1f 91 pop r17 21e: 0f 91 pop r16 220: 08 95 ret 00000222 : void ispConnect() { /* all ISP pins are inputs before */ /* now set output pins */ ISP_DDR |= (1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI); 222: 87 b3 in r24, 0x17 ; 23 224: 8c 62 ori r24, 0x2C ; 44 226: 87 bb out 0x17, r24 ; 23 /* reset device */ ISP_OUT &= ~(1 << ISP_RST); /* RST low */ 228: c2 98 cbi 0x18, 2 ; 24 ISP_OUT &= ~(1 << ISP_SCK); /* SCK low */ 22a: c5 98 cbi 0x18, 5 ; 24 /* positive reset pulse > 2 SCK (target) */ ispDelay(); 22c: cf df rcall .-98 ; 0x1cc ISP_OUT |= (1 << ISP_RST); /* RST high */ 22e: c2 9a sbi 0x18, 2 ; 24 ispDelay(); 230: cd df rcall .-102 ; 0x1cc ISP_OUT &= ~(1 << ISP_RST); /* RST low */ 232: c2 98 cbi 0x18, 2 ; 24 if (ispTransmit == ispTransmit_hw) { 234: 80 91 79 00 lds r24, 0x0079 238: 90 91 7a 00 lds r25, 0x007A 23c: 20 e0 ldi r18, 0x00 ; 0 23e: 83 36 cpi r24, 0x63 ; 99 240: 92 07 cpc r25, r18 242: 09 f4 brne .+2 ; 0x246 spiHWenable(); 244: 6c df rcall .-296 ; 0x11e } /* Initial extended address value */ isp_hiaddr = 0; 246: 10 92 7c 00 sts 0x007C, r1 } 24a: 08 95 ret 0000024c : void ispDisconnect() { /* set all ISP pins inputs */ ISP_DDR &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); 24c: 87 b3 in r24, 0x17 ; 23 24e: 83 7d andi r24, 0xD3 ; 211 250: 87 bb out 0x17, r24 ; 23 /* switch pullups off */ ISP_OUT &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); 252: 88 b3 in r24, 0x18 ; 24 254: 83 7d andi r24, 0xD3 ; 211 256: 88 bb out 0x18, r24 ; 24 /* disable hardware SPI */ spiHWdisable(); 258: 1d b8 out 0x0d, r1 ; 13 } 25a: 08 95 ret 0000025c : while (!(SPSR & (1 << SPIF))) ; return SPDR; } uchar ispEnterProgrammingMode() { 25c: 0f 93 push r16 25e: 1f 93 push r17 uchar check; uchar count = 32; 260: 10 e2 ldi r17, 0x20 ; 32 while (count--) { 262: 2a c0 rjmp .+84 ; 0x2b8 ispTransmit(0xAC); 264: e0 91 79 00 lds r30, 0x0079 268: f0 91 7a 00 lds r31, 0x007A 26c: 8c ea ldi r24, 0xAC ; 172 26e: 09 95 icall ispTransmit(0x53); 270: e0 91 79 00 lds r30, 0x0079 274: f0 91 7a 00 lds r31, 0x007A 278: 83 e5 ldi r24, 0x53 ; 83 27a: 09 95 icall check = ispTransmit(0); 27c: e0 91 79 00 lds r30, 0x0079 280: f0 91 7a 00 lds r31, 0x007A 284: 80 e0 ldi r24, 0x00 ; 0 286: 09 95 icall 288: 08 2f mov r16, r24 ispTransmit(0); 28a: e0 91 79 00 lds r30, 0x0079 28e: f0 91 7a 00 lds r31, 0x007A 292: 80 e0 ldi r24, 0x00 ; 0 294: 09 95 icall if (check == 0x53) { 296: 03 35 cpi r16, 0x53 ; 83 298: 99 f0 breq .+38 ; 0x2c0 return 0; } spiHWdisable(); 29a: 1d b8 out 0x0d, r1 ; 13 /* pulse RST */ ispDelay(); 29c: 97 df rcall .-210 ; 0x1cc ISP_OUT |= (1 << ISP_RST); /* RST high */ 29e: c2 9a sbi 0x18, 2 ; 24 ispDelay(); 2a0: 95 df rcall .-214 ; 0x1cc ISP_OUT &= ~(1 << ISP_RST); /* RST low */ 2a2: c2 98 cbi 0x18, 2 ; 24 ispDelay(); 2a4: 93 df rcall .-218 ; 0x1cc if (ispTransmit == ispTransmit_hw) { 2a6: 80 91 79 00 lds r24, 0x0079 2aa: 90 91 7a 00 lds r25, 0x007A 2ae: 20 e0 ldi r18, 0x00 ; 0 2b0: 83 36 cpi r24, 0x63 ; 99 2b2: 92 07 cpc r25, r18 2b4: 09 f4 brne .+2 ; 0x2b8 spiHWenable(); 2b6: 33 df rcall .-410 ; 0x11e uchar ispEnterProgrammingMode() { uchar check; uchar count = 32; while (count--) { 2b8: 11 50 subi r17, 0x01 ; 1 2ba: a0 f6 brcc .-88 ; 0x264 spiHWenable(); } } return 1; /* error: device dosn't answer */ 2bc: 81 e0 ldi r24, 0x01 ; 1 2be: 01 c0 rjmp .+2 ; 0x2c2 ispTransmit(0x53); check = ispTransmit(0); ispTransmit(0); if (check == 0x53) { return 0; 2c0: 80 e0 ldi r24, 0x00 ; 0 } } return 1; /* error: device dosn't answer */ } 2c2: 1f 91 pop r17 2c4: 0f 91 pop r16 2c6: 08 95 ret 000002c8 : ispTransmit(isp_hiaddr); ispTransmit(0x00); } } uchar ispReadFlash(unsigned long address) { 2c8: ef 92 push r14 2ca: ff 92 push r15 2cc: 0f 93 push r16 2ce: 1f 93 push r17 2d0: 7b 01 movw r14, r22 2d2: 8c 01 movw r16, r24 ispUpdateExtended(address); 2d4: fd de rcall .-518 ; 0xd0 ispTransmit(0x20 | ((address & 1) << 3)); 2d6: 8e 2d mov r24, r14 2d8: 81 70 andi r24, 0x01 ; 1 2da: 88 0f add r24, r24 2dc: 88 0f add r24, r24 2de: 88 0f add r24, r24 2e0: e0 91 79 00 lds r30, 0x0079 2e4: f0 91 7a 00 lds r31, 0x007A 2e8: 80 62 ori r24, 0x20 ; 32 2ea: 09 95 icall ispTransmit(address >> 9); 2ec: d8 01 movw r26, r16 2ee: c7 01 movw r24, r14 2f0: 49 e0 ldi r20, 0x09 ; 9 2f2: b6 95 lsr r27 2f4: a7 95 ror r26 2f6: 97 95 ror r25 2f8: 87 95 ror r24 2fa: 4a 95 dec r20 2fc: d1 f7 brne .-12 ; 0x2f2 2fe: e0 91 79 00 lds r30, 0x0079 302: f0 91 7a 00 lds r31, 0x007A 306: 09 95 icall ispTransmit(address >> 1); 308: d8 01 movw r26, r16 30a: c7 01 movw r24, r14 30c: b6 95 lsr r27 30e: a7 95 ror r26 310: 97 95 ror r25 312: 87 95 ror r24 314: e0 91 79 00 lds r30, 0x0079 318: f0 91 7a 00 lds r31, 0x007A 31c: 09 95 icall return ispTransmit(0); 31e: e0 91 79 00 lds r30, 0x0079 322: f0 91 7a 00 lds r31, 0x007A 326: 80 e0 ldi r24, 0x00 ; 0 328: 09 95 icall } 32a: 1f 91 pop r17 32c: 0f 91 pop r16 32e: ff 90 pop r15 330: ef 90 pop r14 332: 08 95 ret 00000334 : uchar ispWriteFlash(unsigned long address, uchar data, uchar pollmode) { 334: cf 92 push r12 336: df 92 push r13 338: ef 92 push r14 33a: ff 92 push r15 33c: 0f 93 push r16 33e: 1f 93 push r17 340: df 93 push r29 342: cf 93 push r28 344: 0f 92 push r0 346: cd b7 in r28, 0x3d ; 61 348: de b7 in r29, 0x3e ; 62 34a: 7b 01 movw r14, r22 34c: 8c 01 movw r16, r24 34e: d4 2e mov r13, r20 if (data == 0xFF) { return 0; } */ ispUpdateExtended(address); 350: 29 83 std Y+1, r18 ; 0x01 352: be de rcall .-644 ; 0xd0 ispTransmit(0x40 | ((address & 1) << 3)); 354: 8e 2d mov r24, r14 356: 81 70 andi r24, 0x01 ; 1 358: 88 0f add r24, r24 35a: 88 0f add r24, r24 35c: 88 0f add r24, r24 35e: e0 91 79 00 lds r30, 0x0079 362: f0 91 7a 00 lds r31, 0x007A 366: 80 64 ori r24, 0x40 ; 64 368: 09 95 icall ispTransmit(address >> 9); 36a: d8 01 movw r26, r16 36c: c7 01 movw r24, r14 36e: f9 e0 ldi r31, 0x09 ; 9 370: b6 95 lsr r27 372: a7 95 ror r26 374: 97 95 ror r25 376: 87 95 ror r24 378: fa 95 dec r31 37a: d1 f7 brne .-12 ; 0x370 37c: e0 91 79 00 lds r30, 0x0079 380: f0 91 7a 00 lds r31, 0x007A 384: 09 95 icall ispTransmit(address >> 1); 386: c8 01 movw r24, r16 388: b7 01 movw r22, r14 38a: 96 95 lsr r25 38c: 87 95 ror r24 38e: 77 95 ror r23 390: 67 95 ror r22 392: e0 91 79 00 lds r30, 0x0079 396: f0 91 7a 00 lds r31, 0x007A 39a: 86 2f mov r24, r22 39c: 09 95 icall ispTransmit(data); 39e: e0 91 79 00 lds r30, 0x0079 3a2: f0 91 7a 00 lds r31, 0x007A 3a6: 8d 2d mov r24, r13 3a8: 09 95 icall if (pollmode == 0) 3aa: 29 81 ldd r18, Y+1 ; 0x01 3ac: 22 23 and r18, r18 3ae: c1 f0 breq .+48 ; 0x3e0 return 0; if (data == 0x7F) { 3b0: 8d 2d mov r24, r13 3b2: 8f 37 cpi r24, 0x7F ; 127 3b4: 19 f4 brne .+6 ; 0x3bc clockWait(15); /* wait 4,8 ms */ 3b6: 8f e0 ldi r24, 0x0F ; 15 3b8: 7b de rcall .-778 ; 0xb0 3ba: 12 c0 rjmp .+36 ; 0x3e0 return 0; } else { /* polling flash */ uchar retries = 30; uint8_t starttime = TIMERVALUE; 3bc: c2 b6 in r12, 0x32 ; 50 clockWait(15); /* wait 4,8 ms */ return 0; } else { /* polling flash */ uchar retries = 30; 3be: 5e e1 ldi r21, 0x1E ; 30 3c0: d5 2e mov r13, r21 uint8_t starttime = TIMERVALUE; while (retries != 0) { if (ispReadFlash(address) != 0x7F) { 3c2: c8 01 movw r24, r16 3c4: b7 01 movw r22, r14 3c6: 80 df rcall .-256 ; 0x2c8 3c8: 8f 37 cpi r24, 0x7F ; 127 3ca: 51 f4 brne .+20 ; 0x3e0 return 0; }; if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { 3cc: 82 b7 in r24, 0x32 ; 50 3ce: 8c 19 sub r24, r12 3d0: 8d 33 cpi r24, 0x3D ; 61 3d2: 10 f0 brcs .+4 ; 0x3d8 starttime = TIMERVALUE; 3d4: c2 b6 in r12, 0x32 ; 50 retries--; 3d6: da 94 dec r13 } else { /* polling flash */ uchar retries = 30; uint8_t starttime = TIMERVALUE; while (retries != 0) { 3d8: dd 20 and r13, r13 3da: 99 f7 brne .-26 ; 0x3c2 starttime = TIMERVALUE; retries--; } } return 1; /* error */ 3dc: 81 e0 ldi r24, 0x01 ; 1 3de: 01 c0 rjmp .+2 ; 0x3e2 /* polling flash */ uchar retries = 30; uint8_t starttime = TIMERVALUE; while (retries != 0) { if (ispReadFlash(address) != 0x7F) { return 0; 3e0: 80 e0 ldi r24, 0x00 ; 0 } return 1; /* error */ } } 3e2: 0f 90 pop r0 3e4: cf 91 pop r28 3e6: df 91 pop r29 3e8: 1f 91 pop r17 3ea: 0f 91 pop r16 3ec: ff 90 pop r15 3ee: ef 90 pop r14 3f0: df 90 pop r13 3f2: cf 90 pop r12 3f4: 08 95 ret 000003f6 : uchar ispFlushPage(unsigned long address, uchar pollvalue) { 3f6: cf 92 push r12 3f8: df 92 push r13 3fa: ef 92 push r14 3fc: ff 92 push r15 3fe: 0f 93 push r16 400: 1f 93 push r17 402: df 93 push r29 404: cf 93 push r28 406: 0f 92 push r0 408: cd b7 in r28, 0x3d ; 61 40a: de b7 in r29, 0x3e ; 62 40c: 7b 01 movw r14, r22 40e: 8c 01 movw r16, r24 ispUpdateExtended(address); 410: 49 83 std Y+1, r20 ; 0x01 412: 5e de rcall .-836 ; 0xd0 ispTransmit(0x4C); 414: e0 91 79 00 lds r30, 0x0079 418: f0 91 7a 00 lds r31, 0x007A 41c: 8c e4 ldi r24, 0x4C ; 76 41e: 09 95 icall ispTransmit(address >> 9); 420: d8 01 movw r26, r16 422: c7 01 movw r24, r14 424: 39 e0 ldi r19, 0x09 ; 9 426: b6 95 lsr r27 428: a7 95 ror r26 42a: 97 95 ror r25 42c: 87 95 ror r24 42e: 3a 95 dec r19 430: d1 f7 brne .-12 ; 0x426 432: e0 91 79 00 lds r30, 0x0079 436: f0 91 7a 00 lds r31, 0x007A 43a: 09 95 icall ispTransmit(address >> 1); 43c: d8 01 movw r26, r16 43e: c7 01 movw r24, r14 440: b6 95 lsr r27 442: a7 95 ror r26 444: 97 95 ror r25 446: 87 95 ror r24 448: e0 91 79 00 lds r30, 0x0079 44c: f0 91 7a 00 lds r31, 0x007A 450: 09 95 icall ispTransmit(0); 452: e0 91 79 00 lds r30, 0x0079 456: f0 91 7a 00 lds r31, 0x007A 45a: 80 e0 ldi r24, 0x00 ; 0 45c: 09 95 icall if (pollvalue == 0xFF) { 45e: 49 81 ldd r20, Y+1 ; 0x01 460: 4f 3f cpi r20, 0xFF ; 255 462: 19 f4 brne .+6 ; 0x46a <__stack+0xb> clockWait(15); 464: 8f e0 ldi r24, 0x0F ; 15 466: 24 de rcall .-952 ; 0xb0 468: 12 c0 rjmp .+36 ; 0x48e <__stack+0x2f> return 0; } else { /* polling flash */ uchar retries = 30; uint8_t starttime = TIMERVALUE; 46a: c2 b6 in r12, 0x32 ; 50 clockWait(15); return 0; } else { /* polling flash */ uchar retries = 30; 46c: ae e1 ldi r26, 0x1E ; 30 46e: da 2e mov r13, r26 uint8_t starttime = TIMERVALUE; while (retries != 0) { if (ispReadFlash(address) != 0xFF) { 470: c8 01 movw r24, r16 472: b7 01 movw r22, r14 474: 29 df rcall .-430 ; 0x2c8 476: 8f 3f cpi r24, 0xFF ; 255 478: 51 f4 brne .+20 ; 0x48e <__stack+0x2f> return 0; }; if ((uint8_t) (TIMERVALUE - starttime) > CLOCK_T_320us) { 47a: 82 b7 in r24, 0x32 ; 50 47c: 8c 19 sub r24, r12 47e: 8d 33 cpi r24, 0x3D ; 61 480: 10 f0 brcs .+4 ; 0x486 <__stack+0x27> starttime = TIMERVALUE; 482: c2 b6 in r12, 0x32 ; 50 retries--; 484: da 94 dec r13 /* polling flash */ uchar retries = 30; uint8_t starttime = TIMERVALUE; while (retries != 0) { 486: dd 20 and r13, r13 488: 99 f7 brne .-26 ; 0x470 <__stack+0x11> retries--; } } return 1; /* error */ 48a: 81 e0 ldi r24, 0x01 ; 1 48c: 01 c0 rjmp .+2 ; 0x490 <__stack+0x31> uchar retries = 30; uint8_t starttime = TIMERVALUE; while (retries != 0) { if (ispReadFlash(address) != 0xFF) { return 0; 48e: 80 e0 ldi r24, 0x00 ; 0 } return 1; /* error */ } } 490: 0f 90 pop r0 492: cf 91 pop r28 494: df 91 pop r29 496: 1f 91 pop r17 498: 0f 91 pop r16 49a: ff 90 pop r15 49c: ef 90 pop r14 49e: df 90 pop r13 4a0: cf 90 pop r12 4a2: 08 95 ret 000004a4 : uchar ispReadEEPROM(unsigned int address) { 4a4: 1f 93 push r17 4a6: df 93 push r29 4a8: cf 93 push r28 4aa: 0f 92 push r0 4ac: cd b7 in r28, 0x3d ; 61 4ae: de b7 in r29, 0x3e ; 62 4b0: 18 2f mov r17, r24 ispTransmit(0xA0); 4b2: e0 91 79 00 lds r30, 0x0079 4b6: f0 91 7a 00 lds r31, 0x007A 4ba: 80 ea ldi r24, 0xA0 ; 160 4bc: 99 83 std Y+1, r25 ; 0x01 4be: 09 95 icall ispTransmit(address >> 8); 4c0: e0 91 79 00 lds r30, 0x0079 4c4: f0 91 7a 00 lds r31, 0x007A 4c8: 99 81 ldd r25, Y+1 ; 0x01 4ca: 89 2f mov r24, r25 4cc: 09 95 icall ispTransmit(address); 4ce: e0 91 79 00 lds r30, 0x0079 4d2: f0 91 7a 00 lds r31, 0x007A 4d6: 81 2f mov r24, r17 4d8: 09 95 icall return ispTransmit(0); 4da: e0 91 79 00 lds r30, 0x0079 4de: f0 91 7a 00 lds r31, 0x007A 4e2: 80 e0 ldi r24, 0x00 ; 0 4e4: 09 95 icall } 4e6: 0f 90 pop r0 4e8: cf 91 pop r28 4ea: df 91 pop r29 4ec: 1f 91 pop r17 4ee: 08 95 ret 000004f0 : uchar ispWriteEEPROM(unsigned int address, uchar data) { 4f0: 1f 93 push r17 4f2: df 93 push r29 4f4: cf 93 push r28 4f6: 00 d0 rcall .+0 ; 0x4f8 4f8: cd b7 in r28, 0x3d ; 61 4fa: de b7 in r29, 0x3e ; 62 4fc: 18 2f mov r17, r24 ispTransmit(0xC0); 4fe: e0 91 79 00 lds r30, 0x0079 502: f0 91 7a 00 lds r31, 0x007A 506: 80 ec ldi r24, 0xC0 ; 192 508: 6a 83 std Y+2, r22 ; 0x02 50a: 99 83 std Y+1, r25 ; 0x01 50c: 09 95 icall ispTransmit(address >> 8); 50e: e0 91 79 00 lds r30, 0x0079 512: f0 91 7a 00 lds r31, 0x007A 516: 99 81 ldd r25, Y+1 ; 0x01 518: 89 2f mov r24, r25 51a: 09 95 icall ispTransmit(address); 51c: e0 91 79 00 lds r30, 0x0079 520: f0 91 7a 00 lds r31, 0x007A 524: 81 2f mov r24, r17 526: 09 95 icall ispTransmit(data); 528: e0 91 79 00 lds r30, 0x0079 52c: f0 91 7a 00 lds r31, 0x007A 530: 6a 81 ldd r22, Y+2 ; 0x02 532: 86 2f mov r24, r22 534: 09 95 icall clockWait(30); // wait 9,6 ms 536: 8e e1 ldi r24, 0x1E ; 30 538: bb dd rcall .-1162 ; 0xb0 return 0; } 53a: 80 e0 ldi r24, 0x00 ; 0 53c: 0f 90 pop r0 53e: 0f 90 pop r0 540: cf 91 pop r28 542: df 91 pop r29 544: 1f 91 pop r17 546: 08 95 ret 00000548 : static unsigned int prog_nbytes = 0; static unsigned int prog_pagesize; static uchar prog_blockflags; static uchar prog_pagecounter; uchar usbFunctionSetup(uchar data[8]) { 548: cf 93 push r28 54a: df 93 push r29 54c: ec 01 movw r28, r24 uchar len = 0; if (data[1] == USBASP_FUNC_CONNECT) { 54e: 89 81 ldd r24, Y+1 ; 0x01 550: 81 30 cpi r24, 0x01 ; 1 552: 61 f4 brne .+24 ; 0x56c /* set SCK speed */ if ((PINC & (1 << PC2)) == 0) { 554: 9a 99 sbic 0x13, 2 ; 19 556: 02 c0 rjmp .+4 ; 0x55c ispSetSCKOption(USBASP_ISP_SCK_8); 558: 85 e0 ldi r24, 0x05 ; 5 55a: 02 c0 rjmp .+4 ; 0x560 } else { ispSetSCKOption(prog_sck); 55c: 80 91 6d 00 lds r24, 0x006D 560: e5 dd rcall .-1078 ; 0x12c } /* set compatibility mode of address delivering */ prog_address_newmode = 0; 562: 10 92 6e 00 sts 0x006E, r1 ledRedOn(); 566: a9 98 cbi 0x15, 1 ; 21 ispConnect(); 568: 5c de rcall .-840 ; 0x222 56a: 7b c1 rjmp .+758 ; 0x862 } else if (data[1] == USBASP_FUNC_DISCONNECT) { 56c: 82 30 cpi r24, 0x02 ; 2 56e: 11 f4 brne .+4 ; 0x574 ispDisconnect(); 570: 6d de rcall .-806 ; 0x24c 572: 19 c1 rjmp .+562 ; 0x7a6 ledRedOff(); } else if (data[1] == USBASP_FUNC_TRANSMIT) { 574: 83 30 cpi r24, 0x03 ; 3 576: 09 f5 brne .+66 ; 0x5ba replyBuffer[0] = ispTransmit(data[2]); 578: e0 91 79 00 lds r30, 0x0079 57c: f0 91 7a 00 lds r31, 0x007A 580: 8a 81 ldd r24, Y+2 ; 0x02 582: 09 95 icall 584: 80 93 6f 00 sts 0x006F, r24 replyBuffer[1] = ispTransmit(data[3]); 588: e0 91 79 00 lds r30, 0x0079 58c: f0 91 7a 00 lds r31, 0x007A 590: 8b 81 ldd r24, Y+3 ; 0x03 592: 09 95 icall 594: 80 93 70 00 sts 0x0070, r24 replyBuffer[2] = ispTransmit(data[4]); 598: e0 91 79 00 lds r30, 0x0079 59c: f0 91 7a 00 lds r31, 0x007A 5a0: 8c 81 ldd r24, Y+4 ; 0x04 5a2: 09 95 icall 5a4: 80 93 71 00 sts 0x0071, r24 replyBuffer[3] = ispTransmit(data[5]); 5a8: e0 91 79 00 lds r30, 0x0079 5ac: f0 91 7a 00 lds r31, 0x007A 5b0: 8d 81 ldd r24, Y+5 ; 0x05 5b2: 09 95 icall 5b4: 80 93 72 00 sts 0x0072, r24 5b8: 52 c1 rjmp .+676 ; 0x85e len = 4; } else if (data[1] == USBASP_FUNC_READFLASH) { 5ba: 84 30 cpi r24, 0x04 ; 4 5bc: 11 f5 brne .+68 ; 0x602 if (!prog_address_newmode) 5be: 80 91 6e 00 lds r24, 0x006E 5c2: 88 23 and r24, r24 5c4: 91 f4 brne .+36 ; 0x5ea prog_address = (data[3] << 8) | data[2]; 5c6: 3b 81 ldd r19, Y+3 ; 0x03 5c8: 20 e0 ldi r18, 0x00 ; 0 5ca: 8a 81 ldd r24, Y+2 ; 0x02 5cc: 90 e0 ldi r25, 0x00 ; 0 5ce: 82 2b or r24, r18 5d0: 93 2b or r25, r19 5d2: aa 27 eor r26, r26 5d4: 97 fd sbrc r25, 7 5d6: a0 95 com r26 5d8: ba 2f mov r27, r26 5da: 80 93 63 00 sts 0x0063, r24 5de: 90 93 64 00 sts 0x0064, r25 5e2: a0 93 65 00 sts 0x0065, r26 5e6: b0 93 66 00 sts 0x0066, r27 prog_nbytes = (data[7] << 8) | data[6]; 5ea: 3f 81 ldd r19, Y+7 ; 0x07 5ec: 20 e0 ldi r18, 0x00 ; 0 5ee: 8e 81 ldd r24, Y+6 ; 0x06 5f0: 90 e0 ldi r25, 0x00 ; 0 5f2: 82 2b or r24, r18 5f4: 93 2b or r25, r19 5f6: 90 93 68 00 sts 0x0068, r25 5fa: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_READFLASH; 5fe: 82 e0 ldi r24, 0x02 ; 2 600: 1f c1 rjmp .+574 ; 0x840 len = 0xff; /* multiple in */ } else if (data[1] == USBASP_FUNC_READEEPROM) { 602: 87 30 cpi r24, 0x07 ; 7 604: 11 f5 brne .+68 ; 0x64a if (!prog_address_newmode) 606: 80 91 6e 00 lds r24, 0x006E 60a: 88 23 and r24, r24 60c: 91 f4 brne .+36 ; 0x632 prog_address = (data[3] << 8) | data[2]; 60e: 3b 81 ldd r19, Y+3 ; 0x03 610: 20 e0 ldi r18, 0x00 ; 0 612: 8a 81 ldd r24, Y+2 ; 0x02 614: 90 e0 ldi r25, 0x00 ; 0 616: 82 2b or r24, r18 618: 93 2b or r25, r19 61a: aa 27 eor r26, r26 61c: 97 fd sbrc r25, 7 61e: a0 95 com r26 620: ba 2f mov r27, r26 622: 80 93 63 00 sts 0x0063, r24 626: 90 93 64 00 sts 0x0064, r25 62a: a0 93 65 00 sts 0x0065, r26 62e: b0 93 66 00 sts 0x0066, r27 prog_nbytes = (data[7] << 8) | data[6]; 632: 3f 81 ldd r19, Y+7 ; 0x07 634: 20 e0 ldi r18, 0x00 ; 0 636: 8e 81 ldd r24, Y+6 ; 0x06 638: 90 e0 ldi r25, 0x00 ; 0 63a: 82 2b or r24, r18 63c: 93 2b or r25, r19 63e: 90 93 68 00 sts 0x0068, r25 642: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_READEEPROM; 646: 83 e0 ldi r24, 0x03 ; 3 648: fb c0 rjmp .+502 ; 0x840 len = 0xff; /* multiple in */ } else if (data[1] == USBASP_FUNC_ENABLEPROG) { 64a: 85 30 cpi r24, 0x05 ; 5 64c: 11 f4 brne .+4 ; 0x652 replyBuffer[0] = ispEnterProgrammingMode(); 64e: 06 de rcall .-1012 ; 0x25c 650: af c0 rjmp .+350 ; 0x7b0 len = 1; } else if (data[1] == USBASP_FUNC_WRITEFLASH) { 652: 86 30 cpi r24, 0x06 ; 6 654: d1 f5 brne .+116 ; 0x6ca if (!prog_address_newmode) 656: 80 91 6e 00 lds r24, 0x006E 65a: 88 23 and r24, r24 65c: 91 f4 brne .+36 ; 0x682 prog_address = (data[3] << 8) | data[2]; 65e: 3b 81 ldd r19, Y+3 ; 0x03 660: 20 e0 ldi r18, 0x00 ; 0 662: 8a 81 ldd r24, Y+2 ; 0x02 664: 90 e0 ldi r25, 0x00 ; 0 666: 82 2b or r24, r18 668: 93 2b or r25, r19 66a: aa 27 eor r26, r26 66c: 97 fd sbrc r25, 7 66e: a0 95 com r26 670: ba 2f mov r27, r26 672: 80 93 63 00 sts 0x0063, r24 676: 90 93 64 00 sts 0x0064, r25 67a: a0 93 65 00 sts 0x0065, r26 67e: b0 93 66 00 sts 0x0066, r27 prog_pagesize = data[4]; 682: 3c 81 ldd r19, Y+4 ; 0x04 prog_blockflags = data[5] & 0x0F; 684: 8d 81 ldd r24, Y+5 ; 0x05 686: 28 2f mov r18, r24 688: 2f 70 andi r18, 0x0F ; 15 68a: 20 93 6c 00 sts 0x006C, r18 prog_pagesize += (((unsigned int) data[5] & 0xF0) << 4); 68e: 90 e0 ldi r25, 0x00 ; 0 690: 80 7f andi r24, 0xF0 ; 240 692: 90 70 andi r25, 0x00 ; 0 694: 44 e0 ldi r20, 0x04 ; 4 696: 88 0f add r24, r24 698: 99 1f adc r25, r25 69a: 4a 95 dec r20 69c: e1 f7 brne .-8 ; 0x696 69e: 83 0f add r24, r19 6a0: 91 1d adc r25, r1 6a2: 90 93 6a 00 sts 0x006A, r25 6a6: 80 93 69 00 sts 0x0069, r24 if (prog_blockflags & PROG_BLOCKFLAG_FIRST) { 6aa: 20 ff sbrs r18, 0 6ac: 02 c0 rjmp .+4 ; 0x6b2 prog_pagecounter = prog_pagesize; 6ae: 80 93 6b 00 sts 0x006B, r24 } prog_nbytes = (data[7] << 8) | data[6]; 6b2: 3f 81 ldd r19, Y+7 ; 0x07 6b4: 20 e0 ldi r18, 0x00 ; 0 6b6: 8e 81 ldd r24, Y+6 ; 0x06 6b8: 90 e0 ldi r25, 0x00 ; 0 6ba: 82 2b or r24, r18 6bc: 93 2b or r25, r19 6be: 90 93 68 00 sts 0x0068, r25 6c2: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_WRITEFLASH; 6c6: 81 e0 ldi r24, 0x01 ; 1 6c8: bb c0 rjmp .+374 ; 0x840 len = 0xff; /* multiple out */ } else if (data[1] == USBASP_FUNC_WRITEEEPROM) { 6ca: 88 30 cpi r24, 0x08 ; 8 6cc: 41 f5 brne .+80 ; 0x71e if (!prog_address_newmode) 6ce: 80 91 6e 00 lds r24, 0x006E 6d2: 88 23 and r24, r24 6d4: 91 f4 brne .+36 ; 0x6fa prog_address = (data[3] << 8) | data[2]; 6d6: 3b 81 ldd r19, Y+3 ; 0x03 6d8: 20 e0 ldi r18, 0x00 ; 0 6da: 8a 81 ldd r24, Y+2 ; 0x02 6dc: 90 e0 ldi r25, 0x00 ; 0 6de: 82 2b or r24, r18 6e0: 93 2b or r25, r19 6e2: aa 27 eor r26, r26 6e4: 97 fd sbrc r25, 7 6e6: a0 95 com r26 6e8: ba 2f mov r27, r26 6ea: 80 93 63 00 sts 0x0063, r24 6ee: 90 93 64 00 sts 0x0064, r25 6f2: a0 93 65 00 sts 0x0065, r26 6f6: b0 93 66 00 sts 0x0066, r27 prog_pagesize = 0; 6fa: 10 92 6a 00 sts 0x006A, r1 6fe: 10 92 69 00 sts 0x0069, r1 prog_blockflags = 0; 702: 10 92 6c 00 sts 0x006C, r1 prog_nbytes = (data[7] << 8) | data[6]; 706: 3f 81 ldd r19, Y+7 ; 0x07 708: 20 e0 ldi r18, 0x00 ; 0 70a: 8e 81 ldd r24, Y+6 ; 0x06 70c: 90 e0 ldi r25, 0x00 ; 0 70e: 82 2b or r24, r18 710: 93 2b or r25, r19 712: 90 93 68 00 sts 0x0068, r25 716: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_WRITEEEPROM; 71a: 84 e0 ldi r24, 0x04 ; 4 71c: 91 c0 rjmp .+290 ; 0x840 len = 0xff; /* multiple out */ } else if (data[1] == USBASP_FUNC_SETLONGADDRESS) { 71e: 89 30 cpi r24, 0x09 ; 9 720: 81 f4 brne .+32 ; 0x742 /* set new mode of address delivering (ignore address delivered in commands) */ prog_address_newmode = 1; 722: 81 e0 ldi r24, 0x01 ; 1 724: 80 93 6e 00 sts 0x006E, r24 /* set new address */ prog_address = *((unsigned long*) &data[2]); 728: 8a 81 ldd r24, Y+2 ; 0x02 72a: 9b 81 ldd r25, Y+3 ; 0x03 72c: ac 81 ldd r26, Y+4 ; 0x04 72e: bd 81 ldd r27, Y+5 ; 0x05 730: 80 93 63 00 sts 0x0063, r24 734: 90 93 64 00 sts 0x0064, r25 738: a0 93 65 00 sts 0x0065, r26 73c: b0 93 66 00 sts 0x0066, r27 740: 90 c0 rjmp .+288 ; 0x862 } else if (data[1] == USBASP_FUNC_SETISPSCK) { 742: 8a 30 cpi r24, 0x0A ; 10 744: 31 f4 brne .+12 ; 0x752 /* set sck option */ prog_sck = data[2]; 746: 8a 81 ldd r24, Y+2 ; 0x02 748: 80 93 6d 00 sts 0x006D, r24 replyBuffer[0] = 0; 74c: 10 92 6f 00 sts 0x006F, r1 750: 31 c0 rjmp .+98 ; 0x7b4 len = 1; } else if (data[1] == USBASP_FUNC_TPI_CONNECT) { 752: 8b 30 cpi r24, 0x0B ; 11 754: a1 f4 brne .+40 ; 0x77e tpi_dly_cnt = data[2] | (data[3] << 8); 756: 3b 81 ldd r19, Y+3 ; 0x03 758: 20 e0 ldi r18, 0x00 ; 0 75a: 8a 81 ldd r24, Y+2 ; 0x02 75c: 90 e0 ldi r25, 0x00 ; 0 75e: 82 2b or r24, r18 760: 93 2b or r25, r19 762: 90 93 7f 00 sts 0x007F, r25 766: 80 93 7e 00 sts 0x007E, r24 /* RST high */ ISP_OUT |= (1 << ISP_RST); 76a: c2 9a sbi 0x18, 2 ; 24 ISP_DDR |= (1 << ISP_RST); 76c: ba 9a sbi 0x17, 2 ; 23 clockWait(3); 76e: 83 e0 ldi r24, 0x03 ; 3 770: 9f dc rcall .-1730 ; 0xb0 /* RST low */ ISP_OUT &= ~(1 << ISP_RST); 772: c2 98 cbi 0x18, 2 ; 24 ledRedOn(); 774: a9 98 cbi 0x15, 1 ; 21 clockWait(16); 776: 80 e1 ldi r24, 0x10 ; 16 778: 9b dc rcall .-1738 ; 0xb0 tpi_init(); 77a: db d1 rcall .+950 ; 0xb32 77c: 72 c0 rjmp .+228 ; 0x862 } else if (data[1] == USBASP_FUNC_TPI_DISCONNECT) { 77e: 8c 30 cpi r24, 0x0C ; 12 780: a1 f4 brne .+40 ; 0x7aa tpi_send_byte(TPI_OP_SSTCS(TPISR)); 782: 80 ec ldi r24, 0xC0 ; 192 784: e6 d1 rcall .+972 ; 0xb52 tpi_send_byte(0); 786: 80 e0 ldi r24, 0x00 ; 0 788: e4 d1 rcall .+968 ; 0xb52 clockWait(10); 78a: 8a e0 ldi r24, 0x0A ; 10 78c: 91 dc rcall .-1758 ; 0xb0 /* pulse RST */ ISP_OUT |= (1 << ISP_RST); 78e: c2 9a sbi 0x18, 2 ; 24 clockWait(5); 790: 85 e0 ldi r24, 0x05 ; 5 792: 8e dc rcall .-1764 ; 0xb0 ISP_OUT &= ~(1 << ISP_RST); 794: c2 98 cbi 0x18, 2 ; 24 clockWait(5); 796: 85 e0 ldi r24, 0x05 ; 5 798: 8b dc rcall .-1770 ; 0xb0 /* set all ISP pins inputs */ ISP_DDR &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); 79a: 87 b3 in r24, 0x17 ; 23 79c: 83 7d andi r24, 0xD3 ; 211 79e: 87 bb out 0x17, r24 ; 23 /* switch pullups off */ ISP_OUT &= ~((1 << ISP_RST) | (1 << ISP_SCK) | (1 << ISP_MOSI)); 7a0: 88 b3 in r24, 0x18 ; 24 7a2: 83 7d andi r24, 0xD3 ; 211 7a4: 88 bb out 0x18, r24 ; 24 ledRedOff(); 7a6: a9 9a sbi 0x15, 1 ; 21 7a8: 5c c0 rjmp .+184 ; 0x862 } else if (data[1] == USBASP_FUNC_TPI_RAWREAD) { 7aa: 8d 30 cpi r24, 0x0D ; 13 7ac: 29 f4 brne .+10 ; 0x7b8 replyBuffer[0] = tpi_recv_byte(); 7ae: f4 d1 rcall .+1000 ; 0xb98 7b0: 80 93 6f 00 sts 0x006F, r24 len = 1; 7b4: 81 e0 ldi r24, 0x01 ; 1 7b6: 56 c0 rjmp .+172 ; 0x864 } else if (data[1] == USBASP_FUNC_TPI_RAWWRITE) { 7b8: 8e 30 cpi r24, 0x0E ; 14 7ba: 19 f4 brne .+6 ; 0x7c2 tpi_send_byte(data[2]); 7bc: 8a 81 ldd r24, Y+2 ; 0x02 7be: c9 d1 rcall .+914 ; 0xb52 7c0: 50 c0 rjmp .+160 ; 0x862 } else if (data[1] == USBASP_FUNC_TPI_READBLOCK) { 7c2: 8f 30 cpi r24, 0x0F ; 15 7c4: f1 f4 brne .+60 ; 0x802 prog_address = (data[3] << 8) | data[2]; 7c6: 3b 81 ldd r19, Y+3 ; 0x03 7c8: 20 e0 ldi r18, 0x00 ; 0 7ca: 8a 81 ldd r24, Y+2 ; 0x02 7cc: 90 e0 ldi r25, 0x00 ; 0 7ce: 82 2b or r24, r18 7d0: 93 2b or r25, r19 7d2: aa 27 eor r26, r26 7d4: 97 fd sbrc r25, 7 7d6: a0 95 com r26 7d8: ba 2f mov r27, r26 7da: 80 93 63 00 sts 0x0063, r24 7de: 90 93 64 00 sts 0x0064, r25 7e2: a0 93 65 00 sts 0x0065, r26 7e6: b0 93 66 00 sts 0x0066, r27 prog_nbytes = (data[7] << 8) | data[6]; 7ea: 3f 81 ldd r19, Y+7 ; 0x07 7ec: 20 e0 ldi r18, 0x00 ; 0 7ee: 8e 81 ldd r24, Y+6 ; 0x06 7f0: 90 e0 ldi r25, 0x00 ; 0 7f2: 82 2b or r24, r18 7f4: 93 2b or r25, r19 7f6: 90 93 68 00 sts 0x0068, r25 7fa: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_TPI_READ; 7fe: 85 e0 ldi r24, 0x05 ; 5 800: 1f c0 rjmp .+62 ; 0x840 len = 0xff; /* multiple in */ } else if (data[1] == USBASP_FUNC_TPI_WRITEBLOCK) { 802: 80 31 cpi r24, 0x10 ; 16 804: 09 f5 brne .+66 ; 0x848 prog_address = (data[3] << 8) | data[2]; 806: 3b 81 ldd r19, Y+3 ; 0x03 808: 20 e0 ldi r18, 0x00 ; 0 80a: 8a 81 ldd r24, Y+2 ; 0x02 80c: 90 e0 ldi r25, 0x00 ; 0 80e: 82 2b or r24, r18 810: 93 2b or r25, r19 812: aa 27 eor r26, r26 814: 97 fd sbrc r25, 7 816: a0 95 com r26 818: ba 2f mov r27, r26 81a: 80 93 63 00 sts 0x0063, r24 81e: 90 93 64 00 sts 0x0064, r25 822: a0 93 65 00 sts 0x0065, r26 826: b0 93 66 00 sts 0x0066, r27 prog_nbytes = (data[7] << 8) | data[6]; 82a: 3f 81 ldd r19, Y+7 ; 0x07 82c: 20 e0 ldi r18, 0x00 ; 0 82e: 8e 81 ldd r24, Y+6 ; 0x06 830: 90 e0 ldi r25, 0x00 ; 0 832: 82 2b or r24, r18 834: 93 2b or r25, r19 836: 90 93 68 00 sts 0x0068, r25 83a: 80 93 67 00 sts 0x0067, r24 prog_state = PROG_STATE_TPI_WRITE; 83e: 86 e0 ldi r24, 0x06 ; 6 840: 80 93 62 00 sts 0x0062, r24 len = 0xff; /* multiple out */ 844: 8f ef ldi r24, 0xFF ; 255 846: 0e c0 rjmp .+28 ; 0x864 } else if (data[1] == USBASP_FUNC_GETCAPABILITIES) { 848: 8f 37 cpi r24, 0x7F ; 127 84a: 59 f4 brne .+22 ; 0x862 replyBuffer[0] = USBASP_CAP_0_TPI; 84c: 81 e0 ldi r24, 0x01 ; 1 84e: 80 93 6f 00 sts 0x006F, r24 replyBuffer[1] = 0; 852: 10 92 70 00 sts 0x0070, r1 replyBuffer[2] = 0; 856: 10 92 71 00 sts 0x0071, r1 replyBuffer[3] = 0; 85a: 10 92 72 00 sts 0x0072, r1 len = 4; 85e: 84 e0 ldi r24, 0x04 ; 4 860: 01 c0 rjmp .+2 ; 0x864 static uchar prog_blockflags; static uchar prog_pagecounter; uchar usbFunctionSetup(uchar data[8]) { uchar len = 0; 862: 80 e0 ldi r24, 0x00 ; 0 replyBuffer[2] = 0; replyBuffer[3] = 0; len = 4; } usbMsgPtr = replyBuffer; 864: 2f e6 ldi r18, 0x6F ; 111 866: 30 e0 ldi r19, 0x00 ; 0 868: 30 93 8f 00 sts 0x008F, r19 86c: 20 93 8e 00 sts 0x008E, r18 return len; } 870: df 91 pop r29 872: cf 91 pop r28 874: 08 95 ret 00000876 : uchar usbFunctionRead(uchar *data, uchar len) { 876: ef 92 push r14 878: ff 92 push r15 87a: 0f 93 push r16 87c: 1f 93 push r17 87e: cf 93 push r28 880: df 93 push r29 882: 08 2f mov r16, r24 884: 79 2f mov r23, r25 886: 16 2f mov r17, r22 uchar i; /* check if programmer is in correct read state */ if ((prog_state != PROG_STATE_READFLASH) && (prog_state 888: 80 91 62 00 lds r24, 0x0062 88c: 98 2f mov r25, r24 88e: 92 50 subi r25, 0x02 ; 2 890: 92 30 cpi r25, 0x02 ; 2 892: 30 f4 brcc .+12 ; 0x8a0 894: e0 2e mov r14, r16 896: e7 01 movw r28, r14 898: 7e 01 movw r14, r28 89a: f7 2e mov r15, r23 89c: e7 01 movw r28, r14 89e: 4a c0 rjmp .+148 ; 0x934 != PROG_STATE_READEEPROM) && (prog_state != PROG_STATE_TPI_READ)) { 8a0: 85 30 cpi r24, 0x05 ; 5 8a2: 09 f0 breq .+2 ; 0x8a6 8a4: 50 c0 rjmp .+160 ; 0x946 } /* fill packet TPI mode */ if(prog_state == PROG_STATE_TPI_READ) { tpi_read_block(prog_address, data, len); 8a6: 80 91 63 00 lds r24, 0x0063 8aa: 90 91 64 00 lds r25, 0x0064 8ae: 60 2f mov r22, r16 8b0: 41 2f mov r20, r17 8b2: 8b d1 rcall .+790 ; 0xbca prog_address += len; 8b4: 20 91 63 00 lds r18, 0x0063 8b8: 30 91 64 00 lds r19, 0x0064 8bc: 40 91 65 00 lds r20, 0x0065 8c0: 50 91 66 00 lds r21, 0x0066 8c4: 21 0f add r18, r17 8c6: 31 1d adc r19, r1 8c8: 41 1d adc r20, r1 8ca: 51 1d adc r21, r1 8cc: 20 93 63 00 sts 0x0063, r18 8d0: 30 93 64 00 sts 0x0064, r19 8d4: 40 93 65 00 sts 0x0065, r20 8d8: 50 93 66 00 sts 0x0066, r21 return len; 8dc: 35 c0 rjmp .+106 ; 0x948 } /* fill packet ISP mode */ for (i = 0; i < len; i++) { if (prog_state == PROG_STATE_READFLASH) { 8de: 80 91 62 00 lds r24, 0x0062 8e2: 82 30 cpi r24, 0x02 ; 2 8e4: 61 f4 brne .+24 ; 0x8fe data[i] = ispReadFlash(prog_address); 8e6: 20 91 63 00 lds r18, 0x0063 8ea: 30 91 64 00 lds r19, 0x0064 8ee: 40 91 65 00 lds r20, 0x0065 8f2: 50 91 66 00 lds r21, 0x0066 8f6: ca 01 movw r24, r20 8f8: b9 01 movw r22, r18 8fa: e6 dc rcall .-1588 ; 0x2c8 8fc: 05 c0 rjmp .+10 ; 0x908 } else { data[i] = ispReadEEPROM(prog_address); 8fe: 80 91 63 00 lds r24, 0x0063 902: 90 91 64 00 lds r25, 0x0064 906: ce dd rcall .-1124 ; 0x4a4 908: 88 83 st Y, r24 } prog_address++; 90a: 20 91 63 00 lds r18, 0x0063 90e: 30 91 64 00 lds r19, 0x0064 912: 40 91 65 00 lds r20, 0x0065 916: 50 91 66 00 lds r21, 0x0066 91a: 2f 5f subi r18, 0xFF ; 255 91c: 3f 4f sbci r19, 0xFF ; 255 91e: 4f 4f sbci r20, 0xFF ; 255 920: 5f 4f sbci r21, 0xFF ; 255 922: 20 93 63 00 sts 0x0063, r18 926: 30 93 64 00 sts 0x0064, r19 92a: 40 93 65 00 sts 0x0065, r20 92e: 50 93 66 00 sts 0x0066, r21 932: 21 96 adiw r28, 0x01 ; 1 prog_address += len; return len; } /* fill packet ISP mode */ for (i = 0; i < len; i++) { 934: 7e 01 movw r14, r28 936: e0 1a sub r14, r16 938: e1 16 cp r14, r17 93a: 88 f2 brcs .-94 ; 0x8de } prog_address++; } /* last packet? */ if (len < 8) { 93c: 18 30 cpi r17, 0x08 ; 8 93e: 20 f4 brcc .+8 ; 0x948 prog_state = PROG_STATE_IDLE; 940: 10 92 62 00 sts 0x0062, r1 944: 01 c0 rjmp .+2 ; 0x948 uchar i; /* check if programmer is in correct read state */ if ((prog_state != PROG_STATE_READFLASH) && (prog_state != PROG_STATE_READEEPROM) && (prog_state != PROG_STATE_TPI_READ)) { return 0xff; 946: 1f ef ldi r17, 0xFF ; 255 if (len < 8) { prog_state = PROG_STATE_IDLE; } return len; } 948: 81 2f mov r24, r17 94a: df 91 pop r29 94c: cf 91 pop r28 94e: 1f 91 pop r17 950: 0f 91 pop r16 952: ff 90 pop r15 954: ef 90 pop r14 956: 08 95 ret 00000958 : uchar usbFunctionWrite(uchar *data, uchar len) { 958: cf 92 push r12 95a: df 92 push r13 95c: ef 92 push r14 95e: ff 92 push r15 960: 0f 93 push r16 962: 1f 93 push r17 964: df 93 push r29 966: cf 93 push r28 968: 0f 92 push r0 96a: cd b7 in r28, 0x3d ; 61 96c: de b7 in r29, 0x3e ; 62 96e: 6c 01 movw r12, r24 970: f6 2e mov r15, r22 uchar retVal = 0; uchar i; /* check if programmer is in correct write state */ if ((prog_state != PROG_STATE_WRITEFLASH) && (prog_state 972: 80 91 62 00 lds r24, 0x0062 976: 81 30 cpi r24, 0x01 ; 1 978: 09 f4 brne .+2 ; 0x97c 97a: b7 c0 rjmp .+366 ; 0xaea 97c: 84 30 cpi r24, 0x04 ; 4 97e: 09 f4 brne .+2 ; 0x982 980: b4 c0 rjmp .+360 ; 0xaea != PROG_STATE_WRITEEEPROM) && (prog_state != PROG_STATE_TPI_WRITE)) { 982: 86 30 cpi r24, 0x06 ; 6 984: 09 f0 breq .+2 ; 0x988 986: b7 c0 rjmp .+366 ; 0xaf6 return 0xff; } if (prog_state == PROG_STATE_TPI_WRITE) { tpi_write_block(prog_address, data, len); 988: 80 91 63 00 lds r24, 0x0063 98c: 90 91 64 00 lds r25, 0x0064 990: b6 01 movw r22, r12 992: 4f 2d mov r20, r15 994: 24 d1 rcall .+584 ; 0xbde prog_address += len; 996: 80 91 63 00 lds r24, 0x0063 99a: 90 91 64 00 lds r25, 0x0064 99e: a0 91 65 00 lds r26, 0x0065 9a2: b0 91 66 00 lds r27, 0x0066 9a6: 8f 0d add r24, r15 9a8: 91 1d adc r25, r1 9aa: a1 1d adc r26, r1 9ac: b1 1d adc r27, r1 9ae: 80 93 63 00 sts 0x0063, r24 9b2: 90 93 64 00 sts 0x0064, r25 9b6: a0 93 65 00 sts 0x0065, r26 9ba: b0 93 66 00 sts 0x0066, r27 prog_nbytes -= len; 9be: 80 91 67 00 lds r24, 0x0067 9c2: 90 91 68 00 lds r25, 0x0068 9c6: 8f 19 sub r24, r15 9c8: 91 09 sbc r25, r1 9ca: 90 93 68 00 sts 0x0068, r25 9ce: 80 93 67 00 sts 0x0067, r24 if(prog_nbytes <= 0) 9d2: 00 97 sbiw r24, 0x00 ; 0 9d4: 09 f0 breq .+2 ; 0x9d8 9d6: 91 c0 rjmp .+290 ; 0xafa { prog_state = PROG_STATE_IDLE; 9d8: 10 92 62 00 sts 0x0062, r1 return 1; 9dc: 31 e0 ldi r19, 0x01 ; 1 9de: 8e c0 rjmp .+284 ; 0xafc return 0; } for (i = 0; i < len; i++) { if (prog_state == PROG_STATE_WRITEFLASH) { 9e0: 80 91 62 00 lds r24, 0x0062 9e4: 81 30 cpi r24, 0x01 ; 1 9e6: c1 f5 brne .+112 ; 0xa58 /* Flash */ if (prog_pagesize == 0) { 9e8: 40 91 69 00 lds r20, 0x0069 9ec: 50 91 6a 00 lds r21, 0x006A 9f0: 60 91 63 00 lds r22, 0x0063 9f4: 70 91 64 00 lds r23, 0x0064 9f8: 80 91 65 00 lds r24, 0x0065 9fc: 90 91 66 00 lds r25, 0x0066 a00: 0e 2d mov r16, r14 a02: 10 e0 ldi r17, 0x00 ; 0 a04: 41 15 cp r20, r1 a06: 51 05 cpc r21, r1 a08: 41 f4 brne .+16 ; 0xa1a /* not paged */ ispWriteFlash(prog_address, data[i], 1); a0a: f6 01 movw r30, r12 a0c: e0 0f add r30, r16 a0e: f1 1f adc r31, r17 a10: 40 81 ld r20, Z a12: 21 e0 ldi r18, 0x01 ; 1 a14: 39 83 std Y+1, r19 ; 0x01 a16: 8e dc rcall .-1764 ; 0x334 a18: 29 c0 rjmp .+82 ; 0xa6c } else { /* paged */ ispWriteFlash(prog_address, data[i], 0); a1a: 0c 0d add r16, r12 a1c: 1d 1d adc r17, r13 a1e: f8 01 movw r30, r16 a20: 40 81 ld r20, Z a22: 20 e0 ldi r18, 0x00 ; 0 a24: 39 83 std Y+1, r19 ; 0x01 a26: 86 dc rcall .-1780 ; 0x334 prog_pagecounter--; a28: 80 91 6b 00 lds r24, 0x006B a2c: 81 50 subi r24, 0x01 ; 1 a2e: 80 93 6b 00 sts 0x006B, r24 if (prog_pagecounter == 0) { a32: 39 81 ldd r19, Y+1 ; 0x01 a34: 88 23 and r24, r24 a36: d9 f4 brne .+54 ; 0xa6e ispFlushPage(prog_address, data[i]); a38: 60 91 63 00 lds r22, 0x0063 a3c: 70 91 64 00 lds r23, 0x0064 a40: 80 91 65 00 lds r24, 0x0065 a44: 90 91 66 00 lds r25, 0x0066 a48: f8 01 movw r30, r16 a4a: 40 81 ld r20, Z a4c: d4 dc rcall .-1624 ; 0x3f6 prog_pagecounter = prog_pagesize; a4e: 80 91 69 00 lds r24, 0x0069 a52: 80 93 6b 00 sts 0x006B, r24 a56: 0a c0 rjmp .+20 ; 0xa6c } } } else { /* EEPROM */ ispWriteEEPROM(prog_address, data[i]); a58: f6 01 movw r30, r12 a5a: ee 0d add r30, r14 a5c: f1 1d adc r31, r1 a5e: 80 91 63 00 lds r24, 0x0063 a62: 90 91 64 00 lds r25, 0x0064 a66: 60 81 ld r22, Z a68: 39 83 std Y+1, r19 ; 0x01 a6a: 42 dd rcall .-1404 ; 0x4f0 a6c: 39 81 ldd r19, Y+1 ; 0x01 } prog_nbytes--; a6e: 80 91 67 00 lds r24, 0x0067 a72: 90 91 68 00 lds r25, 0x0068 a76: 01 97 sbiw r24, 0x01 ; 1 a78: 90 93 68 00 sts 0x0068, r25 a7c: 80 93 67 00 sts 0x0067, r24 if (prog_nbytes == 0) { a80: 00 97 sbiw r24, 0x00 ; 0 a82: f1 f4 brne .+60 ; 0xac0 prog_state = PROG_STATE_IDLE; a84: 10 92 62 00 sts 0x0062, r1 if ((prog_blockflags & PROG_BLOCKFLAG_LAST) && (prog_pagecounter a88: 80 91 6c 00 lds r24, 0x006C a8c: 81 ff sbrs r24, 1 a8e: 17 c0 rjmp .+46 ; 0xabe != prog_pagesize)) { a90: 20 91 6b 00 lds r18, 0x006B a94: 30 e0 ldi r19, 0x00 ; 0 prog_nbytes--; if (prog_nbytes == 0) { prog_state = PROG_STATE_IDLE; if ((prog_blockflags & PROG_BLOCKFLAG_LAST) && (prog_pagecounter a96: 80 91 69 00 lds r24, 0x0069 a9a: 90 91 6a 00 lds r25, 0x006A a9e: 28 17 cp r18, r24 aa0: 39 07 cpc r19, r25 aa2: 69 f0 breq .+26 ; 0xabe != prog_pagesize)) { /* last block and page flush pending, so flush it now */ ispFlushPage(prog_address, data[i]); aa4: 60 91 63 00 lds r22, 0x0063 aa8: 70 91 64 00 lds r23, 0x0064 aac: 80 91 65 00 lds r24, 0x0065 ab0: 90 91 66 00 lds r25, 0x0066 ab4: f6 01 movw r30, r12 ab6: ee 0d add r30, r14 ab8: f1 1d adc r31, r1 aba: 40 81 ld r20, Z abc: 9c dc rcall .-1736 ; 0x3f6 } retVal = 1; // Need to return 1 when no more data is to be received abe: 31 e0 ldi r19, 0x01 ; 1 } prog_address++; ac0: 80 91 63 00 lds r24, 0x0063 ac4: 90 91 64 00 lds r25, 0x0064 ac8: a0 91 65 00 lds r26, 0x0065 acc: b0 91 66 00 lds r27, 0x0066 ad0: 01 96 adiw r24, 0x01 ; 1 ad2: a1 1d adc r26, r1 ad4: b1 1d adc r27, r1 ad6: 80 93 63 00 sts 0x0063, r24 ada: 90 93 64 00 sts 0x0064, r25 ade: a0 93 65 00 sts 0x0065, r26 ae2: b0 93 66 00 sts 0x0066, r27 return 1; } return 0; } for (i = 0; i < len; i++) { ae6: e3 94 inc r14 ae8: 02 c0 rjmp .+4 ; 0xaee uchar retVal = 0; uchar i; /* check if programmer is in correct write state */ if ((prog_state != PROG_STATE_WRITEFLASH) && (prog_state aea: ee 24 eor r14, r14 aec: 30 e0 ldi r19, 0x00 ; 0 return 1; } return 0; } for (i = 0; i < len; i++) { aee: ef 14 cp r14, r15 af0: 08 f4 brcc .+2 ; 0xaf4 af2: 76 cf rjmp .-276 ; 0x9e0 af4: 03 c0 rjmp .+6 ; 0xafc uchar i; /* check if programmer is in correct write state */ if ((prog_state != PROG_STATE_WRITEFLASH) && (prog_state != PROG_STATE_WRITEEEPROM) && (prog_state != PROG_STATE_TPI_WRITE)) { return 0xff; af6: 3f ef ldi r19, 0xFF ; 255 af8: 01 c0 rjmp .+2 ; 0xafc if(prog_nbytes <= 0) { prog_state = PROG_STATE_IDLE; return 1; } return 0; afa: 30 e0 ldi r19, 0x00 ; 0 prog_address++; } return retVal; } afc: 83 2f mov r24, r19 afe: 0f 90 pop r0 b00: cf 91 pop r28 b02: df 91 pop r29 b04: 1f 91 pop r17 b06: 0f 91 pop r16 b08: ff 90 pop r15 b0a: ef 90 pop r14 b0c: df 90 pop r13 b0e: cf 90 pop r12 b10: 08 95 ret 00000b12
: int main(void) { uchar i, j; /* no pullups on USB and ISP pins */ PORTD = 0; b12: 12 ba out 0x12, r1 ; 18 PORTB = 0; b14: 18 ba out 0x18, r1 ; 24 /* all outputs except PD2 = INT0 */ DDRD = ~(1 << 2); b16: 8b ef ldi r24, 0xFB ; 251 b18: 81 bb out 0x11, r24 ; 17 /* output SE0 for USB reset */ DDRB = ~0; b1a: 8f ef ldi r24, 0xFF ; 255 b1c: 87 bb out 0x17, r24 ; 23 /* delay >10ms for USB reset */ while (--i) ; } /* all USB and ISP pins inputs */ DDRB = 0; b1e: 17 ba out 0x17, r1 ; 23 /* all inputs except PC0, PC1 */ DDRC = 0x03; b20: 83 e0 ldi r24, 0x03 ; 3 b22: 84 bb out 0x14, r24 ; 20 PORTC = 0xfe; b24: 9e ef ldi r25, 0xFE ; 254 b26: 95 bb out 0x15, r25 ; 21 /* init timer */ clockInit(); b28: 83 bf out 0x33, r24 ; 51 /* main event loop */ usbInit(); b2a: 85 d1 rcall .+778 ; 0xe36 sei(); b2c: 78 94 sei for (;;) { usbPoll(); b2e: 6a d0 rcall .+212 ; 0xc04 b30: fe cf rjmp .-4 ; 0xb2e 00000b32 : * TPI init */ .global tpi_init tpi_init: /* CLK <= out */ sbi _SFR_IO_ADDR(TPI_CLK_DDR), TPI_CLK_BIT b32: bd 9a sbi 0x17, 5 ; 23 /* DATAOUT <= high */ sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT #else /* DATA <= pull-up */ cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT b34: bb 98 cbi 0x17, 3 ; 23 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT b36: c3 9a sbi 0x18, 3 ; 24 #endif /* 32 bits */ ldi r21, 32 b38: 50 e2 ldi r21, 0x20 ; 32 1: rcall tpi_bit_h b3a: 17 d0 rcall .+46 ; 0xb6a dec r21 b3c: 5a 95 dec r21 brne 1b b3e: e9 f7 brne .-6 ; 0xb3a ret b40: 08 95 ret 00000b42 : * Update PR * in: r25:r24 <= PR * lost: r18-r21,r24,r30-r31 */ tpi_pr_update: movw r20, r24 b42: ac 01 movw r20, r24 ldi r24, TPI_OP_SSTPR(0) b44: 88 e6 ldi r24, 0x68 ; 104 rcall tpi_send_byte b46: 05 d0 rcall .+10 ; 0xb52 mov r24, r20 b48: 84 2f mov r24, r20 rcall tpi_send_byte b4a: 03 d0 rcall .+6 ; 0xb52 ldi r24, TPI_OP_SSTPR(1) b4c: 89 e6 ldi r24, 0x69 ; 105 rcall tpi_send_byte b4e: 01 d0 rcall .+2 ; 0xb52 mov r24, r21 b50: 85 2f mov r24, r21 00000b52 : * lost: r18-r19,r30-r31 */ .global tpi_send_byte tpi_send_byte: /* start bit */ rcall tpi_bit_l b52: 0f d0 rcall .+30 ; 0xb72 /* 8 data bits */ ldi r18, 8 b54: 28 e0 ldi r18, 0x08 ; 8 ldi r19, 0 b56: 30 e0 ldi r19, 0x00 ; 0 1: // parity eor r19, r24 b58: 38 27 eor r19, r24 // get bit, shift bst r24, 0 b5a: 80 fb bst r24, 0 lsr r24 b5c: 86 95 lsr r24 // send rcall tpi_bit b5e: 06 d0 rcall .+12 ; 0xb6c dec r18 b60: 2a 95 dec r18 brne 1b b62: d1 f7 brne .-12 ; 0xb58 /* parity bit */ bst r19, 0 b64: 30 fb bst r19, 0 rcall tpi_bit b66: 02 d0 rcall .+4 ; 0xb6c /* 2 stop bits */ rcall tpi_bit_h b68: 00 d0 rcall .+0 ; 0xb6a 00000b6a : * in: T <= bit_in * out: T => bit_out * lost: r30-r31 */ tpi_bit_h: set b6a: 68 94 set 00000b6c : 1: #else // DATAOUT = pull-up // if(T == 0) // DATAOUT = low cbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT b6c: bb 98 cbi 0x17, 3 ; 23 sbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT b6e: c3 9a sbi 0x18, 3 ; 24 brts 1f b70: 16 f0 brts .+4 ; 0xb76 00000b72 : tpi_bit_l: cbi _SFR_IO_ADDR(TPI_DATAOUT_PORT), TPI_DATAOUT_BIT b72: c3 98 cbi 0x18, 3 ; 24 sbi _SFR_IO_ADDR(TPI_DATAOUT_DDR), TPI_DATAOUT_BIT b74: bb 9a sbi 0x17, 3 ; 23 1: #endif /* delay(); */ lds r30, tpi_dly_cnt b76: e0 91 7e 00 lds r30, 0x007E lds r31, tpi_dly_cnt+1 b7a: f0 91 7f 00 lds r31, 0x007F 1: sbiw r30, 1 b7e: 31 97 sbiw r30, 0x01 ; 1 brsh 1b b80: f0 f7 brcc .-4 ; 0xb7e /* TPICLK = 1 */ sbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT b82: c5 9a sbi 0x18, 5 ; 24 /* T = TPIDATA */ in r30, _SFR_IO_ADDR(TPI_DATAIN_PIN) b84: e6 b3 in r30, 0x16 ; 22 bst r30, TPI_DATAIN_BIT b86: e3 fb bst r30, 3 /* delay(); */ lds r30, tpi_dly_cnt b88: e0 91 7e 00 lds r30, 0x007E lds r31, tpi_dly_cnt+1 b8c: f0 91 7f 00 lds r31, 0x007F 1: sbiw r30, 1 b90: 31 97 sbiw r30, 0x01 ; 1 brsh 1b b92: f0 f7 brcc .-4 ; 0xb90 /* TPICLK = 0 */ cbi _SFR_IO_ADDR(TPI_CLK_PORT), TPI_CLK_BIT b94: c5 98 cbi 0x18, 5 ; 24 ret b96: 08 95 ret 00000b98 : * lost: r18-r19,r30-r31 */ .global tpi_recv_byte tpi_recv_byte: /* waitfor(start_bit, 192); */ ldi r18, 192 b98: 20 ec ldi r18, 0xC0 ; 192 1: rcall tpi_bit_h b9a: e7 df rcall .-50 ; 0xb6a brtc .tpi_recv_found_start b9c: 46 f4 brtc .+16 ; 0xbae <.tpi_recv_found_start> dec r18 b9e: 2a 95 dec r18 brne 1b ba0: e1 f7 brne .-8 ; 0xb9a 00000ba2 <.tpi_break_ret0>: /* no start bit: set return value */ .tpi_break_ret0: ldi r24, 0 ba2: 80 e0 ldi r24, 0x00 ; 0 /* send 2 breaks (24++ bits) */ ldi r18, 26 ba4: 2a e1 ldi r18, 0x1A ; 26 1: rcall tpi_bit_l ba6: e5 df rcall .-54 ; 0xb72 dec r18 ba8: 2a 95 dec r18 brne 1b baa: e9 f7 brne .-6 ; 0xba6 <.tpi_break_ret0+0x4> /* send hi */ rjmp tpi_bit_h bac: de cf rjmp .-68 ; 0xb6a 00000bae <.tpi_recv_found_start>: // ---- .tpi_recv_found_start: /* recv 8bits(+calc.parity) */ ldi r18, 8 bae: 28 e0 ldi r18, 0x08 ; 8 ldi r19, 0 bb0: 30 e0 ldi r19, 0x00 ; 0 1: rcall tpi_bit_h bb2: db df rcall .-74 ; 0xb6a lsr r24 bb4: 86 95 lsr r24 bld r24, 7 bb6: 87 f9 bld r24, 7 eor r19, r24 bb8: 38 27 eor r19, r24 dec r18 bba: 2a 95 dec r18 brne 1b bbc: d1 f7 brne .-12 ; 0xbb2 <.tpi_recv_found_start+0x4> /* recv parity */ rcall tpi_bit_h bbe: d5 df rcall .-86 ; 0xb6a bld r18, 7 bc0: 27 f9 bld r18, 7 eor r19, r18 bc2: 32 27 eor r19, r18 brmi .tpi_break_ret0 bc4: 72 f3 brmi .-36 ; 0xba2 <.tpi_break_ret0> /* recv stop bits */ rcall tpi_bit_h bc6: d1 df rcall .-94 ; 0xb6a rjmp tpi_bit_h bc8: d0 cf rjmp .-96 ; 0xb6a 00000bca : * Read Block */ .global tpi_read_block tpi_read_block: // X <= dptr movw XL, r22 bca: db 01 movw r26, r22 // r23 <= len mov r23, r20 bcc: 74 2f mov r23, r20 /* set PR */ rcall tpi_pr_update bce: b9 df rcall .-142 ; 0xb42 00000bd0 <.tpi_read_loop>: /* read data */ .tpi_read_loop: ldi r24, TPI_OP_SLD_INC bd0: 84 e2 ldi r24, 0x24 ; 36 rcall tpi_send_byte bd2: bf df rcall .-130 ; 0xb52 rcall tpi_recv_byte bd4: e1 df rcall .-62 ; 0xb98 st X+, r24 bd6: 8d 93 st X+, r24 dec r23 bd8: 7a 95 dec r23 brne .tpi_read_loop bda: d1 f7 brne .-12 ; 0xbd0 <.tpi_read_loop> ret bdc: 08 95 ret 00000bde : * Write block */ .global tpi_write_block tpi_write_block: // X <= sptr movw XL, r22 bde: db 01 movw r26, r22 // r23 <= len mov r23, r20 be0: 74 2f mov r23, r20 /* set PR */ rcall tpi_pr_update be2: af df rcall .-162 ; 0xb42 00000be4 <.tpi_write_loop>: /* write data */ .tpi_write_loop: ldi r24, TPI_OP_SOUT(NVMCMD) be4: 83 ef ldi r24, 0xF3 ; 243 rcall tpi_send_byte be6: b5 df rcall .-150 ; 0xb52 ldi r24, NVMCMD_WORD_WRITE be8: 8d e1 ldi r24, 0x1D ; 29 rcall tpi_send_byte bea: b3 df rcall .-154 ; 0xb52 ldi r24, TPI_OP_SST_INC bec: 84 e6 ldi r24, 0x64 ; 100 rcall tpi_send_byte bee: b1 df rcall .-158 ; 0xb52 ld r24, X+ bf0: 8d 91 ld r24, X+ rcall tpi_send_byte bf2: af df rcall .-162 ; 0xb52 00000bf4 <.tpi_nvmbsy_wait>: .tpi_nvmbsy_wait: ldi r24, TPI_OP_SIN(NVMCSR) bf4: 82 e7 ldi r24, 0x72 ; 114 rcall tpi_send_byte bf6: ad df rcall .-166 ; 0xb52 rcall tpi_recv_byte bf8: cf df rcall .-98 ; 0xb98 andi r24, NVMCSR_BSY bfa: 80 78 andi r24, 0x80 ; 128 brne .tpi_nvmbsy_wait bfc: d9 f7 brne .-10 ; 0xbf4 <.tpi_nvmbsy_wait> dec r23 bfe: 7a 95 dec r23 brne .tpi_write_loop c00: 89 f7 brne .-30 ; 0xbe4 <.tpi_write_loop> ret c02: 08 95 ret 00000c04 : } /* ------------------------------------------------------------------------- */ USB_PUBLIC void usbPoll(void) { c04: 1f 93 push r17 c06: cf 93 push r28 c08: df 93 push r29 schar len; uchar i; len = usbRxLen - 3; c0a: 60 91 90 00 lds r22, 0x0090 c0e: 63 50 subi r22, 0x03 ; 3 if(len >= 0){ c10: 67 fd sbrc r22, 7 c12: a4 c0 rjmp .+328 ; 0xd5c * need data integrity checks with this driver, check the CRC in your app * code and report errors back to the host. Since the ACK was already sent, * retries must be handled on application level. * unsigned crc = usbCrc16(buffer + 1, usbRxLen - 3); */ usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len); c14: 80 91 8d 00 lds r24, 0x008D c18: cc e0 ldi r28, 0x0C ; 12 c1a: d0 e0 ldi r29, 0x00 ; 0 c1c: c8 1b sub r28, r24 c1e: d1 09 sbc r29, r1 c20: cc 56 subi r28, 0x6C ; 108 c22: df 4f sbci r29, 0xFF ; 255 if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */ usbFunctionWriteOut(data, len); return; } #endif if(usbRxToken == (uchar)USBPID_SETUP){ c24: 80 91 8c 00 lds r24, 0x008C c28: 8d 32 cpi r24, 0x2D ; 45 c2a: 09 f0 breq .+2 ; 0xc2e c2c: 85 c0 rjmp .+266 ; 0xd38 if(len != 8) /* Setup size must be always 8 bytes. Ignore otherwise. */ c2e: 68 30 cpi r22, 0x08 ; 8 c30: 09 f0 breq .+2 ; 0xc34 c32: 92 c0 rjmp .+292 ; 0xd58 return; usbMsgLen_t replyLen; usbTxBuf[0] = USBPID_DATA0; /* initialize data toggling */ c34: 83 ec ldi r24, 0xC3 ; 195 c36: 80 93 80 00 sts 0x0080, r24 usbTxLen = USBPID_NAK; /* abort pending transmit */ c3a: 8a e5 ldi r24, 0x5A ; 90 c3c: 80 93 60 00 sts 0x0060, r24 usbMsgFlags = 0; c40: 10 92 77 00 sts 0x0077, r1 uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; c44: 88 81 ld r24, Y c46: 80 76 andi r24, 0x60 ; 96 if(type != USBRQ_TYPE_STANDARD){ /* standard requests are handled by driver */ c48: 31 f0 breq .+12 ; 0xc56 replyLen = usbFunctionSetup(data); c4a: ce 01 movw r24, r28 c4c: 7d dc rcall .-1798 ; 0x548 }else{ replyLen = usbDriverSetup(rq); } #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */ c4e: 8f 3f cpi r24, 0xFF ; 255 c50: 09 f4 brne .+2 ; 0xc54 c52: 61 c0 rjmp .+194 ; 0xd16 c54: 67 c0 rjmp .+206 ; 0xd24 * standard requests instead of class and custom requests. */ static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq) { uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */ uchar value = rq->wValue.bytes[0]; c56: 9a 81 ldd r25, Y+2 ; 0x02 #if USB_CFG_IMPLEMENT_HALT uchar index = rq->wIndex.bytes[0]; #endif dataPtr[0] = 0; /* default reply common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ c58: 10 92 89 00 sts 0x0089, r1 SWITCH_START(rq->bRequest) c5c: 89 81 ldd r24, Y+1 ; 0x01 SWITCH_CASE(USBRQ_GET_STATUS) /* 0 */ c5e: 88 23 and r24, r24 c60: 31 f4 brne .+12 ; 0xc6e dataPtr[0] = USB_CFG_IS_SELF_POWERED; #if USB_CFG_IMPLEMENT_HALT if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81) /* request status for endpoint 1 */ dataPtr[0] = usbTxLen1 == USBPID_STALL; #endif dataPtr[1] = 0; c62: 10 92 8a 00 sts 0x008A, r1 /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for * standard requests instead of class and custom requests. */ static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq) { uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */ c66: 29 e8 ldi r18, 0x89 ; 137 c68: 30 e0 ldi r19, 0x00 ; 0 #if USB_CFG_IMPLEMENT_HALT if(recipient == USBRQ_RCPT_ENDPOINT && index == 0x81) /* request status for endpoint 1 */ dataPtr[0] = usbTxLen1 == USBPID_STALL; #endif dataPtr[1] = 0; len = 2; c6a: 82 e0 ldi r24, 0x02 ; 2 c6c: 4f c0 rjmp .+158 ; 0xd0c if(value == 0 && index == 0x81){ /* feature 0 == HALT for endpoint == 1 */ usbTxLen1 = rq->bRequest == USBRQ_CLEAR_FEATURE ? USBPID_NAK : USBPID_STALL; usbResetDataToggling(); } #endif SWITCH_CASE(USBRQ_SET_ADDRESS) /* 5 */ c6e: 85 30 cpi r24, 0x05 ; 5 c70: 19 f4 brne .+6 ; 0xc78 usbNewDeviceAddr = value; c72: 90 93 91 00 sts 0x0091, r25 c76: 40 c0 rjmp .+128 ; 0xcf8 USB_SET_ADDRESS_HOOK(); SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */ c78: 86 30 cpi r24, 0x06 ; 6 c7a: a9 f5 brne .+106 ; 0xce6 usbTxLen1 = USBPID_NAK; #if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxLen3 = USBPID_NAK; #endif #endif } c7c: 8b 81 ldd r24, Y+3 ; 0x03 { usbMsgLen_t len = 0; uchar flags = USB_FLG_MSGPTR_IS_ROM; SWITCH_START(rq->wValue.bytes[1]) SWITCH_CASE(USBDESCR_DEVICE) /* 1 */ c7e: 81 30 cpi r24, 0x01 ; 1 c80: 19 f4 brne .+6 ; 0xc88 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice) c82: 84 e5 ldi r24, 0x54 ; 84 c84: 90 e0 ldi r25, 0x00 ; 0 c86: 04 c0 rjmp .+8 ; 0xc90 SWITCH_CASE(USBDESCR_CONFIG) /* 2 */ c88: 82 30 cpi r24, 0x02 ; 2 c8a: 41 f4 brne .+16 ; 0xc9c GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) c8c: 86 e6 ldi r24, 0x66 ; 102 c8e: 90 e0 ldi r25, 0x00 ; 0 c90: 90 93 8f 00 sts 0x008F, r25 c94: 80 93 8e 00 sts 0x008E, r24 c98: 82 e1 ldi r24, 0x12 ; 18 c9a: 21 c0 rjmp .+66 ; 0xcde SWITCH_CASE(USBDESCR_STRING) /* 3 */ c9c: 83 30 cpi r24, 0x03 ; 3 c9e: f1 f4 brne .+60 ; 0xcdc if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) flags = 0; len = usbFunctionDescriptor(rq); #else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ SWITCH_START(rq->wValue.bytes[0]) SWITCH_CASE(0) ca0: 99 23 and r25, r25 ca2: 41 f4 brne .+16 ; 0xcb4 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0) ca4: 86 e2 ldi r24, 0x26 ; 38 ca6: 90 e0 ldi r25, 0x00 ; 0 ca8: 90 93 8f 00 sts 0x008F, r25 cac: 80 93 8e 00 sts 0x008E, r24 cb0: 84 e0 ldi r24, 0x04 ; 4 cb2: 15 c0 rjmp .+42 ; 0xcde SWITCH_CASE(1) cb4: 91 30 cpi r25, 0x01 ; 1 cb6: 41 f4 brne .+16 ; 0xcc8 GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor) cb8: 8a e2 ldi r24, 0x2A ; 42 cba: 90 e0 ldi r25, 0x00 ; 0 cbc: 90 93 8f 00 sts 0x008F, r25 cc0: 80 93 8e 00 sts 0x008E, r24 cc4: 8c e1 ldi r24, 0x1C ; 28 cc6: 0b c0 rjmp .+22 ; 0xcde SWITCH_CASE(2) cc8: 92 30 cpi r25, 0x02 ; 2 cca: 41 f4 brne .+16 ; 0xcdc GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice) ccc: 86 e4 ldi r24, 0x46 ; 70 cce: 90 e0 ldi r25, 0x00 ; 0 cd0: 90 93 8f 00 sts 0x008F, r25 cd4: 80 93 8e 00 sts 0x008E, r24 cd8: 8e e0 ldi r24, 0x0E ; 14 cda: 01 c0 rjmp .+2 ; 0xcde /* usbDriverDescriptor() is similar to usbFunctionDescriptor(), but used * internally for all types of descriptors. */ static inline usbMsgLen_t usbDriverDescriptor(usbRequest_t *rq) { usbMsgLen_t len = 0; cdc: 80 e0 ldi r24, 0x00 ; 0 SWITCH_DEFAULT if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ len = usbFunctionDescriptor(rq); } SWITCH_END usbMsgFlags = flags; cde: 90 e4 ldi r25, 0x40 ; 64 ce0: 90 93 77 00 sts 0x0077, r25 ce4: 1f c0 rjmp .+62 ; 0xd24 usbNewDeviceAddr = value; USB_SET_ADDRESS_HOOK(); SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */ len = usbDriverDescriptor(rq); goto skipMsgPtrAssignment; SWITCH_CASE(USBRQ_GET_CONFIGURATION) /* 8 */ ce6: 88 30 cpi r24, 0x08 ; 8 ce8: 59 f0 breq .+22 ; 0xd00 dataPtr = &usbConfiguration; /* send current configuration value */ len = 1; SWITCH_CASE(USBRQ_SET_CONFIGURATION) /* 9 */ cea: 89 30 cpi r24, 0x09 ; 9 cec: 19 f4 brne .+6 ; 0xcf4 usbConfiguration = value; cee: 90 93 93 00 sts 0x0093, r25 cf2: 02 c0 rjmp .+4 ; 0xcf8 usbResetStall(); SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */ cf4: 8a 30 cpi r24, 0x0A ; 10 cf6: 39 f0 breq .+14 ; 0xd06 /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for * standard requests instead of class and custom requests. */ static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq) { uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */ cf8: 29 e8 ldi r18, 0x89 ; 137 cfa: 30 e0 ldi r19, 0x00 ; 0 cfc: 80 e0 ldi r24, 0x00 ; 0 cfe: 06 c0 rjmp .+12 ; 0xd0c USB_SET_ADDRESS_HOOK(); SWITCH_CASE(USBRQ_GET_DESCRIPTOR) /* 6 */ len = usbDriverDescriptor(rq); goto skipMsgPtrAssignment; SWITCH_CASE(USBRQ_GET_CONFIGURATION) /* 8 */ dataPtr = &usbConfiguration; /* send current configuration value */ d00: 23 e9 ldi r18, 0x93 ; 147 d02: 30 e0 ldi r19, 0x00 ; 0 d04: 02 c0 rjmp .+4 ; 0xd0a /* usbDriverSetup() is similar to usbFunctionSetup(), but it's used for * standard requests instead of class and custom requests. */ static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq) { uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */ d06: 29 e8 ldi r18, 0x89 ; 137 d08: 30 e0 ldi r19, 0x00 ; 0 len = 1; SWITCH_CASE(USBRQ_SET_CONFIGURATION) /* 9 */ usbConfiguration = value; usbResetStall(); SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */ len = 1; d0a: 81 e0 ldi r24, 0x01 ; 1 usbResetStall(); #endif SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */ /* Should we add an optional hook here? */ SWITCH_END usbMsgPtr = dataPtr; d0c: 30 93 8f 00 sts 0x008F, r19 d10: 20 93 8e 00 sts 0x008E, r18 d14: 07 c0 rjmp .+14 ; 0xd24 replyLen = usbDriverSetup(rq); } #if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */ /* do some conditioning on replyLen, but on IN transfers only */ if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){ d16: 98 81 ld r25, Y d18: 97 fd sbrc r25, 7 if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ replyLen = rq->wLength.bytes[0]; d1a: 8e 81 ldd r24, Y+6 ; 0x06 }else{ replyLen = rq->wLength.word; } } usbMsgFlags = USB_FLG_USE_USER_RW; d1c: 90 e8 ldi r25, 0x80 ; 128 d1e: 90 93 77 00 sts 0x0077, r25 d22: 07 c0 rjmp .+14 ; 0xd32 }else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */ #endif if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */ if(!rq->wLength.bytes[1] && replyLen > rq->wLength.bytes[0]) /* limit length to max */ d24: 9f 81 ldd r25, Y+7 ; 0x07 d26: 99 23 and r25, r25 d28: 21 f4 brne .+8 ; 0xd32 d2a: 9e 81 ldd r25, Y+6 ; 0x06 d2c: 98 17 cp r25, r24 d2e: 08 f4 brcc .+2 ; 0xd32 d30: 89 2f mov r24, r25 replyLen = rq->wLength.bytes[0]; }else{ if(replyLen > rq->wLength.word) /* limit length to max */ replyLen = rq->wLength.word; } usbMsgLen = replyLen; d32: 80 93 61 00 sts 0x0061, r24 d36: 10 c0 rjmp .+32 ; 0xd58 }else{ /* usbRxToken must be USBPID_OUT, which means data phase of setup (control-out) */ #if USB_CFG_IMPLEMENT_FN_WRITE if(usbMsgFlags & USB_FLG_USE_USER_RW){ d38: 80 91 77 00 lds r24, 0x0077 d3c: 87 ff sbrs r24, 7 d3e: 0c c0 rjmp .+24 ; 0xd58 uchar rval = usbFunctionWrite(data, len); d40: ce 01 movw r24, r28 d42: 0a de rcall .-1004 ; 0x958 if(rval == 0xff){ /* an error occurred */ d44: 8f 3f cpi r24, 0xFF ; 255 d46: 21 f4 brne .+8 ; 0xd50 usbTxLen = USBPID_STALL; d48: 8e e1 ldi r24, 0x1E ; 30 d4a: 80 93 60 00 sts 0x0060, r24 d4e: 04 c0 rjmp .+8 ; 0xd58 }else if(rval != 0){ /* This was the final package */ d50: 88 23 and r24, r24 d52: 11 f0 breq .+4 ; 0xd58 usbMsgLen = 0; /* answer with a zero-sized data packet */ d54: 10 92 61 00 sts 0x0061, r1 usbProcessRx(usbRxBuf + USB_BUFSIZE + 1 - usbInputBufOffset, len); #if USB_CFG_HAVE_FLOWCONTROL if(usbRxLen > 0) /* only mark as available if not inactivated */ usbRxLen = 0; #else usbRxLen = 0; /* mark rx buffer as available */ d58: 10 92 90 00 sts 0x0090, r1 #endif } if(usbTxLen & 0x10){ /* transmit system idle */ d5c: 80 91 60 00 lds r24, 0x0060 d60: 84 ff sbrs r24, 4 d62: 5b c0 rjmp .+182 ; 0xe1a if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */ d64: 80 91 61 00 lds r24, 0x0061 d68: 8f 3f cpi r24, 0xFF ; 255 d6a: 09 f4 brne .+2 ; 0xd6e d6c: 56 c0 rjmp .+172 ; 0xe1a d6e: 18 2f mov r17, r24 d70: 89 30 cpi r24, 0x09 ; 9 d72: 08 f0 brcs .+2 ; 0xd76 d74: 18 e0 ldi r17, 0x08 ; 8 uchar len; wantLen = usbMsgLen; if(wantLen > 8) wantLen = 8; usbMsgLen -= wantLen; d76: 81 1b sub r24, r17 d78: 80 93 61 00 sts 0x0061, r24 usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */ d7c: 80 91 80 00 lds r24, 0x0080 d80: 98 e8 ldi r25, 0x88 ; 136 d82: 89 27 eor r24, r25 d84: 80 93 80 00 sts 0x0080, r24 /* This function is similar to usbFunctionRead(), but it's also called for * data handled automatically by the driver (e.g. descriptor reads). */ static uchar usbDeviceRead(uchar *data, uchar len) { if(len > 0){ /* don't bother app with 0 sized reads */ d88: 11 23 and r17, r17 d8a: b1 f1 breq .+108 ; 0xdf8 #if USB_CFG_IMPLEMENT_FN_READ if(usbMsgFlags & USB_FLG_USE_USER_RW){ d8c: 80 91 77 00 lds r24, 0x0077 d90: 87 ff sbrs r24, 7 d92: 08 c0 rjmp .+16 ; 0xda4 len = usbFunctionRead(data, len); d94: 81 e8 ldi r24, 0x81 ; 129 d96: 90 e0 ldi r25, 0x00 ; 0 d98: 61 2f mov r22, r17 d9a: 6d dd rcall .-1318 ; 0x876 d9c: 18 2f mov r17, r24 if(wantLen > 8) wantLen = 8; usbMsgLen -= wantLen; usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */ len = usbDeviceRead(usbTxBuf + 1, wantLen); if(len <= 8){ /* valid data packet */ d9e: 89 30 cpi r24, 0x09 ; 9 da0: b0 f5 brcc .+108 ; 0xe0e da2: 2a c0 rjmp .+84 ; 0xdf8 if(usbMsgFlags & USB_FLG_USE_USER_RW){ len = usbFunctionRead(data, len); }else #endif { uchar i = len, *r = usbMsgPtr; da4: 20 91 8e 00 lds r18, 0x008E da8: 30 91 8f 00 lds r19, 0x008F dac: 41 2f mov r20, r17 dae: 41 50 subi r20, 0x01 ; 1 if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ db0: 86 ff sbrs r24, 6 db2: 0e c0 rjmp .+28 ; 0xdd0 #endif } /* ------------------------------------------------------------------------- */ USB_PUBLIC void usbPoll(void) db4: 50 e0 ldi r21, 0x00 ; 0 db6: ea 01 movw r28, r20 db8: ce 57 subi r28, 0x7E ; 126 dba: df 4f sbci r29, 0xFF ; 255 dbc: f9 01 movw r30, r18 dbe: a1 e8 ldi r26, 0x81 ; 129 dc0: b0 e0 ldi r27, 0x00 ; 0 #endif { uchar i = len, *r = usbMsgPtr; if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */ do{ uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */ dc2: 84 91 lpm r24, Z+ *data++ = c; dc4: 8d 93 st X+, r24 r++; dc6: 31 96 adiw r30, 0x01 ; 1 }while(--i); dc8: ac 17 cp r26, r28 dca: bd 07 cpc r27, r29 dcc: d1 f7 brne .-12 ; 0xdc2 dce: 0c c0 rjmp .+24 ; 0xde8 dd0: d9 01 movw r26, r18 #endif } /* ------------------------------------------------------------------------- */ USB_PUBLIC void usbPoll(void) dd2: 50 e0 ldi r21, 0x00 ; 0 dd4: ca 01 movw r24, r20 dd6: 8e 57 subi r24, 0x7E ; 126 dd8: 9f 4f sbci r25, 0xFF ; 255 dda: e1 e8 ldi r30, 0x81 ; 129 ddc: f0 e0 ldi r31, 0x00 ; 0 *data++ = c; r++; }while(--i); }else{ /* RAM data */ do{ *data++ = *r++; dde: 6d 91 ld r22, X+ de0: 61 93 st Z+, r22 }while(--i); de2: e8 17 cp r30, r24 de4: f9 07 cpc r31, r25 de6: d9 f7 brne .-10 ; 0xdde #endif } /* ------------------------------------------------------------------------- */ USB_PUBLIC void usbPoll(void) de8: 4f 5f subi r20, 0xFF ; 255 dea: 5f 4f sbci r21, 0xFF ; 255 r++; }while(--i); }else{ /* RAM data */ do{ *data++ = *r++; }while(--i); dec: 42 0f add r20, r18 dee: 53 1f adc r21, r19 } usbMsgPtr = r; df0: 50 93 8f 00 sts 0x008F, r21 df4: 40 93 8e 00 sts 0x008E, r20 wantLen = 8; usbMsgLen -= wantLen; usbTxBuf[0] ^= USBPID_DATA0 ^ USBPID_DATA1; /* DATA toggling */ len = usbDeviceRead(usbTxBuf + 1, wantLen); if(len <= 8){ /* valid data packet */ usbCrc16Append(&usbTxBuf[1], len); df8: 81 e8 ldi r24, 0x81 ; 129 dfa: 90 e0 ldi r25, 0x00 ; 0 dfc: 61 2f mov r22, r17 dfe: 37 d0 rcall .+110 ; 0xe6e len += 4; /* length including sync byte */ e00: 1c 5f subi r17, 0xFC ; 252 if(len < 12) /* a partial package identifies end of message */ e02: 1c 30 cpi r17, 0x0C ; 12 e04: 41 f0 breq .+16 ; 0xe16 usbMsgLen = USB_NO_MSG; e06: 8f ef ldi r24, 0xFF ; 255 e08: 80 93 61 00 sts 0x0061, r24 e0c: 04 c0 rjmp .+8 ; 0xe16 }else{ len = USBPID_STALL; /* stall the endpoint */ usbMsgLen = USB_NO_MSG; e0e: 8f ef ldi r24, 0xFF ; 255 e10: 80 93 61 00 sts 0x0061, r24 usbCrc16Append(&usbTxBuf[1], len); len += 4; /* length including sync byte */ if(len < 12) /* a partial package identifies end of message */ usbMsgLen = USB_NO_MSG; }else{ len = USBPID_STALL; /* stall the endpoint */ e14: 1e e1 ldi r17, 0x1E ; 30 usbMsgLen = USB_NO_MSG; } usbTxLen = len; e16: 10 93 60 00 sts 0x0060, r17 usbCrc16Append(&usbTxBuf[1], len); len += 4; /* length including sync byte */ if(len < 12) /* a partial package identifies end of message */ usbMsgLen = USB_NO_MSG; }else{ len = USBPID_STALL; /* stall the endpoint */ e1a: 84 e1 ldi r24, 0x14 ; 20 if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */ usbBuildTxBlock(); } } for(i = 20; i > 0; i--){ uchar usbLineStatus = USBIN & USBMASK; e1c: 96 b3 in r25, 0x16 ; 22 e1e: 93 70 andi r25, 0x03 ; 3 if(usbLineStatus != 0) /* SE0 has ended */ e20: 31 f4 brne .+12 ; 0xe2e e22: 81 50 subi r24, 0x01 ; 1 if(usbTxLen & 0x10){ /* transmit system idle */ if(usbMsgLen != USB_NO_MSG){ /* transmit data pending? */ usbBuildTxBlock(); } } for(i = 20; i > 0; i--){ e24: d9 f7 brne .-10 ; 0xe1c uchar usbLineStatus = USBIN & USBMASK; if(usbLineStatus != 0) /* SE0 has ended */ goto isNotReset; } /* RESET condition, called multiple times during reset */ usbNewDeviceAddr = 0; e26: 10 92 91 00 sts 0x0091, r1 usbDeviceAddr = 0; e2a: 10 92 8b 00 sts 0x008B, r1 usbResetStall(); DBG1(0xff, 0, 0); isNotReset: usbHandleResetHook(i); } e2e: df 91 pop r29 e30: cf 91 pop r28 e32: 1f 91 pop r17 e34: 08 95 ret 00000e36 : /* ------------------------------------------------------------------------- */ USB_PUBLIC void usbInit(void) { #if USB_INTR_CFG_SET != 0 USB_INTR_CFG |= USB_INTR_CFG_SET; e36: 85 b7 in r24, 0x35 ; 53 e38: 83 60 ori r24, 0x03 ; 3 e3a: 85 bf out 0x35, r24 ; 53 #endif #if USB_INTR_CFG_CLR != 0 USB_INTR_CFG &= ~(USB_INTR_CFG_CLR); #endif USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); e3c: 8b b7 in r24, 0x3b ; 59 e3e: 80 64 ori r24, 0x40 ; 64 e40: 8b bf out 0x3b, r24 ; 59 usbTxLen1 = USBPID_NAK; #if USB_CFG_HAVE_INTRIN_ENDPOINT3 usbTxLen3 = USBPID_NAK; #endif #endif } e42: 08 95 ret 00000e44 : ; poly r20+r21 ; scratch r23 ; resCrc r24+r25 / r16+r17 ; ptr X / Z usbCrc16: mov ptrL, argPtrL e44: a8 2f mov r26, r24 mov ptrH, argPtrH e46: b9 2f mov r27, r25 ldi resCrcL, 0 e48: 80 e0 ldi r24, 0x00 ; 0 ldi resCrcH, 0 e4a: 90 e0 ldi r25, 0x00 ; 0 ldi polyL, lo8(0xa001) e4c: 41 e0 ldi r20, 0x01 ; 1 ldi polyH, hi8(0xa001) e4e: 50 ea ldi r21, 0xA0 ; 160 com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set e50: 60 95 com r22 ldi bitCnt, 0 ; loop counter with starnd condition = end condition e52: 30 e0 ldi r19, 0x00 ; 0 rjmp usbCrcLoopEntry e54: 09 c0 rjmp .+18 ; 0xe68 00000e56 : usbCrcByteLoop: ld byte, ptr+ e56: 2d 91 ld r18, X+ eor resCrcL, byte e58: 82 27 eor r24, r18 00000e5a : usbCrcBitLoop: ror resCrcH ; carry is always set here (see brcs jumps to here) e5a: 97 95 ror r25 ror resCrcL e5c: 87 95 ror r24 brcs usbCrcNoXor e5e: 10 f0 brcs .+4 ; 0xe64 eor resCrcL, polyL e60: 84 27 eor r24, r20 eor resCrcH, polyH e62: 95 27 eor r25, r21 00000e64 : usbCrcNoXor: subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times e64: 30 5e subi r19, 0xE0 ; 224 brcs usbCrcBitLoop e66: c8 f3 brcs .-14 ; 0xe5a 00000e68 : usbCrcLoopEntry: subi argLen, -1 e68: 6f 5f subi r22, 0xFF ; 255 brcs usbCrcByteLoop e6a: a8 f3 brcs .-22 ; 0xe56 00000e6c : usbCrcReady: ret e6c: 08 95 ret 00000e6e : #endif /* USB_USE_FAST_CRC */ ; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len); usbCrc16Append: rcall usbCrc16 e6e: ea df rcall .-44 ; 0xe44 st ptr+, resCrcL e70: 8d 93 st X+, r24 st ptr+, resCrcH e72: 9d 93 st X+, r25 ret e74: 08 95 ret 00000e76 <__vector_1>: ;max allowable interrupt latency: 34 cycles -> max 25 cycles interrupt disable ;max stack usage: [ret(2), YL, SREG, YH, shift, x1, x2, x3, cnt, x4] = 11 bytes ;Numbers in brackets are maximum cycles since SOF. USB_INTR_VECTOR: ;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt push YL ;2 [35] push only what is necessary to sync with edge ASAP e76: cf 93 push r28 in YL, SREG ;1 [37] e78: cf b7 in r28, 0x3f ; 63 push YL ;2 [39] e7a: cf 93 push r28 00000e7c : ;sync up with J to K edge during sync pattern -- use fastest possible loops ;The first part waits at most 1 bit long since we must be in sync pattern. ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to ;waitForJ, ensure that this prerequisite is met. waitForJ: inc YL e7c: c3 95 inc r28 sbis USBIN, USBMINUS e7e: b0 9b sbis 0x16, 0 ; 22 brne waitForJ ; just make sure we have ANY timeout e80: e9 f7 brne .-6 ; 0xe7c 00000e82 : waitForK: ;The following code results in a sampling window of 1/4 bit which meets the spec. sbis USBIN, USBMINUS e82: b0 9b sbis 0x16, 0 ; 22 rjmp foundK e84: 09 c0 rjmp .+18 ; 0xe98 sbis USBIN, USBMINUS e86: b0 9b sbis 0x16, 0 ; 22 rjmp foundK e88: 07 c0 rjmp .+14 ; 0xe98 sbis USBIN, USBMINUS e8a: b0 9b sbis 0x16, 0 ; 22 rjmp foundK e8c: 05 c0 rjmp .+10 ; 0xe98 sbis USBIN, USBMINUS e8e: b0 9b sbis 0x16, 0 ; 22 rjmp foundK e90: 03 c0 rjmp .+6 ; 0xe98 sbis USBIN, USBMINUS e92: b0 9b sbis 0x16, 0 ; 22 rjmp foundK e94: 01 c0 rjmp .+2 ; 0xe98 sts usbSofCount, YL #endif /* USB_COUNT_SOF */ #ifdef USB_SOF_HOOK USB_SOF_HOOK #endif rjmp sofError e96: a1 c0 rjmp .+322 ; 0xfda 00000e98 : foundK: ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling] ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets ;are cycles from center of first sync (double K) bit after the instruction push YH ;2 [2] e98: df 93 push r29 lds YL, usbInputBufOffset;2 [4] e9a: c0 91 8d 00 lds r28, 0x008D clr YH ;1 [5] e9e: dd 27 eor r29, r29 subi YL, lo8(-(usbRxBuf));1 [6] ea0: cc 56 subi r28, 0x6C ; 108 sbci YH, hi8(-(usbRxBuf));1 [7] ea2: df 4f sbci r29, 0xFF ; 255 sbis USBIN, USBMINUS ;1 [8] we want two bits K [sample 1 cycle too early] ea4: b0 9b sbis 0x16, 0 ; 22 rjmp haveTwoBitsK ;2 [10] ea6: 02 c0 rjmp .+4 ; 0xeac pop YH ;2 [11] undo the push from before ea8: df 91 pop r29 rjmp waitForK ;2 [13] this was not the end of sync, retry eaa: eb cf rjmp .-42 ; 0xe82 00000eac : haveTwoBitsK: ;---------------------------------------------------------------------------- ; push more registers and initialize values while we sample the first bits: ;---------------------------------------------------------------------------- push shift ;2 [16] eac: 2f 93 push r18 push x1 ;2 [12] eae: 0f 93 push r16 push x2 ;2 [14] eb0: 1f 93 push r17 in x1, USBIN ;1 [17] <-- sample bit 0 eb2: 06 b3 in r16, 0x16 ; 22 ldi shift, 0xff ;1 [18] eb4: 2f ef ldi r18, 0xFF ; 255 bst x1, USBMINUS ;1 [19] eb6: 00 fb bst r16, 0 bld shift, 0 ;1 [20] eb8: 20 f9 bld r18, 0 push x3 ;2 [22] eba: 4f 93 push r20 push cnt ;2 [24] ebc: 3f 93 push r19 in x2, USBIN ;1 [25] <-- sample bit 1 ebe: 16 b3 in r17, 0x16 ; 22 ser x3 ;1 [26] [inserted init instruction] ec0: 4f ef ldi r20, 0xFF ; 255 eor x1, x2 ;1 [27] ec2: 01 27 eor r16, r17 bst x1, USBMINUS ;1 [28] ec4: 00 fb bst r16, 0 bld shift, 1 ;1 [29] ec6: 21 f9 bld r18, 1 ldi cnt, USB_BUFSIZE;1 [30] [inserted init instruction] ec8: 3b e0 ldi r19, 0x0B ; 11 rjmp rxbit2 ;2 [32] eca: 31 c0 rjmp .+98 ; 0xf2e 00000ecc : ;---------------------------------------------------------------------------- ; Receiver loop (numbers in brackets are cycles within byte after instr) ;---------------------------------------------------------------------------- unstuff0: ;1 (branch taken) andi x3, ~0x01 ;1 [15] ecc: 4e 7f andi r20, 0xFE ; 254 mov x1, x2 ;1 [16] x2 contains last sampled (stuffed) bit ece: 01 2f mov r16, r17 in x2, USBIN ;1 [17] <-- sample bit 1 again ed0: 16 b3 in r17, 0x16 ; 22 ori shift, 0x01 ;1 [18] ed2: 21 60 ori r18, 0x01 ; 1 rjmp didUnstuff0 ;2 [20] ed4: 28 c0 rjmp .+80 ; 0xf26 00000ed6 : unstuff1: ;1 (branch taken) mov x2, x1 ;1 [21] x1 contains last sampled (stuffed) bit ed6: 10 2f mov r17, r16 andi x3, ~0x02 ;1 [22] ed8: 4d 7f andi r20, 0xFD ; 253 ori shift, 0x02 ;1 [23] eda: 22 60 ori r18, 0x02 ; 2 nop ;1 [24] edc: 00 00 nop in x1, USBIN ;1 [25] <-- sample bit 2 again ede: 06 b3 in r16, 0x16 ; 22 rjmp didUnstuff1 ;2 [27] ee0: 29 c0 rjmp .+82 ; 0xf34 00000ee2 : unstuff2: ;1 (branch taken) andi x3, ~0x04 ;1 [29] ee2: 4b 7f andi r20, 0xFB ; 251 ori shift, 0x04 ;1 [30] ee4: 24 60 ori r18, 0x04 ; 4 mov x1, x2 ;1 [31] x2 contains last sampled (stuffed) bit ee6: 01 2f mov r16, r17 nop ;1 [32] ee8: 00 00 nop in x2, USBIN ;1 [33] <-- sample bit 3 eea: 16 b3 in r17, 0x16 ; 22 rjmp didUnstuff2 ;2 [35] eec: 2b c0 rjmp .+86 ; 0xf44 00000eee : unstuff3: ;1 (branch taken) in x2, USBIN ;1 [34] <-- sample stuffed bit 3 [one cycle too late] eee: 16 b3 in r17, 0x16 ; 22 andi x3, ~0x08 ;1 [35] ef0: 47 7f andi r20, 0xF7 ; 247 ori shift, 0x08 ;1 [36] ef2: 28 60 ori r18, 0x08 ; 8 rjmp didUnstuff3 ;2 [38] ef4: 2a c0 rjmp .+84 ; 0xf4a 00000ef6 : unstuff4: ;1 (branch taken) andi x3, ~0x10 ;1 [40] ef6: 4f 7e andi r20, 0xEF ; 239 in x1, USBIN ;1 [41] <-- sample stuffed bit 4 ef8: 06 b3 in r16, 0x16 ; 22 ori shift, 0x10 ;1 [42] efa: 20 61 ori r18, 0x10 ; 16 rjmp didUnstuff4 ;2 [44] efc: 2c c0 rjmp .+88 ; 0xf56 00000efe : unstuff5: ;1 (branch taken) andi x3, ~0x20 ;1 [48] efe: 4f 7d andi r20, 0xDF ; 223 in x2, USBIN ;1 [49] <-- sample stuffed bit 5 f00: 16 b3 in r17, 0x16 ; 22 ori shift, 0x20 ;1 [50] f02: 20 62 ori r18, 0x20 ; 32 rjmp didUnstuff5 ;2 [52] f04: 2f c0 rjmp .+94 ; 0xf64 00000f06 : unstuff6: ;1 (branch taken) andi x3, ~0x40 ;1 [56] f06: 4f 7b andi r20, 0xBF ; 191 in x1, USBIN ;1 [57] <-- sample stuffed bit 6 f08: 06 b3 in r16, 0x16 ; 22 ori shift, 0x40 ;1 [58] f0a: 20 64 ori r18, 0x40 ; 64 rjmp didUnstuff6 ;2 [60] f0c: 32 c0 rjmp .+100 ; 0xf72 00000f0e : ; bit 4: none ; bit 5: none ; bit 6: none ; bit 7: jump, eor rxLoop: eor x3, shift ;1 [0] reconstruct: x3 is 0 at bit locations we changed, 1 at others f0e: 42 27 eor r20, r18 in x1, USBIN ;1 [1] <-- sample bit 0 f10: 06 b3 in r16, 0x16 ; 22 st y+, x3 ;2 [3] store data f12: 49 93 st Y+, r20 ser x3 ;1 [4] f14: 4f ef ldi r20, 0xFF ; 255 nop ;1 [5] f16: 00 00 nop eor x2, x1 ;1 [6] f18: 10 27 eor r17, r16 bst x2, USBMINUS;1 [7] f1a: 10 fb bst r17, 0 bld shift, 0 ;1 [8] f1c: 20 f9 bld r18, 0 in x2, USBIN ;1 [9] <-- sample bit 1 (or possibly bit 0 stuffed) f1e: 16 b3 in r17, 0x16 ; 22 andi x2, USBMASK ;1 [10] f20: 13 70 andi r17, 0x03 ; 3 breq se0 ;1 [11] SE0 check for bit 1 f22: c9 f1 breq .+114 ; 0xf96 andi shift, 0xf9 ;1 [12] f24: 29 7f andi r18, 0xF9 ; 249 00000f26 : didUnstuff0: breq unstuff0 ;1 [13] f26: 91 f2 breq .-92 ; 0xecc eor x1, x2 ;1 [14] f28: 01 27 eor r16, r17 bst x1, USBMINUS;1 [15] f2a: 00 fb bst r16, 0 bld shift, 1 ;1 [16] f2c: 21 f9 bld r18, 1 00000f2e : rxbit2: in x1, USBIN ;1 [17] <-- sample bit 2 (or possibly bit 1 stuffed) f2e: 06 b3 in r16, 0x16 ; 22 andi shift, 0xf3 ;1 [18] f30: 23 7f andi r18, 0xF3 ; 243 breq unstuff1 ;1 [19] do remaining work for bit 1 f32: 89 f2 breq .-94 ; 0xed6 00000f34 : didUnstuff1: subi cnt, 1 ;1 [20] f34: 31 50 subi r19, 0x01 ; 1 brcs overflow ;1 [21] loop control f36: 58 f1 brcs .+86 ; 0xf8e eor x2, x1 ;1 [22] f38: 10 27 eor r17, r16 bst x2, USBMINUS;1 [23] f3a: 10 fb bst r17, 0 bld shift, 2 ;1 [24] f3c: 22 f9 bld r18, 2 in x2, USBIN ;1 [25] <-- sample bit 3 (or possibly bit 2 stuffed) f3e: 16 b3 in r17, 0x16 ; 22 andi shift, 0xe7 ;1 [26] f40: 27 7e andi r18, 0xE7 ; 231 breq unstuff2 ;1 [27] f42: 79 f2 breq .-98 ; 0xee2 00000f44 : didUnstuff2: eor x1, x2 ;1 [28] f44: 01 27 eor r16, r17 bst x1, USBMINUS;1 [29] f46: 00 fb bst r16, 0 bld shift, 3 ;1 [30] f48: 23 f9 bld r18, 3 00000f4a : didUnstuff3: andi shift, 0xcf ;1 [31] f4a: 2f 7c andi r18, 0xCF ; 207 breq unstuff3 ;1 [32] f4c: 81 f2 breq .-96 ; 0xeee in x1, USBIN ;1 [33] <-- sample bit 4 f4e: 06 b3 in r16, 0x16 ; 22 eor x2, x1 ;1 [34] f50: 10 27 eor r17, r16 bst x2, USBMINUS;1 [35] f52: 10 fb bst r17, 0 bld shift, 4 ;1 [36] f54: 24 f9 bld r18, 4 00000f56 : didUnstuff4: andi shift, 0x9f ;1 [37] f56: 2f 79 andi r18, 0x9F ; 159 breq unstuff4 ;1 [38] f58: 71 f2 breq .-100 ; 0xef6 nop2 ;2 [40] f5a: 00 c0 rjmp .+0 ; 0xf5c in x2, USBIN ;1 [41] <-- sample bit 5 f5c: 16 b3 in r17, 0x16 ; 22 eor x1, x2 ;1 [42] f5e: 01 27 eor r16, r17 bst x1, USBMINUS;1 [43] f60: 00 fb bst r16, 0 bld shift, 5 ;1 [44] f62: 25 f9 bld r18, 5 00000f64 : didUnstuff5: andi shift, 0x3f ;1 [45] f64: 2f 73 andi r18, 0x3F ; 63 breq unstuff5 ;1 [46] f66: 59 f2 breq .-106 ; 0xefe nop2 ;2 [48] f68: 00 c0 rjmp .+0 ; 0xf6a in x1, USBIN ;1 [49] <-- sample bit 6 f6a: 06 b3 in r16, 0x16 ; 22 eor x2, x1 ;1 [50] f6c: 10 27 eor r17, r16 bst x2, USBMINUS;1 [51] f6e: 10 fb bst r17, 0 bld shift, 6 ;1 [52] f70: 26 f9 bld r18, 6 00000f72 : didUnstuff6: cpi shift, 0x02 ;1 [53] f72: 22 30 cpi r18, 0x02 ; 2 brlo unstuff6 ;1 [54] f74: 40 f2 brcs .-112 ; 0xf06 nop2 ;2 [56] f76: 00 c0 rjmp .+0 ; 0xf78 in x2, USBIN ;1 [57] <-- sample bit 7 f78: 16 b3 in r17, 0x16 ; 22 eor x1, x2 ;1 [58] f7a: 01 27 eor r16, r17 bst x1, USBMINUS;1 [59] f7c: 00 fb bst r16, 0 bld shift, 7 ;1 [60] f7e: 27 f9 bld r18, 7 00000f80 : didUnstuff7: cpi shift, 0x04 ;1 [61] f80: 24 30 cpi r18, 0x04 ; 4 brsh rxLoop ;2 [63] loop control f82: 28 f6 brcc .-118 ; 0xf0e 00000f84 : unstuff7: andi x3, ~0x80 ;1 [63] f84: 4f 77 andi r20, 0x7F ; 127 ori shift, 0x80 ;1 [64] f86: 20 68 ori r18, 0x80 ; 128 in x2, USBIN ;1 [65] <-- sample stuffed bit 7 f88: 16 b3 in r17, 0x16 ; 22 nop ;1 [66] f8a: 00 00 nop rjmp didUnstuff7 ;2 [68] f8c: f9 cf rjmp .-14 ; 0xf80 00000f8e : */ #define token x1 overflow: ldi x2, 1<: ignorePacket: clr token f92: 00 27 eor r16, r16 rjmp storeTokenAndReturn f94: 17 c0 rjmp .+46 ; 0xfc4 00000f96 : ; Processing of received packet (numbers in brackets are cycles after center of SE0) ;---------------------------------------------------------------------------- ;This is the only non-error exit point for the software receiver loop ;we don't check any CRCs here because there is no time left. se0: subi cnt, USB_BUFSIZE ;[5] f96: 3b 50 subi r19, 0x0B ; 11 neg cnt ;[6] f98: 31 95 neg r19 sub YL, cnt ;[7] f9a: c3 1b sub r28, r19 sbci YH, 0 ;[8] f9c: d0 40 sbci r29, 0x00 ; 0 ldi x2, 1< cpi token, USBPID_DATA1 ;[15] fa8: 0b 34 cpi r16, 0x4B ; 75 breq handleData ;[16] faa: d9 f0 breq .+54 ; 0xfe2 lds shift, usbDeviceAddr;[17] fac: 20 91 8b 00 lds r18, 0x008B ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number fb0: 19 81 ldd r17, Y+1 ; 0x01 lsl x2 ;[21] shift out 1 bit endpoint number fb2: 11 0f add r17, r17 cpse x2, shift ;[22] fb4: 12 13 cpse r17, r18 rjmp ignorePacket ;[23] fb6: ed cf rjmp .-38 ; 0xf92 /* only compute endpoint number in x3 if required later */ #if USB_CFG_HAVE_INTRIN_ENDPOINT || USB_CFG_IMPLEMENT_FN_WRITEOUT ldd x3, y+2 ;[24] endpoint number + crc rol x3 ;[26] shift in LSB of endpoint #endif cpi token, USBPID_IN ;[27] fb8: 09 36 cpi r16, 0x69 ; 105 breq handleIn ;[28] fba: 41 f1 breq .+80 ; 0x100c cpi token, USBPID_SETUP ;[29] fbc: 0d 32 cpi r16, 0x2D ; 45 breq handleSetupOrOut ;[30] fbe: 11 f0 breq .+4 ; 0xfc4 cpi token, USBPID_OUT ;[31] fc0: 01 3e cpi r16, 0xE1 ; 225 brne ignorePacket ;[32] must be ack, nak or whatever fc2: 39 f7 brne .-50 ; 0xf92 00000fc4 : andi x3, 0xf ;[32] breq storeTokenAndReturn ;[33] mov token, x3 ;[34] indicate that this is endpoint x OUT #endif storeTokenAndReturn: sts usbCurrentTok, token;[35] fc4: 00 93 92 00 sts 0x0092, r16 00000fc8 : doReturn: POP_STANDARD ;[37] 12...16 cycles fc8: 3f 91 pop r19 fca: 4f 91 pop r20 fcc: 1f 91 pop r17 fce: 0f 91 pop r16 fd0: 2f 91 pop r18 fd2: df 91 pop r29 USB_LOAD_PENDING(YL) ;[49] fd4: ca b7 in r28, 0x3a ; 58 sbrc YL, USB_INTR_PENDING_BIT;[50] check whether data is already arriving fd6: c6 fd sbrc r28, 6 rjmp waitForJ ;[51] save the pops and pushes -- a new interrupt is already pending fd8: 51 cf rjmp .-350 ; 0xe7c 00000fda : sofError: POP_RETI ;macro call fda: cf 91 pop r28 fdc: cf bf out 0x3f, r28 ; 63 fde: cf 91 pop r28 reti fe0: 18 95 reti 00000fe2 : handleData: #if USB_CFG_CHECK_CRC CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error #endif lds shift, usbCurrentTok;[18] fe2: 20 91 92 00 lds r18, 0x0092 tst shift ;[20] fe6: 22 23 and r18, r18 breq doReturn ;[21] fe8: 79 f3 breq .-34 ; 0xfc8 lds x2, usbRxLen ;[22] fea: 10 91 90 00 lds r17, 0x0090 tst x2 ;[24] fee: 11 23 and r17, r17 brne sendNakAndReti ;[25] ff0: 11 f5 brne .+68 ; 0x1036 ; 2006-03-11: The following two lines fix a problem where the device was not ; recognized if usbPoll() was called less frequently than once every 4 ms. cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack ff2: 34 30 cpi r19, 0x04 ; 4 brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP ff4: 12 f1 brmi .+68 ; 0x103a #if USB_CFG_CHECK_DATA_TOGGLING sts usbCurrentDataToken, token ; store for checking by C code #endif sts usbRxLen, cnt ;[28] store received data, swap buffers ff6: 30 93 90 00 sts 0x0090, r19 sts usbRxToken, shift ;[30] ffa: 20 93 8c 00 sts 0x008C, r18 lds x2, usbInputBufOffset;[32] swap buffers ffe: 10 91 8d 00 lds r17, 0x008D ldi cnt, USB_BUFSIZE ;[34] 1002: 3b e0 ldi r19, 0x0B ; 11 sub cnt, x2 ;[35] 1004: 31 1b sub r19, r17 sts usbInputBufOffset, cnt;[36] buffers now swapped 1006: 30 93 8d 00 sts 0x008D, r19 rjmp sendAckAndReti ;[38] 40 + 17 = 57 until SOP 100a: 17 c0 rjmp .+46 ; 0x103a 0000100c : handleIn: ;We don't send any data as long as the C code has not processed the current ;input data and potentially updated the output data. That's more efficient ;in terms of code size than clearing the tx buffers when a packet is received. lds x1, usbRxLen ;[30] 100c: 00 91 90 00 lds r16, 0x0090 cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free" 1010: 01 30 cpi r16, 0x01 ; 1 brge sendNakAndReti ;[33] unprocessed input packet? 1012: 8c f4 brge .+34 ; 0x1036 ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen 1014: 0a e5 ldi r16, 0x5A ; 90 brne sendNakAndReti ;[36] #else brne handleIn1 ;[36] #endif #endif lds cnt, usbTxLen ;[37] 1016: 30 91 60 00 lds r19, 0x0060 sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set 101a: 34 fd sbrc r19, 4 rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP 101c: 10 c0 rjmp .+32 ; 0x103e sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above 101e: 00 93 60 00 sts 0x0060, r16 ldi YL, lo8(usbTxBuf) ;[43] 1022: c0 e8 ldi r28, 0x80 ; 128 ldi YH, hi8(usbTxBuf) ;[44] 1024: d0 e0 ldi r29, 0x00 ; 0 rjmp usbSendAndReti ;[45] 57 + 12 = 59 until SOP 1026: 0f c0 rjmp .+30 ; 0x1046 00001028 : ;---------------------------------------------------------------------------- txByteLoop: txBitloop: stuffN1Delay: ; [03] ror shift ;[-5] [11] [59] 1028: 27 95 ror r18 brcc doExorN1 ;[-4] [60] 102a: a8 f4 brcc .+42 ; 0x1056 subi x4, 1 ;[-3] 102c: 51 50 subi r21, 0x01 ; 1 brne commonN1 ;[-2] 102e: a9 f4 brne .+42 ; 0x105a lsl shift ;[-1] compensate ror after rjmp stuffDelay 1030: 22 0f add r18, r18 nop ;[00] stuffing consists of just waiting 8 cycles 1032: 00 00 nop rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear 1034: f9 cf rjmp .-14 ; 0x1028 00001036 : sendNakAndReti: ;0 [-19] 19 cycles until SOP ldi x3, USBPID_NAK ;1 [-18] 1036: 4a e5 ldi r20, 0x5A ; 90 rjmp usbSendX3 ;2 [-16] 1038: 03 c0 rjmp .+6 ; 0x1040 0000103a : sendAckAndReti: ;0 [-19] 19 cycles until SOP ldi x3, USBPID_ACK ;1 [-18] 103a: 42 ed ldi r20, 0xD2 ; 210 rjmp usbSendX3 ;2 [-16] 103c: 01 c0 rjmp .+2 ; 0x1040 0000103e : sendCntAndReti: ;0 [-17] 17 cycles until SOP mov x3, cnt ;1 [-16] 103e: 43 2f mov r20, r19 00001040 : usbSendX3: ;0 [-16] ldi YL, 20 ;1 [-15] 'x3' is R20 1040: c4 e1 ldi r28, 0x14 ; 20 ldi YH, 0 ;1 [-14] 1042: d0 e0 ldi r29, 0x00 ; 0 ldi cnt, 2 ;1 [-13] 1044: 32 e0 ldi r19, 0x02 ; 2 00001046 : ;pointer to data in 'Y' ;number of bytes in 'cnt' -- including sync byte ;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt] ;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction) usbSendAndReti: in x2, USBDDR ;[-12] 12 cycles until SOP 1046: 17 b3 in r17, 0x17 ; 23 ori x2, USBMASK ;[-11] 1048: 13 60 ori r17, 0x03 ; 3 sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) 104a: c0 9a sbi 0x18, 0 ; 24 out USBDDR, x2 ;[-8] <--- acquire bus 104c: 17 bb out 0x17, r17 ; 23 in x1, USBOUT ;[-7] port mirror for tx loop 104e: 08 b3 in r16, 0x18 ; 24 ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror) 1050: 20 e4 ldi r18, 0x40 ; 64 ldi x2, USBMASK ;[-5] 1052: 13 e0 ldi r17, 0x03 ; 3 push x4 ;[-4] 1054: 5f 93 push r21 00001056 : doExorN1: eor x1, x2 ;[-2] [06] [62] 1056: 01 27 eor r16, r17 ldi x4, 6 ;[-1] [07] [63] 1058: 56 e0 ldi r21, 0x06 ; 6 0000105a : commonN1: stuffN2Delay: out USBOUT, x1 ;[00] [08] [64] <--- set bit 105a: 08 bb out 0x18, r16 ; 24 ror shift ;[01] 105c: 27 95 ror r18 brcc doExorN2 ;[02] 105e: 20 f4 brcc .+8 ; 0x1068 subi x4, 1 ;[03] 1060: 51 50 subi r21, 0x01 ; 1 brne commonN2 ;[04] 1062: 21 f4 brne .+8 ; 0x106c lsl shift ;[05] compensate ror after rjmp stuffDelay 1064: 22 0f add r18, r18 rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear 1066: f9 cf rjmp .-14 ; 0x105a 00001068 : doExorN2: eor x1, x2 ;[04] [12] 1068: 01 27 eor r16, r17 ldi x4, 6 ;[05] [13] 106a: 56 e0 ldi r21, 0x06 ; 6 0000106c : commonN2: nop ;[06] [14] 106c: 00 00 nop subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1 106e: 3b 5a subi r19, 0xAB ; 171 out USBOUT, x1 ;[08] [16] <--- set bit 1070: 08 bb out 0x18, r16 ; 24 brcs txBitloop ;[09] [25] [41] 1072: d0 f2 brcs .-76 ; 0x1028 00001074 : stuff6Delay: ror shift ;[42] [50] 1074: 27 95 ror r18 brcc doExor6 ;[43] 1076: 28 f4 brcc .+10 ; 0x1082 subi x4, 1 ;[44] 1078: 51 50 subi r21, 0x01 ; 1 brne common6 ;[45] 107a: 29 f4 brne .+10 ; 0x1086 lsl shift ;[46] compensate ror after rjmp stuffDelay 107c: 22 0f add r18, r18 nop ;[47] stuffing consists of just waiting 8 cycles 107e: 00 00 nop rjmp stuff6Delay ;[48] after ror, C bit is reliably clear 1080: f9 cf rjmp .-14 ; 0x1074 00001082 : doExor6: eor x1, x2 ;[45] [53] 1082: 01 27 eor r16, r17 ldi x4, 6 ;[46] 1084: 56 e0 ldi r21, 0x06 ; 6 00001086 : common6: stuff7Delay: ror shift ;[47] [55] 1086: 27 95 ror r18 out USBOUT, x1 ;[48] <--- set bit 1088: 08 bb out 0x18, r16 ; 24 brcc doExor7 ;[49] 108a: 20 f4 brcc .+8 ; 0x1094 subi x4, 1 ;[50] 108c: 51 50 subi r21, 0x01 ; 1 brne common7 ;[51] 108e: 21 f4 brne .+8 ; 0x1098 lsl shift ;[52] compensate ror after rjmp stuffDelay 1090: 22 0f add r18, r18 rjmp stuff7Delay ;[53] after ror, C bit is reliably clear 1092: f9 cf rjmp .-14 ; 0x1086 00001094 : doExor7: eor x1, x2 ;[51] [59] 1094: 01 27 eor r16, r17 ldi x4, 6 ;[52] 1096: 56 e0 ldi r21, 0x06 ; 6 00001098 : common7: ld shift, y+ ;[53] 1098: 29 91 ld r18, Y+ tst cnt ;[55] 109a: 33 23 and r19, r19 out USBOUT, x1 ;[56] <--- set bit 109c: 08 bb out 0x18, r16 ; 24 brne txByteLoop ;[57] 109e: 21 f6 brne .-120 ; 0x1028 ;make SE0: cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles] 10a0: 0c 7f andi r16, 0xFC ; 252 lds x2, usbNewDeviceAddr;[59] 10a2: 10 91 91 00 lds r17, 0x0091 lsl x2 ;[61] we compare with left shifted address 10a6: 11 0f add r17, r17 subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3 10a8: c6 51 subi r28, 0x16 ; 22 sbci YH, 0 ;[63] 10aa: d0 40 sbci r29, 0x00 ; 0 out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle 10ac: 08 bb out 0x18, r16 ; 24 ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm: ;set address only after data packet was sent, not after handshake breq skipAddrAssign ;[01] 10ae: 11 f0 breq .+4 ; 0x10b4 sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer 10b0: 10 93 8b 00 sts 0x008B, r17 000010b4 : skipAddrAssign: ;end of usbDeviceAddress transfer ldi x2, 1< nop2 ;[14] 10c6: 00 c0 rjmp .+0 ; 0x10c8 out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal) 10c8: 08 bb out 0x18, r16 ; 24 out USBDDR, x2 ;[17] <-- release bus now 10ca: 17 bb out 0x17, r17 ; 23 out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active 10cc: 48 bb out 0x18, r20 ; 24 rjmp doReturn 10ce: 7c cf rjmp .-264 ; 0xfc8 000010d0 <_exit>: 10d0: f8 94 cli 000010d2 <__stop_program>: 10d2: ff cf rjmp .-2 ; 0x10d2 <__stop_program>