1 #include "pioneerprotocol.h"
3 #include "pirrx51hardware.h"
5 #include "pirexception.h"
9 // Some global communications stuff:
11 extern bool commandInFlight;
12 extern QMutex commandIFMutex;
14 // Pioneer's protocol seems almost the same as standard NEC protocol, but
15 // a few details are slightly different. (Can't seem to find exact details.)
16 // A "zero" is encoded with a 530 usec pulse, 530 usec space.
17 // A "one" is encoded with a 530 usec pulse, and 3*530 (1590) usec space.
18 // The header is a 8500 usec pulse, 4250 usec space.
19 // Commands end with a trailing 530 usec pulse.
20 // Commands are repeated by re-sending the entire pulse train.
21 // Each command is separated by 25000 usec.
22 // The carrier frequency is probably 40 kHz, duty cycle probably 50%.
24 PioneerProtocol::PioneerProtocol(
35 setCarrierFrequency(40000);
40 void PioneerProtocol::startSendingCommand(
41 unsigned int threadableID,
44 // Exceptions here are problematic; I'll try to weed them out by putting the
45 // whole thing in a try/catch block:
48 // First, check if we are meant to be the recipient of this command:
49 if (threadableID != id) return;
53 KeycodeCollection::const_iterator i = keycodes.find(command);
55 // Do we even have this key defined?
56 if (i == keycodes.end())
58 QMutexLocker cifLocker(&commandIFMutex);
59 commandInFlight = false;
61 // std::string s = "Tried to send a non-existent command.\n";
62 // throw PIRException(s);
65 // construct the device:
66 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
69 int commandDuration = 0;
70 while (repeatCount < MAX_REPEAT_COUNT)
72 // If we are on an odd repetition, and we have a secondary keycode,
73 // we'll generate the secondary command for this key. Otherwise,
74 // we always generate a standard command.
75 if ((repeatCount % 2) && (!(i->second.thirdCode.empty())))
77 commandDuration = generateSecondaryCommand(i->second, rx51device);
81 commandDuration = generateStandardCommand(i->second, rx51device);
84 // Now, tell the device to send the whole command:
85 rx51device.sendCommandToDevice();
87 // sleep until the next repetition of command:
88 sleepUntilRepeat(commandDuration);
90 // Check whether we've reached the minimum required number of repetitons:
91 // if (repeatCount >= minimumRepetitions)
92 // if (repeatCount >= 3)
94 // Check whether we've been asked to stop:
95 if (checkRepeatFlag())
99 QMutexLocker cifLocker(&commandIFMutex);
100 commandInFlight = false;
109 QMutexLocker cifLocker(&commandIFMutex);
110 commandInFlight = false;
112 catch (PIRException e)
115 emit commandFailed(e.getError().c_str());
120 int PioneerProtocol::generateStandardCommand(
121 const PIRKeyBits &pkb,
122 PIRRX51Hardware &rx51device)
126 // First, the "header" pulse:
127 rx51device.addPair(headerPulse, headerSpace);
128 duration += (headerPulse + headerSpace);
130 // Now, the data, following standard NEC rules. (Note that we are not
131 // using the "preData" value here, most Pioneer devices require more than
132 // one address value. Therefore, I'm requiring all keys to explicitly
133 // load the address value into the "firstCode" member.)
134 duration += pushReverseBits(pkb.firstCode, rx51device);
135 duration += pushInvertedReverseBits(pkb.firstCode, rx51device);
136 duration += pushReverseBits(pkb.secondCode, rx51device);
137 duration += pushInvertedReverseBits(pkb.secondCode, rx51device);
139 // Finally add the "trail":
140 rx51device.addSingle(trailerPulse);
141 duration += trailerPulse;
147 int PioneerProtocol::generateSecondaryCommand(
148 const PIRKeyBits &pkb,
149 PIRRX51Hardware &rx51device)
153 // First, the "header" pulse:
154 rx51device.addPair(headerPulse, headerSpace);
155 duration += (headerPulse + headerSpace);
157 // Now, the data, following standard NEC rules. (The secondary command
158 // uses the third and fourth key codes.)
159 duration += pushReverseBits(pkb.thirdCode, rx51device);
160 duration += pushInvertedReverseBits(pkb.thirdCode, rx51device);
161 duration += pushReverseBits(pkb.fourthCode, rx51device);
162 duration += pushInvertedReverseBits(pkb.fourthCode, rx51device);
164 // Finally add the "trail":
165 rx51device.addSingle(trailerPulse);
166 duration += trailerPulse;