int main(int argc, char *argv[]) { buttonstates padButtons; snespad pads; pollButton = 1; pollPads = 1; doRun = 1; // check command line arguments if (argc > 1) { // argv[1]==1 poll controllers only // argv[1]==2 poll button only // argv[1]==3 poll controllers and button switch ( atoi(argv[argc-1]) ) { case 1: printf("[SNESDev-Rpi] Polling only controllers.\n"); pollButton = 0; pollPads = 1; break; case 2: printf("[SNESDev-Rpi] Polling button only.\n"); pollButton = 1; pollPads = 0; break; case 3: printf("[SNESDev-Rpi] Polling controllers and button.\n"); pollButton = 1; pollPads = 1; break; default: return -1; } } else { printf("[SNESDev-Rpi] Polling controllers and button.\n"); } if (!bcm2835_init()) return 1; // initialize button and LEDs bcm2835_gpio_fsel(BUTTONPIN, BCM2835_GPIO_FSEL_INPT); /* initialize controller structures with GPIO pin assignments */ // pin out used in SNESDev article on blog // pads.clock = RPI_GPIO_P1_18; // pads.strobe = RPI_GPIO_P1_16; // pads.data1 = RPI_GPIO_P1_22; // pads.data2 = RPI_GPIO_P1_15; // pin out used pi gamecon GPIO driver pads.clock = RPI_GPIO_P1_19; pads.strobe = RPI_GPIO_P1_23; pads.data1 = RPI_GPIO_P1_07; pads.data2 = RPI_GPIO_P1_05; /* set GPIO pins as input or output pins */ initializePads( &pads ); /* intialize virtual input device */ if ((uinp_fd = setup_uinput_device()) < 0) { printf("[SNESDev-Rpi] Unable to find uinput device\n"); return -1; } if (signal(SIGINT, sig_handler) == SIG_ERR) printf("\n[SNESDev-Rpi] Cannot catch SIGINT\n"); /* enter the main loop */ while ( doRun ) { if (pollButton) { /* Check state of button. */ checkButton(uinp_fd); } if (pollPads) { /* read states of the buttons */ updateButtons(&pads, &padButtons); /* send an event (pressed or released) for each button */ /* key events for first controller */ processPadBtn(padButtons.buttons1, SNES_A, KEY_X, uinp_fd); processPadBtn(padButtons.buttons1, SNES_B, KEY_Z, uinp_fd); processPadBtn(padButtons.buttons1, SNES_X, KEY_S, uinp_fd); processPadBtn(padButtons.buttons1, SNES_Y, KEY_A, uinp_fd); processPadBtn(padButtons.buttons1, SNES_L, KEY_Q, uinp_fd); processPadBtn(padButtons.buttons1, SNES_R, KEY_W, uinp_fd); processPadBtn(padButtons.buttons1, SNES_SELECT,KEY_RIGHTSHIFT, uinp_fd); processPadBtn(padButtons.buttons1, SNES_START, KEY_ENTER, uinp_fd); processPadBtn(padButtons.buttons1, SNES_LEFT, KEY_LEFT, uinp_fd); processPadBtn(padButtons.buttons1, SNES_RIGHT, KEY_RIGHT, uinp_fd); processPadBtn(padButtons.buttons1, SNES_UP, KEY_UP, uinp_fd); processPadBtn(padButtons.buttons1, SNES_DOWN, KEY_DOWN, uinp_fd); // key events for second controller processPadBtn(padButtons.buttons2, SNES_A, KEY_E, uinp_fd); processPadBtn(padButtons.buttons2, SNES_B, KEY_R, uinp_fd); processPadBtn(padButtons.buttons2, SNES_X, KEY_T, uinp_fd); processPadBtn(padButtons.buttons2, SNES_Y, KEY_Y, uinp_fd); processPadBtn(padButtons.buttons2, SNES_L, KEY_U, uinp_fd); processPadBtn(padButtons.buttons2, SNES_R, KEY_I, uinp_fd); processPadBtn(padButtons.buttons2, SNES_SELECT,KEY_O, uinp_fd); processPadBtn(padButtons.buttons2, SNES_START, KEY_P, uinp_fd); processPadBtn(padButtons.buttons2, SNES_LEFT, KEY_C, uinp_fd); processPadBtn(padButtons.buttons2, SNES_RIGHT, KEY_B, uinp_fd); processPadBtn(padButtons.buttons2, SNES_UP, KEY_F, uinp_fd); processPadBtn(padButtons.buttons2, SNES_DOWN, KEY_V, uinp_fd); } /* wait for some time to keep the CPU load low */ delay(FRAMEWAIT); } return 0; }
int main(int argc, char *argv[]) { uint8_t ctr = 0; GPAD_ST gpads[GPADSNUM]; BTN_DEV_ST button; int16_t clockpin; int16_t strobepin; int16_t data1pin; int16_t data2pin; int16_t clockpin_v2; int16_t strobepin_v2; int16_t data1pin_v2; int16_t data2pin_v2; if (!bcm2835_init()) return 1; if (readConfigurationfile() != 0 ) { return 1; } if (strcmp(confres.adapter_version,"1x")==0) { clockpin = RPI_GPIO_P1_19; strobepin = RPI_GPIO_P1_23; data1pin = RPI_GPIO_P1_05; data2pin = RPI_GPIO_P1_07; clockpin_v2 = RPI_V2_GPIO_P1_19; strobepin_v2 = RPI_V2_GPIO_P1_23; data1pin_v2 = RPI_V2_GPIO_P1_05; data2pin_v2 = RPI_V2_GPIO_P1_07; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 1.X\n"); } else if (strcmp(confres.adapter_version,"2x")==0) { clockpin = RPI_GPIO_P1_16; strobepin = RPI_GPIO_P1_18; data1pin = RPI_GPIO_P1_15; data2pin = RPI_GPIO_P1_13; clockpin_v2 = RPI_V2_GPIO_P1_16; strobepin_v2 = RPI_V2_GPIO_P1_18; data1pin_v2 = RPI_V2_GPIO_P1_15; data2pin_v2 = RPI_V2_GPIO_P1_13; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 2.X\n"); } else { clockpin = RPI_GPIO_P1_16; strobepin = RPI_GPIO_P1_18; data1pin = RPI_GPIO_P1_15; data2pin = RPI_GPIO_P1_13; clockpin_v2 = RPI_V2_GPIO_P1_16; strobepin_v2 = RPI_V2_GPIO_P1_18; data1pin_v2 = RPI_V2_GPIO_P1_15; data2pin_v2 = RPI_V2_GPIO_P1_13; printf("[SNESDev-Rpi] Using pin setup for RetroPie GPIO-Adapter Version 2.X\n"); } if (confres.gamepad1_enabled || confres.gamepad2_enabled) { gpads[0].port = 1; gpads[1].port = 1; // check board revision and set pins to be used // these are acutally also used by the gamecon driver if (get_rpi_revision()==1) { gpads[0].pin_clock = clockpin; gpads[0].pin_strobe = strobepin; gpads[0].pin_data = data1pin; gpads[1].pin_clock = clockpin; gpads[1].pin_strobe = strobepin; gpads[1].pin_data = data2pin; } else { gpads[0].pin_clock = clockpin_v2; gpads[0].pin_strobe = strobepin_v2; gpads[0].pin_data = data1pin_v2; gpads[1].pin_clock = clockpin_v2; gpads[1].pin_strobe = strobepin_v2; gpads[1].pin_data = data2pin_v2; } if (strcmp(confres.gamepad1_type,"nes")==0) { gpads[0].type = GPAD_TYPE_NES; } else { gpads[0].type = GPAD_TYPE_SNES; } if (strcmp(confres.gamepad2_type,"nes")==0) { gpads[1].type = GPAD_TYPE_NES; } else { gpads[1].type = GPAD_TYPE_SNES; } if (confres.gamepad1_enabled) { printf("[SNESDev-Rpi] Enabling game pad 1 with type '%s'.\n", confres.gamepad1_type); gpad_open(&gpads[0]); switch (gpads->type) { case GPAD_TYPE_SNES: uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_SNES); break; case GPAD_TYPE_NES: uinput_gpad_open(&uinp_gpads[0], UINPUT_GPAD_TYPE_NES); break; default: break; } } if (confres.gamepad2_enabled) { printf("[SNESDev-Rpi] Enabling game pad 2 with type '%s'.\n", confres.gamepad2_type); gpad_open(&gpads[1]); switch (gpads->type) { case GPAD_TYPE_SNES: uinput_gpad_open(&uinp_gpads[1], UINPUT_GPAD_TYPE_SNES); break; case GPAD_TYPE_NES: uinput_gpad_open(&uinp_gpads[1], UINPUT_GPAD_TYPE_NES); break; default: break; } } } if (confres.button_enabled) { printf("[SNESDev-Rpi] Enabling button.\n"); button.port = 1; if (get_rpi_revision()==1) { button.pin = BUTTONPIN; } else { button.pin = BUTTONPIN_V2; } btn_open(&button); uinput_kbd_open(&uinp_kbd); } register_signalhandlers(); ///* enter the main loop */ doRun = 1; while (doRun) { if (confres.gamepad1_enabled || confres.gamepad2_enabled) { /* read states of the buttons */ for (ctr = 0; ctr < GPADSNUM; ctr++) { gpad_read(&gpads[ctr]); } ///* send an event (pressed or released) for each button */ for (ctr = 0; ctr < GPADSNUM; ctr++) { if ((ctr==0 && !(confres.gamepad1_enabled)) || (ctr==1 && !(confres.gamepad2_enabled))) { continue; } gpad_read(&gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_A, BTN_A, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_B, BTN_B, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_X, BTN_X, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_Y, BTN_Y, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_L, BTN_TL, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_R, BTN_TR, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_SELECT, BTN_SELECT, &uinp_gpads[ctr]); processPadBtn(gpads[ctr].state, EV_KEY, GPAD_SNES_START, BTN_START, &uinp_gpads[ctr]); if ((gpads[ctr].state & GPAD_SNES_LEFT) == GPAD_SNES_LEFT) { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 0, EV_ABS); } else if ((gpads[ctr].state & GPAD_SNES_RIGHT) == GPAD_SNES_RIGHT) { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 4, EV_ABS); } else { uinput_gpad_write(&uinp_gpads[ctr], ABS_X, 2, EV_ABS); } if ((gpads[ctr].state & GPAD_SNES_UP) == GPAD_SNES_UP) { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 0, EV_ABS); } else if ((gpads[ctr].state & GPAD_SNES_DOWN) == GPAD_SNES_DOWN) { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 4, EV_ABS); } else { uinput_gpad_write(&uinp_gpads[ctr], ABS_Y, 2, EV_ABS); } } } if (confres.button_enabled) { btn_read(&button); switch (button.state) { case BTN_STATE_IDLE: break; case BTN_STATE_PRESSED: if (button.pressedCtr == 1 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_R, 1, EV_KEY); } break; case BTN_STATE_RELEASED: if (button.pressedCtr == 1 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_R, 0, EV_KEY); } else if (button.pressedCtr == 3 && button.duration >= 1) { // Sending ESC uinput_kbd_write(&uinp_kbd, KEY_ESC, 1, EV_KEY); usleep(50000); uinput_kbd_write(&uinp_kbd, KEY_ESC, 0, EV_KEY); } else if (button.pressedCtr == 5 && button.duration >= 1) { uinput_kbd_write(&uinp_kbd, KEY_F4, 1, EV_KEY); usleep(50000); uinput_kbd_write(&uinp_kbd, KEY_F4, 0, EV_KEY); // shutting down system("shutdown -t 3 -h now"); } break; } } /* wait for some time to keep the CPU load low */ if (confres.button_enabled && !(confres.gamepad1_enabled || confres.gamepad2_enabled)) { bcm2835_delay(FRAMEWAITLONG); } else { bcm2835_delay(FRAMEWAIT); } } return 0; }