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);
55 while (repeatCount < MAX_REPEAT_COUNT)
57 // First, construct the "Header" segment of the pulse train. For now,
58 // I'm only supporting the "consumer electronics mode" of RC6; this code
59 // must be changed if we want to support more than that!
61 // The header involves:
62 // a) a "lead" of 2666 us pulse, 889 us space;
63 // b) a "start bit", value 1 (so 444 us pulse, 444 us space)
64 // c) three control bits, always set to 0 (so 444 us space,
66 // d) the double-sized "trailer" bit, toggled on each keypress (so
67 // either 889 pulse 889 space, or 889 space 889 pulse)
69 rx51device.addSingle(HEADER_PULSE); // lead pulse
70 duration += HEADER_PULSE;
71 rx51device.addSingle(HEADER_SPACE); // lead space
72 duration += HEADER_SPACE;
73 rx51device.addSingle(biphaseUnit); // start bit pulse
74 duration += biphaseUnit;
76 // start bit space + control bit 1 space:
77 rx51device.addSingle(2 * biphaseUnit);
78 duration += 2 * biphaseUnit;
79 rx51device.addSingle(biphaseUnit); // bit 1 pulse;
80 duration += biphaseUnit;
81 rx51device.addSingle(biphaseUnit); // bit 2 space;
82 duration += biphaseUnit;
83 rx51device.addSingle(biphaseUnit); // bit 2 pulse;
84 duration += biphaseUnit;
85 rx51device.addSingle(biphaseUnit); // bit 3 space;
86 duration += biphaseUnit;
88 // Next, need to check whether we should toggle or not:
89 if (keypressCount % 2)
91 // bit 3 pulse plus long trailer bit pulse:
92 rx51device.addSingle(3 * biphaseUnit);
93 duration += 3 * biphaseUnit;
95 // load the trailer bit space onto the buffer:
96 buffer = 2 * biphaseUnit;
97 bufferContainsSpace = true;
98 bufferContainsPulse = false;
102 rx51device.addSingle(biphaseUnit); // bit three pulse
103 duration += biphaseUnit;
104 rx51device.addSingle(2 * biphaseUnit); // trailer bit space
105 duration += 2 * biphaseUnit;
107 // load the trailer bit pulse onto the buffer:
108 buffer = 2 * biphaseUnit;
109 bufferContainsPulse = true;
110 bufferContainsSpace = false;
113 // Now, we can start the normal buffering process:
115 // push any pre-data onto the device:
116 duration += pushBits(preData, rx51device);
118 // push the actual command:
119 duration += pushBits((*i).second, rx51device);
121 // Flush out the buffer, if necessary:
124 rx51device.addSingle(buffer);
129 // Actually send out the command:
130 rx51device.sendCommandToDevice();
132 // Sleep for an amount of time. (RC6 demands an addtional 6 unit space
133 // at the end of any command...)
134 sleepUntilRepeat(duration + 6 * biphaseUnit);
136 // Have we been told to stop yet?
137 if (checkRepeatFlag())
139 // Yes, we can now quit repeating:
141 QMutexLocker ciflocker(&commandIFMutex);
142 commandInFlight = false;
147 catch (PIRException e)
149 emit commandFailed(e.getError().c_str());
153 QMutexLocker cifLocker(&commandIFMutex);
154 commandInFlight = false;
158 int RC6Protocol::pushBits(
159 const CommandSequence &bits,
160 PIRRX51Hardware &rx51device)
162 int bitsDuration = 0;
164 CommandSequence::const_iterator i = bits.begin();
167 while (i != bits.end())
171 // In RC6, a "0" is represented by a space followed by a pulse,
172 // and a "1" is represented by a pulse followed by a space.
175 // This is a 1, so add a pulse, then a space.
177 if (bufferContainsPulse)
179 rx51device.addSingle(buffer + biphaseUnit);
180 bitsDuration += (buffer + biphaseUnit);
182 bufferContainsPulse = false;
186 if (bufferContainsSpace)
189 rx51device.addSingle(buffer);
190 bitsDuration += buffer;
192 bufferContainsSpace = false;
194 // Now, add the pulse:
195 rx51device.addSingle(biphaseUnit);
196 bitsDuration += biphaseUnit;
199 // Next, push a space onto the buffer:
200 buffer = biphaseUnit;
201 bufferContainsSpace = true;
205 // This is a 0, so add a space, then a pulse.
206 if (bufferContainsSpace)
208 // Merge this space and the previous one, and send to device:
209 rx51device.addSingle(buffer + biphaseUnit);
210 bitsDuration += (buffer + biphaseUnit);
212 bufferContainsSpace = false;
216 if (bufferContainsPulse)
218 // Flush out the buffer:
219 rx51device.addSingle(buffer);
220 bitsDuration += buffer;
222 bufferContainsPulse = false;
225 // push a space onto the device:
226 rx51device.addSingle(biphaseUnit);
227 bitsDuration += biphaseUnit;
230 // Put a pulse into the buffer to wait:
231 buffer = biphaseUnit;
232 bufferContainsPulse = true;