diff options
author | reinelt <> | 2004-01-20 04:51:39 +0000 |
---|---|---|
committer | reinelt <> | 2004-01-20 04:51:39 +0000 |
commit | 252cb9023289ad2af5993cf53c0d0fd7293cff27 (patch) | |
tree | c69d9d3e57c90cb364d3f051813619db38e46e18 | |
parent | 928b0e09a5725abfd53421f19e5e53845e7aa100 (diff) | |
download | lcd4linux-252cb9023289ad2af5993cf53c0d0fd7293cff27.tar.gz |
[lcd4linux @ 2004-01-20 04:51:39 by reinelt]
moved generic stuff from drv_MatrixOrbital to drv_generic
implemented new-stylish bars which are nearly finished
Diffstat (limited to '')
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 20 | ||||
-rw-r--r-- | drv_MatrixOrbital.c | 513 | ||||
-rw-r--r-- | drv_generic.c | 292 | ||||
-rw-r--r-- | drv_generic.h | 74 | ||||
-rw-r--r-- | drv_generic_bar.c | 471 | ||||
-rw-r--r-- | drv_generic_bar.h | 43 | ||||
-rw-r--r-- | lcd4linux.conf.sample | 19 | ||||
-rw-r--r-- | widget_bar.c | 78 | ||||
-rw-r--r-- | widget_bar.h | 15 | ||||
-rw-r--r-- | widget_text.c | 7 |
11 files changed, 1092 insertions, 442 deletions
diff --git a/Makefile.am b/Makefile.am index d0b5732..c11e881 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,8 @@ imon.c imon.h \ \ display.c display.h \ drv.c drv.h \ +drv_generic.c drv_generic.h \ +drv_generic_bar.c \ debug.c debug.h \ cfg.c cfg.h \ lock.c lock.h \ diff --git a/Makefile.in b/Makefile.in index 9d903e3..18a2148 100644 --- a/Makefile.in +++ b/Makefile.in @@ -106,7 +106,7 @@ lcd4linux_LDADD = @DRIVERS@ @DRVLIBS@ #remove next line for liblcd4linux lcd4linux_DEPENDENCIES = @DRIVERS@ -lcd4linux_SOURCES = lcd4linux.c pid.c pid.h hash.c hash.h parser.c parser.h processor.c processor.h layout.c layout.h timer.c timer.h evaluator.c evaluator.h widget.c widget.h widget_text.c widget_text.h widget_bar.c widget_bar.h plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_uname.c plugin_loadavg.c plugin_proc_stat.c plugin_cpuinfo.c plugin_meminfo.c plugin_i2c_sensors.c plugin_xmms.c system.c system.h isdn.c isdn.h wifi.c wifi.h mail.c mail.h seti.c seti.h battery.c battery.h dvb.c dvb.h filter.c filter.h exec.c exec.h expr.c expr.h mail2.c socket.c socket.h imon.c imon.h display.c display.h drv.c drv.h debug.c debug.h cfg.c cfg.h lock.c lock.h pixmap.c pixmap.h bar.c bar.h icon.c icon.h fontmap.c fontmap.h udelay.c udelay.h +lcd4linux_SOURCES = lcd4linux.c pid.c pid.h hash.c hash.h parser.c parser.h processor.c processor.h layout.c layout.h timer.c timer.h evaluator.c evaluator.h widget.c widget.h widget_text.c widget_text.h widget_bar.c widget_bar.h plugin.c plugin.h plugin_math.c plugin_string.c plugin_cfg.c plugin_uname.c plugin_loadavg.c plugin_proc_stat.c plugin_cpuinfo.c plugin_meminfo.c plugin_i2c_sensors.c plugin_xmms.c system.c system.h isdn.c isdn.h wifi.c wifi.h mail.c mail.h seti.c seti.h battery.c battery.h dvb.c dvb.h filter.c filter.h exec.c exec.h expr.c expr.h mail2.c socket.c socket.h imon.c imon.h display.c display.h drv.c drv.h drv_generic.c drv_generic.h drv_generic_bar.c debug.c debug.h cfg.c cfg.h lock.c lock.h pixmap.c pixmap.h bar.c bar.h icon.c icon.h fontmap.c fontmap.h udelay.c udelay.h #liblcd4linux_la_DEPENDENCIES = @DRIVERS@ @@ -157,9 +157,10 @@ plugin_i2c_sensors.$(OBJEXT) plugin_xmms.$(OBJEXT) system.$(OBJEXT) \ isdn.$(OBJEXT) wifi.$(OBJEXT) mail.$(OBJEXT) seti.$(OBJEXT) \ battery.$(OBJEXT) dvb.$(OBJEXT) filter.$(OBJEXT) exec.$(OBJEXT) \ expr.$(OBJEXT) mail2.$(OBJEXT) socket.$(OBJEXT) imon.$(OBJEXT) \ -display.$(OBJEXT) drv.$(OBJEXT) debug.$(OBJEXT) cfg.$(OBJEXT) \ -lock.$(OBJEXT) pixmap.$(OBJEXT) bar.$(OBJEXT) icon.$(OBJEXT) \ -fontmap.$(OBJEXT) udelay.$(OBJEXT) +display.$(OBJEXT) drv.$(OBJEXT) drv_generic.$(OBJEXT) \ +drv_generic_bar.$(OBJEXT) debug.$(OBJEXT) cfg.$(OBJEXT) lock.$(OBJEXT) \ +pixmap.$(OBJEXT) bar.$(OBJEXT) icon.$(OBJEXT) fontmap.$(OBJEXT) \ +udelay.$(OBJEXT) CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -180,11 +181,12 @@ DEP_FILES = .deps/BeckmannEgle.P .deps/Crystalfontz.P .deps/Cwlinux.P \ .deps/MilfordInstruments.P .deps/PalmPilot.P .deps/Raster.P .deps/SIN.P \ .deps/T6963.P .deps/Text.P .deps/USBLCD.P .deps/XWindow.P .deps/bar.P \ .deps/battery.P .deps/cfg.P .deps/debug.P .deps/display.P .deps/drv.P \ -.deps/drv_MatrixOrbital.P .deps/dvb.P .deps/evaluator.P .deps/exec.P \ -.deps/expr.P .deps/filter.P .deps/fontmap.P .deps/hash.P .deps/icon.P \ -.deps/imon.P .deps/isdn.P .deps/layout.P .deps/lcd4linux.P .deps/lock.P \ -.deps/mail.P .deps/mail2.P .deps/parport.P .deps/parser.P .deps/pid.P \ -.deps/pixmap.P .deps/plugin.P .deps/plugin_cfg.P .deps/plugin_cpuinfo.P \ +.deps/drv_MatrixOrbital.P .deps/drv_generic.P .deps/drv_generic_bar.P \ +.deps/dvb.P .deps/evaluator.P .deps/exec.P .deps/expr.P .deps/filter.P \ +.deps/fontmap.P .deps/hash.P .deps/icon.P .deps/imon.P .deps/isdn.P \ +.deps/layout.P .deps/lcd4linux.P .deps/lock.P .deps/mail.P \ +.deps/mail2.P .deps/parport.P .deps/parser.P .deps/pid.P .deps/pixmap.P \ +.deps/plugin.P .deps/plugin_cfg.P .deps/plugin_cpuinfo.P \ .deps/plugin_i2c_sensors.P .deps/plugin_loadavg.P .deps/plugin_math.P \ .deps/plugin_meminfo.P .deps/plugin_proc_stat.P .deps/plugin_string.P \ .deps/plugin_uname.P .deps/plugin_xmms.P .deps/processor.P .deps/seti.P \ diff --git a/drv_MatrixOrbital.c b/drv_MatrixOrbital.c index 96692ae..1fb70d6 100644 --- a/drv_MatrixOrbital.c +++ b/drv_MatrixOrbital.c @@ -1,4 +1,4 @@ -/* $Id: drv_MatrixOrbital.c,v 1.9 2004/01/18 21:25:16 reinelt Exp $ +/* $Id: drv_MatrixOrbital.c,v 1.10 2004/01/20 04:51:39 reinelt Exp $ * * new style driver for Matrix Orbital serial display modules * @@ -23,6 +23,10 @@ * * * $Log: drv_MatrixOrbital.c,v $ + * Revision 1.10 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * * Revision 1.9 2004/01/18 21:25:16 reinelt * Framework for bar widget opened * @@ -84,31 +88,22 @@ #include "cfg.h" #include "plugin.h" #include "lock.h" -#include "drv.h" -#include "bar.h" -#include "icon.h" #include "widget.h" #include "widget_text.h" #include "widget_bar.h" +#include "drv.h" +#include "drv_generic.h" +#include "drv_generic_bar.h" -// these values are hardcoded -#define XRES 5 -#define YRES 8 -#define CHARS 8 +static char Name[]="MatrixOrbital"; -static char *Port=NULL; -static speed_t Speed; -static int Device=-1; static int Model; -static int DROWS, DCOLS; // display size -static int LROWS, LCOLS; // layout size static int GPOS, ICONS, PROTOCOL; -static char *LayoutFB=NULL; -static char *DisplayFB=NULL; -static int GPO[8]; +// Fixme: +// static int GPO[8]; typedef struct { @@ -153,105 +148,17 @@ static MODEL Models[] = { }; -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 (int contrast) -{ - char buffer[4]; - - if (contrast<0 ) contrast=0; - if (contrast>255) contrast=255; - snprintf (buffer, 4, "\376P%c", contrast); - drv_MO_write (buffer, 3); - return contrast; -} - +// **************************************** +// *** hardware dependant functions *** +// **************************************** 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); + drv_generic_serial_write (cmd, 3); + drv_generic_serial_write (buffer, 8); } @@ -260,79 +167,7 @@ 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_clear (int full) -{ - int gpo; - - memset (LayoutFB, ' ', LROWS*LCOLS*sizeof(char)); - - icon_clear(); - bar_clear(); - memset(GPO, 0, sizeof(GPO)); - - if (full) { - memset (DisplayFB, ' ', DROWS*DCOLS*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 int drv_MO_put (int row, int col, char *text) -{ - char *p=LayoutFB+row*DCOLS+col; - char *t=text; - - while (*t && col++<=DCOLS) { - *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; + drv_generic_serial_write(cmd,4); } @@ -340,98 +175,92 @@ static int drv_MO_gpo (int num, int val) static int drv_MO_start (char *section) { int i; - char *port, buffer[256]; char *model; + char *port, buffer[256]; + speed_t speed; - 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()); + error ("%s: %s.Model '%s' is unknown from %s", Name, section, model, cfg_source()); return -1; } Model=i; - info ("MatrixOrbital: using model '%s'", Models[Model].name); + info ("%s: using model '%s'", Name, Models[Model].name); } else { - info ("MatrixOrbital: no '%s.Model' entry from %s, auto-dedecting", section, cfg_source()); + info ("%s: no '%s.Model' entry from %s, auto-dedecting", Name, 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()); + error ("%s: no '%s.Port' entry from %s", Name, 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; + speed=B1200; break; case 2400: - Speed=B2400; + speed=B2400; break; case 9600: - Speed=B9600; + speed=B9600; break; case 19200: - Speed=B19200; + speed=B19200; break; default: - error ("MatrixOrbital: unsupported speed '%d' from %s", i, cfg_source()); + error ("%s: unsupported speed '%d' from %s", Name, i, cfg_source()); return -1; } - info ("MatrixOrbital: using port '%s' at %d baud", Port, i); + info ("%s: using port '%s' at %d baud", Name, port, i); - Device=drv_MO_open(); - if (Device==-1) return -1; + if (drv_generic_serial_open(Name, port, speed)<0) return -1; // read module type - drv_MO_write ("\3767", 2); + drv_generic_serial_write ("\3767", 2); usleep(1000); - if (drv_MO_read (buffer, 1)==1) { + if (drv_generic_serial_read (buffer, 1)==1) { for (i=0; Models[i].type!=0xff; i++) { if (Models[i].type == (int)*buffer) break; } - info ("MatrixOrbital: display reports model '%s' (type 0x%02x)", - Models[i].name, Models[i].type); + info ("%s: display reports model '%s' (type 0x%02x)", + Name, Models[i].name, Models[i].type); // auto-dedection if (Model==-1) Model=i; // auto-dedection matches specified model? if (Models[i].type!=0xff && Model!=i) { - error ("MatrixOrbital: %s.Model '%s' from %s does not match dedected Model '%s'", - section, model, cfg_source(), Models[i].name); + error ("%s: %s.Model '%s' from %s does not match dedected Model '%s'", + Name, section, model, cfg_source(), Models[i].name); return -1; } } else { - info ("MatrixOrbital: display detection failed."); + info ("%s: display detection failed.", Name); } // read serial number - drv_MO_write ("\3765", 2); + drv_generic_serial_write ("\3765", 2); usleep(100000); - if (drv_MO_read (buffer, 2)==2) { - info ("MatrixOrbital: display reports serial number 0x%x", *(short*)buffer); + if (drv_generic_serial_read (buffer, 2)==2) { + info ("%s: display reports serial number 0x%x", Name, *(short*)buffer); } // read version number - drv_MO_write ("\3766", 2); + drv_generic_serial_write ("\3766", 2); usleep(100000); - if (drv_MO_read (buffer, 1)==1) { - info ("MatrixOrbital: display reports firmware version 0x%x", *buffer); + if (drv_generic_serial_read (buffer, 1)==1) { + info ("%s: display reports firmware version 0x%x", Name, *buffer); } // initialize global variables @@ -440,95 +269,28 @@ static int drv_MO_start (char *section) GPOS = Models[Model].gpos; PROTOCOL = Models[Model].protocol; - // 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(DROWS, DCOLS, XRES, YRES, CHARS, ICONS, drv_MO_define_char); - } - // init Bars - bar_init(DROWS, DCOLS, XRES, YRES, CHARS-ICONS); - bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank - bar_add_segment(255,255,255,255); // ASCII 255 = block + // Fixme + // bar_init(DROWS, DCOLS, XRES, YRES, CHARS-ICONS); + // bar_add_segment( 0, 0,255, 32); // ASCII 32 = blank + // bar_add_segment(255,255,255,255); // ASCII 255 = block - // Fixme: where to init contrast? - drv_MO_contrast(128); - if (PROTOCOL==2) - drv_MO_write ("\376\130", 2); // Clear Screen + drv_generic_serial_write ("\376\130", 2); // Clear Screen else - drv_MO_write ("\014", 1); // Clear Screen + drv_generic_serial_write ("\014", 1); // Clear Screen - 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 - - return 0; -} - + drv_generic_serial_write ("\376B", 3); // backlight on + drv_generic_serial_write ("\376K", 2); // cursor off + drv_generic_serial_write ("\376T", 2); // blink off + drv_generic_serial_write ("\376D", 2); // line wrapping off + drv_generic_serial_write ("\376R", 2); // auto scroll off -static int drv_MO_flush (void) -{ - int row, col, pos1, pos2; - int c, equal; - int gpo; - - bar_process(drv_MO_define_char); - - for (row=0; row<DROWS; row++) { - for (col=0; col<DCOLS; col++) { - c=bar_peek(row, col); - if (c==-1) c=icon_peek(row, col); - if (c!=-1) { - LayoutFB[row*DCOLS+col]=(char)c; - } - } - for (col=0; col<DCOLS; col++) { - if (LayoutFB[row*DCOLS+col]==DisplayFB[row*DCOLS+col]) continue; - drv_MO_goto (row, col); - for (pos1=col++, pos2=pos1, equal=0; col<DCOLS; col++) { - if (LayoutFB[row*DCOLS+col]==DisplayFB[row*DCOLS+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 (LayoutFB+row*DCOLS+pos1, pos2-pos1+1); - } - } - - memcpy (DisplayFB, LayoutFB, DROWS*DCOLS*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; } - // **************************************** // *** plugins *** // **************************************** @@ -543,7 +305,7 @@ static void plugin_contrast (RESULT *result, RESULT *arg1) if (contrast<0 ) contrast=0; if (contrast>255) contrast=255; snprintf (buffer, 4, "\376P%c", (int)contrast); - drv_MO_write (buffer, 3); + drv_generic_serial_write (buffer, 3); SetResult(&result, R_NUMBER, &contrast); } @@ -560,11 +322,11 @@ static void plugin_backlight (RESULT *result, RESULT *arg1) if (backlight<0) { // backlight off snprintf (buffer, 3, "\376F"); - drv_MO_write (buffer, 2); + drv_generic_serial_write (buffer, 2); } else { // backlight on for n minutes snprintf (buffer, 4, "\376B%c", (int)backlight); - drv_MO_write (buffer, 3); + drv_generic_serial_write (buffer, 3); } SetResult(&result, R_NUMBER, &backlight); } @@ -592,9 +354,9 @@ static void plugin_gpo (RESULT *result, RESULT *arg1, RESULT *arg2) case 1: if (num==0) { if (val>=1.0) { - drv_MO_write ("\376W", 2); // GPO on + drv_generic_serial_write ("\376W", 2); // GPO on } else { - drv_MO_write ("\376V", 2); // GPO off + drv_generic_serial_write ("\376V", 2); // GPO off } } else { error("Fixme"); @@ -609,7 +371,7 @@ static void plugin_gpo (RESULT *result, RESULT *arg1, RESULT *arg2) cmd[1]='V'; // GPO off } cmd[2]=(char)num; - drv_MO_write (cmd, 3); + drv_generic_serial_write (cmd, 3); break; } @@ -633,7 +395,7 @@ static void plugin_pwm (RESULT *result, RESULT *arg1, RESULT *arg2) if (val>255.0) val=255.0; cmd[3]=(char)val; - drv_MO_write (cmd, 4); + drv_generic_serial_write (cmd, 4); SetResult(&result, R_NUMBER, &val); } @@ -651,9 +413,9 @@ static void plugin_rpm (RESULT *result, RESULT *arg1) if (num>6) num=6; cmd[2]=(char)num; - drv_MO_write (cmd, 3); + drv_generic_serial_write (cmd, 3); usleep(100000); - drv_MO_read (buffer, 7); + drv_generic_serial_read (buffer, 7); debug ("rpm: buffer[0]=0x%01x", buffer[0]); debug ("rpm: buffer[1]=0x%01x", buffer[1]); @@ -668,96 +430,19 @@ static void plugin_rpm (RESULT *result, RESULT *arg1) // **************************************** -// *** internal helper functions *** -// **************************************** - -static void drv_MO_resize (int rows, int cols) -{ - char *newFB; - int row, col; - - // Layout FB is large enough - if (rows<=LROWS && cols<=LCOLS) - return; - - // allocate new Layout FB - newFB=malloc(cols*rows*sizeof(char)); - memset (newFB, ' ', rows*cols*sizeof(char)); - - // transfer contents - if (LayoutFB!=NULL) { - for (row=0; row<LROWS; row++) { - for (col=0; col<LCOLS; col++) { - newFB[row*cols+col]=LayoutFB[row*LCOLS+col]; - } - } - free (LayoutFB); - } - - LayoutFB = newFB; - LCOLS = cols; - LROWS = rows; -} - - -// **************************************** // *** widget callbacks *** // **************************************** int drv_MO_draw_text (WIDGET *W) { - WIDGET_TEXT *T=W->data; - char *txt, *fb1, *fb2; - int row, col, len, end; - - debug ("drv_MO_draw_text(%s) x=%2d y=%2d value=<%s>", W->name, W->col, W->row, T->buffer); - - row=W->row; - col=W->col; - txt=T->buffer; - len=strlen(txt); - end=col+len; - - // maybe grow layout framebuffer - drv_MO_resize (W->row, W->col+len-1); - - fb1 = LayoutFB + row*LCOLS; - fb2 = DisplayFB + row*DCOLS; - - // transfer new text into layout buffer - memcpy (fb1+col, txt, len); - - for (; col<=end; col++) { - int pos1, pos2, equal; - if (fb1[col]==fb2[col]) continue; - drv_MO_goto (row, col); - for (pos1=col, pos2=pos1, col++, equal=0; col<=end; col++) { - if (fb1[col]==fb2[col]) { - // If we find just one equal byte, we don't break, because this - // would require a goto, which takes several bytes, too. - if (++equal>5) break; - } else { - pos2=col; - equal=0; - } - } - memcpy (fb2+pos1, fb1+pos1, pos2-pos1+1); - drv_MO_write (fb2+pos1, pos2-pos1+1); - } - - return 0; + return drv_generic_text_draw_text(W, 5, drv_MO_goto, drv_generic_serial_write); } int drv_MO_draw_bar (WIDGET *W) { - WIDGET_BAR *B=W->data; - - debug ("drv_MO_draw_bar(%s) x=%2d y=%2d ", W->name, W->col, W->row); - - - return 0; + return drv_generic_text_draw_bar(W, 5, drv_MO_define_char, drv_MO_goto, drv_generic_serial_write); } @@ -784,36 +469,36 @@ int drv_MO_init (char *section) WIDGET_CLASS wc; int ret; + XRES=5; + YRES=8; + CHARS=8; + // start display if ((ret=drv_MO_start (section))!=0) return ret; - // init display framebuffer - DisplayFB = (char*)malloc(DCOLS*DROWS*sizeof(char)); - memset (DisplayFB, ' ', DROWS*DCOLS*sizeof(char)); + // initialize generic text driver + if ((ret=drv_generic_text_init(Name))!=0) + return ret; + + // initialize generic bar driver + if ((ret=drv_generic_text_bar_init())!=0) + return ret; - // init layout framebuffer - LROWS = 0; - LCOLS = 0; - LayoutFB=NULL; - drv_MO_resize (DROWS, DCOLS); - - // sanity check - if (LayoutFB==NULL || DisplayFB==NULL) { - error ("MatrixOrbital: framebuffer could not be allocated: malloc() failed"); - return -1; - } + // add fixed chars to the bar driver + drv_generic_text_bar_add_segment ( 0, 0,255, 32); // ASCII 32 = blank + drv_generic_text_bar_add_segment (255,255,255,255); // ASCII 255 = block + + // register text widget + wc=Widget_Text; + wc.draw=drv_MO_draw_text; + widget_register(&wc); // register bar widget wc=Widget_Bar; wc.draw=drv_MO_draw_bar; widget_register(&wc); - // register text widget - wc=Widget_Text; - wc.draw=drv_MO_draw_text; - widget_register(&wc); - // register plugins AddFunction ("contrast", 1, plugin_contrast); AddFunction ("backlight", 1, plugin_backlight); @@ -827,29 +512,19 @@ int drv_MO_init (char *section) // close driver & display int drv_MO_quit (void) { - info("MatrixOrbital: shutting down."); - - debug ("closing port %s", Port); - close (Device); - unlock_port(Port); - - if (LayoutFB) { - free(LayoutFB); - LayoutFB=NULL; - } - - if (DisplayFB) { - free(DisplayFB); - DisplayFB=NULL; - } + + info("%s: shutting down.", Name); + drv_generic_serial_close(); + drv_generic_quit(); return (0); } DRIVER drv_MatrixOrbital = { - name: "MatrixOrbital", - list: drv_MO_list, - init: drv_MO_init, - quit: drv_MO_quit, + name: Name, + list: drv_MO_list, + init: drv_MO_init, + quit: drv_MO_quit, }; + diff --git a/drv_generic.c b/drv_generic.c new file mode 100644 index 0000000..3375254 --- /dev/null +++ b/drv_generic.c @@ -0,0 +1,292 @@ +/* $Id: drv_generic.c,v 1.1 2004/01/20 04:51:39 reinelt Exp $ + * + * generic driver helper for text- and graphic-based displays + * + * Copyright 1999, 2000 Michael Reinelt <reinelt@eunet.at> + * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: drv_generic.c,v $ + * Revision 1.1 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * + */ + +/* + * + * exported fuctions: + * + * Fixme: document me! + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <termios.h> +#include <fcntl.h> + +#include "debug.h" +#include "cfg.h" +#include "plugin.h" +#include "lock.h" +#include "widget.h" +#include "widget_text.h" +#include "widget_bar.h" +#include "drv.h" +#include "drv_generic.h" + + +static char *Driver; +static char *Port; +static speed_t Speed; +static int Device=-1; + + +int DROWS, DCOLS; // display size +int LROWS, LCOLS; // layout size +int XRES, YRES; // pixels of one char cell +int CHARS; // number of user-defineable characters + + +char *LayoutFB = NULL; +char *DisplayFB = NULL; + + +int drv_generic_serial_open (char *driver, char *port, speed_t speed) +{ + int fd; + pid_t pid; + struct termios portset; + + Driver = driver; + Port = port; + Speed = speed; + + if ((pid=lock_port(port))!=0) { + if (pid==-1) + error ("%s: port %s could not be locked", Driver, Port); + else + error ("%s: port %s is locked by process %d", Driver, Port, pid); + return -1; + } + + fd = open(Port, O_RDWR | O_NOCTTY | O_NDELAY); + if (fd==-1) { + error ("%s: open(%s) failed: %s", Driver, Port, strerror(errno)); + unlock_port(Port); + return -1; + } + + if (tcgetattr(fd, &portset)==-1) { + error ("%s: tcgetattr(%s) failed: %s", Driver, Port, strerror(errno)); + unlock_port(Port); + return -1; + } + + cfmakeraw(&portset); + cfsetospeed(&portset, Speed); + if (tcsetattr(fd, TCSANOW, &portset)==-1) { + error ("%s: tcsetattr(%s) failed: %s", Driver, Port, strerror(errno)); + unlock_port(Port); + return -1; + } + + Device=fd; + return Device; +} + + +int drv_generic_serial_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("%s: read(%s, %d) failed: %s", Driver, Port, len, strerror(errno)); + } else if (ret!=len) { + error ("%s: partial read: len=%d ret=%d", Driver, len, ret); + } + + return ret; +} + + +void drv_generic_serial_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)); + } else if (ret!=len) { + error ("MatrixOrbital: partial write: len=%d ret=%d", len, ret); + } + + return; +} + + +int drv_generic_serial_close (void) +{ + debug ("%s: closing port %s", Driver, Port); + close (Device); + unlock_port(Port); + return 0; +} + + +void drv_generic_text_resizeFB (int rows, int cols) +{ + char *newFB; + int row, col; + + // Fixme: resize Bar FB too!!!! + + + // Layout FB is large enough + if (rows<=LROWS && cols<=LCOLS) + return; + + // allocate new Layout FB + newFB=malloc(cols*rows*sizeof(char)); + memset (newFB, ' ', rows*cols*sizeof(char)); + + // transfer contents + if (LayoutFB!=NULL) { + for (row=0; row<LROWS; row++) { + for (col=0; col<LCOLS; col++) { + newFB[row*cols+col]=LayoutFB[row*LCOLS+col]; + } + } + free (LayoutFB); + } + + LayoutFB = newFB; + LCOLS = cols; + LROWS = rows; +} + + + +// **************************************** +// *** widget callbacks *** +// **************************************** + + +int drv_generic_text_draw_text (WIDGET *W, int goto_len, + void (*drv_goto)(int row, int col), + void (*drv_write)(char *buffer, int len)) +{ + WIDGET_TEXT *T=W->data; + char *txt, *fb1, *fb2; + int row, col, len, end; + + row=W->row; + col=W->col; + txt=T->buffer; + len=strlen(txt); + end=col+len; + + // maybe grow layout framebuffer + drv_generic_text_resizeFB (row, col+len-1); + + fb1 = LayoutFB + row*LCOLS; + fb2 = DisplayFB + row*DCOLS; + + // transfer new text into layout buffer + memcpy (fb1+col, txt, len); + + for (; col<=end; col++) { + int pos1, pos2, equal; + if (fb1[col]==fb2[col]) continue; + drv_goto (row, col); + for (pos1=col, pos2=pos1, col++, equal=0; col<=end; col++) { + if (fb1[col]==fb2[col]) { + // If we find just one equal byte, we don't break, because this + // would require a goto, which takes several bytes, too. + if (++equal>goto_len) break; + } else { + pos2=col; + equal=0; + } + } + memcpy (fb2+pos1, fb1+pos1, pos2-pos1+1); + drv_write (fb2+pos1, pos2-pos1+1); + } + + return 0; +} + + +// initialize text driver +int drv_generic_text_init (char *Driver) +{ + // init display framebuffer + DisplayFB = (char*)malloc(DCOLS*DROWS*sizeof(char)); + memset (DisplayFB, ' ', DROWS*DCOLS*sizeof(char)); + + // init layout framebuffer + LROWS = 0; + LCOLS = 0; + LayoutFB=NULL; + drv_generic_text_resizeFB (DROWS, DCOLS); + + // sanity check + if (LayoutFB==NULL || DisplayFB==NULL) { + error ("%s: framebuffer could not be allocated: malloc() failed", Driver); + return -1; + } + + return 0; +} + + +// close driver +int drv_generic_quit (void) { + + if (LayoutFB) { + free(LayoutFB); + LayoutFB=NULL; + } + + if (DisplayFB) { + free(DisplayFB); + DisplayFB=NULL; + } + + return (0); +} diff --git a/drv_generic.h b/drv_generic.h new file mode 100644 index 0000000..9194548 --- /dev/null +++ b/drv_generic.h @@ -0,0 +1,74 @@ +/* $Id: drv_generic.h,v 1.1 2004/01/20 04:51:39 reinelt Exp $ + * + * generic driver helper for text- and graphic-based displays + * + * Copyright 1999, 2000 Michael Reinelt <reinelt@eunet.at> + * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: drv_generic.h,v $ + * Revision 1.1 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * + */ + +/* + * + * exported fuctions: + * + * Fixme: document me! + * + */ + +#ifndef _DRV_GENERIC_H_ +#define _DRV_GENERIC_H_ + + +#include <termios.h> +#include "widget.h" + + +extern int DROWS, DCOLS; // display size +extern int LROWS, LCOLS; // layout size +extern int XRES, YRES; // pixels of one char cell +extern int CHARS; // number of user-defineable characters + + +extern char *LayoutFB; +extern char *DisplayFB; + + +int drv_generic_serial_open (char *driver, char *port, speed_t speed); +int drv_generic_serial_read (char *string, int len); +void drv_generic_serial_write (char *string, int len); +int drv_generic_serial_close (void); + + +int drv_generic_text_init (char *Name); +void drv_generic_text_resizeFB (int rows, int cols); +int drv_generic_text_draw_text (WIDGET *W, int goto_len, + void (*drv_goto)(int row, int col), + void (*drv_write)(char *buffer, int len)); + + +int drv_generic_quit (void); + + +#endif diff --git a/drv_generic_bar.c b/drv_generic_bar.c new file mode 100644 index 0000000..0bf3f7e --- /dev/null +++ b/drv_generic_bar.c @@ -0,0 +1,471 @@ +/* $Id: drv_generic_bar.c,v 1.1 2004/01/20 04:51:39 reinelt Exp $ + * + * generic driver helper for bar creation + * + * Copyright 1999, 2000 Michael Reinelt <reinelt@eunet.at> + * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: drv_generic_bar.c,v $ + * Revision 1.1 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * + */ + +/* + * + * exported fuctions: + * + * Fixme: document me! + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "debug.h" +#include "drv.h" +#include "widget.h" +#include "widget_bar.h" +#include "drv_generic.h" +#include "drv_generic_bar.h" + + +typedef struct { + int val1; + int val2; + DIRECTION dir; + int segment; +} BAR; + +typedef struct { + int val1; + int val2; + DIRECTION dir; + int used; + int ascii; +} SEGMENT; + + +static int RES; + +static int nSegment=0; +static int fSegment=0; +static SEGMENT Segment[128]; + +static BAR *Bar=NULL; + + +int drv_generic_text_bar_init (void) +{ + if (Bar) free (Bar); + + if ((Bar=malloc (LROWS*LCOLS*sizeof(BAR)))==NULL) { + error ("bar buffer allocation failed: out of memory"); + return -1; + } + + nSegment=0; + fSegment=0; + + drv_generic_text_bar_clear(); + + return 0; +} + + +void drv_generic_text_bar_clear(void) +{ + int i; + + for (i=0; i<LROWS*LCOLS; i++) { + Bar[i].val1 = -1; + Bar[i].val2 = -1; + Bar[i].dir = 0; + Bar[i].segment = -1; + } + + for (i=0; i<nSegment;i++) { + Segment[i].used = 0; + } +} + + +void drv_generic_text_bar_add_segment(int val1, int val2, DIRECTION dir, int ascii) +{ + Segment[fSegment].val1=val1; + Segment[fSegment].val2=val2; + Segment[fSegment].dir=dir; + Segment[fSegment].used=0; + Segment[fSegment].ascii=ascii; + + fSegment++; + nSegment=fSegment; +} + + +static void drv_generic_text_bar_create_bar (int row, int col, DIRECTION dir, int len, int val1, int val2) +{ + int rev=0; + + switch (dir) { + case DIR_WEST: + val1 = len-val1; + val2 = len-val2; + rev = 1; + + case DIR_EAST: + while (len > 0 && col < LCOLS) { + Bar[row*LCOLS+col].dir=dir; + Bar[row*LCOLS+col].segment=-1; + if (val1 >= XRES) { + Bar[row*LCOLS+col].val1 = rev?0:XRES; + val1 -= XRES; + } else { + Bar[row*LCOLS+col].val1 = rev?XRES-val1:val1; + val1 = 0; + } + if (val2 >= XRES) { + Bar[row*LCOLS+col].val2 = rev?0:XRES; + val2 -= XRES; + } else { + Bar[row*LCOLS+col].val2 = rev?XRES-val2:val2; + val2 = 0; + } + len--; + col++; + } + break; + + case DIR_SOUTH: + val1 = len-val1; + val2 = len-val2; + rev = 1; + + case DIR_NORTH: + while (len > 0 && row < LROWS) { + Bar[row*LCOLS+col].dir=dir; + Bar[row*LCOLS+col].segment=-1; + if (val1 >= YRES) { + Bar[row*LCOLS+col].val1 = rev?0:YRES; + val1 -= YRES; + } else { + Bar[row*LCOLS+col].val1 = rev?YRES-val1:val1; + val1 = 0; + } + if (val2 >= YRES) { + Bar[row*LCOLS+col].val2 = rev?0:YRES; + val2 -= YRES; + } else { + Bar[row*LCOLS+col].val2 = rev?YRES-val2:val2; + val2 = 0; + } + len--; + row++; + } + break; + + } +} + + +static void drv_generic_text_bar_create_segments (void) +{ + int i, j, n; + int res, l1, l2; + + /* find first unused segment */ + for (i=fSegment; i<nSegment && Segment[i].used; i++); + + /* pack unused segments */ + for (j=i+1; j<nSegment; j++) { + if (Segment[j].used) + Segment[i++]=Segment[j]; + } + nSegment=i; + + /* create needed segments */ + for (n=0; n<LROWS*LCOLS; n++) { + if (Bar[n].dir==0) continue; + res=Bar[n].dir & (DIR_EAST|DIR_WEST) ? XRES:YRES; + for (i=0; i<nSegment; i++) { + if (Segment[i].dir & Bar[n].dir) { + l1 = Segment[i].val1; if (l1>RES) l1=RES; + l2 = Segment[i].val2; if (l2>RES) l2=RES; + if (l1 == Bar[n].val1 && l2 == Bar[n].val2) break; + } + } + if (i==nSegment) { + nSegment++; + Segment[i].val1=Bar[n].val1; + Segment[i].val2=Bar[n].val2; + Segment[i].dir=Bar[n].dir; + Segment[i].used=0; + Segment[i].ascii=-1; + } + Bar[n].segment=i; + } +} + + +static int drv_generic_text_bar_segment_error (int i, int j) +{ + int res; + int i1, i2, j1, j2; + + if (i==j) return 65535; + if (!(Segment[i].dir & Segment[j].dir)) return 65535; + + res = Segment[i].dir&(DIR_EAST|DIR_WEST) ? XRES:YRES; + + i1=Segment[i].val1; if (i1>res) i1=res; + i2=Segment[i].val2; if (i2>res) i2=res; + j1=Segment[j].val1; if (j1>res) j1=res; + j2=Segment[j].val2; if (j2>res) j2=res; + + if (i1==0 && j1!=0) return 65535; + if (i2==0 && j2!=0) return 65535; + if (i1==res && j1<res) return 65535; + if (i2==res && j2<res) return 65535; + if (i1==1 && j1!=1 && i2 > 0) return 65535; + if (i2==1 && j2!=1 && j1 > 0) return 65535; + if (i1==i2 && j1!=j2) return 65535; + + return (i1-j1)*(i1-j1)+(i2-j2)*(i2-j2); +} + + +static void drv_generic_text_bar_pack_segments (void) +{ + int i, j, n, min; + int pack_i, pack_j; + int pass1=1; + int error[nSegment][nSegment]; + + if (nSegment<=fSegment+CHARS) { + return; + } + + for (i=0; i<nSegment; i++) { + for (j=0; j<nSegment; j++) { + error[i][j]=drv_generic_text_bar_segment_error(i,j); + } + } + + while (nSegment>fSegment+CHARS) { + + min=65535; + pack_i=-1; + pack_j=-1; + for (i=fSegment; i<nSegment; i++) { + if (pass1 && Segment[i].used) continue; + for (j=0; j<nSegment; j++) { + if (error[i][j]<min) { + min=error[i][j]; + pack_i=i; + pack_j=j; + } + } + } + if (pack_i==-1) { + if (pass1) { + pass1=0; + continue; + } else { + error ("unable to compact bar characters"); + nSegment=CHARS; + break; + } + } + +#if 1 + debug ("pack_segment: n=%d i=%d j=%d min=%d", nSegment, pack_i, pack_j, min); + debug ("Pack_segment: i1=%d i2=%d j1=%d j2=%d\n", + Segment[pack_i].val1, Segment[pack_i].val2, + Segment[pack_j].val1, Segment[pack_j].val2); +#endif + + nSegment--; + Segment[pack_i]=Segment[nSegment]; + + for (i=0; i<nSegment; i++) { + error[pack_i][i]=error[nSegment][i]; + error[i][pack_i]=error[i][nSegment]; + } + + for (n=0; n<LROWS*LCOLS; n++) { + if (Bar[n].segment==pack_i) Bar[n].segment=pack_j; + if (Bar[n].segment==nSegment) Bar[n].segment=pack_i; + } + } +} + + +static void drv_generic_text_bar_define_chars (void(*defchar)(int ascii, char *matrix)) +{ + int c, i, j; + char buffer[8]; + + for (i=fSegment; i<nSegment; i++) { + if (Segment[i].used) continue; + if (Segment[i].ascii!=-1) continue; + for (c=0; c<CHARS; c++) { + for (j=fSegment; j<nSegment; j++) { + if (Segment[j].ascii==c) break; + } + if (j==nSegment) break; + } + Segment[i].ascii=c; + switch (Segment[i].dir) { + case DIR_EAST: + for (j=0; j<4; j++) { + buffer[j ]=(1<<Segment[i].val1)-1; + buffer[j+4]=(1<<Segment[i].val2)-1; + } + break; + case DIR_WEST: + for (j=0; j<4; j++) { + buffer[j ]=255<<(XRES-Segment[i].val1); + buffer[j+4]=255<<(XRES-Segment[i].val2); + } + break; + case DIR_NORTH: + for (j=0; j<Segment[i].val1; j++) { + buffer[7-j]=(1<<XRES)-1; + } + for (; j<YRES; j++) { + buffer[7-j]=0; + } + break; + case DIR_SOUTH: + for (j=0; j<Segment[i].val1; j++) { + buffer[j]=(1<<XRES)-1; + } + for (; j<YRES; j++) { + buffer[j]=0; + } + break; + } + defchar(c, buffer); + } +} + + +int drv_generic_text_draw_bar (WIDGET *W, int goto_len, + void (*drv_defchar)(int ascii, char *buffer), + void (*drv_goto)(int row, int col), + void (*drv_write)(char *buffer, int len)) +{ + WIDGET_BAR *B = W->data; + int row, col, len, max, val1, val2; + int c, n, s; + DIRECTION dir; + + row = W->row; + col = W->col; + dir = B->direction; + len = B->length; + + // maybe grow layout framebuffer + // bars *always* grow heading North or East! + if (dir==DIR_EAST || dir==DIR_WEST) { + drv_generic_text_resizeFB (row, col+len-1); + RES = XRES; + } else { + drv_generic_text_resizeFB (row, col); + RES = YRES; + } + max = len * RES; + val1 = B->val1 * (double)(max); + val2 = B->val2 * (double)(max); + + if (val1<1) val1=1; + else if (val1>max) val1=max; + + if (val2<1) val2=1; + else if (val2>max) val2=max; + + // create this bar + drv_generic_text_bar_create_bar (row, col, dir, len, val1, val2); + + // process all bars + drv_generic_text_bar_create_segments (); + drv_generic_text_bar_pack_segments (); + drv_generic_text_bar_define_chars(drv_defchar); + + // reset usage flags + for (s=0; s<nSegment; s++) { + Segment[s].used=0; + } + + // set usage flags + for (n=0; n<LROWS*LCOLS; n++) { + if ((s=Bar[n].segment)!=-1) Segment[s].used=1; + } + + // transfer bars into layout buffer + for (n=0; n<LCOLS*LROWS; n++) { + s=Bar[n].segment; + if (s==-1) continue; + c=Segment[s].ascii; + if (c==-1) continue; + if(c==LayoutFB[n]) continue; + LayoutFB[n]=c; + } + + // transfer differences to the display + for (row=0; row<DROWS; row++) { + for (col=0; col<DCOLS; col++) { + int pos1, pos2, equal; + if (LayoutFB[row*LCOLS+col]==DisplayFB[row*DCOLS+col]) continue; + drv_goto (row, col); + for (pos1=col, pos2=pos1, col++, equal=0; col<DCOLS; col++) { + if (LayoutFB[row*LCOLS+col]==DisplayFB[row*DCOLS+col]) { + // If we find just one equal byte, we don't break, because this + // would require a goto, which takes several bytes, too. + if (++equal>goto_len) break; + } else { + pos2=col; + equal=0; + } + } + memcpy (DisplayFB+row*DCOLS+pos1, LayoutFB+row*LCOLS+pos1, pos2-pos1+1); + drv_write (DisplayFB+row*DCOLS+pos1, pos2-pos1+1); + debug ("Michi: bar(%d,%d) len=%d", row, pos1, pos2-pos1+1); + } + } + + return 0; + +} + +int drv_generic_text_bar_peek (int row, int col) +{ + int s; + + s=Bar[row*LCOLS+col].segment; + if (s==-1) { + return -1; + } else { + return Segment[s].ascii; + } +} + diff --git a/drv_generic_bar.h b/drv_generic_bar.h new file mode 100644 index 0000000..8bd3866 --- /dev/null +++ b/drv_generic_bar.h @@ -0,0 +1,43 @@ +/* $Id: drv_generic_bar.h,v 1.1 2004/01/20 04:51:39 reinelt Exp $ + * + * generic driver helper for bar creation + * + * Copyright 1999, 2000 Michael Reinelt <reinelt@eunet.at> + * Copyright 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * $Log: drv_generic_bar.h,v $ + * Revision 1.1 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * + */ + +#ifndef _DRV_GENERIC_BAR_H_ +#define _DRV_GENERIC_BAR_H_ + +int drv_generic_text_bar_init (void); +void drv_generic_text_bar_clear(void); +void drv_generic_text_bar_add_segment(int val1, int val2, DIRECTION dir, int ascii); +int drv_generic_text_draw_bar (WIDGET *W, int goto_len, + void (*drv_defchar)(int ascii, char *buffer), + void (*drv_goto)(int row, int col), + void (*drv_write)(char *buffer, int len)); + +#endif diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample index 4082210..b3ecb18 100644 --- a/lcd4linux.conf.sample +++ b/lcd4linux.conf.sample @@ -2,7 +2,7 @@ Display LK204 { Driver 'MatrixOrbital' Model 'LK204-24-USB' Port '/dev/usb/tts/0' - Port '/dev/tts/0' +# Port '/dev/tts/0' Speed 19200 Contrast 256/2 } @@ -38,7 +38,7 @@ Widget RAM { Widget Busy { class 'Text' expression cpu('busy', 500) - prefix 'Busy ' + prefix 'Busy' postfix '%' width 10 precision 1 @@ -46,15 +46,23 @@ Widget Busy { update tick } +Widget BusyBar { + class 'Bar' + expression cpu('busy', 500) + length 10 + direction 'E' + update tack +} + Widget Load { class 'Text' expression loadavg(1) prefix 'Load' postfix loadavg(1)>1.0?'!':' ' width 10 - precision 2 + precision 1 align 'R' - update tack + update tick } @@ -67,7 +75,8 @@ Layout Default { Col10 'RAM' } Row3 { - Col1 'Busy' + Col1 'Busy' + Col10 'BusyBar' } Row4 { Col1 'Load' diff --git a/widget_bar.c b/widget_bar.c index 7ed6f28..f28c95c 100644 --- a/widget_bar.c +++ b/widget_bar.c @@ -1,4 +1,4 @@ -/* $Id: widget_bar.c,v 1.1 2004/01/18 21:25:16 reinelt Exp $ +/* $Id: widget_bar.c,v 1.2 2004/01/20 04:51:39 reinelt Exp $ * * bar widget handling * @@ -21,6 +21,10 @@ * * * $Log: widget_bar.c,v $ + * Revision 1.2 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * * Revision 1.1 2004/01/18 21:25:16 reinelt * Framework for bar widget opened * @@ -53,9 +57,67 @@ void widget_bar_update (void *Self) WIDGET *W = (WIDGET*)Self; WIDGET_BAR *T = W->data; RESULT result = {0, 0.0, NULL}; + + double val1, val2; + double min, max; + + // evaluate expressions + val1=0.0; + if (T->expression1!=NULL && *T->expression1!='\0') { + Eval(T->expression1, &result); + val1 = R2N(&result); + DelResult(&result); + } + + val2=0.0; + if (T->expression2!=NULL && *T->expression2!='\0') { + Eval(T->expression2, &result); + val2 = R2N(&result); + DelResult(&result); + } + + // minimum: if expression is empty, do auto-scaling + if (T->expr_min!=NULL && *T->expr_min!='\0') { + Eval(T->expr_min, &result); + min = R2N(&result); + DelResult(&result); + } else { + min = T->min; + if (val1 < min) min = val1; + if (val2 < min) min = val2; + } + + // maximum: if expression is empty, do auto-scaling + if (T->expr_max!=NULL && *T->expr_max!='\0') { + Eval(T->expr_max, &result); + max = R2N(&result); + DelResult(&result); + } else { + max = T->max; + if (val1 > max) max = val1; + if (val2 > max) max = val2; + } + + + // calculate bar values + T->min=min; + T->max=max; + if (max>min) { + T->val1=(val1-min)/(max-min); + T->val2=(val2-min)/(max-min); + } else { + T->val1=0.0; + T->val2=0.0; + } + + // finally, draw it! + if (W->class->draw) + W->class->draw(W); + } + int widget_bar_init (WIDGET *Self) { char *section; char *c; @@ -71,9 +133,13 @@ int widget_bar_init (WIDGET *Self) memset (B, 0, sizeof(WIDGET_BAR)); // get raw expressions (we evaluate them ourselves) - B->expression1 = cfg_get_raw (section, "expression", "''"); - B->expression2 = cfg_get_raw (section, "expression2", "''"); + B->expression1 = cfg_get_raw (section, "expression", NULL); + B->expression2 = cfg_get_raw (section, "expression2", NULL); + // minimum and maximum value + B->expr_min = cfg_get_raw (section, "min", NULL); + B->expr_max = cfg_get_raw (section, "max", NULL); + // bar length, default 1 cfg_number (section, "length", 1, 0, 99999, &(B->length)); @@ -107,8 +173,10 @@ int widget_bar_init (WIDGET *Self) free (section); Self->data=B; + debug ("Michi: widget_bar added..."); + timer_add (widget_bar_update, Self, B->update, 0); - + return 0; } @@ -127,7 +195,7 @@ int widget_bar_quit (WIDGET *Self) { WIDGET_CLASS Widget_Bar = { - name: "text", + name: "bar", init: widget_bar_init, draw: NULL, quit: widget_bar_quit, diff --git a/widget_bar.h b/widget_bar.h index 3c725cc..977df98 100644 --- a/widget_bar.h +++ b/widget_bar.h @@ -1,4 +1,4 @@ -/* $Id: widget_bar.h,v 1.1 2004/01/18 21:25:16 reinelt Exp $ +/* $Id: widget_bar.h,v 1.2 2004/01/20 04:51:39 reinelt Exp $ * * bar widget handling * @@ -23,6 +23,10 @@ * * * $Log: widget_bar.h,v $ + * Revision 1.2 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * * Revision 1.1 2004/01/18 21:25:16 reinelt * Framework for bar widget opened * @@ -32,15 +36,20 @@ #ifndef _WIDGET_BAR_H_ #define _WIDGET_BAR_H_ -typedef enum { DIR_EAST, DIR_WEST, DIR_NORTH, DIR_SOUTH } DIRECTION; +typedef enum { DIR_EAST=1, DIR_WEST=2, DIR_NORTH=4, DIR_SOUTH=8 } DIRECTION; typedef struct WIDGET_BAR { char *expression1; // expression that delivers the value char *expression2; // expression that delivers the value + char *expr_min; // expression that delivers the minimum value + char *expr_max; // expression that delivers the maximum value DIRECTION direction; // bar direction int length; // bar length int update; // update interval (msec) - + double val1; // bar value, 0.0 ... 1.0 + double val2; // bar value, 0.0 ... 1.0 + double min; // minimum value + double max; // maximum value } WIDGET_BAR; diff --git a/widget_text.c b/widget_text.c index 9d99b2c..aa30eec 100644 --- a/widget_text.c +++ b/widget_text.c @@ -1,4 +1,4 @@ -/* $Id: widget_text.c,v 1.6 2004/01/15 07:47:02 reinelt Exp $ +/* $Id: widget_text.c,v 1.7 2004/01/20 04:51:39 reinelt Exp $ * * simple text widget handling * @@ -21,6 +21,10 @@ * * * $Log: widget_text.c,v $ + * Revision 1.7 2004/01/20 04:51:39 reinelt + * moved generic stuff from drv_MatrixOrbital to drv_generic + * implemented new-stylish bars which are nearly finished + * * Revision 1.6 2004/01/15 07:47:02 reinelt * debian/ postinst and watch added (did CVS forget about them?) * evaluator: conditional expressions (a?b:c) added @@ -164,6 +168,7 @@ void widget_text_scroll (void *Self) } + void widget_text_update (void *Self) { WIDGET *W = (WIDGET*)Self; |