📄 usbdrvasm165.s
字号:
andi x3, ~0x02 ;[027] in r0, USBIN ;[028] <-- phase ori shift, 0x02 ;[029] mov x2, x1 ;[030] rjmp didUnstuff1 ;[031]; [---] ;[032] ;[022]unstuff2: ;[035] eor r0, x2 ;[036] or phase, r0 ;[037] andi x3, ~0x04 ;[038] in r0, USBIN ;[039] <-- phase ori shift, 0x04 ;[040] mov x1, x2 ;[041] rjmp didUnstuff2 ;[042]; [---] ;[043] ;[033]unstuff3: ;[043] in x2, USBIN ;[044] <-- bit 3 again eor r0, x2 ;[045] or phase, r0 ;[046] andi x3, ~0x08 ;[047] ori shift, 0x08 ;[048] nop ;[049] in r0, USBIN ;[050] <-- phase rjmp didUnstuff3 ;[051]; [---] ;[052] ;[042]unstuff4: ;[053] andi x3, ~0x10 ;[054] in x1, USBIN ;[055] <-- bit 4 again ori shift, 0x10 ;[056] rjmp didUnstuff4 ;[057]; [---] ;[058] ;[048]rxLoop: ;[085] eor x3, shift ;[086] reconstruct: x3 is 0 at bit locations we changed, 1 at others in x1, USBIN ;[000] <-- bit 0 st y+, x3 ;[001]; [---] ;[002] eor r0, x1 ;[003] or phase, r0 ;[004] eor x2, x1 ;[005] in r0, USBIN ;[006] <-- phase ser x3 ;[007] bst x2, USBMINUS ;[008] bld shift, 0 ;[009] andi shift, 0xf9 ;[010]rxbit1: ;[ ] in x2, USBIN ;[011] <-- bit 1 breq unstuff0 ;[012] *** unstuff escape andi x2, USBMASK ;[013] SE0 check for bit 1didUnstuff0: ;[ ] Z only set if we detected SE0 in bitstuff breq se0 ;[014] eor r0, x2 ;[015] or phase, r0 ;[016] in r0, USBIN ;[017] <-- phase eor x1, x2 ;[018] bst x1, USBMINUS ;[019] bld shift, 1 ;[020] andi shift, 0xf3 ;[021]didUnstuff1: ;[ ] in x1, USBIN ;[022] <-- bit 2 breq unstuff1 ;[023] *** unstuff escape eor r0, x1 ;[024] or phase, r0 ;[025] subi cnt, 1 ;[026] overflow check brcs overflow ;[027] in r0, USBIN ;[028] <-- phase eor x2, x1 ;[029] bst x2, USBMINUS ;[030] bld shift, 2 ;[031] andi shift, 0xe7 ;[032]didUnstuff2: ;[ ] in x2, USBIN ;[033] <-- bit 3 breq unstuff2 ;[034] *** unstuff escape eor r0, x2 ;[035] or phase, r0 ;[036] eor x1, x2 ;[037] bst x1, USBMINUS ;[038] in r0, USBIN ;[039] <-- phase bld shift, 3 ;[040] andi shift, 0xcf ;[041]didUnstuff3: ;[ ] breq unstuff3 ;[042] *** unstuff escape nop ;[043] in x1, USBIN ;[044] <-- bit 4 eor x2, x1 ;[045] bst x2, USBMINUS ;[046] bld shift, 4 ;[047]didUnstuff4: ;[ ] eor r0, x1 ;[048] or phase, r0 ;[049] in r0, USBIN ;[050] <-- phase andi shift, 0x9f ;[051] breq unstuff4 ;[052] *** unstuff escape rjmp continueWithBit5;[053]; [---] ;[054].macro POP_STANDARD ; 16 cycles pop cnt pop x4 pop x3 pop x2 pop x1 pop shift pop YH pop YL.endm.macro POP_RETI ; 5 cycles pop r0 out SREG, r0 pop r0.endm#include "asmcommon.S"; USB spec says:; idle = J; J = (D+ = 0), (D- = 1); K = (D+ = 1), (D- = 0); Spec allows 7.5 bit times from EOP to SOP for repliesbitstuff7: eor x1, x4 ;[4] ldi x2, 0 ;[5] nop2 ;[6] C is zero (brcc) rjmp didStuff7 ;[8]bitstuffN: eor x1, x4 ;[5] ldi x2, 0 ;[6] lpm ;[7] 3 cycle NOP, modifies r0 out USBOUT, x1 ;[10] <-- out rjmp didStuffN ;[0]#define bitStatus x3sendNakAndReti: ldi cnt, USBPID_NAK ;[-19] rjmp sendCntAndReti ;[-18]sendAckAndReti: ldi cnt, USBPID_ACK ;[-17]sendCntAndReti: mov r0, cnt ;[-16] ldi YL, 0 ;[-15] R0 address is 0 ldi YH, 0 ;[-14] ldi cnt, 2 ;[-13]; rjmp usbSendAndReti fallthrough;usbSend:;pointer to data in 'Y';number of bytes in 'cnt' -- including sync byte [range 2 ... 12];uses: x1...x4, shift, cnt, Y;Numbers in brackets are time since first bit of sync pattern is sentusbSendAndReti: ; 12 cycles until SOP in x2, USBDDR ;[-12] ori x2, USBMASK ;[-11] sbi USBOUT, USBMINUS;[-10] prepare idle state; D+ and D- must have been 0 (no pullups) in x1, USBOUT ;[-8] port mirror for tx loop out USBDDR, x2 ;[-7] <- acquire bus; need not init x2 (bitstuff history) because sync starts with 0 ldi x4, USBMASK ;[-6] exor mask ldi shift, 0x80 ;[-5] sync byte is first byte sent ldi bitStatus, 0xff ;[-4] init bit loop counter, works for up to 12 bytesbyteloop:bitloop: sbrs shift, 0 ;[8] [-3] eor x1, x4 ;[9] [-2] out USBOUT, x1 ;[10] [-1] <-- out ror shift ;[0] ror x2 ;[1]didStuffN: cpi x2, 0xfc ;[2] brcc bitstuffN ;[3] nop ;[4] subi bitStatus, 37 ;[5] 256 / 7 ~=~ 37 brcc bitloop ;[6] when we leave the loop, bitStatus has almost the initial value sbrs shift, 0 ;[7] eor x1, x4 ;[8] ror shift ;[9]didStuff7: out USBOUT, x1 ;[10] <-- out ror x2 ;[0] cpi x2, 0xfc ;[1] brcc bitstuff7 ;[2] ld shift, y+ ;[3] dec cnt ;[5] brne byteloop ;[6];make SE0: cbr x1, USBMASK ;[7] prepare SE0 [spec says EOP may be 21 to 25 cycles] lds x2, usbNewDeviceAddr;[8] lsl x2 ;[10] we compare with left shifted address out USBOUT, x1 ;[11] <-- out SE0 -- from now 2 bits = 22 cycles until bus idle;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:;set address only after data packet was sent, not after handshake subi YL, 2 ;[0] sbci YH, 0 ;[1] breq skipAddrAssign ;[2] sts usbDeviceAddr, x2; if not skipped: SE0 is one cycle longerskipAddrAssign:;end of usbDeviceAddress transfer ldi x2, 1<<USB_INTR_PENDING_BIT;[4] int0 occurred during TX -- clear pending flag USB_STORE_PENDING(x2) ;[5] ori x1, USBIDLE ;[6] in x2, USBDDR ;[7] cbr x2, USBMASK ;[8] set both pins to input mov x3, x1 ;[9] cbr x3, USBMASK ;[10] configure no pullup on both pins ldi x4, 4 ;[11]se0Delay: dec x4 ;[12] [15] [18] [21] brne se0Delay ;[13] [16] [19] [22] out USBOUT, x1 ;[23] <-- out J (idle) -- end of SE0 (EOP signal) out USBDDR, x2 ;[24] <-- release bus now out USBOUT, x3 ;[25] <-- ensure no pull-up resistors are active rjmp doReturn
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -