// Button handling for IR remotes using Pioneer, NEC, Sony... code // - These DO NOT send a toggle bit on every new button press, so it is difficult to differ hold and re-pressing // - On re-pressing this function will send the button again as fast as possible. It uses timers to filter out unintended multi triggering, // so this can be a little bit delayed (RC5 and RC6 remotes are better in this case) // - If a button is held down, the remote will go on sending the same code every 100ms or so. // This function will then, after some ignored codes, start with some slow repeats, and then switch to fast repeat rate (with the rate of the incoming codes). // special case Pioneer Protocol: // Pioneer Protocol transmits 2 different NEC 32bit codes on each keypress at once // and always with one repetition, so a short keypress sends 4 NEC codes // i.E.: // NEC, 0xD52A34CB, 32 // NEC, 0xF50AF708, 32 // NEC, 0xD52A34CB, 32 // NEC, 0xF50AF708, 32 // Each pair takes about 184ms -> 368ms for one button press. // On button hold the same codes are transmitted continuously. // So the shortest repeat time possible is about every 183ms - but ONLY when the button is held. // If the button is quickly short pressed it looks just like the same on receiver side. // As there is always at least 1 repetition, it is mandatory to filter these out, or a single // button press would always result in 2 events. uint8_t handleButton_lastSentKey; unsigned long handleButton_lastSentKey_begin; unsigned long handleButton_repeatedReceivedMillis; unsigned long handleButton_repeatMillis; #define HANDLEBUTTON_FIRST_REPEAT_INTERVAL 500 // minimum ms for the first repeat(s) to trigger an event. the actual value will be slightly more, as it will be only triggert on the next receive from the RC // so basically it must be a multiple of the time a transmit takes the RC #define HANDLEBUTTON_SLOW_REPEATS 2 // how many slow repeats should occur before fast repeats are engaged #define HANDLEBUTTON_REPEAT_TIMEOUT_0 560 // should be slightly more than 3 transmits of the slowest RC used, so min. 560 for the Pioneer RC #define HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_0 200 // slightly more than one transmit, used to detect repetitions #define HANDLEBUTTON_AVOID_REPEAT_DELAY_0 200 // must be more than one transmits time or repeats could occur also on buttons configured as repeat=false #define HANDLEBUTTON_REPEAT_TIMEOUT_1 130 // should be slightly more than 3 transmits of the slowest RC used, so min. 560 for the Pioneer RC #define HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_1 120 // slightly more than one transmit, used to detect repetitions #define HANDLEBUTTON_AVOID_REPEAT_DELAY_1 100 // must be more than one transmits time or repeats could occur also on buttons configured as repeat=false #define HANDLEBUTTON_REPEAT_TIMEOUT_2 120 // should be slightly more than 3 transmits of the slowest RC used, so min. 560 for the Pioneer RC #define HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_2 110 // slightly more than one transmit, used to detect repetitions #define HANDLEBUTTON_AVOID_REPEAT_DELAY_2 100 // must be more than one transmits time or repeats could occur also on buttons configured as repeat=false unsigned int handleButton_lastKey_countRepeats = 0; void handleButton(uint8_t _key) { handleButton(_key, false, 0); } void handleButton(uint8_t _key, bool _repeat) { handleButton(_key, _repeat, 0); } void handleButton(uint8_t _key, bool _repeat, uint8_t _rcType) { // _repeat: enable/disable repeat for this button - if false, holding the button will not trigger repeated events // _rcType: 0 = RC code types without toggle bit as in RC5/RC6, therefore a higher delay is required to avoid repeated events at single button presses // 1 = other (slower?) remote // 2 = ... unsigned int _minRepeatInterval = 0; if (debug2) { Serial.print(F(" loopTime=")); Serial.print((millis() - lastReceivedMillis)); Serial.println("ms"); } lastReceivedMillis = millis(); unsigned int _handleButton_repeat_Timeout, _handleButton_maxRepeatedReceiveMs, _handleButton_avoidRepeatDelay; if (_rcType == 1) { _handleButton_repeat_Timeout = HANDLEBUTTON_REPEAT_TIMEOUT_1; _handleButton_maxRepeatedReceiveMs = HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_1; _handleButton_avoidRepeatDelay = HANDLEBUTTON_AVOID_REPEAT_DELAY_1; } else if (_rcType == 2) { _handleButton_repeat_Timeout = HANDLEBUTTON_REPEAT_TIMEOUT_2; _handleButton_maxRepeatedReceiveMs = HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_2; _handleButton_avoidRepeatDelay = HANDLEBUTTON_AVOID_REPEAT_DELAY_2; } else { // PIONEER o.A. _handleButton_repeat_Timeout = HANDLEBUTTON_REPEAT_TIMEOUT_0; _handleButton_maxRepeatedReceiveMs = HANDLEBUTTON_MAX_REPEATED_RECEIVE_MS_0; _handleButton_avoidRepeatDelay = HANDLEBUTTON_AVOID_REPEAT_DELAY_0; } if (_repeat) _minRepeatInterval = 1; // if this is the POWER button, always use repeat, regardless of function call variable if (_key == BTN_POWER) _minRepeatInterval = 1; if (_minRepeatInterval > 0) { if (handleButton_lastSentKey == _key && (millis() - handleButton_repeatMillis) < _handleButton_repeat_Timeout && (millis() - handleButton_repeatedReceivedMillis) < _handleButton_maxRepeatedReceiveMs) { if (debug) { Serial.print(F(" R=")); Serial.print(handleButton_lastKey_countRepeats + 1); Serial.print(F(", handleButton_lastSentKey_begin=")); Serial.print(millis() - handleButton_lastSentKey_begin); Serial.print(F("ms, handleButton_repeatMillis=")); Serial.print(millis() - handleButton_repeatMillis); Serial.print(F("ms, handleButton_repeatedReceivedMillis=")); Serial.print(millis() - handleButton_repeatedReceivedMillis); Serial.println(F("ms")); } if ( (millis() - handleButton_repeatMillis) >= HANDLEBUTTON_FIRST_REPEAT_INTERVAL) { // slow repeats sendKey(_key); if (debug2) { Serial.print(F(" SLOW REPEAT ")); } handleButton_repeatMillis = millis(); handleButton_lastKey_countRepeats++; } else if ( handleButton_lastKey_countRepeats >= HANDLEBUTTON_SLOW_REPEATS && (millis() - handleButton_repeatMillis) >= _minRepeatInterval) { // fast repeats sendKey(_key); if (debug2) { Serial.print(F(" FAST REPEAT ")); } handleButton_repeatMillis = millis(); handleButton_lastKey_countRepeats++; } else { // waiting to reach HANDLEBUTTON_FIRST_REPEAT_INTERVAL //handleButton_repeatMillis = millis(); if (debug2) { Serial.println(F(" REPEAT WAITING ")); } } } else { // this is the initial button press handleButton_lastSentKey_begin = millis(); handleButton_repeatMillis = millis(); handleButton_lastSentKey = _key; handleButton_lastKey_countRepeats = 0; sendKey(_key); if (debug2) { Serial.print(F(" INITIAL ")); } if (debug) { Serial.print(F(" R=")); Serial.println(handleButton_lastKey_countRepeats); } } if (handleButton_lastSentKey == _key) { handleButton_repeatedReceivedMillis = millis(); if (debug2) { Serial.println(F(" REPRECV ")); } } } else if (!_repeat) { // only send once if ( handleButton_lastSentKey != _key || (handleButton_lastSentKey == _key && (millis() - handleButton_lastSentKey_begin) > _handleButton_avoidRepeatDelay)) { sendKey(_key); if (debug2) Serial.println(F(" ONCE")); //handleButton_lastSentKey_begin = millis(); handleButton_lastSentKey = _key; } if (handleButton_lastSentKey == _key) { handleButton_lastSentKey_begin = millis(); } } }