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

📄 usbmain.asm

📁 CY7C63743 usb键盘的源码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
; ReInitialize:
; 1. clears watchdog timer
; 2. enables the 1ms, GPIO and USB reset interrupts
; 3. enables device address 0
; 4. enables EP0 to respond to SETUP packets so that the keyboard
;    can enumerate
; 5. enable EP0 interrupts
; 6. disables EP1
; 7. calls the Init routine to initialze RAM and port registers
;

ReInitialize:
    di                                  ;disable interrupts
	iowr	Watchdog					; clear watchdog timer
	iord	Status_Control				; clear the Bus Reset bit in the 
	and A, ~(USBReset + WatchDogReset + PowerOnReset)		      ; Status & Control register
	iowr	Status_Control
	mov		A, GPIO_TIMER_RESET_MASK; enable 1ms and bus reset timer ints
	iowr	Global_Interrupt
	mov		A, 0						; disable endpoint zero interrupt
	iowr	Endpoint_Interrupt			; disable endpoint one interrupt
	iord	EP_A0_Mode					; unlock Mode register
	mov		A, STALL					; enable endpoint zero setup
	iowr	EP_A0_Mode		

	mov		A, 0						; disable endpoint zero response
    iowr	USB_Device_Address 

	mov		A, DISABLED					; disable endpoint one
	iowr	EP_A1_Mode	
	mov		A, DISABLED					; disable endpoint two
	iowr	EP_A2_Mode	

	iowr	Watchdog					; clear Watchdog timer
	mov		A, NORMAL						; initialize the ports
	iowr	GPIO_Config						; write 
    call    ksc_init_keyscan
	mov		A, 0                  
	iowr	Port0_Interrupt					; disable port 0 interrupts
	iowr	Port1_Interrupt					; disable port 1 interrupts
	iowr	Port2_Interrupt					; disable port 2 interrupts
    iowr    Port3_Interrupt                 ; disable port 3 interrupts

    ; initialize variables
    CLEARRAM usbmain_ram_base,USBMAIN_RAM_SIZE
    CLEARRAM e8h,16
	mov		A, UNCONFIGURED
	mov		[configuration_status], A           ; start out unconfigured
	mov		A, REPORT_PROTOCOL
	mov		[protocol_status], A                ; default to report protocol
    call    usb_init_keyscan	
	iowr	Watchdog					; clear Watchdog timer again
    call    mouse_init_module
    ret


  
;========================================================================
;                               RESET 
;  We execute the Reset routine whenever a Power-On Reset (POR) or a
;  WatchDog reset (WDR) occurs.
;========================================================================
; reset processing

Reset:
	iowr	Watchdog				; clear Watchdog timer

    mov		A, datastack_start		; initialize the data stack pointer
	swap	A, dsp                  ; to a position so it does not write over USB fifos
    call    ReInitialize              ; initialize system variables
    ei
    jmp		main


USB_Bus_Reset_ISR:
    iowr    Watchdog
    mov		A, datastack_start		      ; initialize the data stack pointer
	swap	A, dsp                        ; to a position so it does not write over USB fifos
    mov     a,0                             ;set psp stack to 0
    mov     psp,a                           ; 
    call    ReInitialize                  ; initialize system variables
 	mov		A, ADDRESS_ENABLE_BIT		  ; enable endpoint zero response
    iowr	USB_Device_Address 
	mov		A, ENUMERATE				  ; enable endpoint zero interrupt
	iowr	Endpoint_Interrupt			  ; disable endpoint one interrupt
    mov     A,(CAPS_LOCK_LED + NUM_LOCK_LED + SCROLL_LOCK_LED)
    call    ksc_writeLED
    ei


;========================================================================
; 			MAIN LOOP
;========================================================================
main:
	iowr	Watchdog					    ; clear Watchdog timer
	mov		A,[EP0_FLAG]			
    cmp     A,0
    jz      .config                         ;
    mov     A,0
    mov     [EP0_FLAG],A
    call    EP0
.config:
    call    MouseConnectTask
	mov		A, [configuration_status]
	cmp		A, UNCONFIGURED
	jz		main            				; if we're  configured.....
.test_suspend:
	mov		A,[background_flags]			
	and		A,SUSPEND_FLAG                  ; if we need to suspend
	jz		.scan
	call	Suspend							;   do so
	mov		A,[background_flags]			;   then clear the suspend flag
	and		A,~SUSPEND_FLAG
	mov		[background_flags],A
.scan:
	mov		A,[background_flags]			;if we need to scan the kbd
	and		A,SCAN_FLAG
	jz		other_tasks

	call	usbkey_scan_keys				; do so
	call	Send_Keyboard_Report			; send a keyboard report
    call	PowerTask						; check for power report
   
    call    MouseTask                       ; check for mouse data
	call	ConsumerTask                    ; and consumer report
