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

📄 637mouse.asm

📁 这是使用CYPRESS的7C637xx芯片完成USB鼠标的例子。
💻 ASM
📖 第 1 页 / 共 5 页
字号:
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG
    and    A, 07h

;=====================================================================
; Substitute macro DELAY with a readProcessOptics procedure that
; consumes about the same amount of time. The reason is that we do not
; want to miss any optics count (To send or recive a bit in PS2 takes
; about 1 ms)
;======================================================================
    call   readProcessOptics
;   DELAY  30                           ; wait as per spec

    CLEARC
    pop    A
    ret

;========================================================================
; FUNCTION: getBit
;
; Receives  a bit
;
;
; Returns: 
;   MSB of (A) = state of bit clocked in
;   CF = 1 if error; CF = 0 if OK
;
;========================================================================
getBit:
    push   A                       
    iord   PORT2                        ; IF INHIBIT, get out now
    and    A,SCLK
    jz     .error
    mov    A, CLKL_DATAH                ; start with clock low, data high
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG          
    and    A, 07h

    DELAY  35                           ; wait 35 usec

    mov    A,CLKH_DATAH                 ; raise clock line
    or     A, (PS2_PULLUP | USB_PS2_MODE);
    iowr   USB_STATUS_CONTROL_REG       ;
    and    A, 07h
    DELAY  5                            ; wait 5 usec 
    iord   PORT2                        ; read the data line

;=====================================================================
; Substitute macro DELAY with a readProcessOptics procedure that
; consumes about the same amount of time. The reason is that we do not
; want to miss any optics count (To send or recive a bit in PS2 takes
; about 1 ms)
;======================================================================
    push   A
    call   readProcessOptics
    pop    A

;   DELAY  30                           ; wait 30 usec
    and    A, SDATA                     ; mask off all but data bit
                                        ; (and instruction clears CF)
    jz     .low                         ; if data bit high,
    SETC                                ; set the carry

.low:
    pop    A                            ; pop acc and rotate carry into msb
    rrc    A
    CLEARC                              ; clear carry indicating success
    ret                                 ; return

.error:
    pop    A
    SETC
    ret

;========================================================================
; FUNCTION: ps2Receive
;
; Receives a byte 
;
;
; Returns: 
;   C= 0 if reception was successful
;   C= 1 if not
;
;========================================================================
ps2Receive:
    push   X                            ; save X, we'll wipe it out
    mov    X, 18                        ; do the following 18 times:

.wait:                                          
    DELAY  7                            ; kill time for 7 us
    iord   PORT2
    and    A, SDATA                     ; make sure data bit low
    jnz    .exitearly                   ; out now if not
    dec    X                            ; wait again
    jnz    .wait                        ;
                                        ; above loop consumes approx 180 us.
.start:
    DELAY  5
    mov    X, 8                         ; count 9  bits (8 data, 1 parity)
    mov    A, 0                         ; clear parity count
    mov    [ps2Temp0], A

.l1:
    call   getBit
    jc     .inhibit                     ; if not inhibiting
    cmp    A, 80h                       ; see if msbit = 1
    jc     .next                        ; yup,
    inc    [ps2Temp0]                   ; increment parity count

.next:
    dec    X                            ; decrement counter
    jc     .done                        ; if at -1, done    
    jnz    .l1    
    push   A                            ; else save partial result
                                        ; (save all 8 bits)
    jmp    .l1                          ; go and get parity bit

.inhibit:                               ; we were inhibited in
    dec    X                            ; the middle of getting stuff,
    jc     .done                        ; adjust stack appropriately
    push   A

.done:
    ; arrive here with data byte on the stack and the received parity bit in the msb
    ; of the accumulator. the calculated parity bit is in the lsb of ps2Temp0.
    ; if we arrived here due to host inhibit, both parity and data byte are
    ; garbage but that's ok -- we'll abort out of this routine anyway.

    mov    A, [ps2Temp0]                ; get computed parity
    and    A, 1
    mov    X, A
                                        ; X should be 1 if ok

    call   getBit                       ; get stop bit
    jc     .error                       ; if no problem getting it
    rlc    A                           
    jc     .ack                         ; if it's not a 1
    mov    X, 0                         ; X= 0 indicates an error

.badstop:                               
    call   getBit                       ; keep looking for it
    jc     .error
    rlc    a
    jnc    .badstop

.ack:
                                        ; arrive here with x = 1 if no errors
    call   send_0                       ; send a 0 to ack the transaction
    mov    A, X
    cmp    A, 0
    jz     .error

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

.error:
    mov    A,CLKH_DATAH                 ; make sure PS2 bus is left idle
    or     A, (PS2_PULLUP | USB_PS2_MODE)
    iowr   USB_STATUS_CONTROL_REG
    and    A, 07h
    SETC                                ;set carry indicating a problem

.return:
    pop    A                            ; pop result into ACC  
    pop    X                            ; restore X
    ret

.exitearly:
    SETC
    pop    X
    ret


;********************************************************************
;
;         Main Entry for USB Interface
;
;********************************************************************

