/* 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;
}