Browse Source

- 2022-01-11
- EXTENDED REPEAT mode - wenn eine Taste gedrückt gehalten wird:
- erst langsame Wiederholung
- dann wird statt schneller Wiederholung auf HOLD geschaltet
- normaler REPEAT Modus weiterhin vorhanden
- TASK SWITCH verbessert
- POWER BUTTON verbessert
- Handling für NEC Fernbedienungen mit Repeat, Ext.Repeat und Hold
- Handling für RC5/RC6 Fernbedienungen verbessert
- diverse kleine Verbesserungen
- TOSHIBA SE-R0319 (NEC-Code) Fernbedienung wird nun unterstützt

FloKra 2 years ago
parent
commit
0765efc887

+ 15 - 0
CHANGELOG.md

@@ -1,3 +1,18 @@
+- 2022-01-11
+
+  - EXTENDED REPEAT mode - wenn eine Taste gedrückt gehalten wird: 
+    - erst langsame Wiederholung
+    - dann wird statt schneller Wiederholung auf HOLD geschaltet
+  - normaler REPEAT Modus weiterhin vorhanden
+  - TASK SWITCH verbessert
+  - POWER BUTTON verbessert 
+  - Handling für NEC Fernbedienungen mit Repeat, Ext.Repeat und Hold
+  - Handling für RC5/RC6 Fernbedienungen verbessert
+  - diverse kleine Verbesserungen
+  - TOSHIBA SE-R0319 (NEC-Code) Fernbedienung wird nun unterstützt
+  
+  
+  
 - 2022-01-07
 
   - HOLD-Mode bei RC5/RC6: anstatt repeats zu senden (eigene Keyboard Tastendrücke) wird bei Tasten, die auf "HOLD" konfiguriert sind die Taste nicht sofort (virtuall) losgelassen. Wird die Taste der Fernbedienung weiter gehalten so bleibt die virtuelle Keyboardtaste gedrückt, bis die FB-Taste losgelassen wurde (mit timeout). 

+ 350 - 86
src/IR-PC-HID-Remote/IR-PC-HID-Remote.ino

@@ -4,6 +4,10 @@
 #include <IRremote.h>
 #include <HID-Project.h>  // HID-Project 2.8.2
 
+// switch on/off debug mode at once
+bool isDebugBuild = false;
+
+// enable HID Keyboard output
 bool sendHID = true;
 
 // ATTENTION - set ALL debug and useSerial to false in normal usage
@@ -13,8 +17,9 @@ bool debug2 = false;
 bool useSerial = false;
 
 // global conf vars
-unsigned int holdButton_releaseTimeout = 120;
+unsigned int holdButton_releaseTimeout = 120; // global default, will be overwritten depending on RC code used
 
+#define BTN_UNKNOWN 0
 
 #define BTN_1 1
 #define BTN_2 2
@@ -26,6 +31,7 @@ unsigned int holdButton_releaseTimeout = 120;
 #define BTN_8 8
 #define BTN_9 9
 #define BTN_0 10
+
 #define BTN_PLAY 11
 #define BTN_PAUSE 12
 #define BTN_STOP 13
@@ -35,29 +41,37 @@ unsigned int holdButton_releaseTimeout = 120;
 #define BTN_PREV 17
 #define BTN_NEXT 18
 #define BTN_LEFT 20
+
 #define BTN_RIGHT 21
 #define BTN_UP 22
 #define BTN_DOWN 23
 #define BTN_OK_ENTER 24
+
 #define BTN_BACK 25
 #define BTN_MENU 26
 #define BTN_HOME 27
+
 #define BTN_RED 30
 #define BTN_GREEN 31
 #define BTN_YELLOW 32
 #define BTN_BLUE 33
+
 #define BTN_STATUS 34
 #define BTN_RETURN 35
+
 #define BTN_SETUP 36
 #define BTN_GUIDE 37
 #define BTN_RADIO 38
 #define BTN_PREVCH 39
+
 #define BTN_CH_DOWN 40
 #define BTN_CH_UP 41
+
 #define BTN_VOL_DOWN 42
 #define BTN_VOL_UP 43
+
 #define BTN_MUTE 44
-#define BTN_POWER 45
+
 #define BTN_TV 46
 #define BTN_VIDEOS 47
 #define BTN_MUSIC 48
@@ -69,13 +83,19 @@ unsigned int holdButton_releaseTimeout = 120;
 #define BTN_CONTEXT 62
 #define BTN_INFO 63
 
-#define BTN_DUMMY 255
+#define BTN_POWER 100
+#define BTN_TASKSWITCH 101
+#define BTN_SLEEP 102
+
+#define BTN_REPETITION 255
 
 
 // Button Modes
-#define BUTTONMODE_ONCE 0
-#define BUTTONMODE_REPEAT 1
+#define BUTTONMODE_LAST 0
+#define BUTTONMODE_ONCE 1
 #define BUTTONMODE_HOLD 2
+#define BUTTONMODE_REPEAT 3
+#define BUTTONMODE_EXTENDED_REPEAT 4
 
 // Remote Types
 #define REMOTETYPE_RC5 0
@@ -98,7 +118,12 @@ IRrecv irrecv(recvPin);
 //
 void  setup ( )
 {
-  if(useSerial || debug || debug2) Serial.begin(115200);
+  if (isDebugBuild) {
+    useSerial = true;
+    debug = true;
+    debug2 = true;
+  }
+  if (useSerial || debug || debug2) Serial.begin(115200);
   BootKeyboard.begin();
   Consumer.begin();
   System.begin();
@@ -151,17 +176,36 @@ void  dumpInfo (decode_results *results)
 
 
     // Hauppauge Remote
-    if (_currRC5Code == 0xBD) { // POWER
+    if (_currRC5Code == 0xBD) { // POWER (upper right key)
       //handleButton_RCx(BTN_POWER, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handlePowerButton();
+      //handlePowerButton();
+      handleButton_RCx(BTN_POWER, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x90) { // VOL+
-      //handleButton_RCx(BTN_VOL_UP, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_VOL_UP, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+
+    else if (_currRC5Code == 0xBB) { // HOME/GO (upper left key)
+      //handleButton_RCx(BTN_HOME, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+      //handleTaskSwitchButton();
+      handleButton_RCx(BTN_TASKSWITCH, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x91) { // VOL-
-      //handleButton_RCx(BTN_VOL_DOWN, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_VOL_DOWN, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+
+    // media player controls
+    else if (_currRC5Code == 0xB7) { // REC
+      handleButton_RCx(BTN_REC, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0xB6) { // STOP
+      handleButton_RCx(BTN_STOP, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0xB5) { // PLAY
+      handleButton_RCx(BTN_PLAY, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0xB0) { // PAUSE
+      handleButton_RCx(BTN_PAUSE, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0xA4) { // PREV
+      handleButton_RCx(BTN_PREV, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0x9E) { // NEXT
+      handleButton_RCx(BTN_NEXT, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0xB2) { // REWIND
       //handleButton_RCx(BTN_REWD, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
@@ -173,49 +217,78 @@ void  dumpInfo (decode_results *results)
       //handleButton_RCx(BTN_FFWD, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
       handleButton_RCx(BTN_FFWD, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0xA1) { // CH- used as page down
-      handleButton_RCx(BTN_CH_DOWN, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+
+    // above control pad
+    else if (_currRC5Code == 0x9B) { // GUIDE -> left above control pad
+      //handleButton_RCx(BTN_GUIDE, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_TASKSWITCH, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0xA0) { // CH+ used as page up
-      handleButton_RCx(BTN_CH_UP, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    else if (_currRC5Code == 0x8C) { // RADIO -> right above control pad
+      //handleButton_RCx(BTN_RADIO, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_CONTEXT, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+
+    // control pad
+    else if (_currRC5Code == 0xA5) { // OK
+      //handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0x94) { // ARROW UP
       //handleButton_RCx(BTN_UP, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_UP, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      //handleButton_RCx(BTN_UP, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_UP, BUTTONMODE_EXTENDED_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0x95) { // ARROW DOWN
       //handleButton_RCx(BTN_DOWN, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_DOWN, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      //handleButton_RCx(BTN_DOWN, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_DOWN, BUTTONMODE_EXTENDED_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0x96) { // ARROW LEFT
       //handleButton_RCx(BTN_LEFT, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_LEFT, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      //handleButton_RCx(BTN_LEFT, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_LEFT, BUTTONMODE_EXTENDED_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0x97) { // ARROW RIGHT
       //handleButton_RCx(BTN_RIGHT, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_RIGHT, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      //handleButton_RCx(BTN_RIGHT, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_RIGHT, BUTTONMODE_EXTENDED_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0xA5) { // OK
       //handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-      handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
+      handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_EXTENDED_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
+    }
+
+    // below control pad
+    else if (_currRC5Code == 0x9F) { // BACK/EXIT ->  -> swapped and used as on the other remotes as MENU
+      handleButton_RCx(BTN_MENU, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x9F) { // BACK/EXIT
-      //handleButton_RCx(BTN_BACK, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    else if (_currRC5Code == 0x8D) { // i/MENU -> swapped and used as on the other remotes as BACK/EXIT
       handleButton_RCx(BTN_BACK, BUTTONMODE_HOLD, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x8D) { // i/MENU
-      handleButton_RCx(BTN_MENU, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+
+    // volume controls
+    else if (_currRC5Code == 0x90) { // VOL+
+      handleButton_RCx(BTN_VOL_UP, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x92) { // PREV.CH
-      handleButton_RCx(BTN_CONTEXT, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    else if (_currRC5Code == 0x91) { // VOL-
+      handleButton_RCx(BTN_VOL_DOWN, BUTTONMODE_REPEAT, _currRC5Pref, REMOTETYPE_RC5);
     }
     else if (_currRC5Code == 0x8F) { // MUTE
       handleButton_RCx(BTN_MUTE, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0xBB) { // HOME/GO
-      //handleButton_RCx(BTN_HOME, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-      handleTaskSwitchButton();
+
+    // channel controls
+    else if (_currRC5Code == 0xA1) { // CH- used as page down
+      handleButton_RCx(BTN_CH_DOWN, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+    else if (_currRC5Code == 0xA0) { // CH+ used as page up
+      handleButton_RCx(BTN_CH_UP, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
+    else if (_currRC5Code == 0x92) { // PREV.CH
+      handleButton_RCx(BTN_CONTEXT, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
+    }
+
+    // sources
     else if (_currRC5Code == 0x9C) { // TV
       handleButton_RCx(BTN_TV, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
@@ -228,30 +301,8 @@ void  dumpInfo (decode_results *results)
     else if (_currRC5Code == 0x9A) { // PICTURES
       handleButton_RCx(BTN_PICTURES, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
-    else if (_currRC5Code == 0x9B) { // GUIDE
-      handleButton_RCx(BTN_GUIDE, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0x8C) { // RADIO
-      handleButton_RCx(BTN_RADIO, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0xB7) { // REC
-      handleButton_RCx(BTN_REC, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0xB6) { // STOP
-      handleButton_RCx(BTN_STOP, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0xB5) { // PLAY
-      handleButton_RCx(BTN_PLAY, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0xB0) { // PAUSE
-      handleButton_RCx(BTN_PAUSE, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0xA4) { // PREV
-      handleButton_RCx(BTN_PREV, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
-    else if (_currRC5Code == 0x9E) { // NEXT
-      handleButton_RCx(BTN_NEXT, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
-    }
+
+    // number keys
     else if (_currRC5Code == 0x81) { // 1
       handleButton_RCx(BTN_1, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
@@ -288,6 +339,8 @@ void  dumpInfo (decode_results *results)
     else if (_currRC5Code == 0x8E) { // #
       handleButton_RCx(BTN_HASH, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
+
+    // color keys
     else if (_currRC5Code == 0x8B) { // RED
       handleButton_RCx(BTN_RED, BUTTONMODE_ONCE, _currRC5Pref, REMOTETYPE_RC5);
     }
@@ -352,45 +405,61 @@ void  dumpInfo (decode_results *results)
     // with the most important buttons available.
     // Missing buttons configured using learning function, which does not work well with RCx format due to the toggle bit,
     // so i used an old unused IR remote with NEC code for these, which will be OK for non-repeating buttons.
+
+    // power
     if (_currRC6Code == 0x270C) { // POWER (of SOURCE)
       //handleButton_RCx(BTN_POWER, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
-      handlePowerButton();
+      //handlePowerButton();
+      handleButton_RCx(BTN_POWER, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
     }
+
+    // above control pad
+    else if (_currRC6Code == 0x2743) { // X - AUDIO PARAMETER - left above control pad
+      //handleButton_RCx(BTN_HOME, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
+      //handleTaskSwitchButton();
+      handleButton_RCx(BTN_TASKSWITCH, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
+    }
+    else if (_currRC6Code == 0x2754) { // VIDEO PARAMETER - right above control pad
+      //handleButton_RCx(BTN_MENU, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_CONTEXT, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
+    }
+
+    // control pad
     else if (_currRC6Code == 0x275C) { // OK/ENTER
       //handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
       handleButton_RCx(BTN_OK_ENTER, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
     }
-    else if (_currRC6Code == 0x2783) { // RETURN/BACK - bottom right at control pad
-      //handleButton_RCx(BTN_BACK, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_BACK, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
-    }
     else if (_currRC6Code == 0x275A) { // LEFT
       //handleButton_RCx(BTN_LEFT, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_LEFT, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      //handleButton_RCx(BTN_LEFT, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_LEFT, BUTTONMODE_EXTENDED_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
     }
     else if (_currRC6Code == 0x275B) { // RIGHT
       //handleButton_RCx(BTN_RIGHT, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_RIGHT, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      //handleButton_RCx(BTN_RIGHT, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_RIGHT, BUTTONMODE_EXTENDED_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
     }
     else if (_currRC6Code == 0x2758) { // UP
       //handleButton_RCx(BTN_UP, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_UP, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      //handleButton_RCx(BTN_UP, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_UP, BUTTONMODE_EXTENDED_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
     }
     else if (_currRC6Code == 0x2759) { // DOWN
       //handleButton_RCx(BTN_DOWN, BUTTONMODE_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_DOWN, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      //handleButton_RCx(BTN_DOWN, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_DOWN, BUTTONMODE_EXTENDED_REPEAT, _currRC6Pref, REMOTETYPE_RC6);
     }
-    else if (_currRC6Code == 0x27CC) { // HOME MENU - bottom left at control pad
+
+    // below control pad
+    else if (_currRC6Code == 0x27CC) { // HOME MENU - left below control pad
       handleButton_RCx(BTN_MENU, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
-    else if (_currRC6Code == 0x2743) { // X - AUDIO PARAMETER - top left at control pad
-      //handleButton_RCx(BTN_HOME, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
-      handleTaskSwitchButton();
-    }
-    else if (_currRC6Code == 0x2754) { // VIDEO PARAMETER - top right at control pad
-      //handleButton_RCx(BTN_MENU, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
-      handleButton_RCx(BTN_CONTEXT, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
+    else if (_currRC6Code == 0x2783) { // RETURN/BACK - right below control pad
+      //handleButton_RCx(BTN_BACK, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
+      handleButton_RCx(BTN_BACK, BUTTONMODE_HOLD, _currRC6Pref, REMOTETYPE_RC6);
     }
+
+    // media player controls
     else if (_currRC6Code == 0x2771) { // PLAY
       handleButton_RCx(BTN_PLAY, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
@@ -406,6 +475,8 @@ void  dumpInfo (decode_results *results)
     else if (_currRC6Code == 0x2770) { // NEXT
       handleButton_RCx(BTN_NEXT, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
+
+    // number keys
     else if (_currRC6Code == 0x2701) { // 1
       handleButton_RCx(BTN_1, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
@@ -436,6 +507,8 @@ void  dumpInfo (decode_results *results)
     else if (_currRC6Code == 0x2700) { // 0
       handleButton_RCx(BTN_0, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
+
+    // channel up/down
     else if (_currRC6Code == 0x2720) { // CH+
       handleButton_RCx(BTN_CH_UP, BUTTONMODE_ONCE, _currRC6Pref, REMOTETYPE_RC6);
     }
@@ -459,43 +532,221 @@ void  dumpInfo (decode_results *results)
 
 
 
-
   // NEC CODES - used also for Pioneer remote codes here (Pioneer code consists of 2 NEC codes and is not directly supported by Arduino IRRemote.h)
   else if (results->decode_type == NEC && results->bits == 32) {
 
     // Pioneer Remote in BD mode, configured code preset to Sat-PVR/Philips 6139 (RC6 code)
     // -> missing/unused buttons "learned" with codes in NEC format
     if (results->value == 0x4FF18E7) { // RED
-      handleButton(BTN_RED, false);
+      handleButton_NEC(BTN_RED, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF02FD) { // GREEN
-      handleButton(BTN_GREEN, false);
+      handleButton_NEC(BTN_GREEN, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF827D) { // YELLOW
-      handleButton(BTN_YELLOW, false);
+      handleButton_NEC(BTN_YELLOW, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF38C7) { // BLUE
-      handleButton(BTN_BLUE, false);
+      handleButton_NEC(BTN_BLUE, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FFB847) { // REWIND
-      handleButton(BTN_REWD, false);
+      handleButton_NEC(BTN_REWD, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF08F7) { // FAST FORWARD
-      handleButton(BTN_FFWD, false);
+      handleButton_NEC(BTN_FFWD, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF6897) { // ./CLR
-      //handleButton(BTN_, false);
+      //handleButton_NEC(BTN_, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF9867) { // CLASS/ENTER
-      handleButton(BTN_OK_ENTER, false);
+      handleButton_NEC(BTN_OK_ENTER, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FFF807) { // AUDIO
-      //handleButton(BTN_, false);
+      //handleButton_NEC(BTN_, BUTTONMODE_ONCE);
     }
     else if (results->value == 0x4FF7887) { // DISPLAY/INFO
-      handleButton(BTN_INFO, false);
+      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    }
+
+
+
+    // TOSHIBA SE-R0319
+    // NEC 32bit codes
+    else if (results->value == 0x2FD48B7) { // POWER
+      handleButton_NEC(BTN_POWER, BUTTONMODE_REPEAT);
+    }
+    else if (results->value == 0x2FDA857) { // SLEEP
+      handleButton_NEC(BTN_SLEEP, BUTTONMODE_ONCE);
+    }
+
+    // above control pad
+    else if (results->value == 0x2FDCA35) { // left above control pad -> TASKSWITCH
+      handleButton_NEC(BTN_TASKSWITCH, BUTTONMODE_REPEAT);
+    }
+    else if (results->value == 0xA25D9E61) { // right above control pad -> CONTEXT
+      handleButton_NEC(BTN_CONTEXT, BUTTONMODE_ONCE);
+    }
+
+    // control pad
+    else if (results->value == 0x2FDBC43) { // ENTER
+      handleButton_NEC(BTN_OK_ENTER, BUTTONMODE_HOLD);
+    }
+    else if (results->value == 0x22DD8A75) { // LEFT
+      //handleButton_NEC(BTN_LEFT, BUTTONMODE_HOLD);
+      handleButton_NEC(BTN_LEFT, BUTTONMODE_EXTENDED_REPEAT);
+    }
+    else if (results->value == 0x22DDB24D) { // RIGHT
+      //handleButton_NEC(BTN_RIGHT, BUTTONMODE_HOLD);
+      handleButton_NEC(BTN_RIGHT, BUTTONMODE_EXTENDED_REPEAT);
+    }
+    else if (results->value == 0x2FD7C83) { // UP
+      //handleButton_NEC(BTN_UP, BUTTONMODE_HOLD);
+      handleButton_NEC(BTN_UP, BUTTONMODE_EXTENDED_REPEAT);
+    }
+    else if (results->value == 0x2FDFC03) { // DOWN
+      //handleButton_NEC(BTN_DOWN, BUTTONMODE_HOLD);
+      handleButton_NEC(BTN_DOWN, BUTTONMODE_EXTENDED_REPEAT);
+    }
+
+    // below control pad
+    else if (results->value == 0x2FD708F) { // left below control pad -> MENU
+      handleButton_NEC(BTN_MENU, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x22DDF708) { // left below control pad -> BACK
+      handleButton_NEC(BTN_BACK, BUTTONMODE_ONCE);
+    }
+
+    // volume control
+    else if (results->value == 0x2FD58A7) { // VOL+
+      handleButton_NEC(BTN_VOL_UP, BUTTONMODE_REPEAT);
+    }
+    else if (results->value == 0x2FD7887) { // VOL-
+      handleButton_NEC(BTN_VOL_DOWN, BUTTONMODE_REPEAT);
+    }
+    else if (results->value == 0x2FD08F7) { // MUTE
+      handleButton_NEC(BTN_MUTE, BUTTONMODE_ONCE);
+    }
+
+    // media player controls
+    else if (results->value == 0x22DDA857) { // PLAY
+      handleButton_NEC(BTN_PLAY, BUTTONMODE_ONCE);
+    }
+    //    else if (results->value == 0xA25DA857) { // PAUSE - combined with GREEN - unused as PLAY/PAUSE is 1 key anyway
+    //      handleButton_NEC(BTN_PAUSE, BUTTONMODE_ONCE);
+    //    }
+    else if (results->value == 0x22DD28D7) { // STOP
+      handleButton_NEC(BTN_STOP, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25DC43B) { // PREV
+      handleButton_NEC(BTN_PREV, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25D24DB) { // NEXT
+      handleButton_NEC(BTN_NEXT, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25D9867) { // REWD
+      handleButton_NEC(BTN_REWD, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25DC837) { // FFWD
+      handleButton_NEC(BTN_FFWD, BUTTONMODE_ONCE);
     }
 
+    // number keys
+    else if (results->value == 0x2FD807F) { // 1
+      handleButton_NEC(BTN_1, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD40BF) { // 2
+      handleButton_NEC(BTN_2, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FDC03F) { // 3
+      handleButton_NEC(BTN_3, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD20DF) { // 4
+      handleButton_NEC(BTN_4, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FDA05F) { // 5
+      handleButton_NEC(BTN_5, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD609F) { // 6
+      handleButton_NEC(BTN_6, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FDE01F) { // 7
+      handleButton_NEC(BTN_7, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD10EF) { // 8
+      handleButton_NEC(BTN_8, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD906F) { // 9
+      handleButton_NEC(BTN_9, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0x2FD00FF) { // 0
+      handleButton_NEC(BTN_0, BUTTONMODE_ONCE);
+    }
+
+
+    // color keys
+    else if (results->value == 0xA25D708F) { // RED (also SLOW REWD)
+      handleButton_NEC(BTN_RED, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25DA857) { // GREEN (also PAUSE)
+      handleButton_NEC(BTN_GREEN, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25D07F8) { // YELLOW (also PLAY MODE)
+      handleButton_NEC(BTN_YELLOW, BUTTONMODE_ONCE);
+    }
+    else if (results->value == 0xA25DB04F) { // BLUE (also SLOW FWD)
+      handleButton_NEC(BTN_BLUE, BUTTONMODE_ONCE);
+    }
+
+    // other
+    else if (results->value == 0x2FD38C7) { // DISPLAY
+      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    }
+    //    else if (results->value == 0xA23DCD32) { // TV/DVD
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0xA25DAF50) { // EJECT
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DDE11E) { // SUBTITLE
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x2FDF00F) { // INPUT
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x2FD9867) { // MENU/DVD
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DDFB04) { // MENU/TOP
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DDCA35) { // AUDIO SELECT
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0xA25D02FD) { // CH.RTN/ZOOM
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DDBA45) { // RETURN (next to PLAY)
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0xA25D37C8) { // MARKER
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DD6996) { // ANGLE
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DD3AC5) { // REPEAT A+B
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x22DDD926) { // JUMP
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+    //    else if (results->value == 0x2FD9A65) { // PIC SIZE
+    //      handleButton_NEC(BTN_INFO, BUTTONMODE_ONCE);
+    //    }
+
+
+
+
 
 
 
@@ -611,11 +862,24 @@ void  dumpInfo (decode_results *results)
     //    else if (lastNECcode == 0xD52A34CB && results->value == 0xF50AA758) { // ./CLR/D.ACCESS
     //      //handleButton(BTN_POWER, false);
     //    }
+    // remember last NEC code - for PIONEER remotes sending 2 NEC codes as one PIONEER code
+    //lastNECcode = results->value;
+
+
+    else {
+      // unknown / not implemented NEC code -> must reset last key or a repeat of this unknown key will trigger the last one
+      handleButton_NEC(BTN_UNKNOWN, BUTTONMODE_REPEAT);
+    }
 
-    // remember last NEC code
-    lastNECcode = results->value;
   } // END NEC CODES
 
+  // NEC repetitions (0 bits)
+  // RC using NEC code send a 0 bit NEC code as repetition after the actual key press
+  else if (results->decode_type == NEC && results->bits == 0) {
+    if (debug) Serial.println(F("NEC REPETITION"));
+    handleButton_NEC(BTN_REPETITION, BUTTONMODE_LAST);
+  }
+
 
 }
 

+ 180 - 0
src/IR-PC-HID-Remote/handleButton_NEC.ino

@@ -0,0 +1,180 @@
+// Button handling for IR remotes NEC code
+// - These DO NOT send a toggle bit on every new button press, BUT they send a 0 bit NEC code as repetition instead of the
+//   button code, so it is easy to differ between hold and re-pressing
+// - if a Button configured as BUTTONMODE_ONCE the repetitions will be ignored
+// - On re-pressing, this function will send the button again as fast as possible
+// - If a button is held down, the remote will go on sending the 0 bit repeate code code every 70-100ms or so.
+//   This function will then:
+//   - BUTTONMODE_REPEAT:
+//     1. ignore the first couple of repetition codes to prevent multi triggering on single button presses
+//     2. send repeats as they come in from the remote
+//   - BUTTONMODE_REPEAT_EXTENDED:
+//     1. ignore the first couple of repetition codes to prevent multi triggering on single button presses
+//     2. start with some slow repeats
+//     3. switch to medium repeat rate
+//     4. switch to fast repeat rate OR HOLD if configured
+//   - BUTTONMODE_HOLD:
+//     - press the key and dont release it until no more repetitions come in from the RC, then release
+
+
+
+
+
+
+// configuration variables for NEC button handling
+uint8_t handleButton_NEC_ignoreFirstRepeats = 2;          // repeats to ignore when a button is beeing held (the first one is always sent), both for BUTTONMODE_REPEAT and BUTTONMODE_FILTERED_REPEAT
+uint8_t handleButton_NEC_ignoreFirstRepeats_Ext = 6;      // repeats to ignore when a button is beeing held (the first one is always sent), both for BUTTONMODE_REPEAT and BUTTONMODE_FILTERED_REPEAT
+uint8_t handleButton_NEC_slowRepeats = 0;                 // amount of slow repeats to send
+uint8_t handleButton_NEC_slowRepeatsNumFastRepeats = 4;   // how many fast repeats (=sending rate of the RC remote) represent one slow repeat?
+uint8_t handleButton_NEC_mediumRepeats = 5;               // amount of medium repeats to send
+uint8_t handleButton_NEC_mediumRepeatsNumFastRepeats = 2; // how many fast repeats (=sending rate of the RC remote) represent one medium repeat?
+bool handleButton_NEC_useHoldInsteadOfFastRepeat = true;
+
+// hold button mode (key via USB keyboard emulation is not release until the RC stops sending repeats + this timeout)
+uint8_t handleButton_NEC_holdButton_releaseTimeout = 120; // release keys after a button was held (_btnMode=BUTTON_HOLD) after this ms if triggered by handleButton_NEC function
+
+// global variables for NEC button handling
+unsigned int handleButton_NEC_btnRepeatsCounter;
+uint8_t handleButton_NEC_btnSlowRepeatsCounter, handleButton_NEC_btnSlowRepeatsCounter2;
+uint8_t handleButton_NEC_btnMediumRepeatsCounter, handleButton_NEC_btnMediumRepeatsCounter2;
+uint8_t handleButton_NEC_lastButton = 0;
+uint8_t handleButton_NEC_lastButtonMode = 0;
+
+void handleButton_NEC(uint8_t _btn, uint8_t _btnMode) {
+  bool _repeatMode = false;
+  bool _extRepeatMode = false;
+  bool _holdMode = false;
+  if (_btn == BTN_REPETITION && _btnMode == BUTTONMODE_LAST) {
+    if (handleButton_NEC_lastButtonMode == BUTTONMODE_REPEAT) _repeatMode = true;
+    else if (handleButton_NEC_lastButtonMode == BUTTONMODE_EXTENDED_REPEAT) _extRepeatMode = true;
+    else if (handleButton_NEC_lastButtonMode == BUTTONMODE_HOLD) _holdMode = true;
+  }
+  else {
+    if (_btnMode == BUTTONMODE_REPEAT) _repeatMode = true;
+    else if (_btnMode == BUTTONMODE_EXTENDED_REPEAT) _extRepeatMode = true;
+    else if (_btnMode == BUTTONMODE_HOLD) {
+      _holdMode = true;
+      handleHoldButton_setTimeout(handleButton_NEC_holdButton_releaseTimeout);
+    }
+  }
+
+
+  // single/first button press
+  if (_btn != BTN_REPETITION) {
+    handleButton_NEC_lastButtonMode = _btnMode;
+    if (_btn == BTN_UNKNOWN) {
+      // reset lastButton to 0 / BTN_UNKNOWN to avoid triggering a key if an unknown/unimplemented button is held
+      handleButton_NEC_lastButton = BTN_UNKNOWN;
+    }
+    else if (_btn == BTN_POWER) {
+      handleButton_NEC_lastButton = _btn;
+      handlePowerButton();
+    }
+    else if (_btn == BTN_TASKSWITCH) {
+      handleButton_NEC_lastButton = _btn;
+      handleTaskSwitchButton();
+    }
+    else {
+      handleButton_NEC_lastButton = _btn;
+      if (_btnMode == BUTTONMODE_HOLD) {
+        releaseAllKeys();
+        sendKey(_btn, true);
+      }
+      else sendKey(_btn, false);
+    }
+    handleButton_NEC_btnRepeatsCounter = 0;
+    handleButton_NEC_btnSlowRepeatsCounter = 0;
+    handleButton_NEC_btnMediumRepeatsCounter = 0;
+  }
+
+  // BUTTONMODE_REPEAT (direct send a keypress on every repeat received from the RC, except of the first ones)
+  else if (_btn == BTN_REPETITION && _repeatMode) {
+    if (handleButton_NEC_lastButton == BTN_POWER) {
+      handlePowerButton();
+    }
+    else if (handleButton_NEC_lastButton == BTN_TASKSWITCH) {
+      handleTaskSwitchButton();
+    }
+    else {
+      handleButton_NEC_btnRepeatsCounter++;
+      if (debug2) {
+        Serial.print(F("REP #"));
+        Serial.println(handleButton_NEC_btnRepeatsCounter);
+      }
+      if (handleButton_NEC_btnRepeatsCounter > handleButton_NEC_ignoreFirstRepeats) {
+        // filter out 1st repetitions
+        sendKey(handleButton_NEC_lastButton, false);
+      }
+
+    }
+  }
+
+  // BUTTONMODE_EXTENDED_REPEAT (first slow, then getting faster)
+  else if (_btn == BTN_REPETITION && _extRepeatMode) {
+    if (handleButton_NEC_btnRepeatsCounter >= handleButton_NEC_ignoreFirstRepeats_Ext) {
+      if (handleButton_NEC_btnSlowRepeatsCounter == 0) {
+        handleButton_NEC_btnSlowRepeatsCounter++;
+        handleButton_NEC_btnSlowRepeatsCounter2 = 0;
+        if (debug2) {
+          Serial.print(F("NEC BUTTON REPEAT SLOW #"));
+          Serial.println(handleButton_NEC_btnSlowRepeatsCounter);
+        }
+        sendKey(handleButton_NEC_lastButton, false);
+      }
+      else if (handleButton_NEC_btnSlowRepeatsCounter < handleButton_NEC_slowRepeats && handleButton_NEC_slowRepeats > 0) {
+        if (handleButton_NEC_btnSlowRepeatsCounter2 < handleButton_NEC_slowRepeatsNumFastRepeats) {
+          handleButton_NEC_btnSlowRepeatsCounter2++;
+        }
+        else {
+          handleButton_NEC_btnSlowRepeatsCounter++;
+          handleButton_NEC_btnSlowRepeatsCounter2 = 0;
+          if (debug2) {
+            Serial.print(F("NEC BUTTON REPEAT SLOW #"));
+            Serial.println(handleButton_NEC_btnSlowRepeatsCounter);
+          }
+          if (handleButton_NEC_btnSlowRepeatsCounter <= (handleButton_NEC_slowRepeats - 1)) {
+            // do not send keypress on last medium repeat before going on with fast repeat mode
+          sendKey(handleButton_NEC_lastButton, false);
+          }
+        }
+      }
+      else if (handleButton_NEC_btnMediumRepeatsCounter <= handleButton_NEC_mediumRepeats && handleButton_NEC_mediumRepeats > 0) {
+        if (handleButton_NEC_btnMediumRepeatsCounter2 < handleButton_NEC_mediumRepeatsNumFastRepeats) {
+          handleButton_NEC_btnMediumRepeatsCounter2++;
+        }
+        else {
+          handleButton_NEC_btnMediumRepeatsCounter++;
+          handleButton_NEC_btnMediumRepeatsCounter2 = 0;
+          if (debug2) {
+            Serial.print(F("NEC BUTTON REPEAT MEDIUM #"));
+            Serial.println(handleButton_NEC_btnMediumRepeatsCounter);
+          }
+          if (handleButton_NEC_btnMediumRepeatsCounter <= (handleButton_NEC_mediumRepeats - 1)) {
+            // do not send keypress on last medium repeat before going on with fast repeat mode
+            sendKey(handleButton_NEC_lastButton, false);
+          }
+        }
+      }
+      else {
+        if (debug2) {
+          Serial.println(F("NEC BUTTON REPEAT FAST"));
+        }
+        if (handleButton_NEC_useHoldInsteadOfFastRepeat) {
+          if (handleHoldButton_active()) handleHoldButton();
+          else {
+            sendKey(handleButton_NEC_lastButton, true);
+          }
+        }
+        else sendKey(handleButton_NEC_lastButton, false);
+      }
+    }
+    handleButton_NEC_btnRepeatsCounter++;
+  }
+
+
+  // HOLD
+  else if ((_btn == BTN_REPETITION) && (_holdMode || _extRepeatMode)) {
+    handleHoldButton();
+  }
+
+}

+ 71 - 30
src/IR-PC-HID-Remote/handleButton_RCx.ino

@@ -6,13 +6,17 @@
 //   this function will then, after some ignored codes, start with some slow repeats, then switch to medium repeat rate and finally repeat with the rate of the incoming codes
 
 // configuration variables for RCx button handling
-uint8_t handleButton_RCx_ignoreFirstRepeats = 4;          // repeats to ignore when a button is beeing held (the first one is always sent)
-uint8_t handleButton_RCx_slowRepeats = 4;                 // amount of slow repeats to send
+uint8_t handleButton_RCx_ignoreFirstRepeats = 2;          // repeats to ignore when a button is beeing held (the first one is always sent), both for BUTTONMODE_REPEAT and BUTTONMODE_FILTERED_REPEAT
+uint8_t handleButton_RCx_ignoreFirstRepeats_Ext = 6;      // repeats to ignore when a button is beeing held (the first one is always sent), both for BUTTONMODE_REPEAT and BUTTONMODE_FILTERED_REPEAT
+uint8_t handleButton_RCx_slowRepeats = 0;                 // amount of slow repeats to send
 uint8_t handleButton_RCx_slowRepeatsNumFastRepeats = 4;   // how many fast repeats (=sending rate of the RC remote) represent one slow repeat?
 uint8_t handleButton_RCx_mediumRepeats = 5;               // amount of medium repeats to send
-uint8_t handleButton_RCx_mediumRepeatsNumFastRepeats = 2; // how many fast repeats (=sending rate of the RC remote) represent one slow repeat?
-uint8_t handleButton_RC5_holdButton_releaseTimeout = 146; // release keys after a button was held (_btnMode=BUTTON_HOLD) after this ms if triggered by handleButton_RCx function
-uint8_t handleButton_RC6_holdButton_releaseTimeout = 100; // release keys after a button was held (_btnMode=BUTTON_HOLD) after this ms if triggered by handleButton_RCx function
+uint8_t handleButton_RCx_mediumRepeatsNumFastRepeats = 2; // how many fast repeats (=sending rate of the RC remote) represent one medium repeat?
+bool handleButton_RCx_useHoldInsteadOfFastRepeat = true; 
+
+// hold button mode (key via USB keyboard emulation is not release until the RC stops sending repeats + this timeout)
+uint8_t handleButton_RC5_holdButton_releaseTimeout = 150; // release keys after a button was held (_btnMode=BUTTON_HOLD) after this ms if triggered by handleButton_RCx function
+uint8_t handleButton_RC6_holdButton_releaseTimeout = 120; // release keys after a button was held (_btnMode=BUTTON_HOLD) after this ms if triggered by handleButton_RCx function
 
 // global variables for RCx button handling
 unsigned int handleButton_RCx_btnRepeatsCounter;
@@ -26,35 +30,60 @@ uint8_t handleButton_RCx_btnMediumRepeatsCounter, handleButton_RCx_btnMediumRepe
 //}
 
 void handleButton_RCx(uint8_t _btn, uint8_t _btnMode, uint8_t _currPrefix, uint8_t _remoteType) {
-  bool _repeatMode = false;
-  bool _holdMode = false;
-  if (_btnMode == 1) _repeatMode = true;
-  else if (_btnMode == 2) _holdMode = true;
-
   if (_btn != handleButton_RCx_lastButton || (_btn == handleButton_RCx_lastButton) && (_currPrefix != handleButton_RCx_lastPrefix)) {
     if (debug2) {
       Serial.println(F("RCx BUTTON INITIAL"));
     }
-    
-    if (_holdMode) {
-      releaseAllKeys();
-      sendKey(_btn, true);
 
-      if(_remoteType == REMOTETYPE_RC6) holdButton_releaseTimeout = handleButton_RC6_holdButton_releaseTimeout;
-      else if(_remoteType == REMOTETYPE_RC5) holdButton_releaseTimeout = handleButton_RC5_holdButton_releaseTimeout;
-      
-      holdButton_lastTriggeredMillis = millis();
+    if (_btn == BTN_POWER) {
+      handlePowerButton();
+    }
+    else if (_btn == BTN_TASKSWITCH) {
+      handleTaskSwitchButton();
+    }
+    else {
+      if (_remoteType == REMOTETYPE_RC6) handleHoldButton_setTimeout(handleButton_RC6_holdButton_releaseTimeout);
+      else if (_remoteType == REMOTETYPE_RC5) handleHoldButton_setTimeout(handleButton_RC5_holdButton_releaseTimeout);
+        
+      //if (_btnMode == BUTTONMODE_HOLD || _btnMode == BUTTONMODE_EXTENDED_REPEAT && !handleTaskSwitchButton_isActive()) {
+      //if (_btnMode == BUTTONMODE_HOLD && !handleTaskSwitchButton_isActive()) {
+      if (_btnMode == BUTTONMODE_HOLD) {
+        releaseAllKeys();
+        sendKey(_btn, true);
+        handleHoldButton();
+      }
+      else sendKey(_btn, false);
     }
-    else sendKey(_btn, false);
 
     handleButton_RCx_btnRepeatsCounter = 0;
     handleButton_RCx_btnSlowRepeatsCounter = 0;
     handleButton_RCx_btnMediumRepeatsCounter = 0;
   }
 
-  // REPEAT BUTTON
-  else if ((_btn == handleButton_RCx_lastButton) && (_currPrefix == handleButton_RCx_lastPrefix) && _repeatMode) {
-    if (handleButton_RCx_btnRepeatsCounter >= handleButton_RCx_ignoreFirstRepeats) {
+  // BUTTONMODE_REPEAT (direct send a keypress on every repeat received from the RC, except of the first ones)
+  else if ((_btn == handleButton_RCx_lastButton) && (_currPrefix == handleButton_RCx_lastPrefix) && _btnMode == BUTTONMODE_REPEAT) {
+    if (_btn == BTN_POWER) {
+      handlePowerButton();
+    }
+    else if (_btn == BTN_TASKSWITCH) {
+      handleTaskSwitchButton();
+    }
+    else {
+      handleButton_RCx_btnRepeatsCounter++;
+      if (debug2) {
+          Serial.print("REP #");
+          Serial.println(handleButton_RCx_btnRepeatsCounter);
+        }
+      if (handleButton_RCx_btnRepeatsCounter > handleButton_RCx_ignoreFirstRepeats) {
+        // filter out 1st repetition
+        sendKey(_btn, false);
+      }
+    }
+  }
+
+  // BUTTONMODE_EXTENDED_REPEAT (first slow, then getting faster)
+  else if ((_btn == handleButton_RCx_lastButton) && (_currPrefix == handleButton_RCx_lastPrefix) && _btnMode == BUTTONMODE_EXTENDED_REPEAT) {
+    if (handleButton_RCx_btnRepeatsCounter >= handleButton_RCx_ignoreFirstRepeats_Ext) {
       if (handleButton_RCx_btnSlowRepeatsCounter == 0) {
         handleButton_RCx_btnSlowRepeatsCounter++;
         handleButton_RCx_btnSlowRepeatsCounter2 = 0;
@@ -64,7 +93,7 @@ void handleButton_RCx(uint8_t _btn, uint8_t _btnMode, uint8_t _currPrefix, uint8
         }
         sendKey(_btn, false);
       }
-      else if (handleButton_RCx_btnSlowRepeatsCounter < handleButton_RCx_slowRepeats) {
+      else if (handleButton_RCx_btnSlowRepeatsCounter <= handleButton_RCx_slowRepeats && handleButton_RCx_slowRepeats > 0) {
         if (handleButton_RCx_btnSlowRepeatsCounter2 < handleButton_RCx_slowRepeatsNumFastRepeats) {
           handleButton_RCx_btnSlowRepeatsCounter2++;
         }
@@ -75,10 +104,13 @@ void handleButton_RCx(uint8_t _btn, uint8_t _btnMode, uint8_t _currPrefix, uint8
             Serial.print(F("RCx BUTTON REPEAT SLOW #"));
             Serial.println(handleButton_RCx_btnSlowRepeatsCounter);
           }
+          if (handleButton_RCx_btnSlowRepeatsCounter <= (handleButton_RCx_slowRepeats - 1)) {
+            // do not send keypress on last medium repeat before going on with fast repeat mode
           sendKey(_btn, false);
+          }
         }
       }
-      else if (handleButton_RCx_btnMediumRepeatsCounter <= handleButton_RCx_mediumRepeats) {
+      else if (handleButton_RCx_btnMediumRepeatsCounter <= handleButton_RCx_mediumRepeats && handleButton_RCx_mediumRepeats > 0) {
         if (handleButton_RCx_btnMediumRepeatsCounter2 < handleButton_RCx_mediumRepeatsNumFastRepeats) {
           handleButton_RCx_btnMediumRepeatsCounter2++;
         }
@@ -89,24 +121,33 @@ void handleButton_RCx(uint8_t _btn, uint8_t _btnMode, uint8_t _currPrefix, uint8
             Serial.print(F("RCx BUTTON REPEAT MEDIUM #"));
             Serial.println(handleButton_RCx_btnMediumRepeatsCounter);
           }
-
-          sendKey(_btn, false);
+          if (handleButton_RCx_btnMediumRepeatsCounter <= (handleButton_RCx_mediumRepeats - 1)) {
+            // do not send keypress on last medium repeat before going on with fast repeat mode
+            sendKey(_btn, false);
+          }
         }
       }
       else {
         if (debug2) {
           Serial.println(F("RCx BUTTON REPEAT FAST"));
         }
-        sendKey(_btn, false);
+        if(handleButton_RCx_useHoldInsteadOfFastRepeat) {
+          if(handleHoldButton_active()) handleHoldButton();
+          else {
+            sendKey(_btn, true);
+          }
+        }
+        else sendKey(_btn, false);
       }
     }
     handleButton_RCx_btnRepeatsCounter++;
   }
 
-  // HOLD BUTTON
-  else if ((_btn == handleButton_RCx_lastButton) && (_currPrefix == handleButton_RCx_lastPrefix) && _holdMode) {
-    holdButton_lastTriggeredMillis = millis();
+  // BUTTONMODE_HOLD
+  else if ((_btn == handleButton_RCx_lastButton) && (_currPrefix == handleButton_RCx_lastPrefix) && _btnMode == BUTTONMODE_HOLD) {
+    handleHoldButton();
   }
+
   handleButton_RCx_lastPrefix = _currPrefix;
   handleButton_RCx_lastButton = _btn;
 }

+ 15 - 0
src/IR-PC-HID-Remote/handleHoldButtons.ino

@@ -1,15 +1,30 @@
 void handleHoldButtons_loop() {
   if (holdButton_lastTriggeredMillis > 0) {
     if ((millis() - holdButton_lastTriggeredMillis) > holdButton_releaseTimeout) {
+      //if (!handleTaskSwitchButton_isActive()) {
       releaseAllKeys();
       holdButton_lastTriggeredMillis = 0;
       if (useSerial) {
         Serial.println(F("KEY RELEASED"));
       }
+      //}
     }
   }
 }
 
+void handleHoldButton() {
+  holdButton_lastTriggeredMillis = millis();
+}
+
+bool handleHoldButton_active() {
+  if (holdButton_lastTriggeredMillis > 0) return true;
+  else return false;
+}
+
+void handleHoldButton_setTimeout(unsigned int _val) {
+  holdButton_releaseTimeout = _val;
+}
+
 void releaseAllKeys() {
   BootKeyboard.releaseAll();
 }

+ 14 - 14
src/IR-PC-HID-Remote/handlePowerButton.ino

@@ -1,13 +1,13 @@
 unsigned long powerButton_triggeredMillis = 0;
 unsigned long powerButton_lastPressedMillis = 0;
 unsigned long powerButton_disableMillis = 0;
-unsigned int powerButton_execLoopAfter = 250;
+unsigned int powerButton_execLoopAfter = 150;
 unsigned int powerButton_disableAfterAction = 1500;
-unsigned int powerButton_pressDurationMin_shortHoldAction = 250;
-unsigned int powerButton_pressDurationMax_shortHoldAction = 600;
-unsigned int powerButton_pressDurationMin_sleep = 800;
-unsigned int powerButton_pressDurationMax_sleep = 2000;
-unsigned int powerButton_pressDuration_shutdown = 3000;
+unsigned int powerButton_pressDurationMin_veryShortHoldAction = 0;
+unsigned int powerButton_pressDurationMax_veryShortHoldAction = 399;
+unsigned int powerButton_pressDurationMin_shortHoldAction = 400;
+unsigned int powerButton_pressDurationMax_shortHoldAction = 1500;
+unsigned int powerButton_pressDurationMin_longHold = 2500;
 
 void handlePowerButton() {
   powerButton_lastPressedMillis = millis();
@@ -16,14 +16,14 @@ void handlePowerButton() {
   if (powerButton_disableMillis == 0) {
     if (powerButton_triggeredMillis == 0) {
       powerButton_triggeredMillis = millis();
-      if(useSerial) Serial.println(F("POWER INITIALLY PRESSED"));
+      if (useSerial) Serial.println(F("POWER INITIALLY PRESSED"));
       //Serial.println(F("sending ALT+F4"));
       //BootKeyboard.press(KEY_LEFT_ALT);
       //BootKeyboard.press(KEY_F4);
       //delay(50);
-      //BootKeyboard.releaseAll();
+      //releaseAllKeys();
     }
-    else if ( (millis() - powerButton_triggeredMillis) >= powerButton_pressDuration_shutdown) {
+    else if ( (millis() - powerButton_triggeredMillis) >= powerButton_pressDurationMin_longHold) {
       // LONG PRESSED
       powerButton_triggeredMillis = 0;
       powerButton_lastPressedMillis = 0;
@@ -51,7 +51,7 @@ void handlePowerButton_loop() {
           Serial.println("ms");
         }
 
-        if (tDelta >= powerButton_pressDurationMin_sleep && tDelta <= powerButton_pressDurationMax_sleep) {
+        if (tDelta >= powerButton_pressDurationMin_shortHoldAction && tDelta <= powerButton_pressDurationMax_shortHoldAction) {
           // SHORT PRESSED
           if (useSerial) {
             Serial.println(F("POWER SHORT HOLD"));
@@ -62,14 +62,14 @@ void handlePowerButton_loop() {
           powerButton_lastPressedMillis = 0;
           powerButton_disableMillis = millis();
         }
-        else if (tDelta >= powerButton_pressDurationMin_shortHoldAction && tDelta < powerButton_pressDurationMax_shortHoldAction) {
+        else if (tDelta >= powerButton_pressDurationMin_veryShortHoldAction && tDelta < powerButton_pressDurationMax_veryShortHoldAction) {
           // VERY SHORT HOLD
           if (useSerial) {
             Serial.println(F("POWER VERY SHORT HOLD"));
-            Serial.println("sending WIN KEY");
+            //Serial.println("sending WIN KEY");
           }
-          if (sendHID) BootKeyboard.write(KEY_LEFT_WINDOWS);
-
+          //if (sendHID) BootKeyboard.write(KEY_LEFT_WINDOWS);
+          
           powerButton_triggeredMillis = 0;
           powerButton_lastPressedMillis = 0;
           //powerButton_disableMillis = millis();

+ 25 - 16
src/IR-PC-HID-Remote/handleTaskSwButton.ino

@@ -3,16 +3,15 @@ unsigned long taskSwButton_lastPressedMillis = 0;
 unsigned long taskSwButton_disableMillis = 0;
 unsigned long taskSwButton_tabKeyDownMillis = 0;
 unsigned long taskSwButton_winKeyDownMillis = 0;
-unsigned int taskSwButton_execLoopAfter = 250;
+unsigned int taskSwButton_execLoopAfter = 150;
 unsigned int taskSwButton_disableAfterAction = 1000;
-unsigned int taskSwButton_pressDurationMin_veryShortHold = 1;
-unsigned int taskSwButton_pressDurationMax_veryShortHold = 250;
-unsigned int taskSwButton_pressDurationMin_shortHold = 350;
-unsigned int taskSwButton_pressDurationMax_shortHold = 900;
-unsigned int taskSwButton_pressDuration_longHold = 1000;
+unsigned int taskSwButton_pressDurationMin_veryShortHold = 0;
+unsigned int taskSwButton_pressDurationMax_veryShortHold = 220;
+unsigned int taskSwButton_pressDurationMin_shortHold = 221;
+unsigned int taskSwButton_pressDurationMax_shortHold = 999;
+unsigned int taskSwButton_pressDurationMin_longHold = 1000;
 
-unsigned int taskSwButton_tabKey_Up_After = 2000;
-//unsigned int taskSwButton_winKey_Up_After = 3000;
+unsigned int taskSwButton_tabKey_Up_After = 2500;
 
 void handleTaskSwitchButton() {
   taskSwButton_lastPressedMillis = millis();
@@ -32,7 +31,7 @@ void handleTaskSwitchButton() {
       //        BootKeyboard.write(KEY_ESC);
       //      }
     }
-    else if ( (millis() - taskSwButton_triggeredMillis) >= taskSwButton_pressDuration_longHold) {
+    else if ( (millis() - taskSwButton_triggeredMillis) >= taskSwButton_pressDurationMin_longHold) {
       // LONG PRESSED
       taskSwButton_triggeredMillis = 0;
       taskSwButton_lastPressedMillis = 0;
@@ -40,23 +39,33 @@ void handleTaskSwitchButton() {
       if (useSerial) {
         Serial.println(F("TASKSWITCH LONG HOLD"));
       }
+      if(useSerial) Serial.println(F("sending ALT+F4"));
       if (sendHID) {
-        if(useSerial) Serial.println(F("sending ALT+F4"));
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_F4);
         delay(50);
-        BootKeyboard.releaseAll();
+        releaseAllKeys();
       }
     }
   }
 }
 
-void handleTaskSwitchButton_extendAltTabTimeout() {
+void handleTaskSwitchButton_extendTimeout() {
   if(taskSwButton_tabKeyDownMillis > 0) taskSwButton_tabKeyDownMillis = millis();
 }
 
+void handleTaskSwitchButton_end() {
+  taskSwButton_tabKeyDownMillis = 0;
+  releaseAllKeys();
+}
+
+bool handleTaskSwitchButton_isActive() {
+  if (taskSwButton_tabKeyDownMillis > 0) return true;
+  else return false;
+}
+
 void handleTaskSwitchButton_loop() {
-  // handle Power Button short press
+  // handle TaskSwitch Button short press
 
   if (taskSwButton_triggeredMillis > 0) {
     if (taskSwButton_lastPressedMillis > 0) {
@@ -78,7 +87,7 @@ void handleTaskSwitchButton_loop() {
             Serial.println("sending ALT+TAB");
           }
           if (sendHID) {
-            // sending ALT+TAB (leaving TAB engaged
+            // sending ALT+TAB (leaving TAB engaged)
             BootKeyboard.press(KEY_LEFT_ALT);
             BootKeyboard.write(KEY_TAB);
           }
@@ -90,7 +99,7 @@ void handleTaskSwitchButton_loop() {
         }
         else if (tDelta >= taskSwButton_pressDurationMin_veryShortHold && tDelta < taskSwButton_pressDurationMax_veryShortHold) {
           // VERY SHORT HOLD
-          if (useSerial) Serial.println(F("POWER VERY SHORT HOLD"));
+          if (useSerial) Serial.println(F("TASKSWITCH VERY SHORT HOLD"));
 
           //if ((millis() - taskSwButton_winKeyDownMillis) > taskSwButton_winKey_Up_After) {
           if (taskSwButton_tabKeyDownMillis == 0) {
@@ -128,7 +137,7 @@ void handleTaskSwitchButton_loop() {
   if (taskSwButton_tabKeyDownMillis > 0) {
     if ((millis() - taskSwButton_tabKeyDownMillis) > taskSwButton_tabKey_Up_After) {
       taskSwButton_tabKeyDownMillis = 0;
-      if (sendHID) BootKeyboard.releaseAll();
+      if (sendHID) releaseAllKeys();
     }
   }
 

+ 48 - 33
src/IR-PC-HID-Remote/sendKeys.ino

@@ -20,6 +20,10 @@ void printArrow() {
 //}
 
 void sendKey(uint8_t _key, bool _hold) {
+  if(_hold) {
+    handleHoldButton();
+  }
+  
   if (debug) Serial.println(F("SENDING KEY"));
   switch (_key) {
     //    case BTN_POWER:
@@ -29,12 +33,24 @@ void sendKey(uint8_t _key, bool _hold) {
     //        Serial.println(F("POWER"));
     //      }
     //      break;
+    case BTN_SLEEP:
+      if (sendHID) {
+        System.write(SYSTEM_SLEEP);
+      }
+      if (useSerial) {
+        printKey();
+        Serial.println(F("SLEEP"));
+      }
+      break;
     case BTN_OK_ENTER:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_ENTER);
-        else BootKeyboard.write(KEY_ENTER);
+        if (_hold && !handleTaskSwitchButton_isActive()) BootKeyboard.press(KEY_ENTER);
+        else {
+          BootKeyboard.write(KEY_ENTER);
+          if(handleTaskSwitchButton_isActive()) releaseAllKeys();
+        }
       }
-      holdButton_lastTriggeredMillis = millis();
+      handleHoldButton();
       if (useSerial) {
         printKey();
         Serial.println(F("OK_ENTER"));
@@ -42,7 +58,7 @@ void sendKey(uint8_t _key, bool _hold) {
       break;
     case BTN_BACK:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_BACKSPACE);
+        if (_hold) BootKeyboard.press(KEY_BACKSPACE);
         else BootKeyboard.write(KEY_BACKSPACE);
       }
       if (useSerial) {
@@ -52,47 +68,47 @@ void sendKey(uint8_t _key, bool _hold) {
       break;
     case BTN_UP:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_UP_ARROW);
+        if (_hold && !handleTaskSwitchButton_isActive()) BootKeyboard.press(KEY_UP_ARROW);
         else BootKeyboard.write(KEY_UP_ARROW);
       }
       if (useSerial) {
         printKey();
         Serial.println(F("UP"));
       }
-      handleTaskSwitchButton_extendAltTabTimeout();
+      if(handleTaskSwitchButton_isActive()) handleTaskSwitchButton_extendTimeout();
       break;
     case BTN_DOWN:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_DOWN_ARROW);
+        if (_hold && !handleTaskSwitchButton_isActive()) BootKeyboard.press(KEY_DOWN_ARROW);
         else BootKeyboard.write(KEY_DOWN_ARROW);
       }
       if (useSerial) {
         printKey();
         Serial.println(F("DOWN"));
       }
-      handleTaskSwitchButton_extendAltTabTimeout();
+      if(handleTaskSwitchButton_isActive()) handleTaskSwitchButton_extendTimeout();
       break;
     case BTN_RIGHT:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_RIGHT_ARROW);
+        if (_hold && !handleTaskSwitchButton_isActive()) BootKeyboard.press(KEY_RIGHT_ARROW);
         else BootKeyboard.write(KEY_RIGHT_ARROW);
       }
       if (useSerial) {
         printKey();
         Serial.println(F("RIGHT"));
       }
-      handleTaskSwitchButton_extendAltTabTimeout();
+      if(handleTaskSwitchButton_isActive()) handleTaskSwitchButton_extendTimeout();
       break;
     case BTN_LEFT:
       if (sendHID) {
-        if(_hold) BootKeyboard.press(KEY_LEFT_ARROW);
+        if (_hold && !handleTaskSwitchButton_isActive()) BootKeyboard.press(KEY_LEFT_ARROW);
         else BootKeyboard.write(KEY_LEFT_ARROW);
       }
       if (useSerial) {
         printKey();
         Serial.println(F("LEFT"));
       }
-      handleTaskSwitchButton_extendAltTabTimeout();
+      if(handleTaskSwitchButton_isActive()) handleTaskSwitchButton_extendTimeout();
       break;
     case BTN_PLAY:
       if (sendHID) Consumer.write(MEDIA_PLAY_PAUSE);
@@ -172,14 +188,13 @@ void sendKey(uint8_t _key, bool _hold) {
       break;
     case BTN_RED:
       if (sendHID) {
-
         BootKeyboard.press(KEY_LEFT_CTRL);
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F7);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(50);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -193,9 +208,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F8);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(50);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -209,9 +224,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F9);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(50);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -225,9 +240,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F10);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(50);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -259,9 +274,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F5);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(20);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -275,9 +290,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F6);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(20);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -296,14 +311,14 @@ void sendKey(uint8_t _key, bool _hold) {
         printKey();
         Serial.println(F("CONTEXT"));
       }
-      BootKeyboard.write(KEY_C);
+      if(sendHID) BootKeyboard.write(KEY_C);
       break;
     case BTN_INFO:
       if (useSerial) {
         printKey();
         Serial.println(F("INFO"));
       }
-      BootKeyboard.write(KEY_I);
+      if(sendHID) BootKeyboard.write(KEY_I);
       break;
     case BTN_CH_DOWN:
       if (sendHID) {
@@ -375,7 +390,7 @@ void sendKey(uint8_t _key, bool _hold) {
         delay(2);
         BootKeyboard.press(KEY_F1);
         delay(20);
-        BootKeyboard.releaseAll();
+        releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -393,7 +408,7 @@ void sendKey(uint8_t _key, bool _hold) {
         delay(2);
         BootKeyboard.press(KEY_F2);
         delay(20);
-        BootKeyboard.releaseAll();
+        releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -407,9 +422,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_F3);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(20);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();
@@ -423,9 +438,9 @@ void sendKey(uint8_t _key, bool _hold) {
         BootKeyboard.press(KEY_LEFT_WINDOWS);
         BootKeyboard.press(KEY_LEFT_ALT);
         BootKeyboard.press(KEY_F4);
-        holdButton_lastTriggeredMillis = millis();
+        handleHoldButton();
         //delay(20);
-        //BootKeyboard.releaseAll();
+        //releaseAllKeys();
       }
       if (useSerial) {
         printKey();