chiark / gitweb /
new resolution arrangements
authorian <ian>
Sun, 13 Apr 2008 20:00:06 +0000 (20:00 +0000)
committerian <ian>
Sun, 13 Apr 2008 20:00:06 +0000 (20:00 +0000)
12 files changed:
hostside/TODO
hostside/commands.c
hostside/homes.record
hostside/movpos.c
hostside/persist.c
hostside/realtime.h
hostside/resolve.c
hostside/retransmit.c
hostside/safety.c
hostside/safety.h
hostside/startup.c
hostside/stastate.h.gen

index 90e7b6f25869c8a338e526e1e64579b75dde274c..8d7b95967bb41a3dfbb1f18c823bfbfe2d5cd98b 100644 (file)
@@ -1,10 +1,6 @@
 before can test
        commands for speed manager
-       write trivial initial settlement to get data array right
-       write out layout data on crash
        check that everything in Train and Segment is init'd
-       do lay_train in resolution, or moral equivalent
-       set points under existing trains according to existing movposcomb
 
 dunno but maybe before can test
        wiring to gui display
@@ -12,10 +8,6 @@ dunno but maybe before can test
 things not yet considered at all in safety code
        coming up against points the wrong way
        min. curve specifications
-       crossovers
-
-initialise safety_state with appropriate stuff
-
 
 
 make safety stop not be estop
