Search for Power Button Panel
[pierogi] / protocols / paceprotocol.cpp
1 #include "paceprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6
7 // Some global communications stuff:
8 #include <QMutex>
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
11
12 // The Pace protocol is fairly simple.  (Not sure I've got good data, though)
13 // A "zero" is encoded with a 630 usec pulse, 7*630 (4410) usec space.
14 // A "one" is encoded with a 630 usec pulse, 11*630 (6930) usec space.
15 // Different opinions exist on what is the header; I'm going to go with
16 //   a 630 usec pulse, 6930 usec space one.  Hope it works.
17 // Commands end with a trailing 630 usec pulse.
18 // Full pulse train is re-sent when repeating.
19 // Each command runs for 120000 usec.
20 // The carrier frequency is 38 kHz.
21
22 PaceProtocol::PaceProtocol(
23   QObject *guiObject,
24   unsigned int index)
25   : SpaceProtocol(
26       guiObject, index,
27       630, 4410,
28       630, 6930,
29       630, 6930,
30       500,
31       120000, true),
32     keypressCount(0)
33 {
34 }
35
36
37 void PaceProtocol::startSendingCommand(
38   unsigned int threadableID,
39   PIRKeyName command)
40 {
41   // Exceptions here are problematic; I'll try to weed them out by putting the
42   // whole thing in a try/catch block:
43   try
44   {
45     // First, check if we are meant to be the recipient of this command:
46     if (threadableID != id) return;
47
48     clearRepeatFlag();
49
50     KeycodeCollection::const_iterator i = keycodes.find(command);
51
52     // Do we even have this key defined?
53     if (i == keycodes.end())
54     {
55       QMutexLocker cifLocker(&commandIFMutex);
56       commandInFlight = false;
57       return;
58 //      std::string s = "Tried to send a non-existent command.\n";
59 //      throw PIRException(s);
60     }
61
62     // construct the device:
63     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
64
65     int repeatCount = 0;
66     int commandDuration = 0;
67     while (repeatCount < MAX_REPEAT_COUNT)
68     {
69       commandDuration = generateStandardCommand((*i).second, rx51device);
70
71       // Now, tell the device to send the whole command:
72       rx51device.sendCommandToDevice();
73
74       // sleep until the next repetition of command:
75       sleepUntilRepeat(commandDuration);
76
77       // Check whether we've reached the minimum required number of repetitons:
78       if (repeatCount >= minimumRepetitions)
79       {
80         // Check whether we've been asked to stop:
81         if (checkRepeatFlag())
82         {
83           break;
84 /*
85           ++keypressCount;
86           QMutexLocker cifLocker(&commandIFMutex);
87           commandInFlight = false;
88           return;
89 */
90         }
91       }
92
93       ++repeatCount;
94     }
95
96     ++keypressCount;
97     QMutexLocker cifLocker(&commandIFMutex);
98     commandInFlight = false;
99   }
100   catch (PIRException e)
101   {
102     // inform the gui:
103     emit commandFailed(e.getError().c_str());
104   }
105 }
106
107
108 // Pace seems to be going with a header pulse/space, a toggle bit, and nine
109 // more bits of data.  Information is sketchy, however.  I'll be going with
110 // three bits of pre-data (address?), and six bits of command...
111
112 int PaceProtocol::generateStandardCommand(
113   const PIRKeyBits &pkb,
114   PIRRX51Hardware &rx51device)
115 {
116   int duration = 0;
117
118   // First, the "header" pulse:
119   rx51device.addPair(headerPulse, headerSpace);
120   duration += (headerPulse + headerSpace);
121
122   // Next, the toggle bit:
123   if (keypressCount % 2)
124   {
125     rx51device.addPair(onePulse, oneSpace);
126     duration += (onePulse + oneSpace);
127   }
128   else
129   {
130     rx51device.addPair(zeroPulse, zeroSpace);
131     duration += (zeroPulse + zeroSpace);
132   }
133
134   // Next, three bits of pre-data:
135   duration += pushBits(preData, rx51device);
136
137   // Next, six bits of data:
138   duration += pushBits(pkb.firstCode, rx51device);
139
140   // Finally add the "trail":
141   rx51device.addSingle(trailerPulse);
142   duration += trailerPulse;
143
144   return duration;
145 }