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

📄 receiver.asm

📁 WII游戏机无线手柄SNES通讯模块
💻 ASM
📖 第 1 页 / 共 2 页
字号:
		retlw	0
		
		START_PACKET		PACKET_BUFFER		; send id and status
		PACK_CONST	09h
		PACK_CONST	00h
		PACK_CONST	00h
		END_PACKET			PACKET_BUFFER, 3
		call send_packet

		START_PACKET		CONSOLE_BUTTONS		; initialize the buttons packet
		PACK_CONST	00h							; 0     0     0     S     Y     X       B       A
		PACK_CONST	80h							; 1     L     R     Z    D-UP D-DOWN D-RIGHT  D-LEFT
		PACK_CONST	80h							; Joystick X
		PACK_CONST	80h							; Joystick Y
		PACK_CONST	80h							; C-Stick X
		PACK_CONST	80h							; C-Stick Y
		PACK_CONST	00h							; Left shoulder toggle
		PACK_CONST	00h							; Right shoulder toggle
		END_PACKET			CONSOLE_BUTTONS, 8

		retlw	1

; ================================================================================================
; check_41h -	checks to see if we've received a "request origins" command,
;				calibration is easy on this controller...everything's digital.
; ================================================================================================

check_41h
		movfw	BITS_READ								; must be an 8-bit packet
		sublw	8h
		btfss	STATUS, Z
		retlw	0
		movfw	PACKET_BUFFER							; first byte must be 41h
		sublw	41h
		btfss	STATUS, Z
		retlw	0
		
		START_PACKET	PACKET_BUFFER					; send origins/calibration packet
		PACK_CONST		00h
		PACK_CONST		80h
		PACK_CONST		80h
		PACK_CONST		80h
		PACK_CONST		80h
		PACK_CONST		80h
		PACK_CONST		00h
		PACK_CONST		00h
		PACK_CONST		02h
		PACK_CONST		02h
		END_PACKET		PACKET_BUFFER, 0Ah				; 10 bytes in this packet
		call	send_packet
		retlw	1
		

; ================================================================================================
; initialization -	sets up the ports, synchs with the console, enables interrupts and
;					falls through to the wireless_disconnected routine
; ================================================================================================
initialization
		bsf		STATUS, RP0								; select bank 1
		bsf		WIRELESS_PORT, WIRELESS_BIT				; input from the wireless module
		bsf		REC_PORT, REC_BIT						; read data line from the console
		bcf		SEND_PORT, SEND_BIT						; open collector output to the console
		bcf		GREEN_LED_PORT, GREEN_LED_BIT			; LED pin 1
		bcf		RED_LED_PORT, RED_LED_BIT				; LED pin 2
		bcf		TEST_PORT, TEST_BIT						; test point pin
		errorlevel -302
		bcf		OPTION_REG, INTEDG						; select interrupt on falling edge for PORTB, bit0
		errorlevel +302
		bcf		STATUS, RP0								; select bank 0

		TEST_SIGNAL_OFF									; test signal off by default
		clrf	BITS_READ								; we dont' have time to do this in the interrupt initialization
		bsf		SEND_PORT, SEND_BIT						; maintain high output by default
		bcf		INTCON, INTF							; make sure the bit0 interrupt bit is clear
		bsf		INTCON, INTE							; enable external interrupt
		
; ================================================================================================
; wireless_disconnected -	this function is called by the main loop whenever it detects a
;							lost wireless signal. the function disables interrupts (thus breaking
;							off communication with the console) and then sits in a tight loop
;							until it reads several valid packets in a row. a packet is considered
;							valid when we detect the start bit followed by a little less than
;							3.5ms of 0s after the packet.
; ================================================================================================

wireless_disconnected
		bcf		INTCON, GIE								; disable global interrupts
		LED_RED											; show we're in a disconnected state
disconnected_loop
		btfss	WIRELESS_PORT, WIRELESS_BIT				; wait for the start of a wireless pulse
		call	wireless_half_pulse_delay				; advance to the center of the pulse
		movlw	VALID_SIGNAL_COUNT						; we want several good wireless packets in a row
		movwf	PACKET_COUNTER							; 	before we assume we're reconnected
