Search for Power Button Panel
[pierogi] / protocols / jvcprotocol.cpp
1 #include "jvcprotocol.h"
2 #include "pirrx51hardware.h"
3
4 #include "pirexception.h"
5 #include <string>
6
7 // Some global communications stuff:
8 #include <QMutex>
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
11
12 // The JVC protocol should have the following attributes:
13 // A "zero" is encoded with a 526 usec pulse, 526 usec space.
14 // A "one" is encoded with a 526 usec pulse, and 3*526 (1578) usec space.
15 // The header is a 8400 usec pulse, 4200 usec space.
16 // Commands end with a trailing 526 usec pulse.
17 // Commands are repeated by re-sending entire command without the header.
18 // Repeats are broadcast every 60000 usec.
19 // The carrier frequency is 38 kHz, duty cycle is 1/3.
20
21 JVCProtocol::JVCProtocol(
22   QObject *guiObject,
23   unsigned int index)
24   : SpaceProtocol(
25       guiObject, index,
26       526, 526,
27       526, 1578,
28       8400, 4200,
29       526,
30       60000, true)
31 {
32   setCarrierFrequency(38000);
33 //  setDutyCycle(33);
34 }
35
36
37 void JVCProtocol::startSendingCommand(
38   unsigned int threadableID,
39   PIRKeyName command)
40 {
41   // Exceptions here are problematic; I'll try to weed them out by putting the
42   // whole thing in a try/catch block:
43   try
44   {
45     // First, check if we are meant to be the recipient of this command:
46     if (threadableID != id) return;
47
48     clearRepeatFlag();
49
50     KeycodeCollection::const_iterator i = keycodes.find(command);
51
52     // Do we even have this key defined?
53     if (i == keycodes.end())
54     {
55       QMutexLocker cifLocker(&commandIFMutex);
56       commandInFlight = false;
57       return;
58 //      std::string s = "Tried to send a non-existent command.\n";
59 //      throw PIRException(s);
60     }
61
62     // construct the device:
63     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
64
65     int repeatCount = 0;
66     int commandDuration = 0;
67     while (repeatCount < MAX_REPEAT_COUNT)
68     {
69       // If we are currently repeating, and have a special "repeat signal",
70       // use that signal.  Otherwise, generate a normal command string.
71       if (repeatCount)
72       {
73         commandDuration = generateHeadlessCommand((*i).second, rx51device);
74       }
75       else
76       {
77         commandDuration = generateStandardCommand((*i).second, rx51device);
78       }
79
80       // Now, tell the device to send the whole command:
81       rx51device.sendCommandToDevice();
82
83       // sleep until the next repetition of command:
84       sleepUntilRepeat(commandDuration);
85
86       // Check whether we've reached the minimum required number of repetitons:
87       if (repeatCount >= minimumRepetitions)
88       {
89         // Check whether we've been asked to stop:
90         if (checkRepeatFlag())
91         {
92           break;
93 /*
94           QMutexLocker cifLocker(&commandIFMutex);
95           commandInFlight = false;
96           return;
97 */
98         }
99       }
100
101       ++repeatCount;
102     }
103
104     QMutexLocker cifLocker(&commandIFMutex);
105     commandInFlight = false;
106   }
107   catch (PIRException e)
108   {
109     // inform the gui:
110     emit commandFailed(e.getError().c_str());
111   }
112 }
113
114
115 // JVC data is sent in reverse order, i.e., the least signficant bit is
116 // sent first.
117 int JVCProtocol::generateStandardCommand(
118   const PIRKeyBits &pkb,
119   PIRRX51Hardware &rx51device)
120 {
121   int duration = 0;
122
123   // First, the "header" pulse:
124   rx51device.addPair(headerPulse, headerSpace);
125   duration += (headerPulse + headerSpace);
126
127   // Now, push the actual data:
128   duration += pushReverseBits(preData, rx51device);
129   duration += pushReverseBits(pkb.firstCode, rx51device);
130
131   // Finally add the "trail":
132   rx51device.addSingle(trailerPulse);
133   duration += trailerPulse;
134
135   return duration;
136 }
137
138
139 int JVCProtocol::generateHeadlessCommand(
140   const PIRKeyBits &pkb,
141   PIRRX51Hardware &rx51device)
142 {
143   int duration = 0;
144
145   // Push the actual data:
146   duration += pushReverseBits(preData, rx51device);
147   duration += pushReverseBits(pkb.firstCode, rx51device);
148
149   // Finally add the "trail":
150   rx51device.addSingle(trailerPulse);
151   duration += trailerPulse;
152
153   return duration;
154 }