chiark / gitweb /
abstracted bit stuff
authorian <ian>
Sat, 23 Oct 2004 16:23:31 +0000 (16:23 +0000)
committerian <ian>
Sat, 23 Oct 2004 16:23:31 +0000 (16:23 +0000)
TODO
layout/Makefile
layout/compose-segenco.c
layout/layout
layout/segcmap.h [new file with mode: 0644]
layout/segcmapassign
layout/subseg2display.c

diff --git a/TODO b/TODO
index f7f33b4c597c732c4cd42b312cc6ea994364e5ac..dafba0f6430e55d644e546c8933892278352e359 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
 layout polarity diagram colourful segment encoding:
- abstract away the pixel encoding scheme, at least somewhat
  implement segmap so that we can do midx
  decide what to do about crossings (difficult to show both tracks)
  wire layout diagram thing into Tcl and see speed etc.
index 86e45356349d45c2c75673e25fce88b4e5bd4bd4..e1903fcc51330a4129f359e5c03dea36fcfbe50e 100644 (file)
@@ -54,7 +54,7 @@ compose-segenco: compose-segenco.o
 %.segcmapreq:  %.run-layout
                ./$< $(LAYOUTOPTS_SEGS) -GR $o
 
-%.segcmap:     %.segcmapreq segcmapassign
+%.segcmap:     %.segcmapreq segcmapassign segcmap.h
                ./segcmapassign <$< $o
 
 %.dgram.m:     %.dgram-list make-dgram-make
@@ -86,6 +86,8 @@ parts.ps:     showlib.d4 layout
 t.ppm:         ours.dgram-bot.pa.segenco.ppm x.gdb subseg2display
                gdb -x x.gdb
 
+subseg2display.o compose-segenco.o: segcmap.h
+
 clean:
                -rm -f -- *.d4 *~ t.* *.m *.new core
                -rm -f ours-*.ps parts.ps
index fcc6c6a1452ca4456f43eb21eeedcf6613065e22..94e4fcb5af366bef14c401b480cd8a95c7a7a05d 100644 (file)
@@ -17,7 +17,9 @@
 
 #include <ppm.h>
 
