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