Edzelf / ESP32-Radio

Internet radio based on ESP32, VS1053 and a TFT screen.
GNU General Public License v3.0
965 stars 227 forks source link

Recognise Longpress on IR-Remotes #430

Open EFWob opened 3 years ago

EFWob commented 3 years ago

General Idea

Currently only the first press of an IR-Remote key is reported to the application. If you hold the key nothing happens. As this is most often the expected behaviour (i. e. for a preset change), there are situations were you would want the radio to recognise longpress events. Namely if pressing Vol+ or Vol- buttons. This can be achieved by the proposed change.

Application details (how to use the proposed change)

The current approach of handling IR-Events is not altered, but extended. On first press of a key with the code XXXX the preferences are looked up for the existence of the preference setting _irXXXX and the associated command is executed. If the key is hold, the preferences are searched for the setting _irXXXXr and if found, the associated command will be executed.

Consider the example from defaultprefs.h. There you find the setting ir_40BF = upvolume = 2. To have the radio to react on longpress of that key, you should add to the preferences ir_40BFr = upvolume = 1. That will result in a smooth increase of the volume as long as the key is pressed.

The timing distance of repeat events averages around 100ms (could be more or less depending on application load (and the effects of the Nyquist Shannon signal sampling theorem of course and some implementation details of the NEC IR protocol)).

If DEBUG is on, you can observe the Serial output. You will notice that a repeat counter is increased for lonpressed keys. Here an arbitrary example for a key that has no associated entries in the preferences:

21:11:06.848 -> D: IR code 02FD received, but not found in preferences! Timing 558/1681

21:11:06.881 -> D: Longpress IR code 02FD received, repeat count is: 1

21:11:07.014 -> D: Longpress IR code 02FD received, repeat count is: 2

21:11:07.080 -> D: Longpress IR code 02FD received, repeat count is: 3

21:11:07.213 -> D: Longpress IR code 02FD received, repeat count is: 4

21:11:07.312 -> D: Longpress IR code 02FD received, repeat count is: 5

You can hook to a specific repeat of a keypress in the preferences by setting a preference with the pattern _irXXXXrY, where

So, in the example above a preference setting of _ir02FDr2 = reset would result in:

21:30:35.676 -> D: IR code 02FD received, but not found in preferences! Timing 560/1680

21:30:35.709 -> D: Longpress IR code 02FD received, repeat count is: 1

21:30:35.809 -> D: Longpress IR code 02FD received, repeat count is: 2

21:30:35.809 -> D: IR code ir_02FDr2 received. Will execute reset

21:30:35.809 -> D: Command: reset with parameter 0

21:30:35.809 -> D: Command accepted

21:30:36.835 -> ets Jul 29 2019 12:21:46

21:30:36.835 ->

21:30:36.835 -> rst:0xc (SW_CPU_RESET),boot:0x1f (SPI_FAST_FLASH_BOOT)

The following holds true for every sequence for a keypress of key XXXX on the IR remote:

Implementation details

The global variable _irvalue is now _uint32t. It is still produced by _isrIR() and consumed by scanIR(). _isrIR() will set _irvalue to something not Zero if meaningful input has been detected, and scanIR() will reset _irvalue to Zero if the input has been consumed. Major change: the upper half word of _irvalue contains the repeat count. So the sequence for a key press XXXX will be: 0x0000XXXX for the first press followed by 0x0001XXXX, 0x0002XXXX, 0x0003XXXX and so on.

Repeat shots in the NEC IR protocol are coded as frames that start with a 9ms burst (as any dataframe), followed by a 2.25ms space (half of the 4.5ms of a full frame) followed by a 560µs burst. If that pattern is encountered (in _isrIR()) it is checked if there has been a valid key press detected within the last 120ms (could be either an initial press or a repeated press). If so, that key press is reported with an increased repeat counter.

Further more, refer to the comments in the code.