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

📄 ps2d.asm

📁 Cypress cy7c63318 鼠标开发板的源代码
💻 ASM
📖 第 1 页 / 共 3 页
字号:

ENDIF

.delay_done:
    RET
;-----------------------------------------------------------------------------
;  FUNCTION NAME: PS2D_Send
;  DESCRIPTION:   Send a byte of data
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:   A: Contains the data to send
;
;  RETURNS:     A: Contains completion code
;
;  SIDE EFFECTS: REGISTERS ARE VOLATILE: THE A AND X REGISTERS MAY BE MODIFIED!
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
 PS2D_Send:
_PS2D_Send:
.data:    equ -1                             ; Local stack variables
.cnt:     equ -2
.parity:  equ -3
    PUSH    X                               ; Build the local variable 
    ADD     SP, 3                           ; 
    MOV     X, SP                           ; 
    MOV     [X + .data], A                  ; Save off the data byte
    MOV     [X + .parity], 1                ; Start the parity at 1
    MOV     [X + .cnt], 8                   ; Send 8 data bits

; Test for inhibit
.inhibit_wait:    
    M8C_ClearWDT

    TST    REG[PS2D_DR], PS2D_SCLK          ; Inhibit?
    JZ     .inhibit_wait                    ; Continue to wait if we are inhibited 

    DELAY   50, 0                           ; Min delay between check for inhibit

    TST    REG[PS2D_DR], PS2D_SCLK          ; Inhibit? 
    JZ     .inhibit_wait                    ; Continue to wait if we are inhibited 

; Test for RTS
    TST    REG[PS2D_DR], PS2D_SDATA         ; RTS? 
    JZ     .rts                             ; Jump if RTS

; Flow here to send start bit
    CALL   PS2D_Send_0                      ; Start bits are zero
    JC     .inhib                           ; Host has inhibited

    DELAY  2, 12                            ; Wait 2 uSec

; Flow or jump here to sent the data bits
.snb:
    ASR    [X + .data]                       ; rotate the next bit to the carry
    JC     .s1                               ; and send a 1 or 0 based
.s0:
    CALL   PS2D_Send_0                       ; Send 0
    JMP    .cont
.s1:
    INC    [X + .parity]                     ; Count the number of 1 bits for the parity
    CALL   PS2D_Send_1                       ; Send 1
.cont:
    JC     .inhib                            ; Did the host inhibit us during the last bit?     
    DEC    [X + .cnt]                        ; If not, send the next bit
    JZ     .s_parity                         ; When it hits zero, do the parity
    JNC    .snb                              ; It will carry after the parity bit is sent

; Flow here to send the stop bit
    CALL   PS2D_Send_1                       ; Stop bits are 1
    JMP    .success
    
; Flow here after all 8 data bits have been clocked out
.s_parity:
    MOV    A, [X + .parity]                  ; clock out the lsb of the parity 
    MOV    [X + .data],a                     ; Save the data
    JMP    .snb

; Jump here on a successful stop bit
.success:
    MOV    A, 0                              ; Flow here after a successful stop bit
    JMP    .exit
; Jump here if we failed because we were inhibited
.inhib:                                     ; Jump here for any failed bit
    CALL   PS2D_Release                      ; Releaes the bus
    MOV    A, 0x88         
    JMP    .exit
; Jump here if we found a RTS
.rts:                                        ; Jump here for a RTS
    MOV    A, 0x90                           ;
; Jump or flow here to exit    
.exit:
    ADD    SP, -3                            ; Clean up the stack
    POP    X    
    RET   
;-----------------------------------------------------------------------------
;  FUNCTION NAME: PS2D_Send_1, PS2D_Send_0
;  DESCRIPTION:   Local function.  Assembly interface only.
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;
;  RETURNS: 
;
;  SIDE EFFECTS: REGISTERS ARE VOLATILE: THE A AND X REGISTERS MAY BE MODIFIED!
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
PS2D_Send_1:
    OR     [Port_1_Data_SHADE], PS2D_SDATA  ; Set the data bit high
    JMP    PS2D_Clock_Out_Bit

