+5 volts
ground
clock
strobe
serial out
You can read more on how the nes controller works at http://www.gamesx.com
My program provides the necessary clock and strobe signals so that the controller will output the serial information on which buttons have been pressed. The program will then read this serial information and decode it into individual signals. So basically when I press the A button on the controller the RB0 pin outputs 5 volts. If I press the B button it will output 5 volts on pin RB1.
It took a long time, and I had to deal with a bunch of programming issues, but I finally got it done. I will have more to come later, especially on how to interface it with the dreamcast easily. For now I'll only post the code, but I won't explain anything further until I get a tutorial posted just for the sake of my sanity
Here it is:
Code: Select all
;-----------
; NES to decoded outputs
; Written by Kevin Ahrendt based on original code by Tennessee Carmel-Veilleux
; Copyright Notice: Neither Tennessee Carmel-Veilleux nor Kevin Ahrendt is responsible for
; any damage this firmware software may cause.
;----------Assembler Directives-----------------------------------------
list P=16F628A, F=INHX8M, C=80, N=80, ST=OFF, MM=ON, R=DEC
include "p16f628a.inc"
__config (_CP_OFF & _PWRTE_ON & _LVP_OFF & _BODEN_OFF & _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_ON )
;----------Equates------------------------------------------------------
Bank0Ram equ h'0c'
PortAMask equ b'11111001' ; Port a has Inputs for NES pad and control for pad's shift regs
PortBMask equ b'00000000' ; Five LSBs of portb control the atari port shift reg (4094) and fire buttons
Ctrl1D0 equ 0
CtrlClk equ 1
CtrlStrb equ 2
CtrlB equ 0
CtrlA equ 1
CtrlSl equ 2
CtrlSt equ 3
CtrlUp equ 4
CtrlDo equ 5
CtrlLe equ 6
CtrlRi equ 7
;----------Variables----------------------------------------------------
CBLOCK 0x20
CTRLDATA ;We read the NES controller serial data in this var
LOOPCNT
ENDC
;----------Controller Data Format---------------------------------------
;B0 B1 B2 B3 B4 B5 B6 B7
;[A] [B] [SEL] [START] [UP] [DOWN] [LEFT] [RIGHT]
;----------Mainline program---------------------------------------------
org h'000'
movlw 0x07
movwf CMCON
goto Main
nop
Main
movlw PortAMask ; Set PortA/B to their inital TRIS masks and port output values
banksel TRISA
movwf TRISA
movlw PortBMask
movwf TRISB
banksel PORTA
clrf PORTA
; Here starts the main work loop
Loop
movlw h'8' ; Loop 8 times
movwf LOOPCNT
bsf PORTA,CtrlStrb ; Strobe the controllers
nop
nop
bcf PORTA,CtrlStrb
nop
ReadLoop
nop
nop
; Reading starts here
bsf STATUS,C ; Preset Carry to 1
btfss PORTA,Ctrl1D0 ; If data bit is 0, reset carry to 0
bcf STATUS,C
rlf CTRLDATA,F ; Shift-in the carry in the controller information
bsf PORTA,CtrlClk ; Clock the port for next bit
nop
nop
bcf PORTA,CtrlClk
decfsz LOOPCNT,F
goto ReadLoop
; Test if B is pressed
rlf CTRLDATA,F ; Moves data so first bit is in carry bit
btfsc STATUS,C ; Carry Bit is checked
goto BOn ; If on go to BOn, if off
bsf PORTB,CtrlB ; turn line low
goto BDone ; Check next button
; B is on
BOn
bcf PORTB,CtrlB ; Sets pin on high
BDone
rlf CTRLDATA,F
btfsc STATUS,C
goto AOn
bsf PORTB,CtrlA
goto ADone
; A is on
AOn
bcf PORTB,CtrlA
; Test Select
ADone
rlf CTRLDATA,F
btfsc STATUS,C
goto SlOn
bsf PORTB,CtrlSl
goto SlDone
; Select is on
SlOn
bcf PORTB,CtrlSl
; Test Start
SlDone
rlf CTRLDATA,F
btfsc STATUS,C
goto StOn
bsf PORTB,CtrlSt
goto StDone
; Start is on
StOn
bcf PORTB,CtrlSt
; Test Up
StDone
rlf CTRLDATA,F
btfsc STATUS,C
goto UpOn
bsf PORTB,CtrlUp
goto UpDone
; Up is on
UpOn
bcf PORTB,CtrlUp
; Test Down
UpDone
rlf CTRLDATA,F
btfsc STATUS,C
goto DoOn
bsf PORTB,CtrlDo
goto DoDone
; Down is on
DoOn
bcf PORTB,CtrlDo
; Test Left
DoDone
rlf CTRLDATA,F
btfsc STATUS,C
goto LeOn
bsf PORTB,CtrlLe
goto LeDone
; Left is on
LeOn
bcf PORTB,CtrlLe
; Test Right
LeDone
rlf CTRLDATA,F
btfsc STATUS,C
goto RiOn
bsf PORTB,CtrlRi
goto RiDone
; Right is on
RiOn
bcf PORTB,CtrlRi
RiDone
goto Loop ; Loop the main loop
;-----------
END