Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <HID-Project.h>
- #include <HID-Settings.h>
- #define PIN_READ (PIND & 0x01)
- #define MICROSECOND_NOPS "nop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\nnop\n"
- #define WAIT_FALLING_EDGE while( !PIN_READ ); while( PIN_READ );
- #define N64_PIN 3
- #define N64_PREFIX 9
- #define N64_BITCOUNT 32
- #define ZERO '0' // Use a byte value of 0x00 to represent a bit with value 0.
- #define ONE '1' // Use an ASCII one to represent a bit with value 1. This makes Arduino debugging easier.
- #define SPLIT '\n' // Use a new-line character to split up the controller state packets.
- // Declare some space to store the bits we read from a controller.
- unsigned char rawData[ 128 ];
- struct state {
- char stick_x;
- char stick_y;
- // bits: 0, 0, 0, start, y, x, b, a
- unsigned char data1;
- // bits: 1, L, R, Z, Dup, Ddown, Dright, Dleft
- unsigned char data2;
- } N64_status;
- void translate_raw_data()
- {
- memset(&N64_status, 0, sizeof(N64_status));
- for (int i = 0; i < 8; i++) {
- N64_status.data1 |= rawData[9 + i] ? (0x80 >> i) : 0;
- N64_status.data2 |= rawData[17 + i] ? (0x80 >> i) : 0;
- N64_status.stick_x |= rawData[25 + i] ? (0x80 >> i) : 0;
- N64_status.stick_y |= rawData[33 + i] ? (0x80 >> i) : 0;
- }
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // General initialization, just sets all pins to input and starts serial communication.
- void setup()
- {
- Serial.begin( 9600 );
- digitalWrite(N64_PIN, LOW);
- pinMode(N64_PIN, INPUT);
- Gamepad.begin();
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Performs a read cycle from one of Nintendo's one-wire interface based controllers.
- // This includes the N64 and the Gamecube.
- // pin = Pin index on Port D where the data wire is attached.
- // bits = Number of bits to read from the line.
- void read_oneWire( unsigned char bits )
- {
- unsigned char *rawDataPtr = rawData;
- read_loop:
- // Wait for the line to go high then low.
- WAIT_FALLING_EDGE;
- // Wait ~2us between line reads
- asm volatile( MICROSECOND_NOPS MICROSECOND_NOPS );
- // Read a bit from the line and store as a byte in "rawData"
- *rawDataPtr = PIN_READ;
- ++rawDataPtr;
- if( --bits == 0 ) return;
- goto read_loop;
- }
- // Verifies that the 9 bits prefixing N64 controller data in 'rawData'
- // are actually indicative of a controller state signal.
- inline bool checkPrefixN64 ()
- {
- if( rawData[0] != 0 ) return false; // 0
- if( rawData[1] != 0 ) return false; // 0
- if( rawData[2] != 0 ) return false; // 0
- if( rawData[3] != 0 ) return false; // 0
- if( rawData[4] != 0 ) return false; // 0
- if( rawData[5] != 0 ) return false; // 0
- if( rawData[6] != 0 ) return false; // 0
- if( rawData[7] == 0 ) return false; // 1
- if( rawData[8] == 0 ) return false; // 1
- return true;
- }
- void print_N64_status()
- {
- char out[64];
- sprintf(out, "%i%i%i%i%i%i%i%i %i%i%i%i%i%i%i%i %i %i",
- N64_status.data1&128?1:0, //A
- N64_status.data1&64?1:0, //B
- N64_status.data1&32?1:0, //Z
- N64_status.data1&16?1:0, //Start
- N64_status.data1&8?1:0, //Du
- N64_status.data1&4?1:0, //Dd
- N64_status.data1&2?1:0, //Dl
- N64_status.data1&1?1:0, //Dr
- N64_status.data2&128?1:0, //Reset
- 0,
- N64_status.data2&32?1:0, //L
- N64_status.data2&16?1:0, //R
- N64_status.data2&8?1:0, //Cu
- N64_status.data2&4?1:0, //Cd
- N64_status.data2&2?1:0, //Cl
- N64_status.data2&1?1:0, //Cr
- N64_status.stick_x,
- N64_status.stick_y);
- Serial.println(out);
- }
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Arduino sketch main loop definition.
- void loop()
- {
- noInterrupts();
- read_oneWire( N64_PREFIX + N64_BITCOUNT );
- interrupts();
- if( checkPrefixN64() )
- {
- translate_raw_data();
- print_N64_status();
- update_joystick();
- Gamepad.write();
- }
- }
- void update_joystick()
- {
- int i;
- signed char jx=0,jy=0;
- jx|=(unsigned char)N64_status.stick_x;
- jy|=(unsigned char)N64_status.stick_y;
- float JX=jx;
- float JY=-jy;
- Gamepad.xAxis(4096 * 4 + JX);
- Gamepad.yAxis(4096 * 4 + JY);
- for(i=0;i<8;i++)
- {
- if (rawData[i+9])
- Gamepad.press(i+1);
- else
- Gamepad.release(i+1);
- }
- for(i=0;i<6;i++)
- {
- if (rawData[19+i])
- Gamepad.press(i+9);
- else
- Gamepad.release(i+9);
- }
- unsigned char pov_byte=N64_status.data1&0x0F;
- int pov=-1;
- switch (pov_byte)
- {
- default: //Centered
- pov=0;
- break;
- case 1: //RIGHT
- pov=3;
- break;
- case 2: //LEFT
- pov=7;
- break;
- case 4: //DOWN
- pov=5;
- break;
- case 8: //UP
- pov=1;
- break;
- case 10: //UP-LEFT
- pov=8;
- break;
- case 6: //DOWN-LEFT
- pov=6;
- break;
- case 9: //UP-RIGHT
- pov=2;
- break;
- case 5: //DOWN-RIGHT
- pov=4;
- break;
- }
- Gamepad.dPad1(pov);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement