Jump to content
Flirc Forums

Stuck keys - potential solution


jdunne525
 Share

Recommended Posts

Hello,
 

I have the same "Keys stuck" problem that many others seem to have recently.  As in this thread:

 

I'm using openelec on an x86 computer and I'm using a Samsung TV remote to control it.

I am a firmware programmer with experience in USB HID devices and I've studied this problem with my USB analyzer.  I believe I understand the problem. 

First a bit of background:
The Flirc firmware enumerates as a USB HID keyboard which sends keypresses.  It also detects IR signals from remotes.  IR remotes use codes that repeat when a button is held down, so filtering is necessary to prevent unwanted repetition of a keypress.  

Keyboards also have key repeat rates, but it is implemented differently than IR remotes.  USB Keyboards use key on and key off messages.  It is up to the OS or application to fascilitate key repeat.  The problem is that this key repeat delay varies from O/S to O/S, and in some cases from program to program, which is why the inter-key delay settings don't work the same for everyone.  If you press and hold down a key on your keyboard you'll see the keypress immediately register, then a short delay, then it will begin to repeat that key.  

Another thing that complicates things is that IR signals takes some time to actually be received and the IR remote repeat rate varies from remote to remote.. I'm assuming that the vast majority of remotes should take less than 50mS to send a key press, hence my default InterButtonDelay value below.  

I've captured the USB traffic with several different inter-key delay settings in the Flirc v3.1 firmware.  It appears that the inter-key delay setting is actually changing 2 separate things with one delay.   I think this is where the trouble lies.  Both the IR command ignore delay AND the key down time seem to be modified by this one setting.  If the delay is set too low, then the IR repeat rate becomes the dominant factor and you get multiple key presses because of the IR remote sending too quickly (which is unavoidable).  If the delay is set high, then the key down time starts becoming long enough that the O/S thinks the key is being held down, so it starts repeating the key.  The key down time shouldn't be increased simply because the IR button delay time is increased.  When changing both of these, it becomes a balancing act between the two indpendent problems.  Most people don't realize that setting the delay to 6 isn't actually the safest choice and 0 doesn't work well either.  It isn't obvious why this would be the case though.  You really have to find the happy medium that works best. I found a setting of 5 worked best for me, but it still wasn't working completely perfectly.

I propose a different implementation of the inter-key delay that works by detecting how long the button has been released and sending the key up message as soon as it has been detected as released. 

 

Expected behavior:
*If the button is pressed rapidly, as long as there is at least a 50mS pause between presses (button press 20 times per second should be a reasonable limit), then all presses should be recognized as individual presses and releases.
*If the button is held down, as long as it is not released for more than 50mS, then the key released event will not be fired and the OS will eventually start repeating the key as expected.
*If two different buttons are pressed within 50mS of each other, then the first will be pressed briefly and released as the next is pressed. (This should yield expected behavior)

 

I implemented the keyboard sending code as a queue to guarantee that if 2 commands are needed back to back before the next USB EP1 IN request, then both are guaranteed to be done.  This could be implemented a few different ways.  A queue is just the mechanism I used.

 

Initialization:
    ButtonPressed = false;
    ButtonReleasedTime = 0;
    InterButtonDelay = 50;            //default value in milliseconds.. should be configurable.  (this is the time the button is RELEASED, not held...)


Upon receiving a recognized IR command (ReceivedKeyCode):
    if (!ButtonPressed) {
        QueueSendKeyboardCode(ReceivedKeyCode);
    
        //new button pressed:
        ButtonReleasedTime = 0;                //Keep track of how long the button has been released
        ButtonPressed = true;
        ButtonPressKeyCode = ReceivedKeyCode;
    }
    else {
        //a button was pressed and we are waiting the minimum release time of that button:
        if (ButtonPressKeyCode == ReceivedKeyCode) {
            //Same button was pressed:
            ButtonReleasedTime = 0;        //restart the release timer
        }
        else {
            //different button pressed before the release timeout.  Switch buttons
            QueueSendRelease();                            //release previously held button
            QueueSendKeyboardCode(ReceivedKeyCode);        //send new button

            //new button pressed:
            ButtonReleasedTime = 0;
            ButtonPressed = true;
            ButtonPressKeyCode = ReceivedKeyCode;
        }
    }


Timer routine (every millisecond - should be thread safe... should be non-interrupt context: same as above code):
    if (ButtonPressed) {
        ButtonReleasedTime++;
            
        if (ButtonReleasedTime > InterButtonDelay) {
            QueueSendReleased();
            
            ButtonPressed = false;
        }
    }
 

By the way, I understand that this is a closed source project, but if you'd allow me access to the source I'd be happy to work on the project.  I don't have direct experience with Atmel chips, but I have worked with Microchip and ST, and to be honest it doesn't make all that much difference once you have the basic framework in place.

 

I've attached one of the USB captures I made that I exported to excel format to analyze what was going on.

 

Joe

flic brief presses several repeats interkeydelay is 3.zip

Link to comment
Share on other sites

Jason,

 

I'm in the U.S. near Chicago.  I'm glad my work was helpful.  It's refreshing to see that you are as attentive as you are on these forums.  It's quite rare to be able to actually talk with somebody that developed a product I bought on Amazon.  I see you posted an experimental version in the "Keys Stuck" thread.  Is that my suggestion?  I'd like to try it out if so.  I'm at work now right now , so I'll try and find you on skype later tonight.

 

Joe

Edited by jdunne525
Link to comment
Share on other sites

Jason,

 

I'm in the U.S. near Chicago.  I'm glad my work was helpful.  It's refreshing to see that you are as attentive as you are on these forums.  It's quite rare to be able to actually talk with somebody that developed a product I bought on Amazon.  I see you posted an experimental version in the "Keys Stuck" thread.  Is that my suggestion?  I'd like to try it out if so.  I'm at work now right now , so I'll try and find you on skype later tonight.

 

Joe

My pleasure, I poor my heart into this project, so it means a lot for the kind feedback.

 

Yeah, I'll talk further with you about that, but I did post a new firmware image. Give it a shot, I'm pretty confident in it, but no one has tried it.

 

Thanks so much, I really appreciate it.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...