1 #include "rc6protocol.h"
3 #include "pirexception.h"
6 extern bool commandInFlight;
7 extern QMutex commandIFMutex;
9 // These defines might need to be turned into variables, for odd devices.
10 #define HEADER_PULSE 2666
11 #define HEADER_SPACE 889
12 #define TRAILER_PULSE 889
13 #define TRAILER_SPACE 889
15 // I'm requiring standard RC6 initialization to include the 8-bit control
17 RC6Protocol::RC6Protocol(
20 unsigned int eightBitControl)
21 : PIRProtocol(guiObject, index, 108000, true),
26 setCarrierFrequency(36000);
27 setPreData(eightBitControl, 8);
31 void RC6Protocol::startSendingCommand(
32 unsigned int threadableID,
37 // Is this command meant for us?
38 if (threadableID != id) return;
42 KeycodeCollection::const_iterator i = keycodes.find(command);
45 if (i == keycodes.end())
47 std::string s = "Tried to send a non-existent command.\n";
48 throw PIRException(s);
51 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
54 while (repeatCount < MAX_REPEAT_COUNT)
58 // First, construct the "Header" segment of the pulse train. For now,
59 // I'm only supporting the "consumer electronics mode" of RC6; this code
60 // must be changed if we want to support more than that!
62 // The header involves:
63 // a) a "lead" of 2666 us pulse, 889 us space;
64 // b) a "start bit", value 1 (so 444 us pulse, 444 us space)
65 // c) three control bits, always set to 0 (so 444 us space,
67 // d) the double-sized "trailer" bit, toggled on each keypress (so
68 // either 889 pulse 889 space, or 889 space 889 pulse)
70 rx51device.addSingle(HEADER_PULSE); // lead pulse
71 duration += HEADER_PULSE;
72 rx51device.addSingle(HEADER_SPACE); // lead space
73 duration += HEADER_SPACE;
74 rx51device.addSingle(biphaseUnit); // start bit pulse
75 duration += biphaseUnit;
77 // start bit space + control bit 1 space:
78 rx51device.addSingle(2 * biphaseUnit);
79 duration += 2 * biphaseUnit;
80 rx51device.addSingle(biphaseUnit); // bit 1 pulse;
81 duration += biphaseUnit;
82 rx51device.addSingle(biphaseUnit); // bit 2 space;
83 duration += biphaseUnit;
84 rx51device.addSingle(biphaseUnit); // bit 2 pulse;
85 duration += biphaseUnit;
86 rx51device.addSingle(biphaseUnit); // bit 3 space;
87 duration += biphaseUnit;
89 // Next, need to check whether we should toggle or not:
90 if (keypressCount % 2)
92 // bit 3 pulse plus long trailer bit pulse:
93 rx51device.addSingle(3 * biphaseUnit);
94 duration += 3 * biphaseUnit;
96 // load the trailer bit space onto the buffer:
97 buffer = 2 * biphaseUnit;
98 bufferContainsSpace = true;
99 bufferContainsPulse = false;
103 rx51device.addSingle(biphaseUnit); // bit three pulse
104 duration += biphaseUnit;
105 rx51device.addSingle(2 * biphaseUnit); // trailer bit space
106 duration += 2 * biphaseUnit;
108 // load the trailer bit pulse onto the buffer:
109 buffer = 2 * biphaseUnit;
110 bufferContainsPulse = true;
111 bufferContainsSpace = false;
114 // Now, we can start the normal buffering process:
116 // push any pre-data onto the device:
117 duration += pushBits(preData, rx51device);
119 // push the actual command:
120 duration += pushBits((*i).second, rx51device);
122 // Flush out the buffer, if necessary:
125 rx51device.addSingle(buffer);
130 // Actually send out the command:
131 rx51device.sendCommandToDevice();
133 // Sleep for an amount of time. (RC6 demands an addtional 6 unit space
134 // at the end of any command...)
135 sleepUntilRepeat(duration + 6 * biphaseUnit);
137 // Have we been told to stop yet?
138 if (checkRepeatFlag())
140 // Yes, we can now quit repeating:
142 QMutexLocker ciflocker(&commandIFMutex);
143 commandInFlight = false;
148 catch (PIRException e)
150 emit commandFailed(e.getError().c_str());
154 QMutexLocker cifLocker(&commandIFMutex);
155 commandInFlight = false;
159 int RC6Protocol::pushBits(
160 const CommandSequence &bits,
161 PIRRX51Hardware &rx51device)
163 int bitsDuration = 0;
165 CommandSequence::const_iterator i = bits.begin();
168 while (i != bits.end())
172 // In RC6, a "0" is represented by a space followed by a pulse,
173 // and a "1" is represented by a pulse followed by a space.
176 // This is a 1, so add a pulse, then a space.
178 if (bufferContainsPulse)
180 rx51device.addSingle(buffer + biphaseUnit);
181 bitsDuration += (buffer + biphaseUnit);
183 bufferContainsPulse = false;
187 if (bufferContainsSpace)
190 rx51device.addSingle(buffer);
191 bitsDuration += buffer;
193 bufferContainsSpace = false;
195 // Now, add the pulse:
196 rx51device.addSingle(biphaseUnit);
197 bitsDuration += biphaseUnit;
200 // Next, push a space onto the buffer:
201 buffer = biphaseUnit;
202 bufferContainsSpace = true;
206 // This is a 0, so add a space, then a pulse.
207 if (bufferContainsSpace)
209 // Merge this space and the previous one, and send to device:
210 rx51device.addSingle(buffer + biphaseUnit);
211 bitsDuration += (buffer + biphaseUnit);
213 bufferContainsSpace = false;
217 if (bufferContainsPulse)
219 // Flush out the buffer:
220 rx51device.addSingle(buffer);
221 bitsDuration += buffer;
223 bufferContainsPulse = false;
226 // push a space onto the device:
227 rx51device.addSingle(biphaseUnit);
228 bitsDuration += biphaseUnit;
231 // Put a pulse into the buffer to wait:
232 buffer = biphaseUnit;
233 bufferContainsPulse = true;