Advanced Settings Panel
[pierogi] / protocols / sharpprotocol.cpp
1 #include "sharpprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6 #include <string>
7
8 // Some global communications stuff:
9 #include <QMutex>
10 extern bool commandInFlight;
11 extern QMutex commandIFMutex;
12
13 // Sharp's protocol should have the following attributes:
14 // A "zero" is encoded with a 320 usec pulse, 680 usec space.
15 // A "one" is encoded with a 320 usec pulse, and 1680 usec space.
16 // There is no header pulse.
17 // The pulse train ends with a trailing 320 usec pulse.
18 // For repeating, the entire train is re-sent, except that the command
19 // section (and the last two bits) are inverted in each odd repeat.
20 // There is a 40000 usec delay between the end of one command and the start
21 // of the next.
22 // The command should be repeated at least once.
23 // The carrier frequency is 38 kHz, duty cycle is 1/3.
24
25 SharpProtocol::SharpProtocol(
26   QObject *guiObject,
27   unsigned int index,
28   bool expBit)
29   : SpaceProtocol(
30       guiObject, index,
31       320, 680,
32       320, 1680,
33       0, 0,
34       320,
35       40000, false),
36     expansionBit(expBit)
37 {
38   setCarrierFrequency(38000);
39 //  setDutyCycle(33);
40 }
41
42
43 void SharpProtocol::startSendingCommand(
44   unsigned int threadableID,
45   PIRKeyName command)
46 {
47   // Exceptions here are problematic; I'll try to weed them out by putting the
48   // whole thing in a try/catch block:
49   try
50   {
51     // First, check if we are meant to be the recipient of this command:
52     if (threadableID != id) return;
53
54     clearRepeatFlag();
55
56     KeycodeCollection::const_iterator i = keycodes.find(command);
57
58     // Do we even have this key defined?
59     if (i == keycodes.end())
60     {
61       QMutexLocker cifLocker(&commandIFMutex);
62       commandInFlight = false;
63       return;
64 //      std::string s = "Tried to send a non-existent command.\n";
65 //      throw PIRException(s);
66     }
67
68     // construct the device:
69     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
70
71     int repeatCount = 0;
72     int commandDuration = 0;
73     while (repeatCount < MAX_REPEAT_COUNT)
74     {
75       // Every other repeat count, we invert everything but the address:
76       if (repeatCount % 2)
77       {
78         commandDuration = generateToggledCommand((*i).second, rx51device);
79       }
80       else
81       {
82         commandDuration = generateStandardCommand((*i).second, rx51device);
83       }
84
85       // Now, tell the device to send the whole command:
86       rx51device.sendCommandToDevice();
87
88       // sleep until the next repetition of command:
89       sleepUntilRepeat(commandDuration);
90
91       // Check whether we've reached the minimum required number of repetitons:
92 //      if (repeatCount >= minimumRepetitions)
93       if (repeatCount >= 1)
94       {
95         // Check whether we've been asked to stop:
96         if (checkRepeatFlag())
97         {
98           break;
99 /*
100           QMutexLocker cifLocker(&commandIFMutex);
101           commandInFlight = false;
102           return;
103 */
104         }
105       }
106
107       ++repeatCount;
108     }
109
110     QMutexLocker cifLocker(&commandIFMutex);
111     commandInFlight = false;
112   }
113   catch (PIRException e)
114   {
115     // inform the gui:
116     emit commandFailed(e.getError().c_str());
117   }
118 }
119
120
121 int SharpProtocol::generateStandardCommand(
122   const PIRKeyBits &pkb,
123   PIRRX51Hardware &rx51device)
124 {
125   int duration = 0;
126
127   // First, push the address:
128   duration += pushReverseBits(pkb.firstCode, rx51device);
129
130   // Next, push the command:
131   duration += pushReverseBits(pkb.secondCode, rx51device);
132
133   // Next, there is an "expansion" bit and a "check" bit.  Not entirely sure
134   // what these two do.  The check bit is fixed at "0".
135   if (expansionBit)
136   {
137     rx51device.addPair(onePulse, oneSpace);
138     duration += (onePulse + oneSpace);
139   }
140   else
141   {
142     rx51device.addPair(zeroPulse, zeroSpace);
143     duration += (zeroPulse + zeroSpace);
144   }
145
146   rx51device.addPair(zeroPulse, zeroSpace);
147   duration += (zeroPulse + zeroSpace);
148
149   // Finally add the "trail":
150   rx51device.addSingle(trailerPulse);
151   duration += trailerPulse;
152
153   return duration;
154 }
155
156
157 // This is the same as the standard command, except all bits but the address
158 // are inverted:
159 int SharpProtocol::generateToggledCommand(
160   const PIRKeyBits &pkb,
161   PIRRX51Hardware &rx51device)
162 {
163   int duration = 0;
164
165   pushReverseBits(pkb.firstCode, rx51device);
166
167   // This time we invert the command bits:
168   pushInvertedReverseBits(pkb.secondCode, rx51device);
169
170   // We'll also invert the two administrative bits here:
171   if (expansionBit)
172   {
173     rx51device.addPair(zeroPulse, zeroSpace);
174     duration += (zeroPulse + zeroSpace);
175   }
176   else
177   {
178     rx51device.addPair(onePulse, oneSpace);
179     duration += (onePulse + oneSpace);
180   }
181
182   rx51device.addPair(onePulse, oneSpace);
183   duration += (onePulse + oneSpace);
184
185   // Add trail on end:
186   rx51device.addSingle(trailerPulse);
187   duration += trailerPulse;
188
189   return duration;
190 }