 |
forums.ps2dev.org Homebrew PS2, PSP & PS3 Development Discussions
|
| View previous topic :: View next topic |
| Author |
Message |
redflyingpig
Joined: 03 Nov 2005 Posts: 5
|
Posted: Thu Nov 03, 2005 1:01 am Post subject: "Sensitivity" of inputs |
|
|
Hi, I've written an initial testing program on PSP. I use the UP and DOWN buttons as input buttons, when hit, the character displayed changes. It works, only that the inputs are too sensitive. The character changes many times on one hit. Has anybody got the idea to improve this? What is the 'classic' or 'right' way to control input sensitivities? Here is part of my code:
| Code: | int main(void)
{
SceCtrlData pad;
char charList[CHAR_LEN] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','*','/','(',')'};
int curIndex = 0;
pspDebugScreenInit();
SetupCallbacks();
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
while(1) {
pspDebugScreenSetXY(0,0);
printf("Hit UP or DOWN button to change the character:");
pspDebugScreenSetXY(10,10);
printf("Input: %c", charList[curIndex]);
sceCtrlReadBufferPositive(&pad,1);
if(pad.Buttons & PSP_CTRL_UP) {
curIndex = (curIndex + 1) % CHAR_LEN;
}
else
if(pad.Buttons & PSP_CTRL_DOWN) {
curIndex = (curIndex + CHAR_LEN -1) % CHAR_LEN;
}
}
return 0;
}
|
|
|
| Back to top |
|
 |
weltall
Joined: 20 Feb 2004 Posts: 310
|
Posted: Thu Nov 03, 2005 1:11 am Post subject: |
|
|
try putting the result from keys also in a second variable and check if it's equal to the current, so the selected button wont do it's action every time the content of the while is executed like this:
| Code: | int main(void)
{
SceCtrlData pad;
int old_buttons = 0;
char charList[CHAR_LEN] = {'0','1','2','3','4','5','6','7','8','9','.','+','-','*','/','(',')'};
int curIndex = 0;
pspDebugScreenInit();
SetupCallbacks();
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_DIGITAL);
sceCtrlReadBufferPositive(&pad,1);
old_buttons = pad.buttons;
while(1) {
pspDebugScreenSetXY(0,0);
printf("Hit UP or DOWN button to change the character:");
pspDebugScreenSetXY(10,10);
printf("Input: %c", charList[curIndex]);
sceCtrlReadBufferPositive(&pad,1);
if(pad.buttons != old_buttons)
{
old_buttons = pad.buttons;
if(pad.Buttons & PSP_CTRL_UP) {
curIndex = (curIndex + 1) % CHAR_LEN;
}
else
if(pad.Buttons & PSP_CTRL_DOWN) {
curIndex = (curIndex + CHAR_LEN -1) % CHAR_LEN;
}
}
} |
|
|
| Back to top |
|
 |
redflyingpig
Joined: 03 Nov 2005 Posts: 5
|
Posted: Thu Nov 03, 2005 1:35 am Post subject: |
|
|
Thanks, weltall, but that does not give me the intended result. The character will not change any more when the same button is pressed repeatedly, if the code is modified like this, which is not what I intended to do.
I'm currenly thinking of using timestamps to make the input more 'stable'. |
|
| Back to top |
|
 |
weltall
Joined: 20 Feb 2004 Posts: 310
|
Posted: Thu Nov 03, 2005 3:08 am Post subject: |
|
|
you need to wait a cicle before pressing the button again or it wont work, else you need to check that the button was pressed before and if so check how much time it was pressed, if so trigger a faster scrolling.
you could use cputicks you can find the function to get it from psppower if i remember correctly |
|
| Back to top |
|
 |
