N64 controller interface for the mbed.

Dependencies:   mbed

Committer:
igor_m
Date:
Mon Mar 14 04:38:59 2011 +0000
Revision:
0:b9925eab1c38
Rev. 0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
igor_m 0:b9925eab1c38 1
igor_m 0:b9925eab1c38 2 /*
igor_m 0:b9925eab1c38 3 N64 Controller Interface for the mbed.
igor_m 0:b9925eab1c38 4
igor_m 0:b9925eab1c38 5 by Igor Martinovski
igor_m 0:b9925eab1c38 6 March, 2011.
igor_m 0:b9925eab1c38 7
igor_m 0:b9925eab1c38 8 Function Mapping (from www.mixdown.ca/n64dev/)
igor_m 0:b9925eab1c38 9
igor_m 0:b9925eab1c38 10 Bit Function
igor_m 0:b9925eab1c38 11 0 A
igor_m 0:b9925eab1c38 12 1 B
igor_m 0:b9925eab1c38 13 2 Z
igor_m 0:b9925eab1c38 14 3 Start
igor_m 0:b9925eab1c38 15 4 Directional Up
igor_m 0:b9925eab1c38 16 5 Directional Down
igor_m 0:b9925eab1c38 17 6 Directional Left
igor_m 0:b9925eab1c38 18 7 Directional Right
igor_m 0:b9925eab1c38 19
igor_m 0:b9925eab1c38 20 8 unknown (always 0)
igor_m 0:b9925eab1c38 21 9 unknown (always 0)
igor_m 0:b9925eab1c38 22 10 L
igor_m 0:b9925eab1c38 23 11 R
igor_m 0:b9925eab1c38 24 12 C Up
igor_m 0:b9925eab1c38 25 13 C Down
igor_m 0:b9925eab1c38 26 14 C Left
igor_m 0:b9925eab1c38 27 15 C Right
igor_m 0:b9925eab1c38 28
igor_m 0:b9925eab1c38 29 16-23 X value (signed)
igor_m 0:b9925eab1c38 30
igor_m 0:b9925eab1c38 31 23-32 Y value (signed)
igor_m 0:b9925eab1c38 32
igor_m 0:b9925eab1c38 33 Pinout:
igor_m 0:b9925eab1c38 34 Looking at the controller plug, flat side down.
igor_m 0:b9925eab1c38 35 Pin 1 (Left) Ground
igor_m 0:b9925eab1c38 36 Pin 2 (Center) Data**
igor_m 0:b9925eab1c38 37 Pin 3 (Right) +3.3V*
igor_m 0:b9925eab1c38 38
igor_m 0:b9925eab1c38 39 (*)Note: The controller is supplied by 3.6V on the N64, but it seems to work fine on
igor_m 0:b9925eab1c38 40 the 3.3V provided by the mbed.
igor_m 0:b9925eab1c38 41
igor_m 0:b9925eab1c38 42 (**)Warning: The N64 controller must be connected to an open drain pin with a
igor_m 0:b9925eab1c38 43 pull-up resistor. The line must never be driven high by the mbed! If you are not
igor_m 0:b9925eab1c38 44 sure how to connect the controller safely, you may damage the mbed and/or
igor_m 0:b9925eab1c38 45 controller. You have been warned.
igor_m 0:b9925eab1c38 46 */
igor_m 0:b9925eab1c38 47
igor_m 0:b9925eab1c38 48 #include "mbed.h"
igor_m 0:b9925eab1c38 49 #include "stdint.h"
igor_m 0:b9925eab1c38 50
igor_m 0:b9925eab1c38 51 // Controller Commands
igor_m 0:b9925eab1c38 52
igor_m 0:b9925eab1c38 53 #define GET_STATUS 0x00
igor_m 0:b9925eab1c38 54 #define REQUEST_CONTROLS 0x01
igor_m 0:b9925eab1c38 55 #define READ_MEMPACK 0x02
igor_m 0:b9925eab1c38 56 #define WRITE_MEMPACK 0x03
igor_m 0:b9925eab1c38 57 #define READ_EEPROM 0x04
igor_m 0:b9925eab1c38 58 #define WRITE_EEPROM 0x05
igor_m 0:b9925eab1c38 59 #define RESET_CONTROLLER 0xff
igor_m 0:b9925eab1c38 60
igor_m 0:b9925eab1c38 61 #define T1 24 // Corresponds to 1 us
igor_m 0:b9925eab1c38 62 #define T2 72 // Corresponds to 3 us
igor_m 0:b9925eab1c38 63
igor_m 0:b9925eab1c38 64 DigitalInOut inout(p14); // Connect controller here
igor_m 0:b9925eab1c38 65 // using 220 ohm pull-up
igor_m 0:b9925eab1c38 66 Serial pc(USBTX, USBRX);
igor_m 0:b9925eab1c38 67
igor_m 0:b9925eab1c38 68 uint8_t x, y;
igor_m 0:b9925eab1c38 69 char array[256]; // Temp array for controller data
igor_m 0:b9925eab1c38 70
igor_m 0:b9925eab1c38 71 /* void delay(unsigned int n) is used as a short delay to
igor_m 0:b9925eab1c38 72 time the bit patterns. 1 n is roughly 0.042us on 96MHz CCLK
igor_m 0:b9925eab1c38 73 */
igor_m 0:b9925eab1c38 74 void delay(unsigned int n) {
igor_m 0:b9925eab1c38 75 unsigned int i;
igor_m 0:b9925eab1c38 76 for (i=0; i<n; i++)
igor_m 0:b9925eab1c38 77 ;
igor_m 0:b9925eab1c38 78 }
igor_m 0:b9925eab1c38 79
igor_m 0:b9925eab1c38 80 /* int receive(char *data_array, unsigned char n) is used to
igor_m 0:b9925eab1c38 81 receive a bit stream of bits into an array of n bytes coming
igor_m 0:b9925eab1c38 82 from the controller. This must be called immediately after
igor_m 0:b9925eab1c38 83 sending any kind of request to the controller
igor_m 0:b9925eab1c38 84 */
igor_m 0:b9925eab1c38 85
igor_m 0:b9925eab1c38 86 int receive(char *data_array, unsigned char n) {
igor_m 0:b9925eab1c38 87 unsigned char sample, previous_sample;
igor_m 0:b9925eab1c38 88 unsigned char bit, byte;
igor_m 0:b9925eab1c38 89 int i;
igor_m 0:b9925eab1c38 90
igor_m 0:b9925eab1c38 91 //inout.input(); // Not sure about this..
igor_m 0:b9925eab1c38 92
igor_m 0:b9925eab1c38 93 sample = inout.read();
igor_m 0:b9925eab1c38 94 for (i=0;i < n ;i++) {
igor_m 0:b9925eab1c38 95 byte = 0;
igor_m 0:b9925eab1c38 96 bit = 0;
igor_m 0:b9925eab1c38 97 while (bit<8) {
igor_m 0:b9925eab1c38 98 previous_sample = sample;
igor_m 0:b9925eab1c38 99 sample = inout.read();
igor_m 0:b9925eab1c38 100 if ((previous_sample ^ sample) & previous_sample) {
igor_m 0:b9925eab1c38 101
igor_m 0:b9925eab1c38 102 delay(60);
igor_m 0:b9925eab1c38 103 sample=inout.read();
igor_m 0:b9925eab1c38 104 if (sample)
igor_m 0:b9925eab1c38 105 byte = byte | (1<<bit);
igor_m 0:b9925eab1c38 106 bit++;
igor_m 0:b9925eab1c38 107 }
igor_m 0:b9925eab1c38 108
igor_m 0:b9925eab1c38 109 data_array[i]= byte;
igor_m 0:b9925eab1c38 110 }
igor_m 0:b9925eab1c38 111
igor_m 0:b9925eab1c38 112 }
igor_m 0:b9925eab1c38 113 return n;
igor_m 0:b9925eab1c38 114 }
igor_m 0:b9925eab1c38 115 /* void send_byte(unsigned char byte) is used to send a single
igor_m 0:b9925eab1c38 116 byte to the controller.
igor_m 0:b9925eab1c38 117 */
igor_m 0:b9925eab1c38 118 void send_byte(unsigned char byte) {
igor_m 0:b9925eab1c38 119 char i;
igor_m 0:b9925eab1c38 120 //inout.output(); // Not sure about this.
igor_m 0:b9925eab1c38 121 inout.write(1); // Makes sure line is left high
igor_m 0:b9925eab1c38 122
igor_m 0:b9925eab1c38 123 for (i=0; i<8; i++) {
igor_m 0:b9925eab1c38 124 if (byte & 128>>i) {
igor_m 0:b9925eab1c38 125 inout.write(0);
igor_m 0:b9925eab1c38 126 delay(T1);
igor_m 0:b9925eab1c38 127 inout.write(1);
igor_m 0:b9925eab1c38 128 delay(T2);
igor_m 0:b9925eab1c38 129 } else {
igor_m 0:b9925eab1c38 130 inout.write(0);
igor_m 0:b9925eab1c38 131 delay(T2);
igor_m 0:b9925eab1c38 132 inout.write(1);
igor_m 0:b9925eab1c38 133 delay(T1);
igor_m 0:b9925eab1c38 134 }
igor_m 0:b9925eab1c38 135 }
igor_m 0:b9925eab1c38 136 /* Send Stop Bit */
igor_m 0:b9925eab1c38 137 inout.write(0);
igor_m 0:b9925eab1c38 138 delay(T1);
igor_m 0:b9925eab1c38 139 inout.write(1);
igor_m 0:b9925eab1c38 140 delay(T1);
igor_m 0:b9925eab1c38 141
igor_m 0:b9925eab1c38 142 }
igor_m 0:b9925eab1c38 143
igor_m 0:b9925eab1c38 144 int main() {
igor_m 0:b9925eab1c38 145 inout.mode(OpenDrain); // Must use open-drain for N64 Controller!
igor_m 0:b9925eab1c38 146
igor_m 0:b9925eab1c38 147 int i; // Used for the bit-shifting for x and y values
igor_m 0:b9925eab1c38 148 while (1) {
igor_m 0:b9925eab1c38 149
igor_m 0:b9925eab1c38 150 send_byte(1); // Send the request byte
igor_m 0:b9925eab1c38 151 receive(array, 4); // Start receiving bit stream
igor_m 0:b9925eab1c38 152
igor_m 0:b9925eab1c38 153 /* The for loop here is used to reverse the bits for the x and y values retured
igor_m 0:b9925eab1c38 154 by the controller. I am not entirely sure of the format. I'm missing a bit
igor_m 0:b9925eab1c38 155 somewhere.. Values don't range from -127..128. */
igor_m 0:b9925eab1c38 156 x=y=0;
igor_m 0:b9925eab1c38 157 for (i=0;i<=7;i++) {
igor_m 0:b9925eab1c38 158 if (array[2] & (1 << i))
igor_m 0:b9925eab1c38 159 x=x | (1 << (7-i));
igor_m 0:b9925eab1c38 160 if (array[3] & (1 << i))
igor_m 0:b9925eab1c38 161 y=y | (1 << (7-i));
igor_m 0:b9925eab1c38 162 }
igor_m 0:b9925eab1c38 163
igor_m 0:b9925eab1c38 164 pc.printf("%3d %3d %4d %3d \n ", array[0], array[1], (signed char)x, (signed char)y);
igor_m 0:b9925eab1c38 165
igor_m 0:b9925eab1c38 166 }
igor_m 0:b9925eab1c38 167
igor_m 0:b9925eab1c38 168 }