1
/* This is the LCDproc driver for Cwlinux devices (http://www.cwlinux.com)
1
/** \file server/drivers/CwLnx.c
2
* LCDd \c CwLnx driver for CwLinux devices (http://www.cwlinux.com).
3
Applicable Data Sheets:
5
/* Applicable Data Sheets:
4
6
- http://www.cwlinux.com/downloads/cw1602/cw1602-manual.pdf
5
7
- http://www.cwlinux.com/downloads/lcd/cw12232-manual.pdf
7
9
Copyright (C) 2002, Andrew Ip
11
2006,7,8 Peter Marschall
11
13
This program is free software; you can redistribute it and/or modify
12
14
it under the terms of the GNU General Public License as published by
122
125
static void CwLnx_linewrap(int fd, int on);
123
126
static void CwLnx_autoscroll(int fd, int on);
124
127
static void CwLnx_hidecursor(int fd);
128
static void CwLnx_set_char_unrestricted(Driver *drvthis, int n, unsigned char *dat);
127
131
#define LCD_CMD 254
132
136
#define LCD_LIGHT_OFF 70
133
137
#define LCD_LIGHT_BRIGHTNESS 65
134
138
#define LCD_CLEAR 88
135
#define LCD_SET_INSERT 71
136
#define LCD_INIT_INSERT 72
139
#define LCD_SET_INSERT 71 /* go to X,Y */
140
#define LCD_INIT_INSERT 72 /* go to home */
137
141
#define LCD_SET_BAUD 57
138
142
#define LCD_ENABLE_WRAP 67
139
143
#define LCD_DISABLE_WRAP 68
140
144
#define LCD_SETCHAR 78
141
145
#define LCD_ENABLE_SCROLL 81
142
146
#define LCD_DISABLE_SCROLL 82
143
#define LCD_OFF_CURSOR 72
147
#define LCD_SOFT_RESET 86
148
#define LCD_OFF_CURSOR 72 /* is this correct? */
149
#define LCD_UNDERLINE_CURSOR_ON 74 /* set cursor on at X,Y */
150
#define LCD_UNDERLINE_CURSOR_OFF 75
151
#define LCD_MOVE_CURSOR_LEFT 76
152
#define LCD_MOVE_CURSOR_RIGHT 77
153
#define LCD_INVERSE_TEXT_ON 102
154
#define LCD_INVERSE_TEXT_OFF 103
145
156
#define LCD_PUT_PIXEL 112
146
157
#define LCD_CLEAR_PIXEL 113
148
159
#define DELAY 2000 /* 2 milli sec */
149
#define UPDATE_DELAY 0 /* 1 imicro sec */
150
#define SETUP_DELAY 1 /* 2 micro sec */
160
#define UPDATE_DELAY 20000 /* 20 milliseconds */
161
#define SETUP_DELAY 20000 /* 20 milliseconds */
163
#define MOVE_COST 5 /* # bytes for most move-to ops */
154
165
static int Write_LCD(int fd, char *c, int size)
157
168
int retries = 30;
160
171
rc = write(fd, c, size);
176
} else if (rc == 0 || (rc < 0 && errno == EAGAIN)) { /* would have blocked */
181
} while (size > 0 && --retries > 0);
165
} while (--retries > 0);
410
439
MODULE_EXPORT int
411
440
CwLnx_init(Driver *drvthis)
413
struct termios portset_save;
415
442
char device[200] = DEFAULT_DEVICE;
416
443
int speed = DEFAULT_SPEED;
417
444
char size[200] = DEFAULT_SIZE;
450
477
/* Read config file */
452
/* Which model is it (1602 or 12232)? */
479
/* Which model is it (1602, 12232 or 12832)? */
453
480
tmp = drvthis->config_get_int(drvthis->name, "Model", 0, 12232);
454
481
debug(RPT_INFO, "%s: Model (in config) is '%d'", __FUNCTION__, tmp);
455
if ((tmp != 1602) && (tmp != 12232)) {
482
if ((tmp != 1602) && (tmp != 12232) && (tmp != 12832)) {
457
report(RPT_WARNING, "%s: Model must be 12232 or 1602; using default %d",
484
report(RPT_WARNING, "%s: Model must be 12232, 12832 or 1602; using default %d",
458
485
drvthis->name, tmp);
470
497
default_speed = DEFAULT_SPEED_12232;
471
498
p->cellwidth = DEFAULT_CELL_WIDTH_12232;
472
499
p->cellheight = DEFAULT_CELL_HEIGHT_12232;
500
} else if (p->model == 12832) {
501
default_size = DEFAULT_SIZE_12832;
502
default_speed = DEFAULT_SPEED_12832;
503
p->cellwidth = DEFAULT_CELL_WIDTH_12832;
504
p->cellheight = DEFAULT_CELL_HEIGHT_12832;
475
507
/* Which device should be used */
577
609
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
612
Since we don't know what speed the display is using when
613
we first connect to it, configure the port for the speed
614
we don't want to use, send a command to switch the display
615
to the speed we want to use, and flush the command.
579
618
Init_Port(p->fd);
580
tcgetattr(p->fd, &portset_save);
582
Setup_Port(p->fd, speed);
619
if (speed == B9600) {
620
Setup_Port(p->fd, B19200);
586
p->fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY);
588
report(RPT_ERR, "%s: open(%s) failed (%s)", drvthis->name, device, strerror(errno));
623
Setup_Port(p->fd, B9600);
591
report(RPT_INFO, "%s: opened display on %s", drvthis->name, device);
593
628
Init_Port(p->fd);
595
629
Setup_Port(p->fd, speed);
596
631
CwLnx_hidecursor(p->fd);
597
632
CwLnx_linewrap(p->fd, 1);
598
633
CwLnx_autoscroll(p->fd, 0);
712
747
PrivateData *p = drvthis->private_data;
750
int iUpdate = 0, jUpdate = 0;
751
unsigned char *firstUpdate = NULL, *lastUpdate = NULL;
717
753
unsigned char *q = p->framebuf;
718
754
unsigned char *r = p->backingstore;
720
756
for (i = 0; i < p->height; i++) {
721
757
for (j = 0; j < p->width; j++) {
722
758
if ((*q == *r) && !((0 < *q) && (*q < 16))) {
726
/* Draw characters that have changed, as well
727
* as custom characters. We know not if a custom
728
* character has changed. */
730
Set_Insert(p->fd, i, j);
733
Write_LCD(p->fd, (char *) q, 1);
759
if (firstUpdate && q - lastUpdate > MOVE_COST) {
760
Set_Insert(p->fd, iUpdate, jUpdate);
761
Write_LCD(p->fd, (char *) firstUpdate,
762
lastUpdate - firstUpdate + 1);
763
firstUpdate = lastUpdate = NULL;
778
Set_Insert(p->fd, iUpdate, jUpdate);
779
Write_LCD(p->fd, (char *) firstUpdate,
780
lastUpdate - firstUpdate + 1);
739
783
memcpy(p->backingstore, p->framebuf, p->width * p->height);
785
if (p->backlight != p->saved_backlight ||
786
p->brightness != p->saved_brightness) {
788
Backlight_Brightness(p->fd, 1);
790
Backlight_Brightness(p->fd, 1 + p->brightness * 6 / 900); /* 90% and up is full brightness */
792
p->saved_backlight = p->backlight;
793
p->saved_brightness = p->brightness;
744
798
* Print a character on the screen at position (x,y).
745
799
* The upper-left corner is (1,1), the lower-right corner is (p->width, p->height).
904
958
for (i = 1; i <= p->cellwidth; i++) {
905
959
// fill pixel columns from left to right.
906
960
memset(hBar, 0xFF & ~((1 << (p->cellwidth - i)) - 1), sizeof(hBar));
961
#if defined(SEAMLESS_HBARS)
962
CwLnx_set_char_unrestricted(drvthis, i+1, hBar);
907
964
CwLnx_set_char(drvthis, i+1, hBar);
1082
* Identical to CwLnx_set_char, but it doesn't restrict the 12232 to
1083
* using only 5 of its 6 columns. Full 6-column mode is required
1084
* for seamless H-bars.
1087
#if defined(SEAMLESS_HBARS)
1089
CwLnx_set_char_unrestricted(Driver *drvthis, int n, unsigned char *dat)
1091
PrivateData *p = drvthis->private_data;
1096
if ((n <= 0) || (n > CwLnx_get_free_chars(drvthis)))
1102
rc = Write_LCD(p->fd, &c, 1);
1104
rc = Write_LCD(p->fd, &c, 1);
1106
rc = Write_LCD(p->fd, &c, 1);
1108
if (p->model == 1602) { // the character model
1109
unsigned char mask = (1 << p->cellwidth) - 1;
1112
for (row = 0; row < p->cellheight; row++) {
1113
c = dat[row] & mask;
1114
Write_LCD(p->fd, &c, 1);
1116
} else if ((p->model == 12232) || (p->model == 12832)) { // graphical models
1119
for (col = p->cellwidth - 1; col >= 0; col--) {
1123
for (row = p->cellheight - 1; row >= 0; row--) {
1125
letter |= ((dat[row] >> col) & 1);
1130
Write_LCD(p->fd, &c, 1);
1135
rc = Write_LCD(p->fd, &c, 1);
1024
1141
* Place an icon on the screen.
1025
1142
* \param drvthis Pointer to driver structure.
1026
1143
* \param x Horizontal character position (column).
1027
1144
* \param y Vertical character position (row).
1028
1145
* \param icon synbolic value representing the icon.
1029
* \return Information whether the icon is handled here or needs to be handled by the server core.
1146
* \retval 0 Icon has been successfully defined/written.
1147
* \retval <0 Server core shall define/write the icon.
1031
1149
MODULE_EXPORT int
1032
1150
CwLnx_icon(Driver *drvthis, int x, int y, int icon)
1270
* Get next key from the KeyRing.
1388
* Get key from the device.
1271
1389
* \param drvthis Pointer to driver structure.
1272
* \return String representation of the key.
1390
* \return String representation of the key;
1391
* \c NULL if nothing available / unmapped key.
1274
1393
MODULE_EXPORT const char *
1275
1394
CwLnx_get_key(Driver *drvthis)