Advanced Settings Panel
[pierogi] / protocols / lircprotocol.cpp
1 #include "lircprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6 #include <string>
7 //#include <iostream>
8
9 // Some global communications stuff:
10 #include <QMutex>
11 extern bool commandInFlight;
12 extern QMutex commandIFMutex;
13
14 LIRCProtocol::LIRCProtocol(
15   QObject *guiObject,
16   unsigned int index,
17   unsigned int zPulse,
18   unsigned int zSpace,
19   unsigned int oPulse,
20   unsigned int oSpace,
21   unsigned int gSpace,
22   bool iclflag)
23   : SpaceProtocol(
24       guiObject, index,
25       zPulse, zSpace,
26       oPulse, oSpace,
27       0, 0,
28       0,
29       gSpace, iclflag),
30     hasHeaderPair(false),
31     hasTrailerPulse(false),
32     hasRepeatPair(false),
33     repeatNeedsHeader(false),
34     fullHeadlessRepeat(false)
35 {
36 }
37
38 void LIRCProtocol::setHeaderPair(
39   unsigned int pulse,
40   unsigned int space)
41 {
42   headerPulse = pulse;
43   headerSpace = space;
44   hasHeaderPair = true;
45 }
46
47 void LIRCProtocol::setTrailerPulse(
48   unsigned int pulse)
49 {
50   trailerPulse = pulse;
51   hasTrailerPulse = true;
52 }
53
54 void LIRCProtocol::setRepeatPair(
55   unsigned int pulse,
56   unsigned int space)
57 {
58   repeatPulse = pulse;
59   repeatSpace = space;
60   hasRepeatPair = true;
61 }
62
63 void LIRCProtocol::setRepeatNeedsHeader(
64   bool flag)
65 {
66   repeatNeedsHeader = flag;
67 }
68
69 void LIRCProtocol::setFullHeadlessRepeat(
70   bool flag)
71 {
72   fullHeadlessRepeat = flag;
73 }
74
75 void LIRCProtocol::startSendingCommand(
76   unsigned int threadableID,
77   PIRKeyName command)
78 {
79   // Exceptions here are problematic; I'll try to weed them out by putting the
80   // whole thing in a try/catch block:
81   try
82   {
83     // First, check if we are meant to be the recipient of this command:
84     if (threadableID != id) return;
85
86     clearRepeatFlag();
87
88     KeycodeCollection::const_iterator i = keycodes.find(command);
89
90     // Do we even have this key defined?
91     if (i == keycodes.end())
92     {
93       QMutexLocker cifLocker(&commandIFMutex);
94       commandInFlight = false;
95       return;
96 //      std::string s = "Tried to send a non-existent command.\n";
97 //      throw PIRException(s);
98     }
99
100     // construct the device:
101     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
102
103     int repeatCount = 0;
104     int commandDuration = 0;
105     while (repeatCount < MAX_REPEAT_COUNT)
106     {
107       // If we are currently repeating, and have a special "repeat signal",
108       // use that signal.  Otherwise, generate a normal command string.
109       if (hasRepeatPair && repeatCount)
110       {
111         commandDuration = generateRepeatCommand(rx51device);
112       }
113       else if (fullHeadlessRepeat && repeatCount)
114       {
115         commandDuration = generateHeadlessCommand((*i).second, rx51device);
116       }
117       else
118       {
119         commandDuration = generateStandardCommand((*i).second, rx51device);
120       }
121
122       // Now, tell the device to send the whole command:
123       rx51device.sendCommandToDevice();
124
125       // sleep until the next repetition of command:
126       sleepUntilRepeat(commandDuration);
127
128       // Check whether we've reached the minimum required number of repetitons:
129       if (repeatCount >= minimumRepetitions)
130       {
131         // Check whether we've been asked to stop:
132         if (checkRepeatFlag())
133         {
134           break;
135 /*
136           QMutexLocker cifLocker(&commandIFMutex);
137           commandInFlight = false;
138           return;
139 */
140         }
141       }
142
143       ++repeatCount;
144     }
145
146     QMutexLocker cifLocker(&commandIFMutex);
147     commandInFlight = false;
148   }
149   catch (PIRException e)
150   {
151     // inform the gui:
152     emit commandFailed(e.getError().c_str());
153   }
154 }
155
156
157 int LIRCProtocol::generateStandardCommand(
158   const PIRKeyBits &pkb,
159   PIRRX51Hardware &rx51device)
160 {
161   int duration = 0;
162
163   // First, the "header" pulse (if any):
164   if (hasHeaderPair)
165   {
166     rx51device.addPair(headerPulse, headerSpace);
167     duration += (headerPulse + headerSpace);
168   }
169
170   // For LIRC, just dump the bits straight into the device, one by one:
171   duration += pushBits(preData, rx51device);
172   duration += pushBits(pkb.firstCode, rx51device);
173   duration += pushBits(postData, rx51device);
174
175   // Finally add the "trail":
176   if (hasTrailerPulse)
177   {
178     rx51device.addSingle(trailerPulse);
179     duration += trailerPulse;
180   }
181
182   return duration;
183 }
184
185
186 int LIRCProtocol::generateHeadlessCommand(
187   const PIRKeyBits &pkb,
188   PIRRX51Hardware &rx51device)
189 {
190   int duration = 0;
191
192   // First, the "pre" data:
193   duration += pushBits(preData, rx51device);
194
195   // Next, add the actual command:
196   duration += pushBits(pkb.firstCode, rx51device);
197
198   // Next, add the "post" data:
199   duration += pushBits(postData, rx51device);
200
201   // Finally add the "trail":
202   if (hasTrailerPulse)
203   {
204     rx51device.addSingle(trailerPulse);
205     duration += trailerPulse;
206   }
207
208   return duration;
209 }
210
211
212 int LIRCProtocol::generateRepeatCommand(
213   PIRRX51Hardware &rx51device)
214 {
215   int duration = 0;
216
217   // Do we need the header?
218   if (repeatNeedsHeader)
219   {
220     // Do we even have a header?
221     if (hasHeaderPair)
222     {
223       // Ok, then add the header to the repeat:
224       rx51device.addPair(headerPulse, headerSpace);
225       duration += (headerPulse + headerSpace);
226     }
227   }
228
229   // Add the repeat pulse:
230   rx51device.addPair(repeatPulse, repeatSpace);
231   duration += (repeatPulse + repeatSpace);
232
233   // Finally add the trailer:
234   if (hasTrailerPulse)
235   {
236     rx51device.addSingle(trailerPulse);
237     duration += trailerPulse;
238   }
239
240   return duration;
241 }