~siretart/lcd4linux/debian

« back to all changes in this revision

Viewing changes to drv_Noritake.c

  • Committer: Reinhard Tartler
  • Date: 2011-04-27 17:24:15 UTC
  • mto: This revision was merged to the branch mainline in revision 750.
  • Revision ID: siretart@tauware.de-20110427172415-6n4aptmvmz0eztvm
Tags: upstream-0.11.0~svn1143
ImportĀ upstreamĀ versionĀ 0.11.0~svn1143

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 $
 
3
 * 
 
4
 * Driver for a Noritake GU128x32-311 graphical display.
 
5
 * 
 
6
 * Copyright (C) 2005 Julien Aube <ob@obconseil.net>
 
7
 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
 
8
 *
 
9
 * This file is part of LCD4Linux.
 
10
 *
 
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)
 
14
 * any later version.
 
15
 *
 
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.
 
20
 *
 
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.
 
24
 *
 
25
 */
 
26
 
 
27
/*
 
28
 * *** Noritake Itron GU128x32-311 ***
 
29
 * A 128x32 VFD (Vacuum Fluorescent Display).
 
30
 * It is driver by a Hitachi microcontroller, with a specific 
 
31
 * firmware. 
 
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.
 
35
 * 
 
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 
 
38
 * 21 caracters.
 
39
 * There is also a graphical mode that can be used to switch on or off
 
40
 * each one if the 128x32 pixels. (monochrome).
 
41
 * 
 
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.
 
47
 *
 
48
 * This driver support only the character mode at the moment.
 
49
 * A future release will support the graphical mode as an option.
 
50
 * 
 
51
 * This driver is released under the GPL.
 
52
 */
 
53
 
 
54
/* 
 
55
 *
 
56
 * exported fuctions:
 
57
 *
 
58
 * struct DRIVER drv_Noritake
 
59
 *
 
60
 */
 
61
 
 
62
#include "config.h"
 
63
 
 
64
#include <stdlib.h>
 
65
#include <unistd.h>
 
66
#include <string.h>
 
67
 
 
68
#include "debug.h"
 
69
#include "cfg.h"
 
70
#include "qprintf.h"
 
71
#include "plugin.h"
 
72
#include "widget.h"
 
73
#include "widget_text.h"
 
74
#include "widget_icon.h"
 
75
#include "widget_bar.h"
 
76
#include "drv.h"
 
77
#include "udelay.h"
 
78
#include "drv_generic_text.h"
 
79
#include "drv_generic_parport.h"
 
80
 
 
81
 
 
82
static char Name[] = "Noritake";
 
83
 
 
84
typedef struct {
 
85
    int type;
 
86
    char *name;
 
87
    int rows;
 
88
    int cols;
 
89
    int xres;
 
90
    int yrex;
 
91
    int goto_cost;
 
92
    int protocol;
 
93
} MODEL;
 
94
 
 
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}
 
100
};
 
101
 
 
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 */
 
106
 
 
107
#if 0
 
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 */
 
110
#endif
 
111
 
 
112
void (*drv_Noritake_clear) (void);
 
113
 
 
114
/* Data port is positive logic */
 
115
 
 
116
 
 
117
/****************************************/
 
118
/***  hardware dependant functions    ***/
 
119
/****************************************/
 
120
 
 
121
/* Low-level parport driving functions */
 
122
 
 
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.*/
 
126
#if 0
 
127
static void drv_GU311_wait_busy(void)
 
128
{
 
129
    char c;
 
130
 
 
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();
 
136
    }
 
137
}
 
138
#endif
 
139
 
 
140
 
 
141
static void drv_GU311_send_char(char c)
 
142
{
 
143
#if 0
 
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 */
 
146
#endif
 
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 */
 
153
}
 
154
 
 
155
static void drv_GU311_send_string(char *str, int size)
 
156
{
 
157
    int i;
 
158
    for (i = 0; i < size; i++)
 
159
        drv_GU311_send_char(str[i]);
 
160
 
 
161
}
 
162
 
 
163
/* Command-string elaboration functions */
 
164
static void drv_GU311_make_text_string(const int row, const int col, const char *data, int len)
 
165
{
 
166
    static char cmd[96] = { 0x01, 'C', 0, 0, 'S', 0 };
 
167
    unsigned char start_addr;
 
168
 
 
169
    /* Cols are 0x00..0x15, on 4 lines. */
 
170
    start_addr = (0x16 * row) + col;
 
171
    if (start_addr > 0x57)
 
172
        return;
 
173
    if (len > 0x57)
 
174
        return;
 
175
 
 
176
    cmd[2] = start_addr;
 
177
    cmd[3] = len;
 
178
 
 
179
    memcpy(cmd + 5, data, len);
 
180
 
 
181
    drv_GU311_send_string(cmd, len + 5);
 
182
 
 
183
}
 
184
 
 
185
/* API functions */
 
186
 
 
187
static void drv_GU311_clear(void)
 
188
{
 
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 */
 
192
}
 
193
 
 
194
 
 
195
static void drv_GU311_write(const int row, const int col, const char *data, int len)
 
196
{
 
197
    drv_GU311_make_text_string(row, col, data, len);
 
198
}
 
199
 
 
200
 
 
201
static void drv_GU311_reset(void)
 
202
{
 
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 */
 
207
 
 
208
}
 
209
 
 
210
 
 
211
static int drv_GU311_start(const char *section)
 
