Adding Macros!
[pierogi] / protocols / aiwaprotocol.cpp
1 #include "aiwaprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6 #include <string>
7
8 // Some global communications stuff:
9 #include <QMutex>
10 extern bool commandInFlight;
11 extern QMutex commandIFMutex;
12
13 // My information on the Aiwa protocol is that it has the following attributes:
14 // A "zero" is encoded with a 550 usec pulse, 550 usec space.
15 // A "one" is encoded with a 550 usec pulse, 1650 (3 * 550) usec space.
16 // The header has a 8800 usec pulse, 4400 usec space.
17 // There is a 550 usec trailing pulse.
18 // Repeat blocks are 8800 usec pulse, 4400 usec space, then trailing pulse.
19 // Each command lasts for 108000 usec.
20 // Carrier frequency is 38 kHz; I'm using 50% for the duty cycle, for now.
21
22 AiwaProtocol::AiwaProtocol(
23   QObject *guiObject,
24   unsigned int index)
25   : SpaceProtocol(
26       guiObject, index,
27       550, 550,
28       550, 1650,
29       8800, 4400,
30       550,
31       108000, true),
32     repeatPulse(8800),
33     repeatSpace(2250)
34 {
35   setCarrierFrequency(38000);
36 //  setDutyCycle(50);
37 }
38
39
40 void AiwaProtocol::startSendingCommand(
41   unsigned int threadableID,
42   PIRKeyName command)
43 {
44   // Exceptions here are problematic; I'll try to weed them out by putting the
45   // whole thing in a try/catch block:
46   try
47   {
48     // First, check if we are meant to be the recipient of this command:
49     if (threadableID != id) return;
50
51     clearRepeatFlag();
52
53     KeycodeCollection::const_iterator i = keycodes.find(command);
54
55     // Do we even have this key defined?
56     if (i == keycodes.end())
57     {
58       QMutexLocker cifLocker(&commandIFMutex);
59       commandInFlight = false;
60       return;
61 //      std::string s = "Tried to send a non-existent command.\n";
62 //      throw PIRException(s);
63     }
64
65     // construct the device:
66     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
67
68     int repeatCount = 0;
69     int commandDuration = 0;
70     while (repeatCount < MAX_REPEAT_COUNT)
71     {
72       // If we are currently repeating, send the repeat block:
73       if (repeatCount)
74       {
75         commandDuration = generateRepeatCommand(rx51device);
76       }
77       else
78       {
79         commandDuration = generateStandardCommand((*i).second, rx51device);
80       }
81
82       // Now, tell the device to send the whole command:
83       rx51device.sendCommandToDevice();
84
85       // sleep until the next repetition of command:
86       sleepUntilRepeat(commandDuration);
87
88       // Check whether we've reached the minimum required number of repetitons:
89       if (repeatCount >= minimumRepetitions)
90       {
91         // Check whether we've been asked to stop:
92         if (checkRepeatFlag())
93         {
94           break;
95 /*
96           QMutexLocker cifLocker(&commandIFMutex);
97           commandInFlight = false;
98           return;
99 */
100         }
101       }
102
103       ++repeatCount;
104     }
105
106     QMutexLocker cifLocker(&commandIFMutex);
107     commandInFlight = false;
108   }
109   catch (PIRException e)
110   {
111     // inform the gui:
112     emit commandFailed(e.getError().c_str());
113   }
114 }
115
116
117 int AiwaProtocol::generateStandardCommand(
118   const PIRKeyBits &pkb,
119   PIRRX51Hardware &rx51device)
120 {
121   int duration = 0;
122
123   // First, the "header" pulse:
124   rx51device.addPair(headerPulse, headerSpace);
125   duration += (headerPulse + headerSpace);
126
127   // From the information I've got, the "address" portion of the Aiwa protocol
128   // might be split into 8-bit device and 5-bit subdevice subsections, but
129   // for now, I'm just lumping both into a single 13-bit address value.
130   // The command is an 8-bit value.
131   // As with NEC, the address is sent LSB first, then inverted LSB first,
132   // then the command is sent LSB first, then inverted LSB first.
133   duration += pushReverseBits(preData, rx51device);
134   duration += pushInvertedReverseBits(preData, rx51device);
135   duration += pushReverseBits(pkb.firstCode, rx51device);
136   duration += pushInvertedReverseBits(pkb.firstCode, rx51device);
137
138   // Finally add the "trail":
139   rx51device.addSingle(trailerPulse);
140   duration += trailerPulse;
141
142   return duration;
143 }
144
145
146 int AiwaProtocol::generateRepeatCommand(
147   PIRRX51Hardware &rx51device)
148 {
149   int duration = 0;
150
151   // Add the repeat pulse:
152   rx51device.addPair(repeatPulse, repeatSpace);
153   duration += (repeatPulse + repeatSpace);
154
155   // Finally add the trailer:
156   rx51device.addSingle(trailerPulse);
157   duration += trailerPulse;
158
159   return duration;
160 }