Simulate key being held down in C and WINAPI - c

I'm working on a project where I took a Super Nintendo controller, driving it with an Arduino. The Arduino reads the button presses on the controller, and sends it over a serial connection.
I'm working on a receiver program, which will read from the serial port, and then simulate key presses in Windows, so I can use the controller in other programs.
The thing is, I got pretty much everything down. Except there is one issue.
My simulated keypresses aren't actually being held down.
Here is the code for the A button (buttons are active low, so they are 'false' when being pressed)
if(!(buttonState.state_word & B_A))
{
/* If previous state is not pressed, and current is pressed, simulate a keypress */
if(prevState.state_word & B_A)
keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | 0,0);
}
else if(buttonState.state_word & B_A)
{
/* If previous state is pressed, and current is not pressed, simulate a key release */
if(!(prevState.state_word & B_A))
keybd_event(0x41, 0x41,KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP,0);
}
When I press A on the SNES controller, an A will appear in notepad, for example.
And when I hold the A button on the SNES controller, a single A will appear in notepad, but the terminal will print that the key is being held, like I programmed it to do.
When the button is first pressed from being unpressed, it simulates the keypress. When it's held down, no more calls to simulate a keypress are made. And then when the SNES button is released, the keypress is also released.
Since there is this time between the keydown and the keyup, why is there only a single letter being printed, and not as if the keyboard was being held down and printing repeatedly?

Thanks to all who responded.
I ended up taking a different approach, using SendInput instead this time, and now it works like a charm.
As for the reason while I keep state, the way I saw it was if the button is being held down, I don't want to simulate another keypress each time the controller is polled. So I keep state, such that, if the button is pressed, and next time it is polled it is still being pressed, I won't generate another keypress. It will only be generated when the last state of the controller showed it wasn't pressed.
while(1)
{
prevState = buttonState;
ReadFile( hCOM,
&buttonState.state_word,
2,
&bytesRead,
NULL);
for(i = 0; i < 12; i++)
{
if(!(buttonState.state_word & (1 << i)))
{
/* If previous state is not pressed, and current is pressed, simulate a keypress */
if(prevState.state_word & (1 << i))
{
in[i].ki.dwFlags = KEYEVENTF_SCANCODE;
SendInput(1,&in[i],sizeof(INPUT));
}
}
else if(buttonState.state_word & (1 << i))
{
/* If previous state is pressed, and current is not pressed, simulate a key release */
if(!(prevState.state_word & (1 << i)))
{
in[i].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
SendInput(1,&in[i],sizeof(INPUT));
}
}
}
}

Related

How to make SDL_Keypress detect new Keypress during keypress-loop?

