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 std::string s = "Tried to send a non-existent command.\n";
59 throw PIRException(s);
62 // construct the device:
63 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
66 int commandDuration = 0;
67 while (repeatCount < MAX_REPEAT_COUNT)
69 // If we are on an odd repetition, and we have a secondary keycode,
70 // we'll generate the secondary command for this key. Otherwise,
71 // we always generate a standard command.
72 if ((repeatCount % 2) && (!(i->second.thirdCode.empty())))
74 commandDuration = generateSecondaryCommand(i->second, rx51device);
78 commandDuration = generateStandardCommand(i->second, rx51device);
81 // Now, tell the device to send the whole command:
82 rx51device.sendCommandToDevice();
84 // sleep until the next repetition of command:
85 sleepUntilRepeat(commandDuration);
87 // Check whether we've reached the minimum required number of repetitons:
88 // if (repeatCount >= minimumRepetitions)
91 // Check whether we've been asked to stop:
92 if (checkRepeatFlag())
94 QMutexLocker cifLocker(&commandIFMutex);
95 commandInFlight = false;
103 catch (PIRException e)
106 emit commandFailed(e.getError().c_str());
109 QMutexLocker cifLocker(&commandIFMutex);
110 commandInFlight = false;
114 int PioneerProtocol::generateStandardCommand(
115 const PIRKeyBits &pkb,
116 PIRRX51Hardware &rx51device)
120 // First, the "header" pulse:
121 rx51device.addPair(headerPulse, headerSpace);
122 duration += (headerPulse + headerSpace);
124 // Now, the data, following standard NEC rules. (Note that we are not
125 // using the "preData" value here, most Pioneer devices require more than
126 // one address value. Therefore, I'm requiring all keys to explicitly
127 // load the address value into the "firstCode" member.)
128 duration += pushReverseBits(pkb.firstCode, rx51device);
129 duration += pushInvertedReverseBits(pkb.firstCode, rx51device);
130 duration += pushReverseBits(pkb.secondCode, rx51device);
131 duration += pushInvertedReverseBits(pkb.secondCode, rx51device);
133 // Finally add the "trail":
134 rx51device.addSingle(trailerPulse);
135 duration += trailerPulse;
141 int PioneerProtocol::generateSecondaryCommand(
142 const PIRKeyBits &pkb,
143 PIRRX51Hardware &rx51device)
147 // First, the "header" pulse:
148 rx51device.addPair(headerPulse, headerSpace);
149 duration += (headerPulse + headerSpace);
151 // Now, the data, following standard NEC rules. (The secondary command
152 // uses the third and fourth key codes.)
153 duration += pushReverseBits(pkb.thirdCode, rx51device);
154 duration += pushInvertedReverseBits(pkb.thirdCode, rx51device);
155 duration += pushReverseBits(pkb.fourthCode, rx51device);
156 duration += pushInvertedReverseBits(pkb.fourthCode, rx51device);
158 // Finally add the "trail":
159 rx51device.addSingle(trailerPulse);
160 duration += trailerPulse;