1 #include "rc6protocol.h"
3 #include "pirrx51hardware.h"
5 #include "pirexception.h"
8 extern bool commandInFlight;
9 extern QMutex commandIFMutex;
11 // These defines might need to be turned into variables, for odd devices.
12 #define HEADER_PULSE 2666
13 #define HEADER_SPACE 889
14 #define TRAILER_PULSE 889
15 #define TRAILER_SPACE 889
17 // I'm requiring standard RC6 initialization to include the 8-bit control
19 RC6Protocol::RC6Protocol(
22 unsigned int eightBitControl)
23 : PIRProtocol(guiObject, index, 108000, true),
28 setCarrierFrequency(36000);
29 setPreData(eightBitControl, 8);
33 void RC6Protocol::startSendingCommand(
34 unsigned int threadableID,
39 // Is this command meant for us?
40 if (threadableID != id) return;
44 KeycodeCollection::const_iterator i = keycodes.find(command);
47 if (i == keycodes.end())
49 QMutexLocker cifLocker(&commandIFMutex);
50 commandInFlight = false;
52 // std::string s = "Tried to send a non-existent command.\n";
53 // throw PIRException(s);
56 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
60 while (repeatCount < MAX_REPEAT_COUNT)
62 // First, construct the "Header" segment of the pulse train. For now,
63 // I'm only supporting the "consumer electronics mode" of RC6; this code
64 // must be changed if we want to support more than that!
66 // The header involves:
67 // a) a "lead" of 2666 us pulse, 889 us space;
68 // b) a "start bit", value 1 (so 444 us pulse, 444 us space)
69 // c) three control bits, always set to 0 (so 444 us space,
71 // d) the double-sized "trailer" bit, toggled on each keypress (so
72 // either 889 pulse 889 space, or 889 space 889 pulse)
74 rx51device.addSingle(HEADER_PULSE); // lead pulse
75 duration += HEADER_PULSE;
76 rx51device.addSingle(HEADER_SPACE); // lead space
77 duration += HEADER_SPACE;
78 rx51device.addSingle(biphaseUnit); // start bit pulse
79 duration += biphaseUnit;
81 // start bit space + control bit 1 space:
82 rx51device.addSingle(2 * biphaseUnit);
83 duration += 2 * biphaseUnit;
84 rx51device.addSingle(biphaseUnit); // bit 1 pulse;
85 duration += biphaseUnit;
86 rx51device.addSingle(biphaseUnit); // bit 2 space;
87 duration += biphaseUnit;
88 rx51device.addSingle(biphaseUnit); // bit 2 pulse;
89 duration += biphaseUnit;
90 rx51device.addSingle(biphaseUnit); // bit 3 space;
91 duration += biphaseUnit;
93 // Next, need to check whether we should toggle or not:
94 if (keypressCount % 2)
96 // bit 3 pulse plus long trailer bit pulse:
97 rx51device.addSingle(3 * biphaseUnit);
98 duration += 3 * biphaseUnit;
100 // load the trailer bit space onto the buffer:
101 buffer = 2 * biphaseUnit;
102 bufferContainsSpace = true;
103 bufferContainsPulse = false;
107 rx51device.addSingle(biphaseUnit); // bit three pulse
108 duration += biphaseUnit;
109 rx51device.addSingle(2 * biphaseUnit); // trailer bit space
110 duration += 2 * biphaseUnit;
112 // load the trailer bit pulse onto the buffer:
113 buffer = 2 * biphaseUnit;
114 bufferContainsPulse = true;
115 bufferContainsSpace = false;
118 // Now, we can start the normal buffering process:
120 // push any pre-data onto the device:
121 duration += pushBits(preData, rx51device);
123 // push the actual command:
124 duration += pushBits((*i).second.firstCode, rx51device);
126 // Flush out the buffer, if necessary:
129 rx51device.addSingle(buffer);
134 // Actually send out the command:
135 rx51device.sendCommandToDevice();
137 // Sleep for an amount of time. (RC6 demands an addtional 6 unit space
138 // at the end of any command...)
139 sleepUntilRepeat(duration + 6 * biphaseUnit);
141 // Have we been told to stop yet?
142 if (checkRepeatFlag())
146 // Yes, we can now quit repeating:
148 QMutexLocker ciflocker(&commandIFMutex);
149 commandInFlight = false;
156 QMutexLocker cifLocker(&commandIFMutex);
157 commandInFlight = false;
159 catch (PIRException e)
161 emit commandFailed(e.getError().c_str());
166 int RC6Protocol::pushBits(
167 const CommandSequence &bits,
168 PIRRX51Hardware &rx51device)
170 int bitsDuration = 0;
172 CommandSequence::const_iterator i = bits.begin();
175 while (i != bits.end())
179 // In RC6, a "0" is represented by a space followed by a pulse,
180 // and a "1" is represented by a pulse followed by a space.
183 // This is a 1, so add a pulse, then a space.
185 if (bufferContainsPulse)
187 rx51device.addSingle(buffer + biphaseUnit);
188 bitsDuration += (buffer + biphaseUnit);
190 bufferContainsPulse = false;
194 if (bufferContainsSpace)
197 rx51device.addSingle(buffer);
198 bitsDuration += buffer;
200 bufferContainsSpace = false;
202 // Now, add the pulse:
203 rx51device.addSingle(biphaseUnit);
204 bitsDuration += biphaseUnit;
207 // Next, push a space onto the buffer:
208 buffer = biphaseUnit;
209 bufferContainsSpace = true;
213 // This is a 0, so add a space, then a pulse.
214 if (bufferContainsSpace)
216 // Merge this space and the previous one, and send to device:
217 rx51device.addSingle(buffer + biphaseUnit);
218 bitsDuration += (buffer + biphaseUnit);
220 bufferContainsSpace = false;
224 if (bufferContainsPulse)
226 // Flush out the buffer:
227 rx51device.addSingle(buffer);
228 bitsDuration += buffer;
230 bufferContainsPulse = false;
233 // push a space onto the device:
234 rx51device.addSingle(biphaseUnit);
235 bitsDuration += biphaseUnit;
238 // Put a pulse into the buffer to wait:
239 buffer = biphaseUnit;
240 bufferContainsPulse = true;