1 #include "pirprotocol.h"
9 #include "pirexception.h"
11 // A flag for communicating with the main thread:
12 extern bool stopRepeatingFlag;
13 extern QMutex stopRepeatingMutex;
15 // Total of all running commands
16 extern bool commandInFlight;
17 extern QMutex commandIFMutex;
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.
24 PIRProtocol::PIRProtocol(
29 : carrierFrequency(38000),
31 isConstantLength(iclflag),
33 minimumRepetitions(0),
36 qRegisterMetaType<PIRKeyName>("PIRKeyName");
40 SIGNAL(buttonPressed(unsigned int, PIRKeyName)),
42 SLOT(startSendingCommand(unsigned int, PIRKeyName)),
43 Qt::QueuedConnection);
47 SIGNAL(commandFailed(const char *)),
49 SLOT(receivedExternalWarning(const char *)),
50 Qt::QueuedConnection);
54 void PIRProtocol::addKey(
56 unsigned long command,
59 // First, if key already exists, clear it out:
60 KeycodeCollection::iterator i = keycodes.find(key);
61 if (i != keycodes.end())
66 appendToBitSeq(keycodes[key], command, size);
70 void PIRProtocol::addSIRCKey(
72 unsigned int addressData,
74 unsigned int commandData)
76 // First, if key already exists, clear it out:
77 KeycodeCollection::iterator i = keycodes.find(key);
78 if (i != keycodes.end())
83 // First, append the address data:
84 appendToBitSeq(keycodes[key], addressData, size);
86 // Next, the command data. The size is always 7 bits:
87 appendToBitSeq(keycodes[key], commandData, 7);
91 void PIRProtocol::addSIRC20Key(
93 unsigned int secondaryAddressData,
94 unsigned int primaryAddressData,
95 unsigned int commandData)
97 // First, if key already exists, clear it out:
98 KeycodeCollection::iterator i = keycodes.find(key);
99 if (i != keycodes.end())
104 // First, append the secondary address data:
105 appendToBitSeq(keycodes[key], secondaryAddressData, 8);
107 // Next, the primary address data:
108 appendToBitSeq(keycodes[key], primaryAddressData, 5);
110 // Next, the command data. The size is always 7 bits:
111 appendToBitSeq(keycodes[key], commandData, 7);
115 void PIRProtocol::addSharpKey(
117 unsigned int addressData,
118 unsigned int commandData)
120 // First, if key already exists, clear it out:
121 KeycodeCollection::iterator i = keycodes.find(key);
122 if (i != keycodes.end())
127 // Sharp commands are all 5 bit address, 8 bit command:
128 appendToBitSeq(keycodes[key], addressData, 5);
129 appendToBitSeq(keycodes[key], commandData, 8);
133 void PIRProtocol::setCarrierFrequency(
136 carrierFrequency = freq;
140 void PIRProtocol::setDutyCycle(
147 void PIRProtocol::setMinimumRepetitions(
150 minimumRepetitions = minrep;
154 void PIRProtocol::setPreData(
158 // If the container is not empty, first clear it out:
159 if (!preData.empty())
164 appendToBitSeq(preData, data, bits);
168 void PIRProtocol::setPostData(
172 // If the container is not empty, first clear it out:
173 if (!postData.empty())
178 appendToBitSeq(postData, data, bits);
182 bool PIRProtocol::isCommandSupported(
185 return (keycodes.find(command) != keycodes.end());
189 void PIRProtocol::appendToBitSeq(
190 CommandSequence &sequence,
196 // This is bad, but just return silently for now...
200 // For each bit in the char, append a 1 or a 0 into the sequence.
201 // Starting with the largest bit, move forward one bit at a time:
202 unsigned int currentBit = 1 << (size - 1);
206 if (bits & currentBit)
208 sequence.push_back(1);
212 sequence.push_back(0);
215 currentBit = currentBit >> 1;
217 while (currentBit > 0);
221 void PIRProtocol::clearRepeatFlag()
223 QMutexLocker locker(&stopRepeatingMutex);
224 stopRepeatingFlag = false;
228 bool PIRProtocol::checkRepeatFlag()
230 QMutexLocker locker(&stopRepeatingMutex);
231 return stopRepeatingFlag;
235 // Note that the following routine blindly sleeps for the amount of time
236 // specified by the LIRC config file. The extra overhead of processing
237 // each command will mean that repeated commands will overshoot the config
238 // time by some amount. We could improve accuracy by waiting a little less
239 // than the specified time, if we could get a good handle on how long the
240 // overhead is delaying the command...
241 #define PIEROGI_OVERHEAD_HACK 13260
243 void PIRProtocol::sleepUntilRepeat(
248 // If the LIRC config file specifies the flag "CONST_LENGTH", that means
249 // the "gap" value is the exact amount of time to wait between kicking off
250 // each command. If not, then the "gap" needs to be added on to the total
251 // time of the previous command to see how long to sleep.
253 if (isConstantLength)
255 microseconds = (gap - commandDuration) - PIEROGI_OVERHEAD_HACK;
259 microseconds = gap - PIEROGI_OVERHEAD_HACK;
263 // Don't even bother sleeping if there's only a few microseconds:
264 if (microseconds < 1000)
269 // For now, I'm going to enforce a minimum sleep of 10 ms, so that we
270 // don't get runaway commands:
271 if (microseconds < 10000)
273 microseconds = 10000;
277 sleeptime.tv_sec = 0;
278 sleeptime.tv_nsec = microseconds * 1000;
280 timespec remainingtime;
282 if (nanosleep(&sleeptime, &remainingtime) == -1)
284 std::stringstream ss;
285 ss << "Problem while sleeping.\n";
286 ss << "Trying to sleep for: " << microseconds << "\n";
287 ss << "Nanosleep returned error: " << strerror(errno) << "\n";
288 throw PIRException(ss.str());