/************************************************************************************************************ AVR code to emulate Playstation game controller protocol date: October 12, 2009 compiler: gcc-avr compiler AVR: ATmega324p clock source: 8 MHz external crystal *************************************************************************************************************/ #include <avr/io.h> #include "def.h" #include "other.h" #define F_CPU 8000000UL #include <util/delay.h> #include <avr/interrupt.h> #include <string.h> #include <inttypes.h> #include <util/twi.h> int main(void){ uint8_t final_data[18]; // array stores final formatted data that is sent to ps2 uint8_t dsc_data[6]; // array stores raw data acquired from ps controller uint8_t chuck_data[6]; // array stores raw data acquired from nunchuck uint8_t command[6]; // array stores commands sent from ps2 in order they are received uint8_t saturn_data[2]; // array stores raw data acquired from saturn controller uint8_t nes_data[2]; // array stores raw data acquired from NES controller uint8_t DSC_mode_ID = 0x00; // mode ID given by controller connected to ps controller port uint8_t DSC_config_counter = 0x00; // counter used to increment ps controller config sequence uint8_t remapped_x; // stores nunchuck x-axis tilt value in remapped 8-bit range uint8_t remapped_y; // stores nunchuck y-axis tilt value in remapped 8-bit range uint8_t CSR0 = 0x00; // command status register 0 uint8_t MSR0 = 0x00; // macro status register 0 uint8_t TSR0 = 0x00; // turbo status register 0 uint8_t GCSR0 = 0x00; // game controller status register 0 uint8_t display_tracker = 0x00; // keeps track of displayed message on LCD uint8_t katamari_counter = 0x01; // counter for katamari mode macro uint8_t turbo_counter = 0x00; // counter for turbo mode macro uint8_t reader = 0x00; char welcome[] = "Welcome DSC Emu v2.5"; char date[] = "Compiled 10/12/2009"; char katamari[] = "Katamari"; char racing[] = "Racing"; char arcade[] = "Arcade"; char standard[] = "Default"; char turbo[] = "Turbo"; char serial_in[] = "Serial Input"; char mode[] = " Mode"; final_data[0] = 0xFF; // Initialise data variables with neutral values final_data[1] = 0xFF; final_data[2] = 0x80; final_data[3] = 0x80; final_data[4] = 0x80; final_data[5] = 0x80; command[0] = 0x00; command[1] = 0x00; command[2] = 0x00; command[3] = 0x00; command[4] = 0x00; init(); // configure all AVR registers and interrupts lcd_init(); // initialise LCD lcd_string_print(welcome); // print top line welcome message lcd_move_to_address(SECOND_LINE); lcd_string_print(date); lcd_instruction_write(RETURN_HOME); /* Infinite while loop*/ while(1){ /*PS-AVR SPI SECTION*******************************************************************************************/ if(~SPI_PIN & _BV(SS)){ // If attention line (SS/PB2) is brought low, enter transmission mode reader = SPSR; // Read SPI status register to clear SPIF flag SPDR = ~0xFF; // Write SPI data register with initial dummy byte START_TIMER_AT(1); // setup 1ms timer // loop while timer counts up, SS remains low, and SPI transmission flag not set while((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN & _BV(SS)) && (!(SPSR & _BV(SPIF)))); // If these two remain true it means SPI hardware has received a byte and communication continues if((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN &_BV(SS))){ command[0] = SPDR; // Read first command byte from SPI buffer if(command[0] == 0x01){ // If PS is not addressing controller, abandon communication _delay_us(4); // delay before ACK necessary for Ps1 compatibility ACKNOWLEDGE; // ACK pulse sent following every byte except final byte if((CSR0 & _BV(ANALOG_MODE_BIT)) && (!(CSR0 & _BV(CONFIG_MODE_BIT)))){ // if analog mode is active and config mode is inactive... PS_AVR_COMM(0x73, command[1]);} // ...send 0x73, analog mode ID else if((!(CSR0 & _BV(ANALOG_MODE_BIT))) && (!(CSR0 & _BV(CONFIG_MODE_BIT)))){ // if neither config mode nor analog mode active... PS_AVR_COMM(0x41, command[1]);} // ...send 0x41, digital mode ID else if(CSR0 & _BV(CONFIG_MODE_BIT)){ // if config mode is active... PS_AVR_COMM(0xF3, command[1]);} // ...send 0xF3, config mode ID // tests for known commands which the adapter will reply to, commands not listed will terminate communication for the current packet // 0x42 = main polling command used to get control data from adapter // 0x43 = enter/exit config mode command // 0x44 = switch between analog/digital modes and lock/unlock controller in specified mode // 0x45 = command to retrieve status/ID info from adapter // 0x46 = command to retrieve 10 bytes of mystery data from adapter over two packets // 0x47 = command to retrieve 5 bytes of mystery data from adapter // 0x4C = command to retrieve 10 bytes of mystery data from adapter over two packets // 0x4D = maps rumble motor commands to command bytes 3 and 4 in 0x42 polling packet if((command[1] == 0x42) || (command[1] == 0x43) || (command[1] == 0x44) || (command[1] == 0x45) || (command[1] == 0x46) || (command[1] == 0x47) || (command[1] == 0x4C) || (command[1] == 0x4D)){ _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(0x5A, command[2]); // filler byte, always 0x5A if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x45)){ // if adapter is in config mode and 0x45 command is received final_data[0] = 0x01; // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response final_data[1] = 0x02; (CSR0 & _BV(ANALOG_MODE_BIT)) ? (final_data[2] = 0x01) : (final_data[2] = 0x00); // 1 if in analog mode, otherwise 0 final_data[3] = 0x02; final_data[4] = 0x01; final_data[5] = 0x00; } // sets up first two data bytes for a 0x4D command, these bytes report the current rumble motor mapping if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4D)){ if(CSR0 & _BV(FIRST_MOTOR_BYTE_SMALL)) final_data[0] = 0x00; else if(CSR0 & _BV(FIRST_MOTOR_BYTE_LARGE)) final_data[0] = 0x01; else final_data[0] = 0xFF; if(CSR0 & _BV(SECOND_MOTOR_BYTE_SMALL)) final_data[1] = 0x00; else if(CSR0 & _BV(SECOND_MOTOR_BYTE_LARGE)) final_data[1] = 0x01; else final_data[1] = 0xFF; } // ps1 will reject data in the 0x46, 0x47, and 0x4C packets if final_data[0] is not 0x00 if((CSR0 & _BV(CONFIG_MODE_BIT)) && ((command[1] == 0x46) || (command[1] == 0x47) || (command[1] == 0x4C))){ final_data[0] = 0x00; } _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[0], command[3]); // first data byte (8 buttons) if(command[1] == 0x43){ // command[3] tells the adapter to enter or exit config mode when command[1] is 0x43 (command[3] == 0x00) ? (CSR0 &= ~_BV(CONFIG_MODE_BIT)) : (CSR0 |= _BV(CONFIG_MODE_BIT)); } if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x46)){ if(command[3] == 0x00){ final_data[1] = 0x00; // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response final_data[2] = 0x01; final_data[3] = 0x02; final_data[4] = 0x00; final_data[5] = 0x0A; } else if(command[3] == 0x01){ final_data[1] = 0x00; final_data[2] = 0x01; final_data[3] = 0x01; final_data[4] = 0x01; final_data[5] = 0x14; } } if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x47)){ final_data[1] = 0x00; // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response final_data[2] = 0x02; final_data[3] = 0x00; final_data[4] = 0x01; final_data[5] = 0x00; } if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4C)){ if(command[3] == 0x00){ final_data[1] = 0x00; // meaning of these bytes is unknown, copied from analysis of a real Ps1 controller response final_data[2] = 0x00; final_data[3] = 0x04; final_data[4] = 0x00; final_data[5] = 0x00; } else if(command[3] == 0x01){ final_data[1] = 0x00; final_data[2] = 0x00; final_data[3] = 0x07; final_data[4] = 0x00; final_data[5] = 0x00; } } _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[1], command[4]); // second data byte (8 buttons) if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x44)){ // command[3] turns analog mode on or off, command[4] locks controller in specified mode (command[3] == 0x00) ? (CSR0 &= ~_BV(ANALOG_MODE_BIT)) : (CSR0 |= _BV(ANALOG_MODE_BIT)); (command[4] == 0x03) ? (CSR0 |= _BV(LOCK_BIT)) : (CSR0 &= ~_BV(LOCK_BIT)); } if((CSR0 & _BV(CONFIG_MODE_BIT)) && (command[1] == 0x4D)){ if(command[3] == 0){ CSR0 |= _BV(FIRST_MOTOR_BYTE_SMALL); CSR0 &= ~_BV(FIRST_MOTOR_BYTE_LARGE);} else if(command[3] == 1){ CSR0 |= _BV(FIRST_MOTOR_BYTE_LARGE); CSR0 &= ~_BV(FIRST_MOTOR_BYTE_SMALL);} else{ CSR0 &= ~_BV(FIRST_MOTOR_BYTE_SMALL); CSR0 &= ~_BV(FIRST_MOTOR_BYTE_LARGE);} if(command[4] == 0){ CSR0 |= _BV(SECOND_MOTOR_BYTE_SMALL); CSR0 &= ~_BV(SECOND_MOTOR_BYTE_LARGE);} else if(command[4] == 1){ CSR0 |= _BV(SECOND_MOTOR_BYTE_LARGE); CSR0 &= ~_BV(SECOND_MOTOR_BYTE_SMALL);} else{ CSR0 &= ~_BV(SECOND_MOTOR_BYTE_SMALL); CSR0 &= ~_BV(SECOND_MOTOR_BYTE_LARGE);} } START_TIMER_AT(253); // loop while timer counts up, and SS remains low, timeout skips ACK and remaining bytes if Ps cuts off communication early while((!(TIFR2 & _BV(TOV2))) && (~SPI_PIN & _BV(SS))); // continue with transmission of the final 4 bytes if adapter is in analog mode, config mode, or if command[1] is 0x43 if(((CSR0 & _BV(ANALOG_MODE_BIT)) || (CSR0 & _BV(CONFIG_MODE_BIT)) || (command[1] == 0x43)) && (~SPI_PIN & _BV(SS))){ _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[2], command[5]); // Right analog X data Byte _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[3], command[5]); // Right analog Y data byte _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[4], command[5]); // Left analog X data byte _delay_us(4); ACKNOWLEDGE; PS_AVR_COMM(final_data[5], command[5]); // Left analog Y data byte }// if analog mode or config mode }// if command[1] == one of the recognised commands }// 0x01 controller address check else{ SPI_PORT &= ~_BV(MISO); // Clear data output DISABLE_SPI; // Disable SPI hardware to avoid conflict with mem-card comm } }// timer overflow and SS line check }// if SS is low SPI_PORT &= ~_BV(MISO); // Clear data output while(~SPI_PIN & _BV(SS)); // Loop until SS returns high after communication is complete /*CONTROLLER POLLING SECTION*****************************************************************************************/ ENABLE_TWI; // re-enable TWI hardware ENABLE_SPI; // re-enable SPI hardware START_TIMER_AT(64); while((!(TIFR2 & _BV(TOV2))) && (SPI_PIN & _BV(SS))); // Loop while timer counts up and SS pin remains high if(SPI_PIN & _BV(SS)){ // if SS line is high, SPI communication is not being requested final_data[0] = 0xFF; // Clear data bytes before controller polling final_data[1] = 0xFF; final_data[2] = 0x80; final_data[3] = 0x80; final_data[4] = 0x80; final_data[5] = 0x80; chuck_data[0] = 0x80; chuck_data[1] = 0x80; chuck_data[2] = 0x80; chuck_data[3] = 0x80; chuck_data[4] = 0x80; chuck_data[5] = 0xFF; // byte containing unused LSBs of accelerometer data and two digital button states if(!(CONFIG_CYCLE_PIN & _BV(CONFIG_CYCLE))){ if(!(GCSR0 & _BV(BUTTON1_LOW_STATUS_BIT))){ // BUTTON1_LOW_STATUS_BIT indicates whether or not the button is already being pressed lcd_instruction_write(CLEAR_SCREEN); _delay_ms(2); switch(display_tracker){ case STANDARD_MODE: lcd_string_print(katamari); lcd_string_print(mode); display_tracker++; break; case KATAMARI_MODE: lcd_string_print(racing); lcd_string_print(mode); display_tracker++; break; case RACING_MODE: lcd_string_print(arcade); lcd_string_print(mode); display_tracker++; break; case ARCADE_MODE: lcd_string_print(turbo); lcd_string_print(mode); display_tracker++; break; case TURBO_MODE: lcd_string_print(serial_in); lcd_string_print(mode); display_tracker++; break; case SERIAL_IN_MODE: lcd_string_print(standard); lcd_string_print(mode); display_tracker = 0; } lcd_instruction_write(RETURN_HOME); GCSR0 |= _BV(BUTTON1_LOW_STATUS_BIT) | _BV(SKIP_POLLING_BIT);// set BUTTON1_LOW_STATUS_BIT and SKIP_POLLING_BIT flags } } if(CONFIG_CYCLE_PIN & _BV(CONFIG_CYCLE)) // if the button is high (default state)... GCSR0 &= ~_BV(BUTTON1_LOW_STATUS_BIT); // ...reset BUTTON0_LOW_STATUS_BIT to wait for next press // controller polling and data formatting is skipped to save time for remainder of main loop after strings are written to LCD, may not be necessary if(!(GCSR0 & _BV(SKIP_POLLING_BIT))){ // if bit is set in game controller status register this means controller is connecteed, configured, and ready for polling if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ BB_PORT &= ~_BV(ATTENTION); // Begin communication with DSC _delay_us(16); // Delay between ATTENTION dropping low and data transmission ps2_comm(0x01); // byte 0; standard header, packets addressing the controller always start with 0x01 DSC_mode_ID = ps2_comm(0x42); // byte 1; standard header, controller replies with mode ID, 0x41 = digital, 0x73 = analog if(ps2_comm(0x00) == 0x5A){ // byte 2; standard header, data reply should always be 0x5A, used to test connection status // checks motor command configuration set by Ps and passes motor commands sent in 0x42 packet to the corresponding small motor in DSC if((CSR0 & _BV(FIRST_MOTOR_BYTE_SMALL)) && (command[1] == 0x42) && (command[3] != 0x00)){ dsc_data[0] = ps2_comm(command[3]);} else if((CSR0 & _BV(SECOND_MOTOR_BYTE_SMALL)) && (command[1] == 0x42) && (command[4] != 0x00)){ dsc_data[0] = ps2_comm(command[4]);} else{ dsc_data[0] = ps2_comm(0x00);} // checks motor command configuration set by Ps and passes motor commands sent in 0x42 packet to the corresponding large motor in DSC if((CSR0 & _BV(FIRST_MOTOR_BYTE_LARGE)) && (command[1] == 0x42) && (command[3] != 0x00)){ dsc_data[1] = ps2_comm(command[3]);} else if((CSR0 & _BV(SECOND_MOTOR_BYTE_LARGE)) && (command[1] == 0x42) && (command[4] != 0x00)){ dsc_data[1] = ps2_comm(command[4]);} else{ dsc_data[1] = ps2_comm(0x00);} for(uint8_t x = 2; x < ((DSC_mode_ID & 0x0F) << 1); x++) // Loop loads data array with mode specific byte count dsc_data[x] = ps2_comm(0x00); _delay_us(16); // Delay following data transmission before ATTENTION returns high BB_PORT |= _BV(ATTENTION); // End communication with DSC LED_PORT &= ~_BV(STATUS_LED_GREEN); // Green status LED on (controller connected) } else{ GCSR0 &= ~_BV(DSC_CONNECT_STATUS_BIT); // if 0x5A not received in command byte 2, controller != connected; set status register accordingly LED_PORT |= _BV(STATUS_LED_GREEN); // Green status LED off } } if(!(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT))){ // this switch handles the configuration commands to send over six main loops when the DSC is first plugged in switch(DSC_config_counter){ case 0: DSC_mode_ID = config_comm(0x42, 0x00, 0x00, 0x00, 0x00); DSC_config_counter = 1; break; // standard initial polling request, 5 bytes total case 1: DSC_mode_ID = config_comm(0x43, 0x01, 0x00, 0x00, 0x00); DSC_config_counter = 2; break; // enter config mode, 5 bytes total case 2: DSC_mode_ID = config_comm(0x44, 0x01, 0x03, 0x00, 0x04); DSC_config_counter = 3; break; // enable analog mode and lock controller, 9 bytes total case 3: DSC_mode_ID = config_comm(0x4D, 0x00, 0x01, 0xFF, 0x04); DSC_config_counter = 4; break; // vibration motor control byte mapping, command[3] = small motor, command[4] = large motor case 4: DSC_mode_ID = config_comm(0x43, 0x00, 0x5A, 0x5A, 0x04); DSC_config_counter = 5; break; // exit config mode case 5: DSC_mode_ID = config_comm(0x42, 0x00, 0x00, 0x00, 0x04); GCSR0 |= _BV(DSC_CONNECT_STATUS_BIT); DSC_config_counter = 0; break; } // test will reset configuration switch if a communication error occurs or controller is disconnected before full configuration is complete if((DSC_mode_ID == 0x00) || (DSC_mode_ID == 0xFF)){ DSC_config_counter = 0; GCSR0 &= ~_BV(DSC_CONNECT_STATUS_BIT);} } if(!(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT))){ // if no nunchuck is connected (default first time through) twi_start(); twi_send_slaw(NUNCHUCK_ADDRESS); // send 7 bit slave address (0x52) plus LSB R/W bit (0) if(TWI_STATUS_CHECK(TW_MT_SLA_ACK)){ // if TWI status register shows that SLA+R was sent and ack'd GCSR0 |= _BV(CHUCK_CONNECT_STATUS_BIT); twi_write_data(0x40); // sending 0x40 followed by 0x00 is necessary to initialise nunchuck twi_write_data(0x00); SEND_TWI_STOP; } else{ GCSR0 &= ~_BV(CHUCK_CONNECT_STATUS_BIT); SEND_TWI_STOP; // important to send stop condition to recover from bus errors } } _delay_us(10); if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if nunchuck is connected as detected by TWI_STATUS_CHECK twi_start(); twi_send_slaw(NUNCHUCK_ADDRESS); if(TWI_STATUS_CHECK(TW_MT_SLA_ACK)){ // TW_MT_SLA_ACK defined in <util/twi.h> GCSR0 |= _BV(CHUCK_CONNECT_STATUS_BIT); twi_write_data(0x00); // 0x00 must be sent to nunchuck before each data packet request SEND_TWI_STOP; _delay_us(10); twi_start(); twi_send_slar(NUNCHUCK_ADDRESS); chuck_data[0] = twi_read_data(1); chuck_data[1] = twi_read_data(1); chuck_data[2] = twi_read_data(1); chuck_data[3] = twi_read_data(1); chuck_data[4] = twi_read_data(1); chuck_data[5] = twi_read_data(0); SEND_TWI_STOP; }// if(TWI_STATUS_CHECK(TW_MT_SLA_ACK)) else{ GCSR0 &= ~_BV(CHUCK_CONNECT_STATUS_BIT); SEND_TWI_STOP; } }// if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)) NES_GET_DATA(nes_data[0], nes_data[1]); // get data from player1 and player2 NES ports saturn_data[0] = saturn_get_first_byte(); // get first byte of button data from saturn controller saturn_data[1] = saturn_get_second_byte(); // get second byte of data from saturn controller /*DATA FORMATTING SECTION********************************************************************************************/ if(display_tracker == STANDARD_MODE){ if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ // if the playstation controller is connected, map the buttons accordingly OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP); OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN); OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT); OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT); OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT); OR_map(dsc_data[0], &final_data[0], PS_START, PS_START); OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3); OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3); OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS); OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE); OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE); OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE); OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1); OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1); OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2); OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2); // if the playstation controller is in analog mode, map the analog sticks as well if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;} } if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if the Wii nunchuck is connected, map some more stuff OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE); remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210); remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200); FINAL_LJOY_X = remapped_x; FINAL_LJOY_Y = remapped_y; map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT); map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT); map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN); map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP); } OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[0], &final_data[0], NES_START, PS_START); OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT); OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE); OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[1], &final_data[0], NES_START, PS_R3); OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE); OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP); OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN); OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT); OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT); OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L2); OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START); OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS); OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE); OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_TRIANGLE); OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE); OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R1); OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L1); OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R2); // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);} // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);} } // special mode for Ps2 game "Katamari Damacy" else if(display_tracker == KATAMARI_MODE){ if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ // if the playstation controller is connected, map the buttons accordingly OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP); OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN); OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT); OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT); OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT); OR_map(dsc_data[0], &final_data[0], PS_START, PS_START); OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3); OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3); OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS); OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE); OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE); OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE); OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1); OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1); OR_map(dsc_data[1], &final_data[0], PS_R2, PS_R3); OR_map(dsc_data[1], &final_data[0], PS_R2, PS_L3); //OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2); // if the playstation controller is in analog mode, map the analog sticks as well if(DSC_mode_ID == 0x73){ FINAL_LJOY_X = DSC_LJOY_X; FINAL_RJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y; FINAL_RJOY_Y = DSC_LJOY_Y; if((DSC_RJOY_X < 0x64) && (DSC_RJOY_X >= 0x3C)){ FINAL_RJOY_Y = 0x00; FINAL_RJOY_X = 0x80; FINAL_LJOY_Y = 0x80; FINAL_LJOY_X = 0x80;} if(DSC_RJOY_X < 0x3C){ FINAL_RJOY_Y = DSC_RJOY_X; FINAL_RJOY_X = 0x80; FINAL_LJOY_Y = (0xFF - DSC_RJOY_X); FINAL_LJOY_X = 0x80;} if((DSC_RJOY_X > 0x9C) && (DSC_RJOY_X <= 0xC4)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_X = 0x80; FINAL_RJOY_Y = 0x80; FINAL_LJOY_X = 0x80;} if(DSC_RJOY_X > 0xC4){ FINAL_LJOY_Y = (0xFF - DSC_RJOY_X); FINAL_RJOY_X = 0x80; FINAL_RJOY_Y = DSC_RJOY_X; FINAL_LJOY_X = 0x80;} } // "katamari roll" macro for L2 button if(~dsc_data[1] & _BV(PS_L2)){ // if L2 button on controller is pressed if(!(MSR0 & _BV(MACRO0_ACTIVE))){ // if the macro is not already active MSR0 |= _BV(MACRO0_ACTIVE) | _BV(MACRO0_TOGGLE); // set the macro active flag } else if(MSR0 & _BV(MACRO0_ACTIVE)){ if((MSR0 & _BV(MACRO0_TOGGLE)) && (katamari_counter < 255)){ FINAL_LJOY_Y = katamari_counter; FINAL_RJOY_Y = (~FINAL_LJOY_Y); katamari_counter = (katamari_counter + 51);} else{ MSR0 &= ~_BV(MACRO0_TOGGLE);} if((~MSR0 & _BV(MACRO0_TOGGLE)) && (katamari_counter > 0)){ FINAL_LJOY_Y = katamari_counter; FINAL_RJOY_Y = (~FINAL_LJOY_Y); katamari_counter = (katamari_counter - 51);} else{ MSR0 |= _BV(MACRO0_TOGGLE);} } } if(dsc_data[1] & _BV(PS_L2)){ MSR0 &= ~_BV(MACRO0_ACTIVE); MSR0 &= ~_BV(MACRO0_TOGGLE); katamari_counter = 0x00;} } if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if the Wii nunchuck is connected, map some more stuff OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[0], NUNCHUCK_Z, PS_R3); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[0], NUNCHUCK_Z, PS_L3); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_R1); remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210); remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200); FINAL_LJOY_X = remapped_x; FINAL_RJOY_X = remapped_x; FINAL_LJOY_Y = remapped_y; FINAL_RJOY_Y = remapped_y; if(remapped_y < 100){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0x00;} if(remapped_y > 150){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0xFF;} if(NUNCHUCK_JOY_X < 0x6F){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0x00;} if(NUNCHUCK_JOY_X > 0xC0){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0xFF;} } if(~saturn_data[1] & _BV(SAT_DOWN)){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0xFF;} if(~saturn_data[1] & _BV(SAT_UP)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0x00;} if(~saturn_data[1] & _BV(SAT_RIGHT)){ FINAL_LJOY_X = 0xFF; FINAL_RJOY_X = 0xFF;} if(~saturn_data[1] & _BV(SAT_LEFT)){ FINAL_LJOY_X = 0x00; FINAL_RJOY_X = 0x00;} if(~saturn_data[0] & _BV(SAT_X)){ FINAL_LJOY_Y = 0xFF; FINAL_RJOY_Y = 0x00;} if(~saturn_data[0] & _BV(SAT_Z)){ FINAL_LJOY_Y = 0x00; FINAL_RJOY_Y = 0xFF;} OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L1); OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START); OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS); OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE); OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE); OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R1); OR_map(saturn_data[0], &final_data[0], SAT_Y, PS_L3); OR_map(saturn_data[0], &final_data[0], SAT_Y, PS_R3); } else if(display_tracker == RACING_MODE){ if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ // if the playstation controller is connected, map the buttons accordingly OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP); OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN); OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT); OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT); OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT); OR_map(dsc_data[0], &final_data[0], PS_START, PS_START); OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3); OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3); OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS); OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE); OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE); OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE); OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1); OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1); OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2); OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2); // if the playstation controller is in analog mode, map the analog sticks as well if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;} } if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if the Wii nunchuck is connected, map some more stuff OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE); remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210); remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200); FINAL_LJOY_X = remapped_x; FINAL_LJOY_Y = remapped_y; map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT); map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT); map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN); map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP); } OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[0], &final_data[0], NES_START, PS_START); OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT); OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE); OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[1], &final_data[0], NES_START, PS_R3); OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE); OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP); OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN); OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT); OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT); OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L2); OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START); OR_map(saturn_data[0], &final_data[1], SAT_B, PS_TRIANGLE); OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE); OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_CROSS); OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE); OR_map(saturn_data[0], &final_data[1], SAT_R, PS_R1); OR_map(saturn_data[1], &final_data[1], SAT_L, PS_L1); OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R2); // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);} // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);} } if(display_tracker == ARCADE_MODE){ if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ // if the playstation controller is connected, map the buttons accordingly OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP); OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN); OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT); OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT); OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT); OR_map(dsc_data[0], &final_data[0], PS_START, PS_START); OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3); OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3); OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS); OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE); OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE); OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE); OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1); OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1); OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2); OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2); // Ps2 button combo to expand controller functionality simulates PS_R3 button if((~dsc_data[1] & _BV(PS_L2)) && (~dsc_data[1] & _BV(PS_R2)) && (~dsc_data[1] & _BV(PS_TRIANGLE)) && (~dsc_data[1] & _BV(PS_CIRCLE)) && (~dsc_data[0] & _BV(PS_UP)) && (~dsc_data[0] & _BV(PS_LEFT))){ final_data[0] &= ~_BV(PS_R3);} // if the playstation controller is in analog mode, map the analog sticks as well if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;} } if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if the Wii nunchuck is connected, map some more stuff OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE); remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210); remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200); FINAL_LJOY_X = remapped_x; FINAL_LJOY_Y = remapped_y; map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT); map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT); map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN); map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP); } OR_map(nes_data[0], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[0], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[0], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[0], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[0], &final_data[0], NES_START, PS_START); OR_map(nes_data[0], &final_data[0], NES_SELECT, PS_SELECT); OR_map(nes_data[0], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[0], &final_data[1], NES_B, PS_SQUARE); OR_map(nes_data[1], &final_data[0], NES_UP, PS_UP); OR_map(nes_data[1], &final_data[0], NES_DOWN, PS_DOWN); OR_map(nes_data[1], &final_data[0], NES_LEFT, PS_LEFT); OR_map(nes_data[1], &final_data[0], NES_RIGHT, PS_RIGHT); OR_map(nes_data[1], &final_data[0], NES_START, PS_R3); OR_map(nes_data[1], &final_data[1], NES_A, PS_CROSS); OR_map(nes_data[1], &final_data[1], NES_B, PS_CIRCLE); OR_map(saturn_data[1], &final_data[0], SAT_UP, PS_UP); OR_map(saturn_data[1], &final_data[0], SAT_DOWN, PS_DOWN); OR_map(saturn_data[1], &final_data[0], SAT_LEFT, PS_LEFT); OR_map(saturn_data[1], &final_data[0], SAT_RIGHT, PS_RIGHT); OR_map(saturn_data[1], &final_data[0], SAT_L, PS_SELECT); OR_map(saturn_data[0], &final_data[0], SAT_START, PS_START); OR_map(saturn_data[0], &final_data[1], SAT_B, PS_CROSS); OR_map(saturn_data[0], &final_data[1], SAT_A, PS_SQUARE); OR_map(saturn_data[0], &final_data[1], SAT_Y, PS_TRIANGLE); OR_map(saturn_data[0], &final_data[1], SAT_C, PS_CIRCLE); OR_map(saturn_data[0], &final_data[1], SAT_Z, PS_R1); OR_map(saturn_data[0], &final_data[1], SAT_X, PS_L1); OR_map(saturn_data[0], &final_data[0], SAT_R, PS_R3); // NES pad button combo for player2 port (select + down) to expand controller functionality, simulates PS_R2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_DOWN))){ final_data[1] &= ~_BV(PS_R2);} // NES pad button combo for player2 port (select + up) to expand controller functionality, simulates PS_L2 button if((~nes_data[1] & _BV(NES_SELECT)) && (~nes_data[1] & _BV(NES_UP))){ final_data[1] &= ~_BV(PS_L2);} // saturn pad button combo to expand controller functionality, simulates PS_R2 button if((~saturn_data[1] & _BV(SAT_L)) && (~saturn_data[1] & _BV(SAT_DOWN))){ final_data[1] &= ~_BV(PS_R2);} // saturn pad button combo to expand controller functionality, simulates PS_L2 button if((~saturn_data[1] & _BV(SAT_L)) && (~saturn_data[1] & _BV(SAT_UP))){ final_data[1] &= ~_BV(PS_L2);} } else if(display_tracker == TURBO_MODE){ (turbo_counter < TURBO_RATE) ? (turbo_counter++): (turbo_counter = 0); if(GCSR0 & _BV(DSC_CONNECT_STATUS_BIT)){ // if the playstation controller is connected, map the buttons accordingly OR_map(dsc_data[0], &final_data[0], PS_UP, PS_UP); OR_map(dsc_data[0], &final_data[0], PS_DOWN, PS_DOWN); OR_map(dsc_data[0], &final_data[0], PS_LEFT, PS_LEFT); OR_map(dsc_data[0], &final_data[0], PS_RIGHT, PS_RIGHT); OR_map(dsc_data[0], &final_data[0], PS_SELECT, PS_SELECT); OR_map(dsc_data[0], &final_data[0], PS_START, PS_START); OR_map(dsc_data[0], &final_data[0], PS_L3, PS_L3); OR_map(dsc_data[0], &final_data[0], PS_R3, PS_R3); OR_map(dsc_data[1], &final_data[1], PS_CROSS, PS_CROSS); //OR_map(dsc_data[1], &final_data[1], PS_SQUARE, PS_SQUARE); OR_map(dsc_data[1], &final_data[1], PS_TRIANGLE, PS_TRIANGLE); OR_map(dsc_data[1], &final_data[1], PS_CIRCLE, PS_CIRCLE); //OR_map(dsc_data[1], &final_data[1], PS_R1, PS_R1); OR_map(dsc_data[1], &final_data[1], PS_L1, PS_L1); OR_map(dsc_data[1], &final_data[1], PS_R2, PS_R2); OR_map(dsc_data[1], &final_data[1], PS_L2, PS_L2); TURBO_MAP(dsc_data[1], final_data[1], PS_SQUARE, PS_SQUARE, TSR0, TURBO0_ACTIVE, TURBO0_TOGGLE); TURBO_MAP(dsc_data[1], final_data[1], PS_R1, PS_R1, TSR0, TURBO1_ACTIVE, TURBO1_TOGGLE); // if the playstation controller is in analog mode, map the analog sticks as well if(DSC_mode_ID == 0x73){ FINAL_RJOY_X = DSC_RJOY_X; FINAL_RJOY_Y = DSC_RJOY_Y; FINAL_LJOY_X = DSC_LJOY_X; FINAL_LJOY_Y = DSC_LJOY_Y;} } if(GCSR0 & _BV(CHUCK_CONNECT_STATUS_BIT)){ // if the Wii nunchuck is connected, map some more stuff OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_Z, PS_CROSS); OR_map(NUNCHUCK_BUTTON_BYTE, &final_data[1], NUNCHUCK_C, PS_SQUARE); remapped_x = range_8bit(NUNCHUCK_TILT_X, 100, 210); remapped_y = ~range_8bit(NUNCHUCK_TILT_Y, 90, 200); FINAL_LJOY_X = remapped_x; FINAL_LJOY_Y = remapped_y; map_a2d_if_less(NUNCHUCK_JOY_X, &final_data[0], 0x6F, PS_LEFT); map_a2d_if_greater(NUNCHUCK_JOY_X, &final_data[0], 0xC0, PS_RIGHT); map_a2d_if_less(NUNCHUCK_JOY_Y, &final_data[0], 0x5F, PS_DOWN); map_a2d_if_greater(NUNCHUCK_JOY_Y, &final_data[0], 0xC0, PS_UP); } } else if(display_tracker == SERIAL_IN_MODE){ // Serial input is not yet implimented, currently this is a placeholder } /*END DATA FORMATTING************************************************************************************************/ }// if skip polling flag is set GCSR0 &= ~_BV(SKIP_POLLING_BIT); // reset skip polling flag to default 0 // the following checks for a single press of the analog/digital select button and toggles the adapters state accordingly if(~ANA_DIG_SELECT_PIN & _BV(ANA_DIG_SELECT)){ if(!(GCSR0 & _BV(BUTTON0_LOW_STATUS_BIT))){ // BUTTON0_LOW_STATUS_BIT indicates whether or not the button is already being pressed if(!(CSR0 & _BV(LOCK_BIT))){ // check if the adapter is already locked in analog mode if(CSR0 & _BV(ANALOG_MODE_BIT)) // if analog mode is already active... CSR0 &= ~_BV(ANALOG_MODE_BIT); // ...turn off analog mode else if(!(CSR0 & _BV(ANALOG_MODE_BIT))) // if analog mode is not active... CSR0 |= _BV(ANALOG_MODE_BIT); // ...turn on analog mode } GCSR0 |= _BV(BUTTON0_LOW_STATUS_BIT); // set BUTTON0_LOW_STATUS_BIT flag so we know the button press has been recognized } } if(ANA_DIG_SELECT_PIN & _BV(ANA_DIG_SELECT)) // if the button is high (default state)... GCSR0 &= ~_BV(BUTTON0_LOW_STATUS_BIT); // ...reset BUTTON0_LOW_STATUS_BIT to wait for next press DISABLE_TWI; // disable TWI hardware to restart in case of errors on bus if(command[1] == 0x42){ // command 0x42 is the main polling command sent continually once the adapter is configured LED_PORT |= _BV(STATUS_LED_RED2); // Red status LED off LED_PORT &= ~_BV(STATUS_LED_GREEN2); // Green status LED on to indicate that everything is cool LED_PORT |= _BV(STATUS_LED_GREEN2); // FOR DEBUGGING _delay_us(4); // FOR DEBUGGING LED_PORT &= ~_BV(STATUS_LED_GREEN2); // FOR DEBUGGING } else{ LED_PORT |= _BV(STATUS_LED_GREEN2); // Green status LED off LED_PORT &= ~_BV(STATUS_LED_RED2); // Red status LED on to indicate that something might be wrong LED_PORT |= _BV(STATUS_LED_RED2); // FOR DEBUGGING _delay_us(4); // FOR DEBUGGING LED_PORT &= ~_BV(STATUS_LED_RED2); // FOR DEBUGGING } // turns on an LED whenever a command is received to turn on the vibration motors if((CSR0 & 0xF0) && (command[1] == 0x42) && ((command[3] != 0x00) || (command[4] != 0x00))){ LED_PORT &= ~_BV(STATUS_LED_MOTOR);} else{ LED_PORT |= _BV(STATUS_LED_MOTOR);} command[1] = 0x00; command[3] = 0x00; command[4] = 0x00; }// if SS line is still high after timeout COMM_IS_OK; // set flag in "CSR0" to allow SPI communication // loop waits for call from spi master, if not called in 20ms loop to top to keep everything else going for(uint8_t x = 0; ((x < 18) && (SPI_PIN & _BV(SS))); x++){ START_TIMER_AT(1); while((!(TIFR2 & _BV(TOV2))) && (SPI_PIN & _BV(SS))); } }// infinite while(1) loop return 0; }// main loop