I'm writing Conways game of life in C with SDL. The game logic and everything works fine but I want to have it when you press p for example that the game automatically updates until p is pressed again and the loop stops. Somehow it only repeats once and doesn't even register the second time p is pressed.
else if (e.key.keysym.sym == SDLK_p){
bool stop = false;
while (!stop){
nextEpoch();
updateGame(window, renderer, r);
msleep(500);
if (e.type == SDL_KEYDOWN){
if (e.key.keysym.sym == SDLK_p){
stop = true;
printf("s\n");
}
}
}
}
It doesn't register that p is pressed when it in the while-loop.
Here's the full code: https://gist.github.com/PhilippRados/2df8760cc55822c2eac62addafb24403
As already pointed out by someone else in the comments section, you are not updating e in the inner loop. If you want to update e with a new event, you must call SDL_PollEvent( &e ) again to fill it with a new event.
In your linked code, you seem to be attempting to implement a new state of your program outside the main event loop, which represents the running state of the program, whereas the main event loop represents the paused state of the program. That way, you effectively have two separate event loops, one for each state of the program. While it is possible to make your program work this way, I don't recommend it.
For example, the way you have designed your program, your program won't respond to SDL_QUIT events in the running state. It will only do so in the paused state.
Therefore, it would make more sense to have a single event loop for both the running and the paused states of your program.
I don't recommend that you call usleep or SDL_Delay for waiting until it is time to render the next frame, as your program will not be responding to user input during this time. Especially since you have a very low frame rate of 2 frames per second, this means that it will take up to half a second for your program to respond to user input (for example if the user resizes the window or attempts to close it). Instead, I recommend that you set up a timer using SDL_AddTimer. You can program the timer callback function to give you a SDL_USEREVENT event twice per second. That way, when you receive this event, you will know that it is time to update the game and render the next frame. While waiting for this event, your program will still be able to respond to other events.
Note that in order to use SDL timers, you must initialize the corresponding subsystem using the SDL_INIT_TIMER flag when calling SDL_Init. Strangely, your linked code does not seem to call SDL_Init at all, so I am surprised that your code works at all. According to the documentation, you should call SDL_Init like this:
SDL_Init( SDL_INIT_TIMER | SDL_INIT_VIDEO );
Also, calling SDL_PollEvent in a loop seems like a big waste of CPU resources, as your CPU usage will likely be 100% although you are effectively doing nothing most of the time. I recommend that you call SDL_WaitEvent instead, so that the thread will sleep until it receives a new event to respond to.
Another thing worth noting is that when handling an SDL_MOUSEBUTTONDOWN event, it does not seem appropriate to use the result of SDL_GetMouseState to determine the coordinates of the mouse click, as that function will return the current mouse coordinates and not the coordinates at the time of the click. Therefore, it would be more appropriate to read these coordinates from the SDL_MouseButtonEvent structure.
Here is an example of how you could rewrite your event loop to use SDL_WaitEvent instead of SDL_PollEvent and to support both a running and a paused state in the main event loop.
Uint32 my_callbackfunc( Uint32 interval, void *param )
{
SDL_Event e;
e.user.type = SDL_USEREVENT;
e.user.code = 0;
e.user.data1 = NULL;
e.user.data2 = NULL;
SDL_PushEvent( &e );
return interval;
}
int main (int argc, char** argv)
{
[...]
//set timer to trigger twice per second
SDL_TimerID timer = SDL_AddTimer( 500, my_callbackfunc, NULL );
if ( timer == 0 ) {
//TODO: handle error
return EXIT_FAILURE;
}
//start game in a paused state
bool paused = true;
while ( SDL_WaitEvent( &e ) ) {
switch ( e.type ) {
case SDL_QUIT:
goto quit_game;
case SDL_WINDOWEVENT:
//rerender in case of window state change
updateGame( window, renderer, r );
break;
case SDL_USEREVENT:
if ( !paused ) {
nextEpoch();
updateGame(window, renderer, r);
}
break;
case SDL_MOUSEBUTTONDOWN:
mouseX = getNearestMultiple( e.button.x ) / RECT_SIZE;
mouseY = getNearestMultiple( e.button.y) / RECT_SIZE;
if ( Field[mouseX][mouseY] ) {
//Deactivate cell
Field[mouseX][mouseY] = false;
updateGame(window,renderer,r);
}
else {
//activate cell at position x,y
Field[mouseX][mouseY] = true;
updateGame(window,renderer,r);
}
break;
case SDL_KEYDOWN:
switch ( e.key.keysym.sym ) {
case SDLK_SPACE:
if ( paused ) {
nextEpoch();
updateGame(window, renderer, r);
}
break;
case SDLK_r:
memset(Field,0,sizeof(Field[0][0]) * WIDTH * HEIGHT);
memset(nextState,0,sizeof(nextState[0][0]) * WIDTH * HEIGHT);
updateGame(window,renderer, r);
break;
case SDLK_p:
paused = !paused;
}
}
}
quit_game:
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}

How can I make this while loop faster on a microcontroller button?

I am working with a micro controller that has a button A. When I press this button and hold it for 2 seconds, its value becomes 0 and the color turns either blue or green, when I release, its value goes back to 1 but the color stays the same unless it was clicked again and the color changes. The problem is, it shouldn't take someone 2 whole seconds to have to change the led light. What can I do to make the value (either 0 or 1) be read faster?
Here is a snippet of the code in the while loop.
// here are the states for reference. Everything is either a 0 or a 1
const int BUTTON_PRESSED = 0;
const int BUTTON_UNPRESSED = 1;
const int GREEN_LED = 0;
const int BLUE_LED = 1;
const struct timespec sleepTime = { 1, 0 };
while (true) {
Value_Type value;
// this function get the input of button a when pressed
GetValue(button_A_fd, &value);
Log_Debug(
"Button value (%d)\n", value);
// Processing the button.
//Turns LED ON; Button not pressed down
if (value == BUTTON_UNPRESSED) {
last_button_state = BUTTON_UNPRESSED;
} else {
// if last button state is 1 then now it is being pressed
if (last_button_state == BUTTON_UNPRESSED) {
// Flip LEDs
if (active_led == BLUE_LED) {
active_led = GREEN_LED;
}
else if (active_led == GREEN_LED) {
active_led = BLUE_LED;
}
last_button_state = BUTTON_PRESSED;
// sets the pointer to the 0 bit of the file to write
lseek(fd_storage, 0, SEEK_SET);
// write current active led to mutable storage and save
write(fd_storage, &active_led, sizeof(active_led));
}
}
// Blinking the active LED.
// reading input only when pressed and turn off other led
if (active_led == GREEN_LED) {
// turn off blue led, then turn on green
SetValue(blue_led_fd, Value_High);
SetValue(green_led_fd, Value_Low);
nanosleep(&sleepTime, NULL);
SetValue(green_led_fd, Value_High);
nanosleep(&sleepTime, NULL);
}
else if (active_led == BLUE_LED) {
// turn off green led, then turn on blue
SetValue(green_led_fd, Value_High);
SetValue(blue_led_fd, Value_Low);
nanosleep(&sleepTime, NULL);
SetValue(blue_led_fd, Value_High);
nanosleep(&sleepTime, NULL);
}
}
}
I tried to put GetValue() in several parts of the code to see if it could maybe get a value faster but it did not work. How can I move from here? I hope I shared enough code to understand the problem. Thank you.
Looks like your code reads the button which is fast, and then immediately sets outputs and sleeps 1 second, sets an output and sleeps another second before going up to check if the button is pressed again.
You should restructure the code to check the state of the button more frequently where you're going to sleep now.
Sleep for shorter periods and check to see if the button is pressed in a loop until your total sleep time has been met or the button state changes.
Upon further inspection, I found these:
The above picture is linked from here , it is the spec sheet for your microcontroller.
You want to look at the "Board Pin Map section" from this link to match it with the spec sheet of the chip itself

