bengtmartensson / AGirs

A Girs infrared server for the Arduino
http://www.harctoolbox.org/Girs.html
GNU General Public License v2.0
55 stars 13 forks source link

Key presses are reported late by lirc #32

Closed ptsampoukas closed 7 years ago

ptsampoukas commented 7 years ago

I am using GirsLite with lircd (versions 0.9.4d and 0.10.0) and I see that button presses get reported late. Although this can be solved via a configuration change I am reporting it to save time from others.

By default and for most configured remotes, lircd has a large receive timeout. This timeout is called LIRC_SET_REC_TIMEOUT by lircd and receiveending in girs. In my case it was over 100ms as the gap for my remote in the lircd configuration was unnecessarily large (as is in most available conf in the lirc site). Also by default the chosen receive window is 172ms because lirc comes with the devinput remote that has a large gap.

This is a problem because for some remotes many codes can fit in the receive timeout. The first problem is that lircd may drop times because its buffer will quickly get full (with the message "girs: readline buffer full:").

Even if we increase the buffer (by raising LONG_LINE_SIZE in the girs driver) we still have a second problem which is caused by the fact that lircd is designed to decode a single code with each receive command to the driver. If we press two buttons in say 172ms the following may happen:

  1. lircd unblocks in mywaitfordata in the main loop
  2. girs receive gets called, and eventually girs readdata which reads from girslite one line with the times for both buttons in the buffer
  3. the code is decoded and lircd reports the first button press
  4. the main lircd loop blocks in mywaitfordata

The second button press is not reported. When something unblocks curl_poll in mywaitfordata (like a third button press) we get the second button press reported with a significant delay.

Note that timing is important. It is possible that the Arduino is still transmitting the second code when the decoding of the first ends, in which case mywaitfordata will not block. Of course the problem may happen with more button presses.

We can avoid this problem by reducing the gap for all the remotes in the lircd configuration. This was the gap line for my remote:

begin remote
  name  Samsung_BN59-00603A
  bits           16
  ...
  gap          *107567*

An alternative workaround is to modify girslite to not update receiveending from lircd and set a low DEFAULT_RECEIVE_ENDINGTIMEOUT value (for me 30ms was enough).

If a smaller receive timeout is not possible (for example if you have two remotes, one with long and one with short codes) I know no good solution.

bengtmartensson commented 7 years ago

There is the Lirc drvctl, LIRC_SET_REC_TIMEOUT. This is not very often implemented, actually, grep-ping the Lirc plugin directory gives matches only in girs.c. So, when a plugin driver, girs.c (for the first time?) implements it, unwanted effects show up...

It is clear to me that setting receiveending too high is bad, for example with repeating signals (NEC1 comes to my mind). It is not clear to me if the problems you describe are quite correct.

Also by default the chosen receive window is 172ms because lirc comes with the devinput remote that has a large gap.

So why is this so? @leamas, do you know?

As a short-time work-around I would recommend changing line 260 in girs.c from

int millisecs = value / 1000;

to

int millisecs = 30;

As I understand this, AGirs (GirsLite) does what it should. Instead, it appears to be a Lirc problem, and as such should be addressed in a Lirc ticket.

@leamas: care to comment on this?

leamas commented 7 years ago

We can avoid this problem by reducing the gap for all the remotes in the lircd configuration.

Probably not. The gap reflects an actual attribute of the various remotes; the decoding looks for it before starting a new cycle. That said, I cannot see what role the gap plays in the devinput driver - it handles already decoded data, so....

And I don't really understand the map_gap() function in lib/ir_remote.c

So why is this so? @leamas, do you know?

No...

bengtmartensson commented 7 years ago

I opened a Lirc ticket on this, containing a solution proposal.

Ok to close this, and continue in Lirc?

bengtmartensson commented 7 years ago

Closing, since this is about Lirc and/or its Girs driver, and will be treated in the linked ticket.

@ptsampoukas : thank you very much for bringing this problem to my attention.

bengtmartensson commented 7 years ago

The changes to the girs driver has been merged into the main Lirc repository (7f7edd7db7a0aa767e29012320eb041e1e8b8f8b)!

Thanx to @leamas and @ptsampoukas!