packet_loop
		btfss	WIRELESS_PORT, WIRELESS_BIT				; picking up a 1 on the wireless pin?
		goto	disconnected_loop						; no, so start over
		call	wireless_packet_delay					; yep, could be a start bit. skip over the packet.
		movlw	03Bh									; outer loop
		movwf	TIMER1
		movlw	03Ah
		movwf	TIMER2									; inner loop
		btfsc	WIRELESS_PORT, WIRELESS_BIT				; picking up a 0 on the wireless pin?
		goto	disconnected_loop						; no, so start all over again
		decfsz	TIMER2, F								; dec inner loop
		goto	$-3
		decfsz	TIMER1, F
		goto	$-7										; dec outer loop
		movlw	31h										; burn off a few more cycles to make it 3500 exactly
		movwf	TIMER1
		decfsz	TIMER1, F
		goto	$-1
		decfsz	PACKET_COUNTER, F						; we received a clean packet, decrement the counter
		goto	packet_loop								; if we haven't got them all then loop back for more
		clrf	TIMEOUT_COUNTER							; reset the timeout counter
		bsf		INTCON, GIE								; reenable interrupts		
		LED_GREEN										; show we're picking up a valid wireless signal again

; ================================================================================================
; main_loop -	sits in a tight loop polling the wireless module and updating the buttons array.
;				the main loop often gets interrupted by the console when it requests button data
;				be sent to it. these interrupts are long enough to push the detection of the stop
;				bit past the end of the packet so that a 0 is read instead of a 1. when this
;				happens the entire packet is ignored, and a fresh attempt is made to read in the
;				next wireless packet. control is passed to the disconnected handler when
;				too many bad packets in a row are received.
; ================================================================================================

main_loop
		movfw	TIMEOUT_COUNTER							; get the packet counter
		sublw	0Ah										; have we had at least 10 interrupts since
		btfss	STATUS, C								;	the last wireless packet?
		goto	wireless_disconnected					; yes, so we've lost the wireless signal
		clrf	WIRELESS_BUTTONS						; initialize the bytes we'll used to
		clrf	WIRELESS_BUTTONS+1						; 	double-buffer the button data
		call	wait_for_wireless_packet				; wait for the next start bit to arrive
		sublw	0										; if we timed out then transfer control
		btfsc	STATUS, Z								; 	to the disconnected handler
		goto	wireless_disconnected
		call	wireless_half_pulse_delay				; advance half-way into the pulse
		
		; read each button pulse and store the result in the WIRELESS_BUTTONS array. each iteration 
		; of the READ_WIRELESS_BUTTON macro lasts exactly 625uS, i.e. the length of a wireless bit
		; pulse.
		TEST_SIGNAL_ON
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 7, FALSE	; start bit
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS,   1, FALSE	; B
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS,   3, TRUE		; Y	
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 4, FALSE	; SELECT (Z)
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS,   4, TRUE		; START
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 3, FALSE	; D-UP
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 2, TRUE		; D-DOWN
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 0, FALSE	; D-LEFT
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 1, TRUE		; D-RIGHT
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS,   0, FALSE	; A
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS,   2, TRUE		; X
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 6, FALSE	; L
		READ_WIRELESS_BUTTON	WIRELESS_BUTTONS+1, 5, TRUE		; R
		TEST_SIGNAL_OFF

		; at this point we should be at the stop bit, unless we've lost the signal or an interrupt
		; has occurred mid-packet. in either case this wireless packet is invalid and so we ignore it.
		; the TIMEOUT_COUNTER will eventually overflow and control will be passed to the disconnected
		; handler.
		btfss	WIRELESS_PORT, WIRELESS_BIT				; we should be in the middle of the stop bit, is it a 1?
		goto	main_loop								; nope, so ignore this packet
		call	wireless_pulse_delay					; skip over the stop bit

		; if we made it this far then we managed to receive a complete wireless packet,
		; including start and stop bits. it's unlikely we've lost the wireless connection,
		; so copy the button data into the CONSOLE_BUTTONS packet so that it gets sent
		; to the console.
