Igor Martinovski
/
USBJoystick
N64 to USB HID interface
main.cpp
- Committer:
- igor_m
- Date:
- 2011-09-25
- Revision:
- 2:b38d6345dd14
- Parent:
- 1:38815edb0ecb
- Child:
- 3:b9cecf3e2496
File content as of revision 2:b38d6345dd14:
/* N64 Controller Interface for the mbed. by Igor Martinovski March, 2011. Function Mapping (from www.mixdown.ca/n64dev/) Bit Function 0 A 1 B 2 Z 3 Start 4 Directional Up 5 Directional Down 6 Directional Left 7 Directional Right 8 unknown (always 0) 9 unknown (always 0) 10 L 11 R 12 C Up 13 C Down 14 C Left 15 C Right 16-23 X value (signed) 23-32 Y value (signed) Pinout: Looking at the controller plug, flat side down. Pin 1 (Left) Ground Pin 2 (Center) Data** Pin 3 (Right) +3.3V* (*)Note: The controller is supplied by 3.6V on the N64, but it seems to work fine on the 3.3V provided by the mbed. (**)Warning: The N64 controller must be connected to an open drain pin with a pull-up resistor. The line must never be driven high by the mbed! If you are not sure how to connect the controller safely, you may damage the mbed and/or controller. You have been warned. */ #include "mbed.h" #include "stdint.h" #include "usbhid.h" #include "IOMacros.h" USBJoystick joystick; /* N64 Controller Interface for the mbed. by Igor Martinovski March, 2011. Function Mapping (from www.mixdown.ca/n64dev/) Bit Function 0 A 1 B 2 Z 3 Start 4 Directional Up 5 Directional Down 6 Directional Left 7 Directional Right 8 unknown (always 0) 9 unknown (always 0) 10 L 11 R 12 C Up 13 C Down 14 C Left 15 C Right 16-23 X value (signed) 23-32 Y value (signed) Pinout: Looking at the controller plug, flat side down. Pin 1 (Left) Ground Pin 2 (Center) Data** Pin 3 (Right) +3.3V* (*)Note: The controller is supplied by 3.6V on the N64, but it seems to work fine on the 3.3V provided by the mbed. (**)Warning: The N64 controller must be connected to an open drain pin with a pull-up resistor. The line must never be driven high by the mbed! If you are not sure how to connect the controller safely, you may damage the mbed and/or controller. You have been warned. */ #include "mbed.h" #include "stdint.h" // Controller Commands #define GET_STATUS 0x00 #define REQUEST_CONTROLS 0x01 #define READ_MEMPACK 0x02 #define WRITE_MEMPACK 0x03 #define READ_EEPROM 0x04 #define WRITE_EEPROM 0x05 #define RESET_CONTROLLER 0xff #define T1 24 // Corresponds to 1 us #define T2 72 // Corresponds to 3 us DigitalInOut inout(p14); // Connect controller here // using 220 ohm pull-up Serial pc(USBTX, USBRX); DigitalOut led(LED1); uint8_t x, y; volatile char bit_count; union controls { /* A definition and a declaration */ uint8_t array[4]; uint32_t result_32; } controls; /** EINT3_IRQHandler */ void delay (unsigned int); void ISR(void); extern "C" void EINT3_IRQHandler(void) { // The "event" is connected to pin p10 which is LPC1768 P0_1 // so lets trap that and ignore all other GPIO interrupts. // Test for IRQ on Port0. // if (LPC_GPIOINT->IntStatus & 0x1) { // If P0_16/p14 rises, call atint() if (LPC_GPIOINT->IO0IntStatF & (1 << 16)) { delay(30); if (inout.read()) controls.result_32 |= (1UL<< bit_count); else controls.result_32 &= ~(1UL << bit_count); bit_count++; } //} // Clear this and all other possible GPIO generated interrupts as they don't concern us. LPC_GPIOINT->IO2IntClr = (LPC_GPIOINT->IO2IntStatR | LPC_GPIOINT->IO2IntStatF); LPC_GPIOINT->IO0IntClr = (LPC_GPIOINT->IO0IntStatR | LPC_GPIOINT->IO0IntStatF); } void event_irq_init(void) { // Use macro to set p10 as an input. //p10_AS_INPUT; // Enable P0_16/p14 for falling edge interrupt generation. LPC_GPIOINT->IO0IntEnF |= (1UL << 16); // Enable the interrupt. //NVIC_EnableIRQ(EINT3_IRQn); } // Temp array for controller data /* void delay(unsigned int n) is used as a short delay to time the bit patterns. 1 n is roughly 0.042us on 96MHz CCLK */ void delay(unsigned int n) { unsigned int i; for (i=0; i<n; i++) ; } void ISR() { wait_us(2); if (inout.read()) controls.result_32 |= (1UL<< bit_count); else controls.result_32 &= ~(1UL << bit_count); bit_count++; } /* int receive(char *data_array, unsigned char n) is used to receive a bit stream of bits into an array of n bytes coming from the controller. This must be called immediately after sending any kind of request to the controller */ int receive(uint8_t *data_array, unsigned char n) { int i; bit_count=0; //inout.write(1); NVIC_EnableIRQ(EINT3_IRQn); wait_us(500); //led=1; NVIC_DisableIRQ(EINT3_IRQn); x=y=0; for (i=0; i<=7; i++) { if (controls.array[2] & (1 << i)) x=x | (1 << (7-i)); if (controls.array[3] & (1 << i)) y=y | (1 << (7-i)); } data_array[2]=x; data_array[3]=y; return n; } /* void send_byte(unsigned char byte) is used to send a single byte to the controller. */ void send_byte(unsigned char byte) { char i; //inout.output(); // Not sure about this. inout.write(1); // Makes sure line is left high wait_us(500); for (i=0; i<8; i++) { if (byte & 128>>i) { inout.write(0); delay(T1); inout.write(1); delay(T2); } else { inout.write(0); delay(T2); inout.write(1); delay(T1); } } /* Send Stop Bit */ inout.write(0); delay(T1); inout.write(1); delay(T1); } int main() { inout.mode(OpenDrain); // Must use open-drain for N64 Controller! event_irq_init(); uint32_t previous_result=0; // Used for the bit-shifting for x and y values //send_byte(RESET_CONTROLLER); wait_ms(10); while (1) { wait_ms(10); previous_result=controls.result_32; send_byte(1); // Send the request byte receive(controls.array, 4); // Start receiving bit stream pc.printf("bitcount: %d\n",bit_count); if (controls.result_32==previous_result) continue; // pc.printf("%3d %3d %d %d\n ", controls.array[0], controls.array[1], (int8_t)controls.array[2], (int8_t)controls.array[3]); //pc.printf("%d\n",controls.result_32); //joystick.joystick(controls.array[0],controls.array[1], controls.array[2], controls.array[3]); } }