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