#include <string>
//#include <iostream>
+// Some global communications stuff:
+#include <QMutex>
+extern bool commandInFlight;
+extern QMutex commandIFMutex;
+
+// The official NEC protocol, as I understand it, has the following attributes:
+// A "zero" is encoded with a 560 usec pulse, 560 usec space.
+// A "one" is encoded with a 560 usec pulse, and 3*560 (1680) usec space.
+// The header is a 9000 usec pulse, 4500 usec space.
+// Commands end with a trailing 560 usec pulse.
+// A repeat block is a 9000 usec pulse, 2250 usec space, then trailing pulse.
+// Each command runs for 110000 usec before another can be executed.
+
+// For standard NEC, use this constructor:
+NECProtocol::NECProtocol(
+ QObject *guiObject,
+ unsigned int index)
+ : PIRProtocol(guiObject, index, 110000, true),
+ zeroPulse(560),
+ zeroSpace(560),
+ onePulse(560),
+ oneSpace(1680),
+ headerPulse(9000),
+ headerSpace(4500),
+ hasHeaderPair(true),
+ trailerPulse(560),
+ hasTrailerPulse(true),
+ repeatPulse(9000),
+ repeatSpace(2250),
+ hasRepeatPair(true),
+ repeatNeedsHeader(false),
+ fullHeadlessRepeat(false),
+ elevenBitToggle(false)
+{
+}
+
+// For non-standard NEC, use this constructor:
NECProtocol::NECProtocol(
QObject *guiObject,
unsigned int index,
zeroSpace(zSpace),
onePulse(oPulse),
oneSpace(oSpace),
- hasTrailerPulse(false),
hasHeaderPair(false),
+ hasTrailerPulse(false),
hasRepeatPair(false),
repeatNeedsHeader(false),
- fullHeadlessRepeat(false)
+ fullHeadlessRepeat(false),
+ elevenBitToggle(false)
{
}
fullHeadlessRepeat = flag;
}
-void NECProtocol::setPreData(
- unsigned long data,
- unsigned int bits)
-{
- appendToBitSeq(preData, data, bits);
-}
-
-void NECProtocol::setPostData(
- unsigned long data,
- unsigned int bits)
+void NECProtocol::setElevenBitToggle(
+ bool flag)
{
- appendToBitSeq(postData, data, bits);
+ elevenBitToggle = flag;
}
void NECProtocol::startSendingCommand(
// whole thing in a try/catch block:
try
{
- clearRepeatFlag();
-
- // Check if we are meant to be the recipient of this command:
+ // First, check if we are meant to be the recipient of this command:
if (threadableID != id) return;
+ // An object that helps keep track of the number of commands:
+// PIRCommandCounter commandCounter;
+
+ // Ok, we're going to lock down this method and make sure
+ // only one guy at a time passes this point:
+// QMutexLocker commandLocker(&commandMutex);
+
+ clearRepeatFlag();
+
KeycodeCollection::const_iterator i = keycodes.find(command);
// Do we even have this key defined?
}
// construct the device:
- PIRDevice device(carrierFrequency, dutyCycle);
+ PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
int repeatCount = 0;
while (repeatCount < MAX_REPEAT_COUNT)
// use that signal. Otherwise, generate a normal command string.
if (hasRepeatPair && repeatCount)
{
- commandDuration = generateRepeatCommand(device);
+ commandDuration = generateRepeatCommand(rx51device);
}
else if (fullHeadlessRepeat && repeatCount)
{
- commandDuration = generateHeadlessCommand((*i).second, device);
+ commandDuration = generateHeadlessCommand((*i).second, rx51device);
+ }
+ else if (elevenBitToggle && (repeatCount % 2))
+ {
+ commandDuration = generateToggledCommand((*i).second, rx51device);
}
else
{
- commandDuration = generateStandardCommand((*i).second, device);
+ commandDuration = generateStandardCommand((*i).second, rx51device);
}
// Now, tell the device to send the whole command:
- device.sendCommandToDevice();
+ rx51device.sendCommandToDevice();
// sleep until the next repetition of command:
sleepUntilRepeat(commandDuration);
// Check whether we've been asked to stop:
if (checkRepeatFlag())
{
+ QMutexLocker cifLocker(&commandIFMutex);
+ commandInFlight = false;
return;
}
}
// inform the gui:
emit commandFailed(e.getError().c_str());
}
+
+ QMutexLocker cifLocker(&commandIFMutex);
+ commandInFlight = false;
}
int NECProtocol::generateStandardCommand(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
// First, the "header" pulse (if any):
if (hasHeaderPair)
{
- device.addPair(headerPulse, headerSpace);
+ rx51device.addPair(headerPulse, headerSpace);
duration += (headerPulse + headerSpace);
}
// Next, the "pre" data:
- duration += pushBits(preData, device);
+ duration += pushBits(preData, rx51device);
// Next, add the actual command:
- duration += pushBits(bits, device);
+ duration += pushBits(bits, rx51device);
// Next, add the "post" data:
- duration += pushBits(postData, device);
+ duration += pushBits(postData, rx51device);
// Finally add the "trail":
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::generateHeadlessCommand(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
// First, the "pre" data:
- duration += pushBits(preData, device);
+ duration += pushBits(preData, rx51device);
// Next, add the actual command:
- duration += pushBits(bits, device);
+ duration += pushBits(bits, rx51device);
// Next, add the "post" data:
- duration += pushBits(postData, device);
+ duration += pushBits(postData, rx51device);
// Finally add the "trail":
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::generateRepeatCommand(
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
if (hasHeaderPair)
{
// Ok, then add the header to the repeat:
- device.addPair(headerPulse, headerSpace);
+ rx51device.addPair(headerPulse, headerSpace);
duration += (headerPulse + headerSpace);
}
}
// Add the repeat pulse:
- device.addPair(repeatPulse, repeatSpace);
+ rx51device.addPair(repeatPulse, repeatSpace);
duration += (repeatPulse + repeatSpace);
// Finally add the trailer:
if (hasTrailerPulse)
{
- device.addSingle(trailerPulse);
+ rx51device.addSingle(trailerPulse);
+ duration += trailerPulse;
+ }
+
+ return duration;
+}
+
+
+// NOTE! The following is a special command to toggle the last eleven bits
+// of the fifteen-bit commands used by Denon, Sharp, and a few others. It
+// assumes the command sequence will contain all fifteen bits. If this
+// is not the case, it will work incorrectly!
+int NECProtocol::generateToggledCommand(
+ const CommandSequence &bits,
+ PIRRX51Hardware &rx51device)
+{
+ int duration = 0;
+
+ CommandSequence::const_iterator i = bits.begin();
+
+ int bitcount = 0;
+ // First 4 bits:
+ while ((bitcount < 4) && (i != bits.end()))
+ {
+ if (*i)
+ {
+ // Send pulse for "one":
+ rx51device.addPair(onePulse, oneSpace);
+ duration += (onePulse + oneSpace);
+ }
+ else
+ {
+ // Send pulse for "zero":
+ rx51device.addPair(zeroPulse, zeroSpace);
+ duration += (zeroPulse + zeroSpace);
+ }
+ ++i;
+ ++bitcount;
+ }
+
+ // Now, invert the last eleven bits:
+ while (i != bits.end())
+ {
+ if (*i)
+ {
+ // Send pulse for "zero":
+ rx51device.addPair(zeroPulse, zeroSpace);
+ duration += (zeroPulse + zeroSpace);
+ }
+ else
+ {
+ // Send pulse for "one":
+ rx51device.addPair(onePulse, oneSpace);
+ duration += (onePulse + oneSpace);
+ }
+ ++i;
+ }
+
+ // Add trail on end:
+ if (hasTrailerPulse)
+ {
+ rx51device.addSingle(trailerPulse);
duration += trailerPulse;
}
int NECProtocol::pushBits(
const CommandSequence &bits,
- PIRDevice &device)
+ PIRRX51Hardware &rx51device)
{
int duration = 0;
CommandSequence::const_iterator i = bits.begin();
if (*i)
{
// Send the pulse for "One":
- device.addPair(onePulse, oneSpace);
+ rx51device.addPair(onePulse, oneSpace);
duration += (onePulse + oneSpace);
}
else
{
// Send the pulse for "Zero":
- device.addPair(zeroPulse, zeroSpace);
+ rx51device.addPair(zeroPulse, zeroSpace);
duration += (zeroPulse + zeroSpace);
}
++i;