root/tags/0.10.0/drv_Noritake.c

Revision 547, 11.2 kB (checked in by reinelt, 4 years ago)

[lcd4linux @ 2005-05-08 04:32:43 by reinelt]
CodingStyle? added and applied

Line 
1/* $Id: drv_Noritake.c,v 1.4 2005/05/08 04:32:44 reinelt Exp $
2 *
3 * Driver for a Noritake GU128x32-311 graphical display.
4 *
5 * Copyright (C) 2005 Julien Aube <ob@obconseil.net>
6 * Copyright (C) 2005 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
7 *
8 * This file is part of LCD4Linux.
9 *
10 * LCD4Linux is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * LCD4Linux is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * $Log: drv_Noritake.c,v $
25 * Revision 1.4  2005/05/08 04:32:44  reinelt
26 * CodingStyle added and applied
27 *
28 * Revision 1.3  2005/05/05 08:36:12  reinelt
29 * changed SELECT to SLCTIN
30 *
31 * Revision 1.2  2005/05/04 07:18:44  obconseil
32 * Driver modified according to Michels's recommendations :
33 *
34 * - Suppressed linux/parport.h depandancy. It was not needed anyway.
35 * - Compile-time disable the wait_busy polling function, replaced with a time wait.
36 * - Replaced the hardwire_* calls by their wire_* equivalent, to adapt other wirings.
37 * - Created a "Models" structure, containing parameters for the display.
38 * - Other cleanups, to remove compile-time warnings.
39 *
40 * Revision 1.1  2005/05/04 05:42:38  reinelt
41 * Noritake driver added
42 *
43 */
44
45/*
46 * *** Noritake Itron GU128x32-311 ***
47 * A 128x32 VFD (Vacuum Fluorescent Display).
48 * It is driver by a Hitachi microcontroller, with a specific
49 * firmware.
50 * The datasheet can be easily found on the internet by searching for the
51 * the name of the display, it's a PDF file that describe the timing, and
52 * the protocol to communicate with the Hitachi microcontroller.
53 *
54 * The display support 2 modes (that can be mutiplexed), one text mode
55 * thanks to an integrated character generator, and provide 4 lines of
56 * 21 caracters.
57 * There is also a graphical mode that can be used to switch on or off
58 * each one if the 128x32 pixels. (monochrome).
59 *
60 * The protocol include the possibility to clear the display memory quickly,
61 * change the luminosity, swich the display on or off (without affecting the
62 * content of the memory) and finally change the "page" or the caracter
63 * generator. Two pages are available in the ROM, all the characters are
64 * listed in the documentation.
65 *
66 * This driver support only the character mode at the moment.
67 * A future release will support the graphical mode as an option.
68 *
69 * This driver is released under the GPL.
70 */
71
72/*
73 *
74 * exported fuctions:
75 *
76 * struct DRIVER drv_Noritake
77 *
78 */
79
80#include "config.h"
81
82#include <stdlib.h>
83#include <unistd.h>
84#include <string.h>
85
86#include "debug.h"
87#include "cfg.h"
88#include "qprintf.h"
89#include "plugin.h"
90#include "widget.h"
91#include "widget_text.h"
92#include "widget_icon.h"
93#include "widget_bar.h"
94#include "drv.h"
95#include "udelay.h"
96#include "drv_generic_text.h"
97#include "drv_generic_parport.h"
98
99
100static char Name[] = "Noritake";
101
102typedef struct {
103    int type;
104    char *name;
105    int rows;
106    int cols;
107    int xres;
108    int yrex;
109    int goto_cost;
110    int protocol;
111} MODEL;
112
113static int Model, Protocol;
114static MODEL Models[] = {
115    {0x01, "GU311", 4, 21, 6, 8, 5, 1},
116    {0x02, "GU311_Graphic", 4, 21, 6, 8, 6, 1},
117    {0xff, "Unknown", -1, -1, -1, -1, -1, -1}
118};
119
120static unsigned char SIGNAL_CS; /* Chip select, OUTPUT, negative logic, pport AUTOFEED */
121static unsigned char SIGNAL_WR; /* Write        OUTPUT, negative logic, pport STOBE */
122static unsigned char SIGNAL_RESET;  /* Reset,       OUTPUT, negative logic, pport INIT */
123static unsigned char SIGNAL_BLANK;  /* Blank,       OUTPUT , negative logic, pport SELECT-IN */
124                                                            /* static unsigned char SIGNAL_BUSY; *//* Busy,        INPUT , positive logic, pport BUSY, not used */
125                                                             /* static unsigned char SIGNAL_FRP; *//* Frame Pulse, INPUT , positive logic, pport ACK, not used */
126void (*drv_Noritake_clear) (void);
127
128/* Data port is positive logic */
129
130
131/****************************************/
132/***  hardware dependant functions    ***/
133/****************************************/
134
135/* Low-level parport driving functions */
136
137/* This function was used to pool the BUSY line on the parallel port, which
138can be linked to the BUSY line on the display. But since it works
139with a timed wait, this function is not necessary, and is kept just in case.*/
140#if 0
141static void drv_GU311_wait_busy(void)
142{
143    char c;
144
145    c = drv_generic_parport_status();
146    while ((c & SIGNAL_BUSY) == 0) {
147  ndelay(200);    /* Wait 100ns before next consultation of BUSY line
148           if the first one was not successful */
149  c = drv_generic_parport_status();
150    }
151}
152#endif
153
154
155static void drv_GU311_send_char(char c)
156{
157    //drv_GU311_wait_busy(); /* ensuite the display is ready to take the command */
158    /* Disabled because all the cables does not have the busy line linked. */
159    drv_generic_parport_data(c);
160    ndelay(30);     /* delay to ensure data line stabilisation on long cables */
161    drv_generic_parport_control(SIGNAL_WR, 0);  /* write line to enable */
162    ndelay(150);    /* data hold time */
163    drv_generic_parport_control(SIGNAL_WR, 0xff); /* write line to disable */
164    ndelay(75);     /* From spec : minimum time before next command */
165}
166
167static void drv_GU311_send_string(char *str, int size)
168{
169    int i;
170    for (i = 0; i < size; i++)
171  drv_GU311_send_char(str[i]);
172
173}
174
175/* Command-string elaboration functions */
176static void drv_GU311_make_text_string(const int row, const int col, const char *data, int len)
177{
178    static char cmd[96] = { 0x01, 'C', 0, 0, 'S', 0 };
179    unsigned char start_addr;
180
181    /* Cols are 0x00..0x15, on 4 lines. */
182    start_addr = (0x16 * row) + col;
183    if (start_addr > 0x57)
184  return;
185    if (len > 0x57)
186  return;
187
188    cmd[2] = start_addr;
189    cmd[3] = len;
190
191    memcpy(cmd + 5, data, len);
192
193    drv_GU311_send_string(cmd, len + 5);
194
195}
196
197/* API functions */
198
199static void drv_GU311_clear(void)
200{
201    static char clear_cmd[] = { 0x01, 'O', 'P' };
202    drv_GU311_send_string(clear_cmd, sizeof(clear_cmd));
203    ndelay(500);    /* Delay for execution - this command is the longuest */
204}
205
206
207static void drv_GU311_write(const int row, const int col, const char *data, int len)
208{
209    drv_GU311_make_text_string(row, col, data, len);
210}
211
212
213static void drv_GU311_reset(void)
214{
215    drv_generic_parport_control(SIGNAL_RESET, 0); /* initiate reset */
216    ndelay(1000);   /* reset hold time 1ms */
217    drv_generic_parport_control(SIGNAL_RESET, 0xff);
218    ndelay(200000);   /* reset ready time 200ms */
219
220}
221
222
223static int drv_GU311_start(const char *section)
224{
225    char cmd[3] = { 0x01, 'O' };
226
227    /* Parallel port opening and association */
228    if (drv_generic_parport_open(section, Name) < 0)
229  return -1;
230    if ((SIGNAL_CS = drv_generic_parport_wire_ctrl("CS", "AUTOFD")) == 0xff)
231  return -1;
232    if ((SIGNAL_WR = drv_generic_parport_wire_ctrl("WR", "STROBE")) == 0xff)
233  return -1;
234    if ((SIGNAL_RESET = drv_generic_parport_wire_ctrl("RESET", "INIT")) == 0xff)
235  return -1;
236    if ((SIGNAL_BLANK = drv_generic_parport_wire_ctrl("BLANK", "SLCTIN")) == 0xff)
237  return -1;
238    /* SIGNAL_BUSY=PARPORT_STATUS_BUSY; *//* Not currently needed */
239    /* SIGNAL_FRP=PARPORT_STATUS_ACK;   *//* Not currently needed */
240
241    /* Signals configuration */
242    drv_generic_parport_direction(0); /* parallel port in output mode */
243    drv_generic_parport_control(SIGNAL_CS | SIGNAL_WR | SIGNAL_RESET | SIGNAL_BLANK, 0xff);
244    /* All lines to "deactivate", -> 1 level on the wire */
245    drv_generic_parport_control(SIGNAL_CS, 0);  /* CS to 0 all the time, write done by WR */
246    drv_GU311_reset();
247
248    /* Ready for commands from now on. */
249
250    /* Display configuration */
251    cmd[2] = '0';
252    drv_GU311_send_string(cmd, sizeof(cmd));  /* Select char. page 0 */
253    cmd[2] = 'Q';
254    drv_GU311_send_string(cmd, sizeof(cmd));  /* Select 'Quick Mode' */
255    cmd[2] = 'a';
256    drv_GU311_send_string(cmd, sizeof(cmd));  /* Brightness at 100% */
257    cmd[2] = 'T';
258    drv_GU311_send_string(cmd, sizeof(cmd));  /* Ensure display ON */
259
260    drv_Noritake_clear();
261    return 0;
262}
263
264
265
266static int drv_Noritake_start(const char *section)
267{
268    char *model = 0;
269    int i;
270    model = cfg_get(section, "Model", NULL);
271    if (model != NULL && *model != '\0') {
272  for (i = 0; Models[i].type != 0xff; i++) {
273      if (strcasecmp(Models[i].name, model) == 0)
274    break;
275  }
276  if (Models[i].type == 0xff) {
277      error("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source());
278      return -1;
279  }
280  Model = i;
281  info("%s: using model '%s'", Name, Models[Model].name);
282    } else {
283  error("%s: no '%s.Model' entry from %s", Name, section, cfg_source());
284  return -1;
285    }
286
287    DROWS = Models[Model].rows;
288    DCOLS = Models[Model].cols;
289    XRES = Models[Model].xres;
290    YRES = Models[Model].xres;
291    GOTO_COST = Models[Model].goto_cost;
292    Protocol = Models[Model].protocol;
293    /* display preferences */
294    CHARS = 0;      /* number of user-defineable characters */
295    CHAR0 = 0;      /* ASCII of first user-defineable char */
296
297
298
299    /* real worker functions */
300    drv_Noritake_clear = drv_GU311_clear;
301    if (Models[Model].type == 0x01) {
302  drv_generic_text_real_write = drv_GU311_write;
303    } else {
304  error("%s: Unsupported display. Currently supported are : GU311.", Name);
305  return -1;
306    }
307    return drv_GU311_start(section);
308}
309
310
311/****************************************/
312/***            plugins               ***/
313/****************************************/
314
315/* none */
316
317
318/****************************************/
319/***        widget callbacks          ***/
320/****************************************/
321
322
323/* using drv_generic_text_draw(W) */
324
325
326/****************************************/
327/***        exported functions        ***/
328/****************************************/
329
330
331/* list models */
332int drv_Noritake_list(void)
333{
334    printf("GU311 GU311_Graphic");
335    return 0;
336}
337
338
339/* initialize driver & display */
340int drv_Noritake_init(const char *section, const int quiet)
341{
342    WIDGET_CLASS wc;
343    int ret;
344
345    /* start display */
346    if ((ret = drv_Noritake_start(section)) != 0)
347  return ret;
348
349    /* initialize generic text driver */
350    if ((ret = drv_generic_text_init(section, Name)) != 0)
351  return ret;
352
353    /* register text widget */
354    wc = Widget_Text;
355    wc.draw = drv_generic_text_draw;
356    widget_register(&wc);
357
358    /* register plugins */
359    /* none */
360
361    if (!quiet) {
362  char buffer[40];
363  qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS);
364  if (drv_generic_text_greet(buffer, NULL)) {
365      sleep(3);
366      drv_Noritake_clear();
367  }
368    }
369
370    return 0;
371}
372
373
374/* close driver & display */
375int drv_Noritake_quit(const int quiet)
376{
377
378    info("%s: shutting down.", Name);
379
380    /* clear display */
381    drv_Noritake_clear();
382
383    /* say goodbye... */
384    if (!quiet) {
385  drv_generic_text_greet("goodbye!", NULL);
386    }
387
388    drv_generic_parport_close();
389    drv_generic_text_quit();
390    return (0);
391}
392
393
394DRIVER drv_Noritake = {
395  name:Name,
396  list:drv_Noritake_list,
397  init:drv_Noritake_init,
398  quit:drv_Noritake_quit,
399};
Note: See TracBrowser for help on using the browser.