source: npl/mediabox/lcdproc_edwin/src/server/drivers/wirz-sli.c @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 11.7 KB
Line 
1/*      wirz-sli.c -- Source file for LCDproc Wirz SLI driver
2        Copyright (C) 1999 Horizon Technologies-http://horizon.pair.com/
3        Written by Bryan Rittmeyer <bryanr@pair.com> - Released under GPL
4                       
5        LCD info: http://www.wirz.com/sli/                               */
6
7#include <stdlib.h>
8#include <stdio.h>
9#include <unistd.h>
10#include <termios.h>
11#include <fcntl.h>
12#include <string.h>
13#include <errno.h>
14#include "lcd.h"
15#include "wirz-sli.h"
16#include "drv_base.h"
17
18#include "../../shared/debug.h"
19#include "../../shared/str.h"
20
21static int custom=0;
22typedef enum {
23        hbar = 1,
24        vbar = 2,
25        bign = 4,
26        beat = 8 } custom_type;
27
28static int fd;
29static char lastframe[32];
30
31lcd_logical_driver *sli;
32
33/////////////////////////////////////////////////////////////////
34// Opens com port and sets baud correctly...
35//
36int sli_init(lcd_logical_driver *driver, char *args)
37{
38   char *argv[64];
39   int argc;
40   struct termios portset;
41   int i;
42   int tmp;
43   char out[2];
44
45   char device[256] = "/dev/lcd";
46   int speed=B19200;
47   
48   sli = driver;
49
50   //debug("sli_init: Args(all): %s\n", args);
51   
52   argc = get_args(argv, args, 64);
53
54   /*
55   for(i=0; i<argc; i++)
56   {
57      printf("Arg(%i): %s\n", i, argv[i]);
58   }
59   */
60   
61   for(i=0; i<argc; i++)
62   {
63      //printf("Arg(%i): %s\n", i, argv[i]);
64      if(0 == strcmp(argv[i], "-d")  ||
65         0 == strcmp(argv[i], "--device"))
66      {
67         if(i + 1 > argc) {
68            fprintf(stderr, "sli_init: %s requires an argument\n",
69                    argv[i]);
70            return -1;
71         }
72         strcpy(device, argv[++i]);
73      }
74      else if(0 == strcmp(argv[i], "-s")  ||
75         0 == strcmp(argv[i], "--speed"))
76      {
77         if(i + 1 > argc) {
78            fprintf(stderr, "sli_init: %s requires an argument\n",
79                    argv[i]);
80            return -1;
81         }
82         tmp = atoi(argv[++i]);
83         if(tmp==1200) speed=B1200;
84         else if(tmp==2400) speed=B2400;
85         else if(tmp==9600) speed=B9600;
86         else if(tmp==19200) speed=B19200;
87         else if(tmp==38400) speed=B38400;
88         else if(tmp==57600) speed=B57600;
89         else if(tmp==115200) speed=B115200;
90         else {
91            fprintf(stderr, "sli_init: %s argument must be 1200, 2400, 9600, 19200, 38400, 57600, or 115200. Using default value (19200).\n",
92                    argv[i]);
93         }
94      }
95      else if(0 == strcmp(argv[i], "-h")  ||
96         0 == strcmp(argv[i], "--help"))
97      {
98         printf("LCDproc Wirz SLI LCD driver\n"
99                "\t-d\t--device\tSelect the output device to use [/dev/lcd]\n"
100                "\t-s\t--speed\t\tSet the communication speed [19200]\n"
101                "\t-h\t--help\t\tShow this help information\n");
102         return -1;
103      }
104      else
105      {
106         printf("Invalid parameter: %s\n", argv[i]);
107      }
108     
109   }
110   
111   // Set up io port correctly, and open it...
112   fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
113   if (fd == -1)
114   {
115      fprintf(stderr, "sli_init: failed (%s)\n", strerror(errno));
116      return -1;
117   }
118   //else fprintf(stderr, "sli_init: opened device %s\n", device);
119   tcgetattr(fd, &portset);
120   // This is necessary in Linux, but does not exist in irix.
121#ifndef IRIX
122   cfmakeraw(&portset);
123#endif
124   cfsetospeed(&portset, speed);
125   tcsetattr(fd, TCSANOW, &portset);
126
127   /* Initialize SLI using autobaud detection, and then turn off cursor
128      and clear screen */
129   usleep(150000); /* 150ms delay to allow SLI to power on */
130   out[0]=13; /* CR for SLI autobaud */
131   write(fd, out, 1);
132   usleep(3000); /* 3ms delay.. wait for it to autobaud */
133   out[0]=0x0FE;
134   out[1]=0x00C; /* No cursor */
135   write(fd, out, 2);
136   out[0]=0x0FE;
137   out[1]=0x001; /* Clear LCD, not sure if this belongs here */
138   write(fd, out, 2);
139
140   
141   if(!driver->framebuf)
142   {
143      fprintf(stderr, "sli_init: No frame buffer.\n");
144      driver->close();
145      return -1;
146   }
147
148   // Set LCD parameters (I use a 16x2 LCD) -- small but still useful
149   // Its also much cheaper than the higher quality Matrix Orbital modules
150   // Currently, $30 for interface kit and 16x2 non-backlit LCD...
151   driver->wid = 15;
152   driver->hgt = 2;
153
154
155   // Set the functions the driver supports...
156
157   driver->clear =      (void *)-1;
158   driver->string =     (void *)-1;
159   driver->chr =        (void *)-1;
160   driver->vbar =       sli_vbar;
161   driver->init_vbar =  sli_init_vbar;
162   driver->hbar =       sli_hbar;
163   driver->init_hbar =  sli_init_hbar;
164   driver->num =        (void *)-1;
165   driver->init_num =   (void *)-1;
166
167   driver->init =       sli_init;
168   driver->close =      sli_close;
169   driver->flush =      sli_flush;
170   driver->flush_box =  sli_flush_box;
171   driver->contrast =   (void *)-1;
172   driver->backlight =  (void *)-1;
173   driver->set_char =   sli_set_char;
174   driver->icon =       sli_icon;
175   driver->draw_frame = sli_draw_frame;
176
177   driver->getkey =     (void *)-1;
178 
179   return fd;
180}
181
182
183/* Clean-up */
184void sli_close()
185{
186  close(fd);
187
188  if(sli->framebuf) free(sli->framebuf);
189
190  sli->framebuf = NULL;
191}
192
193
194void sli_flush()
195{
196   sli_draw_frame(lcd.framebuf);
197}
198
199
200/* no bounds checking is done in MtxOrb.c (which I shamelessly ripped)
201   this is bad imho, so I added it.. may remove later
202   speed is not a huge issue though, this isnt a
203   device driver or anything ;)                           */
204void sli_flush_box(int lft, int top, int rgt, int bot)
205{
206  int y;
207  char out[2]; /* Why does the matrix driver allocate so much here? */
208
209  /* simple bounds checking */
210  if((top>lcd.hgt)|(bot>lcd.hgt))
211    return;
212
213  if((lft>lcd.wid)|(rgt>lcd.wid))
214    return;
215 
216//  printf("Flush (%i,%i)-(%i,%i)\n", lft, top, rgt, bot);
217
218/* I like having hex, everywhere and all the time */
219  for(y=top; y<=bot; y++)
220    {
221      if(y==1)
222        sprintf(out, "%c%c", 0x0FE, 0x080+lft);
223      if(y==2)
224        sprintf(out, "%c%c", 0x0FE, 0x0C0+lft);
225      write(fd, out, 0x002);
226      write(fd, lcd.framebuf+(y*lcd.wid)+lft, rgt-lft+1);
227    }
228 
229 
230}
231
232/////////////////////////////////////////////////////////////////
233// Prints a character on the lcd display, at position (x,y).  The
234// upper-left is (1,1), and the lower right should be (20,4).
235//
236void sli_chr(int x, int y, char c)
237{
238  y--;
239  x--;
240 
241  lcd.framebuf[(y*lcd.wid) + x] = c;
242}
243
244
245/////////////////////////////////////////////////////////////////
246// Sets up for vertical bars.  Call before lcd.vbar()
247//
248
249/* Because of the way we do this (custom characters in CGRAM)
250   we can't have both horizontal and vertical bars at once...
251   this also appears to be a limitation of the Matrix Orbital
252   modules so I will assume that all client coders know about it
253
254   I think it would be cool to use triangular stuff for the non-full
255   characters, so that you can do both bar types at once.. maybe I
256   will release a new version of the SLI driver that attempts this */
257
258void sli_init_vbar()
259{
260  char a[] = {
261    0,0,0,0,0,
262    0,0,0,0,0,
263    0,0,0,0,0,
264    0,0,0,0,0,
265    0,0,0,0,0,
266    0,0,0,0,0,
267    0,0,0,0,0,
268    1,1,1,1,1,
269  };
270  char b[] = {
271    0,0,0,0,0,
272    0,0,0,0,0,
273    0,0,0,0,0,
274    0,0,0,0,0,
275    0,0,0,0,0,
276    0,0,0,0,0,
277    1,1,1,1,1,
278    1,1,1,1,1,
279  };
280  char c[] = {
281    0,0,0,0,0,
282    0,0,0,0,0,
283    0,0,0,0,0,
284    0,0,0,0,0,
285    0,0,0,0,0,
286    1,1,1,1,1,
287    1,1,1,1,1,
288    1,1,1,1,1,
289  };
290  char d[] = {
291    0,0,0,0,0,
292    0,0,0,0,0,
293    0,0,0,0,0,
294    0,0,0,0,0,
295    1,1,1,1,1,
296    1,1,1,1,1,
297    1,1,1,1,1,
298    1,1,1,1,1,
299  };
300  char e[] = {
301    0,0,0,0,0,
302    0,0,0,0,0,
303    0,0,0,0,0,
304    1,1,1,1,1,
305    1,1,1,1,1,
306    1,1,1,1,1,
307    1,1,1,1,1,
308    1,1,1,1,1,
309  };
310  char f[] = {
311    0,0,0,0,0,
312    0,0,0,0,0,
313    1,1,1,1,1,
314    1,1,1,1,1,
315    1,1,1,1,1,
316    1,1,1,1,1,
317    1,1,1,1,1,
318    1,1,1,1,1,
319  };
320  char g[] = {
321    0,0,0,0,0,
322    1,1,1,1,1,
323    1,1,1,1,1,
324    1,1,1,1,1,
325    1,1,1,1,1,
326    1,1,1,1,1,
327    1,1,1,1,1,
328    1,1,1,1,1,
329  };
330
331  if(custom!=vbar) {
332    sli_set_char(1,a);
333    sli_set_char(2,b);
334    sli_set_char(3,c);
335    sli_set_char(4,d);
336    sli_set_char(5,e);
337    sli_set_char(6,f);
338    sli_set_char(7,g);
339    custom=vbar;
340  }
341}
342
343/////////////////////////////////////////////////////////////////
344// Inits horizontal bars...
345//
346void sli_init_hbar()
347{
348
349  char a[] = {
350    1,0,0,0,0,
351    1,0,0,0,0,
352    1,0,0,0,0,
353    1,0,0,0,0,
354    1,0,0,0,0,
355    1,0,0,0,0,
356    1,0,0,0,0,
357    1,0,0,0,0,
358  };
359  char b[] = {
360    1,1,0,0,0,
361    1,1,0,0,0,
362    1,1,0,0,0,
363    1,1,0,0,0,
364    1,1,0,0,0,
365    1,1,0,0,0,
366    1,1,0,0,0,
367    1,1,0,0,0,
368  };
369  char c[] = {
370    1,1,1,0,0,
371    1,1,1,0,0,
372    1,1,1,0,0,
373    1,1,1,0,0,
374    1,1,1,0,0,
375    1,1,1,0,0,
376    1,1,1,0,0,
377    1,1,1,0,0,
378  };
379  char d[] = {
380    1,1,1,1,0,
381    1,1,1,1,0,
382    1,1,1,1,0,
383    1,1,1,1,0,
384    1,1,1,1,0,
385    1,1,1,1,0,
386    1,1,1,1,0,
387    1,1,1,1,0,
388  };
389
390  if(custom!=hbar) {
391    sli_set_char(1,a);
392    sli_set_char(2,b);
393    sli_set_char(3,c);
394    sli_set_char(4,d);
395    custom=hbar;
396  }
397}
398
399/////////////////////////////////////////////////////////////////
400// Draws a vertical bar...
401//
402
403/* It would be cool if you could start a vertical bar at any y
404   like the horizontal bar routine can start at any x... but
405   since we only have 2 lines anyway this is rather pointless
406   for me to add                                               */
407
408void sli_vbar(int x, int len)
409{
410  char map[9] = {32, 1, 2, 3, 4, 5, 6, 7, 255 };
411 
412
413  int y;
414  for(y=lcd.hgt; y > 0 && len>0; y--)
415    {
416      if(len >= lcd.cellhgt) sli_chr(x, y, 255);
417      else sli_chr(x, y, map[len]);
418
419      len -= lcd.cellhgt;
420    }
421 
422}
423
424/////////////////////////////////////////////////////////////////
425// Draws a horizontal bar to the right.
426//
427void sli_hbar(int x, int y, int len)
428{
429  char map[6] = { 32, 1, 2, 3, 4, 255  };
430
431  for(; x<=lcd.wid && len>0; x++)
432    {
433      if(len >= lcd.cellwid) sli_chr(x,y,255);
434      else sli_chr(x, y, map[len]);
435     
436      len -= lcd.cellwid;
437     
438    }
439
440}
441
442
443/////////////////////////////////////////////////////////////////
444// Sets a custom character from 0-7...
445//
446// For input, values > 0 mean "on" and values <= 0 are "off".
447//
448// The input is just an array of characters...
449//
450void sli_set_char(int n, char *dat)
451{
452  char out[2];
453  int row, col;
454  int letter;
455
456  /* SLI also has 8 user definable characters */
457  if(n < 0 || n > 7) return;
458  if(!dat) return;
459
460  /* Move cursor to CGRAM */
461  out[0]=0x0FE;
462  out[1]=0x040+8*n;
463  write(fd, out, 2);
464
465  for(row=0; row<lcd.cellhgt; row++)
466  {
467    letter = 0;
468    for(col=0; col<lcd.cellwid; col++)
469    {
470      letter <<= 1;
471      letter |= (dat[(row*lcd.cellwid) + col] > 0);
472    }
473    letter|=0x020; /* SLI can't accept CR, LF, etc in this character! */
474    write(fd, &letter, 1);
475  }
476
477  /* Move cursor back to DDRAM */
478  out[0]=0x0FE;
479  out[1]=0x080;
480  write(fd, out, 2);
481}
482
483
484void sli_icon(int which, char dest)
485{
486  char icons[3][5*8] = {
487   {
488     1,1,1,1,1,  // Empty Heart
489     1,0,1,0,1,
490     0,0,0,0,0,
491     0,0,0,0,0,
492     0,0,0,0,0,
493     1,0,0,0,1,
494     1,1,0,1,1,
495     1,1,1,1,1,
496   },   
497
498   {
499     1,1,1,1,1,  // Filled Heart
500     1,0,1,0,1,
501     0,1,0,1,0,
502     0,1,1,1,0,
503     0,1,1,1,0,
504     1,0,1,0,1,
505     1,1,0,1,1,
506     1,1,1,1,1,
507   },
508   
509   {
510     0,0,0,0,0,  // Ellipsis
511     0,0,0,0,0,
512     0,0,0,0,0,
513     0,0,0,0,0,
514     0,0,0,0,0,
515     0,0,0,0,0,
516     0,0,0,0,0,
517     1,0,1,0,1,
518   },
519   
520  };
521 
522  if(custom==bign) custom=beat;
523  sli_set_char(dest, &icons[which][0]);
524}
525
526
527/////////////////////////////////////////////////////////////
528// Blasts a single frame onscreen, to the lcd...
529//
530// Input is a character array, sized lcd.wid*lcd.hgt
531//
532void sli_draw_frame(char *dat)
533{
534  char out[2]; /* Again, why does the Matrix driver allocate so much here? */
535  int y;
536 
537  if(!dat) return;
538
539  /*
540  out[0]=0x0FE;
541  out[1]=0x001;
542  write(fd, out, 2);
543  */
544
545  /* Don't update if we have no new data
546     this keeps me from getting a migraine
547     (just like those copyleft penguin mints... mmmmmm)  */
548
549  //   if (!strncmp(dat,lastframe,32)) /* Nothing has changed */
550  //     return;
551
552  /* Do the actual refresh */
553  out[0]=0x0FE;
554  out[1]=0x080;
555  write(fd, out, 2);
556  write(fd, &dat[0], 16);
557  usleep(10);
558  write(fd, &dat[16],15);
559
560  //   strncpy(lastframe,dat,32); // Update lastframe...
561
562}
Note: See TracBrowser for help on using the repository browser.