Page 1 of 2
Custom made controller for NES
Posted: Tue Jul 22, 2008 9:42 am
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
Posted: Tue Jul 22, 2008 1:03 pm
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!

Posted: Tue Jul 22, 2008 1:24 pm
by electro
Thanks.
Tony
Posted: Tue Jul 22, 2008 1:46 pm
by MottZilla
That's pretty nifty. Quite an invention.
Posted: Tue Jul 22, 2008 2:03 pm
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.
Posted: Tue Jul 22, 2008 2:25 pm
by cd_vision
Yes, yes, but how will this help improve my score in Zelda?
Posted: Tue Jul 22, 2008 6:29 pm
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.
Posted: Tue Jul 22, 2008 6:53 pm
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.
Posted: Tue Jul 22, 2008 7:50 pm
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.
Posted: Tue Jul 22, 2008 7:56 pm
by baisoku
Hah, the device looks a lot like a potato cannon i made out of seemingly very similar PVC components.

Posted: Wed Jul 23, 2008 6:28 am
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
Posted: Thu Jul 24, 2008 1:24 pm
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
Posted: Thu Jul 24, 2008 6:22 pm
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.

Posted: Thu Jul 24, 2008 7:35 pm
by electro
That sounds interesting. Hopefully we can expand on this and come up with more stuff.
Posted: Thu Jul 24, 2008 7:49 pm
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?