aboutsummaryrefslogtreecommitdiffstats
path: root/lcd2041.c
diff options
context:
space:
mode:
authorreinelt <>2000-01-16 12:17:59 +0000
committerreinelt <>2000-01-16 12:17:59 +0000
commit991cae8c076d9da475bf833186219b3d2a396f29 (patch)
treee884a890843544c3039c1af4c58e43e45b642018 /lcd2041.c
downloadlcd4linux-991cae8c076d9da475bf833186219b3d2a396f29.tar.gz
[lcd4linux @ 2000-01-16 12:17:59 by reinelt]
Initial revision
Diffstat (limited to 'lcd2041.c')
-rw-r--r--lcd2041.c314
1 files changed, 314 insertions, 0 deletions
diff --git a/lcd2041.c b/lcd2041.c
new file mode 100644
index 0000000..4987697
--- /dev/null
+++ b/lcd2041.c
@@ -0,0 +1,314 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "lcd2041.h"
+
+#define BAR_HORI 1
+#define BAR_VERT 2
+#define BAR_DUAL 3
+
+static int lcd;
+static char *lcd_device=NULL;
+static int bar_mode=0;
+
+typedef struct {
+ int l1;
+ int l2;
+ int chr;
+} SEGMENT;
+
+typedef struct {
+ int l1;
+ int l2;
+ int lru;
+} CHARACTER;
+
+static SEGMENT Segment[COLS+1][ROWS+1];
+static CHARACTER Character[CHAR];
+
+static int lcd_open(void)
+{
+ int fd;
+ struct termios portset;
+
+ fd = open(lcd_device, O_RDWR | O_NOCTTY | O_NDELAY);
+ if (fd==-1) {
+ fprintf (stderr, "open(%s) failed: %s\n", lcd_device, strerror(errno));
+ return -1;
+ }
+ if (tcgetattr(fd, &portset)==-1) {
+ fprintf (stderr, "tcgetattr(%s) failed: %s\n", lcd_device, strerror(errno));
+ return -1;
+ }
+ cfmakeraw(&portset);
+ cfsetospeed(&portset, B19200);
+ if (tcsetattr(fd, TCSANOW, &portset)==-1) {
+ fprintf (stderr, "tcsetattr(%s) failed: %s\n", lcd_device, strerror(errno));
+ return -1;
+ }
+ return fd;
+}
+
+
+static void lcd_write (char *string, int len)
+{
+ if (lcd==-1) return;
+ if (write (lcd, string, len)==-1) {
+ if (errno==EAGAIN) {
+ usleep(1000);
+ if (write (lcd, string, len)>=0) return;
+ }
+ fprintf (stderr, "write(%s) failed: %s\n", lcd_device, strerror(errno));
+ }
+}
+
+
+void lcd_clear (void)
+{
+ lcd_write ("\014", 1);
+}
+
+
+void lcd_put (int x, int y, char *string)
+{
+ char buffer[256];
+ snprintf (buffer, sizeof(buffer), "\376G%c%c%s", x, y, string);
+ lcd_write (buffer, strlen(buffer));
+}
+
+void lcd_hbar (int x, int y, int dir, int max, int len)
+{
+ char buffer[COLS+5];
+ char *p;
+
+ if (bar_mode!=BAR_HORI) {
+ lcd_write ("\376h", 2);
+ bar_mode=BAR_HORI;
+ }
+
+ if (len<1) len=1;
+ else if (len>max) len=max;
+ if (dir!=0) len=max-len;
+
+ snprintf (buffer, sizeof(buffer), "\376G%c%c", x, y);
+ p=buffer+4;
+
+ while (max>0 && p-buffer<sizeof(buffer)) {
+ if (len==0) {
+ *p=dir?255:32;
+ } else if (len>=XRES) {
+ *p=dir?32:255;
+ len-=XRES;
+ } else {
+ *p=dir?8-len:len-1;
+ len=0;
+ }
+ max-=XRES;
+ p++;
+ }
+ lcd_write (buffer, p-buffer);
+}
+
+
+void lcd_vbar (int x, int y, int dir, int max, int len)
+{
+ char buffer[6];
+ unsigned char c;
+
+ if (bar_mode!=BAR_VERT) {
+ lcd_write ("\376v", 2);
+ bar_mode=BAR_VERT;
+ }
+
+ if (len<1) len=1;
+ else if (len>max) len=max;
+
+ while (max>0 && y>0) {
+ if (len==0) {
+ c=32;
+ } else if (len>=XRES) {
+ c=255;
+ len-=XRES;
+ } else {
+ c=len;
+ len=0;
+ }
+ snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, c);
+ lcd_write (buffer, 5);
+ max-=XRES;
+ y--;
+ }
+}
+
+
+static void lcd_dbar_init (void)
+{
+ int x, y;
+
+ bar_mode=BAR_DUAL;
+
+ for (x=0; x<CHAR; x++) {
+ Character[x].l1=-1;
+ Character[x].l2=-1;
+ Character[x].lru=0;
+ }
+
+ for (x=0; x<COLS; x++) {
+ for (y=0; y<ROWS; y++) {
+ Segment[x][y].l1=-1;
+ Segment[x][y].l2=-1;
+ }
+ }
+}
+
+static int lcd_dbar_char (int l1, int l2)
+{
+ int i, j, min;
+
+ if (l1==127) l1=0;
+ if (l2==127) l2=0;
+
+ if (l1==0 && l2==0) return 32;
+ if (l1==XRES && l2==XRES) return 255;
+
+ for (i=0; i<CHAR; i++) {
+ if (Character[i].l1==l1 && Character[i].l2==l2) {
+ Character[i].lru=2;
+ return i;
+ }
+ }
+
+ for (i=0; i<CHAR; i++) {
+ if (Character[i].lru==0) {
+ printf ("creating char %d (%d/%d)\n", i, l1, l2);
+ Character[i].l1=l1;
+ Character[i].l2=l2;
+ Character[i].lru=2;
+ return i;
+ }
+ }
+
+ min=XRES*YRES;
+ for (i=0; i<CHAR; i++) {
+ int diff;
+ if (l1==0 && Character[i].l1!=0) continue;
+ if (l2==0 && Character[i].l2!=0) continue;
+ if (l1==XRES && Character[i].l1!=XRES) continue;
+ if (l2==XRES && Character[i].l2!=XRES) continue;
+ diff=abs(Character[i].l1-l1)+abs(Character[i].l2-l2);
+ if (diff<min) {
+ min=diff;
+ j=i;
+ }
+ }
+ printf ("lcd_dbar: diff=%d\n", min);
+ return j;
+}
+
+void lcd_dbar (int x, int y, int dir, int max, int len1, int len2)
+{
+ if (bar_mode!=BAR_DUAL)
+ lcd_dbar_init();
+
+ if (len1<1) len1=1;
+ else if (len1>max) len1=max;
+
+ if (len2<1) len2=1;
+ else if (len2>max) len2=max;
+
+ while (max>0 && x<=COLS) {
+ if (len1==0) {
+ Segment[x][y].l1=0;
+ } else if (len1>=XRES) {
+ Segment[x][y].l1=XRES;
+ len1-=XRES;
+ } else {
+ Segment[x][y].l1=len1;
+ len1=0;
+ }
+ if (len2==0) {
+ Segment[x][y].l2=0;
+ } else if (len2>=XRES) {
+ Segment[x][y].l2=XRES;
+ len2-=XRES;
+ } else {
+ Segment[x][y].l2=len2;
+ len2=0;
+ }
+ max-=XRES;
+ x++;
+ }
+}
+
+void lcd_dbar_flush (void)
+{
+ int i, x, y;
+
+ for (y=0; y<=ROWS; y++) {
+ for (x=0; x<=COLS; x++) {
+ if ((Segment[x][y].l1==0 && Segment[x][y].l2==XRES) || (Segment[x][y].l1==XRES && Segment[x][y].l2==0))
+ Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2);
+ }
+ }
+ for (y=0; y<=ROWS; y++) {
+ for (x=0; x<=COLS; x++) {
+ if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1)
+ Segment[x][y].chr=lcd_dbar_char(Segment[x][y].l1, Segment[x][y].l2);
+ }
+ }
+
+ for (i=0; i<CHAR; i++) {
+ if (Character[i].lru==2) {
+ char buffer[12];
+ char pixel[XRES+1]={0, 16, 24, 28, 30, 31};
+ char p0=pixel[Character[i].l1];
+ char p1=pixel[Character[i].l2];
+ snprintf (buffer, sizeof(buffer), "\376N%c%c%c%c%c%c%c%c%c", i, p0, p0, p0, p0, p1, p1, p1, p1);
+ lcd_write (buffer, 11);
+ }
+ if (Character[i].lru>0)
+ Character[i].lru--;
+ }
+
+ for (y=0; y<=ROWS; y++) {
+ for (x=0; x<=COLS; x++) {
+ if (Segment[x][y].l1!=-1 || Segment[x][y].l2!=-1) {
+ char buffer[6];
+ snprintf (buffer, sizeof(buffer), "\376G%c%c%c", x, y, Segment[x][y].chr);
+ lcd_write (buffer, 5);
+ }
+ }
+ }
+}
+
+
+int lcd_init (char *device)
+{
+ if (lcd_device) free (lcd_device);
+ lcd_device=strdup(device);
+ lcd=lcd_open();
+ if (lcd==-1) return -1;
+
+ lcd_clear();
+ lcd_write ("\376B", 3); // backlight on
+ lcd_write ("\376K", 2); // cursor off
+ lcd_write ("\376T", 2); // blink off
+ lcd_write ("\376D", 2); // line wrapping off
+ lcd_write ("\376R", 2); // auto scroll off
+ lcd_write ("\376V", 2); // GPO off
+
+ return 0;
+}
+
+void lcd_contrast (int contrast)
+{
+ char buffer[4];
+ snprintf (buffer, 4, "\376P%c", contrast);
+ lcd_write (buffer, 3);
+}
+