|
1 /* |
|
2 * GraphLCD driver library |
|
3 * |
|
4 * t6963c.c - T6963C driver class |
|
5 * |
|
6 * low level routines based on lcdproc 0.5 driver, (c) 2001 Manuel Stahl |
|
7 * |
|
8 * This file is released under the GNU General Public License. Refer |
|
9 * to the COPYING file distributed with this package. |
|
10 * |
|
11 * (c) 2003, 2004 Andreas Regel <andreas.regel AT powarman.de> |
|
12 */ |
|
13 |
|
14 #include <syslog.h> |
|
15 |
|
16 #include "common.h" |
|
17 #include "config.h" |
|
18 #include "port.h" |
|
19 #include "t6963c.h" |
|
20 |
|
21 |
|
22 namespace GLCD |
|
23 { |
|
24 |
|
25 // T6963 commands |
|
26 const unsigned char kSetCursorPointer = 0x21; |
|
27 const unsigned char kSetOffsetRegister = 0x22; |
|
28 const unsigned char kSetAddressPointer = 0x24; |
|
29 |
|
30 const unsigned char kSetTextHomeAddress = 0x40; |
|
31 const unsigned char kSetTextArea = 0x41; |
|
32 const unsigned char kSetGraphicHomeAddress = 0x42; |
|
33 const unsigned char kSetGraphicArea = 0x43; |
|
34 |
|
35 const unsigned char kSetMode = 0x80; |
|
36 const unsigned char kSetDisplayMode = 0x90; |
|
37 const unsigned char kSetCursorPattern = 0xA0; |
|
38 |
|
39 const unsigned char kDataWriteInc = 0xC0; |
|
40 const unsigned char kDataReadInc = 0xC1; |
|
41 const unsigned char kDataWriteDec = 0xC2; |
|
42 const unsigned char kDataReadDec = 0xC3; |
|
43 const unsigned char kDataWrite = 0xC4; |
|
44 const unsigned char kDataRead = 0xC5; |
|
45 |
|
46 const unsigned char kAutoWrite = 0xB0; |
|
47 const unsigned char kAutoRead = 0xB1; |
|
48 const unsigned char kAutoReset = 0xB2; |
|
49 |
|
50 |
|
51 // T6963 Parameters |
|
52 const unsigned char kModeOr = 0x00; |
|
53 const unsigned char kModeXor = 0x01; |
|
54 const unsigned char kModeAnd = 0x03; |
|
55 const unsigned char kModeTextAttribute = 0x04; |
|
56 const unsigned char kModeInternalCG = 0x00; |
|
57 const unsigned char kModeExternalCG = 0x08; |
|
58 |
|
59 const unsigned char kTextAttributeNormal = 0x00; |
|
60 const unsigned char kTextAttributeInverse = 0x05; |
|
61 const unsigned char kTextAttributeNoDisplay = 0x03; |
|
62 const unsigned char kTextAttributeBlink = 0x08; |
|
63 |
|
64 const unsigned char kDisplayModeBlink = 0x01; |
|
65 const unsigned char kDisplayModeCursor = 0x02; |
|
66 const unsigned char kDisplayModeText = 0x04; |
|
67 const unsigned char kDisplayModeGraphic = 0x08; |
|
68 |
|
69 const unsigned short kGraphicBase = 0x0000; |
|
70 const unsigned short kTextBase = 0x1500; |
|
71 const unsigned short kCGRAMBase = 0x1800; |
|
72 |
|
73 |
|
74 // T6963 Wirings |
|
75 static const std::string kWiringStandard = "Standard"; |
|
76 static const std::string kWiringWindows = "Windows"; |
|
77 static const std::string kWiringSerial = "Serial"; |
|
78 |
|
79 const unsigned char kStandardWRHI = 0x00; // 01 / nSTRB |
|
80 const unsigned char kStandardWRLO = 0x01; // |
|
81 const unsigned char kStandardRDHI = 0x00; // 17 / nSELECT |
|
82 const unsigned char kStandardRDLO = 0x08; // |
|
83 const unsigned char kStandardCEHI = 0x00; // 14 / nLINEFEED |
|
84 const unsigned char kStandardCELO = 0x02; // |
|
85 const unsigned char kStandardCDHI = 0x04; // 16 / INIT |
|
86 const unsigned char kStandardCDLO = 0x00; // |
|
87 |
|
88 const unsigned char kWindowsWRHI = 0x04; // 16 / INIT |
|
89 const unsigned char kWindowsWRLO = 0x00; // |
|
90 const unsigned char kWindowsRDHI = 0x00; // 14 / nLINEFEED |
|
91 const unsigned char kWindowsRDLO = 0x02; // |
|
92 const unsigned char kWindowsCEHI = 0x00; // 01 / nSTRB |
|
93 const unsigned char kWindowsCELO = 0x01; // |
|
94 const unsigned char kWindowsCDHI = 0x00; // 17 / nSELECT |
|
95 const unsigned char kWindowsCDLO = 0x08; // |
|
96 |
|
97 const unsigned char kSerialWRHI = 0x01; // 01 / nSTRB |
|
98 const unsigned char kSerialWRLO = 0x00; // |
|
99 const unsigned char kSerialRDHI = 0x08; // 17 / nSELECT |
|
100 const unsigned char kSerialRDLO = 0x00; // |
|
101 const unsigned char kSerialCEHI = 0x02; // 14 / nLINEFEED |
|
102 const unsigned char kSerialCELO = 0x00; // |
|
103 const unsigned char kSerialCDHI = 0x00; // 16 / INIT |
|
104 const unsigned char kSerialCDLO = 0x04; // |
|
105 |
|
106 |
|
107 cDriverT6963C::cDriverT6963C(cDriverConfig * config) |
|
108 : config(config) |
|
109 { |
|
110 oldConfig = new cDriverConfig(*config); |
|
111 |
|
112 port = new cParallelPort(); |
|
113 |
|
114 //width = config->width; |
|
115 //height = config->height; |
|
116 refreshCounter = 0; |
|
117 displayMode = 0; |
|
118 bidirectLPT = 1; |
|
119 autoWrite = false; |
|
120 serial = 0; |
|
121 } |
|
122 |
|
123 cDriverT6963C::~cDriverT6963C() |
|
124 { |
|
125 delete port; |
|
126 delete oldConfig; |
|
127 } |
|
128 |
|
129 int cDriverT6963C::Init() |
|
130 { |
|
131 int x; |
|
132 |
|
133 width = config->width; |
|
134 if (width <= 0) |
|
135 width = 240; |
|
136 height = config->height; |
|
137 if (height <= 0) |
|
138 height = 128; |
|
139 |
|
140 // default values |
|
141 FS = 6; |
|
142 WRHI = kStandardWRHI; |
|
143 WRLO = kStandardWRLO; |
|
144 RDHI = kStandardRDHI; |
|
145 RDLO = kStandardRDLO; |
|
146 CEHI = kStandardCEHI; |
|
147 CELO = kStandardCELO; |
|
148 CDHI = kStandardCDHI; |
|
149 CDLO = kStandardCDLO; |
|
150 useAutoMode = true; |
|
151 useStatusCheck = true; |
|
152 |
|
153 for (unsigned int i = 0; i < config->options.size(); i++) |
|
154 { |
|
155 if (config->options[i].name == "FontSelect") |
|
156 { |
|
157 int fontSelect = atoi(config->options[i].value.c_str()); |
|
158 if (fontSelect == 6) |
|
159 FS = 6; |
|
160 else if (fontSelect == 8) |
|
161 FS = 8; |
|
162 else |
|
163 syslog(LOG_ERR, "%s error: font select %d not supported, using default (%d)!\n", |
|
164 config->name.c_str(), fontSelect, FS); |
|
165 } |
|
166 else if (config->options[i].name == "Wiring") |
|
167 { |
|
168 if (config->options[i].value == kWiringStandard) |
|
169 { |
|
170 WRHI = kStandardWRHI; |
|
171 WRLO = kStandardWRLO; |
|
172 RDHI = kStandardRDHI; |
|
173 RDLO = kStandardRDLO; |
|
174 CEHI = kStandardCEHI; |
|
175 CELO = kStandardCELO; |
|
176 CDHI = kStandardCDHI; |
|
177 CDLO = kStandardCDLO; |
|
178 } |
|
179 else if (config->options[i].value == kWiringWindows) |
|
180 { |
|
181 WRHI = kWindowsWRHI; |
|
182 WRLO = kWindowsWRLO; |
|
183 RDHI = kWindowsRDHI; |
|
184 RDLO = kWindowsRDLO; |
|
185 CEHI = kWindowsCEHI; |
|
186 CELO = kWindowsCELO; |
|
187 CDHI = kWindowsCDHI; |
|
188 CDLO = kWindowsCDLO; |
|
189 } |
|
190 else if (config->options[i].value == kWiringSerial) |
|
191 { |
|
192 serial = 1; |
|
193 WRHI = kSerialWRHI; |
|
194 WRLO = kSerialWRLO; |
|
195 RDHI = kSerialRDHI; |
|
196 RDLO = kSerialRDLO; |
|
197 CEHI = kSerialCEHI; |
|
198 CELO = kSerialCELO; |
|
199 CDHI = kSerialCDHI; |
|
200 CDLO = kSerialCDLO; |
|
201 } |
|
202 else |
|
203 syslog(LOG_ERR, "%s error: wiring %s not supported, using default (Standard)!\n", |
|
204 config->name.c_str(), config->options[i].value.c_str()); |
|
205 } |
|
206 else if (config->options[i].name == "AutoMode") |
|
207 { |
|
208 if (config->options[i].value == "yes") |
|
209 useAutoMode = true; |
|
210 else if (config->options[i].value == "no") |
|
211 useAutoMode = false; |
|
212 else |
|
213 syslog(LOG_ERR, "%s error: unknown auto mode setting %s, using default (%s)!\n", |
|
214 config->name.c_str(), config->options[i].value.c_str(), useAutoMode ? "yes" : "no"); |
|
215 } |
|
216 else if (config->options[i].name == "StatusCheck") |
|
217 { |
|
218 if (config->options[i].value == "yes") |
|
219 useStatusCheck = true; |
|
220 else if (config->options[i].value == "no") |
|
221 useStatusCheck = false; |
|
222 else |
|
223 syslog(LOG_ERR, "%s error: unknown status check setting %s, using default (%s)!\n", |
|
224 config->name.c_str(), config->options[i].value.c_str(), useStatusCheck ? "yes" : "no"); |
|
225 } |
|
226 } |
|
227 |
|
228 // setup lcd array (wanted state) |
|
229 newLCD = new unsigned char*[(width + (FS - 1)) / FS]; |
|
230 if (newLCD) |
|
231 { |
|
232 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
233 { |
|
234 newLCD[x] = new unsigned char[height]; |
|
235 memset(newLCD[x], 0, height); |
|
236 } |
|
237 } |
|
238 // setup lcd array (current state) |
|
239 oldLCD = new unsigned char*[(width + (FS - 1)) / FS]; |
|
240 if (oldLCD) |
|
241 { |
|
242 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
243 { |
|
244 oldLCD[x] = new unsigned char[height]; |
|
245 memset(oldLCD[x], 0, height); |
|
246 } |
|
247 } |
|
248 |
|
249 if (config->device == "") |
|
250 { |
|
251 // use DirectIO |
|
252 if (port->Open(config->port) != 0) |
|
253 return -1; |
|
254 uSleep(10); |
|
255 } |
|
256 else |
|
257 { |
|
258 // use ppdev |
|
259 if (port->Open(config->device.c_str()) != 0) |
|
260 return -1; |
|
261 } |
|
262 |
|
263 // disable chip |
|
264 // disable reading from LCD |
|
265 // disable writing to LCD |
|
266 // command/status mode |
|
267 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
268 port->SetDirection(kForward); // make 8-bit parallel port an output port |
|
269 |
|
270 // Test ECP mode |
|
271 if (bidirectLPT == 1) |
|
272 { |
|
273 syslog(LOG_DEBUG, "%s: Testing ECP mode...\n", config->name.c_str()); |
|
274 int i = 0; |
|
275 int ecp_input; |
|
276 port->SetDirection(kReverse); |
|
277 for (int i = 0; i < 100; i++) |
|
278 { |
|
279 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // wr, ce, cd, rd |
|
280 T6963CSetControl(WRHI | CELO | CDHI | RDLO); |
|
281 T6963CSetControl(WRHI | CELO | CDHI | RDLO); |
|
282 T6963CSetControl(WRHI | CELO | CDHI | RDLO); |
|
283 ecp_input = port->ReadData(); |
|
284 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
285 if ((ecp_input & 0x03) == 0x03) |
|
286 break; |
|
287 } |
|
288 port->SetDirection(kForward); |
|
289 if (i >= 100) |
|
290 { |
|
291 syslog(LOG_DEBUG, "%s: ECP mode not working! -> is now disabled\n", config->name.c_str()); |
|
292 bidirectLPT = 0; |
|
293 } |
|
294 else |
|
295 syslog(LOG_DEBUG, "%s: working!\n", config->name.c_str()); |
|
296 } |
|
297 |
|
298 T6963CCommandWord(kSetGraphicHomeAddress, kGraphicBase); |
|
299 if (width % FS == 0) |
|
300 T6963CCommandWord(kSetGraphicArea, width / FS); |
|
301 else |
|
302 T6963CCommandWord(kSetGraphicArea, width / FS + 1); |
|
303 |
|
304 T6963CCommand(kSetMode | kModeOr | kModeInternalCG); |
|
305 |
|
306 T6963CDisplayMode(kDisplayModeText, false); |
|
307 T6963CDisplayMode(kDisplayModeGraphic, true); |
|
308 T6963CDisplayMode(kDisplayModeCursor, false); |
|
309 T6963CDisplayMode(kDisplayModeBlink, false); |
|
310 |
|
311 port->Release(); |
|
312 |
|
313 *oldConfig = *config; |
|
314 |
|
315 // clear display |
|
316 Clear(); |
|
317 |
|
318 syslog(LOG_INFO, "%s: T6963 initialized.\n", config->name.c_str()); |
|
319 return 0; |
|
320 } |
|
321 |
|
322 int cDriverT6963C::DeInit() |
|
323 { |
|
324 int x; |
|
325 // free lcd array (wanted state) |
|
326 if (newLCD) |
|
327 { |
|
328 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
329 { |
|
330 delete[] newLCD[x]; |
|
331 } |
|
332 delete[] newLCD; |
|
333 } |
|
334 // free lcd array (current state) |
|
335 if (oldLCD) |
|
336 { |
|
337 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
338 { |
|
339 delete[] oldLCD[x]; |
|
340 } |
|
341 delete[] oldLCD; |
|
342 } |
|
343 |
|
344 if (port->Close() != 0) |
|
345 return -1; |
|
346 return 0; |
|
347 } |
|
348 |
|
349 int cDriverT6963C::CheckSetup() |
|
350 { |
|
351 if (config->device != oldConfig->device || |
|
352 config->port != oldConfig->port || |
|
353 config->width != oldConfig->width || |
|
354 config->height != oldConfig->height) |
|
355 { |
|
356 DeInit(); |
|
357 Init(); |
|
358 return 0; |
|
359 } |
|
360 |
|
361 if (config->upsideDown != oldConfig->upsideDown || |
|
362 config->invert != oldConfig->invert) |
|
363 { |
|
364 oldConfig->upsideDown = config->upsideDown; |
|
365 oldConfig->invert = config->invert; |
|
366 return 1; |
|
367 } |
|
368 return 0; |
|
369 } |
|
370 |
|
371 void cDriverT6963C::Clear() |
|
372 { |
|
373 for (int x = 0; x < (width + (FS - 1)) / FS; x++) |
|
374 memset(newLCD[x], 0, height); |
|
375 } |
|
376 |
|
377 void cDriverT6963C::Set8Pixels(int x, int y, unsigned char data) |
|
378 { |
|
379 if (x >= width || y >= height) |
|
380 return; |
|
381 |
|
382 if (FS == 6) |
|
383 { |
|
384 unsigned char data1 = 0; |
|
385 unsigned char data2 = 0; |
|
386 unsigned char data3 = 0; |
|
387 |
|
388 if (!config->upsideDown) |
|
389 { |
|
390 // normal orientation |
|
391 x = x - (x % 8); |
|
392 data1 = data >> (2 + (x % 6)); |
|
393 if (x % 6 == 5) |
|
394 { |
|
395 data2 = data >> 1; |
|
396 data3 = data << 5; |
|
397 } |
|
398 else |
|
399 data2 = data << (4 - (x % 6)); |
|
400 |
|
401 newLCD[x / 6][y] |= data1; |
|
402 if (x / 6 + 1 < (width + 5) / 6) |
|
403 newLCD[x / 6 + 1][y] |= data2; |
|
404 if (x / 6 + 2 < (width + 5) / 6) |
|
405 if (x % 6 == 5) |
|
406 newLCD[x / 6 + 2][y] |= data3; |
|
407 } |
|
408 else |
|
409 { |
|
410 // upside down orientation |
|
411 x = width - 1 - x; |
|
412 y = height - 1 - y; |
|
413 x = x - (x % 8); |
|
414 data = ReverseBits(data); |
|
415 |
|
416 data1 = data >> (2 + (x % 6)); |
|
417 if (x % 6 == 5) |
|
418 { |
|
419 data2 = data >> 1; |
|
420 data3 = data << 5; |
|
421 } |
|
422 else |
|
423 data2 = data << (4 - (x % 6)); |
|
424 |
|
425 newLCD[x / 6][y] |= data1; |
|
426 if (x / 6 + 1 < (width + 5) / 6) |
|
427 newLCD[x / 6 + 1][y] |= data2; |
|
428 if (x / 6 + 2 < (width + 5) / 6) |
|
429 if (x % 6 == 5) |
|
430 newLCD[x / 6 + 2][y] |= data3; |
|
431 } |
|
432 } |
|
433 else |
|
434 { |
|
435 if (!config->upsideDown) |
|
436 { |
|
437 newLCD[x / 8][y] |= data; |
|
438 } |
|
439 else |
|
440 { |
|
441 x = width - 1 - x; |
|
442 y = height - 1 - y; |
|
443 newLCD[x / 8][y] |= ReverseBits(data); |
|
444 } |
|
445 } |
|
446 } |
|
447 |
|
448 void cDriverT6963C::Refresh(bool refreshAll) |
|
449 { |
|
450 int x,y; |
|
451 int addr = 0; |
|
452 |
|
453 if (CheckSetup() == 1) |
|
454 refreshAll = true; |
|
455 |
|
456 if (config->refreshDisplay > 0) |
|
457 { |
|
458 refreshCounter = (refreshCounter + 1) % config->refreshDisplay; |
|
459 if (!refreshAll && !refreshCounter) |
|
460 refreshAll = true; |
|
461 } |
|
462 |
|
463 port->Claim(); |
|
464 if (refreshAll) |
|
465 { |
|
466 // draw all |
|
467 T6963CCommandWord(kSetAddressPointer, kGraphicBase); |
|
468 if (useAutoMode) |
|
469 { |
|
470 T6963CCommand(kAutoWrite); |
|
471 autoWrite = true; |
|
472 } |
|
473 for (y = 0; y < height; y++) |
|
474 { |
|
475 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
476 { |
|
477 if (autoWrite) |
|
478 T6963CData((newLCD[x][y]) ^ (config->invert ? 0xff : 0x00)); |
|
479 else |
|
480 T6963CCommandByte(kDataWriteInc, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00)); |
|
481 oldLCD[x][y] = newLCD[x][y]; |
|
482 } |
|
483 } |
|
484 if (autoWrite) |
|
485 { |
|
486 T6963CCommand(kAutoReset); |
|
487 autoWrite = false; |
|
488 } |
|
489 // and reset RefreshCounter |
|
490 refreshCounter = 0; |
|
491 } |
|
492 else |
|
493 { |
|
494 // draw only the changed bytes |
|
495 |
|
496 bool cs = false; |
|
497 for (y = 0; y < height; y++) |
|
498 { |
|
499 for (x = 0; x < (width + (FS - 1)) / FS; x++) |
|
500 { |
|
501 if (oldLCD[x][y] != newLCD[x][y]) |
|
502 { |
|
503 if (!cs) |
|
504 { |
|
505 if (width % FS == 0) |
|
506 addr = (y * (width / FS)) + x; |
|
507 else |
|
508 addr = (y * (width / FS + 1)) + x; |
|
509 T6963CCommandWord(kSetAddressPointer, kGraphicBase + addr); |
|
510 if (useAutoMode) |
|
511 { |
|
512 T6963CCommand(kAutoWrite); |
|
513 autoWrite = true; |
|
514 } |
|
515 cs = true; |
|
516 } |
|
517 if (autoWrite) |
|
518 T6963CData((newLCD[x][y]) ^ (config->invert ? 0xff : 0x00)); |
|
519 else |
|
520 T6963CCommandByte(kDataWriteInc, (newLCD[x][y]) ^ (config->invert ? 0xff : 0x00)); |
|
521 oldLCD[x][y] = newLCD[x][y]; |
|
522 } |
|
523 else |
|
524 { |
|
525 if (autoWrite) |
|
526 { |
|
527 T6963CCommand(kAutoReset); |
|
528 autoWrite = false; |
|
529 } |
|
530 cs = false; |
|
531 } |
|
532 } |
|
533 } |
|
534 if (autoWrite) |
|
535 { |
|
536 T6963CCommand(kAutoReset); |
|
537 autoWrite = false; |
|
538 } |
|
539 } |
|
540 port->Release(); |
|
541 } |
|
542 |
|
543 void cDriverT6963C::T6963CSetControl(unsigned char flags) |
|
544 { |
|
545 unsigned char status = port->ReadControl(); |
|
546 status &= 0xF0; // mask 4 bits |
|
547 status |= flags; // add new flags |
|
548 port->WriteControl(status); |
|
549 } |
|
550 |
|
551 void cDriverT6963C::T6963CDSPReady() |
|
552 { |
|
553 int input = 0; |
|
554 |
|
555 port->SetDirection(kReverse); |
|
556 if (bidirectLPT == 1) |
|
557 { |
|
558 for (int i = 0; i < 10; i++) |
|
559 { |
|
560 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
561 T6963CSetControl(WRHI | CELO | CDHI | RDLO); |
|
562 input = port->ReadData(); |
|
563 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
564 if (!autoWrite && (input & 3) == 3) |
|
565 break; |
|
566 if (autoWrite && (input & 8) == 8) |
|
567 break; |
|
568 } |
|
569 } |
|
570 else |
|
571 { |
|
572 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
573 T6963CSetControl(WRHI | CELO | CDHI | RDLO); |
|
574 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); |
|
575 } |
|
576 port->SetDirection(kForward); |
|
577 } |
|
578 |
|
579 void cDriverT6963C::T6963CData(unsigned char data) |
|
580 { |
|
581 if (serial) |
|
582 { |
|
583 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); |
|
584 for (int i = 128; i; i>>=1) |
|
585 { |
|
586 if (data & i) |
|
587 { |
|
588 T6963CSetControl(WRLO | CEHI | CDHI | RDLO); |
|
589 T6963CSetControl(WRHI | CEHI | CDHI | RDLO); |
|
590 } |
|
591 else |
|
592 { |
|
593 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); |
|
594 T6963CSetControl(WRHI | CEHI | CDLO | RDLO); |
|
595 } |
|
596 } |
|
597 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CD down (data) |
|
598 T6963CSetControl(WRLO | CELO | CDLO | RDLO); // CE down |
|
599 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CE up |
|
600 } |
|
601 else |
|
602 { |
|
603 if (useStatusCheck) |
|
604 T6963CDSPReady(); |
|
605 T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CD down (data) |
|
606 T6963CSetControl(WRLO | CELO | CDLO | RDHI); // CE & WR down |
|
607 port->WriteData(data); |
|
608 T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CE & WR up again |
|
609 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CD up again |
|
610 } |
|
611 } |
|
612 |
|
613 void cDriverT6963C::T6963CCommand(unsigned char cmd) |
|
614 { |
|
615 if (serial) |
|
616 { |
|
617 syslog(LOG_DEBUG, "Serial cmd out: "); |
|
618 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); |
|
619 for (int i = 128; i; i>>=1) |
|
620 { |
|
621 if (cmd & i) |
|
622 { |
|
623 T6963CSetControl(WRLO | CEHI | CDHI | RDLO); |
|
624 T6963CSetControl(WRHI | CEHI | CDHI | RDLO); |
|
625 } |
|
626 else |
|
627 { |
|
628 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); |
|
629 T6963CSetControl(WRHI | CEHI | CDLO | RDLO); |
|
630 } |
|
631 } |
|
632 T6963CSetControl(WRLO | CEHI | CDHI | RDLO); // CD up (command) |
|
633 T6963CSetControl(WRLO | CELO | CDHI | RDLO); // CE down |
|
634 T6963CSetControl(WRLO | CEHI | CDHI | RDLO); // CE up |
|
635 T6963CSetControl(WRLO | CEHI | CDLO | RDLO); // CD down |
|
636 } |
|
637 else |
|
638 { |
|
639 if (useStatusCheck) |
|
640 T6963CDSPReady(); |
|
641 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CD up (command) |
|
642 T6963CSetControl(WRLO | CELO | CDHI | RDHI); // CE & WR down |
|
643 port->WriteData(cmd); |
|
644 T6963CSetControl(WRHI | CEHI | CDHI | RDHI); // CE & WR up again |
|
645 T6963CSetControl(WRHI | CEHI | CDLO | RDHI); // CD down again |
|
646 } |
|
647 } |
|
648 |
|
649 void cDriverT6963C::T6963CCommandByte(unsigned char cmd, unsigned char data) |
|
650 { |
|
651 T6963CData(data); |
|
652 T6963CCommand(cmd); |
|
653 } |
|
654 |
|
655 void cDriverT6963C::T6963CCommand2Bytes(unsigned char cmd, unsigned char data1, unsigned char data2) |
|
656 { |
|
657 T6963CData(data1); |
|
658 T6963CData(data2); |
|
659 T6963CCommand(cmd); |
|
660 } |
|
661 |
|
662 void cDriverT6963C::T6963CCommandWord(unsigned char cmd, unsigned short data) |
|
663 { |
|
664 T6963CData(data % 256); |
|
665 T6963CData(data >> 8); |
|
666 T6963CCommand(cmd); |
|
667 } |
|
668 |
|
669 void cDriverT6963C::T6963CDisplayMode(unsigned char mode, bool enable) |
|
670 { |
|
671 if (enable) |
|
672 displayMode |= mode; |
|
673 else |
|
674 displayMode &= ~mode; |
|
675 T6963CCommand(kSetDisplayMode | displayMode); |
|
676 } |
|
677 |
|
678 } |