NES Controller

giuseppe

Member
Hey guys. I am trying to get a 08m2 talking to an NES controller. I know it has the 4021 inside so it should be simple. However, I am not getting the expected data from the controller. The serial terminal keeps telling me that the "A" button is pushed but it is not. I double checked my connections so I think it is probably some silly code mistake or the unlikely event that the controller is bad. The pinout of the controller is here http://www.parallax.com/Portals/0/Downloads/docs/prod/compshop/NES socket_larger.jpg . My code is below:

Code:
#rem
=====================================================================================

    File........... NES Controller Test Code
    Purpose........ To demonstrate how to interface to an NES controller
    Author......... Joseph Corleto 
    E-mail......... jc269@njit.edu
    Started........ 09/03/2011
    Finished....... --/--/--
    Updated........ --/--/--
 
=====================================================================================
   Notes
=====================================================================================
- The NES controller contains one 8-bit 4021 shift register inside. 

- This register takes parallel inputs and converts them into a serial output.

- This code first latches the data and then shifts in the first bit on the data line. 
  Then it clocks and shifts in on the data line until all bits are received.
  
- What is debugged are the button states of the NES controller.

- A logical "1" means the button is not pressed. A logical "0" means the button is
  pressed.
  
- This code shifts the first bit of data into the LSB.

- The order of shifting for the buttons is shown in the table below:

				Bit# | Button   
				--------------
				  0  |   A  
				--------------
				  1  |   B  
				--------------
				  2  | Select   
				--------------
 			          3  | Start  
				--------------
				  4  |   Up  
				--------------
				  5  |  Down  
				--------------
				  6  |  Left   
				--------------
				  7  | Right   
				--------------
				
- The NES controller pinout is shown below:
	 _________
	|	       \
	| 1 O         \	1 - Ground
	|               |	2 - Clock
	| 2 O   O 7  |     3 - Latch
	|               |	4 - Data Out
	| 3 O   O 6  |	5 - No Connection
	|                  |     6 - No Connection
	| 4 O   O 5    |     7 - +5V
	|___________|
			
- This code must be used with the PICAXE 08M2 chip.

=====================================================================================
  Updates
=====================================================================================

#endrem
'====================================================================================
'  Constants
'====================================================================================
symbol bits 	= 	8		'number of bits
symbol MSBvalue 	= 	128		'MSBvalue (=128 for 8 bits, 512 for 10 bits, 
						'2048 for 12 bits)
						
'====================================================================================
'  Variables
'====================================================================================
symbol NESdata	=	b0		'holds NES button data
symbol counter	= 	b1	   	'variable used during loop
symbol mask 	=	w1		'bit masking variable
symbol var_in 	= 	w2		'data variable used during shiftin

'====================================================================================
'  Pin Declarations
'====================================================================================
'Inputs:
symbol serdata	=	pinc.1	'serial data input

'Outputs:
symbol sclk		=	c.2		'clock output
symbol latch	=	c.4		'latch output

'====================================================================================
'  Initialization
'====================================================================================
#picaxe 08m2	'tells compiler this code is used with a PICAXE 08M2 chip.

low sclk	'clock must be low before we can use the shiftin subroutine
low latch	'latch must be low before we can use the pulsout command

'====================================================================================
'  Main
'====================================================================================
Main:
pulsout latch,1				'latch the data into the NES controller's 4021
gosub Shiftin_LSB_Pre			'shift in the button data from the NES controller
let var_in = NESdata			'transfer shifted in bits to the variable NESdata

if bit0 = 1 then sertxd("A is Not Pressed",cr,lf) endif
if bit0 = 0 then sertxd("A is Pressed",cr,lf) endif
pause 500

goto Main				'go back and check the NES controller buttons again

'====================================================================================
'  Sub-Routines
'====================================================================================
' ***** Shiftin LSB first, Data Pre-Clock *****
' Shift in the data LSB first into variable var_in 
' Read data before sending clock pulse 
' Using clock output pin sclk
' Using data input pin serdata 

Shiftin_LSB_Pre:
	let var_in = 0
	for counter = 1 to bits			' number of bits
		var_in = var_in / 2 		' shift right as LSB first	
		if serdata = 0 then skipLSBPre
		var_in = var_in + MSBValue	' set MSB bit if serdata = 1
SkipLSBPre:
		pulsout sclk,1 			' pulse clock to get next data bit
	next counter
	return

Perhaps someone here has an NES controller and could give it a shot as well.
 

giuseppe

Member
Nevermind, found the bug! I had to change "let var_in = NESdata" to "let NESdata = var_in". I knew it was a silly mistake! Here is the completed test code if anyone needs it:

