diff options
author | reinelt <> | 2004-01-10 10:20:22 +0000 |
---|---|---|
committer | reinelt <> | 2004-01-10 10:20:22 +0000 |
commit | ac9acd61f24e6881bb1956ab74fd7d4fd04ceb6b (patch) | |
tree | 810d5271b40b8b68270c88415fe050725bdda06f | |
parent | 117fa6f13e164c7eb5edaee955cabe2666718845 (diff) | |
download | lcd4linux-ac9acd61f24e6881bb1956ab74fd7d4fd04ceb6b.tar.gz |
[lcd4linux @ 2004-01-10 10:20:22 by reinelt]
new MatrixOrbital changes
-rw-r--r-- | drv.c | 17 | ||||
-rw-r--r-- | drv_MatrixOrbital.c | 602 |
2 files changed, 605 insertions, 14 deletions
@@ -1,4 +1,4 @@ -/* $Id: drv.c,v 1.1 2004/01/09 17:03:07 reinelt Exp $ +/* $Id: drv.c,v 1.2 2004/01/10 10:20:22 reinelt Exp $ * * new framework for display drivers * @@ -23,6 +23,9 @@ * * * $Log: drv.c,v $ + * Revision 1.2 2004/01/10 10:20:22 reinelt + * new MatrixOrbital changes + * * Revision 1.1 2004/01/09 17:03:07 reinelt * initiated transfer to new driver architecture * new file 'drv.c' will someday replace 'display.c' @@ -144,7 +147,7 @@ DRIVER *Driver[] = { }; -static DRIVER *Lcd = NULL; +static DRIVER *Drv = NULL; int drv_list (void) @@ -167,9 +170,9 @@ int drv_init (char *section, char *driver) int i; for (i=0; Driver[i]; i++) { if (strcmp (Driver[i]->name, driver)==0) { - Lcd=Driver[i]; - if (Lcd->init==NULL) return 0; - return Lcd->init(Lcd); + Drv=Driver[i]; + if (Drv->init==NULL) return 0; + return Drv->init(section); } } error ("drv_init(%s) failed: no such driver", driver); @@ -179,6 +182,6 @@ int drv_init (char *section, char *driver) int drv_quit (void) { - if (Lcd->quit==NULL) return 0; - return Lcd->quit(); + if (Drv->quit==NULL) return 0; + return Drv->quit(); } diff --git a/drv_MatrixOrbital.c b/drv_MatrixOrbital.c index 1bb55e7..b537ae7 100644 --- a/drv_MatrixOrbital.c +++ b/drv_MatrixOrbital.c @@ -1,4 +1,4 @@ -/* $Id: drv_MatrixOrbital.c,v 1.1 2004/01/09 17:03:07 reinelt Exp $ +/* $Id: drv_MatrixOrbital.c,v 1.2 2004/01/10 10:20:22 reinelt Exp $ * * new style driver for Matrix Orbital serial display modules * @@ -23,6 +23,9 @@ * * * $Log: drv_MatrixOrbital.c,v $ + * Revision 1.2 2004/01/10 10:20:22 reinelt + * new MatrixOrbital changes + * * Revision 1.1 2004/01/09 17:03:07 reinelt * initiated transfer to new driver architecture * new file 'drv.c' will someday replace 'display.c' @@ -56,21 +59,606 @@ #include "bar.h" #include "icon.h" + +static char *Port=NULL; +static speed_t Speed; +static int Device=-1; +static int Model; + +static int ROWS, COLS; +static int XRES, YRES; +static int CHARS, ICONS, GPOS; +static int PROTOCOL; + +static char *FrameBuffer1=NULL; +static char *FrameBuffer2=NULL; +static int GPO[8]; + + +typedef struct { + int type; + char *name; + int rows; + int cols; + int gpos; + int protocol; +} MODEL; + +// Fixme #1: number of gpo's should be verified +// Fixme #2: protocol should be verified + +static MODEL Models[] = { + { 0x01, "LCD0821", 2, 8, 0, 1 }, + { 0x03, "LCD2021", 2, 20, 0, 1 }, + { 0x04, "LCD1641", 4, 16, 0, 1 }, + { 0x05, "LCD2041", 4, 20, 0, 1 }, + { 0x06, "LCD4021", 2, 40, 0, 1 }, + { 0x07, "LCD4041", 4, 40, 0, 1 }, + { 0x08, "LK202-25", 2, 20, 0, 2 }, + { 0x09, "LK204-25", 4, 20, 0, 2 }, + { 0x0a, "LK404-55", 4, 40, 0, 2 }, + { 0x0b, "VFD2021", 2, 20, 0, 1 }, + { 0x0c, "VFD2041", 4, 20, 0, 1 }, + { 0x0d, "VFD4021", 2, 40, 0, 1 }, + { 0x0e, "VK202-25", 2, 20, 0, 1 }, + { 0x0f, "VK204-25", 4, 20, 0, 1 }, + { 0x10, "GLC12232", -1, -1, 0, 1 }, + { 0x13, "GLC24064", -1, -1, 0, 1 }, + { 0x15, "GLK24064-25", -1, -1, 0, 1 }, + { 0x22, "GLK12232-25", -1, -1, 0, 1 }, + { 0x31, "LK404-AT", 4, 40, 0, 2 }, + { 0x32, "VFD1621", 2, 16, 0, 1 }, + { 0x33, "LK402-12", 2, 40, 0, 2 }, + { 0x34, "LK162-12", 2, 16, 0, 2 }, + { 0x35, "LK204-25PC", 4, 20, 0, 2 }, + { 0x36, "LK202-24-USB", 2, 20, 0, 2 }, + { 0x38, "LK204-24-USB", 4, 20, 0, 2 }, + { 0xff, "Unknown", -1, -1, 0, 0 } +}; + + +static int drv_MO_open (void) +{ + int fd; + pid_t pid; + struct termios portset; + + if ((pid=lock_port(Port))!=0) { + if (pid==-1) + error ("MatrixOrbital: port %s could not be locked", Port); + else + error ("MatrixOrbital: port %s is locked by process %d", Port, pid); + return -1; + } + fd = open(Port, O_RDWR | O_NOCTTY | O_NDELAY); + if (fd==-1) { + error ("MatrixOrbital: open(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + if (tcgetattr(fd, &portset)==-1) { + error ("MatrixOrbital: tcgetattr(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + cfmakeraw(&portset); + cfsetospeed(&portset, Speed); + if (tcsetattr(fd, TCSANOW, &portset)==-1) { + error ("MatrixOrbital: tcsetattr(%s) failed: %s", Port, strerror(errno)); + unlock_port(Port); + return -1; + } + return fd; +} + + +static int drv_MO_read (char *string, int len) +{ + int run, ret; + + if (Device==-1) return -1; + for (run=0; run<10; run++) { + ret=read (Device, string, len); + if (ret>=0 || errno!=EAGAIN) break; + debug ("read(): EAGAIN"); + usleep(1000); + } + + if (ret<0) { + error("MatrixOrbital: read(%s, %d) failed: %s", Port, len, strerror(errno)); + } + + return ret; +} + + +static void drv_MO_write (char *string, int len) +{ + int run, ret; + + if (Device==-1) return; + for (run=0; run<10; run++) { + ret=write (Device, string, len); + if (ret>=0 || errno!=EAGAIN) break; + debug ("write(): EAGAIN"); + usleep(1000); + } + + if (ret<0) { + error ("MatrixOrbital: write(%s) failed: %s", Port, strerror(errno)); + } + + // Fixme + if (ret!=len) { + error ("MatrixOrbital: partial write: len=%d ret=%d", len, ret); + } + + return; +} + + +static int drv_MO_contrast (void) +{ + char buffer[4]; + int contrast; + + if (cfg_number(NULL, "Contrast", 160, 0, 255, &contrast)<0) return -1; + snprintf (buffer, 4, "\376P%c", contrast); + drv_MO_write (buffer, 3); + return 0; +} + + +static void drv_MO_define_char (int ascii, char *buffer) +{ + char cmd[3]="\376N"; + + cmd[2]=(char)ascii; + drv_MO_write (cmd, 3); + drv_MO_write (buffer, 8); +} + + +static int drv_MO_clear (int protocol) +{ + int gpo; + + memset (FrameBuffer1, ' ', ROWS*COLS*sizeof(char)); + + icon_clear(); + bar_clear(); + memset(GPO, 0, sizeof(GPO)); + + if (protocol) { + memset (FrameBuffer2, ' ', ROWS*COLS*sizeof(char)); + switch (protocol) { + case 1: + drv_MO_write ("\014", 1); // Clear Screen + drv_MO_write ("\376V", 2); // GPO off + break; + case 2: + drv_MO_write ("\376\130", 2); // Clear Screen + for (gpo=1; gpo<=GPOS; gpo++) { + char cmd1[3]="\376V"; + char cmd2[4]="\376\300x\377"; + cmd1[2]=(char)gpo; + cmd2[2]=(char)gpo; + drv_MO_write (cmd1, 3); // GPO off + drv_MO_write (cmd2, 4); // PWM full power + } + break; + } + } + + return 0; +} + +static void plugin_contrast (RESULT *result, RESULT *arg1) +{ + char buffer[4]; + double contrast; + + contrast=R2N(arg1); + if (contrast<0 ) contrast=0; + if (contrast>255) contrast=255; + snprintf (buffer, 4, "\376P%c", (int)contrast); + drv_MO_write (buffer, 3); + + SetResult(&result, R_NUMBER, &contrast); +} + + +static void plugin_backlight (RESULT *result, RESULT *arg1) +{ + char buffer[4]; + double backlight; + + backlight=R2N(arg1); + if (backlight<-1 ) backlight=-1; + if (backlight>255) backlight=255; + if (backlight<0) { + // backlight off + snprintf (buffer, 3, "\376F"); + drv_MO_write (buffer, 2); + } else { + // backlight on for n minutes + snprintf (buffer, 4, "\376B%c", (int)backlight); + drv_MO_write (buffer, 3); + } + SetResult(&result, R_NUMBER, &backlight); +} + + +static void plugin_gpo (RESULT *result, RESULT *arg1, RESULT *arg2) +{ + int num; + double val; + char cmd[3]="\376"; + // Fixme + int protocol=2; + + num=R2N(arg1); + val=R2N(arg2); + + if (num<1) num=1; + if (num>6) num=6; + + if (val>=1.0) { + val=1.0; + } else { + val=0.0; + } + + switch (protocol) { + case 1: + if (num==0) { + if (val>=1.0) { + drv_MO_write ("\376W", 2); // GPO on + } else { + drv_MO_write ("\376V", 2); // GPO off + } + } else { + error("Fixme"); + val=-1.0; + } + break; + + case 2: + if (val>=1.0) { + cmd[1]='W'; // GPO on + } else { + cmd[1]='V'; // GPO off + } + cmd[2]=(char)num; + drv_MO_write (cmd, 3); + break; + } + + SetResult(&result, R_NUMBER, &val); +} + + +static void plugin_pwm (RESULT *result, RESULT *arg1, RESULT *arg2) +{ + int num; + double val; + char cmd[4]="\376\300"; + + num=R2N(arg1); + if (num<1) num=1; + if (num>6) num=6; + cmd[2]=(char)num; + + val=R2N(arg2); + if (val< 0.0) val= 0.0; + if (val>255.0) val=255.0; + cmd[3]=(char)val; + + drv_MO_write (cmd, 4); + + SetResult(&result, R_NUMBER, &val); +} + + +static void plugin_rpm (RESULT *result, RESULT *arg1) +{ + int num; + double val; + char cmd[3]="\376\301"; + char buffer[7]; + + num=R2N(arg1); + if (num<1) num=1; + if (num>6) num=6; + cmd[2]=(char)num; + + drv_MO_write (cmd, 3); + usleep(100000); + drv_MO_read (buffer, 7); + + debug ("rpm: buffer[0]=0x%01x", buffer[0]); + debug ("rpm: buffer[1]=0x%01x", buffer[1]); + debug ("rpm: buffer[2]=0x%01x", buffer[2]); + debug ("rpm: buffer[3]=0x%01x", buffer[3]); + debug ("rpm: buffer[4]=0x%01x", buffer[4]); + debug ("rpm: buffer[5]=0x%01x", buffer[5]); + debug ("rpm: buffer[6]=0x%01x", buffer[6]); + + SetResult(&result, R_NUMBER, &val); +} + + +static void drv_MO_goto (int row, int col) +{ + char cmd[5]="\376Gyx"; + cmd[2]=(char)col+1; + cmd[3]=(char)row+1; + drv_MO_write(cmd,4); +} + + +static int drv_MO_put (int row, int col, char *text) +{ + char *p=FrameBuffer1+row*COLS+col; + char *t=text; + + while (*t && col++<=COLS) { + *p++=*t++; + } + return 0; +} + + +static int drv_MO_bar (int type, int row, int col, int max, int len1, int len2) +{ + return bar_draw (type, row, col, max, len1, len2); +} + + +static int drv_MO_icon (int num, int seq, int row, int col) +{ + return icon_draw (num, seq, row, col); +} + + +static int drv_MO_gpo (int num, int val) +{ + if (num>=GPOS) + return -1; + + GPO[num]=val; + + // Fixme + GPO[num]=255; + + return 0; +} + + +static int drv_MO_flush (int protocol) +{ + int row, col, pos1, pos2; + int c, equal; + int gpo; + + bar_process(drv_MO_define_char); + + for (row=0; row<ROWS; row++) { + for (col=0; col<COLS; col++) { + c=bar_peek(row, col); + if (c==-1) c=icon_peek(row, col); + if (c!=-1) { + FrameBuffer1[row*COLS+col]=(char)c; + } + } + for (col=0; col<COLS; col++) { + if (FrameBuffer1[row*COLS+col]==FrameBuffer2[row*COLS+col]) continue; + drv_MO_goto (row, col); + for (pos1=col++, pos2=pos1, equal=0; col<COLS; col++) { + if (FrameBuffer1[row*COLS+col]==FrameBuffer2[row*COLS+col]) { + // If we find just one equal byte, we don't break, because this + // would require a goto, which takes one byte, too. + if (++equal>5) break; + } else { + pos2=col; + equal=0; + } + } + drv_MO_write (FrameBuffer1+row*COLS+pos1, pos2-pos1+1); + } + } + + memcpy (FrameBuffer2, FrameBuffer1, ROWS*COLS*sizeof(char)); + + switch (protocol) { + case 1: + if (GPO[0]) { + drv_MO_write ("\376W", 2); // GPO on + } else { + drv_MO_write ("\376V", 2); // GPO off + } + break; + case 2: + for (gpo=1; gpo<=GPOS; gpo++) { + char cmd[3]="\376"; + cmd[1]=GPO[gpo]? 'W':'V'; + cmd[2]=(char)gpo; + drv_MO_write (cmd, 3); + } + break; + } + + return 0; +} + + +// ***************************** +// exported functions start here +// ***************************** + + int drv_MO_list (void) { - printf ("this and that"); + int i; + + for (i=0; Models[i].type!=0xff; i++) { + printf ("%s ", Models[i].name); + } return 0; } -int drv_MO_init (struct DRIVER *Self) + +int drv_MO_init (char *section) { - debug ("consider me initialized"); + int i; + char *port, buffer[256]; + char *model; + + if (Port) { + free (Port); + Port=NULL; + } + + model=cfg_get(section, "Model", NULL); + if (model!=NULL && *model!='\0') { + for (i=0; Models[i].type!=0xff; i++) { + if (strcasecmp(Models[i].name, model)==0) break; + } + if (Models[i].type==0xff) { + error ("MatrixOrbital: %s.Model '%s' is unknown from %s", section, model, cfg_source()); + return -1; + } + Model=i; + info ("MatrixOrbital: using model '%s'", Models[Model].name); + } else { + info ("MatrixOrbital: no '%s.Model' entry from %s, auto-dedecting", section, cfg_source()); + Model=-1; + } + + + port=cfg_get(section, "Port", NULL); + if (port==NULL || *port=='\0') { + error ("MatrixOrbital: no '%s.Port' entry from %s", section, cfg_source()); + return -1; + } + Port=strdup(port); + + if (cfg_number(section, "Speed", 19200, 1200, 19200, &i)<0) return -1; + switch (i) { + case 1200: + Speed=B1200; + break; + case 2400: + Speed=B2400; + break; + case 9600: + Speed=B9600; + break; + case 19200: + Speed=B19200; + break; + default: + error ("MatrixOrbital: unsupported speed '%d' from %s", i, cfg_source()); + return -1; + } + + info ("MatrixOrbital: using port '%s' at %d baud", Port, i); + + Device=drv_MO_open(); + if (Device==-1) return -1; + + // read module type + drv_MO_write ("\3767", 2); + usleep(1000); + drv_MO_read (buffer, 1); + for (i=0; Models[i].type!=0xff; i++) { + if (Models[i].type == (int)*buffer) break; + } + info ("MatrixOrbital: Display identifies itself as a '%s' (type 0x%02x)", + Models[i].name, Models[i].type); + + // auto-dedection + if (Model==-1) Model=i; + + // auto-dedection matches specified model? + if (Model!=i) { + error ("MatrixOrbital: %s.Model '%s' from %s does not match dedected Model '%s'", + section, model, cfg_source(), Models[i].name); + return -1; + } + + // read serial number + drv_MO_write ("\3765", 2); + usleep(100000); + drv_MO_read (buffer, 2); + info ("MatrixOrbital: Display reports Serial Number 0x%x", *(short*)buffer); + + // read version number + drv_MO_write ("\3766", 2); + usleep(100000); + drv_MO_read (buffer, 1); + info ("MatrixOrbital: Display reports Firmware Version 0x%x", *buffer); + + + // Init the framebuffers + FrameBuffer1 = (char*)malloc(COLS*ROWS*sizeof(char)); + FrameBuffer2 = (char*)malloc(COLS*ROWS*sizeof(char)); + if (FrameBuffer1==NULL || FrameBuffer2==NULL) { + error ("MatrixOrbital: framebuffer could not be allocated: malloc() failed"); + return -1; + } + + // init Icons + if (cfg_number(NULL, "Icons", 0, 0, CHARS, &ICONS)<0) return -1; + if (ICONS>0) { + debug ("reserving %d of %d user-defined characters for icons", ICONS, CHARS); + icon_init(ROWS, COLS, XRES, YRES, CHARS, ICONS, drv_MO_define_char); + } + + // init Bars + bar_init(ROWS, COLS, XRES, YRES, CHARS-ICONS); + bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank + bar_add_segment(255,255,255,255); // ASCII 255 = block + + + drv_MO_clear(PROTOCOL); + drv_MO_contrast(); + + drv_MO_write ("\376B", 3); // backlight on + drv_MO_write ("\376K", 2); // cursor off + drv_MO_write ("\376T", 2); // blink off + drv_MO_write ("\376D", 2); // line wrapping off + drv_MO_write ("\376R", 2); // auto scroll off + + // register as a plugin + AddFunction ("contrast", 1, plugin_contrast); + AddFunction ("backlight", 1, plugin_backlight); + AddFunction ("gpo", 2, plugin_gpo); + AddFunction ("pwm", 2, plugin_pwm); + AddFunction ("rpm", 1, plugin_rpm); + return 0; } + int drv_MO_quit (void) { - debug ("consider me gone"); - return 0; + info("MatrixOrbital: shutting down."); + + debug ("closing port %s", Port); + close (Device); + unlock_port(Port); + + if (FrameBuffer1) { + free(FrameBuffer1); + FrameBuffer1=NULL; + } + + if (FrameBuffer2) { + free(FrameBuffer2); + FrameBuffer2=NULL; + } + + return (0); } @@ -78,5 +666,5 @@ DRIVER drv_MatrixOrbital = { name: "MatrixOrbital", list: drv_MO_list, init: drv_MO_init, - quit: drv_MO_quit + quit: drv_MO_quit, }; |