/* $Id: drv_Noritake.c,v 1.1 2005/05/04 05:42:38 reinelt Exp $ * * Driver for a Noritake GU128x32-311 graphical display. * * Copyright (C) 2005 Julien Aube * Copyright (C) 2005 The LCD4Linux Team * * This file is part of LCD4Linux. * * LCD4Linux is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * LCD4Linux is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Log: drv_Noritake.c,v $ * Revision 1.1 2005/05/04 05:42:38 reinelt * Noritake driver added * */ /* * *** Noritake Itron GU128x32-311 *** * A 128x32 VFD (Vacuum Fluorescent Display). * It is driver by a Hitachi microcontroller, with a specific * firmware. * The datasheet can be easily found on the internet by searching for the * the name of the display, it's a PDF file that describe the timing, and * the protocol to communicate with the Hitachi microcontroller. * * The display support 2 modes (that can be mutiplexed), one text mode * thanks to an integrated character generator, and provide 4 lines of * 21 caracters. * There is also a graphical mode that can be used to switch on or off * each one if the 128x32 pixels. (monochrome). * * The protocol include the possibility to clear the display memory quickly, * change the luminosity, swich the display on or off (without affecting the * content of the memory) and finally change the "page" or the caracter * generator. Two pages are available in the ROM, all the characters are * listed in the documentation. * * This driver support only the character mode at the moment. * A future release will support the graphical mode as an option. * * This driver is released under the GPL. */ /* * * exported fuctions: * * struct DRIVER drv_Noritake * */ #include "config.h" #include #include #include #include "debug.h" #include "cfg.h" #include "qprintf.h" #include "plugin.h" #include "widget.h" #include "widget_text.h" #include "widget_icon.h" #include "widget_bar.h" #include "drv.h" #include "udelay.h" #include "drv_generic_text.h" #include "drv_generic_parport.h" #include static char Name[]="Noritake"; static unsigned char SIGNAL_CS; /* Chip select, OUTPUT, negative logic, pport AUTOFEED */ static unsigned char SIGNAL_WR; /* Write OUTPUT, negative logic, pport STOBE */ static unsigned char SIGNAL_RESET; /* Reset, OUTPUT, negative logic, pport INIT */ static unsigned char SIGNAL_BLANK; /* Blank, OUTPUT , negative logic, pport SELECT-IN */ static unsigned char SIGNAL_BUSY; /* Busy, INPUT , positive logic, pport BUSY,*/ static unsigned char SIGNAL_FRP; /* Frame Pulse, INPUT , positive logic, pport ACK, not used */ void (*drv_Noritake_clear) (void) ; /* Data port is positive logic */ /****************************************/ /*** hardware dependant functions ***/ /****************************************/ /* Low-level parport driving functions */ static void drv_GU311_wait_busy(void) { char c; c = drv_generic_parport_status(); while ( (c & SIGNAL_BUSY) == 0 ) { ndelay(200); /* Wait 100ns before next consultation of BUSY line if the first one was not successful */ c = drv_generic_parport_status(); } } static void drv_GU311_send_char(char c) { //drv_GU311_wait_busy(); /* ensuite the display is ready to take the command */ /* Disabled because all the cables does not have the busy line linked. */ drv_generic_parport_data(c); ndelay(30); /* delay to ensure data line stabilisation on long cables */ drv_generic_parport_control(SIGNAL_WR,0); /* write line to enable */ ndelay(150); /* data hold time */ drv_generic_parport_control(SIGNAL_WR,0xff); /* write line to disable */ ndelay(75); /* From spec : minimum time before next command */ } static void drv_GU311_send_string(char * str, int size) { int i; for (i=0;i 0x57 ) return; if ( len > 0x57 ) return ; cmd[2] = start_addr; cmd[3] = len; memcpy(cmd+5,data,len); drv_GU311_send_string(cmd,len+5); } /* API functions */ static void drv_GU311_clear (void) { static char clear_cmd[] = { 0x01, 'O', 'P' }; drv_GU311_send_string( clear_cmd, sizeof(clear_cmd) ); ndelay(500); /* Delay for execution - this command is the longuest */ } static void drv_GU311_write (const int row, const int col, const char *data, int len) { drv_GU311_make_text_string(row,col,data, len); } static void drv_GU311_reset (void) { drv_generic_parport_control(SIGNAL_RESET,0); /* initiate reset */ ndelay(1000); /* reset hold time 1ms */ drv_generic_parport_control(SIGNAL_RESET,0xff); ndelay(200000); /* reset ready time 200ms */ } static int drv_GU311_start(const char *section, const int quiet) { char cmd[3] = { 0x01, 'O' }; DROWS = 4; DCOLS = 21; /* real worker functions */ drv_generic_text_real_write = drv_GU311_write; drv_Noritake_clear = drv_GU311_clear; /* Parallel port opening and association */ if (drv_generic_parport_open(section, Name) < 0) return -1; if ((SIGNAL_CS=drv_generic_parport_hardwire_ctrl ("CS", "AUTOFD"))==0xff) return -1; if ((SIGNAL_WR=drv_generic_parport_hardwire_ctrl ("WR", "STROBE"))==0xff) return -1; if ((SIGNAL_RESET=drv_generic_parport_hardwire_ctrl ("RESET", "INIT"))==0xff) return -1; if ((SIGNAL_BLANK=drv_generic_parport_hardwire_ctrl ("BLANK", "SELECT") )==0xff) return -1; SIGNAL_BUSY=PARPORT_STATUS_BUSY; SIGNAL_FRP=PARPORT_STATUS_ACK; /* Signals configuration */ drv_generic_parport_direction(0); /* parallel port in output mode */ drv_generic_parport_control(SIGNAL_CS|SIGNAL_WR|SIGNAL_RESET|SIGNAL_BLANK, 0xff); /* All lines to "deactivate", -> 1 level on the wire */ drv_generic_parport_control(SIGNAL_CS,0); /* CS to 0 all the time, write done by WR */ drv_GU311_reset(); /* Ready for commands from now on. */ /* Display configuration */ cmd[2] = '0' ; drv_GU311_send_string(cmd, sizeof(cmd) ); /* Select char. page 0 */ cmd[2] = 'Q' ; drv_GU311_send_string(cmd, sizeof(cmd) ); /* Select 'Quick Mode' */ cmd[2] = 'a' ; drv_GU311_send_string(cmd, sizeof(cmd) ); /* Brightness at 100% */ cmd[2] = 'T' ; drv_GU311_send_string(cmd, sizeof(cmd) ); /* Ensure display ON */ drv_Noritake_clear(); return 0; } static int drv_Noritake_start (const char *section, const int quiet) { char * model=0; model = cfg_get(section,"Model","GU311"); if ( model && (strcasecmp("GU311",model) == 0) ) return drv_GU311_start(section,quiet); error("%s : Unsupported display. Currently supported are : GU311.",Name); return -1; } /****************************************/ /*** plugins ***/ /****************************************/ /* none */ /****************************************/ /*** widget callbacks ***/ /****************************************/ /* using drv_generic_text_draw(W) */ /****************************************/ /*** exported functions ***/ /****************************************/ /* list models */ int drv_Noritake_list (void) { printf ("GU311 GU311_Graphic"); return 0; } /* initialize driver & display */ int drv_Noritake_init (const char *section, const int quiet) { WIDGET_CLASS wc; int ret; /* display preferences */ XRES = 6; /* pixel width of one char */ YRES = 8; /* pixel height of one char */ CHARS = 0; /* number of user-defineable characters */ CHAR0 = 0; /* ASCII of first user-defineable char */ GOTO_COST = 6; /* number of bytes a goto command requires */ /* start display */ if ((ret=drv_Noritake_start (section, quiet))!=0) return ret; /* initialize generic text driver */ if ((ret=drv_generic_text_init(section, Name))!=0) return ret; /* register text widget */ wc=Widget_Text; wc.draw=drv_generic_text_draw; widget_register(&wc); /* register plugins */ /* none */ if (!quiet) { char buffer[40]; qprintf(buffer, sizeof(buffer), "%s %dx%d", Name, DCOLS, DROWS); if (drv_generic_text_greet (buffer, NULL)) { sleep (3); drv_Noritake_clear(); } } return 0; } /* close driver & display */ int drv_Noritake_quit (const int quiet) { info("%s: shutting down.", Name); /* clear display */ drv_Noritake_clear(); /* say goodbye... */ if (!quiet) { drv_generic_text_greet ("goodbye!", NULL); } drv_generic_parport_close(); drv_generic_text_quit(); return (0); } DRIVER drv_Noritake = { name: Name, list: drv_Noritake_list, init: drv_Noritake_init, quit: drv_Noritake_quit, };