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