Go Down

Topic: N64 Controller: Done reasearch, need a pros help (Read 6 times) previous topic - next topic


Jan 09, 2010, 01:22 pm Last Edit: Jan 10, 2010, 07:42 am by Waffle Reason: 1
Finally finished! It hasn't been made as 'clean & tidy' (lacking a lot of comments) as I would have liked, however it's fine for an early release and you can download and test it from here: http://arduino.pastebin.com/f286fdbc2

A couple of things you should note:
* The serial baud is 9600.
* The N64 controller's data pin should be connected to Arduino pin 9.
These settings are changeable in the sketch file, but what I've said here are the defaults in this sketch.

It was tested on my Arduino Diecimila (with upgraded ATMega328 chip) with an official Nintendo 64 controller using the Arduino 0017 software. The sketch was quickly put together just now (so hasn't undergone thorough testing), HOWEVER the n64cmd(...) function (the one that does all the hard work in sending & receiving data) has been extensively tested by myself and is fully working with my N64 controller and is even working 100% with the controller paks (I have tried it with the Rumble Pak and Transfer Pak).

The resources I have used in making this are:
Without these resources this would not have been possible!

If it works for you (fingers crossed), I can post the code that allows use of the Rumble Pak if you are interested.


lost my breadboard (d'oh!) but ran a few rudimentary tests involving my girlfriend holding wires together and still no joy, im thinking this must have something to do with my board and the atmega1280 chipset, going to try ONCE more, got some nice reliable 1k resistors (the real deal) & a new prototyping board and im going to try with a controller that i know works with the n64..... if that doesnt work im going to order the arduino mini 5V, its got the atmega168 that is included with the original Duemilanove so i cant go wrong.....i think.....


by the way is there any chance that i can get this to work with an 8mhz atmega168? cause i got a 3.3v arduino mini now i just figured it was a non-factor being that you would have to increase the delays for EVERYTHING (by a factor of two i believe?)....anyway food for though.... ive also got an ipod battery and some xbee controllers i was thinking of making it go wireless...


Jan 11, 2010, 12:03 pm Last Edit: Jan 11, 2010, 12:03 pm by Waffle Reason: 1
Yes it's probably best to try with a known working setup first. Did you get "Controller Error" messages in your serial terminal?

I don't think it's possible to make it run at 8 MHz. You don't need to increase the delays, you need to DECREASE the delays. This becomes a problem because you still need to run the code to send and receive the data, and if you need to decrease the amount of timing and there aren't any more delays left to remove, you can't remove any of the vital code making it impossible.


I had a look at the Arduino Mega pin functions and I think the pins aren't mapped to the same registers as they are on the Diecimila/Duemilanove. Can you try the sketch I posted above (without changing anything) but instead of using pin 9 on the Arduino, can you try pin 52? I think pin 9 on my Arduino is pin 52 on yours.


ill try it out! in the meantime im ordering an arduino mini 5v 16mhz with an atmega328, im going to use a 3.7v ipod battery to power the device and the controller and two xbee controllers to send and recieve the signal...what do you think? i was going to try it with this hacked together RF setup someone else had used but i figured better go with the tried and true xbee protocol before adding more variables into an already f**ked situation haha :)


It must be the data pin, but not luck on 52, where do you find this pinout information for the arduinomega?


Jan 12, 2010, 10:20 am Last Edit: Jan 12, 2010, 10:20 am by Waffle Reason: 1
I've never used the Xbees before so not sure how they work. But assuming you'll have a microcontroller at each end then it should work.

As for the pinout information, I opened up the file: arduino-0017\hardware\cores\arduino\pins_arduino.c
Not sure how it works, maybe you can make some sense out of it. It would be much easier if I had an Arduino Mega.


is the pinout much different between the at168 and the 328 (i might have those exact numbers wrong). because i oredered a 16 mhz arduino mini today maybe it would be wise to wait for that to come.... in the meantime ill take a look at that file mentioned.

again, thanks for all the help waffle


Jan 12, 2010, 07:01 pm Last Edit: Jan 12, 2010, 07:04 pm by dashdanw Reason: 1
ah yes, i think i found the atmega pinout under /hardware/cores/atmega8/pins_atmega8

wish me luck! haha

also i tested the controller in the nintendo 64, 100 percent working

im sure the answer is in THIS code:

Code: [Select]

#define NUM_PINS 28
#define NUM_PORTS 4

#define PB 2
#define PC 3
#define PD 4

int port_to_mode[NUM_PORTS + 1] = {

int port_to_output[NUM_PORTS + 1] = {

int port_to_input[NUM_PORTS + 1] = {

pin_t digital_pin_to_port_array[] = {
     { NOT_A_PIN, NOT_A_PIN },
     { PC, 6 },
     { PD, 0 },
     { PD, 1 },
     { PD, 2 },
     { PD, 3 },
     { PD, 4 },
     { NOT_A_PIN, NOT_A_PIN },
     { NOT_A_PIN, NOT_A_PIN },
     { PB, 6 },
     { PB, 7 },
     { PD, 5 },
     { PD, 6 },
     { PD, 7 },
     { PB, 0 },
     { PB, 1 },
     { PB, 2 },
     { PB, 3 },
     { PB, 4 },
     { PB, 5 },
     { NOT_A_PIN, NOT_A_PIN },
     { NOT_A_PIN, NOT_A_PIN },
     { NOT_A_PIN, NOT_A_PIN },
     { PC, 0 },
     { PC, 1 },
     { PC, 2 },
     { PC, 3 },
     { PC, 4 },
     { PC, 5 },

pin_t *digital_pin_to_port = digital_pin_to_port_array;
pin_t *analog_in_pin_to_port = digital_pin_to_port_array;
pin_t *analog_out_pin_to_port = digital_pin_to_port_array;

let me know if you can shed any light.... im mulling through it myself


also there are two includes listed, avr/io.h and wiring.h

heres wiring.h, couldnt locate avr/io.h

Code: [Select]
 wiring.h - Partial implementation of the Wiring API for the ATmega8.
 Part of Arduino - http://www.arduino.cc/

 Copyright (c) 2005-2006 David A. Mellis

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General
 Public License along with this library; if not, write to the
 Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 Boston, MA  02111-1307  USA

 $Id: wiring.h 602 2009-06-01 08:32:11Z dmellis $

#ifndef Wiring_h
#define Wiring_h

#include <avr/io.h>
#include "binary.h"

#ifdef __cplusplus
extern "C"{

#ifndef ARDUINO
#define ARDUINO 16

#define HIGH 0x1
#define LOW  0x0

#define INPUT 0x0
#define OUTPUT 0x1

#define true 0x1
#define false 0x0

#define PI 3.1415926535897932384626433832795
#define HALF_PI 1.5707963267948966192313216916398
#define TWO_PI 6.283185307179586476925286766559
#define DEG_TO_RAD 0.017453292519943295769236907684886
#define RAD_TO_DEG 57.295779513082320876798154814105

#define SERIAL  0x0
#define DISPLAY 0x1

#define LSBFIRST 0
#define MSBFIRST 1

#define CHANGE 1
#define FALLING 2
#define RISING 3

#define INTERNAL 3
#define DEFAULT 1
#define EXTERNAL 0

// undefine stdlib's abs if encountered
#ifdef abs
#undef abs

#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
#define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define radians(deg) ((deg)*DEG_TO_RAD)
#define degrees(rad) ((rad)*RAD_TO_DEG)
#define sq(x) ((x)*(x))

#define interrupts() sei()
#define noInterrupts() cli()

#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L )
#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() )
#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() )

#define lowByte(w) ((uint8_t) ((w) & 0xff))
#define highByte(w) ((uint8_t) ((w) >> 8))

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))

typedef unsigned int word;

#define bit(b) (1UL << (b))

typedef uint8_t boolean;
typedef uint8_t byte;

void init(void);

void pinMode(uint8_t, uint8_t);
void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogReference(uint8_t mode);
void analogWrite(uint8_t, int);

void beginSerial(long);
void serialWrite(unsigned char);
int serialAvailable(void);
int serialRead(void);
void serialFlush(void);

unsigned long millis(void);
unsigned long micros(void);
void delay(unsigned long);
void delayMicroseconds(unsigned int us);
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout);

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val);

void attachInterrupt(uint8_t, void (*)(void), int mode);
void detachInterrupt(uint8_t);

void setup(void);
void loop(void);

#ifdef __cplusplus
} // extern "C"



The pin out on the 168 and 328 is exactly the same. I don't know what the purpose of /hardware/cores/atmega8/pins_atmega8.c is, but arduino-0017\hardware\cores\arduino\pins_arduino.c has the pin mapping in the 'digital_pin_to_port_PGM' variable.


ive been researching a few cheap wireless ideas, someone reccomend i look into the tr24a wireless tranciever, ($4 per) but cant seem to get much documentation about it, probably the cheapest alternative to the xbee.....also this one looks promising http://www.glacialwanderer.com/hobbyrobotics/?p=291 alot of documentation the only problem is that it would require a mcu at both ends, putting the cost of the trasmitter at 35 dollars (arduinomini:$20+liion battery:$9+transmitter:$4.5) and the reciever at $25(arduino mini:$20+reciever:$4.5).....although i guess i could just use the atmega328 itself and put it on a dev board?



I think you'll an MCU at both ends. The controller protocol has strict timing and I don't think it would cope with the delays when being sent over wireless. With an MCU at both ends you could read the controller and then send it to other MCU in a format that's safe for wireless transfer. Or it might just be easier to get a wireless controller to start with (like the Gamecube's Wavebird)?


yes also i was thinking, is there any extra processing that would be needed on the controller side in order to process the signal for sending? im ordering a 20mhz 168 and a 16mhz crystal tonight, much cheaper than buying the arduino itself, going to try to get the project working with that, and also ordering an rf transmitter and reciever, as listed in that guide, got a prototype board i can lay into with some wire cutters and make a nice small pinout for the IC, but is it going to be more complicated than just using the rf transmitter on the correct pins? or is all of the signal processing done on the recievers end....

Go Up