2 * Driver for serial connected hd44780 LCDs
3 * Copyright (C) 2006-2007 Matteo Pillon <matteo.pillon@gmail.com>
5 * Some parts are based on the original pic-an-lcd driver code
6 * Copyright (C) 1997, Matthias Prinke <m.prinke@trashcan.mcnet.de>
7 * 1998, Richard Rognlie <rrognlie@gamerz.net>
9 * 1999-2000, Benjamin Tse <blt@Comports.com>
11 * 2001-2002, Joris Robijn <joris@robijn.net>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include "hd44780-serial.h"
30 #include "hd44780-low.h"
39 #include <sys/types.h>
49 #define SERIAL_IF serial_interfaces[p->serial_type]
51 /* bitrate conversion */
52 unsigned int bitrate_conversion
[][2] = {
84 , { 1000000, B1000000
}
87 , { 1152000, B1152000
}
90 , { 1500000, B1500000
}
93 , { 2000000, B2000000
}
96 , { 2500000, B2500000
}
99 , { 3000000, B3000000
}
101 #if defined(B3500000)
102 , { 3500000, B3500000
}
104 #if defined(B4000000)
105 , { 4000000, B4000000
}
109 int convert_bitrate(unsigned int conf_bitrate
, size_t *bitrate
) {
111 for (counter
= 0; counter
< sizeof(bitrate_conversion
)/(2*sizeof(unsigned int)); counter
++)
112 if (bitrate_conversion
[counter
][0] == conf_bitrate
) {
113 *bitrate
= (size_t) bitrate_conversion
[counter
][1];
119 static int lastdisplayID
;
121 void serial_HD44780_senddata(PrivateData
*p
, unsigned char displayID
, unsigned char flags
, unsigned char ch
);
122 void serial_HD44780_backlight(PrivateData
*p
, unsigned char state
);
123 unsigned char serial_HD44780_scankeypad(PrivateData
*p
);
124 void serial_HD44780_close(PrivateData
*p
);
126 // initialize the driver
128 hd_init_serial(Driver
*drvthis
)
130 PrivateData
*p
= (PrivateData
*) drvthis
->private_data
;
132 struct termios portset
;
133 char device
[256] = DEFAULT_DEVICE
;
135 /* READ CONFIG FILE */
137 /* Get interface type */
139 char conf_serialif
[SERIALIF_NAME_LENGTH
];
141 strncpy(conf_serialif
, drvthis
->config_get_string(drvthis
->name
, "connectiontype", 0, ""), SERIALIF_NAME_LENGTH
);
142 conf_serialif
[SERIALIF_NAME_LENGTH
-1] = '\0';
144 for (counter
= 0; counter
< (sizeof(serial_interfaces
)/sizeof(SerialInterface
)); counter
++) {
145 if (strcasecmp(conf_serialif
, serial_interfaces
[counter
].name
) == 0) {
146 p
->serial_type
= counter
;
150 if (p
->serial_type
!= counter
) {
151 report(RPT_ERR
, "HD44780: serial: serial interface %s unknown", conf_serialif
);
152 report(RPT_ERR
, "HD44780: serial: available interfaces:");
153 for (counter
= 0; counter
< (sizeof(serial_interfaces
)/sizeof(SerialInterface
)); counter
++)
154 report(RPT_ERR
, " %s", serial_interfaces
[counter
].name
);
158 report(RPT_INFO
,"HD44780: serial: device type: %s", SERIAL_IF
.name
);
160 /* Check if user knows the capabilities of his hardware ;-) */
161 if (p
->have_keypad
&& !(SERIAL_IF
.keypad
)) {
162 report(RPT_ERR
, "HD44780: serial: keypad is not supported by %s", SERIAL_IF
.name
);
163 report(RPT_ERR
, "HD44780: serial: check your configuration file and disable it");
166 if (p
->have_backlight
&& !(SERIAL_IF
.backlight
)) {
167 report(RPT_ERR
, "HD44780: serial: backlight control is not supported by %s", SERIAL_IF
.name
);
168 report(RPT_ERR
, "HD44780: serial: check your configuration file and disable it");
173 unsigned int conf_bitrate
;
176 conf_bitrate
= drvthis
->config_get_int(drvthis
->name
, "Speed", 0, SERIAL_IF
.default_bitrate
);
178 conf_bitrate
= SERIAL_IF
.default_bitrate
;
179 if (convert_bitrate(conf_bitrate
, &bitrate
)) {
180 report(RPT_ERR
, "HD44780: serial: invalid configured bitrate speed");
183 report(RPT_INFO
,"HD44780: serial: using speed: %d", conf_bitrate
);
185 /* Get serial device to use */
186 strncpy(device
, drvthis
->config_get_string(drvthis
->name
, "device", 0, DEFAULT_DEVICE
), sizeof(device
));
187 device
[sizeof(device
)-1] = '\0';
188 report(RPT_INFO
,"HD44780: serial: using device: %s", device
);
190 /* Set up io port correctly, and open it... */
191 p
->fd
= open(device
, O_RDWR
| O_NOCTTY
| O_NDELAY
);
193 report(RPT_ERR
, "HD44780: serial: could not open device %s (%s)", device
, strerror(errno
));
197 /* Get serial device parameters */
198 tcgetattr(p
->fd
, &portset
);
200 /* We use RAW mode */
201 #ifdef HAVE_CFMAKERAW
204 portset
.c_cflag
|= CLOCAL
;
207 portset
.c_iflag
&= ~( IGNBRK
| BRKINT
| PARMRK
| ISTRIP
208 | INLCR
| IGNCR
| ICRNL
| IXON
);
209 portset
.c_oflag
&= ~OPOST
;
210 portset
.c_lflag
&= ~( ECHO
| ECHONL
| ICANON
| ISIG
| IEXTEN
);
211 portset
.c_cflag
&= ~( CSIZE
| PARENB
| CRTSCTS
);
212 portset
.c_cflag
|= CS8
| CREAD
| CLOCAL
;
215 cfsetospeed(&portset
, bitrate
);
216 cfsetispeed(&portset
, B0
);
218 /* Set TCSANOW mode of serial device */
219 tcsetattr(p
->fd
, TCSANOW
, &portset
);
223 /* Assign functions */
224 p
->hd44780_functions
->senddata
= serial_HD44780_senddata
;
225 p
->hd44780_functions
->backlight
= serial_HD44780_backlight
;
227 p
->hd44780_functions
->scankeypad
= serial_HD44780_scankeypad
;
228 p
->hd44780_functions
->close
= serial_HD44780_close
;
230 /* Do initialization */
231 if (SERIAL_IF
.if_bits
== 8) {
232 report(RPT_INFO
,"HD44780: serial: initializing with 8 bits interface");
233 common_init(p
, IF_8BIT
);
235 report(RPT_INFO
,"HD44780: serial: initializing with 4 bits interface");
236 common_init(p
, IF_4BIT
);
242 // serial_HD44780_senddata
244 serial_HD44780_senddata(PrivateData
*p
, unsigned char displayID
, unsigned char flags
, unsigned char ch
)
246 /* Filter illegally sent escape characters (for interfaces without data escape) */
247 if (flags
== RS_DATA
&& SERIAL_IF
.data_escape
== 0 && ch
== SERIAL_IF
.instruction_escape
)
250 if (flags
== RS_DATA
) {
251 /* Do we need a DATA indicator byte? */
252 if ((SERIAL_IF
.data_escape
!= '\0') &&
253 (ch
>= SERIAL_IF
.data_escape_min
) &&
254 (ch
< SERIAL_IF
.data_escape_max
) ||
255 (SERIAL_IF
.multiple_displays
&& displayID
!= lastdisplayID
)) {
256 write(p
->fd
, &SERIAL_IF
.data_escape
+ displayID
, 1);
258 write(p
->fd
, &ch
, 1);
261 write(p
->fd
, &SERIAL_IF
.instruction_escape
, 1);
262 write(p
->fd
, &ch
, 1);
264 lastdisplayID
= displayID
;
268 serial_HD44780_backlight(PrivateData
*p
, unsigned char state
)
270 unsigned char send
[1];
271 if (p
->have_backlight
) {
272 if (SERIAL_IF
.backlight_escape
) {
273 send
[0] = SERIAL_IF
.backlight_escape
;
274 write(p
->fd
, &send
, 1);
276 if (SERIAL_IF
.backlight_on
&& SERIAL_IF
.backlight_off
) {
277 send
[0] = state
? SERIAL_IF
.backlight_on
: SERIAL_IF
.backlight_off
;
280 send
[0] = state
? 0 : 0xFF;
282 write(p
->fd
, &send
, 1);
287 serial_HD44780_scankeypad(PrivateData
*p
)
289 unsigned char buffer
= 0;
290 char hangcheck
= 100;
292 read(p
->fd
, &buffer
, 1);
293 if (buffer
== SERIAL_IF
.keypad_escape
) {
294 while (hangcheck
> 0) {
295 /* Check if I can read another byte */
296 if (read(p
->fd
, &buffer
, 1) == 1) {
306 serial_HD44780_close(PrivateData
*p
)
308 if (SERIAL_IF
.end_code
)
309 write(p
->fd
, &SERIAL_IF
.end_code
, 1);