.next:
	mov		A,[background_flags]			;clear the scan flag
	and		A,~SCAN_FLAG
	mov		[background_flags],A
; other tasks can be inserted here
other_tasks:
    call    SendPowerReport                 ;send reports on EP2
	call	SendConsumerReport
	jmp		main							; no tasks defined


;========================================================================
; PowerTask maintains the idle count for the power packets.  If the idle
; count expires, usb_power_flag is set to indicate the need for sending
; a packet
;========================================================================
PowerTask:
.idle_period_check:
	mov		A, [power_idle_period_ctr]          ; if idle_period is zero, then we only send
	cmp		A, 0                                ; reports on change
	jz		.exit                               ; exit task
    dec     A
    mov     [power_idle_period_ctr],A			;  else decrement idle period
    jnz     .exit								;  exit if idle period not expired
.xmit:
    mov     A,[power_idle_period]				;  reset idle period
    mov     [power_idle_period_ctr],A
    mov		A,1
    mov   [usb_power_flag],A					;and set flag to send a report
.exit:
    ret

;========================================================================
; ConsumerTask maintains the idle count for the consumer packets.  If the idle
; count expires, usb_consumer_flag is set to indicate the need for sending
; a packet
;========================================================================
ConsumerTask:
.idle1_period_check:
	mov		A, [consumer_idle_period_ctr]       ; if idle_period is zero, then we only send
	cmp		A, 0                                ; reports on change
	jz		.exit                               ; exit task
	dec     A
	mov     [consumer_idle_period_ctr],A        ;  else decrement idle period
	jnz     .exit								;  exit if idle period not expired
.xmit:
	mov     A,[consumer_idle_period]            ;  reset idle period
	mov     [consumer_idle_period_ctr],A
	mov		A,1
	mov		[usb_consumer_flag],A               ;and set flag to send a report
.exit:
   ret

;


;========================================================================
; SendPowerReport sends a power key report out on endpoint 2
;========================================================================

SendPowerReport:
    mov		A,[protocol_status]
    cmp		A,BOOT_PROTOCOL
    jz		.exit                               ;don't report power keys in boot mode
    mov     A,[usb_current_state]                 ;don't report power keys if error situation
    cmp     A,USB_REPORT_ERROR
    jz      .exit
	mov		A,[usb_power_flag]					; if power, sleep, or wake keys
	cmp		A,00								; have changed,
    jz		.exit                               ; transmit them
	iord	EP_A2_Mode							 ; are we currently transmitting a report?
	and		A, USB_MODE_MASK
	cmp		A, ACKIN
	jz		.exit								; yes, then exit (so we don't mess up
                                                ;current transaction)
	mov		A,[usb_power_id]					; set report ID 
	mov		[endpoint_2],A
	mov		A,[usb_power_keys]					; get bit field
  	mov		[endpoint_2+1],A
	iord	EP_A2_Counter		
	and		A, DATATOGGLE						; keep data toggle setting
	or		A, POWER_REPORT_LEN					; packet size
	iowr	EP_A2_Counter

	mov		A, ACKIN							; enable packet transmission 
	iowr	EP_A2_Mode
 	mov		A,0
	mov		[usb_power_flag],A
.exit:
	ret

;========================================================================
; SendConsumerReport sends a consumer key report out on endpoint 2
;========================================================================
SendConsumerReport:
    mov		A,[protocol_status]
    cmp		A,BOOT_PROTOCOL
    jz		 .exit                              ;don't report power keys in boot mode
    mov     A,[usb_current_state]                 ;don't report power keys if error situation
    cmp     A,USB_REPORT_ERROR
    jz      .exit
	mov		A,[usb_consumer_flag]				; if power, sleep, or wake keys
	cmp		A,00								; have changed,
    jz		.exit                               ; transmit them
	iord	EP_A2_Mode							; are we currently transmitting a report?
	and		A, USB_MODE_MASK
	cmp		A, ACKIN
	jz		.exit								; yes, then exit (so we don't mess up
                                                ;current transaction)
	mov		A,[usb_consumer_id]					; set report ID 
	mov		[endpoint_2],A
	mov		A,[usb_consumer_keys]				; get bit field
  	mov		[endpoint_2+1],A
	iord	EP_A2_Counter		
	and		A, DATATOGGLE						; keep data toggle setting
	or		A, CONSUMER_REPORT_LEN				; packet size
	iowr	EP_A2_Counter

	mov	A, ACKIN								; enable packet transmission 
	iowr	EP_A2_Mode
 	mov	A,0
	mov	[usb_consumer_flag],A
.exit:
	ret


