⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 637mouse.asm

📁 这是使用CYPRESS的7C637xx芯片完成USB鼠标的例子。
💻 ASM
📖 第 1 页 / 共 5 页
字号:
    ; Delay about 500 ms
    ;
    mov    X, 10

BATouterWait:
    mov    A, 00h                       ; reset 1 ms counter
    mov    [dualInterface1ms], A        ; 
    and    A, 50                        ; set up for 50ms

BATinnerWait:
    iowr   WATCHDOG_REG                 ; clear watchdog reset
    cmp    A, [dualInterface1ms]
    jnz    BATinnerWait
    dec    X
    jnz    BATouterWait
    mov    A, 0AAh                      ; send AA to host
    mov    [ps2XmitBuffer0], A          ;
    mov    A, 00h                       ; send 00h to host
    mov    [ps2XmitBuffer1], A          ;
    mov    A, 02h                       ; buffer has 2 bytes
    mov    [ps2XmitBufferLen], A        ;
    mov    [ps2XmitLen], A              ; to send 2 bytes
    ret

;========================================================================
; FUNCTION: ps2GetHostByte
;
;    Gets a byte from host in (A), if any
;    On exit:
;        (cf) = 1 if receive error or host does not send data
;        (cf) = 0 if receive data
;
;========================================================================
ps2GetHostByte:
    call   ps2HostRequestToSend
    jc     ghbExit                      ; go if host does not request to 
                                        ; send data
    call   disable1msInterrupt          ; to avoid clock jitter
                                        ; during ps2 clock-in
    call   ps2Receive                   ; get byte in (A) 
                                        ; (cf) = 0 if ok
                                        ; (cf) = 1 if error in receiving data
    push   A                            ; save byte for later use
    call   enable1msInterrupt           ;
    pop    A                            ; restore received byte

ghbExit:
    ret

;========================================================================
; FUNCTION: ps2HostRequestToSend
;     (cf) = 1 if host does not request to send data; Else (cf) = 0.
;
;========================================================================
ps2HostRequestToSend:
    iord   PORT2
    and    A, (SCLK + SDATA)
    cmp    A, SCLK 
    jz     hrtsExit                     ; go if host requests to send data
                                        ; (clock high, data low)
    SETC                                ; indicate no host RTS
    ret

hrtsExit:
    CLEARC
    ret

;========================================================================
; FUNCTION: ps2HostInhibit
;     (cf) = 1 if host inhibits, else (CF) = 0
;
;========================================================================
ps2HostInhibit:
    iord   PORT2
    and    A, (SCLK)
    cmp    A, 0h
    jz     hInhibit                     ; go if host inhibits data
                                        ; (clock low)
    CLEARC                              ; indicate no host inhibit
    ret

hInhibit:
    SETC
    ret

;========================================================================
; FUNCTION: disable1msInterrupt
;
;========================================================================
disable1msInterrupt:
    iord   GLOBAL_INTERRUPT_REG    
    and    A, ~1MS_INT        
    iowr   GLOBAL_INTERRUPT_REG    
    ret

;========================================================================
; FUNCTION: enable1msInterrupt
;
;========================================================================
enable1msInterrupt:
    rlc                                 ; save carry flag
    push   A                            ;
    iord   GLOBAL_INTERRUPT_REG    
    or     A, 1MS_INT        
    iowr   GLOBAL_INTERRUPT_REG    
    pop    A                            ; restore (CF)
    rrc                                 ;
    ret

;========================================================================
; FUNCTION: ps2SendNextByte          
;    Sends a byte from transmit buffer
;
;========================================================================
ps2SendNextByte:
    call   ps2HostRequestToSend
    jnc    snbExit                      ; go if host request to send
    call   ps2HostInhibit
    jc     snbExit                      ; go if host inhibits transmission
    mov    A, [ps2XmitBufferLen]        ; compute offset into next byte
    sub    A, [ps2XmitLen]              ; of xmit buffer
    mov    X, A                         ;
    mov    A, [X + ps2XmitBuffer]       ; get byte to send
    push   A                            ; save it for later use
    call   disable1msInterrupt          ; to prevent clock jitter
    pop    A                            ; get it back 
    call   ps2Send                      ; send it to host
    jc     snbNext                      ; go if sending error
    dec    [ps2XmitLen]                 ; point to next byte in buffer

snbNext:
    call    enable1msInterrupt    

snbExit:
    ret

;========================================================================
; FUNCTION: ps2SendResponseByte
;
;     Attempts to send a response byte (ACK, ERROR, RESEND) to the host. 
;
; On entry: (A) = response byte to be sent
;
;========================================================================
ps2SendResponseByte:
    push   A                            ; save sending byte for later use

srbLoop:
    call   ps2HostRequestToSend
    jnc    srbExit                      ; quit if host requests to send data
    call   ps2HostInhibit
    jc     srbNext                      ; go if host inhibits
    call   disable1msInterrupt
    pop    A                            ; get back sending byte    
    call   ps2Send                      ; and send it
    call   enable1msInterrupt
    ret

srbNext:
    iowr   WATCHDOG_REG                 ; clear watchdog timer
    jmp    srbLoop                      ; continue

srbExit:
    pop    A
    ret

