ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
Revision: 37
Committed: 2008-03-05T02:29:38-08:00 (17 years, 3 months ago) by douglas
File size: 7117 byte(s)
Log Message:
Grr! This is going to need a refactor.

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 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)
107 douglas 31 {
108 douglas 26 ::termios state;
109 douglas 25
110 douglas 26 Posix::CheckError(::tcgetattr(ucom, &state));
111     Posix::CheckError(::cfsetospeed(&state, B115200));
112     Posix::CheckError(::cfsetispeed(&state, B115200));
113    
114     state.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF);
115     state.c_iflag |= IGNPAR;
116     state.c_oflag &= ~(OPOST | ONLCR | ONOCR | ONLRET);
117     state.c_cflag &= ~(CSIZE | PARENB | PARODD | HUPCL | CRTSCTS);
118     state.c_cflag |= CREAD | CS8 | CSTOPB | CLOCAL;
119     state.c_lflag &= ~(ISIG | ICANON | IEXTEN | ECHO);
120     state.c_lflag |= NOFLSH;
121    
122     Posix::CheckError(::tcsetattr(ucom, TCSANOW, &state));
123 douglas 33
124     _synchronized (ucomLock)
125     ucomCondition.Signal();
126 douglas 25 }
127    
128 douglas 33 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 douglas 37 next: Timing::NanoSleep(Timing::Time(0, 10000000));
180 douglas 33 }
181     }
182    
183 douglas 29 Display::Packet Display::Communicate_(Display::Packet::Command command, uint8_t length, const uint8_t *data)
184 douglas 25 {
185 douglas 33 Packet packet(command, length, data);
186 douglas 25
187 douglas 36 retry:
188 douglas 33 _synchronized (ucomLock)
189     ucom << packet;
190 douglas 26
191 douglas 33 _synchronized (responsesLock)
192 douglas 26 {
193 douglas 33 while (responses.empty())
194 douglas 36 try
195     {
196 douglas 37 responsesCondition.Wait(Timing::GetTimeOfDay() += 1);
197 douglas 36 }
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 douglas 33 Packet response(responses.front());
207 douglas 28
208 douglas 33 responses.pop();
209 douglas 28
210 douglas 33 assert ((packet.command | Packet::Response) == response.command);
211    
212     return response;
213 douglas 26 }
214 douglas 33
215     throw;
216 douglas 28 }
217 douglas 26
218 douglas 28 bool Display::Ping(const std::string &data)
219     {
220 douglas 29 return data == Communicate<const std::string &>(Packet::PingCommand, data).GetData();
221 douglas 25 }
222 douglas 28
223     std::string Display::Version()
224     {
225     return Communicate(Packet::GetHardwareAndFirmwareVersion).GetData();
226     }
227    
228 douglas 29 void Display::Set(uint8_t column, uint8_t row, const std::string &data)
229 douglas 28 {
230 douglas 30 Communicate(Packet::SendDataToLCD, column, row, data);
231 douglas 28 }
232 douglas 33
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     }

Properties

Name Value
svn:keywords Id