-#define FILES 7
+#include "segcmap.h"
+
+#define FILES (MOVFEATPOS_BITS+1)
 
 struct file {
   const char *fn;
@@ -74,10 +76,11 @@ int main(int argc, char **argv) {
       int gotsegnum=-1, gotmovfeatpos=-1;
       val ov[3];
 
-      ov[0]= ov[1]= ov[2]= 255;
+      DATUM2ARY(ov, BACKGROUND);
       
       for (fi=0; fi<nf; fi++) {
        val iv[3];
+       unsigned long datum;
        int segnum, movfeatpos;
        
        if (fread(iv,1,3,f[fi].f)!=3) {
@@ -85,11 +88,13 @@ int main(int argc, char **argv) {
          else badformat("truncated file");
        }
 
-       if (iv[0]==255 && iv[1]==255 && iv[2]==255)
+       datum= ARY2DATUM(iv);
+
+       if (datum == BACKGROUND)
          continue;
 
-       segnum= ((iv[2] & 0x03) << 8) | iv[3];
-       movfeatpos= iv[1] & 0x0fc;
+       segnum= DATUM2(SEGNUM,datum);
+       movfeatpos= DATUM2(MOVFEATPOS,datum);
 
        if (!!fi != !!movfeatpos)
          badformat("moveable featureness disagrees with file index");
@@ -102,7 +107,9 @@ int main(int argc, char **argv) {
          continue;
        }
        if (fi) {
-         ov[1] |= 0x100 >> fi; /* bits are reversed; first fi pos 1 not 0 */
+         datum= ARY2DATUM(ov);
+         datum |= 1UL << (fi-1 + MOVFEATPOS_BASEBIT);
+         DATUM2ARY(ov,datum);
        }
       }
 
index 4b3ecc67acd878cbec125b6ed6b56c29daeb9abe..391d7c6a6204cfaee05a0619f22c6f6b32d302d9 100755 (executable)
@@ -15,6 +15,7 @@ our $debug=0;
 our $output_layer= '*';
 our $subsegcmapreq=0;
 our $subsegmovfeatpos='f';
+our $subsegcmapangscale;
 
 our $ps_page_shift= 615;
 our $ps_page_xmul= 765.354;
@@ -55,7 +56,7 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
        elsif (s/^GP(\d+|f)$//) { $subsegmovfeatpos=$1; }
        elsif (s/^GL(.*)$//) {
            my ($sscmfn) = $1;
-           my ($sscmf);
+           my ($sscmf, $datum, $csss, $angbits);
            local ($_);
            $sscmf= new IO::File $sscmfn, 'r'
                or die "$sscmfn: cannot open: $!\n";
@@ -63,9 +64,18 @@ while (@ARGV && $ARGV[0] =~ m/^\-/) {
                $!=0; $_= <$sscmf>; die $! unless defined $_;
                last if m/^E/;
                next unless m/^C/;
-               m,^C\s+(\w*/(?:[A-Za-z_]+)?)\s+(\S.*\S)\s*$,
+               m,^C\s+(\w*/(?:[A-Za-z_]+)?)\s+(0x[0-9a-f]+)\s+(\d+)\s*$,
                    or die "$sscmfn:$.: syntax error in subseg cmap\n";
-               $subsegcmap{$1}= $2;
+               ($csss,$datum,$angbits)= ($1,$2,$3);
+               if (!defined $subsegcmapangscale) {
+                   $subsegcmapangscale= 1<<$angbits;
+               } else {
+                   die "angbits varies" if $subsegcmapangscale != 1<<$angbits;
+               }
+               $datum= hex($datum);
+               $subsegcmap{$csss}= sprintf("%.6f %.6f",
+                                           (($datum >> 8) & 0xff)/255.0,
+                                           (($datum >> 16) & 0xff)/255.0);
            }
            $sscmf->error and die "$sscmfn: error reading: $!\n";
            close $sscmf;
@@ -670,11 +680,10 @@ print DEBUG "ps $p0 $p1 $lenperp ($ppu)\n";
                die "unknown subsegment colour for $csegbare\n"
                    unless exists $subsegcmap{$csegbare};
                $red= $pt->{A} / (2*$pi);
-               $red *= 64;
-               $red += 128;
-               $red += 32 if $segments[0] =~ m/^\-/;
-               $red %= 64;
-               $red <<= 2;
+               $red *= $subsegcmapangscale;
+               $red += $subsegcmapangscale*2;
+               $red += $subsegcmapangscale/2 if $segments[0] =~ m/^\-/;
+               $red %= $subsegcmapangscale;
                $red /= 255.0;
                $red= sprintf("%f", $red);
                o("    $red $subsegcmap{$csegbare} setrgbcolor\n");
diff --git a/layout/segcmap.h b/layout/segcmap.h
new file mode 100644 (file)
index 0000000..1f8d35c
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ *
+ * Encodings in segment encodings are as follows:
+ *  firstly, assemble the R, G, B bytes like this:
+ *       blue << 16  |  green << 8  |  red
+ *
+ * Now interpret the resulting 24-bit datum as a bit sequence with the
+ * following parts (LSbit first):
+ *     bits
+ *       6*     moveable feature and position                  } blue
+ *      10*     segment number                                 } blue/green
+ *       1*     reserved - always 0                            } red
+ *       1      `edge'(1) or `core'(0) - currently always 0    } red
+ *       6*     angle                                          } red
+ *
+ * Each moveable feature has an unambiguous prefix the remainder of the
+ * moveable feature bits are the positions of that feature (LSbit is
+ * position 0, etc.).  The feature all-bits-0 (0b000000) is for fixed track
+ * (so every moveable feature prefix must contain at least one 1).
+ *
+ * The unknown/unidentified segment is all-bits-0, with feature
+ * all-bits-0 for fixed parts and feature 0b1.... for moveable parts.
+ * Background is white (all bits set).
+ *
+ * Items marked * can have the number of bits allocated to them
+ * adjusted - see below.
+ */
+
+#ifndef SEGMAP_H
+#define SEGMAP_H
+
+/*---------- bit widths of various datum fields ----------*/
+
+/* Be careful editing this bit: you may change the number of bits
+ * within reason, but preserve the format of the file and the ordering
+ * of info in the datum.  Both segcmapassign and layout have knowledge
+ * of the datum format that doesn't come from here, although there
+ * are arrangements to read the widths of the fields from here. */
+
+#define ANGLE_BITS        6
+#define MOVFEATPOS_BITS   6
+#define SEGNUM_BITS      10
+/* do not make these add up to more than 23 */
+
+/*---------- datum assembly/disassembly macros ----------*/
+
+/* It wouldn't be adviseable to change things beyond this point
+ * without considering editing segcmapassign, layout and various
+ * comments and associated machinery. */
+
+#define BACKGROUND    0x00ffffffUL
+
+#define MOVFEATPOS_BASEBIT (24-MOVFEATPOS_BITS)
+#define SEGNUM_BASEBIT (MOVFEATPOS_BASEBIT-SEGNUM_BITS)
+#define ANGLE_BASEBIT 0
+#define RESERVED_BITS (SEGNUM_BASEBIT-ANGLE_BITS-1)
+
+#define MKMASK(v) (((1UL)<<(v))-1)
+#define DATUM2(q,l) (((l) >> q##_BASEBIT) & MKMASK(q##_BITS))
+#define RESERVED_MASK (MKMASK(RESERVED_BITS+1) << ANGLE_BITS)
+
+/*---------- useful utility macros ----------*/
+                      
+#define RGB2DATUM(r,g,b) (((b)<<16) | ((g)<<8) | (r))
+#define ARY2DATUM(a) RGB2DATUM((a)[0],(a)[1],(a)[2])
+#define DATUM2RGB(r,g,b,l) ((r) = (l)&0xff,            \
+                           (g) = ((l)>>8)&0xff,        \
+                           (b) = ((l)>>16)&0xff)
+#define DATUM2ARY(a,l) DATUM2RGB((a)[0],(a)[1],(a)[2],(l))
+
+/*---------- consequences of the datum format ----------*/
+
+#define ANGLE_TOPBIT (1<<(ANGLE_BITS-1))
+#define NANGLES (1<<ANGLE_BITS)
+#define ANGLE_MAX (NANGLES-1)
+
+#define SEGNUM_MAX ((1<<SEGNUM_BITS)-1)
+#define MOVFEATPOS_MAX ((1<<MOVFEATPOS_BITS)-1)
+
+
+#endif /*SEGMAP_H*/
index e2b23b8af627bff3208d3f91fc5e94465388033e..00c6935e8d2345517d04a6432bd20d3f8e2dad22 100755 (executable)
@@ -5,12 +5,9 @@
 # output:
 #   lines:
 #
