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 std::string s = "Tried to send a non-existent command.\n";
50 throw PIRException(s);
53 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
57 while (repeatCount < MAX_REPEAT_COUNT)
59 // First, construct the "Header" segment of the pulse train. For now,
60 // I'm only supporting the "consumer electronics mode" of RC6; this code
61 // must be changed if we want to support more than that!
63 // The header involves:
64 // a) a "lead" of 2666 us pulse, 889 us space;
65 // b) a "start bit", value 1 (so 444 us pulse, 444 us space)
66 // c) three control bits, always set to 0 (so 444 us space,
68 // d) the double-sized "trailer" bit, toggled on each keypress (so
69 // either 889 pulse 889 space, or 889 space 889 pulse)
71 rx51device.addSingle(HEADER_PULSE); // lead pulse
72 duration += HEADER_PULSE;
73 rx51device.addSingle(HEADER_SPACE); // lead space
74 duration += HEADER_SPACE;
75 rx51device.addSingle(biphaseUnit); // start bit pulse
76 duration += biphaseUnit;
78 // start bit space + control bit 1 space:
79 rx51device.addSingle(2 * biphaseUnit);
80 duration += 2 * biphaseUnit;
81 rx51device.addSingle(biphaseUnit); // bit 1 pulse;
82 duration += biphaseUnit;
83 rx51device.addSingle(biphaseUnit); // bit 2 space;
84 duration += biphaseUnit;
85 rx51device.addSingle(biphaseUnit); // bit 2 pulse;
86 duration += biphaseUnit;
87 rx51device.addSingle(biphaseUnit); // bit 3 space;
88 duration += biphaseUnit;
90 // Next, need to check whether we should toggle or not:
91 if (keypressCount % 2)
93 // bit 3 pulse plus long trailer bit pulse:
94 rx51device.addSingle(3 * biphaseUnit);
95 duration += 3 * biphaseUnit;
97 // load the trailer bit space onto the buffer:
98 buffer = 2 * biphaseUnit;
99 bufferContainsSpace = true;
100 bufferContainsPulse = false;
104 rx51device.addSingle(biphaseUnit); // bit three pulse
105 duration += biphaseUnit;
106 rx51device.addSingle(2 * biphaseUnit); // trailer bit space
107 duration += 2 * biphaseUnit;
109 // load the trailer bit pulse onto the buffer:
110 buffer = 2 * biphaseUnit;
111 bufferContainsPulse = true;
112 bufferContainsSpace = false;
115 // Now, we can start the normal buffering process:
117 // push any pre-data onto the device:
118 duration += pushBits(preData, rx51device);
120 // push the actual command:
121 duration += pushBits((*i).second.firstCode, rx51device);
123 // Flush out the buffer, if necessary:
126 rx51device.addSingle(buffer);
131 // Actually send out the command:
132 rx51device.sendCommandToDevice();
134 // Sleep for an amount of time. (RC6 demands an addtional 6 unit space
135 // at the end of any command...)
136 sleepUntilRepeat(duration + 6 * biphaseUnit);
138 // Have we been told to stop yet?
139 if (checkRepeatFlag())
141 // Yes, we can now quit repeating:
143 QMutexLocker ciflocker(&commandIFMutex);
144 commandInFlight = false;
149 catch (PIRException e)
151 emit commandFailed(e.getError().c_str());
155 QMutexLocker cifLocker(&commandIFMutex);
156 commandInFlight = false;
160 int RC6Protocol::pushBits(
161 const CommandSequence &bits,
162 PIRRX51Hardware &rx51device)
164 int bitsDuration = 0;
166 CommandSequence::const_iterator i = bits.begin();
169 while (i != bits.end())
173 // In RC6, a "0" is represented by a space followed by a pulse,
174 // and a "1" is represented by a pulse followed by a space.
177 // This is a 1, so add a pulse, then a space.
179 if (bufferContainsPulse)
181 rx51device.addSingle(buffer + biphaseUnit);
182 bitsDuration += (buffer + biphaseUnit);
184 bufferContainsPulse = false;
188 if (bufferContainsSpace)
191 rx51device.addSingle(buffer);
192 bitsDuration += buffer;
194 bufferContainsSpace = false;
196 // Now, add the pulse:
197 rx51device.addSingle(biphaseUnit);
198 bitsDuration += biphaseUnit;
201 // Next, push a space onto the buffer:
202 buffer = biphaseUnit;
203 bufferContainsSpace = true;
207 // This is a 0, so add a space, then a pulse.
208 if (bufferContainsSpace)
210 // Merge this space and the previous one, and send to device:
211 rx51device.addSingle(buffer + biphaseUnit);
212 bitsDuration += (buffer + biphaseUnit);
214 bufferContainsSpace = false;
218 if (bufferContainsPulse)
220 // Flush out the buffer:
221 rx51device.addSingle(buffer);
222 bitsDuration += buffer;
224 bufferContainsPulse = false;
227 // push a space onto the device:
228 rx51device.addSingle(biphaseUnit);
229 bitsDuration += biphaseUnit;
232 // Put a pulse into the buffer to wait:
233 buffer = biphaseUnit;
234 bufferContainsPulse = true;