chiark / gitweb /
all-new bit-twiddling and object numbering, wip
authorian <ian>
Sun, 4 Dec 2005 14:26:07 +0000 (14:26 +0000)
committerian <ian>
Sun, 4 Dec 2005 14:26:07 +0000 (14:26 +0000)
cebpic/README.protocol
detpic/detect.asm
detpic/misc.asm
detpic/morse.messages
detpic/reverse.asm [new file with mode: 0644]
detpic/variables.asm
layout/data2safety
layout/layout-data.h
layout/pin-info-gen

index 1b91e3ce22e61dd82069ede4de301efc26a358ec..eb43a4b34faf3612cac22d615947252e7bb30eff 100644 (file)
@@ -145,22 +145,25 @@ The command is of variable length (but at least two bytes):
 
 Each byte after the first contains 7 more R bits.  The first R bit
 (most significant R bit in the first byte) corresponds to track
-detection segment 1; The next bit (2nd most significant bit in the
-first byte) corresponds to track detection segment 2; and so on.
+reversal segment 1; The next bit (2nd most significant bit in the
+first byte) corresponds to track reversal segment 2; and so on.
 
-Bits which do not correspond to defined track detection segments will
-be sent as 0 by the host but may be ignored by the PICs.  The host
-must send exactly as many bytes as are necessary to include all of the
-defined segments.
+Bits which do not correspond to defined reversal segments will be
+ignored by the PICs.  The host must send exactly as many bytes as are
+necessary to include all of the reversal segments for each reversers
+board (for every potential reversal segment, regardless of whether
+that segment is a defined segment corresponding to some actual track).
 
-For example, if there are 14 detection segments (numbered 1 to 14)
+For example, if there are 14 reversible segments (numbered 1 to 14)
 then the following message
    1 0010 000    1 000 1000    0 111 1010     Actual message
   (E      RRR)  (E RRR RRRR)  (E RRR R---)    } helpful annotations
                           1      111 1111     }  and commentary
           123      456 7890      123 4567     }
 specifies to reverse segments 7 and 11 to 14.  The trailing bits are
-for segments 15 to 17 and are ignored.
+for segments 15 to 17 and are ignored.  (Note that the assignment of
+physical segments to segment numbers is complex due to bit-twiddling.
+see detpic/reverse.asm and layout/data2safety.)
 
 The PIC will reply to POLARITY with POLARISED when the polarity change
 is complete.  The host must not send another POLARITY until then.
index 1275fd702080de53448cfac151e685d5fa27d36f..0326ff15c523c8bbb7dcd8a99c8091ddb3d92884 100644 (file)
@@ -1,5 +1,5 @@
 ;======================================================================
-; DETECTION
+; DETECTION AND SLAVE I2C
 
 ; FSR1 is used as pointer to where to add bytes of message; it
 ;  points to previous byte whose top bit must be set before
 ;              to be the same as last time (initially: 0)
 ;      zz      is a zero bit
 ;      MM      indicates that there are extra message byte(s)
+;      two digits indicates that the bit is the corresponding
+;              detection information.  The bit is clear iff current
+;              was detected since the last poll by the master.
+;              The bit value is not defined for unused sense
+;              segments.
 ;
 ;  Following that are the zero, one or two more bytes of
-;  detection data, 
-;      X and Y indicate that further detection bytes exist
-;      M indicates that more 
+;  detection data:
+;      19 09 12 15  18 04 20 17        iff reversers and B1 was set
+;      06 01 07 02  11 14 03 00        iff reversers and B2 was set
+;
+;  Finally, zero or more bytes of extra messages:
+;      MM XX XX XX  XX XX XX XX
+;  where
+;      MM      indicates that further extra message bytes follow;
+;              it is clear iff this is the last extra message byte.
+;      XX      are the lower 7 bits of a POLARISED or POINTED
+;              message (see README.protocol).
+
+; Master may also write to slave.  Every written byte is independent:
+;
+;      11RRRRRR        Set reverse to RRRRRR, see reverse.asm
 
 ;======================================================================
 ; variables and memory organisation
index 132c569331e5a6b91019df7e44436d6fae3f5c60..d42c3065d8b61ffed68e1e4ace24a5e590cc56c3 100644 (file)
@@ -36,4 +36,14 @@ init_read_idlocs
 
        return
 
+init_bitnum2bit
+; populate bitnum2bit
+       mov_lw  0x80
+       mov_lfsr bitnum2bit,0
+init_bitnum2bit_loop
+       rl_w
+       mov_wf  POSTINC0
+       bra_nn  init_bitnum2bit_loop
+       return
+
  include final.inc