212
{
 
213
    char cmd[3] = { 0x01, 'O' };
 
214
 
 
215
    /* Parallel port opening and association */
 
216
    if (drv_generic_parport_open(section, Name) < 0)
 
217
        return -1;
 
218
    if ((SIGNAL_CS = drv_generic_parport_wire_ctrl("CS", "AUTOFD")) == 0xff)
 
219
        return -1;
 
220
    if ((SIGNAL_WR = drv_generic_parport_wire_ctrl("WR", "STROBE")) == 0xff)
 
221
        return -1;
 
222
    if ((SIGNAL_RESET = drv_generic_parport_wire_ctrl("RESET", "INIT")) == 0xff)
 
223
        return -1;
 
224
    if ((SIGNAL_BLANK = drv_generic_parport_wire_ctrl("BLANK", "SLCTIN")) == 0xff)
 
225
        return -1;
 
226
    /* SIGNAL_BUSY=PARPORT_STATUS_BUSY; *//* Not currently needed */
 
227
    /* SIGNAL_FRP=PARPORT_STATUS_ACK;   *//* Not currently needed */
 
228
 
 
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 */
 
234
    drv_GU311_reset();
 
235
 
 
236
    /* Ready for commands from now on. */
 
237
 
 
238
    /* Display configuration */
 
239
    cmd[2] = '0';
 
240
    drv_GU311_send_string(cmd, sizeof(cmd));    /* Select char. page 0 */
 
241
    cmd[2] = 'Q';
 
242
    drv_GU311_send_string(cmd, sizeof(cmd));    /* Select 'Quick Mode' */
 
243
    cmd[2] = 'a';
 
244
    drv_GU311_send_string(cmd, sizeof(cmd));    /* Brightness at 100% */
 
245
    cmd[2] = 'T';
 
246
    drv_GU311_send_string(cmd, sizeof(cmd));    /* Ensure display ON */
 
247
 
 
248
    drv_Noritake_clear();
 
249
    return 0;
 
250
}
 
251
 
 
252
 
 
253
 
 
254
static int drv_Noritake_start(const char *section)
 
255
{
 
256
    char *model = 0;
 
257
    int i;
 
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)
 
262
                break;
 
263
        }
 
264
        if (Models[i].type == 0xff) {
 
265
            error("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source());
 
266
            return -1;
 
267
        }
 
268
        Model = i;
 
269
        info("%s: using model '%s'", Name, Models[Model].name);
 
270
    } else {
 
271
        error("%s: no '%s.Model' entry from %s", Name, section, cfg_source());
 
272
        return -1;
 
273
    }
 
274
 
 
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 */
 
284
 
 
285
 
 
286
 
 
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;
 
291
    } else {
 
292
        error("%s: Unsupported display. Currently supported are : GU311.", Name);
 
293
        return -1;
 
294
    }
 
295
    return drv_GU311_start(section);
 
296
}
 
297
 
 
298
 
 
299
/****************************************/
 
300
/***            plugins               ***/
 
301
/****************************************/
 
302
 
 
303
/* none */
 
304
 
 
305
 
 
306
/****************************************/
 
307
/***        widget callbacks          ***/
 
308
/****************************************/
 
309
 
 
310
 
 
311
/* using drv_generic_text_draw(W) */
 
312
 
 
313
 
 
314
/****************************************/
 
315
/***        exported functions        ***/
 
316
/****************************************/
 
317
 
 
318
 
 
319
/* list models */
 
320
int drv_Noritake_list(void)
 
321
{
 
322
    printf("GU311 GU311_Graphic");
 
323
    return 0;
 
324
}
 
325
 
 
326
 
 
327
/* initialize driver & display */
 
328
int drv_Noritake_init(const char *section, const int quiet)
 
329
{
 
330
    WIDGET_CLASS wc;
 
331
    int ret;
 
332
 
 
333
    info("%s: %s", Name, "$Rev: 771 $");
 
334
 
 
335
    /* start display */
 
336
    if ((ret = drv_Noritake_start(section)) != 0)
 
337
        return ret;
 
338
 
 
339
    /* initialize generic text driver */
 
340
    if ((ret = drv_generic_text_init(section, Name)) != 0)
 
341
        return ret;
 
342
 
 
343
    /* register text widget */
 
344
    wc = Widget_Text;
 
345
    wc.draw = drv_generic_text_draw;
 
346
    widget_register(&wc);
 
347
 
 
348
    /* register plugins */
 
349
    /* none */
 
350
 
 
351
    if (!quiet) {
 
352
        char buffer[40];
 
353
        qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
 
354
        if (drv_generic_text_greet(buffer, NULL)) {
 
355
            sleep(3);
 
356
            drv_Noritake_clear();
 
357
        }
 
358
    }
 
359
 
 
360
    return 0;
 
361
}
 
362
 
 
363
 
 
364
/* close driver & display */
 
365
int drv_Noritake_quit(const int quiet)
 
366
{
 
367
 
 
368
    info("%s: shutting down.", Name);
 
369
 
 
370
    /* clear display */
 
371
    drv_Noritake_clear();
 
372
 
 
373
    /* say goodbye... */
 
374
    if (!quiet) {
 
375
        drv_generic_text_greet("goodbye!", NULL);
 
376
    }
 
377
 
 
378
    drv_generic_parport_close();
 
379
    drv_generic_text_quit();
 
380
    return (0);
 
381
}
 
382
 
 
383
 
 
384
DRIVER drv_Noritake = {
 
385
    .name = Name,
 
386
    .list = drv_Noritake_list,
 
387
    .init = drv_Noritake_init,
 
388
    .quit = drv_Noritake_quit,
 
389
};