ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/truck/DashInterface/Display.cpp
Revision: 33
Committed: 2008-02-29T19:05:18-08:00 (17 years, 3 months ago) by douglas
File size: 6879 byte(s)
Log Message:
This is starting to work, but there seems to be some strange with mutexes every once in a while, grr!

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     next: ::usleep(500);
179     }
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 33 _synchronized (ucomLock)
187     ucom << packet;
188 douglas 26
189 douglas 33 _synchronized (responsesLock)
190 douglas 26 {
191 douglas 33 while (responses.empty())
192     responsesCondition.Wait();
193 douglas 28
194 douglas 33 Packet response(responses.front());
195 douglas 28
196 douglas 33 responses.pop();
197 douglas 28
198 douglas 33 assert ((packet.command | Packet::Response) == response.command);
199    
200     return response;
201 douglas 26 }
202 douglas 33
203     throw;
204 douglas 28 }
205 douglas 26
206 douglas 28 bool Display::Ping(const std::string &data)
207     {
208 douglas 29 return data == Communicate<const std::string &>(Packet::PingCommand, data).GetData();
209 douglas 25 }
210 douglas 28
211     std::string Display::Version()
212     {
213     return Communicate(Packet::GetHardwareAndFirmwareVersion).GetData();
214     }
215    
216 douglas 29 void Display::Set(uint8_t column, uint8_t row, const std::string &data)
217 douglas 28 {
218 douglas 30 Communicate(Packet::SendDataToLCD, column, row, data);
219 douglas 28 }
220 douglas 33
221     Display::KeyActivity Display::GetKeyActivity()
222     {
223     _synchronized (keyActivityLock)
224     if (keyActivity.size())
225     {
226     KeyActivity activity(KeyActivity(*keyActivity.front().data));
227    
228     keyActivity.pop();
229    
230     return activity;
231     }
232    
233     return None;
234     }

Properties

Name Value
svn:keywords Id