Saturday, January 22, 2011
Interfacing a SNES controller and 16x2 LCD to the PIC16f84A
I threw together this demo this morning after finding two snes controllers last night for $1.90 each at a thrift store.
Controller after I meticulously cleaned it.
Next I researched online a bit to find out how to read the button presses (this pdf helped: http://www.parallax.com/dl/docs/prod/prop/hydra-ch6all-v1.0.pdf). The controller uses a active low 16bit wide shift register (last 4bits are always high). Read the pdf for the specifics of pulsing the latch and clock. All that needs to be hooked up is +5v, gnd, Clock, Latch, and Data (the pinout can be found here: http://pinouts.ru/Game/snescontroller_pinout.shtml). I used solid core copper wire that was folded over once to thicken it enough to hold when inserted in the connector socket since I didn't have a proper connector.
Perfect for prototyping.
Next I wired up the breadboard. The first part was the power supply which consists of a AA battery and a max756 to step it up to the 5v needed by the controller, lcd, and pic.
Indicator led and switch to turn on the power.
Next I wired up the PIC16f84A with an external RC clock and icsp header.
Finally I wired the controller (to port A) and lcd (to port B) up and started coding.
The lcd printing button presses.
The code basically initializes the lcd and then continually polls the controller and when a certain button is pressed sends the character to the display. This way the display types the button presses and when you want to clear the screen you just press start or select.
For now I will post the code below (in assembly, and sorry about the formatting, it looked much nicer in mplab) and will upload a schematic and video of it in action when I get some time.
Note: The code provided below is not optimized and is rather messy. Remember that I am not responsible if you try and make this and it doesn't work or ends up blowing up. This was just meant as a proof of concept and a neat morning wake up exercise for me.
UPDATE:
Sorry its been awhile, I've been busy at school, but here is the schematic. Note that I left out the step up converter circuitry.
Code:
;Shawn Maxwell ;
;1/22/11 ;
;LCD SNES ;
;;;;;;;;;;;;;;;;;
;Writes SNES key presses to HD44780 compatable LCD in 4bit mode
COUNT1 equ 08h ;delay constants
COUNT2 equ 09h
Start BSF 03h,5 ;switch from bank 0 to 1
MOVLW b'00000000' ;Out RB to output
MOVWF 06h
MOVLW b'11100' ;Out RA0,1 to output, RA2-4 to input
MOVWF 05h
BCF 03h,5 ;switch from bank 1 to 0
;RS = RB0, EN = RB1, D4-D7 = RB2-RB5
;CLK = RA0, Latch = RA1, Data = RA2
Begin
call LongDelay
call LongDelay
;initialize LCD
movlw b'00001010' ;Out EN high
call Out ;;;;
movlw b'00001000' ;Out to 4 bit operation (note: 1 nibble
operation)
call Out ;;;; ;Out EN low
movlw b'00001010' ;Out EN high
call Out ;;;;
movlw b'00001000' ;Function Out, 8 bit
call Out ;;;; ;Out EN low
movlw b'00100010' ;Out EN high
call Out ;;;;
movlw b'00100000' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Out EN high
call Out ;;;;
movlw b'00000000' ;Display ON, Cursor On, Cursor Blinking
call Out ;;;; ;Out EN low
movlw b'00111110' ;Out EN high
call Out ;;;;
movlw b'00111100' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Out EN high
call Out ;;;;
movlw b'00000000' ;Entry Mode, Increment cursor position, No
display shift
call Out ;;;; ;Out EN low
movlw b'00011010' ;Out EN high
call Out ;;;;
movlw b'00011000' ;2nd nibble
call Out ;;;; ;Out EN low
;initialize SNES controller and read data
SNES
movlw b'00011' ;set Latch, CLK high
movwf 05h
call Delay
movlw b'00001' ;set Latch low
movwf 05h
call Delay
movlw b'00000' ;set CLK low
movwf 05h
call Delay
movlw b'00010' ;pulse Latch high
movwf 05h
call Delay
movwf b'00000'
movwf 05h
btfss 05h,2 ;read B
call buttonB
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Y
call buttonY
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Select
call Clear
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Start
call Clear
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Up
call buttonUp
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Down
call buttonDown
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Left
call buttonLeft
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read Right
call buttonRight
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read A
call buttonA
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read X
call buttonX
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read L
call buttonL
call Delay
call Delay
movlw b'00001' ;Pulse CLK
movwf 05h
call Delay
call Delay
movlw b'00000'
movwf 05h
call Delay
call Delay
btfss 05h,2 ;read R
call buttonR
call Delay
call Delay
goto SNES
;--------------------------------------------
buttonB
movlw b'00010011' ;Out EN,RS high
call Out ;;;;
movlw b'00010001' ;B
call Out ;;;; ;Out EN low
movlw b'00001011' ;Out EN,RS high
call Out ;;;;
movlw b'00001001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonY
movlw b'00010111' ;Out EN,RS high
call Out ;;;;
movlw b'00010101' ;Y
call Out ;;;; ;Out EN low
movlw b'00100111' ;Out EN,RS high
call Out ;;;;
movlw b'00100101' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
Clear
movlw b'00000010' ;Out EN,RS high
call Out ;;;;
movlw b'00000000' ;Clear
call Out ;;;; ;Out EN low
movlw b'00000110' ;Out EN,RS high
call Out ;;;;
movlw b'00000100' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonUp
movlw b'00010111' ;Out EN,RS high
call Out ;;;;
movlw b'00010101' ;Up
call Out ;;;; ;Out EN low
movlw b'00010111' ;Out EN,RS high
call Out ;;;;
movlw b'00010101' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonDown
movlw b'00010011' ;Out EN,RS high
call Out ;;;;
movlw b'00010001' ;Down
call Out ;;;; ;Out EN low
movlw b'00010011' ;Out EN,RS high
call Out ;;;;
movlw b'00010001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonLeft
movlw b'00011111' ;Out EN,RS high
call Out ;;;;
movlw b'00011101' ;Left
call Out ;;;; ;Out EN low
movlw b'00111111' ;Out EN,RS high
call Out ;;;;
movlw b'00111101' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonRight
movlw b'00011111' ;Out EN,RS high
call Out ;;;;
movlw b'00011101' ;Right
call Out ;;;; ;Out EN low
movlw b'00111011' ;Out EN,RS high
call Out ;;;;
movlw b'00111001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonA
movlw b'00010011' ;Out EN,RS high
call Out ;;;;
movlw b'00010001' ;A
call Out ;;;; ;Out EN low
movlw b'00000111' ;Out EN,RS high
call Out ;;;;
movlw b'00000101' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonX
movlw b'00010111' ;Out EN,RS high
call Out ;;;;
movlw b'00010101' ;X
call Out ;;;; ;Out EN low
movlw b'00100011' ;Out EN,RS high
call Out ;;;;
movlw b'00100001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonL
movlw b'00010011' ;Out EN,RS high
call Out ;;;;
movlw b'00010001' ;L
call Out ;;;; ;Out EN low
movlw b'00110011' ;Out EN,RS high
call Out ;;;;
movlw b'00110001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
buttonR
movlw b'00010111' ;Out EN,RS high
call Out ;;;;
movlw b'00010101' ;R
call Out ;;;; ;Out EN low
movlw b'00001011' ;Out EN,RS high
call Out ;;;;
movlw b'00001001' ;2nd nibble
call Out ;;;; ;Out EN low
movlw b'00000010' ;Clear outputs, EN high
movwf 06h
return
Out
movwf 06h
Loop01 decfsz COUNT1,1
goto Loop01
Loop02 decfsz COUNT1,1
goto Loop02
return
Delay
Loop1 decfsz COUNT1,1
goto Loop1
Loop2 decfsz COUNT1,1
goto Loop2
return
LongDelay
loop1 decfsz COUNT1,1
goto loop1
loop2 decfsz COUNT1,1
goto loop2
loop3 decfsz COUNT1,1
goto loop3
loop4 decfsz COUNT1,1
goto loop4
loop5 decfsz COUNT1,1
goto loop5
loop6 decfsz COUNT1,1
goto loop6
loop7 decfsz COUNT1,1
goto loop7
loop8 decfsz COUNT1,1
goto loop8
loop9 decfsz COUNT1,1
goto loop9
loop10 decfsz COUNT1,1
goto loop10
loop11 decfsz COUNT1,1
goto loop11
loop12 decfsz COUNT1,1
goto loop12
loop13 decfsz COUNT1,1
goto loop13
loop14 decfsz COUNT1,1
goto loop14
loop15 decfsz COUNT1,1
goto loop15
loop16 decfsz COUNT1,1
goto loop16
loop17 decfsz COUNT1,1
goto loop17
loop18 decfsz COUNT1,1
goto loop18
loop19 decfsz COUNT1,1
goto loop19
loop20 decfsz COUNT1,1
goto loop20
return
end
Subscribe to:
Posts (Atom)