1 #include "dishprotocol.h"
3 #include "pirrx51hardware.h"
5 #include "pirexception.h"
7 // Some global communications stuff:
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
12 // Dish Network, or now just "Dish", has a unique protocol. It uses "space"
13 // encoding, but otherwise is unlike just about anything else out there.
14 // Here's what I've got on it:
15 // A "zero" is encoded with a 400 usec pulse, 2800 usec space.
16 // A "one" is encoded with a 400 usec pulse, 1600 usec space.
17 // The header is a 400 usec pulse, 6000 usec space.
18 // Commands end with a trailing 400 usec pulse.
19 // Commands are repeated without the header (or, if you like, you can consider
20 // the trailing pulse to be the header for the next repetition).
21 // There is a 6000 usec gap between repetitions.
22 // The carrier frequency is apparently 57600 kHz, or thereabouts.
23 // The duty cycle is 1/3.
25 DishProtocol::DishProtocol(
36 setCarrierFrequency(57600);
41 void DishProtocol::startSendingCommand(
42 unsigned int threadableID,
45 // Exceptions here are problematic; I'll try to weed them out by putting the
46 // whole thing in a try/catch block:
49 // First, check if we are meant to be the recipient of this command:
50 if (threadableID != id) return;
54 KeycodeCollection::const_iterator i = keycodes.find(command);
56 // Do we even have this key defined?
57 if (i == keycodes.end())
59 std::string s = "Tried to send a non-existent command.\n";
60 throw PIRException(s);
63 // construct the device:
64 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
67 int commandDuration = 0;
68 while (repeatCount < MAX_REPEAT_COUNT)
70 // If this is not a repetition, we need to add the initial header:
73 rx51device.addPair(headerPulse, headerSpace);
74 commandDuration += (headerPulse + headerSpace);
77 // generate the rest of the command:
78 commandDuration += generateStandardCommand(i->second, rx51device);
80 // Now, tell the device to send the whole command:
81 rx51device.sendCommandToDevice();
83 // sleep until the next repetition of command:
84 sleepUntilRepeat(commandDuration);
86 // Check whether we've reached the minimum required number of repetitons:
87 if (repeatCount >= minimumRepetitions)
89 // Check whether we've been asked to stop:
90 if (checkRepeatFlag())
92 QMutexLocker cifLocker(&commandIFMutex);
93 commandInFlight = false;
101 catch (PIRException e)
104 emit commandFailed(e.getError().c_str());
107 QMutexLocker cifLocker(&commandIFMutex);
108 commandInFlight = false;
112 int DishProtocol::generateStandardCommand(
113 const PIRKeyBits &pkb,
114 PIRRX51Hardware &rx51device)
118 // In the Dish protocol, the pulse train consists of 6 bits of command
119 // data followed by 10 bits of, uhm, other stuff. I know that at least the
120 // first four bits of these ten can be used for pairing purposes. It looks
121 // like the last five bits can be used as additional command data. For
122 // now, I'm going to split this into 5 "address" and 5 "more command" bits.
124 // The command data is sent MSB-first (I know that at least the first
125 // 6 bits are, I'll represent the last 5 that way as well).
126 // The pairing data is sent LSB-first, god knows why.
127 // - "firstCode" should contain 6-bit value
128 // - "preData" should contain 5 bits of pairing data
129 // - "secondCode" should contain the last 5 bits.
130 duration += pushBits(pkb.firstCode, rx51device);
131 duration += pushReverseBits(postData, rx51device);
132 duration += pushBits(pkb.secondCode, rx51device);
134 // Finally add the "trail":
135 rx51device.addSingle(trailerPulse);
136 duration += trailerPulse;