Gui updated, many keyset changes
[pierogi] / protocols / sharpprotocol.cpp
1 #include "sharpprotocol.h"
2
3 #include "pirexception.h"
4 #include <string>
5 //#include <iostream>
6
7 // Some global communications stuff:
8 #include <QMutex>
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
11
12 // Sharp's protocol should have the following attributes:
13 // A "zero" is encoded with a 320 usec pulse, 680 usec space.
14 // A "one" is encoded with a 320 usec pulse, and 1680 usec space.
15 // There is no header pulse.
16 // The pulse train ends with a trailing 320 usec pulse.
17 // For repeating, the entire train is re-sent, except that the command
18 // section (and the last two bits) are inverted in each odd repeat.
19 // There is a 40000 usec delay between the end of one command and the start
20 // of the next.
21 // The command should be repeated at least once.
22 // The carrier frequency is 38 kHz, duty cycle is 1/3.
23
24 SharpProtocol::SharpProtocol(
25   QObject *guiObject,
26   unsigned int index,
27   bool expBit)
28   : SpaceProtocol(
29       guiObject, index,
30       320, 680,
31       320, 1680,
32       0, 0,
33       320,
34       40000, false),
35     expansionBit(expBit)
36 {
37   setCarrierFrequency(38000);
38   setDutyCycle(33);
39 }
40
41
42 void SharpProtocol::startSendingCommand(
43   unsigned int threadableID,
44   PIRKeyName command)
45 {
46   // Exceptions here are problematic; I'll try to weed them out by putting the
47   // whole thing in a try/catch block:
48   try
49   {
50     // First, check if we are meant to be the recipient of this command:
51     if (threadableID != id) return;
52
53     clearRepeatFlag();
54
55     KeycodeCollection::const_iterator i = keycodes.find(command);
56
57     // Do we even have this key defined?
58     if (i == keycodes.end())
59     {
60       std::string s = "Tried to send a non-existent command.\n";
61       throw PIRException(s);
62     }
63
64     // construct the device:
65     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
66
67     int repeatCount = 0;
68     int commandDuration = 0;
69     while (repeatCount < MAX_REPEAT_COUNT)
70     {
71       // Every other repeat count, we invert everything but the address:
72       if (repeatCount % 2)
73       {
74         commandDuration = generateToggledCommand((*i).second, rx51device);
75       }
76       else
77       {
78         commandDuration = generateStandardCommand((*i).second, rx51device);
79       }
80
81       // Now, tell the device to send the whole command:
82       rx51device.sendCommandToDevice();
83
84       // sleep until the next repetition of command:
85       sleepUntilRepeat(commandDuration);
86
87       // Check whether we've reached the minimum required number of repetitons:
88 //      if (repeatCount >= minimumRepetitions)
89       if (repeatCount >= 1)
90       {
91         // Check whether we've been asked to stop:
92         if (checkRepeatFlag())
93         {
94           QMutexLocker cifLocker(&commandIFMutex);
95           commandInFlight = false;
96           return;
97         }
98       }
99
100       ++repeatCount;
101     }
102   }
103   catch (PIRException e)
104   {
105     // inform the gui:
106     emit commandFailed(e.getError().c_str());
107   }
108
109   QMutexLocker cifLocker(&commandIFMutex);
110   commandInFlight = false;
111 }
112
113
114 int SharpProtocol::generateStandardCommand(
115   const PIRKeyBits &pkb,
116   PIRRX51Hardware &rx51device)
117 {
118   int duration = 0;
119
120   // First, push the address:
121   duration += pushReverseBits(pkb.firstCode, rx51device);
122
123   // Next, push the command:
124   duration += pushReverseBits(pkb.secondCode, rx51device);
125
126   // Next, there is an "expansion" bit and a "check" bit.  Not entirely sure
127   // what these two do.  The check bit is fixed at "1".
128   if (expansionBit)
129   {
130     rx51device.addPair(onePulse, oneSpace);
131     duration += (onePulse + oneSpace);
132   }
133   else
134   {
135     rx51device.addPair(zeroPulse, zeroSpace);
136     duration += (zeroPulse + zeroSpace);
137   }
138
139   rx51device.addPair(zeroPulse, zeroSpace);
140   duration += (zeroPulse + zeroSpace);
141
142   // Finally add the "trail":
143   rx51device.addSingle(trailerPulse);
144   duration += trailerPulse;
145
146   return duration;
147 }
148
149
150 // This is the same as the standard command, except all bits but the address
151 // are inverted:
152 int SharpProtocol::generateToggledCommand(
153   const PIRKeyBits &pkb,
154   PIRRX51Hardware &rx51device)
155 {
156   int duration = 0;
157
158   pushReverseBits(pkb.firstCode, rx51device);
159
160   // This time we invert the command bits:
161   pushInvertedReverseBits(pkb.secondCode, rx51device);
162
163   // We'll also invert the two administrative bits here:
164   if (expansionBit)
165   {
166     rx51device.addPair(zeroPulse, zeroSpace);
167     duration += (zeroPulse + zeroSpace);
168   }
169   else
170   {
171     rx51device.addPair(onePulse, oneSpace);
172     duration += (onePulse + oneSpace);
173   }
174
175   rx51device.addPair(onePulse, oneSpace);
176   duration += (onePulse + oneSpace);
177
178   // Add trail on end:
179   rx51device.addSingle(trailerPulse);
180   duration += trailerPulse;
181
182   return duration;
183 }