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 37 by douglas, 2008-03-05T02:29:38-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);
91 <
92 <                std::cerr << data << '[' << packet.GetData() << ']' << std::endl;
98 >                std::cerr << _B(">> ") << packet << std::endl;
99 > }
100  
101 <                std::free(data);
102 <        }
101 > void Communicate(Display *display)
102 > {
103 >        display->Communicate_();
104   }
105  
106 < Display::Display(const std::string &device) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY))
106 > Display::Display(const std::string &device) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)), ucomCondition(ucomLock), running(true), responsesCondition(responsesLock), thread(reinterpret_cast<void *(*)(void *)>(::Communicate), this)
107   {
108          ::termios state;
109  
# Line 112 | Line 120 | Display::Display(const std::string &devi
120          state.c_lflag |= NOFLSH;
121  
122          Posix::CheckError(::tcsetattr(ucom, TCSANOW, &state));
123 +
124 +        _synchronized (ucomLock)
125 +                ucomCondition.Signal();
126 + }
127 +
128 + Display::~Display()
129 + {
130 +        running = false;
131 +
132 +        thread.Join();
133 +
134 +        Posix::Close(ucom);
135 + }
136 +
137 + void Display::Communicate_()
138 + {
139 +        _synchronized (ucomLock)
140 +                ucomCondition.Wait();
141 +
142 +        while (running)
143 +        {
144 +                Packet response;
145 +
146 +                _synchronized (ucomLock)
147 +                        try
148 +                        {
149 +                                ucom >> response;
150 +                        }
151 +                        catch (const Posix::Error error)
152 +                        {
153 +                                if (error.what() != _B("Resource temporarily unavailable"))
154 +                                        throw error;
155 +
156 +                                goto next;
157 +                        }
158 +
159 +                if ((response.command & Packet::Error) == Packet::Error);
160 +                else if ((response.command & Packet::Report) == Packet::Report)
161 +                        switch (response.command)
162 +                        {
163 +                        case Packet::KeyActivity:
164 +                                _synchronized (keyActivityLock)
165 +                                        keyActivity.push(response);
166 +
167 +                                break;
168 +                        case Packet::FanSpeedReport:
169 +                        case Packet::TemperatureSensorReport:
170 +                                break;
171 +                        }
172 +                else if ((response.command & Packet::Response) == Packet::Response)
173 +                        _synchronized (responsesLock)
174 +                        {
175 +                                responses.push(response);
176 +                                responsesCondition.Signal();
177 +                        }
178 +
179 + next:   Timing::NanoSleep(Timing::Time(0, 10000000));
180 +        }
181   }
182  
183   Display::Packet Display::Communicate_(Display::Packet::Command command, uint8_t length, const uint8_t *data)
184   {
185 <        Packet packet(command, length, data), response;
185 >        Packet packet(command, length, data);
186  
187 <        ucom << packet;
187 > retry:
188 >        _synchronized (ucomLock)
189 >                ucom << packet;
190  
191 <        _forever
191 >        _synchronized (responsesLock)
192          {
193 <                ucom >> response;
193 >                while (responses.empty())
194 >                        try
195 >                        {
196 >                                responsesCondition.Wait(Timing::GetTimeOfDay() += 1);
197 >                        }
198 >                        catch (const Posix::Error &error)
199 >                        {
200 >                                if (error.what() != _B("Operation timed out"))
201 >                                        throw error;
202 >
203 >                                goto retry;
204 >                        }
205  
206 <                if (packet.command | Packet::Response == response.command)
128 <                        return response;
206 >                Packet response(responses.front());
207  
208 <                switch (response.command)
131 <                {
132 <                case Packet::KeyActivity:
133 <                        keyActivity.push(response);
208 >                responses.pop();
209  
210 <                        break;
211 <                case Packet::FanSpeedReport:
212 <                case Packet::TemperatureSensorReport:
138 <                        break;
139 <                }
210 >                assert ((packet.command | Packet::Response) == response.command);
211 >
212 >                return response;
213          }
214 +
215 +        throw;
216   }
217  
218   bool Display::Ping(const std::string &data)
# Line 152 | Line 227 | std::string Display::Version()
227  
228   void Display::Set(uint8_t column, uint8_t row, const std::string &data)
229   {
230 <        Communicate<uint8_t, uint8_t, const std::string &>(Packet::SendDataToLCD, column, row, data);
230 >        Communicate(Packet::SendDataToLCD, column, row, data);
231 > }
232 >
233 > Display::KeyActivity Display::GetKeyActivity()
234 > {
235 >        _synchronized (keyActivityLock)
236 >                if (keyActivity.size())
237 >                {
238 >                        KeyActivity activity(KeyActivity(*keyActivity.front().data));
239 >
240 >                        keyActivity.pop();
241 >
242 >                        return activity;
243 >                }
244 >
245 >        return None;
246   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines