manueller import aus nem CVS checkout (ist eh nur zum testen)
[ds1820tousb.git] / usbdrv / usbdrvasm128.inc
CommitLineData
93ac315e
MPM
1/* Name: usbdrvasm128.inc
2 * Project: AVR USB driver
3 * Author: Christian Starkjohann
4 * Creation Date: 2008-10-11
5 * Tabsize: 4
6 * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
7 * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
8 * This Revision: $Id: usbdrvasm128.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/*
16General Description:
17This file is the 12.8 MHz version of the USB driver. It is intended for use
18with the internal RC oscillator. Although 12.8 MHz is outside the guaranteed
19calibration range of the oscillator, almost all AVRs can reach this frequency.
20This version contains a phase locked loop in the receiver routine to cope with
21slight clock rate deviations of up to +/- 1%.
22
23See usbdrv.h for a description of the entire driver.
24
25LIMITATIONS
26===========
27Although it may seem very handy to save the crystal and use the internal
28RC oscillator of the CPU, this method (and this module) has some serious
29limitations:
30(1) The guaranteed calibration range of the oscillator is only 8.1 MHz.
31They typical range is 14.5 MHz and most AVRs can actually reach this rate.
32(2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
33the write procedure is timed from the RC oscillator.
34(3) End Of Packet detection is between bit 0 and bit 1 where the EOP condition
35may not be reliable when a hub is used. It should be in bit 1.
36(4) Code size is much larger than that of the other modules.
37
38Since almost all of this code is timing critical, don't change unless you
39really know what you are doing! Many parts require not only a maximum number
40of CPU cycles, but even an exact number of cycles!
41
42Implementation notes:
43======================
44min frequency: 67 cycles for 8 bit -> 12.5625 MHz
45max frequency: 69.286 cycles for 8 bit -> 12.99 MHz
46nominal frequency: 12.77 MHz ( = sqrt(min * max))
47
48sampling positions: (next even number in range [+/- 0.5])
49cycle index range: 0 ... 66
50bits:
51.5, 8.875, 17.25, 25.625, 34, 42.375, 50.75, 59.125
52[0/1], [9], [17], [25/+26], [34], [+42/43], [51], [59]
53
54bit number: 0 1 2 3 4 5 6 7
55spare cycles 1 2 1 2 1 1 1 0
56
57operations to perform: duration cycle
58 ----------------
59 eor fix, shift 1 -> 00
60 andi phase, USBMASK 1 -> 08
61 breq se0 1 -> 16 (moved to 11)
62 st y+, data 2 -> 24, 25
63 mov data, fix 1 -> 33
64 ser data 1 -> 41
65 subi cnt, 1 1 -> 49
66 brcs overflow 1 -> 50
67
68layout of samples and operations:
69[##] = sample bit
70<##> = sample phase
71*##* = operation
72
730: *00* [01] 02 03 04 <05> 06 07
741: *08* [09] 10 11 12 <13> 14 15 *16*
752: [17] 18 19 20 <21> 22 23
763: *24* *25* [26] 27 28 29 <30> 31 32
774: *33* [34] 35 36 37 <38> 39 40
785: *41* [42] 43 44 45 <46> 47 48
796: *49* *50* [51] 52 53 54 <55> 56 57 58
807: [59] 60 61 62 <63> 64 65 66
81*****************************************************************************/
82
83/* we prefer positive expressions (do if condition) instead of negative
84 * (skip if condition), therefore use defines for skip instructions:
85 */
86#define ifioclr sbis
87#define ifioset sbic
88#define ifrclr sbrs
89#define ifrset sbrc
90
91/* The registers "fix" and "data" swap their meaning during the loop. Use
92 * defines to keep their name constant.
93 */
94#define fix x2
95#define data x1
96#undef phase /* phase has a default definition to x4 */
97#define phase x3
98
99
100USB_INTR_VECTOR:
101;order of registers pushed: YL, SREG [sofError], YH, shift, x1, x2, x3, cnt, r0
102 push YL ;2 push only what is necessary to sync with edge ASAP
103 in YL, SREG ;1
104 push YL ;2
105;----------------------------------------------------------------------------
106; Synchronize with sync pattern:
107;----------------------------------------------------------------------------
108;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
109;sync up with J to K edge during sync pattern -- use fastest possible loops
110;The first part waits at most 1 bit long since we must be in sync pattern.
111;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
112;waitForJ, ensure that this prerequisite is met.
113waitForJ:
114 inc YL
115 sbis USBIN, USBMINUS
116 brne waitForJ ; just make sure we have ANY timeout
117waitForK:
118;The following code results in a sampling window of 1/4 bit which meets the spec.
119 sbis USBIN, USBMINUS
120 rjmp foundK
121 sbis USBIN, USBMINUS
122 rjmp foundK
123 sbis USBIN, USBMINUS
124 rjmp foundK
125 sbis USBIN, USBMINUS
126 rjmp foundK
127 sbis USBIN, USBMINUS ;[0]
128 rjmp foundK ;[1]
129#if USB_COUNT_SOF
130 lds YL, usbSofCount
131 inc YL
132 sts usbSofCount, YL
133#endif /* USB_COUNT_SOF */
134#ifdef USB_SOF_HOOK
135 USB_SOF_HOOK
136#endif
137 rjmp sofError
138
139foundK:
140;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
141;we have 1 bit time for setup purposes, then sample again. Numbers in brackets
142;are cycles from center of first sync (double K) bit after the instruction
143 push YH ;[2]
144 lds YL, usbInputBufOffset;[4]
145 clr YH ;[6]
146 subi YL, lo8(-(usbRxBuf));[7]
147 sbci YH, hi8(-(usbRxBuf));[8]
148
149 sbis USBIN, USBMINUS ;[9] we want two bits K [we want to sample at 8 + 4 - 1.5 = 10.5]
150 rjmp haveTwoBitsK ;[10]
151 pop YH ;[11] undo the push from before
152 rjmp waitForK ;[13] this was not the end of sync, retry
153haveTwoBitsK:
154;----------------------------------------------------------------------------
155; push more registers and initialize values while we sample the first bits:
156;----------------------------------------------------------------------------
157#define fix x2
158#define data x1
159
160 push shift ;[12]
161 push x1 ;[14]
162 push x2 ;[16]
163 ldi shift, 0x80 ;[18] prevent bit-unstuffing but init low bits to 0
164 ifioset USBIN, USBMINUS ;[19] [01] <--- bit 0 [10.5 + 8 = 18.5]
165 ori shift, 1<<0 ;[02]
166 push x3 ;[03]
167 push cnt ;[05]
168 push r0 ;[07]
169 ifioset USBIN, USBMINUS ;[09] <--- bit 1
170 ori shift, 1<<1 ;[10]
171 ser fix ;[11]
172 ldi cnt, USB_BUFSIZE ;[12]
173 mov data, shift ;[13]
174 lsl shift ;[14]
175 nop2 ;[15]
176 ifioset USBIN, USBMINUS ;[17] <--- bit 2
177 ori data, 3<<2 ;[18] store in bit 2 AND bit 3
178 eor shift, data ;[19] do nrzi decoding
179 andi data, 1<<3 ;[20]
180 in phase, USBIN ;[21] <- phase
181 brne jumpToEntryAfterSet ;[22] if USBMINS at bit 3 was 1
182 nop ;[23]
183 rjmp entryAfterClr ;[24]
184jumpToEntryAfterSet:
185 rjmp entryAfterSet ;[24]
186
187;----------------------------------------------------------------------------
188; Receiver loop (numbers in brackets are cycles within byte after instr)
189;----------------------------------------------------------------------------
190#undef fix
191#define fix x1
192#undef data
193#define data x2
194
195bit7IsSet:
196 ifrclr phase, USBMINUS ;[62] check phase only if D- changed
197 lpm ;[63]
198 in phase, USBIN ;[64] <- phase (one cycle too late)
199 ori shift, 1 << 7 ;[65]
200 nop ;[66]
201;;;;rjmp bit0AfterSet ; -> [00] == [67] moved block up to save jump
202bit0AfterSet:
203 eor fix, shift ;[00]
204#undef fix
205#define fix x2
206#undef data
207#define data x1 /* we now have result in data, fix is reset to 0xff */
208 ifioclr USBIN, USBMINUS ;[01] <--- sample 0
209 rjmp bit0IsClr ;[02]
210 andi shift, ~(7 << 0) ;[03]
211 breq unstuff0s ;[04]
212 in phase, USBIN ;[05] <- phase
213 rjmp bit1AfterSet ;[06]
214unstuff0s:
215 in phase, USBIN ;[06] <- phase (one cycle too late)
216 andi fix, ~(1 << 0) ;[07]
217 ifioclr USBIN, USBMINUS ;[00]
218 ifioset USBIN, USBPLUS ;[01]
219 rjmp bit0IsClr ;[02] executed if first expr false or second true
220jumpToSe0AndStore:
221 rjmp se0AndStore ;[03] executed only if both bits 0
222bit0IsClr:
223 ifrset phase, USBMINUS ;[04] check phase only if D- changed
224 lpm ;[05]
225 in phase, USBIN ;[06] <- phase (one cycle too late)
226 ori shift, 1 << 0 ;[07]
227bit1AfterClr:
228 andi phase, USBMASK ;[08]
229 ifioset USBIN, USBMINUS ;[09] <--- sample 1
230 rjmp bit1IsSet ;[10]
231 breq jumpToSe0AndStore ;[11]
232 andi shift, ~(7 << 1) ;[12]
233 in phase, USBIN ;[13] <- phase
234 breq unstuff1c ;[14]
235 rjmp bit2AfterClr ;[15]
236unstuff1c:
237 andi fix, ~(1 << 1) ;[16]
238 nop2 ;[08]
239 nop2 ;[10]
240bit1IsSet:
241 ifrclr phase, USBMINUS ;[12] check phase only if D- changed
242 lpm ;[13]
243 in phase, USBIN ;[14] <- phase (one cycle too late)
244 ori shift, 1 << 1 ;[15]
245 nop ;[16]
246bit2AfterSet:
247 ifioclr USBIN, USBMINUS ;[17] <--- sample 2
248 rjmp bit2IsClr ;[18]
249 andi shift, ~(7 << 2) ;[19]
250 breq unstuff2s ;[20]
251 in phase, USBIN ;[21] <- phase
252 rjmp bit3AfterSet ;[22]
253unstuff2s:
254 in phase, USBIN ;[22] <- phase (one cycle too late)
255 andi fix, ~(1 << 2) ;[23]
256 nop2 ;[16]
257 nop2 ;[18]
258bit2IsClr:
259 ifrset phase, USBMINUS ;[20] check phase only if D- changed
260 lpm ;[21]
261 in phase, USBIN ;[22] <- phase (one cycle too late)
262 ori shift, 1 << 2 ;[23]
263bit3AfterClr:
264 st y+, data ;[24]
265entryAfterClr:
266 ifioset USBIN, USBMINUS ;[26] <--- sample 3
267 rjmp bit3IsSet ;[27]
268 andi shift, ~(7 << 3) ;[28]
269 breq unstuff3c ;[29]
270 in phase, USBIN ;[30] <- phase
271 rjmp bit4AfterClr ;[31]
272unstuff3c:
273 in phase, USBIN ;[31] <- phase (one cycle too late)
274 andi fix, ~(1 << 3) ;[32]
275 nop2 ;[25]
276 nop2 ;[27]
277bit3IsSet:
278 ifrclr phase, USBMINUS ;[29] check phase only if D- changed
279 lpm ;[30]
280 in phase, USBIN ;[31] <- phase (one cycle too late)
281 ori shift, 1 << 3 ;[32]
282bit4AfterSet:
283 mov data, fix ;[33] undo this move by swapping defines
284#undef fix
285#define fix x1
286#undef data
287#define data x2
288 ifioclr USBIN, USBMINUS ;[34] <--- sample 4
289 rjmp bit4IsClr ;[35]
290 andi shift, ~(7 << 4) ;[36]
291 breq unstuff4s ;[37]
292 in phase, USBIN ;[38] <- phase
293 rjmp bit5AfterSet ;[39]
294unstuff4s:
295 in phase, USBIN ;[39] <- phase (one cycle too late)
296 andi fix, ~(1 << 4) ;[40]
297 nop2 ;[33]
298 nop2 ;[35]
299bit4IsClr:
300 ifrset phase, USBMINUS ;[37] check phase only if D- changed
301 lpm ;[38]
302 in phase, USBIN ;[39] <- phase (one cycle too late)
303 ori shift, 1 << 4 ;[40]
304bit5AfterClr:
305 ser data ;[41]
306 ifioset USBIN, USBMINUS ;[42] <--- sample 5
307 rjmp bit5IsSet ;[43]
308 andi shift, ~(7 << 5) ;[44]
309 breq unstuff5c ;[45]
310 in phase, USBIN ;[46] <- phase
311 rjmp bit6AfterClr ;[47]
312unstuff5c:
313 in phase, USBIN ;[47] <- phase (one cycle too late)
314 andi fix, ~(1 << 5) ;[48]
315 nop2 ;[41]
316 nop2 ;[43]
317bit5IsSet:
318 ifrclr phase, USBMINUS ;[45] check phase only if D- changed
319 lpm ;[46]
320 in phase, USBIN ;[47] <- phase (one cycle too late)
321 ori shift, 1 << 5 ;[48]
322bit6AfterSet:
323 subi cnt, 1 ;[49]
324 brcs jumpToOverflow ;[50]
325 ifioclr USBIN, USBMINUS ;[51] <--- sample 6
326 rjmp bit6IsClr ;[52]
327 andi shift, ~(3 << 6) ;[53]
328 cpi shift, 2 ;[54]
329 in phase, USBIN ;[55] <- phase
330 brlt unstuff6s ;[56]
331 rjmp bit7AfterSet ;[57]
332
333jumpToOverflow:
334 rjmp overflow
335
336unstuff6s:
337 andi fix, ~(1 << 6) ;[50]
338 lpm ;[51]
339bit6IsClr:
340 ifrset phase, USBMINUS ;[54] check phase only if D- changed
341 lpm ;[55]
342 in phase, USBIN ;[56] <- phase (one cycle too late)
343 ori shift, 1 << 6 ;[57]
344 nop ;[58]
345bit7AfterClr:
346 ifioset USBIN, USBMINUS ;[59] <--- sample 7
347 rjmp bit7IsSet ;[60]
348 andi shift, ~(1 << 7) ;[61]
349 cpi shift, 4 ;[62]
350 in phase, USBIN ;[63] <- phase
351 brlt unstuff7c ;[64]
352 rjmp bit0AfterClr ;[65] -> [00] == [67]
353unstuff7c:
354 andi fix, ~(1 << 7) ;[58]
355 nop ;[59]
356 rjmp bit7IsSet ;[60]
357
358se0AndStore:
359 st y+, x1 ;[15/17] cycles after start of byte
360 rjmp se0 ;[17/19]
361
362bit7IsClr:
363 ifrset phase, USBMINUS ;[62] check phase only if D- changed
364 lpm ;[63]
365 in phase, USBIN ;[64] <- phase (one cycle too late)
366 ori shift, 1 << 7 ;[65]
367 nop ;[66]
368;;;;rjmp bit0AfterClr ; -> [00] == [67] moved block up to save jump
369bit0AfterClr:
370 eor fix, shift ;[00]
371#undef fix
372#define fix x2
373#undef data
374#define data x1 /* we now have result in data, fix is reset to 0xff */
375 ifioset USBIN, USBMINUS ;[01] <--- sample 0
376 rjmp bit0IsSet ;[02]
377 andi shift, ~(7 << 0) ;[03]
378 breq unstuff0c ;[04]
379 in phase, USBIN ;[05] <- phase
380 rjmp bit1AfterClr ;[06]
381unstuff0c:
382 in phase, USBIN ;[06] <- phase (one cycle too late)
383 andi fix, ~(1 << 0) ;[07]
384 ifioclr USBIN, USBMINUS ;[00]
385 ifioset USBIN, USBPLUS ;[01]
386 rjmp bit0IsSet ;[02] executed if first expr false or second true
387 rjmp se0AndStore ;[03] executed only if both bits 0
388bit0IsSet:
389 ifrclr phase, USBMINUS ;[04] check phase only if D- changed
390 lpm ;[05]
391 in phase, USBIN ;[06] <- phase (one cycle too late)
392 ori shift, 1 << 0 ;[07]
393bit1AfterSet:
394 andi phase, USBMASK ;[08]
395 ifioclr USBIN, USBMINUS ;[09] <--- sample 1
396 rjmp bit1IsClr ;[10]
397 andi shift, ~(7 << 1) ;[11]
398 breq unstuff1s ;[12]
399 in phase, USBIN ;[13] <- phase
400 nop ;[14]
401 rjmp bit2AfterSet ;[15]
402unstuff1s:
403 in phase, USBIN ;[14] <- phase (one cycle too late)
404 andi fix, ~(1 << 1) ;[15]
405 nop2 ;[08]
406 nop2 ;[10]
407bit1IsClr:
408 ifrset phase, USBMINUS ;[12] check phase only if D- changed
409 lpm ;[13]
410 in phase, USBIN ;[14] <- phase (one cycle too late)
411 breq se0AndStore ;[15] if we come from unstuff1s, Z bit is never set
412 ori shift, 1 << 1 ;[16]
413bit2AfterClr:
414 ifioset USBIN, USBMINUS ;[17] <--- sample 2
415 rjmp bit2IsSet ;[18]
416 andi shift, ~(7 << 2) ;[19]
417 breq unstuff2c ;[20]
418 in phase, USBIN ;[21] <- phase
419 rjmp bit3AfterClr ;[22]
420unstuff2c:
421 in phase, USBIN ;[22] <- phase (one cycle too late)
422 andi fix, ~(1 << 2) ;[23]
423 nop2 ;[16]
424 nop2 ;[18]
425bit2IsSet:
426 ifrclr phase, USBMINUS ;[20] check phase only if D- changed
427 lpm ;[21]
428 in phase, USBIN ;[22] <- phase (one cycle too late)
429 ori shift, 1 << 2 ;[23]
430bit3AfterSet:
431 st y+, data ;[24]
432entryAfterSet:
433 ifioclr USBIN, USBMINUS ;[26] <--- sample 3
434 rjmp bit3IsClr ;[27]
435 andi shift, ~(7 << 3) ;[28]
436 breq unstuff3s ;[29]
437 in phase, USBIN ;[30] <- phase
438 rjmp bit4AfterSet ;[31]
439unstuff3s:
440 in phase, USBIN ;[31] <- phase (one cycle too late)
441 andi fix, ~(1 << 3) ;[32]
442 nop2 ;[25]
443 nop2 ;[27]
444bit3IsClr:
445 ifrset phase, USBMINUS ;[29] check phase only if D- changed
446 lpm ;[30]
447 in phase, USBIN ;[31] <- phase (one cycle too late)
448 ori shift, 1 << 3 ;[32]
449bit4AfterClr:
450 mov data, fix ;[33] undo this move by swapping defines
451#undef fix
452#define fix x1
453#undef data
454#define data x2
455 ifioset USBIN, USBMINUS ;[34] <--- sample 4
456 rjmp bit4IsSet ;[35]
457 andi shift, ~(7 << 4) ;[36]
458 breq unstuff4c ;[37]
459 in phase, USBIN ;[38] <- phase
460 rjmp bit5AfterClr ;[39]
461unstuff4c:
462 in phase, USBIN ;[39] <- phase (one cycle too late)
463 andi fix, ~(1 << 4) ;[40]
464 nop2 ;[33]
465 nop2 ;[35]
466bit4IsSet:
467 ifrclr phase, USBMINUS ;[37] check phase only if D- changed
468 lpm ;[38]
469 in phase, USBIN ;[39] <- phase (one cycle too late)
470 ori shift, 1 << 4 ;[40]
471bit5AfterSet:
472 ser data ;[41]
473 ifioclr USBIN, USBMINUS ;[42] <--- sample 5
474 rjmp bit5IsClr ;[43]
475 andi shift, ~(7 << 5) ;[44]
476 breq unstuff5s ;[45]
477 in phase, USBIN ;[46] <- phase
478 rjmp bit6AfterSet ;[47]
479unstuff5s:
480 in phase, USBIN ;[47] <- phase (one cycle too late)
481 andi fix, ~(1 << 5) ;[48]
482 nop2 ;[41]
483 nop2 ;[43]
484bit5IsClr:
485 ifrset phase, USBMINUS ;[45] check phase only if D- changed
486 lpm ;[46]
487 in phase, USBIN ;[47] <- phase (one cycle too late)
488 ori shift, 1 << 5 ;[48]
489bit6AfterClr:
490 subi cnt, 1 ;[49]
491 brcs overflow ;[50]
492 ifioset USBIN, USBMINUS ;[51] <--- sample 6
493 rjmp bit6IsSet ;[52]
494 andi shift, ~(3 << 6) ;[53]
495 cpi shift, 2 ;[54]
496 in phase, USBIN ;[55] <- phase
497 brlt unstuff6c ;[56]
498 rjmp bit7AfterClr ;[57]
499unstuff6c:
500 andi fix, ~(1 << 6) ;[50]
501 lpm ;[51]
502bit6IsSet:
503 ifrclr phase, USBMINUS ;[54] check phase only if D- changed
504 lpm ;[55]
505 in phase, USBIN ;[56] <- phase (one cycle too late)
506 ori shift, 1 << 6 ;[57]
507bit7AfterSet:
508 ifioclr USBIN, USBMINUS ;[59] <--- sample 7
509 rjmp bit7IsClr ;[60]
510 andi shift, ~(1 << 7) ;[61]
511 cpi shift, 4 ;[62]
512 in phase, USBIN ;[63] <- phase
513 brlt unstuff7s ;[64]
514 rjmp bit0AfterSet ;[65] -> [00] == [67]
515unstuff7s:
516 andi fix, ~(1 << 7) ;[58]
517 nop ;[59]
518 rjmp bit7IsClr ;[60]
519
520macro POP_STANDARD ; 14 cycles
521 pop r0
522 pop cnt
523 pop x3
524 pop x2
525 pop x1
526 pop shift
527 pop YH
528 endm
529macro POP_RETI ; 5 cycles
530 pop YL
531 out SREG, YL
532 pop YL
533 endm
534
535#include "asmcommon.inc"
536
537;----------------------------------------------------------------------------
538; Transmitting data
539;----------------------------------------------------------------------------
540
541txByteLoop:
542txBitloop:
543stuffN1Delay: ; [03]
544 ror shift ;[-5] [11] [63]
545 brcc doExorN1 ;[-4] [64]
546 subi x3, 1 ;[-3]
547 brne commonN1 ;[-2]
548 lsl shift ;[-1] compensate ror after rjmp stuffDelay
549 nop ;[00] stuffing consists of just waiting 8 cycles
550 rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
551
552sendNakAndReti:
553 ldi cnt, USBPID_NAK ;[-19]
554 rjmp sendCntAndReti ;[-18]
555sendAckAndReti:
556 ldi cnt, USBPID_ACK ;[-17]
557sendCntAndReti:
558 mov r0, cnt ;[-16]
559 ldi YL, 0 ;[-15] R0 address is 0
560 ldi YH, 0 ;[-14]
561 ldi cnt, 2 ;[-13]
562; rjmp usbSendAndReti fallthrough
563
564; USB spec says:
565; idle = J
566; J = (D+ = 0), (D- = 1) or USBOUT = 0x01
567; K = (D+ = 1), (D- = 0) or USBOUT = 0x02
568; Spec allows 7.5 bit times from EOP to SOP for replies (= 60 cycles)
569
570;usbSend:
571;pointer to data in 'Y'
572;number of bytes in 'cnt' -- including sync byte
573;uses: x1...x3, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x3 = bitstuff cnt]
574;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
575usbSendAndReti:
576 in x2, USBDDR ;[-10] 10 cycles until SOP
577 ori x2, USBMASK ;[-9]
578 sbi USBOUT, USBMINUS ;[-8] prepare idle state; D+ and D- must have been 0 (no pullups)
579 out USBDDR, x2 ;[-6] <--- acquire bus
580 in x1, USBOUT ;[-5] port mirror for tx loop
581 ldi shift, 0x40 ;[-4] sync byte is first byte sent (we enter loop after ror)
582 ldi x2, USBMASK ;[-3]
583doExorN1:
584 eor x1, x2 ;[-2] [06] [62]
585 ldi x3, 6 ;[-1] [07] [63]
586commonN1:
587stuffN2Delay:
588 out USBOUT, x1 ;[00] [08] [64] <--- set bit
589 ror shift ;[01]
590 brcc doExorN2 ;[02]
591 subi x3, 1 ;[03]
592 brne commonN2 ;[04]
593 lsl shift ;[05] compensate ror after rjmp stuffDelay
594 rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
595doExorN2:
596 eor x1, x2 ;[04] [12]
597 ldi x3, 6 ;[05] [13]
598commonN2:
599 nop2 ;[06] [14]
600 subi cnt, 171 ;[08] [16] trick: (3 * 171) & 0xff = 1
601 out USBOUT, x1 ;[09] [17] <--- set bit
602 brcs txBitloop ;[10] [27] [44]
603
604stuff6Delay:
605 ror shift ;[45] [53]
606 brcc doExor6 ;[46]
607 subi x3, 1 ;[47]
608 brne common6 ;[48]
609 lsl shift ;[49] compensate ror after rjmp stuffDelay
610 nop ;[50] stuffing consists of just waiting 8 cycles
611 rjmp stuff6Delay ;[51] after ror, C bit is reliably clear
612doExor6:
613 eor x1, x2 ;[48] [56]
614 ldi x3, 6 ;[49]
615common6:
616stuff7Delay:
617 ror shift ;[50] [58]
618 out USBOUT, x1 ;[51] <--- set bit
619 brcc doExor7 ;[52]
620 subi x3, 1 ;[53]
621 brne common7 ;[54]
622 lsl shift ;[55] compensate ror after rjmp stuffDelay
623 rjmp stuff7Delay ;[56] after ror, C bit is reliably clear
624doExor7:
625 eor x1, x2 ;[54] [62]
626 ldi x3, 6 ;[55]
627common7:
628 ld shift, y+ ;[56]
629 nop ;[58]
630 tst cnt ;[59]
631 out USBOUT, x1 ;[60] [00]<--- set bit
632 brne txByteLoop ;[61] [01]
633;make SE0:
634 cbr x1, USBMASK ;[02] prepare SE0 [spec says EOP may be 15 to 18 cycles]
635 lds x2, usbNewDeviceAddr;[03]
636 lsl x2 ;[05] we compare with left shifted address
637 subi YL, 2 + 0 ;[06] Only assign address on data packets, not ACK/NAK in r0
638 sbci YH, 0 ;[07]
639 out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
640;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
641;set address only after data packet was sent, not after handshake
642 breq skipAddrAssign ;[01]
643 sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
644skipAddrAssign:
645;end of usbDeviceAddress transfer
646 ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
647 USB_STORE_PENDING(x2) ;[04]
648 ori x1, USBIDLE ;[05]
649 in x2, USBDDR ;[06]
650 cbr x2, USBMASK ;[07] set both pins to input
651 mov x3, x1 ;[08]
652 cbr x3, USBMASK ;[09] configure no pullup on both pins
653 lpm ;[10]
654 lpm ;[13]
655 out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
656 out USBDDR, x2 ;[17] <-- release bus now
657 out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
658 rjmp doReturn
659
660
661
662/*****************************************************************************
663The following PHP script generates a code skeleton for the receiver routine:
664
665<?php
666
667function printCmdBuffer($thisBit)
668{
669global $cycle;
670
671 $nextBit = ($thisBit + 1) % 8;
672 $s = ob_get_contents();
673 ob_end_clean();
674 $s = str_replace("#", $thisBit, $s);
675 $s = str_replace("@", $nextBit, $s);
676 $lines = explode("\n", $s);
677 for($i = 0; $i < count($lines); $i++){
678 $s = $lines[$i];
679 if(ereg("\\[([0-9-][0-9])\\]", $s, $regs)){
680 $c = $cycle + (int)$regs[1];
681 $s = ereg_replace("\\[[0-9-][0-9]\\]", sprintf("[%02d]", $c), $s);
682 }
683 if(strlen($s) > 0)
684 echo "$s\n";
685 }
686}
687
688function printBit($isAfterSet, $bitNum)
689{
690 ob_start();
691 if($isAfterSet){
692?>
693 ifioclr USBIN, USBMINUS ;[00] <--- sample
694 rjmp bit#IsClr ;[01]
695 andi shift, ~(7 << #) ;[02]
696 breq unstuff#s ;[03]
697 in phase, USBIN ;[04] <- phase
698 rjmp bit@AfterSet ;[05]
699unstuff#s:
700 in phase, USBIN ;[05] <- phase (one cycle too late)
701 andi fix, ~(1 << #) ;[06]
702 nop2 ;[-1]
703 nop2 ;[01]
704bit#IsClr:
705 ifrset phase, USBMINUS ;[03] check phase only if D- changed
706 lpm ;[04]
707 in phase, USBIN ;[05] <- phase (one cycle too late)
708 ori shift, 1 << # ;[06]
709<?php
710 }else{
711?>
712 ifioset USBIN, USBMINUS ;[00] <--- sample
713 rjmp bit#IsSet ;[01]
714 andi shift, ~(7 << #) ;[02]
715 breq unstuff#c ;[03]
716 in phase, USBIN ;[04] <- phase
717 rjmp bit@AfterClr ;[05]
718unstuff#c:
719 in phase, USBIN ;[05] <- phase (one cycle too late)
720 andi fix, ~(1 << #) ;[06]
721 nop2 ;[-1]
722 nop2 ;[01]
723bit#IsSet:
724 ifrclr phase, USBMINUS ;[03] check phase only if D- changed
725 lpm ;[04]
726 in phase, USBIN ;[05] <- phase (one cycle too late)
727 ori shift, 1 << # ;[06]
728<?php
729 }
730 printCmdBuffer($bitNum);
731}
732
733$bitStartCycles = array(1, 9, 17, 26, 34, 42, 51, 59);
734for($i = 0; $i < 16; $i++){
735 $bit = $i % 8;
736 $emitClrCode = ($i + (int)($i / 8)) % 2;
737 $cycle = $bitStartCycles[$bit];
738 if($emitClrCode){
739 printf("bit%dAfterClr:\n", $bit);
740 }else{
741 printf("bit%dAfterSet:\n", $bit);
742 }
743 ob_start();
744 echo " ***** ;[-1]\n";
745 printCmdBuffer($bit);
746 printBit(!$emitClrCode, $bit);
747 if($i == 7)
748 echo "\n";
749}
750
751?>
752*****************************************************************************/
This page took 0.10191 seconds and 4 git commands to generate.