;========================================================================
; Send keyboard report to host
;========================================================================
Send_Keyboard_Report:
    mov     A,[usb_tx_required]
	cmp		A,0								; if nothing to report 
    jz		.idle							; check idle status
    cmp		A,USB_REPORT_ERROR				; else if we've got to send an error report
    jnz		.send
    cmp		A,[last_key_report]				; and the last one sent was not an error
    jnz		.send							; we can send this one too
.idle:										; else check idle status 
	mov		A, [kbd_idle_period_ctr]		; if idle_period is zero, then we only send
	cmp		A, 0							; reports on change
	jz		.exit							; exit task

    dec     A
    mov     [kbd_idle_period_ctr],A			; decrement idle period

    jnz     .exit							; and exit if idle period not expired
      
    mov      A,[last_key_report]			; otherwize get type of last report


.send:										;ok, we're REALLY  going to send a new report
 	push	A

	iord	EP_A1_Mode						; are we currently transmitting a report?
	and		A, USB_MODE_MASK
	cmp		A, ACKIN
    pop		A								; pop current request into A
	jz		.out           					; yes, then exit (so we don't mess up
											; the current transmission)
											; 
    mov		[last_key_report],A
    mov     A,0
    mov     [usb_tx_required],A
	call	Copy_report_buffer_to_EP1		; copy report buffer to EP1 FIFO
	call	Enable_EP1_Transmission			; enable EP1 transmission
.out: 
    mov		A,[kbd_idle_period]
    mov		[kbd_idle_period_ctr],A			;reset idle period
.exit:
	ret

;========================================================================
; Copy report_buffer contents to EP1 FIFO
;========================================================================
Copy_report_buffer_to_EP1:
	push	A						        ; save registers on stack
	push	X
	mov		X, 7                            ;count 8 of the darn things
copy_report_buffer_loop:
   mov      A,[last_key_report]             ;if we're sending an error report
   cmp      A,USB_REPORT_ERROR
   mov      A,1                             ;stuff a '1' into the buffer
   jz       .next
	mov		A, [X + usb_report_buffer]      ;else fetch a byte from the key buffer
.next:
	mov		[X + endpoint_1], A             ;put it into ep0 fifo
	dec		X
	jnc		copy_report_buffer_loop         ;do next one

	pop		X						        ; restore registers from stack
	pop		A
	ret
	

;========================================================================
; Enable transmission from EP1 FIFO
;========================================================================
Enable_EP1_Transmission:
	push	A								; save accumulator on stack
	iord	EP_A1_Counter              
      and	A, DATATOGGLE					; keep data toggle setting
	or		A, 8h                           ; packet size
	iowr	EP_A1_Counter

	mov		A, ACKIN						; enable packet transmission 
	iowr	EP_A1_Mode

	pop		A                               ; restore accumulator
	ret										; return

;========================================================================
;USB_EP0_ISR
;
;this routine is entered due to an interrupt on EP0. In the event that a
;setup packet causes the interrupt, the SIE automatically switches to NAKing ins and outs.
;
;the other possible sources of this interrupt are:
;
;control read data phase: the SIE switches from ACKing INS and status OUTs, to 
;NAKing INs, ACKing STATUS OUTs.  It is possible that in this case, the last
;data phase in a control read transaction could be followed very quickly by the
;STATUS OUT phase, or the start of another SETUP if the STATUS OUT phase is
;omitted. If either or both of these occurs while
;the firmware is getting around to processing the last data phase, 
;the firmware will recover cleanly.  
;The out will be acked, and/or the ensuing setup will generate another interrupt
;which will cause the SIE to NAK ins and outs.
;
;
;control read status out phase: The SIE does not switch modes.  The STATUS OUT
;will be ACKed by the SIE.  This interrupt will flag this occurrence to the main loop.
;If the next SETUP occurs before the main loop sees the STATUS OUT, it will simply
;switch to NAKing INs and OUTs and allow the main loop to catch up. 
;
;
;control write data phase: the SIE switches from ACKing OUTs and STATUS INs,
;to NAKing OUTS, ACKing STATUS INs.  As the only data out transaction to worry
; about in the keyboard code is the LED byte (1st byte in the fifo), this byte
;is copied within this ISR to a shadow location, to prevent its being trampled 
;by another SETUP before the byte is processed by the main loop code.
;note that although it is possible that this status out is very quickly followed
;by the STATUS IN, this will still be ACKed by the SIE for us.  In addition,
;if the STATUS IN is omitted and a rapidly succeeding SETUP occurs, the SIE will
;still ACK it, switch to NAKing INs and OUTs, and allow the main loop to catch up.
;
;control write status in phase: The SIE does not switch modes.  The STATUS IN
;will be ACKed by the SIE.  This interrupt will flag this occurrence to the main loop.
;If the next SETUP occurs before the main loop sees the STATUS IN, it will simply
;switch to NAKing INs and OUTs and allow the main loop to catch up. 
;

⌨️ 快捷键说明

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