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

📄 usb_ch9.asm

📁 This firmware translates a PS/2 mouse to a USB mouse. The translator firmware is entirely interrup
💻 ASM
📖 第 1 页 / 共 4 页
字号:
; ******************************************************************
Get_Interface_Status        ; starts in bank 2
    bsf     STATUS, RP0     ; bank 3
    movf    BD0IAL,w        ; get buffer pointer
    movwf   FSR
    clrf    INDF
    incf    FSR,f
    clrf    INDF

    movlw   0x02
    movwf   BD0IBC          ; set byte count to 2
    movlw   0xC8
    movwf   BD0IST          ; Data 1 packet, set owns bit
    return

; ******************************************************************
; Returns the Endpoint stall bit via a 2 byte in buffer
; ******************************************************************
Get_Endpoint_Status         ; starts in bank 2
    movlw   0x0f
    andwf   BufferData+wIndex,w    ; get endpoint, strip off direction bit
    xorlw   0x01            ; is it EP1?
    btfsc   STATUS,Z
    goto    get_EP1_status

    movlw   0x0f
    andwf   BufferData+wIndex,w    ; get endpoint, strip off direction bit
    xorlw   0x02            ; is it EP2?
    btfss   STATUS,Z
    goto    wrongstate

get_EP2_status
    bcf     STATUS,C
    bsf     STATUS,RP0
    btfsc   UEP2,EP_STALL
    bsf     STATUS,C
    goto    build_status_buffer

get_EP1_status
    bcf     STATUS,C
    bsf     STATUS,RP0
    btfsc   UEP1,EP_STALL
    bsf     STATUS,C
         
build_status_buffer
    movf    BD0IAL,w        ; get address of buffer
    movwf   FSR
    clrf    INDF            ; clear byte 0 in buffer
    rlf     INDF,f          ; rotate in carry bit (EP_stall bit)
    incf    FSR,f           ; bump pointer
    clrf    INDF            ; clear byte

    movlw   0x02
    movwf   BD0IBC          ; set byte count to 2
    movlw   0xC8
    movwf   BD0IST          ; Data 1 packet, set owns bit
    return


; *********************************************************************
; The low order byte of wValue now has the new device address as assigned
; from the host.  Save it in the UADDR, transition to the ADDRESSED state
; and clear the current configuration.
; This assumes the SIE has already sent the status stage of the transaction
; as implied by Figure 3-35 of the DOS (Rev A-7)
; ******************************************************************
Set_Address     ; starts in bank 2
    movlw   SET_ADDRESS
    movwf   USB_dev_req            ; currently processing a get descriptor request
    movf    BufferData+wValue,w    ; new address in low order byte of wValue
    movwf   USB_address_pending

    bsf     STATUS, RP0
    clrf    BD0IBC
    movlw   0xc8
    movwf   BD0IST          ; write the whole mess back
    return

finish_set_address          ; starts in bank 2
    clrf    USB_dev_req     ; no request pending
    clrf    USB_Curr_Config ; make sure current configuration is 0
    movf    USB_address_pending,w
    bsf     STATUS, RP0
    movwf   UADDR           ; set the device address
    btfsc   STATUS,Z        ; was address 0?
    goto    endfinishsetaddr    ; yes: don't change state

    movlw   ADDRESS_STATE   ; non-zero: transition to addressed state
    movwf   USWSTAT         ; transition to addressed state
#ifdef SHOW_ENUM_STATUS
    banksel PORTB
    bsf     PORTB,2         ; set bit 2 to indicate Addressed state
    banksel USWSTAT         ; not necessary, Send_0LenPkt resets bank bits
#endif

endfinishsetaddr
    return

; ******************************************************************
; only feature valid for device feature is Device Remote wakeup
; ******************************************************************
Clear_Device_Feature        ; starts in bank2
    movf    BufferData+wValue,w
    xorlw   0x01            ; was it a Device Remote wakeup? If not, return STALL,
    btfss   STATUS,Z        ; since we only implement this feature on this device.
    goto    wrongstate

