N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Wed Dec 10 14:22:30 2014 +0000
Revision:
5:eb93a4f91396
Parent:
4:fee2d61ad6bc
Initial Release

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