ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
(Generate patch)

Comparing DashInterface/Display.cpp (file contents):
Revision 29 by douglas, 2008-02-27T16:09:18-08:00 vs.
Revision 39 by douglas, 2008-03-05T14:39:41-08:00

# Line 5 | Line 5
5   // $Id$
6  
7   #include <foreach.hpp>
8 + #include <scopes.hpp>
9 + #include <timing.hpp>
10  
11 + #include <iomanip>
12   #include <iostream>
13  
14   #include <fcntl.h>
# Line 69 | Line 72 | Display::Packet::Packet(Display::Packet:
72          crc = GetCRC(reinterpret_cast<uint8_t *>(this), length + 2);
73   }
74  
75 < void operator<<(int fd, const Display::Packet::Packet &packet)
75 > std::ostream &operator<<(std::ostream &output, const Display::Packet &packet)
76 > {
77 >        return output << _B("0x") << std::hex << std::setw(2) << std::setfill('0') << unsigned(packet.command) << _B(" [") << packet.GetData() << ']';
78 > }
79 >
80 > void operator<<(int fd, const Display::Packet &packet)
81   {
82          if (packet.length != sizeof (packet.data))
83                  ::memcpy(const_cast<uint8_t *>(packet.data) + packet.length, &packet.crc, 2);
84  
85 +        if (debug)
86 +                std::cerr << _B("<< ") << packet << std::endl;
87 +
88          Posix::Write(fd, &packet, packet.length + 4);
89   }
90  
91 < void operator>>(int fd, Display::Packet::Packet &packet)
91 > void operator>>(int fd, Display::Packet &packet)
92   {
93          Posix::Read(fd, &packet, 2);
94          Posix::Read(fd, packet.data, packet.length);
95          Posix::Read(fd, &packet.crc, 2);
96  
97          if (debug)
98 <        {
99 <                char *data;
89 <
90 <                ::asprintf(&data, "0x%02x %i ", packet.command, packet.length);
98 >                std::cerr << _B(">> ") << packet << std::endl;
99 > }
100  
101 <                std::cerr << data << '[' << packet.GetData() << ']' << std::endl;
101 > void Communicate(Display *display)
102 > {
103 >        display->Communicate_();
104 > }
105  
106 <                std::free(data);
107 <        }
106 > void Activity(Display *display)
107 > {
108 >        display->Activity();
109   }
110  
111 < Display::Display(const std::string &device) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY))
111 > Display::Display(const std::string &device, Callback callback, void *data) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)), ucomCondition(ucomLock), running(true), responsesCondition(responsesLock), keyActivityCondition(keyActivityLock), callback(callback), data(data), communicate(reinterpret_cast<void *(*)(void *)>(::Communicate), this), activity(reinterpret_cast<void *(*)(void *)>(::Activity), this)
112   {
113          ::termios state;
114  
# Line 112 | Line 125 | Display::Display(const std::string &devi
125          state.c_lflag |= NOFLSH;
126  
127          Posix::CheckError(::tcsetattr(ucom, TCSANOW, &state));
128 +
129 +        _synchronized (ucomLock)
130 +                ucomCondition.Signal();
131 + }
132 +
133 + Display::~Display()
134 + {
135 +        running = false;
136 +
137 +        communicate.Join();
138 +        activity.Join();
139 +
140 +        Posix::Close(ucom);
141 + }
142 +
143 + void Display::Communicate_()
144 + {
145 +        _synchronized (ucomLock)
146 +                ucomCondition.Wait();
147 +
148 +        while (running)
149 +        {
150 +                Packet response;
151 +
152 +                _synchronized (ucomLock)
153 +                        try
154 +                        {
155 +                                ucom >> response;
156 +                        }
157 +                        catch (const Posix::Error error)
158 +                        {
159 +                                if (error.what() != _B("Resource temporarily unavailable"))
160 +                                        throw error;
161 +
162 +                                goto next;
163 +                        }
164 +
165 +                if ((response.command & Packet::Error) == Packet::Error);
166 +                else if ((response.command & Packet::Report) == Packet::Report)
167 +                        switch (response.command)
168 +                        {
169 +                        case Packet::KeyActivity:
170 +                                _synchronized (keyActivityLock)
171 +                                {
172 +                                        keyActivity.push(response);
173 +                                        keyActivityCondition.Signal();
174 +                                }
175 +
176 +                                break;
177 +                        case Packet::FanSpeedReport:
178 +                        case Packet::TemperatureSensorReport:
179 +                                break;
180 +                        }
181 +                else if ((response.command & Packet::Response) == Packet::Response)
182 +                        _synchronized (responsesLock)
183 +                        {
184 +                                responses.push(response);
185 +                                responsesCondition.Signal();
186 +                        }
187 +
188 + next:   Timing::NanoSleep(Timing::Time(0, 10000000));
189 +        }
190 +
191 +        keyActivityCondition.Signal();
192   }
193  
194   Display::Packet Display::Communicate_(Display::Packet::Command command, uint8_t length, const uint8_t *data)
195   {
196 <        Packet packet(command, length, data), response;
196 >        Packet packet(command, length, data);
197  
198 <        ucom << packet;
198 > retry:
199 >        _synchronized (ucomLock)
200 >                ucom << packet;
201  
202 <        _forever
202 >        _synchronized (responsesLock)
203          {
204 <                ucom >> response;
204 >                while (responses.empty())
205 >                        try
206 >                        {
207 >                                responsesCondition.Wait(Timing::GetTimeOfDay() += 1);
208 >                        }
209 >                        catch (const Posix::Error &error)
210 >                        {
211 >                                if (error.what() != _B("Operation timed out"))
212 >                                        throw error;
213 >
214 >                                goto retry;
215 >                        }
216  
217 <                if (packet.command | Packet::Response == response.command)
128 <                        return response;
217 >                Packet response(responses.front());
218  
219 <                switch (response.command)
219 >                responses.pop();
220 >
221 >                assert ((packet.command | Packet::Response) == response.command);
222 >
223 >                return response;
224 >        }
225 >
226 >        throw;
227 > }
228 >
229 > void Display::Activity()
230 > {
231 >        if (callback == NULL)
232 >                return;
233 >
234 >        while (running)
235 >                _synchronized (keyActivityLock)
236                  {
237 <                case Packet::KeyActivity:
238 <                        keyActivity.push(response);
237 >                        while (keyActivity.empty())
238 >                                keyActivityCondition.Wait();
239  
240 <                        break;
241 <                case Packet::FanSpeedReport:
242 <                case Packet::TemperatureSensorReport:
243 <                        break;
240 >                        while (keyActivity.size())
241 >                        {
242 >                                KeyActivity activity(KeyActivity(*keyActivity.front().data));
243 >
244 >                                keyActivity.pop();
245 >
246 >                                _desynchronized (keyActivityLock)
247 >                                        callback(activity, data);
248 >                        }
249                  }
140        }
250   }
251  
252   bool Display::Ping(const std::string &data)
# Line 152 | Line 261 | std::string Display::Version()
261  
262   void Display::Set(uint8_t column, uint8_t row, const std::string &data)
263   {
264 <        Communicate<uint8_t, uint8_t, const std::string &>(Packet::SendDataToLCD, column, row, data);
264 >        Communicate(Packet::SendDataToLCD, column, row, data);
265   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines