PIC N64 Controller

Includes but not limited to: SNES, Genesis, Sega CD, PlayStation 1, Nintendo 64, Dreamcast, Game Gear and I guess the Virtual Boy.

Moderator: Moderators

User avatar
marshallh
Moderator
Posts: 2986
Joined: Sat Sep 10, 2005 2:17 pm
360 GamerTag: marshallh
Location: here and there
Contact:

Re: PIC N64 Controller

Post by marshallh » Sun Jan 30, 2011 11:46 pm

Neat work. Eventually I'm going to do something similar, but integrate it with other stuff on a pcb. hehe

Considered moving to an LPC or PIC32 to do controller pak support?
Image

User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Mon Jan 31, 2011 1:44 am

marshallh wrote:Neat work.
Thanks. That means a lot coming from you. To be honest even if I was using something with a bit more power I don't have the knowledge or skill to implement the crc algorithm. Not to mention optimising the maths so it could be returned fast enough. I will look into it though.

Integrate it with other stuff. Hmmm, I wonder what that could entail...

edit: After looking into it I'm having some success calculating CRCs. Trying to optimise the process atm.

User avatar
bassmasta
Posts: 684
Joined: Sun Sep 06, 2009 8:56 pm
Steam ID: randomguy737
Contact:

Re: PIC N64 Controller

Post by bassmasta » Mon Jan 31, 2011 6:45 pm

evilteddy wrote:Actually I was going to make a controller board so this could be smaller and more professional but I figured that I'd be the only one interested. I figured others may be interested in a breakout board so it would be easy to use in a portable.
Perhaps you could draw up an Eagle design and publish it to BatchPCB? Then you can get a few bucks for your work, too.
zeturi wrote:If you're getting 404'd when trying to use the links in stickies, try this tutorial to find that juicy info.

User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Mon Jan 31, 2011 7:09 pm

Actually that would require I live in the US. Anyway, I was going to use batchpcb and just let the design go up for free. I'll be doing two designs, a small board designed to fit compactly in a portable and a controller board which would be used to make a mini n64 controller. I would definitely include a rumble pack on the controller board and let others add their own rumble pack for the other board. Including a memory pack is looking increasingly possible. It seems strange that calculating the n64 crc could be as easy as it seems.

User avatar
blaze3927
Portablizer
Posts: 1114
Joined: Mon Dec 08, 2008 6:14 am
360 GamerTag: notjames
Location: Australia
Contact:

Re: PIC N64 Controller

Post by blaze3927 » Tue Feb 01, 2011 5:52 am

looks really amazing, a n64 controller that can fit in my pocket, SWEET.
and is there any particular reason you chose pic over avr?

and yes uni' cutoff's were weird this year and vacancies were so extreme (well for EE) i got into my selection with the cutoff over 20 than my atar xD
Australian Kaillera server
[url]hhttp://i56.tinypic.com/ncb0wi.gif[/url]

User avatar
lucidPerspective
Posts: 435
Joined: Fri Jun 04, 2010 10:03 pm

Re: PIC N64 Controller

Post by lucidPerspective » Tue Feb 01, 2011 6:19 am

Amazing work with this! I was just wondering when you think you will release your code/schematics? if you plan to make them available for free that is :P ..I would love to use this in my next N64p! Controller pak (memory card) support isn't essential, although it would be awesome. You got all the buttons working 100% right? Mind if I take a look at that code, and circuit? how far off till you get controller pak support do you reckon?

Again, great work, making a huge difference to N64p scene! :mrgreen:
Image

User avatar
limpport
Senior Member
Posts: 1873
Joined: Sun Jan 29, 2006 12:32 pm
Location: (the only person here from) Vermont
Contact:

Re: PIC N64 Controller

Post by limpport » Tue Feb 01, 2011 11:50 am

lucidPerspective wrote:Amazing work with this! I was just wondering when you think you will release your code/schematics? if you plan to make them available for free that is :P ..I would love to use this in my next N64p! Controller pak (memory card) support isn't essential, although it would be awesome. You got all the buttons working 100% right? Mind if I take a look at that code, and circuit? how far off till you get controller pak support do you reckon?
1st page, 4th post down :wink:

User avatar
lucidPerspective
Posts: 435
Joined: Fri Jun 04, 2010 10:03 pm

Re: PIC N64 Controller

Post by lucidPerspective » Tue Feb 01, 2011 4:12 pm

limpport wrote:1st page, 4th post down :wink:
That was the earliest stage of the code, before he actually got it all working properly (minus the mem pak) ..not something I could actually use as it is :wink:
Image

User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Wed Feb 09, 2011 11:19 pm

Tbh the reason I chose pics over avrs was that I was browsing retroactive one day and saw the cheap pic jdm programmer. I was extremely excited and by the next day I was running LED flashing programs after picking up a couple of parts from Dick Smith. I wasn't even aware back then that there was an alternative.

I was a bit sick today so while I lay in bed feeling not very creative I cleaned up the code for this on my netbook. Its still messy as hell but its commented now so you might be able to understand and use this spaghetti code. For those who are brave venture ahead but remember this way lies monsters.
Spoiler:

Code: Select all

	;This is the code for my N64 controller on a Pic16f1827 with no expansion pack capability. Due to this it may not work on some
	;games however it does work on every game I've tried so far. It uses an internal oscillator so no need to connect a crystal or
	;resonator. The joystick didn't work properly for me. That could be bad programming, poor understanding of how the N64 uses the
	;joystick or an incompatible joystick. Still it was probably equivalent in quality to a very old official N64 joystick. Anyway
	;have fun and don't blame anything bad that happens to you on me. :)
	;RA0 = x axis of pot joystick
	;RA1 = y axis of pot joystick
	;RB0 = controller line input
	;the rest of portb and porta are other buttons


	LIST p = 16f1827
	include "p16f1827.inc"
	__CONFIG 	_CONFIG1,	_FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF 
	__CONFIG    _CONFIG2,	_WRT_OFF & _PLLEN_ON & _STVREN_OFF & _BORV_19 & _LVP_OFF
	ERRORLEVEL	0,	-302

	cblock 0x20
		temp
		button1
		button2
		joystick1
		joystick2
		delay#counter
		iterate
		backup
		joywork1
		joywork2
		joycab1
		joycab2
	endc

	cblock	0xA0
		iteratesend
		tempsend
	endc

	org 0x0000
	goto	start

	org 0x0004				;interrupt is here and most likely took 3 cycles to arrive

	banksel	PORTB
	nop
	goto	$+1				;delay a bit so our first read will be in the middle of the first bit.
	
	call	record8bits		;get the command byte
	 
	movlw	0x14			;the controller responds after a couple of us
	call	delay#	

	bcf		PORTB,	0

	movlw	0x00			;we then check which command was sent
	subwf	temp,	w

	btfsc	STATUS,	Z
	call	contstatus

	movlw	0x01
	subwf	temp,	w

	btfsc	STATUS,	Z
	call	contbuttons

	movlw	0xFF			;nearly forgot this one
	subwf	temp,	w

	btfsc	STATUS,	Z
	call	contstatus

	movlw	0x02
	subwf	temp,	w

	btfsc	STATUS,	Z
	call	clear

	movlw	0x03
	subwf	temp,	w

	btfsc	STATUS,	Z
	call	clear
	
	banksel	TRISB

	movlw	0xFF
	movwf	TRISB			;All Port B are inputs

	banksel	PORTA

	bcf		INTCON, 1		;Reset the int flag
	RETFIE					;end of interrupt



start	
	banksel	TRISA

	movlw	0xFF
	movwf	TRISB			;All Port B are inputs
	movlw	0xFF
	movwf	TRISA			;All Port A are inputs

	bcf		OPTION_REG,	7	;lets pull ups be enabled
	bcf		OPTION_REG,	6	;interrupts on falling edge on RB0

	movlw	b'11110000'		;set to 8Mhz with 4x multiplier (32Mhz)
	movwf	OSCCON

	banksel	WPUB

	movlw	0xFF
	movwf	WPUB
	movwf	WPUA
	banksel	PORTA			;pull ups are on
	
	banksel	ANSELA			;the next big block of code is a quick implementation of calibrating so make sure 
	movlw	b'00000011'		;the joystick is straight when turned on (just like a normal N64 controller)
	movwf	ANSELA	
	movlw	0x00
	movwf	ANSELB

	banksel	ADCON0
	movlw	b'00000001'
	movwf	ADCON0
	movlw	b'00100000'
	movwf	ADCON1

	BSF 	ADCON0,ADGO
	BTFSC 	ADCON0,ADGO
	GOTO 	$-1
	BANKSEL ADRESH
	movfw	ADRESH

	banksel	joystick2

	movwf	joycab2

	banksel	ADCON0
	movlw	b'00000101'
	movwf	ADCON0
	movlw	b'00100000'
	movwf	ADCON1

	BSF 	ADCON0,ADGO
	BTFSC 	ADCON0,ADGO
	GOTO 	$-1
	BANKSEL ADRESH
	movfw	ADRESH

	banksel	joystick2

	movwf	joycab1
	
	banksel	TRISA

	bsf		INTCON,	7		;Turn on Interrupts
	bsf		INTCON,	4		;Turn on RB0 interrupt
	bcf		INTCON, 1		;Clearing the INT flag

	bcf		PIE1,	6		;clear ADC interrupt just in case

	banksel	PORTA

	movlw	0x00
	movwf	button1
	movwf	button2
	movwf	joystick1
	movwf	joystick2



looping	clrf	PORTB

	btfss	PORTB,	7			;c up		;these can obviously be changed and more added on the spare PORTA pins
	bsf		button2,	3					;if you were ok with using multiplexing (ideally on c buttons and d pad) you could get every button.
	btfsc	PORTB,	7
	bcf		button2,	3

	btfss	PORTB,	6			;c down
	bsf		button2,	2
	btfsc	PORTB,	6
	bcf		button2,	2

	btfss	PORTB,	5			;c left
	bsf		button2,	1
	btfsc	PORTB,	5
	bcf		button2,	1

	btfss	PORTB,	4			;start
	bsf		button1,	5
	btfsc	PORTB,	4
	bcf		button1,	5

	btfss	PORTB,	3			;Z
	bsf		button1,	5
	btfsc	PORTB,	3
	bcf		button1,	5

	btfss	PORTB,	2			;B
	bsf		button1,	6
	btfsc	PORTB,	2
	bcf		button1,	6
 
	btfss	PORTB,	1			;A
	bsf		button1,	7
	btfsc	PORTB,	1
	bcf		button1,	7
		

	banksel	ADCON0
	movlw	b'00000001'
	movwf	ADCON0
	movlw	b'00100000'
	movwf	ADCON1
	BSF 	ADCON0,ADGO
	BTFSC 	ADCON0,ADGO
	GOTO 	$-1
	BANKSEL ADRESH
	movfw	ADRESH
	banksel	joystick1
	movwf	backup
	movfw	joycab2
	subwf	backup,	w

	movwf	backup			;checking to see if the joystick is in the deadzone
	movwf	joywork1
	btfss	joywork1,	7	;if its negative then we make it positive
	goto	$+4
	comf	joywork1,	f
	movlw	0x01
	addwf	joywork1,	f		

	movlw	0x20			;adjust as desired. This is the deadzone of the joystick
	subwf	joywork1,	w
	btfsc	STATUS,	C
	goto	$+3
	movlw	0x00
	goto	$+2
	call	notdead
	
	movwf	joystick2


	banksel	ADCON0
	movlw	b'00000101'
	movwf	ADCON0
	movlw	b'00100000'
	movwf	ADCON1

	BSF 	ADCON0,ADGO
	BTFSC 	ADCON0,ADGO
	GOTO 	$-1
	BANKSEL ADRESH
	movfw	ADRESH

	banksel	joystick2
	movwf	backup
	movfw	joycab1
	subwf	backup,	f
	comf	backup
	movfw	backup

	movwf	backup			;checking to see if the joystick is in the deadzone
	movwf	joywork2
	btfss	joywork2,	7	;again the value must be positive for the > check below
	goto	$+4
	comf	joywork2,	f
	movlw	0x01
	addwf	joywork2,	f

	movlw	0x20
	subwf	joywork2,	w
	btfsc	STATUS,	C	;if clear then joystick is less than 0x20
	goto	$+3
	movlw	0x00
	goto	$+2
	call	notdead

	movwf	joystick1

	banksel	PORTB

	goto	looping


;/////////////////////////////////////////////////////////////////////////////////////////
;Start of the rest of the routines.

record8bits	movlw	0x00			;this routine records a byte from the console
	movwf	temp
	movlw	0x08
	movwf	iterate
	goto	$+3

iteraterecord	movlw	0x07
	call	delay#					;add 25 cycle delay to make the whole thing time to 32 cycles and therefore 4us
	btfsc	PORTB,	0		
	bsf	temp,	7
	rlf	temp,	f
	decfsz	iterate,	f
	goto	iteraterecord
	rlf	temp,	f
	return

contstatus	goto	$+1			;sends 5,0,2. A normal controller with no expansion inserted.
	goto	$+1
	movlw	0x05
	call	send8bits
	movlw	0x00
	call	send8bits
	movlw	0x02
	call	send8bits

	call	stopbit

	return


contbuttons	movfw	button1		;again this is fairly self explanatory
	call	send8bits
	movfw	button2
	call	send8bits
	movfw	joystick1
	call	send8bits
	movfw	joystick2
	call	send8bits

	call	stopbit
	return