CyberBill
Joined: 26 Jul 2005 Posts: 86 Location: Redmond, WA
|
Posted: Thu Nov 03, 2005 6:21 am Post subject: |
|
|
One cycle isnt enough.
The typical way to do key holding is to set a timer when you press the key down, and once that timer reaches some value (400ms or so) you signal the output again, and then set the timer back to something like 300ms, so that the next signal only takes 100ms... This is how you get the effect of holding a keyboard key down.
Try it out..
OOOOOOOOOOOOOOOOOOOOOOOOOOOO :D
(This means you'll have to implement a timer system, as a counter is totally inaccurate) |
|
| Back to top |
|
 |
redflyingpig
Joined: 03 Nov 2005 Posts: 5
|
Posted: Thu Nov 03, 2005 7:25 am Post subject: |
|
|
| Could you give me more information about setting up a timer, like, which functions can be utilized to implement it? |
|
| Back to top |
|
 |
Arwin
Joined: 12 Jul 2005 Posts: 426
|
Posted: Thu Nov 03, 2005 8:08 am Post subject: |
|
|
| redflyingpig wrote: | | Could you give me more information about setting up a timer, like, which functions can be utilized to implement it? |
You don't need a special function. You can just add a counter to the routine with which you check the controller now. |
|
| Back to top |
|
 |
CyberBill
Joined: 26 Jul 2005 Posts: 86 Location: Redmond, WA
|
Posted: Thu Nov 03, 2005 8:44 am Post subject: |
|
|
Dont use a counter.
| Code: |
unsigned GetMilliseconds()
{
SceKernelSysClock clock;
sceKernelGetSystemTime(&clock);
unsigned time = clock.low / 1000;
time += clock.hi * (0xFFFFFFFF / 1000);
return time;
}
|
This gets the time. When someone presses a Key, set somewhere what the current time is and what the key they pressed is, and maybe a flag saying a key is down. Then, every 'frame' or update, check the current time against that time:
| Code: |
if ( KeyBeingHeld && ( GetMilliseconds() - KeyDownTime > REPEAT_WAIT ) )
{
//Repeat the key event
KeyDownTime -= REPEAT_INTERVAL;
}
|
Where REPEAT_WAIT is an unsigned int corresponding to the number of milliseconds it takes before the first repeat is done, and where REPEAT_INTERVAL is the time between subsequent repeats.
REPEAT_WAIT ~= 400; REPEAT_INTERVAL ~= 100; Those should give you decent results.[/code] |
|
| Back to top |
|
 |
redflyingpig
Joined: 03 Nov 2005 Posts: 5
|
Posted: Thu Nov 03, 2005 9:04 am Post subject: |
|
|
Thanks a lot, CyberBill. I know what you mean, it's a rather accurate solution, however, I've found another way, by simply adding a loop:
| Code: | for(i=0; i<6; i++) {
sceDisplayWaitVblankStart(); |
at the end of each iteration. In this way I set intervals between frames so that the input won't be updated that fast and thus the input becomes less sensitive. Currently it works fine but I don't know exactly what's going on. Could you explain the up/down sides of these solutions? And also, can anybody explain for me what the function 'sceDisplayWaitVblankState()' is doing? |
|
| Back to top |
|
 |
CyberBill
Joined: 26 Jul 2005 Posts: 86 Location: Redmond, WA
|
Posted: Thu Nov 03, 2005 9:11 am Post subject: |
|
|
sceDisplayWaitVBlankStart() waits until the VSynch gets called to the OS. Its tied into the screen refresh rate, the PSP refreshes 60 times a second. So calling it 6 times in a tight loop essentially is the same thing as doing a sceKernelDelayThread( 6 * (1000000/60) ); which should be 100 milliseconds or 100,000 microseconds..
The upside to this solution is that its easy and gets the job done. The bad side is that the code isnt going to port well if you plan on doing a game because some code needs to have full control of the graphics system and game loop, and this throws it out of whack. And dont even think about trying to do that in a multithreaded situation where you have some other system drawing, very strange results I'm sure!! |
|
| Back to top |
|
 |
redflyingpig
Joined: 03 Nov 2005 Posts: 5
|
Posted: Thu Nov 03, 2005 9:47 am Post subject: |
|
|
| Thanks a lot for help! |
|
| Back to top |
|
 |
JustChris
Joined: 03 Nov 2005 Posts: 21
|
Posted: Sun Nov 06, 2005 1:26 pm Post subject: |
|
|
I decided to ask the following here because it's related to the topic, instead of making another topic:
How do I detect when a button is released?
For example, I need to make an event happen only once when the button is pressed/held down. And maybe, I want something else to happen after the button is released.[/code] |
|
| Back to top |
|
 |
weltall
Joined: 20 Feb 2004 Posts: 310
|
Posted: Sun Nov 06, 2005 6:44 pm Post subject: |
|
|
you could do something like that if it's only one button
sceCtrlReadBufferPositive(&pad,1);
if(pad.Buttons & PSP_CTRL_BUTTON)
{
//do action
}
else
{
//stop action
} |
|
| Back to top |
|
 |
CyberBill
Joined: 26 Jul 2005 Posts: 86 Location: Redmond, WA
|
Posted: Sun Nov 06, 2005 9:19 pm Post subject: |
|
|
sceCtrlReadBufferPositive() will set the "buttons" flags with the current state of the buttons (if the flag is present then that means the button is pressed down, if its not present then the button is not pressed).
The code from weltall only handles half of this. What you really want to do is detect not when the button is not pressed, but when the button's state changes from not pressed to pressed and back.
So:
| Code: |
static int oldstate = 0;
SceCtrlData state;
sceCtrlReadBufferPositive(&state, 1);
for(int i=0; i<32; i++)
{
if ((state.Buttons & (1<<i)) != (oldstate & (1<<i))
{
//Button 'i' was changed!!
if (state.Buttons & (1<<i))
{
//Button i was PRESSED
}
else
{
//Button i was RELEASED
}
}
}
oldstate = state.Buttons;
|
You can then compare 'i' to the different #defines (SCE_CTRL_SELECT, SCE_CTRL_UP, etc) to see what logical button it is. Also, clearly there is not 32 buttons... But the bits are all over the place. You could technically do different ifs for each button instead of a loop, but it wouldnt be good coding style.
Id also like to point out that there is latch functionality in the PSP to do some hardware switches that apparantly is more correct, and wont ever miss button presses (wheras this could potential miss a press if the app was slow enough). However I havnt looked into this... you may want to search and see how it works.
Good luck! |
|
| Back to top |
|
 |
nerdcore
Joined: 07 Nov 2005 Posts: 1 Location: Ottawa, ON, CA
|
Posted: Mon Nov 07, 2005 12:06 pm Post subject: sceCtrlSetSamplingCycle? |
|
|
One easy solution for slowing input would be to sleep the input thread using sceKernelDelayThread(int microsecs).
| Code: | while (1) {
sceCtrlReadBufferPositive(&input, 1);
if (input.Buttons & PSP_CTRL_UP) { }
if (input.Buttons & PSP_CTRL_DOWN) { }
sceKernelDelayThread(333333); // Delay for about 1/3 second
} |
This is not as nice a solution as checking the time of input against the last input, but perhaps cleaner than assuming sceDisplayWaitVblankStart() takes any given length of time, because it is not dependant on the system refresh rate.
But my question would be this: What exactly does sceCtrlSetSamplingCycle(int arg) do? It sounds to me like this would be a sensible way to change the sampling rate of the controls, but the pspsdk doc suggests that this always be set to 0. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|