N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Sun Sep 25 16:22:03 2011 +0000
Revision:
1:38815edb0ecb
Parent:
0:547c5459faa6
Child:
2:b38d6345dd14
changed to interrupts

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 1:38815edb0ecb 51 #include "IOMacros.h"
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 1:38815edb0ecb 121 DigitalOut led(LED1);
igor_m 0:547c5459faa6 122 uint8_t x, y;
igor_m 1:38815edb0ecb 123 volatile char bit_count;
igor_m 0:547c5459faa6 124 union controls { /* A definition and a declaration */
igor_m 0:547c5459faa6 125 uint8_t array[4];
igor_m 0:547c5459faa6 126 uint32_t result_32;
igor_m 0:547c5459faa6 127 } controls;
igor_m 0:547c5459faa6 128
igor_m 1:38815edb0ecb 129 /** EINT3_IRQHandler
igor_m 1:38815edb0ecb 130 */
igor_m 1:38815edb0ecb 131 void ISR(void);
igor_m 1:38815edb0ecb 132 extern "C" void EINT3_IRQHandler(void) {
igor_m 1:38815edb0ecb 133
igor_m 1:38815edb0ecb 134 // The "event" is connected to pin p10 which is LPC1768 P0_1
igor_m 1:38815edb0ecb 135 // so lets trap that and ignore all other GPIO interrupts.
igor_m 1:38815edb0ecb 136 // Test for IRQ on Port0.
igor_m 1:38815edb0ecb 137
igor_m 1:38815edb0ecb 138 if (LPC_GPIOINT->IntStatus & 0x1) {
igor_m 1:38815edb0ecb 139 // If P0_16/p14 rises, call atint()
igor_m 1:38815edb0ecb 140 if (LPC_GPIOINT->IO0IntStatF & (1 << 16)) ISR();
igor_m 1:38815edb0ecb 141 }
igor_m 1:38815edb0ecb 142 // Clear this and all other possible GPIO generated interrupts as they don't concern us.
igor_m 1:38815edb0ecb 143 LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF);
igor_m 1:38815edb0ecb 144 LPC_GPIOINT->IO0IntClr = (LPC_GPIOINT->IO0IntStatR | LPC_GPIOINT->IO0IntStatF);
igor_m 1:38815edb0ecb 145
igor_m 1:38815edb0ecb 146 }
igor_m 1:38815edb0ecb 147
igor_m 1:38815edb0ecb 148 void event_irq_init(void) {
igor_m 1:38815edb0ecb 149 // Use macro to set p10 as an input.
igor_m 1:38815edb0ecb 150 //p10_AS_INPUT;
igor_m 1:38815edb0ecb 151 // Enable P0_16/p14 for falling edge interrupt generation.
igor_m 1:38815edb0ecb 152 LPC_GPIOINT->IO0IntEnF |= (1UL << 16);
igor_m 1:38815edb0ecb 153 // Enable the interrupt.
igor_m 1:38815edb0ecb 154 //NVIC_EnableIRQ(EINT3_IRQn);
igor_m 1:38815edb0ecb 155 }
igor_m 1:38815edb0ecb 156
igor_m 1:38815edb0ecb 157
igor_m 0:547c5459faa6 158 // Temp array for controller data
igor_m 0:547c5459faa6 159
igor_m 0:547c5459faa6 160 /* void delay(unsigned int n) is used as a short delay to
igor_m 0:547c5459faa6 161 time the bit patterns. 1 n is roughly 0.042us on 96MHz CCLK
igor_m 0:547c5459faa6 162 */
igor_m 0:547c5459faa6 163 void delay(unsigned int n) {
igor_m 0:547c5459faa6 164 unsigned int i;
igor_m 0:547c5459faa6 165 for (i=0; i<n; i++)
igor_m 0:547c5459faa6 166 ;
igor_m 0:547c5459faa6 167 }
igor_m 0:547c5459faa6 168
igor_m 1:38815edb0ecb 169 void ISR(){
igor_m 1:38815edb0ecb 170 delay(48);
igor_m 1:38815edb0ecb 171 if (inout.read()) controls.result_32 |= (1UL<< bit_count);
igor_m 1:38815edb0ecb 172 else controls.result_32 &= ~(1UL << bit_count);
igor_m 1:38815edb0ecb 173 bit_count++;
igor_m 1:38815edb0ecb 174 }
igor_m 1:38815edb0ecb 175
igor_m 0:547c5459faa6 176 /* int receive(char *data_array, unsigned char n) is used to
igor_m 0:547c5459faa6 177 receive a bit stream of bits into an array of n bytes coming
igor_m 0:547c5459faa6 178 from the controller. This must be called immediately after
igor_m 0:547c5459faa6 179 sending any kind of request to the controller
igor_m 0:547c5459faa6 180 */
igor_m 0:547c5459faa6 181
igor_m 0:547c5459faa6 182 int receive(uint8_t *data_array, unsigned char n) {
igor_m 1:38815edb0ecb 183
igor_m 0:547c5459faa6 184 int i;
igor_m 1:38815edb0ecb 185 bit_count=0;
igor_m 0:547c5459faa6 186
igor_m 1:38815edb0ecb 187 NVIC_EnableIRQ(EINT3_IRQn);
igor_m 0:547c5459faa6 188
igor_m 1:38815edb0ecb 189 while(bit_count<33){
igor_m 1:38815edb0ecb 190 ;//Wait for Interrupts
igor_m 1:38815edb0ecb 191 }
igor_m 1:38815edb0ecb 192 led=1;
igor_m 1:38815edb0ecb 193 NVIC_DisableIRQ(EINT3_IRQn);
igor_m 0:547c5459faa6 194
igor_m 0:547c5459faa6 195 x=y=0;
igor_m 0:547c5459faa6 196 for (i=0;i<=7;i++) {
igor_m 0:547c5459faa6 197 if (controls.array[2] & (1 << i))
igor_m 0:547c5459faa6 198 x=x | (1 << (7-i));
igor_m 0:547c5459faa6 199 if (controls.array[3] & (1 << i))
igor_m 0:547c5459faa6 200 y=y | (1 << (7-i));
igor_m 0:547c5459faa6 201 }
igor_m 0:547c5459faa6 202 data_array[2]=x;
igor_m 0:547c5459faa6 203 data_array[3]=y;
igor_m 0:547c5459faa6 204 return n;
igor_m 0:547c5459faa6 205 }
igor_m 1:38815edb0ecb 206
igor_m 1:38815edb0ecb 207
igor_m 0:547c5459faa6 208 /* void send_byte(unsigned char byte) is used to send a single
igor_m 0:547c5459faa6 209 byte to the controller.
igor_m 0:547c5459faa6 210 */
igor_m 0:547c5459faa6 211 void send_byte(unsigned char byte) {
igor_m 0:547c5459faa6 212 char i;
igor_m 0:547c5459faa6 213 //inout.output(); // Not sure about this.
igor_m 0:547c5459faa6 214 inout.write(1); // Makes sure line is left high
igor_m 0:547c5459faa6 215
igor_m 0:547c5459faa6 216 wait_us(500);
igor_m 0:547c5459faa6 217 for (i=0; i<8; i++) {
igor_m 0:547c5459faa6 218 if (byte & 128>>i) {
igor_m 0:547c5459faa6 219 inout.write(0);
igor_m 0:547c5459faa6 220 delay(T1);
igor_m 0:547c5459faa6 221 inout.write(1);
igor_m 0:547c5459faa6 222 delay(T2);
igor_m 0:547c5459faa6 223 } else {
igor_m 0:547c5459faa6 224 inout.write(0);
igor_m 0:547c5459faa6 225 delay(T2);
igor_m 0:547c5459faa6 226 inout.write(1);
igor_m 0:547c5459faa6 227 delay(T1);
igor_m 0:547c5459faa6 228 }
igor_m 0:547c5459faa6 229 }
igor_m 0:547c5459faa6 230 /* Send Stop Bit */
igor_m 0:547c5459faa6 231 inout.write(0);
igor_m 0:547c5459faa6 232 delay(T1);
igor_m 0:547c5459faa6 233 inout.write(1);
igor_m 0:547c5459faa6 234 delay(T1);
igor_m 0:547c5459faa6 235
igor_m 0:547c5459faa6 236 }
igor_m 0:547c5459faa6 237
igor_m 0:547c5459faa6 238 int main() {
igor_m 0:547c5459faa6 239 inout.mode(OpenDrain); // Must use open-drain for N64 Controller!
igor_m 1:38815edb0ecb 240 event_irq_init();
igor_m 1:38815edb0ecb 241 uint32_t previous_result=0; // Used for the bit-shifting for x and y values
igor_m 0:547c5459faa6 242 send_byte(RESET_CONTROLLER);
igor_m 0:547c5459faa6 243 wait_ms(10);
igor_m 0:547c5459faa6 244 while (1) {
igor_m 0:547c5459faa6 245 wait_ms(10);
igor_m 0:547c5459faa6 246 previous_result=controls.result_32;
igor_m 0:547c5459faa6 247 send_byte(1); // Send the request byte
igor_m 0:547c5459faa6 248 receive(controls.array, 4); // Start receiving bit stream
igor_m 0:547c5459faa6 249
igor_m 0:547c5459faa6 250 if (controls.result_32==previous_result) continue;
igor_m 0:547c5459faa6 251
igor_m 0:547c5459faa6 252
igor_m 0:547c5459faa6 253 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 254 //pc.printf("%d\n",controls.result_32);
igor_m 0:547c5459faa6 255 //joystick.joystick(controls.array[0],controls.array[1], controls.array[2], controls.array[3]);
igor_m 0:547c5459faa6 256 }
igor_m 0:547c5459faa6 257
igor_m 0:547c5459faa6 258 }