Custom made controller for NES

Discuss hardware-related topics, such as development cartridges, CopyNES, PowerPak, EPROMs, or whatever.

Moderators: B00daW, Moderators

User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Custom made controller for NES

Post by electro »

I made this custom controller for the NES a couple of months ago. It's made out of PVC and I use a pic microcontroller that reads touch sensor presses and sends data out to a shift register. The same kind of shift register used in the NES gamepad.

I didn't want to destroy gamepads to use their plugs so I decided to just add a few rca jacks in the back of the NES. Those rca jack just connect to the appropriate pins of the gamepad port.

Here's the YouTube video: http://www.youtube.com/watch?v=Bgkh00sHR5c

The code for the cart I made (called Super Synth Drums), is a very simple program that was mostly given to me in the the "newbie" section of this forum. Most of the code is there if anyone wants to see it. It was begun mainly as a lesson, learning about NES programming. So it was in all respects a "newbies" program. The custom controller is really what makes it fun.

Here's a descriptive image of the controller, called the DrumAxe.
http://electrokraft.com/images/drumaxe_detail_info.jpg

I sold some of the carts on ebay and my website, donating a percentage to a Hunger charity called Action Against Hunger, and also the St. Jude Children's Hospital.

Tony
Nessie
Posts: 134
Joined: Mon Sep 20, 2004 11:13 am
Location: Sweden
Contact:

Post by Nessie »

Wow, that's really cool!
Perhaps somebody could write a Guitar Hero clone - it would be so awesome to play the downhill guitar solo in "Ski or Die" on your DrumAxe! :)
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

Thanks.

Tony
User avatar
MottZilla
Posts: 2835
Joined: Wed Dec 06, 2006 8:18 pm

Post by MottZilla »

That's pretty nifty. Quite an invention.
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

Thanks. I have a little more experience in hardware than in programming (just a beginner in NES programming).

The circuit is a pic microcontroller that is detecting the senors, and then outputting to a shift register. Same shift register used in the NES gamepad.

While experimenting I also came up with a musical sequencer circuit and a guitar input circuit that triggered the percussion sounds when you played a note on the guitar. Haven't really developed those things, maybe in future.
cd_vision
Posts: 52
Joined: Thu Jul 27, 2006 8:05 pm

Post by cd_vision »

Yes, yes, but how will this help improve my score in Zelda?
User avatar
Zepper
Formerly Fx3
Posts: 3264
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Post by Zepper »

Interesting device. Ok, so it plays drums (noise chan), but since there's only one chan, samples don't overlap. You can output the drums to any other channel by using a few tricks.

Do you think about adding a guitar-style effect with the square waves? It gives me a lot of ideas... but I don't know how you planned the input system, and even if the use of squares would be good.
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

Yes, the cart is very rudimentary. There could be much more you can do. I'm not a programmer, just beginner with NES programming.

I haven't yet tried the other channels to get polyphony. Polyphony is the goal.

I was also ready to add more touch sensors and more sounds.

It's really just 6 touch sensors, a pic microcontroller and a shift register, that's all.

If anyone wants to contribute some more to this just let me know. I would like to make an improved cart, donate a percentage. For me it would be more of an education in programming.

I will re-post my simple program again here if anyone would like to slowly, and stepwise enhance it so that it would also be educational for us newbies.
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

So I guess each sensor is mapped to an NES button, right? If you tell us how they're mapped, we could write some interesting apps for it.
User avatar
baisoku
Posts: 121
Joined: Thu Nov 11, 2004 5:30 am
Location: San Francisco, CA
Contact:

Post by baisoku »

Hah, the device looks a lot like a potato cannon i made out of seemingly very similar PVC components. :)
...patience...
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

tepples wrote:So I guess each sensor is mapped to an NES button, right? If you tell us how they're mapped, we could write some interesting apps for it.
That's right. You can also just use the gamepads instead. Gamepad #2 just adds the looping/pulsing effect.

I'll post the code in the newbie section so that whatever might be added/modified or enhanced can be learned by us beginners.

Thanks,
T
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

Here is the code. It's very simple since I am just a beginner with NES programming.

If anyone wants to do anything to it, I thought we can repost this code in the newbie section and continue "stepwise" so the changes, enhancements, mods to the code can be taught to newbies like me.

My custom controller, the DrumAxe just replaces one of the gamepads, each sensor on the DrumAxe corresponds to a button on gamepad #1. Gamepad #2 can be used to create pulsing effects.

Would be nice to explore the other sound channels. I'm not claiming any exclusive rights to any of this code. Most of this code was spoon fed to me in the newbie section back in Feb-April. If no one has any objections, I'm humbly proposing that it can be shared and used as anyone wishes, freely open.

If anyone wants details of the DrumAxe circuit let me know, it's really a simple device.

