ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
Revision: 38
Committed: 2008-03-05T13:36:38-08:00 (17 years, 3 months ago) by douglas
File size: 7567 byte(s)
Log Message:
Begin refactoring how key events work.

File Contents

# User Rev Content
1 douglas 26 // Display (Crystalfontz CFA-635 USB LCD)
2 douglas 6 //
3     // Douglas Thrift
4     //
5     // $Id$
6    
7 douglas 28 #include <foreach.hpp>
8 douglas 33 #include <scopes.hpp>
9 douglas 37 #include <timing.hpp>
10 douglas 28
11 douglas 30 #include <iomanip>
12 douglas 25 #include <iostream>
13 douglas 6
14 douglas 26 #include <fcntl.h>
15     #include <termios.h>
16 douglas 25
17 douglas 26 #include "Display.hpp"
18 douglas 25
19 douglas 28 extern bool debug;
20    
21 douglas 26 static uint16_t GetCRC(uint8_t *buffer, size_t length)
22 douglas 25 {
23 douglas 26 static const uint16_t table[256] = {
24 douglas 29 0x00000, 0x01189, 0x02312, 0x0329b, 0x04624, 0x057ad, 0x06536, 0x074bf,
25     0x08C48, 0x09DC1, 0x0AF5A, 0x0BED3, 0x0CA6C, 0x0DBE5, 0x0E97E, 0x0F8F7,
26     0x01081, 0x00108, 0x03393, 0x0221a, 0x056a5, 0x0472c, 0x075b7, 0x0643e,
27     0x09CC9, 0x08D40, 0x0BFDB, 0x0AE52, 0x0DAED, 0x0CB64, 0x0F9FF, 0x0E876,
28     0x02102, 0x0308b, 0x00210, 0x01399, 0x06726, 0x076af, 0x04434, 0x055bd,
29     0x0AD4A, 0x0BCC3, 0x08E58, 0x09FD1, 0x0EB6E, 0x0FAE7, 0x0C87C, 0x0D9F5,
30     0x03183, 0x0200a, 0x01291, 0x00318, 0x077a7, 0x0662e, 0x054b5, 0x0453c,
31     0x0BDCB, 0x0AC42, 0x09ED9, 0x08F50, 0x0FBEF, 0x0EA66, 0x0D8FD, 0x0C974,
32     0x04204, 0x0538d, 0x06116, 0x0709f, 0x00420, 0x015a9, 0x02732, 0x036bb,
33     0x0ce4c, 0x0dfc5, 0x0ed5e, 0x0fcd7, 0x08868, 0x099e1, 0x0ab7a, 0x0baf3,
34     0x05285, 0x0430c, 0x07197, 0x0601e, 0x014a1, 0x00528, 0x037b3, 0x0263a,
35     0x0decd, 0x0cf44, 0x0fddf, 0x0ec56, 0x098e9, 0x08960, 0x0bbfb, 0x0aa72,
36     0x06306, 0x0728f, 0x04014, 0x0519d, 0x02522, 0x034ab, 0x00630, 0x017b9,
37     0x0EF4E, 0x0FEC7, 0x0CC5C, 0x0DDD5, 0x0A96A, 0x0B8E3, 0x08A78, 0x09BF1,
38     0x07387, 0x0620e, 0x05095, 0x0411c, 0x035a3, 0x0242a, 0x016b1, 0x00738,
39     0x0FFCF, 0x0EE46, 0x0DCDD, 0x0CD54, 0x0B9EB, 0x0A862, 0x09AF9, 0x08B70,
40     0x08408, 0x09581, 0x0a71a, 0x0b693, 0x0c22c, 0x0d3a5, 0x0e13e, 0x0f0b7,
41     0x00840, 0x019c9, 0x02b52, 0x03adb, 0x04e64, 0x05fed, 0x06d76, 0x07cff,
42     0x09489, 0x08500, 0x0b79b, 0x0a612, 0x0d2ad, 0x0c324, 0x0f1bf, 0x0e036,
43     0x018c1, 0x00948, 0x03bd3, 0x02a5a, 0x05ee5, 0x04f6c, 0x07df7, 0x06c7e,
44     0x0a50a, 0x0b483, 0x08618, 0x09791, 0x0e32e, 0x0f2a7, 0x0c03c, 0x0d1b5,
45     0x02942, 0x038cb, 0x00a50, 0x01bd9, 0x06f66, 0x07eef, 0x04c74, 0x05dfd,
46     0x0b58b, 0x0a402, 0x09699, 0x08710, 0x0f3af, 0x0e226, 0x0d0bd, 0x0c134,
47     0x039C3, 0x0284A, 0x01AD1, 0x00B58, 0x07FE7, 0x06E6E, 0x05CF5, 0x04D7C,
48     0x0c60c, 0x0d785, 0x0e51e, 0x0f497, 0x08028, 0x091a1, 0x0a33a, 0x0b2b3,
49     0x04a44, 0x05bcd, 0x06956, 0x078df, 0x00c60, 0x01de9, 0x02f72, 0x03efb,
50     0x0d68d, 0x0c704, 0x0f59f, 0x0e416, 0x090a9, 0x08120, 0x0b3bb, 0x0a232,
51     0x05AC5, 0x04B4C, 0x079D7, 0x0685E, 0x01CE1, 0x00D68, 0x03FF3, 0x02E7A,
52     0x0e70e, 0x0f687, 0x0c41c, 0x0d595, 0x0a12a, 0x0b0a3, 0x08238, 0x093b1,
53     0x06b46, 0x07acf, 0x04854, 0x059dd, 0x02d62, 0x03ceb, 0x00e70, 0x01ff9,
54     0x0f78f, 0x0e606, 0x0d49d, 0x0c514, 0x0b1ab, 0x0a022, 0x092b9, 0x08330,
55     0x07BC7, 0x06A4E, 0x058D5, 0x0495C, 0x03DE3, 0x02C6A, 0x01EF1, 0x00F78,
56 douglas 26 };
57     register uint16_t crc(0xffff);
58 douglas 25
59 douglas 26 while (length--)
60     crc = (crc >> 8) ^ table[(crc ^ *buffer++) & 0xff];
61 douglas 25
62 douglas 26 return ~crc;
63     }
64 douglas 25
65 douglas 28 Display::Packet::Packet(Display::Packet::Command command, uint8_t length, const uint8_t *data) : command(command), length(length)
66 douglas 26 {
67     if (length > sizeof (this->data))
68     throw;
69 douglas 25
70 douglas 28 ::memcpy(this->data, data, length);
71 douglas 25
72 douglas 26 crc = GetCRC(reinterpret_cast<uint8_t *>(this), length + 2);
73     }
74 douglas 25
75 douglas 30 std::ostream &operator<<(std::ostream &output, const Display::Packet &packet)
76 douglas 26 {
77 douglas 33 return output << _B("0x") << std::hex << std::setw(2) << std::setfill('0') << unsigned(packet.command) << _B(" [") << packet.GetData() << ']';
78 douglas 30 }
79    
80     void operator<<(int fd, const Display::Packet &packet)
81     {
82 douglas 26 if (packet.length != sizeof (packet.data))
83     ::memcpy(const_cast<uint8_t *>(packet.data) + packet.length, &packet.crc, 2);
84 douglas 25
85 douglas 30 if (debug)
86     std::cerr << _B("<< ") << packet << std::endl;
87    
88 douglas 26 Posix::Write(fd, &packet, packet.length + 4);
89     }
90 douglas 25
91 douglas 30 void operator>>(int fd, Display::Packet &packet)
92 douglas 26 {
93     Posix::Read(fd, &packet, 2);
94     Posix::Read(fd, packet.data, packet.length);
95     Posix::Read(fd, &packet.crc, 2);
96 douglas 25
97 douglas 28 if (debug)
98 douglas 30 std::cerr << _B(">> ") << packet << std::endl;
99 douglas 25 }
100    
101 douglas 31 void Communicate(Display *display)
102 douglas 25 {
103 douglas 33 display->Communicate_();
104 douglas 31 }
105    
106 douglas 38 void Activity(Display *display)
107 douglas 31 {
108 douglas 38 display->Activity();
109     }
110    
111     Display::Display(const std::string &device, Callback callback) : ucom(Posix::Open(device, O_RDWR | O_NOCTTY | O_NONBLOCK)), ucomCondition(ucomLock), running(true), responsesCondition(responsesLock), keyActivityCondition(keyActivityLock), callback(callback), communicate(reinterpret_cast<void *(*)(void *)>(::Communicate), this), activity(reinterpret_cast<void *(*)(void *)>(::Activity), this)
112     {
113 douglas 26 ::termios state;
114 douglas 25
115 douglas 26 Posix::CheckError(::tcgetattr(ucom, &state));
116     Posix::CheckError(::cfsetospeed(&state, B115200));
117     Posix::CheckError(::cfsetispeed(&state, B115200));
118    
119     state.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF);
120     state.c_iflag |= IGNPAR;
121     state.c_oflag &= ~(OPOST | ONLCR | ONOCR | ONLRET);
122     state.c_cflag &= ~(CSIZE | PARENB | PARODD | HUPCL | CRTSCTS);
123     state.c_cflag |= CREAD | CS8 | CSTOPB | CLOCAL;
124     state.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO);
125     state.c_lflag |= NOFLSH;
126    
127     Posix::CheckError(::tcsetattr(ucom, TCSANOW, &state));
128 douglas 33
129     _synchronized (ucomLock)
130     ucomCondition.Signal();
131 douglas 25 }
132    
133 douglas 33 Display::~Display()
134     {
135     running = false;
136    
137 douglas 38 communicate.Join();
138     activity.Join();
139 douglas 33
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 douglas 38 {
172 douglas 33 keyActivity.push(response);
173 douglas 38 keyActivityCondition.Signal();
174     }
175 douglas 33
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 douglas 37 next: Timing::NanoSleep(Timing::Time(0, 10000000));
189 douglas 33 }
190 douglas 38
191     keyActivityCondition.Signal();
192 douglas 33 }
193    
194 douglas 29 Display::Packet Display::Communicate_(Display::Packet::Command command, uint8_t length, const uint8_t *data)
195 douglas 25 {
196 douglas 33 Packet packet(command, length, data);
197 douglas 25
198 douglas 36 retry:
199 douglas 33 _synchronized (ucomLock)
200     ucom << packet;
201 douglas 26
202 douglas 33 _synchronized (responsesLock)
203 douglas 26 {
204 douglas 33 while (responses.empty())
205 douglas 36 try
206     {
207 douglas 37 responsesCondition.Wait(Timing::GetTimeOfDay() += 1);
208 douglas 36 }
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 douglas 33 Packet response(responses.front());
218 douglas 28
219 douglas 33 responses.pop();
220 douglas 28
221 douglas 33 assert ((packet.command | Packet::Response) == response.command);
222    
223     return response;
224 douglas 26 }
225 douglas 33
226     throw;
227 douglas 28 }
228 douglas 26
229 douglas 38 void Display::Activity()
230     {
231     if (callback == NULL)
232     return;
233    
234     while (running)
235     _synchronized (keyActivityLock)
236     {
237     while (keyActivity.empty())
238     keyActivityCondition.Wait();
239    
240     while (keyActivity.size())
241     {
242     KeyActivity activity(KeyActivity(*keyActivity.front().data));
243    
244     keyActivity.pop();
245    
246     _desynchronized (keyActivityLock)
247     callback(activity);
248     }
249     }
250     }
251    
252 douglas 28 bool Display::Ping(const std::string &data)
253     {
254 douglas 29 return data == Communicate<const std::string &>(Packet::PingCommand, data).GetData();
255 douglas 25 }
256 douglas 28
257     std::string Display::Version()
258     {
259     return Communicate(Packet::GetHardwareAndFirmwareVersion).GetData();
260     }
261    
262 douglas 29 void Display::Set(uint8_t column, uint8_t row, const std::string &data)
263 douglas 28 {
264 douglas 30 Communicate(Packet::SendDataToLCD, column, row, data);
265 douglas 28 }

Properties

Name Value
svn:keywords Id