ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
Revision: 53
Committed: 2008-07-12T17:00:15-07:00 (16 years, 11 months ago) by douglas
File size: 7633 byte(s)
Log Message:
64bit cleanify.

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

Properties

Name Value
svn:keywords Id