N64 to USB HID interface

Dependencies:   mbed

main.cpp

Committer:
igor_m
Date:
2011-09-25
Revision:
0:547c5459faa6
Child:
1:38815edb0ecb

File content as of revision 0:547c5459faa6:


/*
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"
#include "usbhid.h"


USBJoystick joystick;


/*
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;
union controls { /* A definition and a declaration */
    uint8_t array[4];
    uint32_t result_32;
} controls;

// 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(uint8_t *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;
        }

    }
     /* 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 (controls.array[2] & (1 << i))
                x=x | (1 << (7-i));
            if (controls.array[3] & (1 << i))
                y=y | (1 << (7-i));
        }
        data_array[2]=x;
        data_array[3]=y;
    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

    wait_us(500);
    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!

    uint32_t i, previous_result=0;                           // Used for the bit-shifting for x and y values
    send_byte(RESET_CONTROLLER);
              wait_ms(10);
    while (1) {
        wait_ms(10);
        previous_result=controls.result_32;
        send_byte(1);                // Send the request byte
        receive(controls.array, 4);           // Start receiving bit stream
        
        if (controls.result_32==previous_result) continue;
        
        
        pc.printf("%3d %3d %d %d\n ", controls.array[0], controls.array[1], (int8_t)controls.array[2], (int8_t)controls.array[3]);
        //pc.printf("%d\n",controls.result_32);
//joystick.joystick(controls.array[0],controls.array[1], controls.array[2], controls.array[3]);
    }

}