📄 usb.asm
字号:
RAM_PROLOGUE RAM_USE_CLASS_4
RAM_PROLOGUE RAM_USE_CLASS_3
RAM_SETPAGE_CUR >USB_bCurrentDevice ; Set the CUR_PP to the right page
RAM_SETPAGE_IDX2STK
mov X, SP
mov A, [X+EP_NUM]
cmp A, USB_MAX_EP_NUMBER+1 ; Range check
jnc .exit ; Bail out
;Should we toggle the data bit??
;SET THE COUNT AND TOGGLE
mov A, [X+CNTLEN_MSB] ; Get the MSB of the Count
and A, 0x01 ; Mask off the count bit
mov [USB_APITemp+1], A ; Save the count
mov A, [X+CNTLEN_LSB] ; Get the LSB of the Count
mov [USB_APITemp], A ; Save the count
mov A, [X+TOGGLE]
jz .noToggle
mov A, [X+EP_NUM] ; Get the Endpoint number
mov X, A ; Make it into an index
RAM_SETPAGE_IDX >USB_EPDataToggle
xor [X + USB_EPDataToggle], USB_CNT_TOGGLE
jmp .FinishUp
.noToggle:
mov A, [X+EP_NUM] ; Get the Endpoint number
mov X, A ; Make it into an index
RAM_SETPAGE_IDX >USB_EPDataToggle
.FinishUp:
mov A, [X + USB_EPDataToggle] ; Get the Data toggle for EP
or [USB_APITemp+1], A ; Or it into the saved CNT MSB
RAM_SETPAGE_IDX2STK
mov X, SP
mov A, [X+EP_NUM] ; Get the Endpoint number
asl A ; Double the ep number for proper cnt access
mov X, A ; Make it into an index
mov A, [USB_APITemp] ; Retrieve the saved MSB
mov reg[X+USB_EP1CNT1 - 1], A ; Write it into the register
dec X ; Decrement the index to access the LSB
mov A, [USB_APITemp+1] ; Retrieve the saved LSB
mov reg[X+USB_EP1CNT1 - 1], A ; Write it into the register
; It's Time to move the data
; First we need to determine where within the PMA the EP Start Address is
mov X, SP ; Get the Stack Pointer
mov A, [X+EP_NUM] ; Get the Endpoint number
mov X, A ; Use the EP number as an index
mov A, reg[X+TMP_DR0-1] ; Get the address of ep from tmp register
M8C_SetBank1
mov reg[PMA0_WA], A ; Set the Write pointer of our pma to ep space
M8C_SetBank0
; Now we are ready to start moving data
mov X, SP
and [X+CNTLEN_MSB], 0x01 ; Mask off the MSB bit
jnz .start_send ; If it is high then we have 256 bytes
mov A, [X+CNTLEN_LSB] ; Check the LSB register
jz .done ; If it is 0 then we have a 0 length packet
.start_send:
mov A, [X+DATA_LSB]
push A
IF SYSTEM_LARGE_MEMORY_MODEL
mov A, [X+DATA_MSB]
mov reg[IDX_PP], A
ENDIF
pop X
.loop:
mov A, [X]
mov reg[PMA0_DR], A
inc X
dec [USB_APITemp]
jnz .loop
RAM_SETPAGE_IDX2STK
.done:
mov X, SP
mov A, [X+EP_NUM]
mov X, A
RAM_SETPAGE_IDX >USB_EndpointAPIStatus
mov [X + USB_EndpointAPIStatus], NO_EVENT_PENDING ; Set the state
M8C_SetBank1
mov A, reg[X+TMP_DR0-1] ; Get the value of the PMA start Address
mov reg[X + PMA0_RA], A ; Load it into EP PMA so pre-fetch occurs
mov reg[X + USB_EP1MODE-1], USB_MODE_ACK_IN ; Enable the endpoint
M8C_SetBank0
.exit:
RAM_EPILOGUE RAM_USE_CLASS_3
RAM_EPILOGUE RAM_USE_CLASS_4
ret
.ENDSECTION
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: USB_EnableOutEP
;
; DESCRIPTION: This function enables an OUT endpoint. It should not be
; called for an IN endpoint.
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS: A contains the endpoint number
;
; RETURNS: None
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
USB_EnableOutEP:
_USB_EnableOutEP:
RAM_PROLOGUE RAM_USE_CLASS_3
RAM_SETPAGE_IDX >USB_EndpointAPIStatus
cmp A, 0 ; Can't enable EP0
jz .exit ; Bail out
cmp A, (USB_MAX_EP_NUMBER + 1) ; Range check
jnc .exit ; Bail out
; Flow here to enable an endpoint
mov X, A ; Endpoint number is the index
push X
mov [X+USB_EndpointAPIStatus], NO_EVENT_PENDING ; For the API
mov A, X
asl A
mov X, A
mov reg[X+EP1_CNT1-1], 64
M8C_SetBank1
pop X
mov A, reg[X+TMP_DR0-1]
mov reg[X+PMA0_WA], A
mov A, reg[X+USB_EP1MODE-1] ; Unlock the mode register
mov reg[X+USB_EP1MODE-1], USB_MODE_ACK_OUT ; Enable the endpoint
M8C_SetBank0
; Jump or flow here for a common exit
.exit:
RAM_EPILOGUE RAM_USE_CLASS_3
ret ; All done
.ENDSECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: USB_DisableEP
;
; DESCRIPTION: This function disables an OUT endpoint. It should not be
; called for an IN endpoint.
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS: A the endpoint number
;
; RETURNS: none
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
.SECTION
USB_DisableOutEP:
_USB_DisableOutEP:
cmp A, 0 ; Can't disable EP0
jz .exit ; Bail out
cmp A, (USB_MAX_EP_NUMBER + 1) ; Range check
jnc .exit ; Bail out
; Flow here to disable an endpoint
mov X, A ; Endpoint number is the index
M8C_SetBank1
mov A, reg[X+USB_EP1MODE-1] ; Unlock the mode register
mov reg[X+USB_EP1MODE-1], USB_MODE_NAK_OUT ; Disable the endpoint
M8C_SetBank0
; Jump or flow here for a common exit
.exit:
ret ; All done
.ENDSECTION
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: USB_Force
;
; DESCRIPTION: Force the J/K/SE0 State of D+/D-
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS: A: USB_FORCE_J
; USB_FORCE_K
; USB_FORCE_SE0
; USB_FORCE_NONE
;
; RETURNS: Nothing
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
USB_Force:
_USB_Force:
mov reg[USB_USBIO_CR0], A
ret ; Exit
.ENDSECTION
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: USB_bReadOutEP
;
; DESCRIPTION: This function loads the specified endpoint buffer
; with the number of bytes previously set in the count
; register.
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS:
; [SP-7] MSB of Count to read
; [SP-6] LSB of Count to read
; [SP-5] MSB of data array address to put data in
; [SP-4] LSB of data array address to put data in
; [SP-3] Endpoint Number
;
; RETURNS:
; none
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
; Currently only the page pointer registers listed below are modified:
; CUR_PP
; IDX_PP
;
EP_NUMR: equ -3 ; Endpoint Number
DATA_LSBR: equ -4 ; MSB pointer of data
DATA_MSBR: equ -5 ; LSB pointer of data
CNTLEN_LSBR: equ -6 ; Length of data to send
CNTLEN_MSBR: equ -7
USB_bReadOutEP:
_USB_bReadOutEP:
RAM_PROLOGUE RAM_USE_CLASS_4
RAM_PROLOGUE RAM_USE_CLASS_3
RAM_SETPAGE_CUR >USB_bCurrentDevice ; Set the CUR_PP to the right page
RAM_SETPAGE_IDX2STK
mov X, SP
mov A, [X+EP_NUMR]
CMP A, USB_MAX_EP_NUMBER+1 ; Range check
JNC .exit ; Bail out
;Get the count value passed
mov A, [X+CNTLEN_MSBR] ; Get the MSB of the Count
and A, 0x01 ; Mask off the count bit
mov [USB_APITemp], A ; Save the count
mov A, [X+CNTLEN_LSBR] ; Get the LSB of the Count
mov [USB_APITemp+1], A ; Save the count
;Determine which is smaller the requested data or the available data
mov A, [X+EP_NUMR] ; Get the Endpoint number
asl A ; Double the ep number for proper cnt access
mov X, A ; Make it into an index
mov A, reg[X+USB_EP1CNT1 - 2] ; Get the Real count MSB
and A, 0x01 ; Mask off the LSB
cmp A, [USB_APITemp] ; Are they equal
jz .MSBEqual ; If they are check if they are 1
jc .CountDetermined ;If the requested count is smaller use it
mov [USB_APITemp], A ; Else use the actual
mov A, reg[X+USB_EP1CNT1 - 1] ; Get the Real count LSB
mov [USB_APITemp + 1], A ; Else use the actual
jmp .CountDetermined
.MSBEqual:
mov A, [USB_APITemp]
jz .CheckLSB
mov [USB_APITemp + 1], 0
jmp .CountDetermined
.CheckLSB:
mov A, reg[X+USB_EP1CNT1 - 1] ; Get the Real count LSB
cmp A, [USB_APITemp+1] ; Are they equal
jz .CountDetermined ; If they are check if they are 1
jnc .CountDetermined ;If the requested count is smaller use it
mov [USB_APITemp+1], A ; Else use the actual
.CountDetermined:
; First we need to determine where within the PMA the EP Start Address is
mov X, SP ; Get the Stack Pointer
mov A, [X+EP_NUMR] ; Get the Endpoint number
mov X, A ; Use the EP number as an index
mov A, reg[X+TMP_DR0-1] ; Get the address of ep from tmp register
M8C_SetBank1
mov reg[PMA0_RA], A ; Set the Read pointer of our pma to ep space
M8C_SetBank0
; Now we are ready to start moving data
and [USB_APITemp], 0x01 ; Mask off the MSB bit
jnz .start_send ; If it is high then we have 256 bytes
mov A, [USB_APITemp+1] ; Check the LSB register
jz .done ; If it is 0 then we have a 0 length packet
.start_send:
mov X, SP
mov A, [X+DATA_LSBR] ; Get the LSB of the pointer
push A ; save on stack
IF SYSTEM_LARGE_MEMORY_MODEL
mov A, [X+DATA_MSBR] ; Get the MSB of the pointer
mov reg[IDX_PP], A ; Use as value for IDX_PP
ENDIF
pop X ; Get the LSB again
.loop:
mov A, reg[PMA0_DR] ; Get the data from the PMA space
mov [X], A ; save it in data array
inc X ; increment the pointer
dec [USB_APITemp+1] ; decrement the counter
jnz .loop ; wait for count to zero out
RAM_SETPAGE_IDX2STK
mov X, SP
mov A, [X+EP_NUM]
asl A
mov X, A
mov A, reg[X+USB_EP1CNT1 - 1] ; Get the Real count LSB
sub A, 2
.done:
.exit:
RAM_EPILOGUE RAM_USE_CLASS_3
RAM_EPILOGUE RAM_USE_CLASS_4
ret
.ENDSECTION
.SECTION
;-----------------------------------------------------------------------------
; FUNCTION NAME: USB_bGetEPAckState
;
; DESCRIPTION: Returns whether the ACK bit of EP has been set for
; an endpoint
;
;-----------------------------------------------------------------------------
;
; ARGUMENTS: A is the Endpoint Number
;
; RETURNS: A is 0 if ACK bit is not set and non-zero if it is
;
; SIDE EFFECTS:
; The A and X registers may be modified by this or future implementations
; of this function. The same is true for all RAM page pointer registers in
; the Large Memory Model. When necessary, it is the calling function's
; responsibility to perserve their values across calls to fastcall16
; functions.
;
USB_bGetEPAckState:
_USB_bGetEPAckState:
mov X, A
M8C_SetBank1
mov A, reg[X + USB_EP1MODE-1]
M8C_SetBank0
and A, 0x10
ret ; Exit
.ENDSECTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -