/* LCD display for AKI-LAN (POSIX style) 2005/03/01 This code was designed and coded by SHIBUYA K. */ #include "lcd_dev.h" #include "3052.h" #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <string.h> #define LINESIZE 16 #define LINES 2 #define LCDPORT PB.DR.BYTE #define LCDPORTDDR PB.DDR #define WAITSTROBE() {asm("nop");asm("nop");asm("nop");asm("nop");} typedef unsigned char uchar; static char linebuf[LINESIZE*LINES]; static uchar curx,cury; /* assuming LINESIZE and LINES < 256 */ static char initialized = 0; static void microwait(int n) { n *= 3; while(--n){ WAITSTROBE(); } } static void out(uchar data, int cmdflag) { uchar udata,ldata,led; led = LCDPORT&0x0f; udata = (data>>4); ldata = (data&0x0f); if(!cmdflag){ udata |= 0x10; ldata |= 0x10; } LCDPORT = udata; udata |= 0x80; LCDPORT = udata; WAITSTROBE(); udata &= 0x7f; LCDPORT = udata; WAITSTROBE(); LCDPORT=ldata; ldata |= 0x80; LCDPORT = ldata; WAITSTROBE(); ldata &= 0x7f; LCDPORT = ldata; WAITSTROBE(); LCDPORT = led; microwait(40); } static void init() { LCDPORTDDR = 0xff; microwait(15000); /* Wait more than 15ms after vcc rises to 4.5V */ LCDPORT = 0x83; WAITSTROBE(); LCDPORT = 0x03; microwait(4100); LCDPORT = 0x83; WAITSTROBE(); LCDPORT = 0x03; microwait(4100); LCDPORT = 0x83; WAITSTROBE(); LCDPORT = 0x03; microwait(40); LCDPORT = 0x82; WAITSTROBE(); LCDPORT = 0x02; microwait(40); out(0x28,1); /* Function Set */ out(0x08,1); /* Display OFF */ out(0x01,1); /* Clear Display */ microwait(1600); out(0x06,1); /* Entry Mode Set */ out(0x0c,1); /* Display ON */ LCDPORT = 0x0f; memset(linebuf,' ',sizeof(linebuf)); curx = cury = 0; initialized = 1; } ssize_t lcd_write(int fd, const void *data, size_t n) { const char *str = (const char *)data; size_t i,j; if(!initialized) init(); for(i = 0; i < n; i++){ switch(*str){ case '\r': curx = 0; break; case '\n': cury++; curx = 0; break; default: if(cury >= LINES){ cury = LINES-1; memmove(linebuf,linebuf+LINESIZE,LINESIZE*(LINES-1)); memset(linebuf+(cury*LINESIZE),' ',LINESIZE); } if(curx < LINESIZE){ linebuf[cury*LINESIZE+curx] = *str; curx++; } } str++; } for(j = 0; j < LINES; j++){ out(0x80+0x40*j,1); for(i = 0; i < LINESIZE; i++){ out(linebuf[j*LINESIZE+i],0); } } return n; } int lcd_fstat(int fd, struct stat *sb) { memset(sb,0,sizeof(*sb)); sb->st_mode = S_IFCHR|0777; return 0; }