index 9219297e56d5eee4a7a5d63173abcf035cfb92de..b6848c9d2b1b8aca3f7bf9e21013fcff74380117 100644 (file)
@@ -48,3 +48,7 @@ SD    i2clib:st                       ; impr. i2cm_read_done/i2cs_read_data
 DW                                     ; slave write (nyi)
 DQ     FSR2L,outmsg_end                ; previous slave read incomplete
 DR     FSR2L,outmsg_end                ; slave read overrun
+
+# Messages for specific peripherals
+PS     FSR0L                           ; POLARITY message too short
+PL     FSR0L                           ; POLARITY message too long
diff --git a/detpic/reverse.asm b/detpic/reverse.asm
new file mode 100644 (file)
index 0000000..0a86fc1
--- /dev/null
@@ -0,0 +1,108 @@
+;======================================================================
+
+
+board0 res 1
+gather res 1
+
+polarities_waiting res 1
+       ; no of 11... entries in reversers_commanded_buffer
+
+reversers_commanded_buffer res 32
+       ; Each byte is:
+       ;       11RRRRRRR       reverse command for slave pic
+       ;       000000001       this pic is not a reversers pic
+       ;       000000000       have sent any relevant POLARITY
+       ;       000000002       sentinel
+
+;----------
+polarity_decode_message
+; message format
+;              SS zz zz SS  ZZ 2f 2e 2d        g is board 2
+;              MM 2c 0f 0e  0d 0c 0b 0a        board 0
+;              MM 2b 1f 1e  1d 1c 1b 1a        board 1
+;              MM 2a 3f 3e  3d 3c 3b 3a        g, board 2, complete, also 3
+;              MM 9f 4f 4e  4d 4c 4b 4a        g is board 9
+;              MM 9e 5f 5e  5d 5c 5b 5a
+;              MM 9d 6f 6e  6d 6c 6b 6a
+;              MM 9c 7f 7e  7d 7c 7b 7a
+;              MM 9b 8f 8e  8d 8c 8b 8a
+;              MM 9a af ae  ad ac ab aa
+;              etc.
+; where
+;      SS      bit set
+;      zz      bit zero
+;      other things are <board><segment> where <segment>
+;              is a for LSb in message to PIC, b for next bit,
+;              and so on until f for bit 5.  (See polarity_do_here, below.)
+;
+       mov_lfsr message_buffer_start,0
+       mov_lfsr reversers_commanded_buffer,1
+       mov_fw  POSTINC0        ; W =           10010RRR
+       mov_wf  gather          ; gather =      10010ggg
+       xor_lw  0b10001000      ; gather =      00011ggg
+loop ; exit from this loop is done by board popping and returning
+       rrc_fw  INDF0           ; W =           ?Mhhhhhh  C = g
+       rlc_f   gather          ; gather =      0*11g+    C = ?
+       bra_nn  if_not_gathered
+       ;                       ; gather =      11gggggg
+       mov_fw  gather
+       rcall   board
+       mov_lw  0b00000011      ; W =           00000011
+       mov_wf  gather          ; gather =      00000011
+if_not_gathered                        ; *INDF0 =      Mhhhhhhg
+       rr_fw   INDF0           ; W =           gMhhhhhh
+       or_lw   0b11000000      ; W =           11hhhhhh
+       rcall   board
+       bt_f_if1 POSTINC0,7     ; *POSTINC0 :   M.......
+       bra     loop
+       ; otherwise:
+       panic   morse_PS
+
+;----------
+board
+       mov_wf  INDF1           ; *(this pic) = 11RRRRRR
+                               ; FSR1 -> pic we've just filled
+;...
+board_next_loop
+       dec_fw  PREINC1         ; FSR1 -> pic after one we're testing
+                               ; W = 1???????  existing reverse command
+                               ;     00000000  not a reversers pic
+                               ;     ffffffff  no existing command
+                               ;     00000001  sentinel
+       bra_z   board_next_loop ; not a reversers pic
+       bra_nn  board_next_none ; sentinel
+
+       bt_f_if0 INDF1,7        ;     1.......  existing command
+                               ;     0.......  no existing command
+       inc_f   polarities_waiting
+       return
+
+;----------
+board_next_none
+       bt_f_if1 INDF0,7        ; *INDFO :      M.......
+       bra     board_next_none_more_message
+;...
+; now we're exiting from the loop in when_reverse_message_found
+       pop
+       return
+
+
+;----------
+polarity_do_here
+;              W       here polarity           SS SS v3 v0  v2 v1 v5 v4
+       mov_wf  input           ; input =       SS SS v3 v0  v2 v1 v5 v4
+
+       mov_wf  LATE            ; W =           kk kk kk kk  kk kk o5 o4
+       xor_wfw input           ; W =           ?? ?? ?? ??  ?? ?? d5 d4
+       and_wfw maske           ; W =           zz zz zz zz  zz zz d5 d4
+       xor_wff LATE            ; LATA =        kk kk kk kk  kk kk v5 v4
+
+       bc_f    input,2         ; input =       SS SS v3 v0  v2 v1 zz v4
+       bt_f_if1 input,4        ; input :       .. .. .. v0  .. .. .. ..
+       bs_f    input,2         ; input =       SS SS v3 v0  v2 v1 v0 v4
+
+       mov_wf  LATA            ; W =           kk kk r3 kk  r2 r1 r0 kk
+       xor_wfw input           ; W =           ?? ?? r3 ??  r2 r1 r0 ??
+       and_wfw maska           ; W =           zz zz r3 zz  r2 r1 r0 zz
+       xor_wff LATA            ; LATE =        kk kk r3 kk  r2 r1 r0 kk
+       return
index 9f76900c6ef6ec941981cb8514b95f54968563ce..1fbbd4526a0778080d658f027c42583a8971848d 100644 (file)
@@ -13,6 +13,9 @@ outbuf_szln2  equ     7
 outbuf_size    equ     (1<<outbuf_szln2)
 outbuf         res     outbuf_size
 
