]> git.webhop.me Git - lcd4linux.git/commitdiff
[lcd4linux @ 2004-01-20 04:51:39 by reinelt]
authorreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Tue, 20 Jan 2004 04:51:39 +0000 (04:51 +0000)
committerreinelt <reinelt@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Tue, 20 Jan 2004 04:51:39 +0000 (04:51 +0000)
moved generic stuff from drv_MatrixOrbital to drv_generic
implemented new-stylish bars which are nearly finished

git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@321 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

Makefile.am
Makefile.in
drv_MatrixOrbital.c
drv_generic.c [new file with mode: 0644]
drv_generic.h [new file with mode: 0644]
drv_generic_bar.c [new file with mode: 0644]
drv_generic_bar.h [new file with mode: 0644]
lcd4linux.conf.sample
widget_bar.c
widget_bar.h
widget_text.c

index d0b573205e6cd56578356c68724f6f523721257a..c11e88192eaa1b68bfddd7ee9fa43e45877cafb3 100644 (file)
@@ -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 \
index 9d903e328b1e73f3292a042eaae7beaa12e0d067..18a2148e941aae54cd7bb5d51fc0d9b66b11e4e0 100644 (file)
@@ -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 \
index 96692aed4cd8aa4b73ff365a00e40278ce6b6be7..1fb70d6869a01ef74f03e85d922d2f448bf97d11 100644 (file)
@@ -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
  *
  *
  *
  * $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
  *
 #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]);
@@ -667,39 +429,6 @@ 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          ***
 // ****************************************
@@ -707,57 +436,13 @@ static void drv_MO_resize (int rows, int cols)
 
 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 (file)
index 0000000..3375254
--- /dev/null
@@ -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 (file)
index 0000000..9194548
--- /dev/null
@@ -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 (file)
index 0000000..0bf3f7e
--- /dev/null
@@ -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 (file)
index 0000000..8bd3866
--- /dev/null
@@ -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
index 40822105aed69c356c0c233f168b6742ad824569..b3ecb18ddf002d085589dcd711124e881fb7eb5b 100644 (file)
@@ -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'
index 7ed6f288d0c3d7b9495ae302fce73b98710dc3a6..f28c95cdfc1f908e8dc687ff976e3e1521ee8790 100644 (file)
@@ -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
  *
  *
  *
  * $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,
index 3c725cce1dffa7cfa0ff4d74afbddbb2f491be95..977df98bab39b3607c950dcce5b4477516801a7a 100644 (file)
@@ -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
  *
  *
  *
  * $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
  *
 #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;
 
 
index 9d99b2c8aaf6b22eb4cdbf703344cb3649ef587f..aa30eecf45fdfa3640dde37af74ae3da4af17f84 100644 (file)
@@ -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
  *
  *
  *
  * $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;