right_state_clear_feature
    bcf     USB_status_device,1 ; set device remote wakeup
    call    Send_0Len_pkt
    return

; ******************************************************************
; Only endpoint feature is Endpoint halt.
; ******************************************************************
Clear_Endpoint_Feature  ; starts in bank 2
    movlw   0x0f
    andwf   BufferData+wIndex,w ; mask off the EP number bits
    xorlw   0x01            ; is it EP1?
    btfsc   STATUS,Z
    goto    ClearEP1

    movlw   0x0f
    andwf   BufferData+wIndex,w ; mask off the EP number bits
    xorlw   0x02            ; is it EP2?
    btfss   STATUS,Z
    goto    wrongstate

ClearEP2
    bsf     STATUS, RP0
    bcf     UEP2,EP_STALL       ; set the stall bit
    goto    clear_endpoint_end  ; skip the second stall
ClearEP1
    bsf     STATUS, RP0
    bcf     UEP1,EP_STALL   ; set the stall bit

clear_endpoint_end
    call    Send_0Len_pkt
    return

Clear_Interface_Feature     ; starts in bank2
    return

; ******************************************************************
; only feature valid for device feature is Device Remote wakeup
; ******************************************************************
Set_Device_Feature  ; starts in bank 2
    movf    BufferData+wValue,w ; get high order byte of wValue    
    xorlw   0x01            ; was it a Device Remote wakeup?
    btfss   STATUS,Z
    goto    wrongstate      ; request error
    bsf     USB_status_device,1 ; set device remote wakeup
    call    Send_0Len_pkt
    return

; ******************************************************************
; Only endpoint feature is Endpoint halt.
; ******************************************************************
Set_Endpoint_Feature            ; starts in bank 2
    movlw   0x0f
    andwf   BufferData+wIndex,w ; mask off the EP number bits
    xorlw   0x01            ; is it EP1?
    btfsc   STATUS,Z
    goto    StallEP1

    movlw   0x0f
    andwf   BufferData+wIndex,w ; mask off the EP number bits
    xorlw   0x02            ; is it EP2?
    btfss   STATUS,Z
    goto    wrongstate

StallEP2
    bsf     STATUS, RP0
    bsf     UEP2,EP_STALL   ; set the stall bit
    goto    StallEnd        ; skip the second stall

StallEP1
    bsf     STATUS, RP0
    bsf     UEP1,EP_STALL   ; set the stall bit
StallEnd
    call    Send_0Len_pkt
    return

Set_Interface_Feature       ; starts in bank 2
    goto    wrongstate      ; invalid request
    return

; ********************************************************************
; Get configuration returns a single byte Data1 packet indicating the 
; configuration in use.
; Default State    - undefined
; Addressed State  - returns 0
; Configured state - returns current configured state.
; ******************************************************************
Get_Configuration           ; starts in bank 2
    bsf     STATUS, RP0
    movf    low BD0IAL,w    ; get address of buffer
    movwf   FSR
    bcf     STATUS, RP0
    bsf     STATUS,IRP      ; indirectly to banks 2-3
    movf    USB_Curr_Config,w
    movwf   INDF            ; write byte to buffer
    bsf     STATUS, RP0
    movlw   0x01
    movwf   BD0IBC          ; set byte count to 1
    movlw   0xc8            ; DATA1 packet, DTS enabled
    movwf   BD0IST          ; give buffer back to SIE
    return