-# C <csss> <green> <blue>
-#   where <csss> is N/[M] (see informat.txt) and <green> and <blue>
-#   contain no whitespace and are suitable for inserting like this
-#   into the PostScript output:
-#         ...code to compute and stack red in range [0,1>...
-#          <green> <blue> setrgbcolor
+# C <csss> 0x<datum> <angle-bits>
+#   where <csss> is N/[M] (see informat.txt) and <datum>
+#   is the hex value of the datum (see segmap.h)
 #
 # S <segname> 0x<segnum>
 # F <segname> 0x<segnum> <featname> 0x<prefix> <configbits>
 # # comments for debugging segcmapassign etc.
 # E
 #     final line, always present
-#
-# Encoding in final segment encoding map is as follows
-# (bits from MSbit to LSbit):
-#
-#  RED
-#     6 bits angle
-#     1 bit reserved (0)
-#     1 bit `edge or core' (currently 0 meaning `core')
-#
-#  GREEN
-#     2 bits segment overflow
-#     6 bits moveable feature and position
-#          each moveable feature has an unambiguous prefix
-#          the remainder of the bits are the positions of that feature
-#          (LSbit is position 0, etc.)
-#       the feature all-bits-0 (0b000000) is for fixed track
-#       (so every moveable feature prefix must contain at least one 1)
-#     BUT all of the bits are in the reverse order (so the
-#     MSbit of GREEN is the LSbit of the moveable feature and position)
-#
-#  BLUE
-#     8 bits segment main IN REVERSE ORDER
-#
-# The unknown/unidentified segment is 00 0000 0000, with feature 00 0000
-# for fixed parts and feature 1x xxxx for moveable parts.
-# Background is white (all bits set).
 
 use strict;
 use IO::Handle;
@@ -53,31 +24,43 @@ use IO::Handle;
 our ($seg,$movfeat,$movconf,$si,$fi);
 our (%seg);
 
+our %bits;
+
+sub read_segcmap_h () {
+    my ($p);
+    open H, "< segcmap.h" or die $!;
+    map { $bits{$_}=0 } qw(Angle Movfeatpos Segnum);
+    while (<H>) {
+       next unless m/^\#define\s+([A-Z])([A-Z]*)_BITS\s+([1-9]\d*)\s*$/;
+       $p= uc($1).lc($2);
+       next unless exists $bits{$p};
+       die $p if $bits{$p};
+       $bits{$p}= $3;
+    }
+    map { die $_ unless $bits{$_} } keys %bits;
+}
+
+read_segcmap_h();
+
 sub cssnmap ($$$$) {
     my ($seg,$movfeat,$segnum,$posinfo) = @_;
-    my ($green,$blue,$greenr,$bluer);
-    $green= (($segnum >> 8) & 0x03)<<6;
-    $green |= $posinfo;
-    $blue= $segnum & 0xff;
-    $greenr= reverse_bits_in_byte($green);
-    $bluer= reverse_bits_in_byte($blue);
-    printf("C %s/%s %.6f %.6f\n".
-          "# %s/%s 0x%x 0x%x 0x%x 0x%x\n",
-          $seg,$movfeat, $greenr/255.0, $bluer/255.0,
-          $seg,$movfeat, $green, $blue, $greenr, $bluer)
+    my ($datum);
+    $datum=
+       ($posinfo << (24 - $bits{Movfeatpos})) |
+       ($segnum << (24 - $bits{Angle} - $bits{Segnum}));
+    printf("C %s/%s 0x%012x %d\n",
+          $seg, $movfeat, $datum, $bits{Angle})
        or die $!;
 }
 
-our $movfeatposbits= 6;
-
 while (<>) {
     m,^(\w*)/([A-Za-z_]*)(\d*)$, or die;
     ($seg,$movfeat,$movconf)=($1,$2,$3);
     if (!length $seg) {
        die "too many $seg $movfeat" if
-           length $movfeat && $movconf >= $movfeatposbits-1;
+           length $movfeat && $movconf >= $bits{Movfeatpos}-1;
        cssnmap($seg,$movfeat,0,
-               length $movfeat ? 1<<($movfeatposbits-1) : 0);
+               length $movfeat ? 1<<($bits{Movfeatpos}-1) : 0);
        next;
     }
     die if length $movconf && !length $movfeat;
@@ -91,15 +74,6 @@ while (<>) {
     }
 }
 
-sub reverse_bits_in_byte ($) {
-    my ($a) = @_;
-    my ($b,$c,$d);
-    $b= (($a >> 1) & 0x55) | (($a << 1) & 0xaa);
-    $c= (($b >> 2) & 0x33) | (($b << 2) & 0xcc);
-    $d= (($c >> 4) & 0x0f) | (($c << 4) & 0xf0);
-    return $d;
-}
-
 our ($segnum) = 1;
 
 our ($conf,$posbit,$posbiti,$abovenext);