;========================================================================
; FUNCTION: checkWheel
;
;    Checks whether proper sequence of commands have been issued
; by host to enable the wheel of the mouse. The sequence is 3 consecutive
; setting rate commands of 200, 100 and 80 reports/sec.
;
;    On Entry: (A) = rate (reports/sec)
;    On Exit: [ps2Wheel] = 1 if z-wheel enabled, else [ps2Wheel] = 0
;
;========================================================================

    XPAGEOFF
rateArray:               db    200, 100, 80
RATE_ARRAY_SIZE:        equ    03h
    XPAGEON


checkWheel:
    mov    [temp], A                    ; save rate for later use
    mov    A, 00h                       ; get 1st element in array
    index  rateArray                    ; 
    cmp    A, [temp]
    jnz    cw1                          ; go if rates mismatch
    
    mov    A, 00h
    mov    [sequence], A                ; start sequence from beginning

cw1:
    mov    A, [sequence]                ; get element in rateArray
    index  rateArray                    ;
    cmp    A, [temp]
    jnz    cwExit                       ; go if rates do not match
    inc    [sequence]                   ; next element
    mov    A, [sequence]        
    cmp    A, RATE_ARRAY_SIZE
    jc     cwExit2
    mov    A, 01h                       ; enable Z-WHEEL
    mov    [ps2Wheel], A                ; 

cwExit:
    mov    A, 00h
    mov    [sequence], A                ; reset index

cwExit2:
    ret

    
;********************************************************************
;
;             PS2 I/O Routines
;
;   Contains the code that sends/receives data via the 
;   D- and D+ output pins, in ps2 format
;
;********************************************************************
;
;
; Defines for the 4 combinations of clock and data
; (SCLK = D+, SDATA = D-)

CLKH_DATAH:              equ     07h    ; force D+ HiZ, D- HiZ
CLKL_DATAH:              equ     06h    ; force D+ Low, D- HiZ
CLKH_DATAL:              equ     05h    ; force D+ HiZ, D- Low
CLKL_DATAL:              equ     04h    ; force D+ Low, D- Low


;========================================================================
; FUNCTION: ps2Send
;
; Sends a byte in (A) 
;
;
; Returns: 
;   C= 0 if transmission was successful
;   C= 1 if not
;
;========================================================================
ps2Send:
    push    A                           ; save our data byte                    
    push    X                           ; save X register
    mov     X, A                        ; save data byte momentarily in X               
    DELAY   50                          ; delay a bit time between bytes
 
.l1:                                    ; some PC's.
    call    send_0                      ; clock out start bit
    jnc    .sendStartBitSuccess

    ; if we are being inhibited and the host is not requesting to send,
    ; then continue to try to send the start bit

.sendInhibitWait:
    iowr   WATCHDOG_REG                 ; reset the watchdog
    iord   PORT2
    and    A, (SCLK + SDATA)            ; if CLK=low (inhibit) and DATA=high
    cmp    A, SDATA                     ; then wait until host releases clock
    jz     .sendInhibitWait
    cmp    A, SCLK                      ; if host is requesting to send, then 
    jz     .error                       ; quit with error

    jmp    .l1                          ; else try to send start bit again

.sendStartBitSuccess:
    mov    A, 1
    mov    [ps2Temp0], A                ; keep track of parity
    mov    A, X                         ; get back our data byte
    mov    X, 8                         ; count 8 bits

.l2:
    asr    A                            ; shift bit to send into carry
    jc     .one                         ; if carry is zero
    call   send_0                       ; send a zero
    jc     .error                       ; problem, quit now
    jmp    .next                        ; 

.one:                                   ; else
    call   send_1                       ; send a 1
    jc     .error                       ; problem, quit now
    inc    [ps2Temp0]                   ; keep track of parity

.next:                                  ;
    dec    X                            ; decrement counter
    jz     .parity                      ; if at zero do parity
    jnc    .l2                          ; if -1, exit

.stopbit:
    call   send_1                       ; clock out stop bit  
    CLEARC
    jmp    .exit

.parity:
    mov    A, [ps2Temp0]                ; now send parity too
    jmp    .l2

.error:
    mov    A, CLKH_DATAH                ; make sure PS2 bus is left idle
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG
    SETC
    jmp    .exit2

.exit:
    mov    A, CLKH_DATAH                ; make sure PS2 bus is left idle
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG

.exit2:
    pop    X
    pop    A
    ret                         

;========================================================================
; FUNCTION: send_0,send_1
;
; Sends bit out the ps2 port
;
;
; Returns: 
;   C= 0 if transmission was successful
;   C= 1 if not
;
;========================================================================
;
; The following state table defines the next state for the clock-data pair
; to clock out a given bit.
;

XPAGEOFF
drive_table:
       db       0, 0, 0, CLKH_DATAL, 0, CLKL_DATAL, CLKH_DATAH, CLKL_DATAH
XPAGEON

send_1:
    push   A
    mov    A, CLKH_DATAH                ; start with clock high, data high
    jmp    clock

send_0:
    push   A
    mov    A,CLKH_DATAL                 ; start with clock high, data low

clock:
    push   A
    iord   PORT2                        ; read clock
    and    A, SCLK            
    pop    A    
    jnz    .l2
    SETC
    pop    A                            ; should be high
    ret

.l2:
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG  ; set up register
    and    A, 07h
    DELAY  5 
    index  drive_table                  ; wait 5 us
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG       ; write it out
    and    A, 07h

    DELAY  35                           ; delay as per spec

    index  drive_table                  ; deassert clock

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -