From: ian Date: Sat, 23 Oct 2004 16:23:31 +0000 (+0000) Subject: abstracted bit stuff X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=3b6c361016bec4789bba37ae4e2b65fc956a8489;p=trains.git abstracted bit stuff --- diff --git a/TODO b/TODO index f7f33b4..dafba0f 100644 --- 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. diff --git a/layout/Makefile b/layout/Makefile index 86e4535..e1903fc 100644 --- a/layout/Makefile +++ b/layout/Makefile @@ -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 diff --git a/layout/compose-segenco.c b/layout/compose-segenco.c index fcc6c6a..94e4fcb 100644 --- a/layout/compose-segenco.c +++ b/layout/compose-segenco.c @@ -17,7 +17,9 @@ #include -#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> fi; /* bits are reversed; first fi pos 1 not 0 */ + datum= ARY2DATUM(ov); + datum |= 1UL << (fi-1 + MOVFEATPOS_BASEBIT); + DATUM2ARY(ov,datum); } } diff --git a/layout/layout b/layout/layout index 4b3ecc6..391d7c6 100755 --- a/layout/layout +++ b/layout/layout @@ -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 index 0000000..1f8d35c --- /dev/null +++ b/layout/segcmap.h @@ -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< -# where is N/[M] (see informat.txt) and and -# contain no whitespace and are suitable for inserting like this -# into the PostScript output: -# ...code to compute and stack red in range [0,1>... -# setrgbcolor +# C 0x +# where is N/[M] (see informat.txt) and +# is the hex value of the datum (see segmap.h) # # S 0x # F 0x 0x @@ -20,32 +17,6 @@ # # 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 () { + 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 $!; diff --git a/layout/subseg2display.c b/layout/subseg2display.c index fa4e020..4653b8a 100644 --- a/layout/subseg2display.c +++ b/layout/subseg2display.c @@ -38,6 +38,8 @@ #include #include +#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> 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++) {