@@ -107,8 +81,8 @@ our ($conf,$posbit,$posbiti,$abovenext);
 foreach $seg (sort keys %seg) {
     $si= $seg{$seg};
     $si->{Num}= $segnum++;
-    die if $si->{Num} >= 1024;
-    $abovenext= 1<<$movfeatposbits;
+    die if $si->{Num} >= 1 << $bits{Segnum};
+    $abovenext= 1 << $bits{Movfeatpos};
     printf("S %s 0x%x\n",
           $seg, $si->{Num})
        or die $!;
index fa4e0202c55a7b7fb2b7b8423b6de826fae24ce9..4653b8a53701ceedbc97c6ced96edabe8bccc223 100644 (file)
@@ -38,6 +38,8 @@
 #include <publib.h>
 #include <ppm.h>
 
+#include "segcmap.h"
+
 /*---------- lookup data structure ----------*/
 
 struct result {
@@ -52,8 +54,6 @@ struct movperseg {
 };
 
 #define NCHARS 256
-#define MAXSEGNUM ((1<<10)-1)
-#define MAXMOVFEATPOS ((1<<6)-1)
 
 static struct result idinfo[NCHARS];
 static struct result background;
@@ -153,7 +153,7 @@ static void subsegarg(id ix, const char *arg) {
   errno= 0;
   segnum= strtoul(arg,&ep,0);
   if (errno) badusage();
-  if (segnum > MAXSEGNUM) badusage();
+  if (segnum > SEGNUM_MAX) badusage();
 
   if (!*ep) {
     ensure_ids(&fixed,&fixed_a,segnum);
@@ -166,12 +166,12 @@ static void subsegarg(id ix, const char *arg) {
   errno= 0;
   movfeatpos= strtoul(ep+1,&ep,0);
   if (*ep || errno) badusage();
-  if (movfeatpos > MAXMOVFEATPOS) badusage();
+  if (movfeatpos > MOVFEATPOS_MAX) badusage();
 
   ensure_mps(&moveable,&moveable_a,segnum);
   mps= &moveable[segnum];
-  ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MAXMOVFEATPOS);
-  mps->lookup[movfeatpos ^ MAXMOVFEATPOS]= ix;
+  ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MOVFEATPOS_MAX);
+  mps->lookup[movfeatpos ^ MOVFEATPOS_MAX]= ix;
 }  
 
 /*---------- actual image processing ----------*/
@@ -185,20 +185,12 @@ static void badformat(const char *m) {
   exit(12);
 }
 
-static unsigned reverse_bits_in_byte(unsigned a) {
-  unsigned b, c, d;
-  b= ((a >> 1) & 0x55) | ((a << 1) & 0xaa);
-  c= ((b >> 2) & 0x33) | ((b << 2) & 0xcc);
-  d= ((c >> 4) & 0x0f) | ((c << 4) & 0xf0);
-  return d;
-}
-
 static void angle_to_colour(double result[3],
-                           int angle_i /* [0..63> */) {
+                           int angle_i /* [0..ANGLE_MAX> */) {
   int s;
   double angle, f, u, d, U, D;
 
-  angle= angle_i / 64.0 * 6.0;
+  angle= angle_i / (double)NANGLES * 6.0;
   s= floor(angle);
   f= angle - s;
   
@@ -219,12 +211,12 @@ static void angle_to_colour(double result[3],
   }
 }
 
-static double anglemap[64][3];
+static double anglemap[NANGLES][3];
 
 static void angle_to_colour_init(void) {
   int i;
   
-  for (i=0; i<64; i++)
+  for (i=0; i<NANGLES; i++)
     angle_to_colour(anglemap[i],i);
 }
 
@@ -245,34 +237,30 @@ static void process(void) {
   for (row=0; row<rows; row++)
     for (col=0; col<cols; col++) {
       unsigned char rgbi[3], rgbo[3];
+      unsigned long datum;
 
       if (fread(rgbi,1,3,encodingfile)!=3) {
        if (ferror(encodingfile)) { perror("reading"); exit(12); }
        else badformat("truncated file");
       }
 
-      if (rgbi[0]==255 && rgbi[1]==255 && rgbi[2]==255) {
+      datum= ARY2DATUM(rgbi);
+      
+      if (datum == BACKGROUND) {
 
        if (fwrite(rgbob,1,3,stdout)!=3) { perror("filling"); exit(12); }
        
       } else {
-       int segnum, movfeatpos, movfeatposix, red, blue, green, ix, angle;
+       int segnum, movfeatpos, movfeatposix, ix, angle;
        double *rgbdirn, alpha;
        struct result *r;
 
-       red= rgbi[0];
-       green= reverse_bits_in_byte(rgbi[1]);
-       blue= reverse_bits_in_byte(rgbi[2]);
-      
-       if (red & 0x03) badformat("reserved bits set in red");
-       angle= ((red >> 2) & 0x3f);
-
-       segnum= blue | ((green & 0xc0) << 2);
-       movfeatpos= green & 0x3f;
-       movfeatposix= movfeatpos ^ MAXMOVFEATPOS;
+       if (datum & RESERVED_MASK) badformat("reserved bits set");
+       angle= DATUM2(ANGLE,datum);
 
-       assert(segnum <= MAXSEGNUM);
-       assert(movfeatpos <= MAXMOVFEATPOS);
+       segnum= DATUM2(SEGNUM,datum);
+       movfeatpos= DATUM2(MOVFEATPOS,datum);
+       movfeatposix= movfeatpos ^ MOVFEATPOS_MAX;
 
        ix= !movfeatpos ?
          (segnum < fixed_a ? fixed[segnum] : 0) :
@@ -281,7 +269,7 @@ static void process(void) {
 
        r= &idinfo[ix];
 
-       rgbdirn= anglemap[ angle ^ (r->alpha < 0 ? 32 : 0) ];
+       rgbdirn= anglemap[ angle ^ (r->alpha < 0 ? ANGLE_TOPBIT : 0) ];
        alpha= fabs(r->alpha);
 
        for (i=0; i<3; i++) {