save_buttons
		movfw	WIRELESS_BUTTONS
		movwf	CONSOLE_BUTTONS
		movfw	WIRELESS_BUTTONS+1
		movwf	CONSOLE_BUTTONS+1
		clrf	TIMEOUT_COUNTER							; reset the packet counter
		goto	main_loop

; ================================================================================================
; send_packet -	sends a stream of bits to the console. 0 is sent as a 1uS low pulse followed by
;				a 3uS high pulse. 1 is sent as a 3uS low pulse followed by a 1uS high pulse.
;				this function should be called with the number of bits to send loaded into W
;				and the address of the send buffer loaded into FSR. execution time is exactly
;				numbits*20+8 instructions, including the call to and return from function.
; ================================================================================================

send_packet
		movwf	BITS_TO_SEND		; store the number of bytes to send
		clrf	BIT_NUM				; haven't sent any bytes yet
		movfw	INDF				; make a copy of the first byte to send so we don't trash it
		movwf	CURRENT_BYTE
		incf	FSR, F				; and advance the ptr
send_bit
		SEND_0						; 0uS
		nop
		incf	BIT_NUM, F			; add one to the bytes sent counter
		rlf		CURRENT_BYTE, F
		btfsc	STATUS, C
		SEND_1						; 1uS, send the MSB of CURRENT_BYTE to the console
		btfsc	BIT_NUM, 3			; have we sent 8 bits yet?
		goto	advance_byte
		nop
		nop
		nop							; 2uS
		nop
		nop
		nop
		nop
end_bit
		SEND_1						; 3uS, either way, the pulse should be 1 at this stage
bit_sent
		decf	BITS_TO_SEND, F		; one bit less to send
		btfss	STATUS, Z			; finished yet?
		goto	send_bit			; nah
		return						; yup
advance_byte
		movfw	INDF				; make a copy of the first byte to send so we don't trash it
		movwf	CURRENT_BYTE
		incf	FSR, F				; and advance the ptr
		clrf	BIT_NUM				; haven't sent any bytes yet
		goto	end_bit

; ================================================================================================
; timing routines
; ================================================================================================

		; spends roughly 7ms polling the wireless bit to see if a 1 has arrived.
		; returns 1 in W when a pulse is detected, otherwise returns 0 to
		; signify a time-out (i.e. wireless disconnected state)
wait_for_wireless_packet
		movlw	053h
		movwf	TIMER1
		movlw	053h
		movwf	TIMER2
		btfsc	WIRELESS_PORT, WIRELESS_BIT		; wait for the start of a wireless pulse
		retlw	1
		decfsz	TIMER2, F
		goto	$-3
		decfsz	TIMER1, F
		goto	$-7
		retlw	0

		; delays the length of a wireless packet, i.e. exactly 3.5ms
		; including the call-to and return-from. at 20MHz
		; 3.5mS == 17500 cycles
wireless_packet_delay
		movlw	04Bh
		movwf	TIMER1
		movlw	04Bh
		movwf	TIMER2
		decfsz	TIMER2, F
		goto	$-1
		decfsz	TIMER1, F
		goto	$-5
		movlw	6Ah
		movwf	TIMER1
		decfsz	TIMER1, F
		goto	$-1
		nop
		return

		; waits the length of each RF receiver pulse minus 3, i.e. exactly 1247 cycles
		; including the call-to and return-from. the 3 is taken off so that the
		; calling prodecure has a few cycles spare to grab the button state
wireless_pulse_delay
		movlw	0FFh
		movwf	TIMER1
		decfsz	TIMER1, F
		goto	$-1
		movlw	09Eh
		movwf	TIMER1
		decfsz	TIMER1, F
		goto	$-1
		nop
		nop
		return

		; waits the length of half an RF pulse, i.e. exactly 625 cycles,
		; including the call-to and return-from. this is called so that
		; readings are taken in the center of the wireless pulses so
		; that they can accommadate some drift.
wireless_half_pulse_delay
		movlw	0CEh
		movwf	TIMER1
		decfsz	TIMER1, F
		goto	$-1
		nop
		nop
		return

		end

⌨️ 快捷键说明

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