chiark / gitweb /
split points into mfq and points core, so we can have relays
authorian <ian>
Sun, 11 May 2008 10:29:19 +0000 (10:29 +0000)
committerian <ian>
Sun, 11 May 2008 10:29:19 +0000 (10:29 +0000)
hostside/README.commands
hostside/movpos.c
hostside/realtime.h
hostside/startup.c
layout/layout-data.h

index b10c1b58246c95f1975de7a84e9da46a979c2893..f249a82c8223bcfbd676ddd7c51c64f31f55be7b 100644 (file)
@@ -53,7 +53,7 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC
                      ! for foredetect
                      @ for det_ignore
 
- U< movpos <segment> point <feat><posn>
+ U< movpos <segment> feat <feat><posn> point|relay
  U< movpos <segment> position <overallposn> moving
  U< movpos <segment> position <overallposn> stable
             <overallposn> may be ? for unknown
index a81abd0b0869483bd90b4fd8ebb6480c24ad9d6f..efac841f5ab6b1443dc13955f07f49bbb056cfa6 100644 (file)
@@ -11,7 +11,7 @@ typedef struct {
   Small posn;
 } Motion;
 
-typedef struct KindInfo KindInfo;
+typedef struct Method Method;
 
 /* Kind-independent code is responsible for determining
  * the method, doing a bit of cleanup, and adjusting the flow
@@ -30,7 +30,7 @@ typedef struct KindInfo KindInfo;
  */
 
 typedef struct MovPosChange {      /* valid in:   filled in by and when:     */
-  const KindInfo **ki;             /*  ARCDE       indep after allocate()    */
+  Method *meth;                    /*  ARCDE       indep after allocate()    */
   Segment *move;                   /*  ARCDE       indep after allocate()    */
   MovPosComb actual;               /*  CD          see below                 */
   MovPosComb intent;               /*  RCD         indep after allocate()    */
@@ -49,13 +49,16 @@ typedef struct MovPosChange {      /* valid in:   filled in by and when:     */
    * the indep code never untangles it so the kind can manage the
    * proper transition.  */
 
-struct KindInfo {
+struct Method {
   const char *pname;
-  Change *(*allocate)(int alloc_motions); /* U->A (always succeeds) */
-  ErrorCode (*reserve)(Change*, Segment*, int ms); /* A->R; error: A->E */
-  ErrorCode (*confirm)(Change*, Segment*, int n_motions,
-                      const Motion*, int ms);   /* [AR]->C; error; [AR]->E */
-  void (*destroy)(Change*);                        /* [ARCE]->U */
+  MovFeatKind kind;
+  Change *(*allocate)(Method *m, int alloc_motions);     /* U->A (never err) */
+  ErrorCode (*reserve)(Method *m, Change*, Segment*,                 /* A->R */
+                      int ms);                               /* error: A->E */
+  ErrorCode (*confirm)(Method *m, Change*, Segment*,          /*     [AR]->C */
+                      int n_motions, const Motion*, int ms); /* err:[AR]->E */
+  void (*destroy)(Method *m, Change*);                          /* [ARCE]->U */
+  void (*all_abandon)(Method *m);
   /* indep guarantees that
    *   alloc_motions >= move->i->n_motions    on reserve
    *   alloc_motions >= n_motions             on confirm
@@ -82,7 +85,7 @@ static void motion_done(Segment *move, MovPosComb actual) {
          move->i->pname, posnpname(move, move->movposcomb));
 }
 
-/*========== points ==========*/
+/*========== points and other fixed timeslot movfeats ==========*/
 
 /*
  * We maintain two queues, one for reserved one for actually confirmed
@@ -95,13 +98,14 @@ static void motion_done(Segment *move, MovPosComb actual) {
  *     currently     next in      after
  *     changing      line         that
  *
- * We increment cslot when we issue a POINT command to the PIC.
+ * We increment cslot when we consider the movfeat to move;
+ * for points and relays this is when we issue the command to the PIC.
  * In a request, the deadline represents the latest allowable value
  * of cslot just before that increment.
  */
 
-typedef unsigned PtSlot;
-typedef int PtSlotSigned;
+typedef unsigned FsqSlot;
+typedef int FsqSlotSigned;
 
 /* We think there are three states: Allocated, Reserved and Confirmed.
  * (plus of course Unallocated where we don't have a request at all).
@@ -121,25 +125,25 @@ typedef int PtSlotSigned;
 typedef struct {                 /* Allocated  Reserved   Confirmed       */
                      /* in queue?    absent     reserved   confirmed      */
   Change h;
-  PtSlot deadline;   /*              ~0         relative   absolute    <- */
+  FsqSlot deadline;  /*              ~0         relative   absolute    <- */
   MovPosComb actual; /*              undef      undef      see below      */
   int n_motions;     /*              alloc'd    alloc'd    undone         */
   Motion motions[];  /*   [0].i:     0          0          non-0       <- */
                      /*  [..].i:     undef      undef      non-0          */
                      /*   .posn:     undef      undef      defined        */
-} PointReq;
+} FsqReq;
   /* We can determine the the state by looking at the two
    * `statedet' fields, marked <- above.
    * There are also intermediate states where the req's
    *  statedet fields do not agree with the queue it's on.
    *  We write these as, for example,
-   *      AR   to mean  statedet says Allocated, but queued on pt_reserved
+   *      AR   to mean  statedet says Allocated, but queued on fsq_reserved
    *      A?   to mean  statedet says Allocated, but may be queued
-   *  etc.  They are only allowed while we are in a pt_... method function.
+   *  etc.  They are only allowed while we are in a fsq_... method function.
    */
-  /* PointReq.actual is subtly differnet to MovPosChange.actual,
+  /* FsqReq.actual is subtly differnet to MovPosChange.actual,
    * as follows:
-   *                              in MovPosChange     in PointReq
+   *                              in MovPosChange     in FsqReq
    *  Position unknown              -1                  0
    *  Position partly known         -1                  unknown feats are 0
    *  Position completely known     exact               exact
@@ -153,89 +157,73 @@ typedef struct {                 /* Allocated  Reserved   Confirmed       */
    * we lose the partial knowledge.
    */
 
-#define CDU_RECHARGE   250 /*ms*/
-#define POINT_MOVEMENT  50 /*ms*/
-#define PT_MAX_QUEUE  15
+#define FSQ_MAX_QUEUE  15
 
 typedef struct {
   int n;
-  PointReq *l[PT_MAX_QUEUE];
-} PointQueue;
+  FsqReq *l[FSQ_MAX_QUEUE];
+} FsqQueue;
 
-/*
- * CDU and point queue states:
- *
- *
- *    ____________                 pt_cdu_     conf'd
- *   /   points_  \                charged       .n
- *   |   all_      |
- *   |   abaondon  |
- *   |             V
- *   |from       INACTIVE              -1      0
- *   |any       <=Sta_Settling
- *  ^^^^^^^^     (start)
- *                 |
- *     ___________ |turning
- *    /           \| _on
- *   |             V
- *   |           CHARGING              0       any
- *   |          >=Sta_Resolving
- *   |             |
- *   |             |on_pic
- *   |             |_charged
- *   |             V
- *   ^           READY                 1       any
- *   |             |
- *   |             |pt_check_action
- *   |             | fires a point
- *    \___________/
- *
- */
+typedef struct FsqMethod FsqMethod;
 
-static PtSlot pt_cslot;
-static int pt_cdu_charged;
-static PointQueue pt_confirmed, pt_reserved;
+typedef struct {
+  /* set by fsq's client before fsq_init */
+  int slot_ms, lag_ms;
+  void (*move)(FsqMethod *m, const MovFeatInfo *mfi, int movfeatposn);
+  /* shared */
+  int ready; /* >0 means ready; set to 0 by fsq just before move */
+  /* fsq's client must arrange that these start out at all-bits-zero */
+  FsqSlot cslot;
+  FsqQueue confirmed, reserved;
+} FsqState;
+
+struct FsqMethod {
+  Method m;
+  FsqState f;
+  /* client may put things here */
+};
 
-static void pt_check_action(void);
-static ErrorCode pt_check_plan(void);
+static void fsq_check_action(FsqMethod *m);
+static ErrorCode fsq_check_plan(FsqMethod *m);
 
-static PtSlotSigned pt_maxdelay_reldeadline(int maxdelay_ms, int n_motions) {
-  if (maxdelay_ms==-1) return PT_MAX_QUEUE*16;
-  return (maxdelay_ms - POINT_MOVEMENT) / CDU_RECHARGE - n_motions;
+static FsqSlotSigned fsq_maxdelay_reldeadline(FsqMethod *m,
+                                             int maxdelay_ms, int n_motions) {
+  if (maxdelay_ms==-1) return FSQ_MAX_QUEUE*16;
+  return (maxdelay_ms - m->f.lag_ms) / m->f.slot_ms - n_motions;
 }
 
-static void pt_queue_remove_index(PointQueue *q, int index) {
+static void fsq_queue_remove_index(FsqQueue *q, int index) {
   q->n--;
   memmove(&q->l[index], &q->l[index+1], sizeof(q->l[0]) * (q->n - index));
 }
 
-static int pt_req_compar(const void *av, const void *bv) {
-  PointReq *const *a= av;
-  PointReq *const *b= av;
-  return (PtSlotSigned)((*b)->deadline - (*a)->deadline);
+static int fsq_req_compar(const void *av, const void *bv) {
+  FsqReq *const *a= av;
+  FsqReq *const *b= av;
+  return (FsqSlotSigned)((*b)->deadline - (*a)->deadline);
 }
 
-static void pt_queue_remove_item(PointQueue *q, PointReq *r) {
-  PointReq **entry;
-  entry= bsearch(r, q->l, q->n, sizeof(q->l[0]), pt_req_compar);
+static void fsq_queue_remove_item(FsqQueue *q, FsqReq *r) {
+  FsqReq **entry;
+  entry= bsearch(r, q->l, q->n, sizeof(q->l[0]), fsq_req_compar);
   assert(entry);
-  pt_queue_remove_index(q, entry - q->l);
+  fsq_queue_remove_index(q, entry - q->l);
 }
 
-static void pt_dequeue(PointReq *r) { /* X->XA */
+static void fsq_dequeue(FsqMethod *m, FsqReq *r) { /* X->XA */
   if (r->motions[0].i) {
-    pt_queue_remove_item(&pt_confirmed, r);
+    fsq_queue_remove_item(&m->f.confirmed, r);
   } else if (~r->deadline) {
-    pt_queue_remove_item(&pt_reserved, r);
+    fsq_queue_remove_item(&m->f.reserved, r);
   } else {
     return;
   }
-  pt_check_plan();
+  fsq_check_plan(m);
 }
 
-static void pt_mark_as_allocated(PointReq *r) { /* AX->X */
+static void fsq_mark_as_allocated(FsqReq *r) { /* AX->X */
   /* Sets statedet fields for Allocated */
-  r->deadline= ~(PtSlot)0;
+  r->deadline= ~(FsqSlot)0;
   r->motions[0].i=0;
 }
 
@@ -244,29 +232,29 @@ static void pt_mark_as_allocated(PointReq *r) { /* AX->X */
    whichwhen= wh##when,                                \
    wh++)
 
-static ErrorCode pt_check_plan(void) {
+static ErrorCode fsq_check_plan(FsqMethod *m) {
   /* Checks whether we can meet the currently queued commitments */
   int future, conf, resv, whichwhen;
-  PointReq *whichr;
+  FsqReq *whichr;
 
   conf=resv=0;
   future=0;
 
-  oprintf(DUPO("movpos/point") "  plan");
+  oprintf(DUPO("movpos/fsq") "%s   plan", m->m.pname);
 
   /* If CDU is charged we can't do one right away */
-  if (!pt_cdu_charged) {
+  if (m->f.ready<0) {
     oprintf(UPO, " +");
     future++;
   }
 
   for (;;) {
-    PointReq *confr= conf < pt_confirmed.n ? pt_confirmed.l[conf] : 0;
-    PointReq *resvr= resv < pt_reserved .n ? pt_reserved .l[resv] : 0;
+    FsqReq *confr= conf < m->f.confirmed.n ? m->f.confirmed.l[conf] : 0;
+    FsqReq *resvr= resv < m->f.reserved .n ? m->f.reserved .l[resv] : 0;
     if (!confr && !resvr) break;
     oprintf(UPO," %d:",future);
-    int confwhen= confr ? confr->deadline - pt_cslot : INT_MAX;
-    int resvwhen= resvr ? resvr->deadline            : INT_MAX;
+    int confwhen= confr ? confr->deadline - m->f.cslot : INT_MAX;
+    int resvwhen= resvr ? resvr->deadline              : INT_MAX;
     if (future && resvwhen < confwhen) {
       WHICH(resv);
       oprintf(UPO,"~");
@@ -292,65 +280,65 @@ static ErrorCode pt_check_plan(void) {
 
 #undef WHICH
 
-static ErrorCode pt_enqueue(PointQueue *q, PointReq *r) { /* XA -> X */
+static ErrorCode fsq_enqueue(FsqMethod *m, FsqQueue *q,         /* XA -> X */
+                            FsqReq *r) {        /* or on error,   XA -> A */
   int insat;                 /* ... where X is R or C and corresponds to q */
-                             /* or on error,   XA -> A */
 
-  if (q->n == PT_MAX_QUEUE) {
+  if (q->n == FSQ_MAX_QUEUE)
     return EC_BufferFull;
-  }
 
   for (insat= q->n;
-       insat>0 && (PtSlotSigned)(r->deadline - q->l[insat-1]->deadline) < 0;
+       insat>0 && (FsqSlotSigned)(r->deadline - q->l[insat-1]->deadline) < 0;
        insat--)
     q->l[insat]= q->l[insat-1];
   q->l[insat]= r;
   q->n++;
 
-  return pt_check_plan();
-  /* if this fails, indep machinery calls pt_destroy which dequeues */
+  return fsq_check_plan(m);
+  /* if this fails, indep machinery calls fsq_destroy which dequeues */
 }
 
-/*---------- kind method entrypoints ----------*/
+/*---------- method entrypoints ----------*/
 
-static Change *point_allocate(int alloc_motions) {
-  PointReq *r;
+static Change *fsq_allocate(Method *mm, int alloc_motions) {
+  FsqReq *r;
 
-  assert(pt_cdu_charged>=0);
   if (!alloc_motions)
     /* we need at least one motion in the table so we can tell
      *  the difference between the states by looking at motions[0].i */
     alloc_motions= 1;
 
   r= mmalloc(sizeof(*r) + alloc_motions * sizeof(r->motions[0]));
-  r->deadline= ~(PtSlot)0;
+  r->deadline= ~(FsqSlot)0;
   r->n_motions= alloc_motions;
   r->motions[0].i= 0;
   return (Change*)r;
 }
 
-static ErrorCode point_reserve(Change *chg, Segment *move,
-                              int maxdelay_ms) {
-  PointReq *r= (PointReq*)chg;
-  PtSlotSigned reldeadline;
+static ErrorCode fsq_reserve(Method *mm, Change *chg,
+                            Segment *move, int maxdelay_ms) {
+  FsqMethod *m= (void*)mm;
+  FsqReq *r= (FsqReq*)chg;
+  FsqSlotSigned reldeadline;
 
-  reldeadline= pt_maxdelay_reldeadline(maxdelay_ms, r->n_motions);
-  if (reldeadline <= 0) { pt_mark_as_allocated(r); return EC_MovFeatTooLate; }
+  reldeadline= fsq_maxdelay_reldeadline(m, maxdelay_ms, r->n_motions);
+  if (reldeadline <= 0) { fsq_mark_as_allocated(r); return EC_MovFeatTooLate; }
   r->deadline= reldeadline;
-  return pt_enqueue(&pt_reserved, r);
+  return fsq_enqueue(m, &m->f.reserved, r);
 }
 
-static ErrorCode point_confirm(Change *chg, Segment *move,
-                              int n_motions, const Motion *motions,
-                              int maxdelay_ms) {
-  PointReq *r= (PointReq*)chg;
-  PtSlotSigned reldeadline;
+static ErrorCode fsq_confirm(Method *mm, Change *chg, Segment *move,
+                            int n_motions, const Motion *motions,
+                            int maxdelay_ms) {
+  FsqMethod *m= (void*)mm;
+  FsqReq *r= (FsqReq*)chg;
+  FsqSlotSigned reldeadline;
   int allow_failure;
   ErrorCode ec;
 
-  oprintf(DUPO("movpos/point") "confirm %s n=%d maxdelay=%dms"
+  oprintf(DUPO("movpos/fsq") "%s confirm %s n=%d maxdelay=%dms"
          " (res: [%d@t+%d])\n",
-         move->i->pname, n_motions, maxdelay_ms,
+         m->m.pname, move->i->pname, n_motions, maxdelay_ms,
          r->n_motions, r->deadline);
 
   /* If the segment is moving, these motions are already based on the
@@ -364,26 +352,27 @@ static ErrorCode point_confirm(Change *chg, Segment *move,
   assert(n_motions <= r->n_motions);
   if (maxdelay_ms == -1) {
     reldeadline= r->deadline;
-    if (!~r->deadline) reldeadline= pt_maxdelay_reldeadline(-1, n_motions);
+    if (!~r->deadline) reldeadline= fsq_maxdelay_reldeadline(m, -1, n_motions);
   } else {
-    reldeadline= pt_maxdelay_reldeadline(maxdelay_ms, n_motions);
+    reldeadline= fsq_maxdelay_reldeadline(m, maxdelay_ms, n_motions);
   }
-  allow_failure= reldeadline < (PtSlotSigned)r->deadline;
-  oprintf(DUPO("movpos/point") " reldeadline=[%d@t+%d] allow_failure=%d\n",
-         n_motions, reldeadline, allow_failure);
+  allow_failure= reldeadline < (FsqSlotSigned)r->deadline;
+  oprintf(DUPO("movpos/fsq") "%s  reldeadline=[%d@t+%d] allow_failure=%d\n",
+         m->m.pname, n_motions, reldeadline, allow_failure);
 
   /* state A or R */
-  pt_dequeue(r);
+  fsq_dequeue(m, r);
                                            /* states of existing: */
-  PointReq *existing=
-    move->moving ? (PointReq*)move->motion : 0;   /* U or C */
+  FsqReq *existing=
+    move->moving ? (FsqReq*)move->motion : 0;   /* U or C */
   if (existing) {
-    oprintf(DUPO("movpos/point")
-           " existing %s n=%d deadline=t+%d\n",
+    oprintf(DUPO("movpos/fsq")
+           "%s  existing %s n=%d deadline=t+%d\n",
+           m->m.pname,
            existing->h.move->i->pname,
            existing->n_motions,
-           existing->deadline - pt_cslot);
-    pt_dequeue(existing);                         /* U or CA */
+           existing->deadline - m->f.cslot);
+    fsq_dequeue(m, existing);                   /* U or CA */
   }
 
   /* state A or RA */
@@ -391,7 +380,7 @@ static ErrorCode point_confirm(Change *chg, Segment *move,
   if (!n_motions) r->motions[0].i= move->i->movfeats;
   assert(r->motions[0].i);
   r->n_motions= n_motions;
-  r->deadline= reldeadline + pt_cslot;
+  r->deadline= reldeadline + m->f.cslot;
 
   if (n_motions == move->i->n_movfeats)
     r->actual= 0;
@@ -400,15 +389,15 @@ static ErrorCode point_confirm(Change *chg, Segment *move,
   assert(r->actual >= 0);
 
   /* state CA */
-  ec= pt_enqueue(&pt_confirmed, r);
-  oprintf(DUPO("movpos/point") " pt_enqueue=%s\n", ec2str(ec));
+  ec= fsq_enqueue(m, &m->f.confirmed, r);
+  oprintf(DUPO("movpos/fsq") "%s  pt_enqueue=%s\n", m->m.pname, ec2str(ec));
   assert(allow_failure || !ec);
 
   if (existing) {                                  /* CA */
     if (ec) { /* state C but bad */
-      pt_dequeue(r); /* state CA */
-      pt_mark_as_allocated(r); /* state A */
-      ErrorCode ec_putback= pt_enqueue(&pt_confirmed, existing);
+      fsq_dequeue(m,r); /* state CA */
+      fsq_mark_as_allocated(r); /* state A */
+      ErrorCode ec_putback= fsq_enqueue(m,&m->f.confirmed, existing);
       assert(!ec_putback);                         /* C */
     } else { /* state C and good */
       free(existing);                              /* U */
@@ -425,44 +414,44 @@ static ErrorCode point_confirm(Change *chg, Segment *move,
   move->motion= chg;
   move->movposcomb= -1;
   ouposn_moving(chg);
-  pt_check_action();
+  fsq_check_action(m);
   return 0;
 }
 
-static void point_destroy(Change *chg) { /* X->XA and then free it */
-  PointReq *r= (PointReq*)chg;
-  pt_dequeue(r);
+static void fsq_destroy(Method *mm, Change *chg) { /* X->XA and then freed */
+  FsqMethod *m= (void*)mm;
+  FsqReq *r= (FsqReq*)chg;
+  fsq_dequeue(m,r);
   free(r);
 }
 
-/*---------- actually firing points, yay! ----------*/
+/*---------- something to do ? ----------*/
 
-static void pt_check_action(void) {
-  PicInsn piob;
+static void fsq_check_action(FsqMethod *m) {
+  /* client should call this after it sets ready */
   ErrorCode ec;
 
-  if (!pt_confirmed.n) {
+  if (!m->f.confirmed.n) {
     if (sta_state == Sta_Finalising) resolve_motioncheck();
     return;
   }
 
-  PointReq *r= pt_confirmed.l[0];
+  FsqReq *r= m->f.confirmed.l[0];
 
-  if (r->n_motions && pt_cdu_charged) {
-    /* look for something to fire */
-    Motion *m= &r->motions[--r->n_motions];
-    assert(m->posn < m->i->posns);
-    enco_pic_point(&piob, m->i->boob[m->posn]);
-    serial_transmit(&piob);
-    oprintf(UPO, "movpos %s point %s%d\n", r->h.move->i->pname,
-           m->i->pname, m->posn);
-    pt_cdu_charged= 0;
-    pt_cslot++;
+  if (r->n_motions && m->f.ready>0) {
+    /* look for something to move */
+    Motion *mo= &r->motions[--r->n_motions];
+    assert(mo->posn < mo->i->posns);
+    m->f.ready= 0;
+    m->f.move(m, mo->i, mo->posn);
+    oprintf(UPO, "movpos %s feat %s%d %s\n", r->h.move->i->pname,
+           mo->i->pname, mo->posn, m->m.pname);
+    m->f.cslot++;
 
-    MovPosComb above_weight= m->i->weight * m->i->posns;
+    MovPosComb above_weight= mo->i->weight * mo->i->posns;
     MovPosComb above= r->actual / above_weight;
-    MovPosComb below= r->actual % m->i->weight;
-    r->actual= above*above_weight + m->posn*m->i->weight + below;
+    MovPosComb below= r->actual % mo->i->weight;
+    r->actual= above*above_weight + mo->posn*mo->i->weight + below;
     if (r->h.actual >= 0 || !r->n_motions)
       r->h.actual= r->actual;
     ouposn_moving(&r->h);
@@ -475,86 +464,145 @@ static void pt_check_action(void) {
      */
     Segment *move= r->h.move;
     assert(move->moving && move->motion == (Change*)r);
-    pt_queue_remove_index(&pt_confirmed,0);
-    pt_mark_as_allocated(r); /* now state A aka Done */
+    fsq_queue_remove_index(&m->f.confirmed,0);
+    fsq_mark_as_allocated(r); /* now state A aka Done */
     motion_done(move,r->h.actual);
     free(r);
-    ec= pt_check_plan();  assert(!ec);
-    pt_check_action();
+    ec= fsq_check_plan(m);  assert(!ec);
+    fsq_check_action(m);
   }
 }
 
 /*---------- entrypoints from rest of program ----------*/
 
-void points_all_abandon(void) {
+static void fsq_all_abandon(Method *mm) {
+  FsqMethod *m= (void*)mm;
   int i;
 
-  assert(!pt_reserved.n);
+  assert(!m->f.reserved.n);
 
-  for (i=0; i<pt_confirmed.n; i++) {
-    PointReq *r= pt_confirmed.l[i];
+  for (i=0; i<m->f.confirmed.n; i++) {
+    FsqReq *r= m->f.confirmed.l[i];
     Segment *move= r->h.move;
     assert(move->motion == (Change*)r);
     motion_done(move,r->h.actual);
     free(r);
   }
-  pt_confirmed.n= 0;
-  pt_cdu_charged= -1;
+  m->f.confirmed.n= 0;
 }
 
-void points_turning_on(void) {
-  pt_cdu_charged= 0;
+/*========== points ==========*/
+
+/*
+ * CDU and point queue states:
+ *
+ *
+ *    ____________                             conf'd
+ *   /   points_  \                ready         .n
+ *   |   all_      |
+ *   |   abandon   |
+ *   |             V
+ *   |from       INACTIVE              -1      0
+ *   |any       <=Sta_Settling
+ *  ^^^^^^^^     (start)
+ *                 |
+ *     ___________ |turning
+ *    /           \| _on
+ *   |             V
+ *   |           CHARGING              0       any
+ *   |          >=Sta_Resolving
+ *   |             |
+ *   |             |on_pic
+ *   |             |_charged
+ *   |             V
+ *   ^           READY                 1       any
+ *   |             |
+ *   |             |fsq_check_action
+ *   |             | calls point_move which fires a point
+ *    \___________/
+ *
+ */
+
+#define CDU_RECHARGE   250 /*ms*/
+#define POINT_MOVEMENT  50 /*ms*/
+
+static Change *point_allocate(Method *mm, int alloc_motions) {
+  FsqMethod *m= (void*)mm;
+  assert(m->f.ready>=0);
+  return fsq_allocate(mm, alloc_motions);
+}
+
+static void point_move(FsqMethod *m, const MovFeatInfo *mfi, int posn) {
+  /* actually firing points, yay! */
+  PicInsn piob;
+  enco_pic_point(&piob, mfi->boob[posn]);
+  serial_transmit(&piob);
 }
 
+static void points_all_abandon(Method *mm) {
+  FsqMethod *m= (void*)mm;
+  m->f.ready= -1;
+  fsq_all_abandon(mm);
+}
+
+static FsqMethod points_method;
+
+void points_turning_on(void) {
+  FsqMethod *m= &points_method;
+  m->f.ready= 0;
+}
 void on_pic_charged(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
-  if (pt_cdu_charged<0) return;
-  pt_cdu_charged= 1;
-  pt_check_action();
+  FsqMethod *m= &points_method;
+  if (m->f.ready<0) return;
+  m->f.ready= 1;
+  fsq_check_action(m);
 }
 
-static const KindInfo point_method= {
-  "point",  point_allocate,  point_reserve,  point_confirm,  point_destroy
+static FsqMethod points_method= {
+  { "point", mfk_point,
+    point_allocate, fsq_reserve, fsq_confirm,
+    fsq_destroy, points_all_abandon },
+  { .lag_ms= POINT_MOVEMENT, .slot_ms= CDU_RECHARGE, .move= point_move }
 };
 
 /*========== dummy `nomove' kind ==========*/
 
-static Change *nomove_allocate(int alloc_motions) {
+static Change *nomove_allocate(Method *m, int alloc_motions) {
   oprintf(DUPO("movfeatkind-momove") "allocate %d\n",alloc_motions);
   return mmalloc(sizeof(Change));
 }
-static void nomove_destroy(Change *chg) {
-  free(chg);
-}
-
-static ErrorCode nomove_reserve(Change *chg, Segment *move, int ms) {
+static ErrorCode nomove_reserve(Method *m, Change *c, Segment *move, int ms) {
   oprintf(DUPO("movfeatkind-nomove") "reserve\n");
   return 0;
 }
-static ErrorCode nomove_confirm(Change *chg, Segment *move, int n_motions,
+static void nomove_destroy(Method *m, Change *c) { free(c); }
+static ErrorCode nomove_confirm(Method *m, Change *c, Segment *move, int n,
                       const Motion *motions, int ms) {
   oprintf(DUPO("movfeatkind-nomove") "confirm\n");
-  nomove_destroy(chg);
+  nomove_destroy(m,c);
   return 0;
 }
+static void nomove_all_abandon(Method *m) { }
 
-static const KindInfo nomove_method= {
-  "nomove", nomove_allocate, nomove_reserve, nomove_confirm, nomove_destroy
+static Method nomove_method= {
+  "nomove", mfk_none, nomove_allocate, nomove_reserve, nomove_confirm,
+  nomove_destroy, nomove_all_abandon
 };
 
 /*========== method-independent machinery ==========*/
 
-static const KindInfo *methodinfos[]= {
+static Method *methods[]= {
   &nomove_method,
-  &point_method,
-  0,
+  (Method*)&points_method,
+  0, /* relay */
   0
 };
 
-static Change *mp_allocate(const KindInfo **ki, Segment *move,
+static Change *mp_allocate(Method *meth, Segment *move,
                           int alloc_motions, MovPosComb target) {
   assert(sta_state >= Sta_Resolving);
-  Change *chg= (*ki)->allocate(alloc_motions);
-  chg->ki=        ki;
+  Change *chg= meth->allocate(meth, alloc_motions);
+  chg->meth=      meth;
   chg->move=      move;
   chg->intent=    target;
   return chg;
@@ -566,7 +614,7 @@ static int change_needed(const MovFeatInfo *feati,
   r= startpoint<0 ||
     (target - startpoint) / feati->weight % feati->posns;
   oprintf(DUPO("movpos/change-needed") "%s:%s(%d*%d) %d..%d => %d\n",
-         methodinfos[feati->kind]->pname, feati->pname,
+         methods[feati->kind]->pname, feati->pname,
          feati->posns, feati->weight,
          startpoint, target, r);
   return r;
@@ -601,7 +649,7 @@ static int evaluate_target(Segment *move, MovPosComb target,
 
   if (kind_r) *kind_r= kind;
   oprintf(DUPO("movpos/eval") "changes=%d kind=%s\n",
-         tchanges, methodinfos[kind]->pname);
+         tchanges, methods[kind]->pname);
   return tchanges;
 }
 
@@ -653,7 +701,7 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
     actual= move->movposcomb;
     assert(!move->motion);
   } else {
-    kind= move->motion->ki - methodinfos;
+    kind= move->motion->meth->kind;
     actual= move->motion->actual;
   }
 
@@ -661,7 +709,7 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
          move->i->pname, posnpname(move,target),
          maxdelay_ms, posnpname(move, actual));
   if (chg) oprintf(DUPO("movpos/change") " chg=%s:%s/%s\n",
-                  (*chg->ki)->pname, chg->move->i->pname,
+                  chg->meth->pname, chg->move->i->pname,
                   posnpname(chg->move, chg->intent));
 
   { /* provide horizon for visibility of motions[] */
@@ -684,21 +732,21 @@ ErrorCode movpos_change(Segment *move, MovPosComb target,
       n_motions++;
     }
 
-    const KindInfo **ki= &methodinfos[kind];
+    Method *meth= methods[kind];
 
     if (chg) {
-      if (chg->ki != ki ||
+      if (chg->meth != meth ||
          chg->move != move ||
          chg->intent != target)
        return EC_MovFeatReservationInapplicable;
     } else {
-      chg= mp_allocate(ki,move,n_motions,target);
+      chg= mp_allocate(meth,move,n_motions,target);
     }
     chg->actual= actual;
 
     oprintf(DUPO("movpos/change") "confirm %s:%d...\n",
-           (*ki)->pname, n_motions);
-    ec= (*ki)->confirm(chg, move, n_motions, motions, maxdelay_ms);
+           meth->pname, n_motions);
+    ec= meth->confirm(meth, chg, move, n_motions, motions, maxdelay_ms);
     oprintf(DUPO("movpos/change") "confirm => %s\n",errorcodelist[ec]);
     if (ec) goto x;
   }
@@ -723,11 +771,11 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r,
   nchanges= evaluate_target(move,target,startpoint,&kind);
   if (nchanges==-1) return EC_MovFeatKindsCombination;
 
-  const KindInfo **ki= &methodinfos[kind];
+  Method *meth= methods[kind];
   oprintf(DUPO("movpos/reserve") "allocate %s:%d...\n",
-         (*ki)->pname, nchanges);
-  Change *chg= mp_allocate(ki, move, nchanges, target);
-  ec= (*ki)->reserve(chg, move, maxdelay_ms);
+         meth->pname, nchanges);
+  Change *chg= mp_allocate(meth, move, nchanges, target);
+  ec= meth->reserve(meth, chg, move, maxdelay_ms);
   oprintf(DUPO("movpos/reserve") "reserve => %s\n",errorcodelist[ec]);
   if (ec) goto x;
 
@@ -742,9 +790,9 @@ movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r,
 void movpos_unreserve(MovPosChange *res) {
   if (!res) return;
   oprintf(DUPO("movpos/unreserve") "%s:%s/%s\n",
-         (*res->ki)->pname, res->move->i->pname,
+         res->meth->pname, res->move->i->pname,
          posnpname(res->move, res->intent));
-  (*res->ki)->destroy(res);
+  res->meth->destroy(res->meth, res);
 }
 
 MovPosComb movpos_poscomb_actual(Segment *seg) {
@@ -754,3 +802,9 @@ MovPosComb movpos_poscomb_actual(Segment *seg) {
 MovPosComb movpos_change_intent(MovPosChange *chg) {
   return chg->intent;
 }
+
+void motions_all_abandon(void) {
+  Method **meth;
+  for (meth=methods; *meth; meth++)
+    (*meth)->all_abandon(*meth);
+}
index 7bb1540fc9ddd309ee98abb0a64fcd73f7e906dc..3a573d23589d1d76471b9c6f54f19e7b7c1f3219 100644 (file)
@@ -185,7 +185,7 @@ int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi);
 /*---------- from movpos.c ----------*/
 
 void points_turning_on(void);
-void points_all_abandon(void);
+void motions_all_abandon(void);
 
 /*---------- from eventhelp.c ----------*/
 
index 6b457ddc646a05c8811249dc88654510c31c76df..0fdcfcb5850470686db223ddec290029d6ada5c2 100644 (file)
@@ -77,7 +77,7 @@ static void sta_goto(StartupState new_state) {
   if (new_state < Sta_Run)
     choreographers_all_abandon();
   if (new_state < Sta_Finalising)
-    points_all_abandon();
+    motions_all_abandon();
 
   piob.l= 0;
   switch (new_state) {
index c45ab8a9e705e28d154b25fda92c3f012a66b145..03b877208da5ec7ce3a458ca6785bbf6a045bd50 100644 (file)
@@ -28,7 +28,7 @@ typedef enum {
   mfk_none,
   mfk_point,
   mfk_relay
-  /* must also add new entries to movpos.c:methodinfos */
+  /* must also add new entries to movpos.c:methods[] */
 } MovFeatKind;
 
 /*========== data from config files and layout cad/cam ==========*/