N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Fri Sep 30 23:16:52 2011 +0000
Revision:
4:fee2d61ad6bc
Parent:
3:b9cecf3e2496
Child:
5:eb93a4f91396
GCPad - Working

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 4:fee2d61ad6bc 115 #define T1 22 // Corresponds to 1 us
igor_m 4:fee2d61ad6bc 116 #define T2 68 // 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 4:fee2d61ad6bc 124 uint8_t array[8];
igor_m 4:fee2d61ad6bc 125 uint32_t result[2];
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 4:fee2d61ad6bc 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 4:fee2d61ad6bc 173 /* The for loop here is used to reverse the bits for the x and y values retured
igor_m 4:fee2d61ad6bc 174 by the controller. I am not entirely sure of the format. I'm missing a bit
igor_m 4:fee2d61ad6bc 175 somewhere.. Values don't range from -127..128. */
igor_m 4:fee2d61ad6bc 176 /*
igor_m 4:fee2d61ad6bc 177 x=y=0;
igor_m 4:fee2d61ad6bc 178 for (i=0; i<=7; i++) {
igor_m 4:fee2d61ad6bc 179 if (controls.array[2] & (1 << i))
igor_m 4:fee2d61ad6bc 180 x=x | (1 << (7-i));
igor_m 4:fee2d61ad6bc 181 if (controls.array[3] & (1 << i))
igor_m 4:fee2d61ad6bc 182 y=y | (1 << (7-i));
igor_m 4:fee2d61ad6bc 183 }
igor_m 4:fee2d61ad6bc 184 data_array[2]=x;
igor_m 4:fee2d61ad6bc 185 data_array[3]=y;
igor_m 4:fee2d61ad6bc 186 */
igor_m 4:fee2d61ad6bc 187 //data_array[2]= 5;
igor_m 0:547c5459faa6 188 return n;
igor_m 0:547c5459faa6 189 }
igor_m 0:547c5459faa6 190 /* void send_byte(unsigned char byte) is used to send a single
igor_m 0:547c5459faa6 191 byte to the controller.
igor_m 0:547c5459faa6 192 */
igor_m 0:547c5459faa6 193 void send_byte(unsigned char byte) {
igor_m 0:547c5459faa6 194 char i;
igor_m 0:547c5459faa6 195 //inout.output(); // Not sure about this.
igor_m 0:547c5459faa6 196 inout.write(1); // Makes sure line is left high
igor_m 0:547c5459faa6 197
igor_m 0:547c5459faa6 198 wait_us(500);
igor_m 0:547c5459faa6 199 for (i=0; i<8; i++) {
igor_m 0:547c5459faa6 200 if (byte & 128>>i) {
igor_m 0:547c5459faa6 201 inout.write(0);
igor_m 0:547c5459faa6 202 delay(T1);
igor_m 0:547c5459faa6 203 inout.write(1);
igor_m 0:547c5459faa6 204 delay(T2);
igor_m 0:547c5459faa6 205 } else {
igor_m 0:547c5459faa6 206 inout.write(0);
igor_m 0:547c5459faa6 207 delay(T2);
igor_m 0:547c5459faa6 208 inout.write(1);
igor_m 0:547c5459faa6 209 delay(T1);
igor_m 0:547c5459faa6 210 }
igor_m 0:547c5459faa6 211 }
igor_m 0:547c5459faa6 212 /* Send Stop Bit */
igor_m 0:547c5459faa6 213 inout.write(0);
igor_m 0:547c5459faa6 214 delay(T1);
igor_m 0:547c5459faa6 215 inout.write(1);
igor_m 0:547c5459faa6 216 delay(T1);
igor_m 4:fee2d61ad6bc 217 }
igor_m 4:fee2d61ad6bc 218
igor_m 4:fee2d61ad6bc 219 /* void send_byte(unsigned char byte) is used to send a single
igor_m 4:fee2d61ad6bc 220 byte to the controller.
igor_m 4:fee2d61ad6bc 221 */
igor_m 4:fee2d61ad6bc 222 void send(uint8_t * cmd, uint8_t n) {
igor_m 4:fee2d61ad6bc 223 uint8_t i,j,byte;
igor_m 4:fee2d61ad6bc 224
igor_m 4:fee2d61ad6bc 225 inout.write(1); // Makes sure line is left high
igor_m 4:fee2d61ad6bc 226 wait_us(500);
igor_m 4:fee2d61ad6bc 227 for (j=0; j<n; j++) {
igor_m 4:fee2d61ad6bc 228 byte=cmd[j];
igor_m 4:fee2d61ad6bc 229 for (i=0; i<8; i++) {
igor_m 4:fee2d61ad6bc 230 if (byte & 128>>i) {
igor_m 4:fee2d61ad6bc 231 inout.write(0);
igor_m 4:fee2d61ad6bc 232 delay(T1);
igor_m 4:fee2d61ad6bc 233 inout.write(1);
igor_m 4:fee2d61ad6bc 234 delay(T2);
igor_m 4:fee2d61ad6bc 235 } else {
igor_m 4:fee2d61ad6bc 236 inout.write(0);
igor_m 4:fee2d61ad6bc 237 delay(T2);
igor_m 4:fee2d61ad6bc 238 inout.write(1);
igor_m 4:fee2d61ad6bc 239 delay(T1);
igor_m 4:fee2d61ad6bc 240 }
igor_m 4:fee2d61ad6bc 241 }
igor_m 4:fee2d61ad6bc 242
igor_m 4:fee2d61ad6bc 243 }/* Send Stop Bit */
igor_m 4:fee2d61ad6bc 244 inout.write(0);
igor_m 4:fee2d61ad6bc 245 delay(T1);
igor_m 4:fee2d61ad6bc 246 inout.write(1);
igor_m 4:fee2d61ad6bc 247 delay(T1);
igor_m 0:547c5459faa6 248
igor_m 0:547c5459faa6 249 }
igor_m 0:547c5459faa6 250
igor_m 4:fee2d61ad6bc 251
igor_m 4:fee2d61ad6bc 252 uint8_t cmd[8];
igor_m 4:fee2d61ad6bc 253
igor_m 4:fee2d61ad6bc 254
igor_m 0:547c5459faa6 255 int main() {
igor_m 0:547c5459faa6 256 inout.mode(OpenDrain); // Must use open-drain for N64 Controller!
igor_m 4:fee2d61ad6bc 257 uint8_t cmd[8];
igor_m 4:fee2d61ad6bc 258 int8_t n;
igor_m 4:fee2d61ad6bc 259 int temp;
igor_m 3:b9cecf3e2496 260 uint32_t i, previous_result=0; // Used for the bit-shifting for x and y values
igor_m 0:547c5459faa6 261 while (1) {
igor_m 0:547c5459faa6 262 wait_ms(10);
igor_m 4:fee2d61ad6bc 263 n=3;
igor_m 4:fee2d61ad6bc 264 cmd[0]=2; // Request Controls
igor_m 4:fee2d61ad6bc 265 cmd[1]=3;
igor_m 4:fee2d61ad6bc 266 cmd[0]=64;
igor_m 4:fee2d61ad6bc 267 send(cmd,3);
igor_m 4:fee2d61ad6bc 268 receive(controls.array, 8); // Start receiving bit stream
igor_m 4:fee2d61ad6bc 269 //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 4:fee2d61ad6bc 270
igor_m 4:fee2d61ad6bc 271 for (n=7; n>=0; n--){
igor_m 4:fee2d61ad6bc 272 if (controls.array[2] & (1 << n))
igor_m 4:fee2d61ad6bc 273 pc.printf("1");
igor_m 4:fee2d61ad6bc 274 else
igor_m 4:fee2d61ad6bc 275 pc.printf("0");
igor_m 4:fee2d61ad6bc 276 }
igor_m 4:fee2d61ad6bc 277 //pc.printf("%d %d", (int8_t)(controls.array[2]^= (1 << 7)),controls.array[3]);
igor_m 4:fee2d61ad6bc 278 pc.printf("\n");
igor_m 4:fee2d61ad6bc 279 /*
igor_m 4:fee2d61ad6bc 280 for (n=0; n<16; n++)
igor_m 4:fee2d61ad6bc 281 pc.printf("%d", (1 & ((uint16_t)controls.result[0] >> n)));
igor_m 4:fee2d61ad6bc 282 pc.printf(" ");
igor_m 4:fee2d61ad6bc 283
igor_m 4:fee2d61ad6bc 284 for (n=17; n<32; n++)
igor_m 4:fee2d61ad6bc 285 pc.printf("%d", (1 & ((uint32_t)controls.result[0] >> n)));
igor_m 4:fee2d61ad6bc 286 pc.printf(" ");
igor_m 3:b9cecf3e2496 287
igor_m 4:fee2d61ad6bc 288 for (n=0; n<16; n++)
igor_m 4:fee2d61ad6bc 289 pc.printf("%d", (1 & ((uint16_t)controls.result[1] >> n)));
igor_m 4:fee2d61ad6bc 290 pc.printf(" ");
igor_m 3:b9cecf3e2496 291
igor_m 4:fee2d61ad6bc 292 for (n=17; n<32; n++)
igor_m 4:fee2d61ad6bc 293 pc.printf("%d", (1 & ((uint32_t)controls.result[1] >> n)));
igor_m 4:fee2d61ad6bc 294 pc.printf("\n");
igor_m 4:fee2d61ad6bc 295 */
igor_m 4:fee2d61ad6bc 296 }
igor_m 4:fee2d61ad6bc 297
igor_m 4:fee2d61ad6bc 298 while (1) {
igor_m 4:fee2d61ad6bc 299 wait_ms(10);
igor_m 4:fee2d61ad6bc 300 //previous_result=controls.result_32;
igor_m 4:fee2d61ad6bc 301 send_byte(1); // Send the request byte
igor_m 4:fee2d61ad6bc 302 receive(controls.array, 8); // Start receiving bit stream
igor_m 4:fee2d61ad6bc 303
igor_m 4:fee2d61ad6bc 304 // if (controls.result_32==previous_result) continue;
igor_m 4:fee2d61ad6bc 305
igor_m 4:fee2d61ad6bc 306
igor_m 3:b9cecf3e2496 307 //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 308 //pc.printf("%d\n",controls.result_32);
igor_m 4:fee2d61ad6bc 309 joystick.joystick(controls.array[0],controls.array[1], controls.array[2], controls.array[3]);
igor_m 0:547c5459faa6 310 }
igor_m 0:547c5459faa6 311
igor_m 0:547c5459faa6 312 }