Advanced Settings Panel
[pierogi] / protocols / pirprotocol.cpp
1 #include "pirprotocol.h"
2
3 #include <QMutex>
4 #include <QMetaType>
5
6 #include <time.h>
7 #include <sstream>
8 #include <errno.h>
9 #include "pirexception.h"
10
11 // A flag for communicating with the main thread:
12 extern bool stopRepeatingFlag;
13 extern QMutex stopRepeatingMutex;
14
15 // Check if a command is running:
16 //extern bool commandInFlight;
17 //extern QMutex commandIFMutex;
18
19 // From what I understand (mostly from reading LIRC config files), NEC
20 // protocol based remotes mostly use a frequency of 38000 units and a
21 // duty cycle of 50%.  They'll be set to these defaults here, and overridden
22 // as needed by child classes.
23
24 PIRProtocol::PIRProtocol(
25   QObject *guiObject,
26   unsigned int index,
27   unsigned int gSpace,
28   bool iclflag)
29   : carrierFrequency(38000),
30     dutyCycle(50),
31     isConstantLength(iclflag),
32     gap(gSpace),
33     minimumRepetitions(0),
34     id(index)
35 {
36   qRegisterMetaType<PIRKeyName>("PIRKeyName");
37
38   QObject::connect(
39     guiObject,
40     SIGNAL(buttonPressed(unsigned int, PIRKeyName)),
41     this,
42     SLOT(startSendingCommand(unsigned int, PIRKeyName)),
43     Qt::QueuedConnection);
44
45   QObject::connect(
46     this,
47     SIGNAL(commandFailed(const char *)),
48     guiObject,
49     SLOT(receivedExternalWarning(const char *)),
50     Qt::QueuedConnection);
51 }
52
53
54 unsigned int PIRProtocol::getCarrierFrequency() const
55 {
56   return carrierFrequency;
57 }
58
59
60 void PIRProtocol::setCarrierFrequency(
61   unsigned int cf)
62 {
63   carrierFrequency = cf;
64 }
65
66
67 unsigned int PIRProtocol::getDutyCycle() const
68 {
69   return dutyCycle;
70 }
71
72
73 void PIRProtocol::setDutyCycle(
74   unsigned int dc)
75 {
76   dutyCycle = dc;
77 }
78
79
80 void PIRProtocol::addKey(
81   PIRKeyName key,
82   unsigned long command,
83   unsigned int size)
84 {
85   // First, if key already exists, clear it out:
86   PIRKeyBits *pkb = 0;
87   KeycodeCollection::iterator i = keycodes.find(key);
88   if (i != keycodes.end())
89   {
90     pkb = &(i->second);
91     pkb->firstCode.clear();
92   }
93   else
94   {
95     pkb = &(keycodes[key]);
96   }
97
98   appendToBitSeq(pkb->firstCode, command, size);
99 }
100
101
102 void PIRProtocol::addSIRCKey(
103   PIRKeyName key,
104   unsigned int addressData,
105   unsigned int size,
106   unsigned int commandData)
107 {
108   // First, if key already exists, clear it out:
109   PIRKeyBits *pkb = 0;
110   KeycodeCollection::iterator i = keycodes.find(key);
111   if (i != keycodes.end())
112   {
113     pkb = &(i->second);
114     pkb->firstCode.clear();
115     pkb->secondCode.clear();
116     pkb->thirdCode.clear();
117   }
118   else
119   {
120     pkb = &(keycodes[key]);
121   }
122
123   // First, append the address data:
124   appendToBitSeq(pkb->firstCode, addressData, size);
125
126   // Next, the command data.  The size is always 7 bits:
127   appendToBitSeq(pkb->secondCode, commandData, 7);
128 }
129
130
131 void PIRProtocol::addSIRC20Key(
132   PIRKeyName key,
133   unsigned int secondaryAddressData,
134   unsigned int primaryAddressData,
135   unsigned int commandData)
136 {
137   // First, if key already exists, clear it out:
138   PIRKeyBits *pkb = 0;
139   KeycodeCollection::iterator i = keycodes.find(key);
140   if (i != keycodes.end())
141   {
142     pkb = &(i->second);
143     pkb->firstCode.clear();
144     pkb->secondCode.clear();
145     pkb->thirdCode.clear();
146   }
147   else
148   {
149     pkb = &(keycodes[key]);
150   }
151
152   // First, append the secondary address data:
153   appendToBitSeq(pkb->firstCode, secondaryAddressData, 8);
154
155   // Next, the primary address data:
156   appendToBitSeq(pkb->secondCode, primaryAddressData, 5);
157
158   // Next, the command data.  The size is always 7 bits:
159   appendToBitSeq(pkb->thirdCode, commandData, 7);
160 }
161
162
163 void PIRProtocol::addSharpKey(
164   PIRKeyName key,
165   unsigned int addressData,
166   unsigned int commandData)
167 {
168   // First, if key already exists, clear it out:
169   PIRKeyBits *pkb = 0;
170   KeycodeCollection::iterator i = keycodes.find(key);
171   if (i != keycodes.end())
172   {
173     pkb = &(i->second);
174     pkb->firstCode.clear();
175     pkb->secondCode.clear();
176   }
177   else
178   {
179     pkb = &(keycodes[key]);
180   }
181
182   // Sharp commands are all 5 bit address, 8 bit command:
183   appendToBitSeq(pkb->firstCode, addressData, 5);
184   appendToBitSeq(pkb->secondCode, commandData, 8);
185 }
186
187
188 void PIRProtocol::addNECKey(
189   PIRKeyName key,
190   unsigned int addressData,
191   unsigned int commandData)
192 {
193   PIRKeyBits *pkb = 0;
194   KeycodeCollection::iterator i = keycodes.find(key);
195   if (i != keycodes.end())
196   {
197     pkb = &(i->second);
198     pkb->firstCode.clear();
199     pkb->secondCode.clear();
200     pkb->thirdCode.clear();
201     pkb->fourthCode.clear();
202   }
203   else
204   {
205     pkb = &(keycodes[key]);
206   }
207
208   // NEC commands should always be 8 bits address, 8 bits command:
209   appendToBitSeq(pkb->firstCode, addressData, 8);
210   appendToBitSeq(pkb->secondCode, commandData, 8);
211 }
212
213
214 void PIRProtocol::addPanOldKey(
215   PIRKeyName key,
216   unsigned int addressData,
217   unsigned int commandData)
218 {
219   PIRKeyBits *pkb = 0;
220   KeycodeCollection::iterator i = keycodes.find(key);
221   if (i != keycodes.end())
222   {
223     pkb = &(i->second);
224     pkb->firstCode.clear();
225     pkb->secondCode.clear();
226     pkb->thirdCode.clear();
227     pkb->fourthCode.clear();
228   }
229   else
230   {
231     pkb = &(keycodes[key]);
232   }
233
234   // The "Old Panasonic" commands have 5 bits address, 6 bits command:
235   appendToBitSeq(pkb->firstCode, addressData, 5);
236   appendToBitSeq(pkb->secondCode, commandData, 6);
237 }
238
239
240 // Most Pioneer keys use the NEC key format, but some are pairs of
241 // NEC keys sent together:
242 void PIRProtocol::addPioneerKey(
243   PIRKeyName key,
244   unsigned int firstAddress,
245   unsigned int firstCommand,
246   unsigned int secondAddress,
247   unsigned int secondCommand)
248 {
249   PIRKeyBits *pkb = 0;
250   KeycodeCollection::iterator i = keycodes.find(key);
251   if (i != keycodes.end())
252   {
253     pkb = &(i->second);
254     pkb->firstCode.clear();
255     pkb->secondCode.clear();
256     pkb->thirdCode.clear();
257     pkb->fourthCode.clear();
258   }
259   else
260   {
261     pkb = &(keycodes[key]);
262   }
263
264   // All four codes should be 8 bits in length:
265   appendToBitSeq(pkb->firstCode, firstAddress, 8);
266   appendToBitSeq(pkb->secondCode, firstCommand, 8);
267   appendToBitSeq(pkb->thirdCode, secondAddress, 8);
268   appendToBitSeq(pkb->fourthCode, secondCommand, 8);
269 }
270
271
272 /*
273 void PIRProtocol::addRCAKey(
274   PIRKeyName key,
275   unsigned int addressData,
276   unsigned int commandData)
277 {
278   PIRKeyBits *pkb = 0;
279   KeycodeCollection::iterator i = keycodes.find(key);
280   if (i != keycodes.end())
281   {
282     pkb = &(i->second);
283     pkb->firstcode.clear();
284     pkb->secondCode.clear();
285   }
286   else
287   {
288     pkb = &(keycodes[key]);
289   }
290
291   // Address is 4 bits, command is 8 bits:
292   appendToBitSeq(pkb->firstCode, addressData, 4);
293   appendToBitSeq(pkb->secondCode, commandData, 8);
294 }
295 */
296
297
298 void PIRProtocol::addKaseikyoKey(
299   PIRKeyName key,
300   unsigned int addressData,
301   unsigned int commandData)
302 {
303   PIRKeyBits *pkb = 0;
304   KeycodeCollection::iterator i = keycodes.find(key);
305   if (i != keycodes.end())
306   {
307     pkb = &(i->second);
308     pkb->firstCode.clear();
309     pkb->secondCode.clear();
310   }
311   else
312   {
313     pkb = &(keycodes[key]);
314   }
315
316   appendToBitSeq(pkb->firstCode, addressData, 12);
317   appendToBitSeq(pkb->secondCode, commandData, 8);
318 }
319
320
321 void PIRProtocol::addDishKey(
322   PIRKeyName key,
323   unsigned int firstCommand,
324   unsigned int secondCommand)
325 {
326   PIRKeyBits *pkb = 0;
327   KeycodeCollection::iterator i = keycodes.find(key);
328   if (i != keycodes.end())
329   {
330     pkb = &(i->second);
331     pkb->firstCode.clear();
332     pkb->secondCode.clear();
333   }
334   else
335   {
336     pkb = &(keycodes[key]);
337   }
338
339   appendToBitSeq(pkb->firstCode, firstCommand, 6);
340   appendToBitSeq(pkb->secondCode, secondCommand, 5);
341 }
342
343
344 void PIRProtocol::addXMPKey(
345   PIRKeyName key,
346   unsigned int firstCommand,
347   unsigned int secondCommand)
348 {
349   PIRKeyBits *pkb = 0;
350   KeycodeCollection::iterator i = keycodes.find(key);
351   if (i != keycodes.end())
352   {
353     pkb = &(i->second);
354     pkb->firstCode.clear();
355     pkb->secondCode.clear();
356   }
357   else
358   {
359     pkb = &(keycodes[key]);
360   }
361
362   appendToBitSeq(pkb->firstCode, firstCommand, 8);
363   appendToBitSeq(pkb->secondCode, secondCommand, 8);
364 }
365
366
367 void PIRProtocol::setMinimumRepetitions(
368   unsigned int minrep)
369 {
370   minimumRepetitions = minrep;
371 }
372
373
374 void PIRProtocol::setPreData(
375   unsigned long data,
376   unsigned int bits)
377 {
378   // If the container is not empty, first clear it out:
379   if (!preData.empty())
380   {
381     preData.clear();
382   }
383
384   appendToBitSeq(preData, data, bits);
385 }
386
387
388 void PIRProtocol::setPostData(
389   unsigned long data,
390   unsigned int bits)
391 {
392   // If the container is not empty, first clear it out:
393   if (!postData.empty())
394   {
395     postData.clear();
396   }
397
398   appendToBitSeq(postData, data, bits);
399 }
400
401
402 bool PIRProtocol::isCommandSupported(
403   PIRKeyName command)
404 {
405   return (keycodes.find(command) != keycodes.end());
406 }
407
408
409 void PIRProtocol::appendToBitSeq(
410   CommandSequence &sequence,
411   unsigned int bits,
412   int size)
413 {
414   if (size == 0)
415   {
416     // This is bad, but just return silently for now...
417     return;
418   }
419
420   // For each bit in the char, append a 1 or a 0 into the sequence.
421   // Starting with the largest bit, move forward one bit at a time:
422   unsigned int currentBit = 1 << (size - 1);
423
424   do
425   {
426     if (bits & currentBit)
427     {
428       sequence.push_back(1);
429     }
430     else
431     {
432       sequence.push_back(0);
433     }
434
435     currentBit = currentBit >> 1;
436   }
437   while (currentBit > 0);
438 }
439
440
441 void PIRProtocol::clearRepeatFlag()
442 {
443   QMutexLocker locker(&stopRepeatingMutex);
444   stopRepeatingFlag = false;
445 }
446
447
448 bool PIRProtocol::checkRepeatFlag()
449 {
450   QMutexLocker locker(&stopRepeatingMutex);
451   return stopRepeatingFlag;
452 }
453
454
455 // Note that the following routine blindly sleeps for the amount of time
456 // specified by the LIRC config file.  The extra overhead of processing
457 // each command will mean that repeated commands will overshoot the config
458 // time by some amount.  We could improve accuracy by waiting a little less
459 // than the specified time, if we could get a good handle on how long the
460 // overhead is delaying the command...
461 #define PIEROGI_OVERHEAD_HACK 13260
462
463 void PIRProtocol::sleepUntilRepeat(
464   int commandDuration)
465 {
466   int microseconds;
467
468   // If the LIRC config file specifies the flag "CONST_LENGTH", that means
469   // the "gap" value is the exact amount of time to wait between kicking off
470   // each command.  If not, then the "gap" needs to be added on to the total
471   // time of the previous command to see how long to sleep.
472
473   if (isConstantLength)
474   {
475     microseconds = (gap - commandDuration) - PIEROGI_OVERHEAD_HACK;
476   }
477   else
478   {
479     microseconds = gap - PIEROGI_OVERHEAD_HACK;
480   }
481
482 /*
483   // Don't even bother sleeping if there's only a few microseconds:
484   if (microseconds < 1000)
485   {
486     return;
487   }
488 */
489   // For now, I'm going to enforce a minimum sleep of 10 ms, so that we
490   // don't get runaway commands:
491   if (microseconds < 10000)
492   {
493     microseconds = 10000;
494   }
495
496   timespec sleeptime;
497   sleeptime.tv_sec = 0;
498   sleeptime.tv_nsec = microseconds * 1000;
499
500   timespec remainingtime;
501
502   if (nanosleep(&sleeptime, &remainingtime) == -1)
503   {
504     std::stringstream ss;
505     ss << "Problem while sleeping.\n";
506     ss << "Trying to sleep for: " << microseconds << "\n";
507     ss << "Nanosleep returned error: " << strerror(errno) << "\n";
508     throw PIRException(ss.str());
509   }
510 }
511
512
513 void PIRProtocol::setGapSize(
514   int gapSize,
515   bool iclFlag)
516 {
517   gap = gapSize;
518   isConstantLength = iclFlag;
519 }