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

📄 transmitter.asm

📁 WII游戏机无线手柄SNES通讯模块
💻 ASM
字号:
; ================================================================================================
; PROJECT:		SnesHack - A wireless/Wii-enabled SNES controller hack.
; FILENAME:		Transmitter.asm
; DESCRIPTION:	Code for the 16F84A firmware in the SNES controller.
; COPYRIGHT:	Copyright (c) 2007 Mark Feldman. All Rights Reserved.
; ================================================================================================

	list	p=16F84A
	radix	hex

	#include "C:\Program Files\Microchip\MPASM Suite\p16f84a.inc"

	__config	_HS_OSC & _PWRTE_OFF & _WDT_ON & _CP_OFF

; ================================================================================================
; constants
; ================================================================================================

NUM_BUTTONS		equ	0Ch

; clocks the data out of the controller
CLOCK_PORT		equ	PORTB
CLOCK_BIT		equ	0

; signals the controller to latch all button states
LATCH_PORT		equ	PORTB
LATCH_BIT		equ	1

; reads the clocked data from the controller
DATA_PORT		equ	PORTB
DATA_BIT		equ	2

; sends a packet of button press data to the transmitter chip
WIRELESS_PORT	equ	PORTA
WIRELESS_BIT	equ	1

; ================================================================================================
; variables
; ================================================================================================

TIMER1			equ	0Ch							; misc variables used by the routines
TIMER2			equ	0Dh
CURBIT			equ	0Eh

START_BIT		equ	0Fh							; this must be on an odd address to assist ASK-friendly encoding
BUTTON_BITS		equ (START_BIT+1)
STOP_BIT		equ (BUTTON_BITS+NUM_BUTTONS)

	org	0000h

; ================================================================================================
; entry point -	performs initialization
; ================================================================================================

start
		bsf		STATUS, RP0						; select bank 1
		bcf		WIRELESS_PORT,  WIRELESS_BIT	; wireless  bit is an output
		bcf		LATCH_PORT, LATCH_BIT			; latch bit is an output
		bcf		CLOCK_PORT, CLOCK_BIT			; clock bit is an output
		bsf		DATA_PORT,  DATA_BIT			; data  bit is an input
		bcf		STATUS, RP0						; select bank 0

		clrf	START_BIT						; set packet start bit to 0 (gets negated during output)
		clrf	STOP_BIT						; set packet stop bit to 1 (doesn't get negated during output)
		bsf		STOP_BIT, WIRELESS_BIT
		bcf		LATCH_PORT, LATCH_BIT			; default latch state is 0
		bsf		CLOCK_PORT, CLOCK_BIT			; default clock state is 1
		bcf		WIRELESS_PORT, WIRELESS_BIT		; default wireless state is 0
		
main_loop

		; read the button states from the controller
		bsf		LATCH_PORT, LATCH_BIT			; latch = 1 maintain for 12us
		movlw   2
        call    delay
		bcf		LATCH_PORT, LATCH_BIT			; latch = 0 maintain for 6us
		movlw	BUTTON_BITS						; 		point FSR to the location of the button states array
		movwf	FSR
		movlw   NUM_BUTTONS						; 		set up the bit counter
		movwf   CURBIT
		nop
read_loop
		bcf		CLOCK_PORT, CLOCK_BIT			; clock = 0, maintain for 6uS
		clrf	INDF							;		clear destination bit
		btfss	DATA_PORT, DATA_BIT				; 		read the button state, is it a 0?
		bsf		INDF, WIRELESS_BIT				;		if yes then set destination bit
		nop
		incf	FSR, F							; 		move the array ptr to the next entry
		bsf		CLOCK_PORT, CLOCK_BIT			; clock = 1, maintain for 6uS
		nop
		nop
		decfsz	CURBIT, F						; 		any more bits to read?
		goto	read_loop						; 		yep, so loop back

; send the packet to the transmitter
transmit_packet
		movlw	START_BIT						; point FSR to the location of the button states
		movwf	FSR
		movlw   NUM_BUTTONS+2					; 1 start bit + 12 data bits + 1 stop bit
		movwf   CURBIT
send_loop
		movfw	WIRELESS_PORT					; grab the port state
		andlw	~(1 << WIRELESS_BIT)			; clear the send bit
		iorwf	INDF, W							; move the bit from the buffer into W
		btfsc	FSR, 0							; change polarity of each bit for ASK-friendly encoding
		xorlw	1 << WIRELESS_BIT
		movwf	PORTA							; send it to the transmitter
		incf	FSR, F							; move to the next position
		movlw   4Eh								; hard-coded delay to help pad the pulse out to 250 cycles
        call    delay							; keep the line like this for the duration of the pulse
		nop
		decfsz	CURBIT, F						; any more bits to send?
		goto	send_loop						; yep, so loop back
		bcf		WIRELESS_PORT, WIRELESS_BIT		; pad the 3.5mS between packets with 0s

; the length of the wireless packet is exactly 3.5ms/3500 cycles, so we now need to pad it out with enough
; 0s to make the main loop exactly 7ms/7000 cycles. i would have liked to put the chip to sleep for this
; to save power, but clock interrupts are disabled during sleep :(
pause
		movlw   0ffh
		call    delay
		movlw   0ffh
		call    delay
		movlw   0ffh
		call    delay
		movlw   0ffh
		call    delay
		movlw   052h
		call    delay
		nop
		clrwdt									; let the watchdog timer know I'm still awake
		goto	main_loop						; all done


; this routine causes a delay of (4 + W * 3) instructions (ie. uS), including the call here and the return
delay   movwf   TIMER1
dloop   decfsz  TIMER1,f
        goto    dloop
        return

		end

⌨️ 快捷键说明

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