PS2D_Send_0:
    AND    [Port_1_Data_SHADE], ~PS2D_SDATA ; Set the data bit low
    JMP    PS2D_Clock_Out_Bit               ; This jump maintains the same number
                                            ; of clock cycles for both a 1 or 0
; Jump here to clock out the bit
PS2D_Clock_Out_Bit:
    MOV    A, [Port_1_Data_SHADE]           ; Get the shadow
    MOV    REG[PS2D_DR], A                  ; Clock High and data

    DELAY    10, 12                         ; Wait 10 uSec

    ; Clock Low                             ; Clock Low and the data
    XOR    [Port_1_Data_SHADE], PS2D_SCLK   ; Clock Low
    MOV    A, [Port_1_Data_SHADE]           ; Get the shadow
    MOV    REG[PS2D_DR], A                  ; Clock Low and data
    
    DELAY    38, 12                         ; Wait 38 uSec

    ; Clock High                            ; Finally Clock High and the data
    XOR    [Port_1_Data_SHADE], PS2D_SCLK   ; Clock High
    MOV    A, [Port_1_Data_SHADE]           ; Get the shadow
    MOV    REG[PS2D_DR], A                  ; Clock High and data
    
    DELAY    22, 60                         ; Wait 22 uSec

    ; Check for inhibit
    CLEARC                                  ; Carry clear indicates success
    TST    REG[PS2D_DR], PS2D_SCLK          ; Inhibit? 
    JNZ    .clock_done                      ; Jump if not 
    SETC                                    ; Carry set indicates fail/Inhibit

.clock_done:
    ; Done
    RET

;-----------------------------------------------------------------------------
;  FUNCTION NAME: PS2D_Receive
;  DESCRIPTION:
;     Receive one byte from the host.  Assumes PS2_HostRequestToSend has
;     been called to check for a host RTS
;
;-----------------------------------------------------------------------------
;
;  ARGUMENTS:
;
;  RETURNS:
;     A = unsigned char from PS2 Host
;     X = 00h Valid data
;     X msb set indicates an error
;     X = 10000000 no data
;     X = 1xxxxxx1 parity error
;     X = 1xxxxx1x bad stop bit
;     X = 1xxxx1xx invalid start bit
;     X = 1xxx1xxx inhibited
;
;  SIDE EFFECTS: REGISTERS ARE VOLATILE: THE A AND X REGISTERS MAY BE MODIFIED!
;
;  THEORY of OPERATION or PROCEDURE:
;
;-----------------------------------------------------------------------------
 PS2D_Receive:
.data:     equ -1                            ; Local stack variables
.cnt:      equ -2                            ;
.parity:   equ -3                            ; 
.r_status: equ -4                            ; 
    ADD    SP, 4                             ;
    MOV    X, SP                             ;
    
; Look for the start bit--180 usec total
    MOV    [X + .r_status], 84h              ; Assume no start bit
    MOV    [X + .cnt], 18                    ; Do 18 samples ( 18 is legacy)

    DELAY  30, 0

.check_start:
    DELAY  10, 48

    TST    REG[PS2D_DR], PS2D_SCLK           ; Ensure clock is set 
    JZ     .exit                             ; Jump if clock not set, invalid start
    
    TST    REG[PS2D_DR], PS2D_SDATA          ; Ensure data is set cleared
    JNZ    .exit                             ; Jump if data not clear, invalid start

    DEC    [X + .cnt]                        ; Check again?
    JNZ    .check_start                      ; 

; Flow here for a valid start bit from the host
    MOV    A, 0                              ; A will get the data bit rotated into the msb
    MOV    [X + .parity], A                  ; Start the parity at 0
    MOV    [X + .r_status], A                ; Assume good data
    MOV    [X + .cnt], 8                     ; Receive 8 data bits

