lcd_dev.c

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

This page was generated at 2005/4/24 14:14:43