1 #include "irobotprotocol.h"
3 #include "pirrx51hardware.h"
5 #include "pirexception.h"
7 // Some global communications stuff:
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
12 // The iRobot (Roomba) protocol seems to be extremely simple.
13 // A "zero" is encoded with a 1000 usec pulse, 3000 usec space.
14 // A "one" is encoded with a 3000 usec pulse, 1000 usec space.
15 // So, it looks a little like a shift encoded protocol, even though it
17 // There is no header and no trailer.
18 // Each command may run for 100000 usec (sources differ), but it looks like
19 // commands are not repeated at all...
20 // The carrier frequency is the usual 38 kHz.
22 IRobotProtocol::IRobotProtocol(
36 void IRobotProtocol::startSendingCommand(
37 unsigned int threadableID,
40 // Exceptions here are problematic; I'll try to weed them out by putting the
41 // whole thing in a try/catch block:
44 // First, check if we are meant to be the recipient of this command:
45 if (threadableID != id) return;
49 KeycodeCollection::const_iterator i = keycodes.find(command);
51 // Do we even have this key defined?
52 if (i == keycodes.end())
54 std::string s = "Tried to send a non-existent command.\n";
55 throw PIRException(s);
58 // construct the device:
59 PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
62 int commandDuration = 0;
63 while (repeatCount < MAX_REPEAT_COUNT)
65 // It looks like we only generate the command once, and remain
66 // silent for the rest of the time the button is held down. So, no
70 commandDuration = generateCommand((*i).second, rx51device);
72 // Tell the device to send the command:
73 rx51device.sendCommandToDevice();
76 // sleep until the next repetition of command:
77 sleepUntilRepeat(commandDuration);
79 // Check whether we've reached the minimum required number of repetitons:
80 if (repeatCount >= minimumRepetitions)
82 // Check whether we've been asked to stop:
83 if (checkRepeatFlag())
85 QMutexLocker cifLocker(&commandIFMutex);
86 commandInFlight = false;
94 catch (PIRException e)
97 emit commandFailed(e.getError().c_str());
100 QMutexLocker cifLocker(&commandIFMutex);
101 commandInFlight = false;
105 int IRobotProtocol::generateCommand(
106 const PIRKeyBits &pkb,
107 PIRRX51Hardware &rx51device)
111 // The protocol seems to involve 8 command bits, a 16000 usec pause, and
112 // the same 8 bits repeated again. So, we need to tack a 16000 usec
113 // space on at the end of the first 8 bits, and just drop the last space
114 // definition at the end of the second 8 bits:
118 CommandSequence::const_iterator i = pkb.firstCode.begin();
119 while ((index < 7) && (i != pkb.firstCode.end()))
123 rx51device.addPair(onePulse, oneSpace);
124 duration += onePulse + oneSpace;
128 rx51device.addPair(zeroPulse, zeroSpace);
129 duration += zeroPulse + zeroSpace;
136 // Eighth bit with extra space at the end:
137 if (i != pkb.firstCode.end())
141 rx51device.addPair(onePulse, oneSpace + 16000);
142 duration += onePulse + oneSpace + 16000;
146 rx51device.addPair(zeroPulse, zeroSpace + 16000);
147 duration += zeroPulse + zeroSpace + 16000;
151 // The following seven bits:
153 i = pkb.firstCode.begin();
154 while ((index < 7) && (i != pkb.firstCode.end()))
158 rx51device.addPair(onePulse, oneSpace);
159 duration += onePulse + oneSpace;
163 rx51device.addPair(zeroPulse, zeroSpace);
164 duration += zeroPulse + zeroSpace;
171 // The last half-bit:
172 if (i != pkb.firstCode.end())
176 rx51device.addSingle(onePulse);
177 duration += onePulse;
181 rx51device.addSingle(zeroPulse);
182 duration += zeroPulse;