Skip to content

Commit

Permalink
Three-state machine for button
Browse files Browse the repository at this point in the history
- press and hold: send "r" key (for rewind function of RetroArch)
- press and release three times: send "ESC"
- press and release five times: shutdown
  • Loading branch information
petrockblog committed Nov 13, 2012
1 parent 7952b58 commit 65bf6a5
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 26 deletions.
47 changes: 47 additions & 0 deletions include/button.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* SNESDev - Simulates a virtual keyboard for two SNES controllers that are
* connected to the GPIO pins of the Raspberry Pi.
*
* (c) Copyright 2012 Florian Müller (petrockblog@flo-mueller.com)
*
* SNESDev homepage: https://github.com/petrockblog/SNESDev-RPi
*
* Permission to use, copy, modify and distribute SNESDev in both binary and
* source form, for non-commercial purposes, is hereby granted without fee,
* providing that this license information and copyright notice appear with
* all copies and any derived work.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event shall the authors be held liable for any damages
* arising from the use of this software.
*
* SNESDev is freeware for PERSONAL USE only. Commercial users should
* seek permission of the copyright holders first. Commercial use includes
* charging money for SNESDev or software derived from SNESDev.
*
* The copyright holders request that bug fixes and improvements to the code
* should be forwarded to them so everyone can benefit from the modifications
* in future versions.
*
* Raspberry Pi is a trademark of the Raspberry Pi Foundation.
*/

#ifndef button_h
#define button_h

#include <inttypes.h>
#include <bcm2835.h>
#include <unistd.h>
#include <stdio.h>

/* holds the GPIO pins for the clock, strobe and data signals */
typedef struct {
int
} button;


/* check the state of each button of each controller */
void updateButton();

#endif

89 changes: 63 additions & 26 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,20 @@

/* time to wait after each cycle */
#define FRAMEWAIT 20
#define FRAMEWAITLONG 200
#define FRAMEWAITLONG 100

/* set the GPIO pins of the button and the LEDs. */
#define BUTTONPIN RPI_GPIO_P1_11
#define BTNSTATE_IDLE 0
#define BTNSTATE_PRESS 1
#define BTNSTATE_RELEASE 2


int uinp_fd;
int doRun, pollButton, pollPads;
time_t timePressed;
uint8_t lastBtnState;
time_t btnLastTime;
uint8_t btnState;
uint8_t btnPressCtr;

/* Signal callback function */
void sig_handler(int signo) {
Expand Down Expand Up @@ -128,30 +133,59 @@ void checkButton(int uinh) {
// read the state of the button into a local variable
uint8_t buttonState = bcm2835_gpio_lev(BUTTONPIN);

if (buttonState==HIGH && lastBtnState==LOW) {
timePressed=time(NULL);
} else if (buttonState==LOW && lastBtnState==HIGH) {
time_t curTime = time(NULL);
double dif = difftime(curTime,timePressed);
if ( dif>=3 ) {
// send F4 (quit Emulation Station) and shut down
pollButton = 0;
pollPads = 0;
send_key_event(uinh, KEY_F4,1);
usleep(50000);
send_key_event(uinh, KEY_F4,0);

system("shutdown -t 3 -h now");
} else {
// Sending ESC
send_key_event(uinh, KEY_ESC,1);
usleep(50000);
send_key_event(uinh, KEY_ESC,0);
}

// three-state machine:
// - press and hold: send "r" key (for rewind function of RetroArch)
// - press and release three times: send "ESC"
// - press and release five times: shutdown
switch ( btnState ) {
case BTNSTATE_IDLE:
if (buttonState==HIGH ) {
btnLastTime=time(NULL);
btnState = BTNSTATE_PRESS;
btnPressCtr += 1;
}
break;
case BTNSTATE_PRESS:
if (buttonState==LOW ) {
btnLastTime=time(NULL);
btnState = BTNSTATE_RELEASE;
} else if (buttonState==HIGH && btnPressCtr==1 && difftime(time(NULL),btnLastTime)>1) {
send_key_event(uinh, KEY_R,1);
}
break;
case BTNSTATE_RELEASE:
if (buttonState==LOW && difftime(time(NULL),btnLastTime)>1 ) {

if (btnPressCtr==1) {
send_key_event(uinh, KEY_R,0);
} else if (btnPressCtr==3) {
// Sending ESC
printf("Sending ESC.\n");
send_key_event(uinh, KEY_ESC,1);
usleep(50000);
send_key_event(uinh, KEY_ESC,0);
} else if ( btnPressCtr==5 ) {
printf("Shutting down.\n");
pollButton = 0;
pollPads = 0;
send_key_event(uinh, KEY_F4,1);
usleep(50000);
send_key_event(uinh, KEY_F4,0);

system("shutdown -t 3 -h now");
}

btnLastTime=time(NULL);
btnState = BTNSTATE_IDLE;
btnPressCtr = 0;
} else if (buttonState==HIGH ) {
btnLastTime=time(NULL);
btnState = BTNSTATE_PRESS;
btnPressCtr += 1;
}
break;
}
lastBtnState=buttonState;

// printf("State: %d, ctr: %d\n",btnState,btnPressCtr );
}

/* checks, if a button on the pad is pressed and sends an event according the button state. */
Expand All @@ -172,6 +206,9 @@ int main(int argc, char *argv[]) {
pollPads = 1;
doRun = 1;

btnState = BTNSTATE_IDLE;
btnPressCtr = 0;

// check command line arguments
if (argc > 1) {
// argv[1]==1 poll controllers only
Expand Down

0 comments on commit 65bf6a5

Please sign in to comment.