index 1c9953ae156a4f28ffbc0e17fe2d29f374d82014..f6a638c646dacb8f866491069a834daffc907848 100644 (file)
@@ -202,7 +202,7 @@ static void cmd_movfeat(ParseState *ps, const CmdInfo *ci) {
 
   if (!ps_neednoargs(ps)) return;
 
-  ec= movpos_change(back,move,fwd,ms,0);
+  ec= movpos_change_bysegs(back,move,fwd,ms,0);
   if (ec) {
     badcmd(ps,"movfeat %s %s %s %ld %s",
           back->i->pname, move->i->pname, fwd->i->pname,
index 284fbf2297fc33a50873bdf38f1a09897f11f118..808cb3738d05d9628633b769b3095ec179a53d44 100644 (file)
@@ -1 +1,2 @@
-train santafe home X5 X6
+train santafe home -X5
+train shinkansen home -X9 -A5 -A6
index 6abf02bbc6f1335071b43b2d4604f681a8bb1fc8..98c3dc7e485b5dd0bd61fd4bc700171602896a5c 100644 (file)
@@ -35,18 +35,18 @@ typedef struct MovPosChange {      /* valid in:   filled in by and when:     */
   MovPosComb actual;               /*  CD          see below                 */
   /* kind-specific data follows */ /*  varies     kind-specific code, varies */
 } Change;
-  /* `actual' contains the kind's record of the physical state.  It is
-   * initialised by indep (just before confirm) from move->moving->actual
-   * or move->movposcomb as the case may be.  It should be updated
-   * by the kind, since it is used by indep for calculating the number
-   * and identities of the features which may need to change when a
-   * new move request is intended to replace an existing one - ie, the
-   * contents of the motions[] provided to a subsequent confirm().
-   * So while a change is Confirmed, the physical state is recorded
-   * only in the relevant change, and not in the segment's movposcomb.
-   * Once a change goes to Confirmed, the indep code never untangles it
-   * so the kind can manage the proper transition.
-   */
+  /* `actual' contains the kind's public opinion about the physical
+   * state.  It is initialised by indep (just before confirm) from
+   * move->moving->actual or move->movposcomb as the case may be.  It
+   * should be updated by the kind, since it is used by indep for
+   * calculating the number and identities of the features which may
+   * need to change when a new move request is intended to replace an
+   * existing one - ie, the contents of the motions[] provided to a
+   * subsequent confirm().  So while a change is Confirmed, the
+   * physical state is recorded only in the relevant change, and not
+   * in the segment's movposcomb.  Once a change goes to Confirmed,
+   * the indep code never untangles it so the kind can manage the
+   * proper transition.  */
 
 struct KindInfo {
   Change *(*allocate)(int alloc_motions); /* U->A (always succeeds) */
@@ -355,6 +355,7 @@ fprintf(stderr,"  point confirm\n");
 
   if (!ec) {
     move->moving= chg;
+    move->movposcomb= -1;
     pt_check_action();
   }
 
@@ -372,7 +373,10 @@ static void point_destroy(Change *chg) { /* X->XA and then free it */
 static void pt_check_action(void) {
   PicInsn piob;
 
-  if (!pt_confirmed.n) return;
+  if (!pt_confirmed.n) {
+    if (sta_state == Sta_Finalising) resolve_motioncheck();
+    return;
+  }
 
   PointReq *r= pt_confirmed.l[0];
 
@@ -475,73 +479,94 @@ static Change *mp_allocate(const KindInfo *ki, Segment *move,
   return chg;
 }
 
-ErrorCode
-movpos_change(Segment *back, Segment *move, Segment *fwd,
-             int maxdelay_ms, MovPosChange *chg) {
+static int movpos__evaluate_target(Segment *move, MovPosComb target) {
+  /* returns number of features which have to change to reach target */
   const SegmentInfo *movei= move->i;
-  const SegPosCombInfo *pci;
+  int feat, tchanges;
+  MovPosComb actual;
   const MovFeatInfo *feati;
-  int feat;
-  MovPosComb actual, tcomb, bestcomb=0;
-  int tchanges, bestchanges=INT_MAX;
-  ErrorCode ec;
-  MovFeatKind kind= mfk_none;
 
-  if (move->moving) {
-    kind= move->moving->ki - methodinfos;
-    actual= move->moving->actual;
-  } else {
-    actual= move->movposcomb;
-  }
+  actual= movpos_poscomb_actual(move);
+
+  for (feat=0, feati=movei->movfeats, tchanges=0;
+       feat<movei->n_movfeats;
+       feat++)
+    if (actual<0 || (target - actual) / feati->weight % feati->posns)
+      tchanges++;
+  return tchanges;
+}
+
+ErrorCode
+movpos_change_bysegs(Segment *back, Segment *move, Segment *fwd,
+                    int maxdelay_ms, MovPosChange *chg) {
+  const SegmentInfo *movei= move->i;
+  MovPosComb tcomb, bestcomb=0;
+  int tchanges, bestchanges=INT_MAX;
+  const SegPosCombInfo *pci;
 
-fprintf(stderr,"moving %s\n",move->i->pname);
+  //fprintf(stderr,"moving %s\n",move->i->pname);
   for (tcomb=0, pci=movei->poscombs;
        tcomb<movei->n_poscombs;
        tcomb++, pci++) {
-fprintf(stderr," tcomb %lu\n",tcomb);
+    //fprintf(stderr," tcomb %lu\n",tcomb);
     Segment *tback= &segments[pci->backwards.next];
     Segment *tfwd=  &segments[pci->forwards .next];
-fprintf(stderr,"  tback %s tfwd %s\n",
-       tback?tback->i->pname:"-",
-       tfwd?tfwd->i->pname:"-"
-       );
+    //fprintf(stderr,"  tback %s tfwd %s\n",
+    // tback?tback->i->pname:"-",
+    // tfwd?tfwd->i->pname:"-"
+    // );
     if (back && !(back==tback || back==tfwd)) continue;
     if (fwd  && !(fwd ==tback || fwd ==tfwd)) continue;
 
     if (movei->n_movfeats>1) {
-fprintf(stderr,"  several feats\n");
+      //fprintf(stderr,"  several feats\n");
       /* we have to search for the one which is least effort, then */
-      for (feat=0, feati=movei->movfeats, tchanges=0;
-          feat<movei->n_movfeats;
-          feat++)
-       if (actual<0 || (tcomb - actual) / feati->weight % feati->posns)
-         tchanges++;
+      tchanges= movpos__evaluate_target(move, tcomb);
       if (tchanges > bestchanges)
        continue;
     } else {
       tchanges= 1;
     }
-fprintf(stderr,"  best %lu changes %d\n",tcomb,tchanges);
+    //fprintf(stderr,"  best %lu changes %d\n",tcomb,tchanges);
     bestcomb= tcomb;
     bestchanges= tchanges;
   }
 
-fprintf(stderr," best %lu changes %d\n",bestcomb,bestchanges);
-  if (bestchanges==INT_MAX) { ec= EC_Invalid; goto x; }
+  //fprintf(stderr," best %lu changes %d\n",bestcomb,bestchanges);
+  if (bestchanges==INT_MAX) { movpos_unreserve(chg); return EC_Invalid; }
+
+  return movpos_change(move, tcomb, maxdelay_ms, chg);
+}
+
+ErrorCode movpos_change(Segment *move, MovPosComb target,
+                       int maxdelay_ms, MovPosChange *chg) {
+  const SegmentInfo *movei= move->i;
+  const MovFeatInfo *feati;
+  int feat;
+  MovPosComb actual;
+  ErrorCode ec;
+  MovFeatKind kind= mfk_none;
+
+  if (move->moving) {
+    kind= move->moving->ki - methodinfos;
+    actual= move->moving->actual;
+  } else {
+    actual= move->movposcomb;
+  }
 
   {
     int n_motions=0;
     Motion motions[movei->n_movfeats];
 
-fprintf(stderr," motions...  best=%lu actual=%ld\n",bestcomb,actual);
+fprintf(stderr," motions...  best=%lu actual=%ld\n",target,actual);
     for (feat=0, feati=movei->movfeats;
         feat<movei->n_movfeats;
         feat++, feati++) {
 fprintf(stderr,"  checking %s w=%lu posns=%d\n",
        feati->pname,feati->weight,(int)feati->posns);
-      if (actual>=0 && !((bestcomb - actual) / feati->weight % feati->posns))
+      if (actual>=0 && !((target - actual) / feati->weight % feati->posns))
        continue;
-      MovPosComb posn= bestcomb / feati->weight % feati->posns;
+      MovPosComb posn= target / feati->weight % feati->posns;
 fprintf(stderr,"    motion %s %lu kind=%d\n",feati->pname,posn,kind);
       if (kind) {
        if (feati->kind != kind) { ec= EC_MovFeatKindsCombination; goto x; }
@@ -606,3 +631,7 @@ void movpos_unreserve(MovPosChange *res) {
   if (!res) return;
   res->ki->destroy(res);
 }
+
+MovPosComb movpos_poscomb_actual(Segment *seg) {
+ return seg->moving ? seg->moving->actual : seg->movposcomb;
+}
index f2abe1727df8d2106e65fbddf7c365235f8ec4a4..1335bc7027eef4d9d06afd54ba2cde0e25723050 100644 (file)
@@ -365,6 +365,7 @@ static void persist_mapread(void) {
 void persist_entrails_run_converter(void) {
   TRA_IV;
   SEG_IV;
+  MovPosComb report;
 
   persist_mapread();
 
@@ -382,6 +383,11 @@ void persist_entrails_run_converter(void) {
       continue;
     printf("seg %s has %s%s\n",
           segi->pname, seg->tr_backwards ? "-" : "", seg->owner->pname);
+
+    if (segi->n_poscombs>1 &&
+       (report= movpos_poscomb_actual(seg)) >=0 &&
+       report < segi->n_poscombs)
+      printf("seg %s at %s\n", segi->pname, segi->poscombs[report].pname);
   }
   if (ferror(stdout) || fflush(stdout))
     diee("entrails converter: stdout write error");
index 15007c9204ddc839572eaf3f215f600cfc8970ab..8bc4a3bd0fa09238cc9df3d7599ea59203191ee0 100644 (file)
@@ -110,6 +110,7 @@ extern int picio_send_noise;
 #include "stastate.h"
 
 void sta_startup(void);
+void sta_finalising_done(void);
 void serial_moredata(PicInsn *buf);
 
 extern StartupState sta_state;
@@ -117,6 +118,7 @@ extern const char *const stastatelist[];
 
 void resolve_begin(void); /* from resolve.c */
 int resolve_complete(void);
+void resolve_motioncheck(void);
 
 /*---------- from/for record.c and persist.c ----------*/
 
index 317f9ac51104b1ad3ec38b29a56e7088b649b872..c527bd8218a72882386e76bd07d3fc3706449b5c 100644 (file)
@@ -213,6 +213,11 @@ int resolve_complete(void) {
          goto not_3a;
        }
 
+       if (d->movposcomb < 0) {
+         oprintf(UPO, "resolving     track-unknown-position\n");
+         goto not_3a;
+       }
+
        if (t->resolution == RR_E)
          /* we added it in this sweep and have found another d */
          goto already_3a;
@@ -279,19 +284,74 @@ int resolve_complete(void) {
       if (phase<2)
        continue;
 
-      oprintf(UPO, "resolving    inexplicable @%s\n", di->pname);
+      oprintf(UPO, "resolution inexplicable @%s\n", di->pname);
       d->res_detect= 0;
       problems++;
     }
   }
     
-  if (problems) oprintf(UPO,"resolve problems %d\n",problems);
+  FOR_SEGMENT(d,NOOP,NOOP) {
+    d->tr_updated= 0;
+    d->cm_autostop= 0;
+
+    MovPosComb target= -1;
+
+    if (d->owner) {
+      d->until_detect= 1;
+      switch (d->owner->resolution) {
+      case RR_H:
+       d->tr_backwards= d->ho_backwards;
+       target= 0; /* a bit kludgey */
+       break;
+      case RR_E:
+       target= d->movposcomb;
+       d->tr_backwards ^= d->owner->backwards;
+       /* ... we set d->owner->backwards to 0 below, so cancel that out */
+       break;
+      default:
+       abort();
+      }
+    }
+    if (d->i->n_poscombs>1) {
+      d->movposcomb= -1;
+      if (target >= 0) {
+       ErrorCode ec= movpos_change(d,target,INT_MAX,0);
+       if (ec) {
+         oprintf(UPO, "resolution movpos-change-failed %s/%s %s\n",
+                 d->i->pname, d->i->poscombs[target].pname,
+                 errorcodelist[ec]);
+         problems++;
+       }
+      }
+    }
+  }
 
-  FOR_SEGMENT(d,NOOP,NOOP)
-    d->tr_updated= d->res_detect= 0;
+  FOR_TRAIN(t,NOOP,NOOP) {
+    if (t->resolution == RR_E)
+      t->backwards= 0;
+  }
 
-  if (problems)
+  if (problems) {
+    oprintf(UPO,"resolution problems (%d)\n",problems);
     return -1;
+  }
 
   return 0;
 }
+
+void resolve_motioncheck(void) {
+  SEG_IV;
+  assert(sta_state == Sta_Finalising);
+  
+  FOR_SEG
+    if (seg->moving) return;
+
+  FOR_SEG {
+    if (seg->res_detect) {
+      seg->res_detect= 0;
+      safety_notify_detection(seg);
+    }
+  }
+  
+  sta_finalising_done();
+}
index d6f16480b026b871cec9e6b9b84cafc0cf4669ce..52aaa9c20ef2dbab9ad68e86bca8b9940c1fed99 100644 (file)
@@ -137,3 +137,13 @@ void retransmit_urgent_cancel(RetransmitUrgentNode *urg) {
     DLIST2_REMOVE(speedies[urg->u.ix].queue,urg,u.queue);
   retransmit_relaxed_cancel(&urg->u.relaxed);
 }
+
+
+void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+  if (!objnum) die("PIC sent NUL!");
+  if (sta_state <= Sta_Settling) return;
+  if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
+
+  while (objnum--)
+    retransmit_something();
+}
index c4bb33b8e2e539e57fce35f9abe06e26239d6223..7f18853a6c6c3bdf54759826cce578bd7471f18f 100644 (file)
@@ -30,23 +30,10 @@ typedef struct {
   Segment *invert_forcer; /* the unswitchable which forces */
 } LayTrainState;
 
-static void lay_train_check_clash(LayTrainState *l, Segment *check,
-                                 Segment *report) {
-  const char *exi1="", *exi2="";
-  if (check!=report) { exi1= " at "; exi2= check->i->pname; }
-  
-  if (seg->tr_updated) {
-    l->ec= safety_problem(l->tra, report, "self-collision%s%s", exi1,exi2);
-    return;
-  }
-  if (seg->owner) {
-    if (seg->owner != l->tra) {
-      l->ec= safety_problem(l->tra, tloc.seg, "collision with %s"
-                           "%s%s", seg->owner->pname, exi1,exi2);
-      return;
-    }
-  }
-}
+#define INTERFERING_MOVPOSCOMB(seg,segi)                               \
+  ((seg)->moving ||                                                    \
+   (seg)->movposcomb < 0 ||                                            \
+   (segi)->interferes_movposcomb_map & (1u << (seg)->movposcomb))
 
 static Segment *interferes(Segment *base) {
   const SegmentInfo *basei, *interi;
@@ -54,28 +41,46 @@ static Segment *interferes(Segment *base) {
   Segment *inter;
 
   basei= base->i;
-  intern= seg->i->interferes;
+  intern= basei->interferes;
 
   if (!SOMEP(intern)) return 0;
-  if (!(segi->interferes_movposcomb_map & (1u << base->movposcomb)))
-    return 0;
+  if (!INTERFERING_MOVPOSCOMB(base,basei)) return 0;
 
   inter= &segments[intern];
   interi= &info_segments[intern];
 
-  assert(base == &info_segments[interi->interferes]);
-  if (!inter->moving &&
-      !(interi->interferes_movposcomb_map & (1u << inter->movposcomb)))
-     return 0;
+  assert(basei == &info_segments[interi->interferes]);
+  if (!INTERFERING_MOVPOSCOMB(inter,interi))
+    return 0;
 
   return inter;
 }
 
+static void lay_train_check_clash(LayTrainState *l, Segment *check,
+                                 Segment *report) {
+  const char *exi1="", *exi2="";
+  if (check!=report) { exi1= " at "; exi2= check->i->pname; }
+  
+  if (check->tr_updated) {
+    l->ec= safety_problem(l->tra, report, "self-collision%s%s", exi1,exi2);
+    return;
+  }
+  if (check->owner) {
+    if (check->owner != l->tra) {
+      l->ec= safety_problem(l->tra, report, "collision with %s"
+                           "%s%s", check->owner->pname, exi1,exi2);
+      return;
+    }
+  }
+  if (check->movposcomb < 0)
+    l->ec= safety_problem(l->tra, report, "track route not set");
+}
+
 static void lay_train_pass(LayTrainState *l,
                           TrackLocation tloc, long advance,
                           long speed, unsigned backwards,
                           unsigned check_clash) {
-  Segment *seg;
+  Segment *seg, *inter;
   long overall, remain, dist_until, time_until;
   int *invert_likehere, train_inverted_here;
   Train *tra= l->tra;
@@ -91,7 +96,7 @@ static void lay_train_pass(LayTrainState *l,
 
     if (check_clash) {
       lay_train_check_clash(l,seg,seg);
-      inter= interfere_physical(seg);
+      inter= interferes(seg);
       if (inter) lay_train_check_clash(l,inter,seg);
     }
 
@@ -242,7 +247,7 @@ void safety_notify_detection(Segment *seg) {
   }
   tra->uncertainty= tra->maxinto;
 
-  if (!tra->estopping) {
+  if (!(tra->estopping || tra->speed==0)) {
     ec= lay_train(tra, 0);
     if (ec) {
       logmsg(ec,tra,seg->i, "emergency stop");
index 518a54bb26ed42a370c00c2f15e29982c55dcc29..a3b54f288bf528173a8f4ffdef7dd7bc4759f537 100644 (file)
@@ -81,7 +81,7 @@ struct Segment {
     res_detect:1; /* detection noticed here during resolution */
   TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but      */
     until_detect;          /* ) 0 if already */  /* )  meaningful iff owner */
-  MovPosComb movposcomb; /* -1 means not known */
+  MovPosComb movposcomb; /* -1 means not known or moving */
   MovPosChange *moving; /* non-0 iff feature(s) have been told to change */
   const SegmentInfo *i;
 };
@@ -134,13 +134,9 @@ void safety_notify_detection(Segment *seg);
  */
 
 ErrorCode
-movpos_change(Segment *back, Segment *tomove, Segment *fwd,
+movpos_change(Segment *tomove, MovPosComb target,
              int maxdelay_ms, MovPosChange *reservation);
-  /* back and fwd may be 0 if we don't care (and must be if there is
-   * no track in that direction.  It is immaterial which is back and
-   * which fwd.
-   *
-   * If segment has already been requested to change, an attempt is
+  /* If segment has already been requested to change, an attempt is
    * made to replace that change with the new request; if this is not
    * successful then the existing change will still happen.
    *
@@ -159,6 +155,14 @@ movpos_change(Segment *back, Segment *tomove, Segment *fwd,
    * met because of lack of ability to change points.
    */
 
+ErrorCode
+movpos_change_bysegs(Segment *back, Segment *tomove, Segment *fwd,
+                    int maxdelay_ms, MovPosChange *reservation);
+  /* back and fwd may be 0 if we don't care (and must be if there is
+   * no track in that direction.  It is immaterial which is back and
+   * which fwd.
+   */
+
 ErrorCode
 movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r);
   /* Returns EC_MovFeatTooLate if the maxdelay_ms could not be met.
@@ -172,6 +176,11 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r);
 
 void movpos_unreserve(MovPosChange *reservation);
 
+MovPosComb movpos_poscomb_actual(Segment *seg);
+  /* gives actual current position as published by movfeatkind
+   *  -1 means not known or cannot be represented as a MovPosComb
+   */
+
 /*========== speedmgr.c ==========*/
 
 void speedmanager_speedchange_request(Train *tra, long speed);
index f6a318ce030eac1a77b4b8600a12bf037e6b32a0..5f55c1389aee47351694bd6a896acd2c4a4c9c55 100644 (file)
@@ -47,6 +47,7 @@ static void initial_ping(void) {
 }
 
 void sta_startup(void) { sta_goto(Sta_Flush); }
+void sta_finalising_done(void) { sta_goto(Sta_Run); }
 
 static void sta_goto(StartupState new_state) {
   toev_stop(&sta_toev);
@@ -68,12 +69,13 @@ static void sta_goto(StartupState new_state) {
   case Sta_Fault:                                  break;
   case Sta_Settling:   sta_toev.duration=   750;   break;
   case Sta_Resolving:  sta_toev.duration=   500;   break;
+  case Sta_Finalising:                             break;
   case Sta_Run:                                    break;
   }
 
   if (new_state < Sta_Run)
     choreographers_all_abandon();
-  if (new_state < Sta_Resolving)
+  if (new_state < Sta_Finalising)
     points_all_abandon();
 
   piob.l= 0;
@@ -88,10 +90,13 @@ static void sta_goto(StartupState new_state) {
     points_turning_on();
     enco_pic_on(&piob);
     break;
-  case Sta_Run:
+  case Sta_Finalising:
     if (resolve_complete() <0)
       /* in this case, we get stuck - user has to power cycle the layout */
       return;
+    /* resolve_motioncheck will move us to Run eventually, we hope */
+    break;
+  case Sta_Run:
     persist_install();
     retransmit_start();
     break;
@@ -104,6 +109,7 @@ static void sta_goto(StartupState new_state) {
   /* notify various people: */
   oprintf(UPO, "stastate %s\n", stastatelist[sta_state]);
   /* ... add others here. */
+  if (sta_state == Sta_Finalising) resolve_motioncheck();
 }   
 
 void serial_moredata(PicInsn *buf) {
@@ -194,7 +200,8 @@ void on_pic_fault(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
 
 void on_pic_wtimeout(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
   if (sta_state <= Sta_Settling) return;
-  if (sta_state == Sta_Resolving) die("PIC sent WTIMEOUT in Resolving");
+  if (sta_state == Sta_Resolving || sta_state == Sta_Finalising)
+    die("PIC sent WTIMEOUT in Resolving or Finalising");
   oprintf(UPO, "warning watchdog \"PIC watchdog timer triggered\"\n");
 }
 
@@ -222,9 +229,11 @@ static SegmentNum on_pic_detect_prep(int detyn, int objnum) {
 void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
   SegmentNum segn;
   Segment *seg;
+  const char *pname;
   
   segn= on_pic_detect_prep(1,objnum);
   seg= &segments[segn];
+  pname= info_segments[segn].pname;
   
   switch (sta_state) {
   case Sta_Flush:
@@ -232,25 +241,22 @@ void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
   case Sta_Ping:
   case Sta_Fault:
   case Sta_Settling:
-    oprintf(UPO, "warning fixme ignored non-Run detection @%s\n",
-           info_segments[segn].pname);
     break;
-  case Sta_Resolving:  seg->res_detect= 1;             break;
-  case Sta_Run:        safety_notify_detection(seg);   break;
+  case Sta_Resolving:
+    seg->res_detect= 1;
+    break;
+  case Sta_Finalising:
+    if (!seg->res_detect) {
+      oprintf(UPO, "resolution new-detection-in-finalising @%s\n", pname);
+      sta_goto(Sta_Settling);
+    }
+    break;
+  case Sta_Run:
+    safety_notify_detection(seg);
+    break;
   }
 }
 
-/*---------- fixme move these to where they want to go ----------*/
-
-void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
-  if (!objnum) die("PIC sent NUL!");
-  if (sta_state <= Sta_Settling) return;
-  if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
-
-  while (objnum--)
-    retransmit_something();
-}
-
 void on_pic_detect0(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
   on_pic_detect_prep(0,objnum);
 }
index faa07fbf7d84b6f93d48729e0672ca4070f1d7e3..91a24056799a732e329c471a64f4c4f16c808c28 100755 (executable)
@@ -3,14 +3,14 @@
 set -e
 Sta () { l="$l $1"; }
 
-                 # sta_toev   ping_toev
-  Sta Flush      #  R 300      I ?         
-  Sta Off        #  I ?        I ?         
-  Sta Ping       #  I ?        I ?         
-  Sta Fault      #  I ?        R set       
-  Sta Settling   #  I ?        R set       
-  Sta Resolving  #  I ?        R set       
-  Sta Run        #  I ?        R set       
+  Sta Flush
+  Sta Off
+  Sta Ping
+  Sta Fault
+  Sta Settling
+  Sta Resolving
+  Sta Finalising
+  Sta Run
 
 echo 'typedef enum {'
 for s in $l; do echo "  Sta_$s,"; done