Still fixing install, more keyset work
[pierogi] / necprotocol.cpp
index 036c15e..6468e12 100644 (file)
@@ -4,6 +4,43 @@
 #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,
@@ -18,11 +55,12 @@ NECProtocol::NECProtocol(
     zeroSpace(zSpace),
     onePulse(oPulse),
     oneSpace(oSpace),
-    hasTrailerPulse(false),
     hasHeaderPair(false),
+    hasTrailerPulse(false),
     hasRepeatPair(false),
     repeatNeedsHeader(false),
-    fullHeadlessRepeat(false)
+    fullHeadlessRepeat(false),
+    elevenBitToggle(false)
 {
 }
 
@@ -63,18 +101,10 @@ void NECProtocol::setFullHeadlessRepeat(
   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(
@@ -85,11 +115,18 @@ 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?
@@ -117,6 +154,10 @@ void NECProtocol::startSendingCommand(
       {
         commandDuration = generateHeadlessCommand((*i).second, rx51device);
       }
+      else if (elevenBitToggle && (repeatCount % 2))
+      {
+        commandDuration = generateToggledCommand((*i).second, rx51device);
+      }
       else
       {
         commandDuration = generateStandardCommand((*i).second, rx51device);
@@ -134,6 +175,8 @@ void NECProtocol::startSendingCommand(
         // Check whether we've been asked to stop:
         if (checkRepeatFlag())
         {
+          QMutexLocker cifLocker(&commandIFMutex);
+          commandInFlight = false;
           return;
         }
       }
@@ -146,6 +189,9 @@ void NECProtocol::startSendingCommand(
     // inform the gui:
     emit commandFailed(e.getError().c_str());
   }
+
+  QMutexLocker cifLocker(&commandIFMutex);
+  commandInFlight = false;
 }
 
 
@@ -240,6 +286,67 @@ int NECProtocol::generateRepeatCommand(
 }
 
 
+// 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;
+  }
+
+  return duration;
+}
+
+
 int NECProtocol::pushBits(
   const CommandSequence &bits,
   PIRRX51Hardware &rx51device)