Code:
#rem
=====================================================================================

    File........... NES Controller Test Code
    Purpose........ To demonstrate how to interface to an NES controller
    Author......... Joseph Corleto 
    E-mail......... jc269@njit.edu
    Started........ 09/03/2011
    Finished....... --/--/--
    Updated........ --/--/--
 
=====================================================================================
   Notes
=====================================================================================
- The NES controller contains one 8-bit 4021 shift register inside. 

- This register takes parallel inputs and converts them into a serial output.

- This code first latches the data and then shifts in the first bit on the data line. 
  Then it clocks and shifts in on the data line until all bits are recieved.
  
- What is debugged are the button states of the NES controller.

- A logical "1" means the button is not pressed. A logical "0" means the button is
  pressed.
  
- This code shifts the first bit of data into the LSB.

- The order of shifting for the buttons is shown in the table below:

				Bit# | Button   
				--------------
				  0  |   A  
				--------------
				  1  |   B  
				--------------
				  2  | Select   
				--------------
 			        3  | Start  
				--------------
				  4  |   Up  
				--------------
				  5  |  Down  
				--------------
				  6  |  Left   
				--------------
				  7  | Right   
				--------------
				
- The NES controller pinout is shown below:
	 _________
	|	    \
	| 1 O      \	1 - Ground
	|           |	2 - Clock
	| 2 O   O 7 |     3 - Latch
	|           |	4 - Data Out
	| 3 O   O 6 |	5 - No Connection
	|           |     6 - No Connection
	| 4 O   O 5 |     7 - +5V
	|___________|
			
- This code must be used with the PICAXE 08M2 chip.

=====================================================================================
  Updates
=====================================================================================

#endrem
'====================================================================================
'  Constants
'====================================================================================
symbol bits 	= 	8		'number of bits
symbol MSBvalue 	= 	128		'MSBvalue (=128 for 8 bits, 512 for 10 bits, 
						'2048 for 12 bits)
						
'====================================================================================
'  Variables
'====================================================================================
symbol NESdata	=	b0		'holds NES button data
symbol counter	= 	b1	   	'variable used during loop
symbol mask 	=	w1		'bit masking variable
symbol var_in 	= 	w2		'data variable used during shiftin

'====================================================================================
'  Pin Declarations
'====================================================================================
'Inputs:
symbol serdata	=	pinc.1	'serial data input

'Outputs:
symbol sclk		=	c.2		'clock output
symbol latch	=	c.4		'latch output

'====================================================================================
'  Initialization
'====================================================================================
#picaxe 08m2	'tells compiler this code is used with a PICAXE 08M2 chip.

low sclk	'clock must be low before we can use the shiftin subroutine
low latch	;latch must be low before we can use the pulsout command

'====================================================================================
'  Main
'====================================================================================
Main:
pulsout latch,1				'latch the data into the NES controller's 4021
gosub Shiftin_LSB_Pre			'shift in the button data from the NES controller
let NESdata = var_in			'transfer shifted in bits to the variable NESdata

if bit0 = 0 then sertxd("A pressed     ",cr,lf) endif
if bit1 = 0 then sertxd("B pressed     ",cr,lf) endif
if bit2 = 0 then sertxd("Select pressed",cr,lf) endif
if bit3 = 0 then sertxd("Start pressed ",cr,lf) endif
if bit4 = 0 then sertxd("Up pressed    ",cr,lf) endif
if bit5 = 0 then sertxd("Down pressed  ",cr,lf) endif
if bit6 = 0 then sertxd("Left pressed  ",cr,lf) endif
if bit7 = 0 then sertxd("Right pressed ",cr,lf) endif

pause 50

goto Main				'go back and check the NES controller buttons again

'====================================================================================
'  Sub-Routines
'====================================================================================
' ***** Shiftin LSB first, Data Pre-Clock *****
' Shift in the data LSB first into variable var_in 
' Read data before sending clock pulse 
' Using clock output pin sclk
' Using data input pin serdata 

Shiftin_LSB_Pre:
	let var_in = 0
	for counter = 1 to bits			' number of bits
		var_in = var_in / 2 		' shift right as LSB first	
		if serdata = 0 then skipLSBPre
		var_in = var_in + MSBValue	' set MSB bit if serdata = 1
SkipLSBPre:
		pulsout sclk,1 			' pulse clock to get next data bit
	next counter
	return
 

SgtB

Member
Good work. I've been meaning to get my pair of old NES controllers working. This looks like an easy way to get going. Thanks for posting.:)
 
Top