+ udata 0x0f8 ; bottom byte is all-bits-set except for 3 bitnum bits
+bitnum2bit     res     8       ; bitnum2bit[x] = 1<<x
+
  include final.inc
 
 ;======================================================================
index 09feff8518e1aadefe228d4a67ee0814b5a7b52e..be6041a3480cfcbe008e6a5cf28c890b88fd7e83 100755 (executable)
@@ -28,11 +28,13 @@ our (%nodes);
 # $nodes{$node}[$side]{Seg}
 # $nodes{$node}[$side]{End}
 
-our ($nextboardnum,@objkinds,@boardobjbase,@boardtype,%pin_used);
+our ($nextboardnum,@boardtype,%numboards,$nreverses);
 # @boardtype[$boardnum]
+# $numboards{$type}
+# $nreverses
 # $boardobjbase[$boardnum]{$kind}
-# %pin_used{$objkind}[$objnum] = [ $boardnum, $pin_info, $objonboard ]
 $nextboardnum= 0;
+$nreverses= 0;
 @objkinds= qw(pt sense reverse);
 map { $boardobjbase[0]{$_}= 1; } @objkinds;
 
@@ -120,9 +122,13 @@ sub line_boards () {
     $nextboardnum++;
     require "./$type.pin-info";
     $boardtype[$num]= $type;
-    foreach $k (@objkinds) {
-       $boardobjbase[$nextboardnum]{$k}=
-           $boardobjbase[$num]{$k} + $kind_count{$type}{$k};
+    $numboards{$type}++;
+    if ($type eq 'reversers') {
+       my ($i,$objnum);
+       for ($i=0; $i<5; $i++) {
+           $objnum= so_boob('reverse', [ $num,$i ]);
+           $nreverses= $objnum+1 if $objnum >= $nreverses;
+       }
     }
 }
 
@@ -205,20 +211,78 @@ sub pa_boob ($) {
     return [ $1,$2 ];
 }
 
+# so_boob_KIND($boardnum,$boardtype,$objnum) -> global object number
+
+sub so_boob_pt($$$) {
+    my ($boardnum,$boardtype,$obj)=@_;
+    die if $boardnum>31 || $obj>31;
+    return ($boardnum << 5) | $obj;
+}
+
+sub so_boob_reverse($$$) {
+    my ($boardnum,$boardtype,$obj)=@_;
+
+    # Converts board and object number (in canonical pic number plus
+    # and reverse0...reverse5 as seen on pinout diagrams), to
+    # object number for POLARITY command numbered as shown in
+    # README.protocol.
+    #
+    # There are three basic stages:
+    #
+    #  * We invert the on-board mapping; ie, we untangle the
+    #    tangling between the message from master to slave pic
+    #    and the actual pins (see reverse.asm, polarity_do_here)
+    #
+    #  * We figure out which bit of which message byte the
+    #    object corresponds to.  (see reverse.asm, polarity_decode_message)
+    #
+    #  * We compute the README.protocol bit and byte number.
+    
+    my ($cycle);
+    mistake("reversable segment on non-reversers board $board")
+       unless $boardtype eq 'reversers';
+    mistake("reversable segment out of range")
+       unless unless $obj>=0 && $obj<6;
+    $obj = sprintf '%d', $obj;
+    $obj =~ y/302154/543210/; # mapping due to polarity_do_here
+    $cycle= int(($boardnum+3) / 7);
+    $boardincycle= ($boardnum+3) - $cycle*7;
+    $cyclebasebyte= $cycle*6 - 2;
+    if ($boardnum==2 && $obj > 2) {
+       $byte= 0; $bit= $obj-3;
+       return 3 - $bit; # only these three in byte 0, a special case
+    } elsif ($boardincycle<5) {
+       $byte= $cyclebasebyte + $boardincycle; $bit= $obj;
+    } elsif ($boardincycle==6) {
+       $byte= $cyclebasebyte + 5; $bit= $obj;
+    } elsif ($boardincycle==5) {
+       $byte= $cyclebasebyte + 5 - $bit; $bit= 6;
+    } else {
+       die;
+    }
+    return $byte*7 + 3 - $bit;
+}
+
+sub so_boob_sense($$$) {
+    my ($boardnum,$boardtype,$obj)=@_;
+
+    die 'unimplemented';
+}    
+
 sub so_boob ($$) {
-    my ($k,$bo) = @_;
+    my ($kind,$bo) = @_;
     if (defined $bo) {
        my ($board,$obj)= @$bo;
        my ($objnum,$type,$pi);
        mistake("unknown board number $board")
            unless defined $boardtype[$board];
-       $objnum= $boardobjbase[$board]{$k} + $obj;
        $type= $boardtype[$board];
-       $pi= $pin_info{$type}{$k};
-       mistake("object reference $k $board.$obj out of range for".
+       $objnum= &{"so_boob_$kind"}($board,$type,$obj);
+       $pi= $pin_info{$type}{$kind};
+       mistake("object reference $kind $board.$obj out of range for".
                " board type $type")
            unless defined $pi->[$obj];
-       $pin_used{$k}[$objnum]= [ $board, $pi->[$obj], $obj ];
+       $pin_used{$kind}[$objnum]= [ $board, $pi->[$obj], $obj ];
        return sprintf("%4d /* %d.%-2d*/", $objnum, $board, $obj);
     } else {
        return "   0 /*none*/ ";
@@ -226,8 +290,8 @@ sub so_boob ($$) {
 }
 
 sub so_oboob ($$) {
-    my ($k,$obj) = @_;
-    return so_boob($k, defined $obj ? $obj->{BoOb} : undef);
+    my ($kind,$obj) = @_;
+    return so_boob($kind, defined $obj ? $obj->{BoOb} : undef);
 }
 
 sub mainread () {
@@ -365,53 +429,54 @@ sub writeasm () {
     o("        include pindata.inc\n".
       "        radix hex\n".
       "X       equ 0xff\n");
-    $each= 10;
-    for $k (@objkinds) {
-       for $w (qw(pic port bit)) {
-           @d=();
-           o("\n");
-           o("${k}_${w}_data_section  org  ${k}_${w}_data\n");
-           for ($i=0; $i<@{ $pin_used{$k} }; $i++) {
-               $or= $pin_used{$k}[$i];
-               if (defined $or) {
-                   $or->[1] =~ m/^(\d+)\,(\w+)$/;
-                   ($portnum,$bit)= ($1,$2);
-                   $portnum= sprintf "%02x", $portnum + 0x89; # 89=LATA
-                   $bit= sprintf "%02x", hex $bit;
-               } else {
-                   $portnum=$bit='00';
-               }
-               if ($w eq 'pic') {
-                   if (defined $or) {
-                       push @d, $or->[0];
-                   } else {
-                       push @d, 'X',
-                   }
-               } elsif ($w eq 'port') {
-                   push @d, $portnum;
-               } elsif ($w eq 'bit') {
-                   push @d, $bit;
-               } else {
-                   die;
-               }
-           }
-           push @d, 'X' if @d^1;
-           @d= map { s/^[a-f]/0$&/; sprintf "%3s", $_ } @d;
-           for (;;) {
-               $d[$each/2] = " $d[$each/2]" if $#d >= $each/2;
-               last if @d <= $each;
-               o("        db      ". join(',',@d[0..($each-1)]). "\n");
-               @d= @d[$each..$#d];
-           }
-           o("        db      ".join(',',@d)."\n");
-           if ($w eq 'pic') {
-               o("        if \$ > ${k}_pic_data + ${k}_num_max\n".
-                 "         error \"too much ${k}_picdata\"\n".
-                 "        endif\n".
-                 "        fill 0xffff, ${k}_pic_data + ${k}_num_max - \$\n");
-           }
-       }
-    }
+    o("
+#    $each= 10;
+#     for $k (@objkinds) {
+#      for $w (qw(pic port bit)) {
+#          @d=();
+#          o("\n");
+#          o("${k}_${w}_data_section  org  ${k}_${w}_data\n");
+#          for ($i=0; $i<@{ $pin_used{$k} }; $i++) {
+#              $or= $pin_used{$k}[$i];
+#              if (defined $or) {
+#                  $or->[1] =~ m/^(\d+)\,\d+,(\w+)$/;
+#                  ($portnum,$bit)= ($1,$2);
+#                  $portnum= sprintf "%02x", $portnum + 0x89; # 89=LATA
+#                  $bit= sprintf "%02x", hex $bit;
+#              } else {
+#                  $portnum=$bit='00';
+#              }
+#              if ($w eq 'pic') {
+#                  if (defined $or) {
+#                      push @d, $or->[0];
+#                  } else {
+#                      push @d, 'X',
+#                  }
+#              } elsif ($w eq 'port') {
+#                  push @d, $portnum;
+#              } elsif ($w eq 'bit') {
+#                  push @d, $bit;
+#              } else {
+#                  die;
+#              }
+#          }
+#          push @d, 'X' if @d^1;
+#          @d= map { s/^[a-f]/0$&/; sprintf "%3s", $_ } @d;
+#          for (;;) {
+#              $d[$each/2] = " $d[$each/2]" if $#d >= $each/2;
+#              last if @d <= $each;
+#              o("        db      ". join(',',@d[0..($each-1)]). "\n");
+#              @d= @d[$each..$#d];
+#          }
+#          o("        db      ".join(',',@d)."\n");
+#          if ($w eq 'pic') {
+#              o("        if \$ > ${k}_pic_data + ${k}_num_max\n".
+#                "         error \"too much ${k}_picdata\"\n".
+#                "        endif\n".
+#                "        fill 0xffff, ${k}_pic_data + ${k}_num_max - \$\n");
+#          }
+#      }
+#     }
     o("\n        end\n");
 }
 mainread();
index 38c262d437541d3ca9052945332bf6c8db4b4626..84391c7b213026a1bd9aba351e0c16fd3b21cd16 100644 (file)
@@ -79,6 +79,8 @@ extern const SegmentInfo info_segments[];
 extern const TrainNum info_nsegments;
 extern const TrainInfo info_trains[];
 
+extern const BoardObject info_nreverses; /* max. reverse + 1 */
+
 #define NOTA(x) (~(x##Num)0)
 
 #endif /*LAYOUT_DATA_H*/
index e046dc489e3cd14d40d6d97eb260f80f4d41a5dd..2da9769a32f2993098bae2de4ae55c4265f55a68 100755 (executable)
@@ -16,9 +16,10 @@ for (;;) {
        $cpin++;
     } elsif (s/^[ABCDE]\s+//) {
        $port= ord($&) - ord('A');
-    } elsif (s/^([0-9a-f][0-9a-f])\s+//) {
+    } elsif (s/^([0-7])\s+//) {
        die unless defined $port;
-       $pins[$cpin++]= "$port,0x$1";
+       $pins[$cpin++]= sprintf "%d,%d,0x%02x",
+           $port, $1, 1 << $1;
     } else {
        die "$_ ?";
     }
@@ -57,15 +58,15 @@ print "1;\n"
 __DATA__
 # 1..20
 -
-A 01 02 04 08 10 20
-E 01 02 04
+A 0 1 2 3 4 5
+E 0 1 2
 - - -
-A 40
-C 01 02 04 08
-D 01 02
-# 21..40
-D 04 08
-C 10 20 40 80
-D 10 20 40 80
+A 6
+C 0 1 2 3
+D 0 1
+# 21..6
+D 2 3
+C 4 5 6 7
+D 4 5 6 7
 - -
-B 01 02 04 08 10 20 40 80
+B 0 1 2 3 4 5 6 7