1
/* $Id: drv_Noritake.c 771 2007-02-25 12:27:26Z michael $
2
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/drv_Noritake.c $
4
* Driver for a Noritake GU128x32-311 graphical display.
6
* Copyright (C) 2005 Julien Aube <ob@obconseil.net>
7
* Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
9
* This file is part of LCD4Linux.
11
* LCD4Linux is free software; you can redistribute it and/or modify
12
* it under the terms of the GNU General Public License as published by
13
* the Free Software Foundation; either version 2, or (at your option)
16
* LCD4Linux is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
* GNU General Public License for more details.
21
* You should have received a copy of the GNU General Public License
22
* along with this program; if not, write to the Free Software
23
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28
* *** Noritake Itron GU128x32-311 ***
29
* A 128x32 VFD (Vacuum Fluorescent Display).
30
* It is driver by a Hitachi microcontroller, with a specific
32
* The datasheet can be easily found on the internet by searching for the
33
* the name of the display, it's a PDF file that describe the timing, and
34
* the protocol to communicate with the Hitachi microcontroller.
36
* The display support 2 modes (that can be mutiplexed), one text mode
37
* thanks to an integrated character generator, and provide 4 lines of
39
* There is also a graphical mode that can be used to switch on or off
40
* each one if the 128x32 pixels. (monochrome).
42
* The protocol include the possibility to clear the display memory quickly,
43
* change the luminosity, swich the display on or off (without affecting the
44
* content of the memory) and finally change the "page" or the caracter
45
* generator. Two pages are available in the ROM, all the characters are
46
* listed in the documentation.
48
* This driver support only the character mode at the moment.
49
* A future release will support the graphical mode as an option.
51
* This driver is released under the GPL.
58
* struct DRIVER drv_Noritake
73
#include "widget_text.h"
74
#include "widget_icon.h"
75
#include "widget_bar.h"
78
#include "drv_generic_text.h"
79
#include "drv_generic_parport.h"
82
static char Name[] = "Noritake";
95
static int Model, Protocol;
96
static MODEL Models[] = {
97
{0x01, "GU311", 4, 21, 6, 8, 5, 1},
98
{0x02, "GU311_Graphic", 4, 21, 6, 8, 6, 1},
99
{0xff, "Unknown", -1, -1, -1, -1, -1, -1}
102
static unsigned char SIGNAL_CS; /* Chip select, OUTPUT, negative logic, pport AUTOFEED */
103
static unsigned char SIGNAL_WR; /* Write OUTPUT, negative logic, pport STOBE */
104
static unsigned char SIGNAL_RESET; /* Reset, OUTPUT, negative logic, pport INIT */
105
static unsigned char SIGNAL_BLANK; /* Blank, OUTPUT , negative logic, pport SELECT-IN */
108
static unsigned char SIGNAL_BUSY; /* Busy, INPUT , positive logic, pport BUSY, not used */
109
static unsigned char SIGNAL_FRP; /* Frame Pulse, INPUT , positive logic, pport ACK, not used */
112
void (*drv_Noritake_clear) (void);
114
/* Data port is positive logic */
117
/****************************************/
118
/*** hardware dependant functions ***/
119
/****************************************/
121
/* Low-level parport driving functions */
123
/* This function was used to pool the BUSY line on the parallel port, which
124
can be linked to the BUSY line on the display. But since it works
125
with a timed wait, this function is not necessary, and is kept just in case.*/
127
static void drv_GU311_wait_busy(void)
131
c = drv_generic_parport_status();
132
while ((c & SIGNAL_BUSY) == 0) {
133
ndelay(200); /* Wait 100ns before next consultation of BUSY line
134
if the first one was not successful */
135
c = drv_generic_parport_status();
141
static void drv_GU311_send_char(char c)
144
/* Disabled because all the cables does not have the busy line linked. */
145
drv_GU311_wait_busy(); /* ensuite the display is ready to take the command */
147
drv_generic_parport_data(c);
148
ndelay(30); /* delay to ensure data line stabilisation on long cables */
149
drv_generic_parport_control(SIGNAL_WR, 0); /* write line to enable */
150
ndelay(150); /* data hold time */
151
drv_generic_parport_control(SIGNAL_WR, 0xff); /* write line to disable */
152
ndelay(75); /* From spec : minimum time before next command */
155
static void drv_GU311_send_string(char *str, int size)
158
for (i = 0; i < size; i++)
159
drv_GU311_send_char(str[i]);
163
/* Command-string elaboration functions */
164
static void drv_GU311_make_text_string(const int row, const int col, const char *data, int len)
166
static char cmd[96] = { 0x01, 'C', 0, 0, 'S', 0 };
167
unsigned char start_addr;
169
/* Cols are 0x00..0x15, on 4 lines. */
170
start_addr = (0x16 * row) + col;
171
if (start_addr > 0x57)
179
memcpy(cmd + 5, data, len);
181
drv_GU311_send_string(cmd, len + 5);
187
static void drv_GU311_clear(void)
189
static char clear_cmd[] = { 0x01, 'O', 'P' };
190
drv_GU311_send_string(clear_cmd, sizeof(clear_cmd));
191
ndelay(500); /* Delay for execution - this command is the longuest */
195
static void drv_GU311_write(const int row, const int col, const char *data, int len)
197
drv_GU311_make_text_string(row, col, data, len);
201
static void drv_GU311_reset(void)
203
drv_generic_parport_control(SIGNAL_RESET, 0); /* initiate reset */
204
ndelay(1000); /* reset hold time 1ms */
205
drv_generic_parport_control(SIGNAL_RESET, 0xff);
206
ndelay(200000); /* reset ready time 200ms */
211
static int drv_GU311_start(const char *section)
213
char cmd[3] = { 0x01, 'O' };
215
/* Parallel port opening and association */
216
if (drv_generic_parport_open(section, Name) < 0)
218
if ((SIGNAL_CS = drv_generic_parport_wire_ctrl("CS", "AUTOFD")) == 0xff)
220
if ((SIGNAL_WR = drv_generic_parport_wire_ctrl("WR", "STROBE")) == 0xff)
222
if ((SIGNAL_RESET = drv_generic_parport_wire_ctrl("RESET", "INIT")) == 0xff)
224
if ((SIGNAL_BLANK = drv_generic_parport_wire_ctrl("BLANK", "SLCTIN")) == 0xff)
226
/* SIGNAL_BUSY=PARPORT_STATUS_BUSY; *//* Not currently needed */
227
/* SIGNAL_FRP=PARPORT_STATUS_ACK; *//* Not currently needed */
229
/* Signals configuration */
230
drv_generic_parport_direction(0); /* parallel port in output mode */
231
drv_generic_parport_control(SIGNAL_CS | SIGNAL_WR | SIGNAL_RESET | SIGNAL_BLANK, 0xff);
232
/* All lines to "deactivate", -> 1 level on the wire */
233
drv_generic_parport_control(SIGNAL_CS, 0); /* CS to 0 all the time, write done by WR */
236
/* Ready for commands from now on. */
238
/* Display configuration */
240
drv_GU311_send_string(cmd, sizeof(cmd)); /* Select char. page 0 */
242
drv_GU311_send_string(cmd, sizeof(cmd)); /* Select 'Quick Mode' */
244
drv_GU311_send_string(cmd, sizeof(cmd)); /* Brightness at 100% */
246
drv_GU311_send_string(cmd, sizeof(cmd)); /* Ensure display ON */
248
drv_Noritake_clear();
254
static int drv_Noritake_start(const char *section)
258
model = cfg_get(section, "Model", NULL);
259
if (model != NULL && *model != '\0') {
260
for (i = 0; Models[i].type != 0xff; i++) {
261
if (strcasecmp(Models[i].name, model) == 0)
264
if (Models[i].type == 0xff) {
265
error("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source());
269
info("%s: using model '%s'", Name, Models[Model].name);
271
error("%s: no '%s.Model' entry from %s", Name, section, cfg_source());
275
DROWS = Models[Model].rows;
276
DCOLS = Models[Model].cols;
277
XRES = Models[Model].xres;
278
YRES = Models[Model].xres;
279
GOTO_COST = Models[Model].goto_cost;
280
Protocol = Models[Model].protocol;
281
/* display preferences */
282
CHARS = 0; /* number of user-defineable characters */
283
CHAR0 = 0; /* ASCII of first user-defineable char */
287
/* real worker functions */
288
drv_Noritake_clear = drv_GU311_clear;
289
if (Models[Model].type == 0x01) {
290
drv_generic_text_real_write = drv_GU311_write;
292
error("%s: Unsupported display. Currently supported are : GU311.", Name);
295
return drv_GU311_start(section);
299
/****************************************/
301
/****************************************/
306
/****************************************/
307
/*** widget callbacks ***/
308
/****************************************/
311
/* using drv_generic_text_draw(W) */
314
/****************************************/
315
/*** exported functions ***/
316
/****************************************/
320
int drv_Noritake_list(void)
322
printf("GU311 GU311_Graphic");
327
/* initialize driver & display */
328
int drv_Noritake_init(const char *section, const int quiet)
333
info("%s: %s", Name, "$Rev: 771 $");
336
if ((ret = drv_Noritake_start(section)) != 0)
339
/* initialize generic text driver */
340
if ((ret = drv_generic_text_init(section, Name)) != 0)
343
/* register text widget */
345
wc.draw = drv_generic_text_draw;
346
widget_register(&wc);
348
/* register plugins */
353
qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
354
if (drv_generic_text_greet(buffer, NULL)) {
356
drv_Noritake_clear();
364
/* close driver & display */
365
int drv_Noritake_quit(const int quiet)
368
info("%s: shutting down.", Name);
371
drv_Noritake_clear();
375
drv_generic_text_greet("goodbye!", NULL);
378
drv_generic_parport_close();
379
drv_generic_text_quit();
384
DRIVER drv_Noritake = {
386
.list = drv_Noritake_list,
387
.init = drv_Noritake_init,
388
.quit = drv_Noritake_quit,