clear	movlw	0x00		;In this version of the controller I haven't programmed support for memory read/writes
	call	send8bits		;for some reason a byte of garbage data seems to satisfy most games.
	return


stopbit	movlw	0x01		;I like to think the title of this is fairly self explanatory
	banksel	TRISB
	bcf		TRISB,	0
	call	delay#
	bsf		TRISB,	0
	banksel	PORTA

	return

send8bits					;again this is what the name says. Because there is no open collector on this pic I switch 
	banksel	TRISB			;between high impedance input and sinking current output.
	bcf		TRISB,	0
	movwf	tempsend
	movlw	0x07
	movwf	iteratesend
	goto	jumpin
sendloop	goto	$+1
	nop
	rlf		tempsend,	f
	bcf		TRISB,	0
	goto	$+1
	goto	$+1
	nop
jumpin	nop

	btfsc	tempsend,	7
	bsf		TRISB,	0
	movlw	0x03
	call	delay#
	nop
	bsf		TRISB,	0			
	decfsz	iteratesend,	f
	goto	sendloop
						
	goto	$+1					;last time for extra time so the concurrent bits are properly timed.
	goto	$+1
	rlf		tempsend,	f
	bcf		TRISB,	0
	goto	$+1
	goto	$+1
	goto	$+1
	btfsc	tempsend,	7
	bsf		TRISB,	0
	movlw	0x03
	call	delay#
	rlf		tempsend,	f

	bsf		TRISB,	0	

	banksel	PORTA
	return

notdead	;movfw	backup
	movlw	0x20			;this subtracts a bit from the value of the joystick so when you exit the deadzone it will give a soft value
	btfss	backup,	7		;I'm not sure if this is necessary. If you want to try without uncomment the first line and comment out everything else in this function.
	subwf	backup,	w
	btfsc	backup,	7
	addwf	backup,	w
	return

delay#	movwf	delay#counter			;function is 4 cycles for call and return, 1 cycle for setting delay#counter and 3 * w value
iter	decfsz	delay#counter,	f
	goto	iter
	return	

	end 
This is very much an on a chip design therefore the schematic is: wire 3.3V and ground to respective pins. Wire wipers of joystick to AN0 and AN1 with 3.3V and ground wired to the other pins of the joystick pots. PORTB and PORTA, 5 have weak pull ups internally so connect the buttons ones side to the pin and the other side to ground. There are no external components necessary apart from the buttons and joystick.

If anyone is interested I'm releasing this under the wtfpl.

btw the n64 crc is not as easy as it first seemed but still possible.
Last edited by evilteddy on Sun Mar 06, 2011 5:45 pm, edited 1 time in total.

User avatar
jjhammerstein
Senior Member
Posts: 1562
Joined: Tue Nov 18, 2008 7:15 pm
Location: Southern CT
Contact:

Re: PIC N64 Controller

Post by jjhammerstein » Mon Feb 14, 2011 4:07 pm

wtfpl is best pl.
GET FREE WOW GOLD SEX VISIT MODRETRO


User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Wed Feb 16, 2011 5:42 am

Image

not very tidy but I think it will work.

User avatar
lucidPerspective
Posts: 435
Joined: Fri Jun 04, 2010 10:03 pm

Re: PIC N64 Controller

Post by lucidPerspective » Wed Feb 16, 2011 5:47 am

Looking good man
Image

User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Wed Mar 16, 2011 4:30 am

Image

User avatar
lucidPerspective
Posts: 435
Joined: Fri Jun 04, 2010 10:03 pm

Re: PIC N64 Controller

Post by lucidPerspective » Wed Mar 16, 2011 5:47 am

looking good! let us know how you get on
Image

User avatar
evilteddy
Portablizer
Posts: 423
Joined: Tue Mar 25, 2008 2:11 am
360 GamerTag: Kirren of Smeg
Steam ID: kizzinator
Location: Newcastle, Australia

Re: PIC N64 Controller

Post by evilteddy » Sun Jul 17, 2011 12:04 am

Does anyone know the response of the PIF to a CRC error. It turns out that starting an eeprom read takes longer than I thought which means that the only way I can make it work is if I give a bad CRC the first time and then I can have plenty of time to read the eeprom if the n64 will just retry it. I would just try it but there's no harm in checking if anyone knows if this will work or if on the other hand I need to get a new design that's not fundamentally flawed. On a good note I've got a completely working implementation of the CRC that takes very few clock cycles.

Post Reply