]> git.cryptolib.org Git - labortage2013badge.git/blob - firmware/usbdrv/usbdrvasm15.inc
initial - non working - stuff
[labortage2013badge.git] / firmware / usbdrv / usbdrvasm15.inc
1 /* Name: usbdrvasm15.inc
2  * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
3  * Author: contributed by V. Bosch
4  * Creation Date: 2007-08-06
5  * Tabsize: 4
6  * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
7  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8  */
9
10 /* Do not link this file! Link usbdrvasm.S instead, which includes the
11  * appropriate implementation!
12  */
13
14 /*
15 General Description:
16 This file is the 15 MHz version of the asssembler part of the USB driver. It
17 requires a 15 MHz crystal (not a ceramic resonator and not a calibrated RC
18 oscillator).
19
20 See usbdrv.h for a description of the entire driver.
21
22 Since almost all of this code is timing critical, don't change unless you
23 really know what you are doing! Many parts require not only a maximum number
24 of CPU cycles, but even an exact number of cycles!
25 */
26
27 ;max stack usage: [ret(2), YL, SREG, YH, bitcnt, shift, x1, x2, x3, x4, cnt] = 12 bytes
28 ;nominal frequency: 15 MHz -> 10.0 cycles per bit, 80.0 cycles per byte
29 ; Numbers in brackets are clocks counted from center of last sync bit
30 ; when instruction starts
31
32 ;----------------------------------------------------------------------------
33 ; order of registers pushed: 
34 ;       YL, SREG [sofError] YH, shift, x1, x2, x3, bitcnt, cnt, x4
35 ;----------------------------------------------------------------------------
36 USB_INTR_VECTOR:              
37     push    YL                   ;2     push only what is necessary to sync with edge ASAP
38     in      YL, SREG             ;1 
39     push    YL                   ;2 
40 ;----------------------------------------------------------------------------
41 ; Synchronize with sync pattern:
42 ;
43 ;   sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
44 ;   sync up with J to K edge during sync pattern -- use fastest possible loops
45 ;The first part waits at most 1 bit long since we must be in sync pattern.
46 ;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
47 ;waitForJ, ensure that this prerequisite is met.
48 waitForJ:
49     inc     YL
50     sbis    USBIN, USBMINUS
51     brne    waitForJ        ; just make sure we have ANY timeout
52 ;-------------------------------------------------------------------------------
53 ; The following code results in a sampling window of < 1/4 bit 
54 ;       which meets the spec.
55 ;-------------------------------------------------------------------------------
56 waitForK:                        ;- 
57     sbis    USBIN, USBMINUS      ;1 [00] <-- sample
58     rjmp    foundK               ;2 [01]
59     sbis    USBIN, USBMINUS      ;       <-- sample
60     rjmp    foundK
61     sbis    USBIN, USBMINUS      ;       <-- sample
62     rjmp    foundK
63     sbis    USBIN, USBMINUS      ;       <-- sample
64     rjmp    foundK
65     sbis    USBIN, USBMINUS      ;       <-- sample
66     rjmp    foundK
67     sbis    USBIN, USBMINUS      ;       <-- sample
68     rjmp    foundK
69 #if USB_COUNT_SOF
70     lds     YL, usbSofCount
71     inc     YL
72     sts     usbSofCount, YL
73 #endif  /* USB_COUNT_SOF */
74 #ifdef USB_SOF_HOOK
75     USB_SOF_HOOK
76 #endif
77     rjmp    sofError
78 ;------------------------------------------------------------------------------
79 ; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for 
80 ;       center sampling] 
81 ;       we have 1 bit time for setup purposes, then sample again. 
82 ;       Numbers in brackets are cycles from center of first sync (double K) 
83 ;       bit after the instruction
84 ;------------------------------------------------------------------------------
85 foundK:                          ;- [02]
86     lds     YL, usbInputBufOffset;2 [03+04]     tx loop
87     push    YH                   ;2 [05+06]
88     clr     YH                   ;1 [07]
89     subi    YL, lo8(-(usbRxBuf)) ;1 [08]        [rx loop init]
90     sbci    YH, hi8(-(usbRxBuf)) ;1 [09]        [rx loop init]
91     push    shift                ;2 [10+11]
92     ser     shift                ;1 [12]
93     sbis    USBIN, USBMINUS      ;1 [-1] [13] <--sample:we want two bits K (sample 1 cycle too early)
94     rjmp    haveTwoBitsK         ;2 [00] [14]
95     pop     shift                ;2      [15+16] undo the push from before
96     pop     YH                   ;2      [17+18] undo the push from before
97     rjmp    waitForK             ;2      [19+20] this was not the end of sync, retry
98 ; The entire loop from waitForK until rjmp waitForK above must not exceed two
99 ; bit times (= 20 cycles).
100
101 ;----------------------------------------------------------------------------
102 ; push more registers and initialize values while we sample the first bits:
103 ;----------------------------------------------------------------------------
104 haveTwoBitsK:                   ;- [01]
105     push    x1                  ;2 [02+03]
106     push    x2                  ;2 [04+05]
107     push    x3                  ;2 [06+07]
108     push    bitcnt              ;2 [08+09]      
109     in      x1, USBIN           ;1 [00] [10] <-- sample bit 0
110     bst     x1, USBMINUS        ;1 [01]
111     bld     shift, 0            ;1 [02]
112     push    cnt                 ;2 [03+04]
113     ldi     cnt, USB_BUFSIZE    ;1 [05] 
114     push    x4                  ;2 [06+07] tx loop
115     rjmp    rxLoop              ;2 [08]
116 ;----------------------------------------------------------------------------
117 ; Receiver loop (numbers in brackets are cycles within byte after instr)
118 ;----------------------------------------------------------------------------
119 unstuff0:                       ;- [07] (branch taken)
120     andi    x3, ~0x01           ;1 [08]
121     mov     x1, x2              ;1 [09] x2 contains last sampled (stuffed) bit
122     in      x2, USBIN           ;1 [00] [10] <-- sample bit 1 again
123     andi    x2, USBMASK         ;1 [01]
124     breq    se0Hop              ;1 [02] SE0 check for bit 1 
125     ori     shift, 0x01         ;1 [03] 0b00000001
126     nop                         ;1 [04]
127     rjmp    didUnstuff0         ;2 [05]
128 ;-----------------------------------------------------
129 unstuff1:                       ;- [05] (branch taken)
130     mov     x2, x1              ;1 [06] x1 contains last sampled (stuffed) bit
131     andi    x3, ~0x02           ;1 [07]
132     ori     shift, 0x02         ;1 [08] 0b00000010
133     nop                         ;1 [09]
134     in      x1, USBIN           ;1 [00] [10] <-- sample bit 2 again
135     andi    x1, USBMASK         ;1 [01]
136     breq    se0Hop              ;1 [02] SE0 check for bit 2 
137     rjmp    didUnstuff1         ;2 [03]
138 ;-----------------------------------------------------
139 unstuff2:                       ;- [05] (branch taken)
140     andi    x3, ~0x04           ;1 [06]
141     ori     shift, 0x04         ;1 [07] 0b00000100
142     mov     x1, x2              ;1 [08] x2 contains last sampled (stuffed) bit
143     nop                         ;1 [09]
144     in      x2, USBIN           ;1 [00] [10] <-- sample bit 3
145     andi    x2, USBMASK         ;1 [01]
146     breq    se0Hop              ;1 [02] SE0 check for bit 3 
147     rjmp    didUnstuff2         ;2 [03]
148 ;-----------------------------------------------------
149 unstuff3:                       ;- [00] [10]  (branch taken)
150     in      x2, USBIN           ;1 [01] [11] <-- sample stuffed bit 3 one cycle too late
151     andi    x2, USBMASK         ;1 [02]
152     breq    se0Hop              ;1 [03] SE0 check for stuffed bit 3 
153     andi    x3, ~0x08           ;1 [04]
154     ori     shift, 0x08         ;1 [05] 0b00001000
155     rjmp    didUnstuff3         ;2 [06]
156 ;----------------------------------------------------------------------------
157 ; extra jobs done during bit interval:
158 ;
159 ; bit 0:    store, clear [SE0 is unreliable here due to bit dribbling in hubs], 
160 ;               overflow check, jump to the head of rxLoop
161 ; bit 1:    SE0 check
162 ; bit 2:    SE0 check, recovery from delay [bit 0 tasks took too long]
163 ; bit 3:    SE0 check, recovery from delay [bit 0 tasks took too long]
164 ; bit 4:    SE0 check, none
165 ; bit 5:    SE0 check, none
166 ; bit 6:    SE0 check, none
167 ; bit 7:    SE0 check, reconstruct: x3 is 0 at bit locations we changed, 1 at others
168 ;----------------------------------------------------------------------------
169 rxLoop:                         ;- [09]
170     in      x2, USBIN           ;1 [00] [10] <-- sample bit 1 (or possibly bit 0 stuffed)
171     andi    x2, USBMASK         ;1 [01]
172     brne    SkipSe0Hop          ;1 [02]
173 se0Hop:                         ;- [02]
174     rjmp    se0                 ;2 [03] SE0 check for bit 1 
175 SkipSe0Hop:                     ;- [03]
176     ser     x3                  ;1 [04]
177     andi    shift, 0xf9         ;1 [05] 0b11111001
178     breq    unstuff0            ;1 [06]
179 didUnstuff0:                    ;- [06]
180     eor     x1, x2              ;1 [07]
181     bst     x1, USBMINUS        ;1 [08]
182     bld     shift, 1            ;1 [09] 
183     in      x1, USBIN           ;1 [00] [10] <-- sample bit 2 (or possibly bit 1 stuffed)
184     andi    x1, USBMASK         ;1 [01]
185     breq    se0Hop              ;1 [02] SE0 check for bit 2 
186     andi    shift, 0xf3         ;1 [03] 0b11110011
187     breq    unstuff1            ;1 [04] do remaining work for bit 1
188 didUnstuff1:                    ;- [04]
189     eor     x2, x1              ;1 [05]
190     bst     x2, USBMINUS        ;1 [06]
191     bld     shift, 2            ;1 [07]
192     nop2                        ;2 [08+09]
193     in      x2, USBIN           ;1 [00] [10] <-- sample bit 3 (or possibly bit 2 stuffed)
194     andi    x2, USBMASK         ;1 [01]
195     breq    se0Hop              ;1 [02] SE0 check for bit 3 
196     andi    shift, 0xe7         ;1 [03] 0b11100111
197     breq    unstuff2            ;1 [04]
198 didUnstuff2:                    ;- [04]
199     eor     x1, x2              ;1 [05]
200     bst     x1, USBMINUS        ;1 [06]
201     bld     shift, 3            ;1 [07]
202 didUnstuff3:                    ;- [07]
203     andi    shift, 0xcf         ;1 [08] 0b11001111
204     breq    unstuff3            ;1 [09]
205     in      x1, USBIN           ;1 [00] [10] <-- sample bit 4
206     andi    x1, USBMASK         ;1 [01]
207     breq    se0Hop              ;1 [02] SE0 check for bit 4
208     eor     x2, x1              ;1 [03]
209     bst     x2, USBMINUS        ;1 [04]
210     bld     shift, 4            ;1 [05]
211 didUnstuff4:                    ;- [05]
212     andi    shift, 0x9f         ;1 [06] 0b10011111
213     breq    unstuff4            ;1 [07]
214     nop2                        ;2 [08+09]
215     in      x2, USBIN           ;1 [00] [10] <-- sample bit 5
216     andi    x2, USBMASK         ;1 [01]
217     breq    se0                 ;1 [02] SE0 check for bit 5
218     eor     x1, x2              ;1 [03]
219     bst     x1, USBMINUS        ;1 [04]
220     bld     shift, 5            ;1 [05]
221 didUnstuff5:                    ;- [05]
222     andi    shift, 0x3f         ;1 [06] 0b00111111
223     breq    unstuff5            ;1 [07]
224     nop2                        ;2 [08+09]
225     in      x1, USBIN           ;1 [00] [10] <-- sample bit 6
226     andi    x1, USBMASK         ;1 [01]
227     breq    se0                 ;1 [02] SE0 check for bit 6
228     eor     x2, x1              ;1 [03]
229     bst     x2, USBMINUS        ;1 [04]
230     bld     shift, 6            ;1 [05]
231 didUnstuff6:                    ;- [05]
232     cpi     shift, 0x02         ;1 [06] 0b00000010
233     brlo    unstuff6            ;1 [07]
234     nop2                        ;2 [08+09]
235     in      x2, USBIN           ;1 [00] [10] <-- sample bit 7
236     andi    x2, USBMASK         ;1 [01]
237     breq    se0                 ;1 [02] SE0 check for bit 7
238     eor     x1, x2              ;1 [03]
239     bst     x1, USBMINUS        ;1 [04]
240     bld     shift, 7            ;1 [05]
241 didUnstuff7:                    ;- [05] 
242     cpi     shift, 0x04         ;1 [06] 0b00000100
243     brlo    unstuff7            ;1 [07]
244     eor     x3, shift           ;1 [08] reconstruct: x3 is 0 at bit locations we changed, 1 at others
245     nop                         ;1 [09]
246     in      x1, USBIN           ;1 [00] [10] <-- sample bit 0
247     st      y+, x3              ;2 [01+02] store data
248     eor     x2, x1              ;1 [03]
249     bst     x2, USBMINUS        ;1 [04]
250     bld     shift, 0            ;1 [05]
251     subi    cnt, 1              ;1 [06]
252     brcs    overflow    ;1 [07]
253     rjmp    rxLoop              ;2 [08]
254 ;-----------------------------------------------------
255 unstuff4:                       ;- [08] 
256     andi    x3, ~0x10           ;1 [09]
257     in      x1, USBIN           ;1 [00] [10] <-- sample stuffed bit 4
258     andi    x1, USBMASK         ;1 [01]
259     breq    se0                 ;1 [02] SE0 check for stuffed bit 4
260     ori     shift, 0x10         ;1 [03]
261     rjmp    didUnstuff4         ;2 [04]
262 ;-----------------------------------------------------
263 unstuff5:                       ;- [08] 
264     ori     shift, 0x20         ;1 [09]
265     in      x2, USBIN           ;1 [00] [10] <-- sample stuffed bit 5
266     andi    x2, USBMASK         ;1 [01]
267     breq    se0                 ;1 [02] SE0 check for stuffed bit 5
268     andi    x3, ~0x20           ;1 [03]
269     rjmp    didUnstuff5         ;2 [04]
270 ;-----------------------------------------------------
271 unstuff6:                       ;- [08] 
272     andi    x3, ~0x40           ;1 [09]
273     in      x1, USBIN           ;1 [00] [10] <-- sample stuffed bit 6
274     andi    x1, USBMASK         ;1 [01]
275     breq    se0                 ;1 [02] SE0 check for stuffed bit 6
276     ori     shift, 0x40         ;1 [03]
277     rjmp    didUnstuff6         ;2 [04]
278 ;-----------------------------------------------------
279 unstuff7:                       ;- [08]
280     andi    x3, ~0x80           ;1 [09]
281     in      x2, USBIN           ;1 [00] [10] <-- sample stuffed bit 7
282     andi    x2, USBMASK         ;1 [01]
283     breq    se0                 ;1 [02] SE0 check for stuffed bit 7
284     ori     shift, 0x80         ;1 [03]
285     rjmp    didUnstuff7         ;2 [04]
286     
287 macro POP_STANDARD ; 16 cycles
288     pop     x4    
289     pop     cnt
290     pop     bitcnt
291     pop     x3
292     pop     x2
293     pop     x1
294     pop     shift
295     pop     YH
296     endm
297 macro POP_RETI     ; 5 cycles
298     pop     YL
299     out     SREG, YL
300     pop     YL
301     endm
302
303 #include "asmcommon.inc"
304
305 ;---------------------------------------------------------------------------
306 ; USB spec says:
307 ; idle = J
308 ; J = (D+ = 0), (D- = 1)
309 ; K = (D+ = 1), (D- = 0)
310 ; Spec allows 7.5 bit times from EOP to SOP for replies
311 ;---------------------------------------------------------------------------
312 bitstuffN:                      ;- [04]
313     eor     x1, x4              ;1 [05]
314     clr     x2                  ;1 [06]
315     nop                         ;1 [07]
316     rjmp    didStuffN           ;1 [08]
317 ;---------------------------------------------------------------------------    
318 bitstuff6:                      ;- [04]
319     eor     x1, x4              ;1 [05]
320     clr     x2                  ;1 [06]
321     rjmp    didStuff6           ;1 [07]
322 ;---------------------------------------------------------------------------
323 bitstuff7:                      ;- [02]
324     eor     x1, x4              ;1 [03]
325     clr     x2                  ;1 [06]
326     nop                         ;1 [05]
327     rjmp    didStuff7           ;1 [06]
328 ;---------------------------------------------------------------------------
329 sendNakAndReti:                 ;- [-19]
330     ldi     x3, USBPID_NAK      ;1 [-18]
331     rjmp    sendX3AndReti       ;1 [-17]
332 ;---------------------------------------------------------------------------
333 sendAckAndReti:                 ;- [-17]
334     ldi     cnt, USBPID_ACK     ;1 [-16]
335 sendCntAndReti:                 ;- [-16]
336     mov     x3, cnt             ;1 [-15]
337 sendX3AndReti:                  ;- [-15]
338     ldi     YL, 20              ;1 [-14] x3==r20 address is 20
339     ldi     YH, 0               ;1 [-13]
340     ldi     cnt, 2              ;1 [-12]
341 ;   rjmp    usbSendAndReti      fallthrough
342 ;---------------------------------------------------------------------------
343 ;usbSend:
344 ;pointer to data in 'Y'
345 ;number of bytes in 'cnt' -- including sync byte [range 2 ... 12]
346 ;uses: x1...x4, btcnt, shift, cnt, Y
347 ;Numbers in brackets are time since first bit of sync pattern is sent
348 ;We need not to match the transfer rate exactly because the spec demands 
349 ;only 1.5% precision anyway.
350 usbSendAndReti:                 ;- [-13] 13 cycles until SOP
351     in      x2, USBDDR          ;1 [-12]
352     ori     x2, USBMASK         ;1 [-11]
353     sbi     USBOUT, USBMINUS    ;2 [-09-10] prepare idle state; D+ and D- must have been 0 (no pullups)
354     in      x1, USBOUT          ;1 [-08] port mirror for tx loop
355     out     USBDDR, x2          ;1 [-07] <- acquire bus
356         ; need not init x2 (bitstuff history) because sync starts with 0 
357     ldi     x4, USBMASK         ;1 [-06]        exor mask
358     ldi     shift, 0x80         ;1 [-05]        sync byte is first byte sent
359     ldi     bitcnt, 6           ;1 [-04] 
360 txBitLoop:                      ;- [-04] [06]
361     sbrs    shift, 0            ;1 [-03] [07]
362     eor     x1, x4              ;1 [-02] [08] 
363     ror     shift               ;1 [-01] [09]  
364 didStuffN:                      ;-       [09]
365     out     USBOUT, x1          ;1 [00]  [10] <-- out N
366     ror     x2                  ;1 [01]
367     cpi     x2, 0xfc            ;1 [02]
368     brcc    bitstuffN           ;1 [03]
369     dec     bitcnt              ;1 [04]
370     brne    txBitLoop           ;1 [05]
371     sbrs    shift, 0            ;1 [06]
372     eor     x1, x4              ;1 [07]
373     ror     shift               ;1 [08]
374 didStuff6:                      ;- [08]
375     nop                         ;1 [09]
376     out     USBOUT, x1          ;1 [00] [10] <-- out 6
377     ror     x2                  ;1 [01] 
378     cpi     x2, 0xfc            ;1 [02]
379     brcc    bitstuff6           ;1 [03]
380     sbrs    shift, 0            ;1 [04]
381     eor     x1, x4              ;1 [05]
382     ror     shift               ;1 [06]
383     ror     x2                  ;1 [07]
384 didStuff7:                      ;- [07]
385     ldi     bitcnt, 6           ;1 [08]
386     cpi     x2, 0xfc            ;1 [09]
387     out     USBOUT, x1          ;1 [00] [10] <-- out 7
388     brcc    bitstuff7           ;1 [01]
389     ld      shift, y+           ;2 [02+03]
390     dec     cnt                 ;1 [04]
391     brne    txBitLoop           ;1 [05]
392 makeSE0:
393     cbr     x1, USBMASK         ;1 [06]         prepare SE0 [spec says EOP may be 19 to 23 cycles]
394     lds     x2, usbNewDeviceAddr;2 [07+08]
395     lsl     x2                  ;1 [09] we compare with left shifted address
396 ;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
397 ;set address only after data packet was sent, not after handshake
398     out     USBOUT, x1          ;1 [00] [10] <-- out SE0-- from now 2 bits==20 cycl. until bus idle
399     subi    YL, 20 + 2          ;1 [01] Only assign address on data packets, not ACK/NAK in x3
400     sbci    YH, 0               ;1 [02]
401     breq    skipAddrAssign      ;1 [03]
402     sts     usbDeviceAddr, x2   ;2 [04+05] if not skipped: SE0 is one cycle longer
403 ;----------------------------------------------------------------------------
404 ;end of usbDeviceAddress transfer
405 skipAddrAssign:                         ;- [03/04]
406     ldi     x2, 1<<USB_INTR_PENDING_BIT ;1 [05] int0 occurred during TX -- clear pending flag
407     USB_STORE_PENDING(x2)           ;1 [06]
408     ori     x1, USBIDLE                 ;1 [07]
409     in      x2, USBDDR                  ;1 [08]
410     cbr     x2, USBMASK                 ;1 [09] set both pins to input
411     mov     x3, x1                      ;1 [10]
412     cbr     x3, USBMASK                 ;1 [11] configure no pullup on both pins
413     ldi     x4, 3                       ;1 [12]
414 se0Delay:                               ;- [12] [15] 
415     dec     x4                          ;1 [13] [16] 
416     brne    se0Delay                    ;1 [14] [17] 
417     nop2                                ;2      [18+19]
418     out     USBOUT, x1                  ;1      [20] <--out J (idle) -- end of SE0 (EOP sig.)
419     out     USBDDR, x2                  ;1      [21] <--release bus now
420     out     USBOUT, x3                  ;1      [22] <--ensure no pull-up resistors are active
421     rjmp    doReturn                    ;1      [23]
422 ;---------------------------------------------------------------------------