Constantly check for keyboard input while theres already a loop

Im creating a little game thats like a keyboard version of guitar hero. I'm almost done, but i'm just confused over one thing. I want to constantly be checking if the player is pressing anything on the keyboard and to see if they are pressing the correct key, but I already have a loop that sleeps every 1 second to update the game, so I cant have another loop running at the same time to constantly check the keyboard input (or can I?). I tried putting the keyboard check inside the game loop, but since it sleeps every second, it sometimes doesnt catch when the player presses the key.
This is my while loop:
while (playing)
{
updateBoard(score, game);
checkKeyPress(game);
Sleep(time);
if (rand() % 2 == 1)
spawnNewLetter(game);
}
updateBoard just prints out the new board, spawnNewLetter is just to spawn a new letter to fall down the board, and checkKeyPress is to check the keyboard input, this is it:
void checkKeyPress(char game[GAME_ROW][GAME_COL])
{
if (_kbhit())
{
switch (_getch())
{
case 97:
checkLetter(game, 'a');
break;
case 98:
checkLetter(game, 'b');
break;
The function goes on, but its just repeating to check for all the letters.
Any help would be appreciated, thanks!

Embedded C programming: Clearing LCD properly

I am trying to write the code for an embedded board (RX63N)in which I want to use the LCD along with the on board switches for the following functionality:
On pressing the switch the program should "pause" or "unpause" depending on the previous state and the LCD should display "paused" when it is paused. On unpausing, the LCD should display the custom graphics at the position defined by x and y. It is displayed using the function Set_LCD_Char(N) where N is defined as a custom graphic from a bitmap image. But I will need to clear the LCD before making any changes and that is where I am struggling. On using lcd_clear() function anywhere in the while keeps the LCD blank (or almost blank i.e. the text and graphics are so faint that they are as good as absent) Can someone please help me? heres the code:
while (1)
{
// lcd_clear();
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
}
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
}
else if(!(pause_flag)){
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}
Firstly, it's generally not a good idea to do a busy polling loop as you are doing. But I can't recommend any concrete alternatives as platform and OS (if any) have not been provided (perhaps your platform has no support for events).
Anyway, not sure if this is the answer you need. But since you ask for an example and I can't effectively put code into the comments, below is what I mean. The problem is that you are continuously writing and clearing the LCD. So in effect the two operations are competing with each other. So one way to solve this is to only update the LCD when the state changes.
while (1)
{
if(g_sw3_press == true){ //detect switch press
pause_flag = !pause_flag;
g_sw3_press = false; //reset switch
} else {
/* No state change - nothing to do. Poll again. */
continue;
}
lcd_clear();
if (pause_flag){
RESET_ALL_LEDS();
jet_x = 0;
jet_y = 0;
Set_Font_Bitmap(); //changes from text mode to bitmap
Set_LCD_Pos(jet_x,jet_y);
Set_LCD_Char(3);
} else {
ALL_RED_LEDS_ON();
Set_Font_8_by_8();
lcd_display(LCD_LINE1, " PAUSED ");
}
}

SDL: Timers and WaitEvent

So, the main loop of my game is based on a SDL_WaitEvent type, where it waits for the user to enter new letters while trying to discover a random word. My game need this to work properly but it looks like SDL_WaitEvent stays idle until user press something. The problem is I need my timer to continuosly refresh in order for the player to keep track of it, but when the game reaches the event loop, my timer stays idle and I am not able to find a away to keep it refreshing, any tips would be very appreciated.
Summarizing:
Timer starts: 59 (seconds)
.
.
.
It only will refresh and show the time elapsed when and IF I press something.
SDL_AddTimer() with a callback that uses SDL_PushEvent() to post a user message to the event queue:
/* Start the timer; the callback below will be executed after the delay */
Uint32 delay = (33 / 10) * 10; /* To round it down to the nearest 10 ms */
SDL_TimerID my_timer_id = SDL_AddTimer(delay, my_callbackfunc, my_callback_param);
...
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
/* In this example, our callback pushes an SDL_USEREVENT event
into the queue, and causes our callback to be called again at the
same interval: */
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
return(interval);
}

Resources