ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
Revision: 36
Committed: 2008-03-04T22:24:35-08:00 (17 years, 3 months ago) by douglas
File size: 7176 byte(s)
Log Message:
Huzzah, figured that one out!

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

Properties

Name Value
svn:keywords Id