crankyoldgit / IRremoteESP8266

Infrared remote library for ESP8266/ESP32: send and receive infrared signals with multiple protocols. Based on: https://github.com/shirriff/Arduino-IRremote/
GNU Lesser General Public License v2.1
2.98k stars 832 forks source link

RC6 36bit Toggle Bit #618

Closed JoergBo closed 5 years ago

JoergBo commented 5 years ago

Version/revison of the library used

v2.5.5 release

Expected behavior

I use IRRemote sending RC6 36bit. Sending works fine, when i watch the IR signal with a second device as a receiver. Only it seems that the toggle bit "0x8000" for RC6 36bit never toggles.

At a first look, everything looks ok in ir_RC5_RC6.cpp:

#if SEND_RC6
[...]
// Status: BETA / Should work fine.
//
// Ref:
//   http://www.sbprojects.com/knowledge/ir/rc6.php
//   http://www.righto.com/2010/12/64-bit-rc6-codes-arduino-and-xbox.html
uint64_t IRsend::toggleRC6(uint64_t data, uint16_t nbits) {
  if (nbits == kRC6_36Bits) return data ^ kRc6_36ToggleMask;
  return data ^ kRc6ToggleMask;
}

but when i test the sent IR-signal, nothing is toggled at the IR_Send routine. I mean, toggle should not be done for every sending, because you allways get the same output. Toggle should only be done every second sent signal.

Sending data=0xC80460001 len=36 produces 0xC80460001 at the IR-receiver, but should be 0xC80468001 for every second transmission.

crankyoldgit commented 5 years ago

Please see comment(s) in the code here: https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp#L232

// Send a Philips RC-6 packet.
// Note: Caller needs to take care of flipping the toggle bit (The 4th Most
//   Significant Bit). That bit differentiates between key press & key release.

i.e. you'd need to call it like this (code off the top of my head, un-tested etc)

// Simulating a button press etc.
uint64_t kButton = 0xC80460001;
uint8_t kBits = 36;
irsend.sendRC6(kButton, kBits);  // Button pressed.
delay(1000); // Pretend button is held down for a second.
irsend.sendRC6(irsend.toggleRC6(kButton, kBits), kBits);  // Button released.

The library doesn't keep state for you for button presses as it could be asked to send a 36 bit RC6 message to one device, and then a standard RC6 20 bit message to some other device. The library has no way of knowing what the user intends, hence it gives you all the tools you need to help you, but the user supplied program has to be the one remembering the state. Unfortunately there is no safe way for the library to operate in all possible situations.

JoergBo commented 5 years ago

OK, thanks for that explanation. I already integrated a toggle routine around the lib, but didn't understood, how to use the integrated toggle routine.

JoergBo commented 5 years ago

Please see comment(s) in the code here: https://github.com/markszabo/IRremoteESP8266/blob/master/src/ir_RC5_RC6.cpp#L232

// Send a Philips RC-6 packet.
// Note: Caller needs to take care of flipping the toggle bit (The 4th Most
//   Significant Bit). That bit differentiates between key press & key release.

i.e. you'd need to call it like this (code off the top of my head, un-tested etc)

// Simulating a button press etc.
uint64_t kButton = 0xC80460001;
uint8_t kBits = 36;
irsend.sendRC6(kButton, kBits);  // Button pressed.
delay(1000); // Pretend button is held down for a second.
irsend.sendRC6(irsend.toggleRC6(kButton, kBits), kBits);  // Button released.

The library doesn't keep state for you for button presses as it could be asked to send a 36 bit RC6 message to one device, and then a standard RC6 20 bit message to some other device. The library has no way of knowing what the user intends, hence it gives you all the tools you need to help you, but the user supplied program has to be the one remembering the state. Unfortunately there is no safe way for the library to operate in all possible situations.

One additional comment to that: The toggle bit at RC6-36 has nothing to do with press and release. Its working this way: if you press a button on the remote controll it sends the same code continously, without toggle, until you release the button. Next time you press the button on the remote, the toggle bit is flipped and as log as you hold the button, the same code is sent. And so on. So there is a possibility to handle that inside the lib, But ok, i understand that its more flexible in the main routine...

crankyoldgit commented 5 years ago

Yes. You are correct, I remember now. It was for subsequent presses that the protocol requires the bit to be toggled.

The library can't act like you propose without creating a list of all previous button presses to see if it needs to toggle that bit. That, as you understand and point out, is best done outside of the sendRC6() routine, especially due to memory handling considerations.