1 #include "necxprotocol.h"
3 #include "pirrx51hardware.h"
5 #include "pirexception.h"
7 // Some global communications stuff:
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
12 // The NECX protocol is a slight variation of the NEC protocol. It features
13 // a slightly different header and a slightly different repeat mechanism.
14 // Most of them use the "extended" address form, so I'll just assume that all
15 // of them do. (It won't hurt anything.)
16 // Otherwise it is nearly identical:
17 // A "zero" is encoded with a 560 usec pulse, 560 usec space.
18 // A "one" is encoded with a 560 usec pulse, and 3*560 (1680) usec space.
19 // The header is a 4500 usec pulse, 4500 usec space.
20 // Commands end with a trailing 560 usec pulse.
21 // A repeat block (if used) is a 4500 usec pulse, 4500 usec space, then a 1
22 // (560 usec pulse, 1680 usec space), then the trailing pulse.
23 // Each command runs for 110000 usec before another can be executed.
24 // The carrier frequency is 38 kHz.
26 NECXProtocol::NECXProtocol(
42 void NECXProtocol::startSendingCommand(
43 unsigned int threadableID,
46 // Exceptions here are problematic; I'll try to weed them out by putting the
47 // whole thing in a try/catch block:
50 // First, check if we are meant to be the recipient of this command:
51 if (threadableID != id) return;
55 KeycodeCollection::const_iterator i = keycodes.find(command);
57 // Do we even have this key defined?
58 if (i == keycodes.end())
60 QMutexLocker cifLocker(&commandIFMutex);
61 commandInFlight = false;
63 // std::string s = "Tried to send a non-existent command.\n";
64 // throw PIRException(s);
67 // construct the device:
68 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
71 int commandDuration = 0;
72 while (repeatCount < MAX_REPEAT_COUNT)
74 // If we are currently repeating, and have a special "repeat signal",
75 // use that signal. Otherwise, generate a normal command string.
76 if (isShortRepeat && repeatCount)
78 commandDuration = generateRepeatCommand(rx51device);
82 commandDuration = generateStandardCommand((*i).second, rx51device);
85 // Now, tell the device to send the whole command:
86 rx51device.sendCommandToDevice();
88 // sleep until the next repetition of command:
89 sleepUntilRepeat(commandDuration);
91 // Check whether we've reached the minimum required number of repetitons:
92 if (repeatCount >= minimumRepetitions)
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 NECXProtocol::generateStandardCommand(
121 const PIRKeyBits &pkb,
122 PIRRX51Hardware &rx51device)
126 // First, the "header" pulse:
127 rx51device.addPair(headerPulse, headerSpace);
128 duration += (headerPulse + headerSpace);
130 // In NECX, the address is 16 bits, and is only sent once. The command
131 // portion is 8 bits, and an inverted copy is sent.
132 // - "preData" should contain 16-bit value
133 // - "bits" should contain 8-bit value
134 duration += pushReverseBits(preData, rx51device);
135 duration += pushReverseBits(pkb.firstCode, rx51device);
136 duration += pushInvertedReverseBits(pkb.firstCode, rx51device);
138 // Finally add the "trail":
139 rx51device.addSingle(trailerPulse);
140 duration += trailerPulse;
146 int NECXProtocol::generateRepeatCommand(
147 PIRRX51Hardware &rx51device)
151 // Start with the header:
152 rx51device.addPair(headerPulse, headerSpace);
153 duration += (headerPulse + headerSpace);
156 rx51device.addPair(onePulse, oneSpace);
157 duration += (onePulse + oneSpace);
160 rx51device.addSingle(trailerPulse);
161 duration += trailerPulse;