(I will also post this in the newbie section, and we'll continue the thread there, instead of here.)

Code: Select all

;Nes Gamepad demo program 4/28/08
;-------------------

; INES header setup


	.inesprg 1
	.ineschr 0	; zero because we don't have character data
	.inesmir 1
	.inesmap 0  

	.bank 1
	.org $FFFA
	.dw 0 		; NMI routine
	.dw start 	; Reset routine
	.dw 0           ; IRQ routine

	.bank 0
	.org $8000

start:

key_a		EQU	%00000001 ; A button press 
key_b		EQU 	%00000010 ; B 
key_select  	EQU 	%00000100 ; select 
key_start  	EQU 	%00001000 ; start 
key_up  	EQU 	%00010000 ; up arrow 
key_down  	EQU 	%00100000 ; down 
key_left  	EQU 	%01000000 ; left arrow 
key_right  	EQU 	%10000000 ; right


ab_pressed	EQU	%00000011 ; A and B are pressed 
			
button_state    EQU     $00
button_state2	EQU	$0F


    sei        ; ignore IRQs
    cld        ; disable decimal mode
    ldx #$40
    stx $4017  ; disable APU frame IRQ
    ldx #$ff
    txs        ; Set up stack
    inx        ; now X = 0
    stx $2000  ; disable NMI
    stx $2001  ; disable rendering
    stx $4010  ; disable DMC IRQs

vblankwait1:  
    bit $2002
    bpl vblankwait1

    ; We now have about 30,000 cycles to burn before the PPU stabilizes.
    ; Use it to clear RAM.  X is still 0...
    txa
clrmem:		; this is for the video stuff
    sta $000,x
    sta $100,x
    sta $200,x
    sta $300,x
    sta $400,x
    sta $500,x
    sta $600,x
    sta $700,x  ; Remove this if you're storing reset-persistent data
    inx
    bne clrmem
   
vblankwait2:
    bit $2002
    bpl vblankwait2


; *** CLEAR SOUND REGISTERS ***
	

	lda #$00		; clear all the sound registers by setting
	ldx #$00		; everything to 0 in the Clear_Sound loop
Clear_Sound:
	sta $4000,x		; store accumulator at $4000 offset by x
	inx			; increment x
	cpx #$0F		; compare x to $0F
	bne Clear_Sound		; branch back to Clear_Sound if x != $0F

	lda #$10		; load accumulator with $10
	sta $4010		; store accumulator in $4010
	lda #$00		; load accumulator with 0
	sta $4011		; clear these 3 registers that are 
	sta $4012		; associated with the delta modulation
	sta $4013		; channel of the NES



loop: 
   jsr updatejoy

   ;Check the state of the right key 
   lda button_state 
   and #key_right 
   beq right_not_pressed 
   jsr right_is_pressed 


right_not_pressed: 
    
   ;Check the state of the left button 
   lda button_state 
   and #key_left 
   beq left_not_pressed 
   jsr left_is_pressed 

left_not_pressed:

   ;Check the state of the up arrow
   lda button_state
   and #key_up
   beq up_not_pressed
   jsr up_is_pressed

up_not_pressed:

   ;Check the state of the downss arrow
   lda button_state
   and #key_down
   beq down_not_pressed
   jsr down_is_pressed

down_not_pressed:


   ;Check if A and B are pressed
   lda button_state

   AND #$03  ; mask out A+B bits
   CMP #$03  ; see if it equals A+B
   BNE ab_not_pressed 
   
   jsr ab_is_pressed

ab_not_pressed: 

   ;Check if A is pressed
   lda button_state
   AND #key_a  ; mask out bits
   BEQ a_not_pressed 
   jsr a_is_pressed

a_not_pressed:

   ;Check if b button is pressed
   lda button_state
   and #key_b
   beq b_not_pressed
   jsr b_is_pressed

b_not_pressed:	


   ;Check if select button is pressed
   lda button_state
   and #key_select
   beq select_not_pressed
   jsr select_is_pressed


select_not_pressed:



   ;Check if start button is pressed
   lda button_state
   and #key_start
   beq start_not_pressed
   jsr start_is_pressed


start_not_pressed:



  ;Check State of Right Button of Joypad #2
   lda button_state2 
   and #key_right 
   beq right_not_pressed_2 
   jsr right_is_pressed_2 




right_not_pressed_2:


   ;check state of A button of joypad #2
   lda button_state2
   AND #key_a  ; mask out bits
   BEQ a_not_pressed_2 
   jsr a_is_pressed_2

a_not_pressed_2:   




   ;Check state of b button on joypad #2
   lda button_state2
   and #key_b
   beq b_not_pressed_2
   jsr b_is_pressed_2



b_not_pressed_2:	


	
   ;Check the state of the left button of joypad #2 
   lda button_state2 
   and #key_left 
   beq left_not_pressed_2 
   jsr left_is_pressed_2 

left_not_pressed_2:

   ;Check the state of the up arrow of joypad #2
   lda button_state2
   and #key_up
   beq up_not_pressed_2
   jsr up_is_pressed_2

up_not_pressed_2:

   ;Check the state of the up arrow of joypad #3
   lda button_state2
   and #key_down
   beq down_not_pressed_2
   jsr down_is_pressed_2

down_not_pressed_2:



   ;Check if select button is pressed
   lda button_state2
   and #key_select
   beq select_not_pressed_2
   jsr select_is_pressed_2


select_not_pressed_2:



   jmp loop ;Go back and keep reading the joypad forever 


updatejoy:

    LDA #1 		  ; strobe joypad 1 
    STA $4016 
    LDA #0 
    STA $4016

    LDX #$08             ; set X to 8 (the number of times we want to loop, once fo each button) 
    


joybuttons: 
    
    LDA $4016            ; get button state 
    LSR A                ; shift it into the C flag 
    ROR button_state     ; rotate C flag into our button_state variable 

    
    DEX                  ; decrement X (our loop counter) 
    BNE joybuttons       ; jump back to our loop until X is zero 
   

	; Begin reading joypad #2 and store bits in button_state2 variable.


    LDY #$08

joybuttons2:

    LDA $4017            ; get button state 
    LSR A                ; shift it into the C flag 
    ROR button_state2    ; rotate C flag into our button_state variable 

    
    DEY                  ; decrement X (our loop counter) 
    BNE joybuttons2      ; jump back to our loop until Y is zero 


    rts
		

   
 
right_is_pressed: ; play sound when right arrow is pressed.


        lda #$0F   	 ; Enable channels
	sta $4015
	
	
	lda #%00111101   ; mode, period
	sta $400E

	lda #%0000000    ; duration
	sta $400F

	

	rts
	

	
left_is_pressed:


	lda #$0F   	 ; Enable channels
	sta $4015
	
		
	lda #%00010101   ; mode, period
	sta $400E

	lda #%10000000   ; duration
	sta $400F

        rts



up_is_pressed:



	lda #$0F   	 ; Enable channels
	sta $4015
	
		
	lda #%00111111   ; mode, period  low rumble
	sta $400E

	lda #%0000000    ; duration
	sta $400F


	rts


down_is_pressed:


	lda #$0F   	 ; Enable channels
	sta $4015
	
			
	lda #%00111110   ; mode, period
	sta $400E

	lda #%11111000   ; duration
	sta $400F

       
	
	rts



a_is_pressed:


	lda #$0F   	 ; Enable channels
	sta $4015
	
	
	lda #%00010111   ; mode, period
	sta $400E

	lda #%10000000   ; duration
	sta $400F
	
        
		

	rts




b_is_pressed: 


	lda #$0F   	 ; Enable channels
	sta $4015
	
		
	lda #%01011011   ; mode, period  low rumble
	sta $400E

	lda #%00000000    ; duration
	sta $400F

    
	      

        rts



select_is_pressed:



	lda #$0F   	 ; Enable channels
	sta $4015
	

	lda #%10111011   ; mode, period
	sta $400E

	lda #%10101111    ; duration
	sta $400F


	rts


start_is_pressed:


	lda #$0F   	 ; Enable channels
	sta $4015
	
			
	lda #%11000011   ; mode, period
	sta $400E


	lda #%10101001   ; duration
	sta $400F


	rts


ab_is_pressed:


	rts




	;JoyPad #2 subroutines below

	


right_is_pressed_2:



	lda #$0F   	 ; Enable channels
	sta $4015
	
	lda #%00100011   ; enable medium looping with a 1 at bit 5
	sta $400C


	rts







left_is_pressed_2:



	lda #$0F   	 ; Enable channels
	sta $4015
	
	lda #%00100111   ; enable medium/slow looping with a 1 at bit 5
	sta $400C



	rts


up_is_pressed_2:



	lda #$0F   	 ; Enable channels
	sta $4015
	
	lda #%00100001   ; enable fast looping with a 1 at bit 5
	sta $400C


	rts



down_is_pressed_2:



	lda #$0F   	 ; Enable channels
	sta $4015
	
	lda #%00101111   ; enable slow looping
	sta $400C


	rts




a_is_pressed_2:



	rts




b_is_pressed_2:



	rts




start_is_pressed_2:



	rts



select_is_pressed_2:


	jsr start	 ; Resets sound to the beginning, clears sound registers:(Stops the volume decay loop).	
	
	rts

User avatar
BMF54123
Posts: 410
Joined: Mon Aug 28, 2006 2:52 am
Contact:

Post by BMF54123 »

I should probably mention that this thread inspired me to make a "buzzer" system for a 4-player trivia/challenge game (currently a hack of SMB2, believe it or not). It basically consists of 4 buttons jammed into plastic tubes, all wired to the guts of an NES controller (one button for each direction). Not an incredibly complex device, but neat nonetheless. :)
User avatar
electro
Posts: 132
Joined: Tue Jan 29, 2008 11:12 am
Location: New York

Post by electro »

That sounds interesting. Hopefully we can expand on this and come up with more stuff.
User avatar
Banshaku
Posts: 2404
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Post by Banshaku »

BMF54123 wrote:I should probably mention that this thread inspired me to make a "buzzer" system for a 4-player trivia/challenge game (currently a hack of SMB2, believe it or not). It basically consists of 4 buttons jammed into plastic tubes, all wired to the guts of an NES controller (one button for each direction). Not an incredibly complex device, but neat nonetheless. :)
I remember in Japan seeing a famicom trivia game that had a game pad which was a single button for every player. The button were all independant square boxes with one big red button on each. Have you ever seen it?
Post Reply