; ******************************************************************
; Set configuration uses the configuration selected by the low order
; byte of wValue.  Sets up a zero length data1 packet as a reply.
; ******************************************************************
Set_Configuration           ; starts in bank 2
; All we do is set a meaningless number.  This'll 
; need more code here to actually give meaning to each configuration
; we choose.
    movf    BufferData+wValue,w ; is it a valid configuration?
    sublw   NUM_CONFIGURATIONS    
    btfss   STATUS,C        ; if config <= num configs, request appears valid
    goto    wrongstate

    movf    BufferData+wValue,w    
    movwf   USB_Curr_Config ; store new state in configuration

    btfsc   STATUS,Z        ; was the configuration zero?
    goto    AckSetConfigCmd ; yes: stay in the addressed state

    bsf     STATUS, RP0     ; bank 3
    movlw   CONFIG_STATE    ; No: transition to configured
    movwf   USWSTAT         ; save new state.
#ifdef SHOW_ENUM_STATUS
    banksel PORTB
    bsf     PORTB,3         ; set bit 3 to show configured
;    banksel USWSTAT         ; not necessary, Send_0LenPkt resets bank bits
#endif

AckSetConfigCmd
    call    Send_0Len_pkt

; These configure the EP1 and EP2  endpoints.  Change these as necessary
; for your application.
    banksel BD1OST
    movlw   0x88            ; set own bit of EP1 (SIE can write)
    movwf   BD1OST
    movlw   USB_Buffer+0x10 ; Endpoint 1 OUT gets a buffer
    movwf   BD1OAL          ; set up buffer address
    movlw   8
    movwf   BD1OBC          ; set byte count

    movlw   0x48            ; set own bit of EP1 (PIC can write)
    movwf   BD1IST        
    movlw   USB_Buffer+0x18 ; Endpoint 1 IN gets a buffer
    movwf   BD1IAL          ; set up buffer address

    movlw   0x88            ; set own bit of EP2 (SIE can write)
    movwf   BD2OST
    movlw   USB_Buffer+0x20 ; Endpoint 2 OUT gets a buffer
    movwf   BD2OAL          ; set up buffer address
    movlw   8
    movwf   BD2OBC          ; set byte count

    movlw   0x48            ; set own bit of EP2 (PIC can write)
    movwf   BD2IST
    movlw   USB_Buffer+0x20 ; EP1 In and EP2 In share a buffer
    movwf   BD2IAL          ; set up buffer address
; Set up the Endpoint Control Registers.  The following patterns are defined
; ENDPT_DISABLED - endpoint not used
; ENDPT_IN_ONLY  - endpoint supports IN transactions only
; ENDPT_OUT_ONLY - endpoint supports OUT transactions only
; ENDPT_CONTROL     - Supports IN, OUT and CONTROL transactions - Only use with EP0
; ENDPT_NON_CONTROL - Supports both IN and OUT transactions
    movlw   ENDPT_NON_CONTROL
    movwf   UEP1            ; enable EP's 1 and 2 for In and Outs...
    movlw   ENDPT_NON_CONTROL
    movwf   UEP2

;    pagesel SetConfiguration    ; call SetConfiguration etc. after configuration changed
;    movf    USB_Curr_Config,w   ; if you have multiple configurations
;    call    SetConfiguration
;    pagesel Set_Configuration
    return


; ********************************************************************
; Get interface returns a single byte Data1 packet indicating the 
; interface in use.
; Default State    - undefined
; Addressed State  - Not valid - returns stall
; Configured state - returns current configured state.
; ******************************************************************
Get_Interface   ; STARTS IN BANK 2
    bsf     STATUS, RP0
    movf    USWSTAT,w       ; Not valid in the addressed state
    bcf     STATUS,RP0      ; bank 2
    andlw   0x03
    xorlw   ADDRESS_STATE
    btfsc   STATUS,Z
    goto    wrongstate

    movf    BufferData+wIndex,w ; get interface ID
    addlw   low USB_Interface
    movwf   FSR
    bsf     STATUS,IRP
    movf    INDF,w        
    movwf   temp            ; store in temp register
    
    bsf     STATUS,RP0      ; bank 3
    movf    BD0IAL,w        ; get address of buffer
    movwf   FSR
    movf    temp,w          ; load temp
    movwf   INDF            ; write byte to buffer

    movlw   0x01
    movwf   BD0IBC          ; set byte count to 1
    movlw   0xc8            ; DATA1 packet, DTS enabled
    movwf   BD0IST          ; give buffer back to SIE
    return

