N64 controller interface for the mbed.

Dependencies:   mbed

main.cpp

Committer:
igor_m
Date:
2011-03-14
Revision:
0:b9925eab1c38

File content as of revision 0:b9925eab1c38:


/*
N64 Controller Interface for the mbed. 

by Igor Martinovski 
March, 2011. 

Function Mapping (from www.mixdown.ca/n64dev/)

Bit     Function
0	    A
1	    B
2	    Z
3	    Start
4	    Directional Up
5	    Directional Down
6	    Directional Left
7	    Directional Right

8	    unknown (always 0)
9	    unknown (always 0)
10	    L
11	    R
12	    C Up
13	    C Down
14	    C Left
15	    C Right

16-23   X value (signed)

23-32   Y value (signed)

Pinout:
Looking at the controller plug, flat side down.
Pin 1 (Left)    Ground
Pin 2 (Center)  Data**
Pin 3 (Right)   +3.3V*

(*)Note: The controller is supplied by 3.6V on the N64, but it seems to work fine on
the 3.3V provided by the mbed.

(**)Warning: The N64 controller must be connected to an open drain pin with a
pull-up resistor. The line must never be driven high by the mbed! If you are not
sure how to connect the controller safely, you may damage the mbed and/or
controller. You have been warned.
*/

#include "mbed.h"
#include "stdint.h"

// Controller Commands

#define GET_STATUS          0x00
#define REQUEST_CONTROLS    0x01
#define READ_MEMPACK        0x02
#define WRITE_MEMPACK       0x03
#define READ_EEPROM         0x04
#define WRITE_EEPROM        0x05
#define RESET_CONTROLLER    0xff

#define T1                  24      // Corresponds to 1 us        
#define T2                  72      // Corresponds to 3 us

DigitalInOut inout(p14);            // Connect controller here
                                    // using 220 ohm pull-up
Serial pc(USBTX, USBRX);

uint8_t x, y;
char array[256];                    // Temp array for controller data

/* void delay(unsigned int n) is used as a short delay to
   time the bit patterns. 1 n is roughly 0.042us on 96MHz CCLK
 */
void delay(unsigned int n) {
    unsigned int i;
    for (i=0; i<n; i++)
        ;
}

/* int receive(char *data_array, unsigned char n) is used to
   receive a bit stream of bits into an array of n bytes coming
   from the controller. This must be called immediately after
   sending any kind of request to the controller
 */

int receive(char *data_array, unsigned char n) {
    unsigned char sample, previous_sample;
    unsigned char bit, byte;
    int i;

    //inout.input();                // Not sure about this..

    sample = inout.read();
    for (i=0;i < n ;i++) {
        byte = 0;
        bit  = 0;
        while (bit<8) {
            previous_sample = sample;
            sample = inout.read();
            if ((previous_sample ^ sample) & previous_sample) {

                delay(60);
                sample=inout.read();
                if (sample)
                    byte = byte  | (1<<bit);
                bit++;
            }

            data_array[i]= byte;
        }

    }
    return n;
}
/* void send_byte(unsigned char byte) is used to send a single
   byte to the controller. 
 */
void send_byte(unsigned char byte) {
    char i;
    //inout.output();           // Not sure about this.
    inout.write(1);             // Makes sure line is left high
  
    for (i=0; i<8; i++) {
        if (byte & 128>>i) {
            inout.write(0);
            delay(T1);
            inout.write(1);
            delay(T2);
        } else {
            inout.write(0);
            delay(T2);
            inout.write(1);
            delay(T1);
        }
    }
    /* Send Stop Bit */
    inout.write(0);
    delay(T1);
    inout.write(1);
    delay(T1);

}

int main() {
    inout.mode(OpenDrain);           // Must use open-drain for N64 Controller!
    
    int i;                           // Used for the bit-shifting for x and y values
    while (1) {

        send_byte(1); // Send the request byte
        receive(array, 4);           // Start receiving bit stream

        /* The for loop here is used to reverse the bits for the x and y values retured
           by the controller. I am not entirely sure of the format. I'm missing a bit
           somewhere.. Values don't range from -127..128. */
        x=y=0;
        for (i=0;i<=7;i++) {
            if (array[2] & (1 << i))
                x=x | (1 << (7-i));
            if (array[3] & (1 << i))
                y=y | (1 << (7-i));
        }

        pc.printf("%3d %3d %4d %3d \n ", array[0], array[1], (signed char)x, (signed char)y);

    }

}