1 #include "rc5protocol.h"
3 #include "pirexception.h"
6 extern bool commandInFlight;
7 extern QMutex commandIFMutex;
9 RC5Protocol::RC5Protocol(
17 : PIRProtocol(guiObject, index, gSpace, iclflag),
27 void RC5Protocol::setHeaderPair(
37 void RC5Protocol::setPreData(
41 appendToBitSeq(preData, data, bits);
45 void RC5Protocol::setToggleBit(
52 void RC5Protocol::startSendingCommand(
53 unsigned int threadableID,
56 // Dumping entire method inside of try/catch, to deal with cross-thread
57 // exception handling:
60 // Check if this command is meant for us:
61 if (threadableID != id) return;
65 KeycodeCollection::const_iterator i = keycodes.find(command);
67 // Sanity check, make sure command exists first:
68 if (i == keycodes.end())
70 std::string s = "Tried to send a non-existent command.\n";
71 throw PIRException(s);
74 // Construct the object that communicates with the device driver:
75 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
78 while (repeatCount < MAX_REPEAT_COUNT)
80 int commandDuration = 0;
82 // Now, throw together an RC5 protocol command string:
84 bufferContainsPulse = false;
85 bufferContainsSpace = false;
87 // Start off the first pulse with the lead, if any:
91 bufferContainsPulse = true;
95 commandDuration += pushBits((*i).second, rx51device);
97 // Clear out the buffer, if necessary:
100 rx51device.addSingle(buffer);
101 commandDuration += buffer;
103 bufferContainsSpace = false;
104 bufferContainsPulse = false;
107 // Now, tell the device to send the whole command:
108 rx51device.sendCommandToDevice();
110 // Sleep for an amount of time. (Need to make this interruptable!)
111 sleepUntilRepeat(commandDuration);
113 // Have we satisfied the minimum number of repetitions?
114 if (repeatCount >= minimumRepetitions)
116 // Have we been told to stop yet?
117 if (checkRepeatFlag())
119 // Ok, then we can quit now:
121 QMutexLocker cifLocker(&commandIFMutex);
122 commandInFlight = false;
130 catch (PIRException e)
132 emit commandFailed(e.getError().c_str());
136 QMutexLocker cifLocker(&commandIFMutex);
137 commandInFlight = false;
141 int RC5Protocol::pushBits(
142 const CommandSequence &bits,
143 PIRRX51Hardware &rx51device)
145 int bitsDuration = 0;
147 // Rather than encoding a 0 or 1 through the timing of a pulse, RC5 encodes
148 // a bit by swapping the order of pulses and spaces. (This is called
151 CommandSequence::const_iterator i = bits.begin();
155 while (i != bits.end())
159 if (bitCount == toggleBit) // are we on a toggled bit?
161 if (keypressCount % 2) // is it time to toggle?
163 bitValue = !bitValue; // then flip the bit
169 // We've got a "1". First add a space, then a pulse.
170 if (bufferContainsSpace)
172 // Merge our space with the previous space, and send them to
174 rx51device.addSingle(buffer + biphaseSpace);
175 bitsDuration += (buffer + biphaseSpace);
177 bufferContainsSpace = false;
181 if (bufferContainsPulse)
184 rx51device.addSingle(buffer);
185 bitsDuration += buffer;
187 bufferContainsPulse = false;
190 rx51device.addSingle(biphaseSpace);
191 bitsDuration += biphaseSpace;
194 // Put a pulse into the buffer to wait.
195 buffer = biphasePulse;
196 bufferContainsPulse = true;
200 // We've got a "0". First add a pulse, then a space.
201 if (bufferContainsPulse)
203 // Merge our pulse with the previous one, and send them to the device:
204 rx51device.addSingle(buffer + biphasePulse);
205 bitsDuration += (buffer + biphasePulse);
207 bufferContainsPulse = false;
211 if (bufferContainsSpace)
213 // Flush out the buffer:
214 rx51device.addSingle(buffer);
215 bitsDuration += buffer;
217 bufferContainsSpace = false;
221 rx51device.addSingle(biphasePulse);
222 bitsDuration += biphasePulse;
225 // Put a space into the buffer to wait:
226 buffer = biphaseSpace;
227 bufferContainsSpace = true;