.gnb:
    CALL   PS2D_GetBit                       ; Clock in the bit
    JC     .inhib                            ; Jump if inhibited
    CMP    A, 0x80                           ; Accumulate the parity, if needed
    JC     .skip_parity                      ; 
    INC    [X + .parity]                     ; Accumulate the parity

.skip_parity:
    DEC    [X + .cnt]                        ; Finished one bit
    JC     .stop                             ; Jump if we just did the parity bit
    JNZ    .gnb                              ; Get the next bit
    
    MOV    [X + .data], A                    ; Save the data
    JMP    .gnb                              ; Go get the parity

.stop:
    CALL   PS2D_GetBit                       ; Get the stop bit
    JC     .inhib                            ; Jump if inhibited
    RLC    A                                 ; Stop bit should be 1
    JC     .ack                              ; Jump if we got the correct stop bit
    
    MOV    [X + .r_status], 0x82             ; Flag the bad stop bit
    JNC    .stop                             ; Keep looking for stop bit
    
.ack:
    CALL   PS2D_Send_0                        ; Send a zero ack
    JMP    .exit                             ; We've already logged any errors in .r_status
    
.inhib:
    MOV    [X + .r_status], 0x84             ; Return inhibit

.exit:
    CALL   PS2D_Release                      ; Releaes the bus
    TST    [X + .parity], 01h                ; Check the parity
    JNZ    .parity_ok
    OR     [x+.r_status],81h                  ; Return bad status

.parity_ok:
    MOV    A, [X + .data]                    ; return the data
    MOV    X, [X + .r_status]                ; return the validity flag
    ADD    SP, -4                            ; Clean up the stack
    RET
;-----------------------------------------------------------------------------
;  FUNCTION NAME: PS2D_GetBit
;
;  DESCRIPTION:
;     Clock in a single bit from the PS/2 Host
;
;  ARGUMENTS:
;     A--Normally the previous bits clocked in
;
;  RETURNS:
;     A >> 1 and msb of A is set to the clocked bit
;     Carry set on error (Host Inhibit)
;
;  SIDE EFFECTS:
;     REGISTERS ARE VOLATILE: THE A AND X REGISTERS MAY BE MODIFIED!
;
;  THEORY of OPERATION OR PROCEDURE:
;     TOP goes here
;
;-----------------------------------------------------------------------------
PS2D_GetBit:
    PUSH   A                                 ; Save the previously clocked data

    DELAY  10, 12                           ; Wait 10 uSec

    ; Clock Low
    AND    [Port_1_Data_SHADE], ~PS2D_SCLK  ; Clock Low
    MOV    A, [Port_1_Data_SHADE]           ; Get the shadow
    MOV    REG[PS2D_DR], A                  ; Update
    
    DELAY  38, 12                           ; Wait 38 uSec
    
    ; Clock high
    OR     [Port_1_Data_SHADE], PS2D_SCLK   ; Clock High
    MOV    A, [Port_1_Data_SHADE]           ; Get the shadow
    MOV    REG[PS2D_DR], A                  ; Update

    DELAY  22, 72                           ; Wait 22 uSec
    
    ; Sample the data
    MOV    A, REG[PS2D_DR]                  ; Sample the data    

    ; Extract the data
    CLEARC                                   ; Assume the clocked bit is 0
    AND    A, PS2D_SDATA                    ; Isolate the data bit
    JZ     .exit
    SETC                                    ; The clocked bit was 1

.exit:
	; The following lines does not change C
    POP    A                                ; Restore the previously saved data
    TST    REG[PS2D_DR], PS2D_SCLK          ; Get the port 
    JZ     .error                           ; Error if inhibit

    RRC    A                                ; MSB updated with the clocked bit
    CLEARC        
    RET

.error:      
    SETC                                    ; Flag error/inhibit
    RET
; End of File PS2D.asm

⌨️ 快捷键说明

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