/******************************************************** *vfd.c program to drive vacuum fluorescent display * *aka lcd.c for lcd 44780 Displays * *(c) 31 May 1999 Andrew McMeikan GPL v2 * *andrewm@engineer.com ; andrew.mcmeikan@mitswa.com.au * *toggles lines on the parallel port * *D0 is data * *D1 is clock * *D2 is reset line * *this first version uses port at 0x378 * *due to the use of outb macro you must compile with -O * *if you want non-root use remember to chmod +s it * * Modified: 1 June 1999 Andrew McMeikan * * optimised display * * 1 Sept 1999 Andrew McMeikan * * seperated LCD and VFD pins * *As it is intended to have a keypad hanging off the * *shift register for the LCD the VFD display is to be * *re-located onto its own pins to prevent key reads * *upsetting a VFD Display. * * D0 VFD DATA * * D1 VFD CLOCK * * D2 VFD RESET ; LCD E Signal * * D3 LCD DATA FOR SHIFT REGISTER * * D4 LCD CLOCK FOR SHIFT REGISTER * ********************************************************/ #define LCDDATA 8 #define LCDCLOCK 16 #define VFDDATA 1 #define VFDCLOCK 2 #define RESET 4 #define E 4 #define PORT 0x378 #include #include void dochar( char); char shiftreg(char); void lcdinit(void); void ldat(char); void lcmd(char); void lcdmessage(char*); int main (int argc, char *argv[]) { int i; if (argc!=2) { printf("%s:must specify text to display (max 16chars)\n",argv[0]); printf("%s:eg. %s \"HELLO WORLD\"\n",argv[0],argv[0]); return(1); } ioperm(PORT,1,255); if (strcmp(argv[0],"lcd")==0) /*note: ./lcd will not match! put in path*/ { /*printf("doing lcd stuff\n");*/ lcdmessage(argv[1]); return(0); } else { outb(RESET,PORT); outb(0,PORT); usleep(10); /* allow recover time after reset */ dochar(255); /* set display mode and brightness */ for (i=0;(argv[1][i]!=0)&&(i!=16);i++) dochar(argv[1][i]); /* display user string */ if (i<16) for (;i!=16;i++) dochar(' '); /*pad out rest of display to blank */ return(0); /* exit happy */ } } void dochar(char d) /* this function displays on char */ { int i; for (i=7;i>=0;i--) /* MSB first */ { outb(VFDCLOCK|(((d>>i)&1)*VFDDATA),PORT); outb(((d>>i)&1)*VFDDATA,PORT); /* falling clock latches bit */ outb(VFDCLOCK|(((d>>i)&1)*VFDDATA),PORT); } } char shiftreg (char r) /* this function sends r out onto */ { /* the shift register returning any */ int i; /* data collected [obsolete-k/b to be /* seperate program] */ char d; d=0; for (i=7;i>=0;i--) /* MSB first */ { outb(((r>>i)&1)*LCDDATA,PORT); /*set up data */ outb((((r>>i)&1)*LCDDATA)|LCDCLOCK,PORT);/*rising edge of clock */ } outb(E,PORT); /*latch it */ outb(0,PORT); return(d); } #define RS 16 void lcmd (char c) /*this function sends the command c */ { /* to the lcd display */ char n; /*n is nibble of command */ n=c>>4; /*get high nibble */ n=n&15; shiftreg(n); /*clock it */ n=c&15; shiftreg(n); /*clock it */ usleep(40); } void ldat (char c) /*this function sends the data c */ { /* to the lcd display */ char n; /*n is nibble of data */ n=c>>4; /*get high nibble */ n=n&15; shiftreg(n|RS); /*clock it */ n=c&15; shiftreg(n|RS); /*clock it */ } void lcdinit(void) { shiftreg(3); usleep(4100); shiftreg(3); usleep(100); shiftreg(3); usleep(40); shiftreg(2); usleep(40); lcmd(0x28); lcmd(0x06); lcmd(0x0F); lcmd(0x01); usleep(1600); lcmd(0x80); } void lcdmessage(char *m) { int i; lcdinit(); for (i=0;i