/**************************************************************** lcd.c Linux lcd display driver via parallel printer port. Compile with: gcc lcd.c -o lcd Run as root: ./lcd * Copyright (C) 2009 Rick Matthews, Adelaide AUSTRALIA * * This program 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 of the License, or * (at your option) any later version. * * This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ************************** WIRING ******************************* LCD MODULE PARALLEL PORT USB POWER ----------------------------------------------------------------- pin 1 Ground pins 18 to 25 (ground) Ground pin 2 +5V +5V pin 3 Contrast pin 4 RS pin 1 (Strobe, ctrl bit 0) pin 5 R/W pin 14 (Auto LF, ctrl bit 1) pin 6 E pin 16 (-Init, ctrl bit 2) pin 7 bit 0 pin 2 (data bit 0) pin 8 bit 1 pin 3 (data bit 1) pin 9 bit 2 pin 4 (data bit 2) pin 10 bit 3 pin 5 (data bit 3) pin 11 bit 4 pin 6 (data bit 4) pin 12 bit 5 pin 7 (data bit 5) pin 13 bit 6 pin 8 (data bit 6) pin 14 bit 7 pin 9 (data bit 7) pin 15 *(+backlight) *(+5V) pin 16 *(Ground) *(Ground) *These pins only used for backlight on some modules - CHECK THIS THOROUGHLY!!! ********************* Parallel Port Control Byte ******************* 7 6 5 4 3 2 1 0 ------------------------------------------- - | - | - | - | - | E | RW | RS --> LCD module commands - | - | - |IRQ |sel |init| LF |strobe --> equivalent printer commands ************** LCD display initialization procedure **************** Power On - Wait for more then 30ms after VDD Rises to 4.5V Function Set RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 L = 0 1-Line Mode, 1 2-Line Mode. 0 0 0 0 1 1 L F * * F = 0 Display off, 1 Display on Wait for more then 39us Display ON / OFF Control D = 0 Display off, 1 Display on RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 C = 0 Cursor off, 1 Cursor on 0 0 0 0 0 0 1 D C B B = 0 Blink off, 1 Blink on Wait for more then 39us Display Clear RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 0 0 0 0 0 0 0 0 0 1 Wait for more then 1.53us Entry Mode Set RS RW DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 I/D = 0 Decrement mode, 1 Increment mode 0 0 0 0 0 0 0 1 I/D SH SH = 0 Entire shift off, 1 Entire shift on Initialization End Display Off Display Clear Entry Mode Set ************************Instruction set ************************* Instruction Code RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 Clear Display 0 0 0 0 0 0 0 0 0 1 Return Home 0 0 0 0 0 0 0 0 1 * Entry mode set 0 0 0 0 0 0 0 1 I/D SH Display On/Off 0 0 0 0 0 0 1 D C B Curs/Disp Shift 0 0 0 0 0 1 S/C R/L * * Function Set 0 0 0 0 1 DL N F * * Set CG Ram Addr 0 0 0 1 ACG Set DD Ram Addr 0 0 1 ADD Read BusyFlag&Addr 0 1 BF ADD Write CG or DD 1 0 AC Read CG or DD 1 1 Read * No Effect ( Don`t Care ) Remarks: I/D 1 Increment 0 Decrement DD RAM : Display Data RAM SH 1 Entire Shift on 0 Entire Shift off CG RAM : Character Generator RAM S/C 1 Display Shift 0 Cursor move ACG : CG RAM Address R/L 1 Shift to the Right 0 Shift to the Left ADD : CG RAM Addr : Corresponds to cursor Addr DL 1 8 Bits 0 4 Bits AC : Addr counter used for both DD and CG RAM Addr N 1 2 Lines 0 1 Lines F 1 5 x 11 Dots 0 5 x 8 Dots BF 1 Internally Operation 0 Can accept instruction D 1 display on 0 display off C 1 cursor on 0 cursor off B 1 blink on 0 blink off ************************* DD RAM Address ************************ Display position 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1-Line 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 2-Line 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F *****************************************************************/ #include #include #include #include #include #define DATA 0x378 #define CTRL 0x37A #define DISP_CLEAR 1 //clear the display #define DISP_HOME 2 //home the cursor #define RETURN_HOME 3 //return home #define INC_SHIFT 6 //increment & shift on #define DISP_CTRL 0x0C //display on, no cursor, no blink #define TWO_LINES 0x3F //8 bits, 2 lines, 5x11 characters //#define TWO_LINES 0x30 //8 bits, 1 line, 5x8 characters //------------------------------------------------------ int dinit(void) { usleep(500000); outb(RETURN_HOME, DATA); //return home outb(0x30, CTRL); //Enable=0 RW=1 RS=1 outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(50); outb(TWO_LINES, DATA); //use 2 Lines, 5x11 font outb(0x03, CTRL); //Enable=0 RW=1 RS=1 outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(50); outb(DISP_CTRL, DATA); //switch display on outb(0x03, CTRL); //Enable=0 RW=1 RS=1 outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(50); outb(DISP_CLEAR, DATA); //clear display outb(0x03, CTRL); //Enable=0 RW=1 RS=1 outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(50); outb(INC_SHIFT, DATA); //increment & shift outb(0x03, CTRL); //Enable=0 RW=1 RS=1 outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(50); return 0; } //--------------------------------------------------- void dputchar(char c) { outb(0x02, CTRL); //Enable=0 RW=1 RS=0 outb(c, DATA); outb(0x06, CTRL); //Enable=1 RW=1 RS=0 usleep(100); outb(0x02, CTRL); //Enable=0 RW=1 RS=0 usleep(100); } //--------------------------------------------------- int dprint(char *c, unsigned int len) { int i = 0; while( (i < len) && (c[i] != '\0')) dputchar(c[i++]); return i; } //--------------------------------------------------- void dsecondline(void) { outb(0x07, CTRL); //Enable=1 RW=1 RS=1 outb(DISP_CTRL, DATA); //display on, no cursor, no blink usleep(100); outb(0x03, CTRL); //Enable=0 RW=1 RS=1 usleep(100); } //-------------------------------------------------- int main(int argc, char *argv[]) { if(ioperm(DATA, 3, 1)) //get parallel port access { perror("ioperm"); return 1; } //printf("userID=%d\n",geteuid()); //seteuid("x"); dinit(); if(argc == 1) dprint("Rick Matthews", 13); if(argc == 2) dprint(*(argv+1),strlen(*(argv+1))); if(argc > 2) { dprint(*(argv+1),strlen(*(argv+1))); dsecondline(); dprint(*(argv+2),strlen(*(argv+2))); } usleep(1000000); outb(0, DATA); //reset the parallel port data i/o to zero if (ioperm(DATA, 3, 0)) //cancel parallel port access { perror("ioperm"); return 1; } return 0; } //**************************** end *******************************