usbMain:
    ;
    ; set wakeup timer interval and disable XTALOUT 
    ;
    mov    A, WAKEUP_ADJUST2 | WAKEUP_ADJUST0 | INTERNAL_CLK | PRECISION_USB_CLOCKING 
    iowr    CLOCK_CONFIG

    ;
    ; initialize USB variables
    ;
    mov    A, 00h        
    mov    [ep0InMachine], A
    mov    [configuration], A
    mov    [ep1Stall], A
    mov    [idle], A
    mov    [suspendCount], A
    mov    [intTemp], A
    mov    [idleTimer], A
    mov    [idlePrescaler], A
    mov    [ep0Transtype], A
    mov    [ep1DmaBuff0], A
    mov    [ep1DmaBuff1], A
    mov    [ep1DmaBuff2], A
    mov    [ep1DmaBuff3], A

    mov    A, HID_REPORT
    mov    [protocol], A

    mov    A, SET
    mov    [remoteWakeup], A

    ;
    ; enable USB address for endpoint 0
    ;
    mov    A, ADDRESS_ENABLE
    iowr   USB_ADDRESS

    ;
    ; enable global and EP0 interrupts
    ;
    mov          A, (1MS_INT | USB_RESET_INT)
    iowr   GLOBAL_INTERRUPT_REG

    mov    A, EP0_INT            
    iowr   ENDPOINT_INT

    ei

    ;
    ; enable USB pullup resistor
    ;
    mov    A, VREG_ENABLE  
    iowr   USB_STATUS_CONTROL_REG

;********************************************************************
;
;         Main Task Loop for USB Interface
;
;********************************************************************
usbTaskLoop:
    ;
    ; usb main loop - watchdog clear
    ;

    iowr   WATCHDOG_REG                 ; clear watchdog
    call   processButtons        
    mov    A, [eventMachine]
    cmp    A, EVENT_PENDING             ; need to send data back to host?
    jnz    usbOptic                     ; no - go do optics
    mov    A, [buttonValue]             ; assign button value to EP1
    mov    [ep1DmaBuff0], A             ; 

usbOptic:
    call   readProcessOptics
    mov    A, [eventMachine]
    cmp    A, EVENT_PENDING             ; need to send data back to host?
    jnz    usbOptic2                    ; no - continue
    mov    A, [xCount]                  ; yes, save data to EP1 FIFO
    mov    [ep1DmaBuff1], A             ;

    mov    A, [yCount]                  ; need to invert y-coordinate for
    cpl    A                            ; proper direction
    inc    A                            ;
    mov    [ep1DmaBuff2], A             ;

    mov    A, [protocol]
    cmp    A, 01h                       ; is it 4-byte packet?
    jnz    usbOptic2                    ; go if 3-byte packet
    mov    A, [zCount]                  ;
    mov    [ep1DmaBuff3], A             ;


; this task sends data out from endpoint 1 if the endpoint is configured
; and not set to stall

usbOptic2:
    mov    A, [eventMachine]
    jacc   eventMachineJumptable
        
eventPending:
    ;
    ; if not configured then skip data transfer
    ;
    mov    A, [configuration]
    cmp    A, 01h
    jnz    eventTaskDone                ; go if not configured

    ;
    ; if stalled then skip data transfer
    ;
    mov    A, [ep1Stall]
    cmp    A, FFh
    jz     eventTaskDone                ; go if EP1 stalled

    mov    A, [protocol]
    cmp    A, 01h                       ; is z-wheel enabled in either USB 
                                        ; (REPORT_PROTOCOL mode) or PS2 mode?
    mov    A, MOUSE_PACKET_4            ; set up endpoint 1 to send 4 bytes
    jz     formPacket                   ; go if wheel button supported
    dec    A                            ; set up endpoint 1 to send 3 bytes

formPacket:            
    or     A, [ep1DataToggle]           ;
    iowr   EP1_COUNT                    ;
    mov    A, ACK_IN                    ; set to ack on endpoint 1
    iowr   EP1_MODE                     ;

eventTaskDone:
    mov    A, NO_EVENT_PENDING          ; clear pending events
    mov    [eventMachine], A 

noEventTask:
    jmp usbTaskLoop


;========================================================================
; FUNCTION: Interrupt handler: dualUsbBusReset_ps2Error
;    Purpose: 
;      If USB 
;        process USB reset
;      Else
;        goes to error handler
;
;========================================================================
dualUsbBusReset_ps2Error:
    mov    A, [dualInterfaceMouse]      ; get interface type in (A)
    cmp    A, USB_MOUSE
    jz     usbBusReset                  ; go if USB 
    jmp    ps2Error                     ; should not get here if PS2

usbBusReset:
    mov    A, STALL_IN_OUT              ; set to STALL INs&OUTs
    iowr   EP0_MODE                     ;
    mov    A, ADDRESS_ENABLE            ; enable USB address 0
    iowr   USB_ADDRESS                  ;
    mov    A, DISABLE                   ; disable endpoint1
    iowr   EP1_MODE                     ;
    mov    A, 00h                       ; reset program stack pointer
    mov    psp,a                        ;
    jmp    usbMain

;========================================================================
; FUNCTION: dual1msTimer
;    Purpose: 
;      Poll the buttons every ms;
;      If USB 
;         watches for USB suspend and handles the HID idle timer
;
;========================================================================
dual1msTimer:
    push   A
    inc    [dualInterface1ms]           ; otherwise, increment 1ms counter

    ;
    ; poll buttons for button on/off state
    ;
    ; Notes: 
    ;    Any time we read a button port we will set
    ;     buttonMachine = BUTTON_DATA_PENDING
    ;
    mov     A, [buttonMachine]
    cmp     A, BUTTON_DATA_PENDING      ; has button port been read?
    jz      1msSuspendTimer             ; go if yes

    call    getButtons                  ; get but

⌨️ 快捷键说明

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