N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Fri Sep 30 00:15:10 2011 +0000
Revision:
3:b9cecf3e2496
Parent:
2:b38d6345dd14
Child:
4:fee2d61ad6bc
GC

Who changed what in which revision?

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