USBasp 2007.10.23.
[pub/USBasp.git] / firmware / usbdrv / usbdrvasm165.S
1 /* Name: usbdrvasm165.S
2 * Project: AVR USB driver
3 * Author: Christian Starkjohann
4 * Creation Date: 2007-04-22
5 * Tabsize: 4
6 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
8 * Revision: $Id$
9 */
10
11 /* Do not link this file! Link usbdrvasm.S instead, which includes the
12 * appropriate implementation!
13 */
14
15 /*
16 General Description:
17 This file is the 16.5 MHz version of the USB driver. It is intended for the
18 ATTiny45 and similar controllers running on 16.5 MHz internal RC oscillator.
19 This version contains a phase locked loop in the receiver routine to cope with
20 slight clock rate deviations of up to +/- 1%.
21
22 See usbdrv.h for a description of the entire driver.
23
24 Since almost all of this code is timing critical, don't change unless you
25 really know what you are doing! Many parts require not only a maximum number
26 of CPU cycles, but even an exact number of cycles!
27 */
28
29 ;Software-receiver engine. Strict timing! Don't change unless you can preserve timing!
30 ;interrupt response time: 4 cycles + insn running = 7 max if interrupts always enabled
31 ;max allowable interrupt latency: 59 cycles -> max 52 cycles interrupt disable
32 ;max stack usage: [ret(2), r0, SREG, YL, YH, shift, x1, x2, x3, x4, cnt] = 12 bytes
33 ;nominal frequency: 16.5 MHz -> 11 cycles per bit
34 ; 16.3125 MHz < F_CPU < 16.6875 MHz (+/- 1.1%)
35 ; Numbers in brackets are clocks counted from center of last sync bit
36 ; when instruction starts
37
38
39 SIG_INTERRUPT0:
40 ;order of registers pushed: r0, SREG [sofError], YL, YH, shift, x1, x2, x3, x4, cnt
41 push r0 ;[-23] push only what is necessary to sync with edge ASAP
42 in r0, SREG ;[-21]
43 push r0 ;[-20]
44 ;----------------------------------------------------------------------------
45 ; Synchronize with sync pattern:
46 ;----------------------------------------------------------------------------
47 ;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
48 ;sync up with J to K edge during sync pattern -- use fastest possible loops
49 ;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
50 waitForJ:
51 sbis USBIN, USBMINUS ;[-18] wait for D- == 1
52 rjmp waitForJ
53 waitForK:
54 ;The following code results in a sampling window of < 1/4 bit which meets the spec.
55 sbis USBIN, USBMINUS ;[-15]
56 rjmp foundK ;[-14]
57 sbis USBIN, USBMINUS
58 rjmp foundK
59 sbis USBIN, USBMINUS
60 rjmp foundK
61 sbis USBIN, USBMINUS
62 rjmp foundK
63 sbis USBIN, USBMINUS
64 rjmp foundK
65 sbis USBIN, USBMINUS
66 rjmp foundK
67 rjmp sofError
68 foundK: ;[-12]
69 ;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
70 ;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
71 ;are cycles from center of first sync (double K) bit after the instruction
72 push YL ;[-12]
73 ; [---] ;[-11]
74 push YH ;[-10]
75 ; [---] ;[-9]
76 lds YL, usbInputBufOffset;[-8]
77 ; [---] ;[-7]
78 clr YH ;[-6]
79 subi YL, lo8(-(usbRxBuf));[-5] [rx loop init]
80 sbci YH, hi8(-(usbRxBuf));[-4] [rx loop init]
81 mov r0, x2 ;[-3] [rx loop init]
82 sbis USBIN, USBMINUS ;[-2] we want two bits K (sample 2 cycles too early)
83 rjmp haveTwoBitsK ;[-1]
84 pop YH ;[0] undo the pushes from before
85 pop YL ;[2]
86 rjmp waitForK ;[4] this was not the end of sync, retry
87 ; The entire loop from waitForK until rjmp waitForK above must not exceed two
88 ; bit times (= 22 cycles).
89
90 ;----------------------------------------------------------------------------
91 ; push more registers and initialize values while we sample the first bits:
92 ;----------------------------------------------------------------------------
93 haveTwoBitsK: ;[1]
94 push shift ;[1]
95 push x1 ;[3]
96 push x2 ;[5]
97 push x3 ;[7]
98 ldi shift, 0xff ;[9] [rx loop init]
99 ori x3, 0xff ;[10] [rx loop init] == ser x3, clear zero flag
100
101 in x1, USBIN ;[11] <-- sample bit 0
102 bst x1, USBMINUS ;[12]
103 bld shift, 0 ;[13]
104 push x4 ;[14] == phase
105 ; [---] ;[15]
106 push cnt ;[16]
107 ; [---] ;[17]
108 ldi phase, 0 ;[18] [rx loop init]
109 ldi cnt, USB_BUFSIZE;[19] [rx loop init]
110 rjmp rxbit1 ;[20]
111 ; [---] ;[21]
112
113 ;----------------------------------------------------------------------------
114 ; Receiver loop (numbers in brackets are cycles within byte after instr)
115 ;----------------------------------------------------------------------------
116 /*
117 byte oriented operations done during loop:
118 bit 0: store data
119 bit 1: SE0 check
120 bit 2: overflow check
121 bit 3: catch up
122 bit 4: rjmp to achieve conditional jump range
123 bit 5: PLL
124 bit 6: catch up
125 bit 7: jump, fixup bitstuff
126 ; 87 [+ 2] cycles
127 ------------------------------------------------------------------
128 */
129 continueWithBit5:
130 in x2, USBIN ;[055] <-- bit 5
131 eor r0, x2 ;[056]
132 or phase, r0 ;[057]
133 sbrc phase, USBMINUS ;[058]
134 lpm ;[059] optional nop3; modifies r0
135 in phase, USBIN ;[060] <-- phase
136 eor x1, x2 ;[061]
137 bst x1, USBMINUS ;[062]
138 bld shift, 5 ;[063]
139 andi shift, 0x3f ;[064]
140 in x1, USBIN ;[065] <-- bit 6
141 breq unstuff5 ;[066] *** unstuff escape
142 eor phase, x1 ;[067]
143 eor x2, x1 ;[068]
144 bst x2, USBMINUS ;[069]
145 bld shift, 6 ;[070]
146 didUnstuff6: ;[ ]
147 in r0, USBIN ;[071] <-- phase
148 cpi shift, 0x02 ;[072]
149 brlo unstuff6 ;[073] *** unstuff escape
150 didUnstuff5: ;[ ]
151 nop2 ;[074]
152 ; [---] ;[075]
153 in x2, USBIN ;[076] <-- bit 7
154 eor x1, x2 ;[077]
155 bst x1, USBMINUS ;[078]
156 bld shift, 7 ;[079]
157 didUnstuff7: ;[ ]
158 eor r0, x2 ;[080]
159 or phase, r0 ;[081]
160 in r0, USBIN ;[082] <-- phase
161 cpi shift, 0x04 ;[083]
162 brsh rxLoop ;[084]
163 ; [---] ;[085]
164 unstuff7: ;[ ]
165 andi x3, ~0x80 ;[085]
166 ori shift, 0x80 ;[086]
167 in x2, USBIN ;[087] <-- sample stuffed bit 7
168 nop ;[088]
169 rjmp didUnstuff7 ;[089]
170 ; [---] ;[090]
171 ;[080]
172
173 unstuff5: ;[067]
174 eor phase, x1 ;[068]
175 andi x3, ~0x20 ;[069]
176 ori shift, 0x20 ;[070]
177 in r0, USBIN ;[071] <-- phase
178 mov x2, x1 ;[072]
179 nop ;[073]
180 nop2 ;[074]
181 ; [---] ;[075]
182 in x1, USBIN ;[076] <-- bit 6
183 eor r0, x1 ;[077]
184 or phase, r0 ;[078]
185 eor x2, x1 ;[079]
186 bst x2, USBMINUS ;[080]
187 bld shift, 6 ;[081] no need to check bitstuffing, we just had one
188 in r0, USBIN ;[082] <-- phase
189 rjmp didUnstuff5 ;[083]
190 ; [---] ;[084]
191 ;[074]
192
193 unstuff6: ;[074]
194 andi x3, ~0x40 ;[075]
195 in x1, USBIN ;[076] <-- bit 6 again
196 ori shift, 0x40 ;[077]
197 nop2 ;[078]
198 ; [---] ;[079]
199 rjmp didUnstuff6 ;[080]
200 ; [---] ;[081]
201 ;[071]
202
203 unstuff0: ;[013]
204 eor r0, x2 ;[014]
205 or phase, r0 ;[015]
206 andi x2, USBMASK ;[016] check for SE0
207 in r0, USBIN ;[017] <-- phase
208 breq didUnstuff0 ;[018] direct jump to se0 would be too long
209 andi x3, ~0x01 ;[019]
210 ori shift, 0x01 ;[020]
211 mov x1, x2 ;[021] mov existing sample
212 in x2, USBIN ;[022] <-- bit 1 again
213 rjmp didUnstuff0 ;[023]
214 ; [---] ;[024]
215 ;[014]
216
217 unstuff1: ;[024]
218 eor r0, x1 ;[025]
219 or phase, r0 ;[026]
220 andi x3, ~0x02 ;[027]
221 in r0, USBIN ;[028] <-- phase
222 ori shift, 0x02 ;[029]
223 mov x2, x1 ;[030]
224 rjmp didUnstuff1 ;[031]
225 ; [---] ;[032]
226 ;[022]
227
228 unstuff2: ;[035]
229 eor r0, x2 ;[036]
230 or phase, r0 ;[037]
231 andi x3, ~0x04 ;[038]
232 in r0, USBIN ;[039] <-- phase
233 ori shift, 0x04 ;[040]
234 mov x1, x2 ;[041]
235 rjmp didUnstuff2 ;[042]
236 ; [---] ;[043]
237 ;[033]
238
239 unstuff3: ;[043]
240 in x2, USBIN ;[044] <-- bit 3 again
241 eor r0, x2 ;[045]
242 or phase, r0 ;[046]
243 andi x3, ~0x08 ;[047]
244 ori shift, 0x08 ;[048]
245 nop ;[049]
246 in r0, USBIN ;[050] <-- phase
247 rjmp didUnstuff3 ;[051]
248 ; [---] ;[052]
249 ;[042]
250
251 unstuff4: ;[053]
252 andi x3, ~0x10 ;[054]
253 in x1, USBIN ;[055] <-- bit 4 again
254 ori shift, 0x10 ;[056]
255 rjmp didUnstuff4 ;[057]
256 ; [---] ;[058]
257 ;[048]
258
259 rxLoop: ;[085]
260 eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others
261 in x1, USBIN ;[000] <-- bit 0
262 st y+, x3 ;[001]
263 ; [---] ;[002]
264 eor r0, x1 ;[003]
265 or phase, r0 ;[004]
266 eor x2, x1 ;[005]
267 in r0, USBIN ;[006] <-- phase
268 ser x3 ;[007]
269 bst x2, USBMINUS ;[008]
270 bld shift, 0 ;[009]
271 andi shift, 0xf9 ;[010]
272 rxbit1: ;[ ]
273 in x2, USBIN ;[011] <-- bit 1
274 breq unstuff0 ;[012] *** unstuff escape
275 andi x2, USBMASK ;[013] SE0 check for bit 1
276 didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff
277 breq se0 ;[014]
278 eor r0, x2 ;[015]
279 or phase, r0 ;[016]
280 in r0, USBIN ;[017] <-- phase
281 eor x1, x2 ;[018]
282 bst x1, USBMINUS ;[019]
283 bld shift, 1 ;[020]
284 andi shift, 0xf3 ;[021]
285 didUnstuff1: ;[ ]
286 in x1, USBIN ;[022] <-- bit 2
287 breq unstuff1 ;[023] *** unstuff escape
288 eor r0, x1 ;[024]
289 or phase, r0 ;[025]
290 subi cnt, 1 ;[026] overflow check
291 brcs overflow ;[027]
292 in r0, USBIN ;[028] <-- phase
293 eor x2, x1 ;[029]
294 bst x2, USBMINUS ;[030]
295 bld shift, 2 ;[031]
296 andi shift, 0xe7 ;[032]
297 didUnstuff2: ;[ ]
298 in x2, USBIN ;[033] <-- bit 3
299 breq unstuff2 ;[034] *** unstuff escape
300 eor r0, x2 ;[035]
301 or phase, r0 ;[036]
302 eor x1, x2 ;[037]
303 bst x1, USBMINUS ;[038]
304 in r0, USBIN ;[039] <-- phase
305 bld shift, 3 ;[040]
306 andi shift, 0xcf ;[041]
307 didUnstuff3: ;[ ]
308 breq unstuff3 ;[042] *** unstuff escape
309 nop ;[043]
310 in x1, USBIN ;[044] <-- bit 4
311 eor x2, x1 ;[045]
312 bst x2, USBMINUS ;[046]
313 bld shift, 4 ;[047]
314 didUnstuff4: ;[ ]
315 eor r0, x1 ;[048]
316 or phase, r0 ;[049]
317 in r0, USBIN ;[050] <-- phase
318 andi shift, 0x9f ;[051]
319 breq unstuff4 ;[052] *** unstuff escape
320 rjmp continueWithBit5;[053]
321 ; [---] ;[054]
322
323 ;----------------------------------------------------------------------------
324 ; Processing of received packet (numbers in brackets are cycles after center of SE0)
325 ;----------------------------------------------------------------------------
326 ;This is the only non-error exit point for the software receiver loop
327 ;we don't check any CRCs here because there is no time left.
328 #define token x1
329 se0:
330 subi cnt, USB_BUFSIZE ;[5]
331 neg cnt ;[6]
332 cpi cnt, 3 ;[7]
333 ldi x2, 1<<USB_INTR_PENDING_BIT ;[8]
334 out USB_INTR_PENDING, x2;[9] clear pending intr and check flag later. SE0 should be over.
335 brlo doReturn ;[10] this is probably an ACK, NAK or similar packet
336 sub YL, cnt ;[11]
337 sbci YH, 0 ;[12]
338 ld token, y ;[13]
339 cpi token, USBPID_DATA0 ;[15]
340 breq handleData ;[16]
341 cpi token, USBPID_DATA1 ;[17]
342 breq handleData ;[18]
343 ldd x2, y+1 ;[19] ADDR and 1 bit endpoint number
344 mov x3, x2 ;[21] store for endpoint number
345 andi x2, 0x7f ;[22] x2 is now ADDR
346 lds shift, usbDeviceAddr;[23]
347 cp x2, shift ;[25]
348 overflow: ; This is a hack: brcs overflow will never have Z flag set
349 brne ignorePacket ;[26] packet for different address
350 cpi token, USBPID_IN ;[27]
351 breq handleIn ;[28]
352 cpi token, USBPID_SETUP ;[29]
353 breq handleSetupOrOut ;[30]
354 cpi token, USBPID_OUT ;[31]
355 breq handleSetupOrOut ;[32]
356 ; rjmp ignorePacket ;fallthrough, should not happen anyway.
357
358 ignorePacket:
359 clr shift
360 sts usbCurrentTok, shift
361 doReturn:
362 pop cnt
363 pop x4
364 pop x3
365 pop x2
366 pop x1
367 pop shift
368 pop YH
369 pop YL
370 sofError:
371 pop r0
372 out SREG, r0
373 pop r0
374 reti
375
376 #if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3
377 handleIn3:
378 lds cnt, usbTxLen3 ;[43]
379 sbrc cnt, 4 ;[45]
380 rjmp sendCntAndReti ;[46] 48 + 16 = 64 until SOP
381 sts usbTxLen3, x1 ;[47] x1 == USBPID_NAK from above
382 ldi YL, lo8(usbTxBuf3) ;[49]
383 ldi YH, hi8(usbTxBuf3) ;[50]
384 rjmp usbSendAndReti ;[51] 53 + 12 = 65 until SOP
385 #endif
386
387 ;Setup and Out are followed by a data packet two bit times (16 cycles) after
388 ;the end of SE0. The sync code allows up to 40 cycles delay from the start of
389 ;the sync pattern until the first bit is sampled. That's a total of 56 cycles.
390 handleSetupOrOut: ;[34]
391 #if USB_CFG_IMPLEMENT_FN_WRITEOUT /* if we have data for second OUT endpoint, set usbCurrentTok to -1 */
392 sbrc x3, 7 ;[34] skip if endpoint 0
393 ldi token, -1 ;[35] indicate that this is endpoint 1 OUT
394 #endif
395 sts usbCurrentTok, token;[36]
396 pop cnt ;[38]
397 pop x4 ;[40]
398 pop x3 ;[42]
399 pop x2 ;[44]
400 pop x1 ;[46]
401 pop shift ;[48]
402 pop YH ;[50]
403 pop YL ;[52]
404 in r0, USB_INTR_PENDING;[54]
405 sbrc r0, USB_INTR_PENDING_BIT;[55] check whether data is already arriving
406 rjmp waitForJ ;[56] save the pops and pushes -- a new interrupt is aready pending
407 rjmp sofError ;[57] not an error, but it does the pops and reti we want
408
409
410 handleData:
411 lds token, usbCurrentTok;[20]
412 tst token ;[22]
413 breq doReturn ;[23]
414 lds x2, usbRxLen ;[24]
415 tst x2 ;[26]
416 brne sendNakAndReti ;[27]
417 ; 2006-03-11: The following two lines fix a problem where the device was not
418 ; recognized if usbPoll() was called less frequently than once every 4 ms.
419 cpi cnt, 4 ;[28] zero sized data packets are status phase only -- ignore and ack
420 brmi sendAckAndReti ;[29] keep rx buffer clean -- we must not NAK next SETUP
421 sts usbRxLen, cnt ;[30] store received data, swap buffers
422 sts usbRxToken, token ;[32]
423 lds x2, usbInputBufOffset;[34] swap buffers
424 ldi cnt, USB_BUFSIZE ;[36]
425 sub cnt, x2 ;[37]
426 sts usbInputBufOffset, cnt;[38] buffers now swapped
427 rjmp sendAckAndReti ;[40] 42 + 17 = 59 until SOP
428
429 handleIn:
430 ;We don't send any data as long as the C code has not processed the current
431 ;input data and potentially updated the output data. That's more efficient
432 ;in terms of code size than clearing the tx buffers when a packet is received.
433 lds x1, usbRxLen ;[30]
434 cpi x1, 1 ;[32] negative values are flow control, 0 means "buffer free"
435 brge sendNakAndReti ;[33] unprocessed input packet?
436 ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
437 #if USB_CFG_HAVE_INTRIN_ENDPOINT
438 sbrc x3, 7 ;[35] x3 contains addr + endpoint
439 rjmp handleIn1 ;[36]
440 #endif
441 lds cnt, usbTxLen ;[37]
442 sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
443 rjmp sendCntAndReti ;[40] 42 + 16 = 58 until SOP
444 sts usbTxLen, x1 ;[41] x1 == USBPID_NAK from above
445 ldi YL, lo8(usbTxBuf) ;[43]
446 ldi YH, hi8(usbTxBuf) ;[44]
447 rjmp usbSendAndReti ;[45] 47 + 12 = 59 until SOP
448
449 ; Comment about when to set usbTxLen to USBPID_NAK:
450 ; We should set it back when we receive the ACK from the host. This would
451 ; be simple to implement: One static variable which stores whether the last
452 ; tx was for endpoint 0 or 1 and a compare in the receiver to distinguish the
453 ; ACK. However, we set it back immediately when we send the package,
454 ; assuming that no error occurs and the host sends an ACK. We save one byte
455 ; RAM this way and avoid potential problems with endless retries. The rest of
456 ; the driver assumes error-free transfers anyway.
457
458 #if USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
459 handleIn1: ;[38]
460 #if USB_CFG_HAVE_INTRIN_ENDPOINT3
461 ; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
462 ldd x2, y+2 ;[38]
463 sbrc x2, 0 ;[40]
464 rjmp handleIn3 ;[41]
465 #endif
466 lds cnt, usbTxLen1 ;[42]
467 sbrc cnt, 4 ;[44] all handshake tokens have bit 4 set
468 rjmp sendCntAndReti ;[45] 47 + 16 = 63 until SOP
469 sts usbTxLen1, x1 ;[46] x1 == USBPID_NAK from above
470 ldi YL, lo8(usbTxBuf1) ;[48]
471 ldi YH, hi8(usbTxBuf1) ;[49]
472 rjmp usbSendAndReti ;[50] 52 + 12 + 64 until SOP
473 #endif
474
475
476 ; USB spec says:
477 ; idle = J
478 ; J = (D+ = 0), (D- = 1)
479 ; K = (D+ = 1), (D- = 0)
480 ; Spec allows 7.5 bit times from EOP to SOP for replies
481
482 bitstuff7:
483 eor x1, x4 ;[4]
484 ldi x2, 0 ;[5]
485 nop2 ;[6] C is zero (brcc)
486 rjmp didStuff7 ;[8]
487
488 bitstuffN:
489 eor x1, x4 ;[5]
490 ldi x2, 0 ;[6]
491 lpm ;[7] 3 cycle NOP, modifies r0
492 out USBOUT, x1 ;[10] <-- out
493 rjmp didStuffN ;[0]
494
495 #define bitStatus x3
496
497 sendNakAndReti:
498 ldi cnt, USBPID_NAK ;[-19]
499 rjmp sendCntAndReti ;[-18]
500 sendAckAndReti:
501 ldi cnt, USBPID_ACK ;[-17]
502 sendCntAndReti:
503 mov r0, cnt ;[-16]
504 ldi YL, 0 ;[-15] R0 address is 0
505 ldi YH, 0 ;[-14]
506 ldi cnt, 2 ;[-13]
507 ; rjmp usbSendAndReti fallthrough
508
509 ;usbSend:
510 ;pointer to data in 'Y'
511 ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
512 ;uses: x1...x4, shift, cnt, Y
513 ;Numbers in brackets are time since first bit of sync pattern is sent
514 usbSendAndReti: ; 12 cycles until SOP
515 in x2, USBDDR ;[-12]
516 ori x2, USBMASK ;[-11]
517 sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
518 in x1, USBOUT ;[-8] port mirror for tx loop
519 out USBDDR, x2 ;[-7] <- acquire bus
520 ; need not init x2 (bitstuff history) because sync starts with 0
521 ldi x4, USBMASK ;[-6] exor mask
522 ldi shift, 0x80 ;[-5] sync byte is first byte sent
523 ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytes
524 byteloop:
525 bitloop:
526 sbrs shift, 0 ;[8] [-3]
527 eor x1, x4 ;[9] [-2]
528 out USBOUT, x1 ;[10] [-1] <-- out
529 ror shift ;[0]
530 ror x2 ;[1]
531 didStuffN:
532 cpi x2, 0xfc ;[2]
533 brcc bitstuffN ;[3]
534 nop ;[4]
535 subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37
536 brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value
537 sbrs shift, 0 ;[7]
538 eor x1, x4 ;[8]
539 ror shift ;[9]
540 didStuff7:
541 out USBOUT, x1 ;[10] <-- out
542 ror x2 ;[0]
543 cpi x2, 0xfc ;[1]
544 brcc bitstuff7 ;[2]
545 ld shift, y+ ;[3]
546 dec cnt ;[5]
547 brne byteloop ;[6]
548 ;make SE0:
549 cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles]
550 lds x2, usbNewDeviceAddr;[8]
551 out USBOUT, x1 ;[10] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle
552 ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
553 ;set address only after data packet was sent, not after handshake
554 subi YL, 2 ;[0]
555 sbci YH, 0 ;[1]
556 breq skipAddrAssign ;[2]
557 sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longer
558 skipAddrAssign:
559 ;end of usbDeviceAddress transfer
560 ldi x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag
561 out USB_INTR_PENDING, x2;[5]
562 ori x1, USBIDLE ;[6]
563 in x2, USBDDR ;[7]
564 cbr x2, USBMASK ;[8] set both pins to input
565 mov x3, x1 ;[9]
566 cbr x3, USBMASK ;[10] configure no pullup on both pins
567 ldi x4, 4 ;[11]
568 se0Delay:
569 dec x4 ;[12] [15] [18] [21]
570 brne se0Delay ;[13] [16] [19] [22]
571 out USBOUT, x1 ;[23] <-- out J (idle) -- end of SE0 (EOP signal)
572 out USBDDR, x2 ;[24] <-- release bus now
573 out USBOUT, x3 ;[25] <-- ensure no pull-up resistors are active
574 rjmp doReturn