24c71ff7df947622d449f6457d927a4d96b0e575
[pierogi] / protocols / daewooprotocol.cpp
1 #include "daewooprotocol.h"
2
3 #include "pirrx51hardware.h"
4
5 #include "pirexception.h"
6
7 // Some global communications stuff:
8 #include <QMutex>
9 extern bool commandInFlight;
10 extern QMutex commandIFMutex;
11
12 // Daewoo is using a protocol similar to NEC, but with the distinction that
13 // it does not send inverted copies of the address and command, and it places
14 // a 550 usec pulse / 2000 usec space between the address and the command.
15 // Here are the fine details:
16 // A "zero" is encoded with a 550 usec pulse, 450 usec space.
17 // A "one" is encoded with a 550 usec pulse, and 1450 usec space.
18 // The header is a 8000 usec pulse, 4000 usec space.
19 // There is a mid-way marker of 550 usec pulse, 2000 usec space.
20 // The pulse train ends with a trailing 550 usec pulse.
21 // The entire train is resent for repeats.
22 // Each command runs for 60000 usec before another can be executed.
23 // The carrier frequency is 38 kHz.
24
25 DaewooProtocol::DaewooProtocol(
26   QObject *guiObject,
27   unsigned int index)
28   : SpaceProtocol(
29       guiObject, index,
30       550, 450,
31       550, 1450,
32       8000, 4000,
33       550,
34       60000, true),
35     midPulse(550),
36     midSpace(2000)
37 {
38 }
39
40
41 void DaewooProtocol::startSendingCommand(
42   unsigned int threadableID,
43   PIRKeyName command)
44 {
45   // Exceptions here are problematic; I'll try to weed them out by putting the
46   // whole thing in a try/catch block:
47   try
48   {
49     // First, check if we are meant to be the recipient of this command:
50     if (threadableID != id) return;
51
52     clearRepeatFlag();
53
54     KeycodeCollection::const_iterator i = keycodes.find(command);
55
56     // Do we even have this key defined?
57     if (i == keycodes.end())
58     {
59       std::string s = "Tried to send a non-existent command.\n";
60       throw PIRException(s);
61     }
62
63     // construct the device:
64     PIRRX51Hardware rx51device(carrierFrequency, dutyCycle);
65
66     int repeatCount = 0;
67     int commandDuration = 0;
68     while (repeatCount < MAX_REPEAT_COUNT)
69     {
70       commandDuration = generateStandardCommand((*i).second, rx51device);
71
72       // Now, tell the device to send the whole command:
73       rx51device.sendCommandToDevice();
74
75       // sleep until the next repetition of command:
76       sleepUntilRepeat(commandDuration);
77
78       // Check whether we've reached the minimum required number of repetitons:
79       if (repeatCount >= minimumRepetitions)
80       {
81         // Check whether we've been asked to stop:
82         if (checkRepeatFlag())
83         {
84           QMutexLocker cifLocker(&commandIFMutex);
85           commandInFlight = false;
86           return;
87         }
88       }
89
90       ++repeatCount;
91     }
92   }
93   catch (PIRException e)
94   {
95     // inform the gui:
96     emit commandFailed(e.getError().c_str());
97   }
98
99   QMutexLocker cifLocker(&commandIFMutex);
100   commandInFlight = false;
101 }
102
103
104 int DaewooProtocol::generateStandardCommand(
105   const PIRKeyBits &pkb,
106   PIRRX51Hardware &rx51device)
107 {
108   int duration = 0;
109
110   // First, the "header" pulse:
111   rx51device.addPair(headerPulse, headerSpace);
112   duration += (headerPulse + headerSpace);
113
114   // The address data:
115   duration += pushReverseBits(preData, rx51device);
116
117   // The Daewoo mid-train marker:
118   rx51device.addPair(midPulse, midSpace);
119   duration += (midPulse + midSpace);
120
121   // The command data:
122   duration += pushReverseBits(pkb.firstCode, rx51device);
123
124   // Finally add the "trail":
125   rx51device.addSingle(trailerPulse);
126   duration += trailerPulse;
127
128   return duration;
129 }
130