Rev Author Line No. Line
3331 kaklik 1 ; ======================================================================
2 ; USB interrupt handler
3 ;
4 ; This is the handler for the interrupt caused by the initial rising edge
5 ; on the D+ USB signal. The NRZI encoding and bit stuffing are removed,
6 ; and the packet is saved in one of the two input buffers. In some cases,
7 ; a reply packet is sent right away.
8 ;
9 ; When a DATA0/DATA1 packet directly follows a SETUP or OUT packet, while
10 ; this interrupt handler is not yet finished, there would be no time to
11 ; return and take another interrupt. In that case, the second packet is
3333 kaklik 12 ; decoded directly in the same invocation. A packet immediately following
13 ; an ignored packet is also decoded directly.
3331 kaklik 14 ;
15 ; This code is *extremely* time critical. For instance, there is not a
16 ; single spare cycle in the receiver loop, and only two in the transmitter
17 ; loop. In addition, the various code paths are laid out in such a way that
18 ; the various USB timeouts are not violated, in particular the maximum time
3333 kaklik 19 ; between the reception of a packet and the reply, which is 7.5 bit times
20 ; (TRSPIPD2) for a low-speed USB captive cable. The worst-case delay here
21 ; is 51 cycles, which is well below the 60 cycles limit, and even below the
22 ; 6.5 bit times limit for a detachable cable (TRSPIPD1).
3331 kaklik 23 ;
24 ; The interrupt handler must be reached within 34 cycles after D+ goes high
3333 kaklik 25 ; for the first time. The interrupt response time is 4 cycles, and the RJMP
26 ; in the vector table takes 2 cycles. Therefore, the interrupts should not
27 ; be disabled for longer than: 34 - 4 - 2 = 28 cycles. When the I-bit is
28 ; reenabled, a single instruction is always executed before a pending
29 ; interrupt is served, so this instruction should be included in the
30 ; calculation. For RETI, the next instruction can be anything, so we
31 ; should assume the worst-case of 4 cycles.
3331 kaklik 32 ;
33 ; The end-of-packet (EOP) is sampled in the second bit, because the USB
34 ; standard allows the EOP to be delayed by up to one bit. As the EOP
35 ; duration is two bits, this is not a problem.
36 ;
37 ; Stack usage including the return address: 11 bytes.
38 ;
3333 kaklik 39 ; Copyright 2006-2010 Dick Streefland
3331 kaklik 40 ;
41 ; This is free software, licensed under the terms of the GNU General
42 ; Public License as published by the Free Software Foundation.
43 ; ======================================================================
44  
45 #include "def.h"
46  
47 ; ----------------------------------------------------------------------
48 ; local data
49 ; ----------------------------------------------------------------------
50 .data
51 tx_ack: .byte USB_PID_ACK ; ACK packet
52 tx_nak: .byte USB_PID_NAK ; NAK packet
53 .lcomm token_pid, 1 ; PID of most recent token packet
3333 kaklik 54 .global __do_copy_data
3331 kaklik 55  
56 ; ----------------------------------------------------------------------
57 ; register definitions
58 ; ----------------------------------------------------------------------
59 // receiver:
60 #define count r16
61 #define usbmask r17
62 #define odd r18
63 #define byte r19
64 #define fixup r20
65 #define even r22
66  
67 // transmitter:
68 #define output odd
69 #define done fixup
70 #define next even
71  
72 // control:
73 #define pid odd
74 #define addr usbmask
75 #define tmp fixup
76  
77 #define nop2 rjmp .+0 // not .+2 for some strange reason
78  
79 ; ----------------------------------------------------------------------
80 ; interrupt handler
81 ; ----------------------------------------------------------------------
82 .text
83 .global USB_INT_VECTOR
84 .type USB_INT_VECTOR, @function
85 ; ----------------------------------------------------------------------
86 ; This handler must be reached no later than 34 cycles after D+ goes high
87 ; for the first time.
88 ; ----------------------------------------------------------------------
89 USB_INT_VECTOR:
90 ; save registers
91 push count
92 push usbmask
93 push odd
94 push YH
95 push YL
96 in count, SREG
97 push count
98  
99 ; ----------------------------------------------------------------------
100 ; Synchronize to the pattern 10101011 on D+. This code must be reached
101 ; no later than 47 cycles after D+ goes high for the first time.
102 ; ----------------------------------------------------------------------
103 sync:
104 ; wait until D+ == 0
105 sbic USB_IN, USBTINY_DPLUS
106 rjmp sync ; jump if D+ == 1
107 resync:
108 ; sync on 0-->1 transition on D+ with a 2 cycle resolution
109 sbic USB_IN, USBTINY_DPLUS
110 rjmp sync6 ; jump if D+ == 1
111 sbic USB_IN, USBTINY_DPLUS
112 rjmp sync6 ; jump if D+ == 1
113 sbic USB_IN, USBTINY_DPLUS
114 rjmp sync6 ; jump if D+ == 1
115 sbic USB_IN, USBTINY_DPLUS
116 rjmp sync6 ; jump if D+ == 1
117 sbic USB_IN, USBTINY_DPLUS
118 rjmp sync6 ; jump if D+ == 1
119 ldi count, 1<<USB_INT_PENDING_BIT
120 out USB_INT_PENDING, count
121 rjmp return ; ==> false start, bail out
122  
123 sync6:
124 ; we are now between -1 and +1 cycle from the center of the bit
125 ; following the 0-->1 transition
126 lds YL, usb_rx_off
127 clr YH
128 subi YL, lo8(-(usb_rx_buf)) ; Y = & usb_rx_buf[usb_rx_off]
129 sbci YH, hi8(-(usb_rx_buf))
130 ldi count, USB_BUFSIZE ; limit on number of bytes to receive
131 ldi usbmask, USB_MASK ; why is there no eori instruction?
132 ldi odd, USB_MASK_DPLUS
133  
134 sync7:
135 ; the last sync bit should also be 1
136 sbis USB_IN, USBTINY_DPLUS ; bit 7 of sync byte?
137 rjmp resync ; no, wait for next transition
138 push byte
139 push fixup
140 push even
141  
142 ; ----------------------------------------------------------------------
143 ; receiver loop
144 ; ----------------------------------------------------------------------
145 in even, USB_IN ; sample bit 0
146 ldi byte, 0x80 ; load sync byte for correct unstuffing
147 rjmp rxentry ; 2 cycles
148  
149 rxloop:
150 in even, USB_IN ; sample bit 0
151 or fixup, byte
152 st Y+, fixup ; 2 cycles
153 rxentry:
154 clr fixup
155 andi even, USB_MASK
156 eor odd, even
157 subi odd, 1
158 in odd, USB_IN ; sample bit 1
159 andi odd, USB_MASK
160 breq eop ; ==> EOP detected
161 ror byte
162 cpi byte, 0xfc
163 brcc skip0
164 skipped0:
165 eor even, odd
166 subi even, 1
167 in even, USB_IN ; sample bit 2
168 andi even, USB_MASK
169 ror byte
170 cpi byte, 0xfc
171 brcc skip1
172 skipped1:
173 eor odd, even
174 subi odd, 1
175 ror byte
176 in odd, USB_IN ; sample bit 3
177 andi odd, USB_MASK
178 cpi byte, 0xfc
179 brcc skip2
180 eor even, odd
181 subi even, 1
182 ror byte
183 skipped2:
184 cpi byte, 0xfc
185 in even, USB_IN ; sample bit 4
186 andi even, USB_MASK
187 brcc skip3
188 eor odd, even
189 subi odd, 1
190 ror byte
191 skipped4:
192 cpi byte, 0xfc
193 skipped3:
194 brcc skip4
195 in odd, USB_IN ; sample bit 5
196 andi odd, USB_MASK
197 eor even, odd
198 subi even, 1
199 ror byte
200 skipped5:
201 cpi byte, 0xfc
202 brcc skip5
203 dec count
204 in even, USB_IN ; sample bit 6
205 brmi overflow ; ==> overflow
206 andi even, USB_MASK
207 eor odd, even
208 subi odd, 1
209 ror byte
210 skipped6:
211 cpi byte, 0xfc
212 brcc skip6
213 in odd, USB_IN ; sample bit 7
214 andi odd, USB_MASK
215 eor even, odd
216 subi even, 1
217 ror byte
218 cpi byte, 0xfc
219 brcs rxloop ; 2 cycles
220 rjmp skip7
221  
222 eop:
223 rjmp eop2
224 overflow:
225 rjmp ignore
226  
227 ; ----------------------------------------------------------------------
228 ; out-of-line code to skip stuffing bits
229 ; ----------------------------------------------------------------------
230 skip0: ; 1+6 cycles
231 eor even, usbmask
232 in odd, USB_IN ; resample bit 1
233 andi odd, USB_MASK
234 cbr byte, (1<<7)
235 sbr fixup, (1<<0)
236 rjmp skipped0
237  
238 skip1: ; 2+5 cycles
239 cbr byte, (1<<7)
240 sbr fixup, (1<<1)
241 in even, USB_IN ; resample bit 2
242 andi even, USB_MASK
243 eor odd, usbmask
244 rjmp skipped1
245  
246 skip2: ; 3+7 cycles
247 cbr byte, (1<<7)
248 sbr fixup, (1<<2)
249 eor even, usbmask
250 in odd, USB_IN ; resample bit 3
251 andi odd, USB_MASK
252 eor even, odd
253 subi even, 1
254 ror byte
255 rjmp skipped2
256  
257 skip3: ; 4+7 cycles
258 cbr byte, (1<<7)
259 sbr fixup, (1<<3)
260 eor odd, usbmask
261 ori byte, 1
262 in even, USB_IN ; resample bit 4
263 andi even, USB_MASK
264 eor odd, even
265 subi odd, 1
266 ror byte
267 rjmp skipped3
268  
269 skip4: ; 5 cycles
270 cbr byte, (1<<7)
271 sbr fixup, (1<<4)
272 eor even, usbmask
273 rjmp skipped4
274  
275 skip5: ; 5 cycles
276 cbr byte, (1<<7)
277 sbr fixup, (1<<5)
278 eor odd, usbmask
279 rjmp skipped5
280  
281 skip6: ; 5 cycles
282 cbr byte, (1<<7)
283 sbr fixup, (1<<6)
284 eor even, usbmask
285 rjmp skipped6
286  
287 skip7: ; 7 cycles
288 cbr byte, (1<<7)
289 sbr fixup, (1<<7)
290 eor odd, usbmask
291 nop2
292 rjmp rxloop
293  
294 ; ----------------------------------------------------------------------
295 ; end-of-packet detected (worst-case: 3 cycles after end of SE0)
296 ; ----------------------------------------------------------------------
297 eop2:
298 ; clear pending interrupt (SE0+3)
299 ldi byte, 1<<USB_INT_PENDING_BIT
300 out USB_INT_PENDING, byte ; clear pending bit at end of packet
3333 kaklik 301 ; calculate packet length
3331 kaklik 302 subi count, USB_BUFSIZE
303 neg count ; count = packet length
304 ; get PID
305 sub YL, count
3333 kaklik 306 sbci YH, 0
3331 kaklik 307 ld pid, Y
3333 kaklik 308 ; separate out the non-Token packets (SE0+11)
309 sbrc pid, 1
310 rjmp is_data_handshake ; jump for Data or Handshake packet
311 ; check ADDR of Token packet (SE0+13)
3331 kaklik 312 ldd addr, Y+1
313 andi addr, 0x7f
314 lds tmp, usb_address
315 cp addr, tmp ; is this packet for me?
316 brne ignore ; no, ignore
3333 kaklik 317 ; dispatch Token packets (SE0+20)
3331 kaklik 318 cpi pid, USB_PID_IN
3333 kaklik 319 brne is_setup_out ; handle SETUP and OUT packets
3331 kaklik 320  
321 ; ----------------------------------------------------------------------
3333 kaklik 322 ; Handle IN (SE0+22)
3331 kaklik 323 ; ----------------------------------------------------------------------
3333 kaklik 324 lds count, usb_tx_len
325 tst count ; data ready?
326 breq nak ; no, reply with NAK
327 lds tmp, usb_rx_len
328 tst tmp ; unprocessed input packet?
329 brne nak ; yes, don't send old data for new packet
330 sts usb_tx_len, tmp ; buffer is available again (after reti)
331 lds tmp, usb_new_address
332 sts usb_address, tmp ; assign new address at end of transfer
333 ldi YL, lo8(usb_tx_buf)
334 ldi YH, hi8(usb_tx_buf)
335 rjmp send_packet ; SE0+40, SE0 --> SOP <= 51
336  
337 ; ----------------------------------------------------------------------
338 ; exit point for ignored packets (SE0+21)
339 ; ----------------------------------------------------------------------
3331 kaklik 340 ignore:
3333 kaklik 341 clr pid
342 ignore0:
3331 kaklik 343  
344 ; ----------------------------------------------------------------------
3333 kaklik 345 ; Handle SETUP/OUT (SE0+23)
3331 kaklik 346 ; ----------------------------------------------------------------------
347 is_setup_out:
348 sts token_pid, pid ; save PID of token packet
349 pop even
350 pop fixup
351 pop byte
352 in count, USB_INT_PENDING ; next packet already started?
353 sbrc count, USB_INT_PENDING_BIT
3333 kaklik 354 rjmp sync ; yes, get it right away (SE0+35)
3331 kaklik 355  
356 ; ----------------------------------------------------------------------
3333 kaklik 357 ; restore registers and return from interrupt (SE0+34)
3331 kaklik 358 ; ----------------------------------------------------------------------
359 return:
360 pop count
361 out SREG, count
362 pop YL
363 pop YH
364 pop odd
365 pop usbmask
366 pop count
367 reti
368  
369 ; ----------------------------------------------------------------------
3333 kaklik 370 ; send NAK packet (SE0+31)
3331 kaklik 371 ; ----------------------------------------------------------------------
3333 kaklik 372 nak:
373 ldi YL, lo8(tx_nak)
374 ldi YH, hi8(tx_nak)
375 rjmp send_token
3331 kaklik 376  
377 ; ----------------------------------------------------------------------
3333 kaklik 378 ; Handle Data and Handshake packets (SE0+14)
3331 kaklik 379 ; ----------------------------------------------------------------------
3333 kaklik 380 is_data_handshake:
381 andi pid, 0x01
382 breq ignore0 ; ignore ACK/NAK/STALL
383  
384 ; ----------------------------------------------------------------------
385 ; Handle DATA0/DATA1 (SE0+16)
386 ; ----------------------------------------------------------------------
3331 kaklik 387 lds pid, token_pid
388 tst pid ; data following our SETUP/OUT
3333 kaklik 389 breq ignore0 ; no, ignore
3331 kaklik 390 lds tmp, usb_rx_len
391 tst tmp ; buffer free?
392 brne nak ; no, reply with NAK
393 sts usb_rx_len, count ; pass buffer length
394 sts usb_rx_token, pid ; pass PID of token (SETUP or OUT)
395 lds count, usb_rx_off ; switch to other input buffer
396 ldi tmp, USB_BUFSIZE
397 sub tmp, count
398 sts usb_rx_off, tmp
399  
400 ; ----------------------------------------------------------------------
3333 kaklik 401 ; send ACK packet (SE0+34)
3331 kaklik 402 ; ----------------------------------------------------------------------
403 ldi YL, lo8(tx_ack)
404 ldi YH, hi8(tx_ack)
405 send_token:
3333 kaklik 406 ldi count, 1 ; SE0+37, SE0 --> SOP <= 48
3331 kaklik 407  
408 ; ----------------------------------------------------------------------
409 ; acquire the bus and send a packet (11 cycles to SOP)
410 ; ----------------------------------------------------------------------
411 send_packet:
412 in output, USB_OUT
413 cbr output, USB_MASK
414 ori output, USB_MASK_DMINUS
415 in usbmask, USB_DDR
416 ori usbmask, USB_MASK
417 out USB_OUT, output ; idle state
418 out USB_DDR, usbmask ; acquire bus
419 ldi usbmask, USB_MASK
420 ldi byte, 0x80 ; start with sync byte
421  
422 ; ----------------------------------------------------------------------
423 ; transmitter loop
424 ; ----------------------------------------------------------------------
425 txloop:
426 sbrs byte, 0
427 eor output, usbmask
428 out USB_OUT, output ; output bit 0
429 ror byte
430 ror done
431 stuffed0:
432 cpi done, 0xfc
433 brcc stuff0
434 sbrs byte, 0
435 eor output, usbmask
436 ror byte
437 stuffed1:
438 out USB_OUT, output ; output bit 1
439 ror done
440 cpi done, 0xfc
441 brcc stuff1
442 sbrs byte, 0
443 eor output, usbmask
444 ror byte
445 nop
446 stuffed2:
447 out USB_OUT, output ; output bit 2
448 ror done
449 cpi done, 0xfc
450 brcc stuff2
451 sbrs byte, 0
452 eor output, usbmask
453 ror byte
454 nop
455 stuffed3:
456 out USB_OUT, output ; output bit 3
457 ror done
458 cpi done, 0xfc
459 brcc stuff3
460 sbrs byte, 0
461 eor output, usbmask
462 ld next, Y+ ; 2 cycles
463 out USB_OUT, output ; output bit 4
464 ror byte
465 ror done
466 stuffed4:
467 cpi done, 0xfc
468 brcc stuff4
469 sbrs byte, 0
470 eor output, usbmask
471 ror byte
472 stuffed5:
473 out USB_OUT, output ; output bit 5
474 ror done
475 cpi done, 0xfc
476 brcc stuff5
477 sbrs byte, 0
478 eor output, usbmask
479 ror byte
480 stuffed6:
481 ror done
482 out USB_OUT, output ; output bit 6
483 cpi done, 0xfc
484 brcc stuff6
485 sbrs byte, 0
486 eor output, usbmask
487 ror byte
488 mov byte, next
489 stuffed7:
490 ror done
491 out USB_OUT, output ; output bit 7
492 cpi done, 0xfc
493 brcc stuff7
494 dec count
495 brpl txloop ; 2 cycles
496  
497 rjmp gen_eop
498  
499 ; ----------------------------------------------------------------------
500 ; out-of-line code to insert stuffing bits
501 ; ----------------------------------------------------------------------
502 stuff0: ; 2+3
503 eor output, usbmask
504 clr done
505 out USB_OUT, output
506 rjmp stuffed0
507  
508 stuff1: ; 3
509 eor output, usbmask
510 rjmp stuffed1
511  
512 stuff2: ; 3
513 eor output, usbmask
514 rjmp stuffed2
515  
516 stuff3: ; 3
517 eor output, usbmask
518 rjmp stuffed3
519  
520 stuff4: ; 2+3
521 eor output, usbmask
522 clr done
523 out USB_OUT, output
524 rjmp stuffed4
525  
526 stuff5: ; 3
527 eor output, usbmask
528 rjmp stuffed5
529  
530 stuff6: ; 3
531 eor output, usbmask
532 rjmp stuffed6
533  
534 stuff7: ; 3
535 eor output, usbmask
536 rjmp stuffed7
537  
538 ; ----------------------------------------------------------------------
539 ; generate EOP, release the bus, and return from interrupt
540 ; ----------------------------------------------------------------------
541 gen_eop:
542 cbr output, USB_MASK
543 out USB_OUT, output ; output SE0 for 2 bit times
544 pop even
545 pop fixup
546 pop byte
547 ldi count, 1<<USB_INT_PENDING_BIT
548 out USB_INT_PENDING, count ; interrupt was triggered by transmit
549 pop YH ; this is the saved SREG
550 pop YL
551 in usbmask, USB_DDR
552 mov count, output
553 ori output, USB_MASK_DMINUS
554 out USB_OUT, output ; output J state for 1 bit time
555 cbr usbmask, USB_MASK
556 out SREG, YH
557 pop YH
558 pop odd ; is the same register as output!
559 nop
560 out USB_DDR, usbmask ; release bus
561 out USB_OUT, count ; disable D- pullup
562 pop usbmask
563 pop count
564 reti