; ******************************************************************
; Set configuration uses the configuration selected by the low order
; byte of wValue.  Sets up a zero length data1 packet as a reply.
; ******************************************************************
Set_Interface   ; start bank 2
    bsf     STATUS, RP0
    movf    USWSTAT,w       ; test to make sure we're configured
    bcf     STATUS,RP0      ; bank2
    andlw   0x03
    xorlw   CONFIG_STATE
    btfss   STATUS,Z
    goto    wrongstate

    bcf     STATUS, RP0
    movf    BufferData+wIndex,w ; get interface
    addlw   USB_Interface   ; add offset to array
    movwf   FSR
    bsf     STATUS,IRP      ; indirectly to banks 2-3
    movf    BufferData+wValue,w ; get alternate interface
    movwf   INDF            ; store in array
; All we do is set a meaningless number.  This'll 
; need more code here to actually give meaning to each configuration
; we choose.

    call    Send_0Len_pkt
    return

; *********************************************************************
; copies the next chunk of buffer descriptor over to the EP0 In buffer.
; Inputs:
;    EP0_start - points to first byte of configuration table to transfer
;    EP0_end - total number of bytes to transfer
;    EP0_maxLength - maximum number of bytes that can be sent during
;    a single transfer
;
; toggles the data0/1 bit before setting the UOWN bit over to SIE.
; ******************************************************************
copy_descriptor_to_EP0
    global  copy_descriptor_to_EP0
    banksel BD0IAL
    bankisel BD0IAL
    movf    BD0IAL,w        ; get buffer address
    movwf   FSR 
    banksel bufindex
    clrf    bufindex        ; bufindex = 0
gdd_loop
    movf    bufindex,w      ; while (bufindex < EP0_maxLength)
    subwf   EP0_maxLength,w ;    && (EP0_start < EP0_end)
    btfsc   STATUS,Z
    goto    end_gdd_loop

    decfsz  EP0_end, f
    goto    gdd_copy_loop
    goto    end_gdd_loop_short_packet

gdd_copy_loop
    pagesel Descriptions
    call    Descriptions
    pagesel gdd_copy_loop
    movwf   INDF
    
    incf    bufindex,f    
    incf    FSR,f
    incfsz  EP0_start,f
    goto    gdd_loop
    incf    EP0_start+1,f
    goto    gdd_loop

end_gdd_loop_short_packet
    clrf    USB_dev_req     ; we're sending a short packet, clear the device request
end_gdd_loop
    movf    bufindex,w      ; write number of bytes to byte count
    bsf     STATUS,RP0      ; Bank 3
    movwf   BD0IBC
    movlw   (0x01<<DATA01)  ; toggle data0/1 bit
    xorwf   BD0IST,w
    andlw   (0x01<<DATA01)  ; clear PID bits
    iorlw   0x88            ; set OWN and DTS bits
    movwf   BD0IST          ; write the whole mess back
    pagesel copy_descriptor_to_EP0
    return
; *********************************************************************
; SetConfiguration
; 
; This function is called when the host issues a Set Configuration 
; command.  The housekeeping within USB is handled within the CH9 commands
; This function should be filled in to give meaning to the command within
; the application.
;
; SetConfiguration is called from within the ISR so this function should
; be kept as short as possible.
; *********************************************************************
SetConfiguration
    global  SetConfiguration
    return

; *********************************************************************
; Vendor Specific calls
; control is transferred here when bmRequestType bits 5 & 6 = 10 indicating
; the request is a vendor specific request.  This function then would 
; interpret the bRequest field to determine what action is required.
; The end of each vendor specific command should be terminated with a 
; return.  
; *********************************************************************
CheckVendor    
    global  CheckVendor
    return  ; *** remove this line and uncomment out the remainder    

    end




⌨️ 快捷键说明

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