chiark / gitweb /
giant reorg abolishes TrainNum most of the time; working on making it build
authorian <ian>
Sun, 10 Sep 2006 18:37:11 +0000 (18:37 +0000)
committerian <ian>
Sun, 10 Sep 2006 18:37:11 +0000 (18:37 +0000)
21 files changed:
hostside/.cvsignore
hostside/Makefile
hostside/actual.c
hostside/common.h
hostside/dummy-trains.c
hostside/main.c
hostside/realtime.c
hostside/realtime.h
hostside/record-l.l
hostside/record-y.y
hostside/record.c
hostside/record.h [new file with mode: 0644]
hostside/rtmacros.h [deleted file]
hostside/safety.c
hostside/safety.h
hostside/speed.c
hostside/startup.c
hostside/trackloc.c
hostside/utils.c
layout/data2safety
layout/layout-data.h

index 62750d50a700e6d95bba998eecdaf70d8a54cf5e..82443edb81fe96de41fcb94c66a9fe0d53f7f943 100644 (file)
@@ -11,5 +11,5 @@ gui-plan-bot
 selectors.h
 errorcodes.h
 retransmit-table.h
-record-l.c
+record-l.[ch]
 record-y.[ch]
index a718672ccae36716ef4a23eb8a4d587d14918e0d..caca32556bfbcae00184eddfe15da75d28a302d7 100644 (file)
@@ -17,6 +17,8 @@ hostside-old: serialio.o nmra.o main.o encode.o utils.o
 
 BESSAR=bessar:things/trains-bessar/hostside/.
 
+SPECIAL_CFLAGS_record-l= $(FLEXCFLAGS)
+
 on-bessar:     $(TARGETS)
                RSYNC_RSH=fsh rsync $(TARGETS) $(BESSAR)
 
@@ -24,9 +26,11 @@ on-bessar:   $(TARGETS)
                RSYNC_RSH=fsh rsync $^ $(BESSAR)
 
 realtime:      realtime.o startup.o cdumgr.o safety.o trackloc.o       \
-                actual.o dummy-trains.o                                \
+                speed.o actual.o retransmit.o                          \
                 cmdinput.o obc.o eventhelp.o                           \
+                record.o record-l.o record-y.o                         \
                 utils.o serialio.o parseutils.o auproto-pic.o          \
+                nmra.o encode.o                                        \
                 ../layout/ours.layout-data.o                           \
                 __oop-read-copy.o -loop
                $(LINK)
index ef86d3a10615c0451d9873134fc969c62652e698..21eef04e61241576530ba166dffc280b4df9a463 100644 (file)
@@ -7,9 +7,6 @@
 
 static PicInsn polarityinsn= { { 0x90 }, 0 };
 
-#define SEG                                            \
-  const SegmentInfo *segi= &info_segments[segn];
-
 #define OPONBIT_BYTE (polarityinsn.d[bytenum])
 #define OPONBIT(body) do{                              \
     BoardObject bo;                                    \
@@ -25,8 +22,7 @@ static PicInsn polarityinsn= { { 0x90 }, 0 };
     { body }                                           \
   }while(0)
 
-int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn) {
-  SEG;
+int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi) {
   OPONBIT({
     return !!(OPONBIT_BYTE & bitv);
   });
@@ -36,10 +32,8 @@ void actual_inversions_start(void) {
   polarityinsn.l= (info_maxreverse + 4 + 6) / 7;
 }
 
-void actual_inversions_segment(SegmentNum segn) {
-  SEG;
-  State *s= &safety_state;
-  const SegmentState *seg= &s->segments[segn];
+void actual_inversions_segment(Segment *seg) {
+  const SegmentInfo *segi= seg->i;
   
   OPONBIT({
     Byte *insnbyte= &OPONBIT_BYTE;
index 83754b392ba8075912e92aa90668bb1252baf820..b44acbd2966764003d3e1e2f058d109ab2720139 100644 (file)
@@ -97,10 +97,13 @@ void die_vprintf_hook(const char *fmt, va_list al)
      __attribute__((format(printf,1,0)));
 
 void *mmalloc(size_t sz);
+void *mrealloc(void *old, size_t sz);
 char *mstrdupl(const char *s, int l);
 char *mstrdup(const char *s);
 void mgettimeofday(struct timeval *tv);
 
+void badusage(const char *why);
+
 #define massert(x) ((x) ? (void)0 : diem())
 
 /*---------- from serialio.c ----------*/
index 86bd7c1ab5382ee8e2068dd3f926c98abe0c46d4..f03295a91988fdb74ec5da750fcbe17142fd0648 100644 (file)
@@ -1,6 +1,8 @@
 /*
  */
 
+FIXME this should go in a config file
+
 #include "realtime.h"
 
 #define NOTA_TRAIN { 0,0,0,0, "internal-error-not-a-train" }
index 6ea07ec49bd17d2fbcae3c2f91434b3c9d0b9703..1a8ffbd16c3ab2b6e63d3ec18c5ed04e03068733 100644 (file)
@@ -30,10 +30,6 @@ static Nmra buf;
 void die_hook(void) { }
 void die_vprintf_hook(const char *fmt, va_list al) { }
 
-static void badusage(const char *why) {
-  fprintf(stderr,"bad usage: %s\n",why); exit(8);
-}
-
 static void pahex(const char **argv) {
   const char *data_string;
   char hbuf[3], *ep;
index cb8274c6ac6cbc840281d673634734f22f1fcfaf..629b5152460c079388ff4b4867b742bc4496c0ff 100644 (file)
@@ -10,7 +10,7 @@ const char *progname= "realtime";
 
 CommandInput cmdi;
 
-static const char *device;
+static const char *device= "/dev/ttya0";
 
 /*---------- general event handling ----------*/
 
@@ -40,48 +40,48 @@ static void *read_exception(oop_source *evts, int fd,
 
 /*---------- logging etc. ----------*/
 
-static char *transegn2suffixstring(TrainNum tran, SegmentNum segn) {
-  /* Either arg may be NOTA(...), in which case it's not included.
+static char *transegn2suffixstring(Train *tra, Segment *seg) {
+  /* Either arg may be 0, in which case it's not included.
    * Result string will be empty, or start with ": "
    * Result string is from malloc.
    * Never fails.
    */
-  const char *tra, *seg;
+  const char *trapn, *segpn;
   char *s;
   int r;
 
-  seg= SOMEP(segn) ? info_segments[segn].pname : 0;
-  tra= SOMEP(tran) ? info_trains[tran].pname : 0;
+  segpn= seg ? seg->i->pname : 0;
+  trapn= tra ? tra->pname : 0;
 
   r= asprintf(&s, "%s%s%s%s%s",
-             seg||tra ? ":" : "",
-             seg ? " @" : "",
-             seg ? seg : "",
-             tra ? " " : "",
-             tra ? tra : "");
-  if (r<0) diee("vasprintf failed in transegn2suffixstring "
-               "tran=%lu segn=%lu", (unsigned long)tran, (unsigned long)segn);
+             segpn||trapn ? ":" : "",
+             segpn ? " @" : "",
+             segpn ? segpn : "",
+             trapn ? " " : "",
+             trapn ? trapn : "");
+  if (r<0) diee("vasprintf failed in transegn2suffixstring");
   return s;
 }
 
-void vlogmsg(ErrorCode ec, TrainNum tran, SegmentNum segn,
+void vlogmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
             const char *fmt, va_list al) {
   oprintf(UPO, "message %s ", ec ? errorcodelist[ec] : "info");
   ovprintf(UPO,fmt,al);
-  if (SOMEP(segn) || SOMEP(tran)) oprintf(UPO, ":");
-  if (SOMEP(segn)) oprintf(UPO, " @%s", info_segments[segn].pname);
-  if (SOMEP(tran)) oprintf(UPO, " %s",  info_trains[tran].pname);
+  if (segi || tra) oprintf(UPO, ":");
+  if (segi) oprintf(UPO, " @%s", segi->pname);
+  if (tra) oprintf(UPO, " %s",  tra->pname);
   oprintf(UPO, "\n");
 }
 
-void logmsg(ErrorCode ec, TrainNum tran, SegmentNum segn,const char *fmt,...) {
+void logmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
+           const char *fmt,...) {
   va_list al;
   va_start(al,fmt);
-  vlogmsg(ec,tran,segn,fmt,al);
+  vlogmsg(ec,tra,segi,fmt,al);
   va_end(al);
 }
 
-void safety_vpanic(TrainNum tran, SegmentNum segn,const char *fmt,va_list al) {
+void safety_vpanic(Train *tra, Segment *seg,const char *fmt,va_list al) {
   char *msg, *where;
   PicInsn piob;
 
@@ -91,20 +91,20 @@ void safety_vpanic(TrainNum tran, SegmentNum segn,const char *fmt,va_list al) {
   if (vasprintf(&msg,fmt,al) < 0)
     diee("vasprintf failed in safety_vpanic fmt=\"%s\"", fmt);
 
-  where= transegn2suffixstring(tran,segn);
+  where= transegn2suffixstring(tra,seg);
   die("fatal safety problem: %s%s", msg, where);
 }
 
-void safety_panic(TrainNum tran, SegmentNum segn, const char *fmt, ...) {
+void safety_panic(Train *tra, Segment *seg, const char *fmt, ...) {
   va_list al;
   va_start(al,fmt);
-  safety_panic(tran, segn, fmt, al);
+  safety_panic(tra, seg, fmt, al);
 }
 
-ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt,...) {
+ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt,...) {
   va_list al;
   va_start(al,fmt);
-  vlogmsg(EC_Safety, tran, segn, fmt, al);
+  vlogmsg(EC_Safety, tra, seg?seg->i:0, fmt, al);
   va_end(al);
   return EC_Safety;
 }
@@ -199,7 +199,7 @@ void serial_transmit(const PicInsn *pi) {
         segn < info_nsegments;
         segn++, segi++) {
       if (!segi->invertible) continue;
-      if (!picinsn_polarity_testbit(pi,segn)) continue;
+      if (!picinsn_polarity_testbit(pi,segi)) continue;
       oprintf(UPO,"%s%s", delim, segi->pname);
       delim= ",";
     }
@@ -224,10 +224,18 @@ void serial_transmit(const PicInsn *pi) {
 
 int main(int argc, const char **argv) {
   oop_source_sys *sys_events;
+  const char *arg;
   int r;
 
-  device= argv[1];
-  if (!device) device= "/dev/ttya0";
+  while ((arg=*++argv) && *arg=='-') {
+    arg++;
+    switch (*arg++) {
+    case 's': device= arg; break;
+    default: badusage("unknown option");
+    }
+  }
+
+  records_parse(argv);
 
   sys_events= oop_sys_new();  if (!sys_events) diee("oop_sys_new");
   events= oop_sys_source(sys_events);  massert(events);
index c18118d9624703d3b6dff159dc1122a570b60b05..197efc68fa38f4198c9ed06db6c3bc70ec5c73f6 100644 (file)
@@ -6,7 +6,6 @@
 #define REALTIME_H
 
 #include "daemons.h"
-#include "safety.h"
 #include "auproto-pic.h"
 #include "dliste.h"
 
 #include <errno.h>
 #include <assert.h>
 #include <stdlib.h>
+#include <limits.h>
+#include <stddef.h>
 
 #include <sys/types.h>
 #include <sys/time.h>
 
+#include "../layout/layout-data.h"
+
+typedef struct Segment Segment;
+typedef struct Train Train;
+
 /*---------- from retransmit.c ----------*/
 
 typedef struct RetransmitRelaxedNode RetransmitRelaxedNode;
@@ -74,6 +80,10 @@ void serial_moredata(PicInsn *buf);
 
 extern StartupState sta_state;
 
+/*---------- from/for record.c ----------*/
+
+void records_parse(const char **argv);
+
 /*---------- from/for realtime.c ----------*/
 
 void oupicio(const char *dirn, const PicInsnInfo *pii, int objnum);
@@ -83,7 +93,7 @@ void serial_transmit(const PicInsn *pi);
 
 /*---------- from actual.c ----------*/
 
-int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn);
+int picinsn_polarity_testbit(const PicInsn *pi, const SegmentInfo *segi);
   /* this belongs in {au,skel}proto-pic.[ch] really but it's
    * more convenient here. */
 
@@ -91,4 +101,8 @@ int picinsn_polarity_testbit(const PicInsn *pi, SegmentNum segn);
 
 void abandon_run(void);
 
+
+#include "safety.h"
+
+
 #endif /*REALTIME_H*/
index 4a61e8d6b543cfc8ecd0a80bdd229b1da1b49e37..20f845bf0931140fabc15cb4b919c180ef0f12c0 100644 (file)
@@ -1,24 +1,22 @@
 /* -*- fundamental -*- */
 
 %{
-#include "y.tab.h"
+#include "record.h"
 %}
 
 %option warn
 %option batch
 %option noyywrap
-
-%option bison-locations
-%option bison-bridge
+%option yylineno
+%option prefix="record_yy"
+%option header-file="record-l.h"
 
 %{
-#define STR  yylval->str= xstrdup(yytext); return
+#define STR  record_yylval.name= record_tempzone_strdup(yytext);  return
 %}
 
 %%
 
-max-trains     { yylval->str= 0; return MAXTRAINS; }
-
 train          { STR TRAIN; }
 seg            { STR SEG; }
 is             { STR IS; }
@@ -27,15 +25,15 @@ has         { STR HAS; }
 step           { STR STEP; }           
 end            { STR END; }            
 
-[A-Za-z0-9_]+  { STR IDENT; }
+[A-Za-z][A-Za-z0-9_]+  { STR IDENT; }
 
-[0-9]{0,5}     { yylval->num= strtoul(yytext,0,10); return NUM; }
-[0-9]{6}       { badrecord("number too long"); }
+[0-9]{0,5}     { record_yylval.num= strtoul(yytext,0,10); return NUM; }
+[0-9]{6}       { record_yyerror("number too long"); }
 
-[-+:=~$/]      { yylval->str= 0; return yytext[0]; }
+[-+:=~/]       { record_yylval.name= 0; return yytext[0]; }
 
-\#.*\n|\       { yylval->str= 0; return NL; }
+\#.*\n|\n      { record_yylval.name= 0; return NL; }
 
 [ \t]          { }
 
-.              { badrecord("lexically invalid input"); }
+.              { record_yyerror("lexically invalid input"); }
index 3f8f76971550d5891f3634908ff25b61e4d272a6..5ba3d1ce6bf4ba52c5f73f492092048925971955 100644 (file)
@@ -1,55 +1,60 @@
 /* -*- fundamental -*- */
 
 %{
-#include "realtime.h"
+#include "record.h"
+#include "record-l.h"
 %}
 
 %union {
-  char *name;
+  const char *name;
   Train *train;
   Segment *seg;
   int num;
 }
 
 %token <name>  TRAIN  SEG IS AT HAS STEP END  IDENT
-%token <name>  MAXTRAINS NL
+%token <name>  NL
 %token <num>   NUM
 
 %type <name>   ident
 %type <train>  train
-%type <segment>        seg
-%type <num>    sign
+%type <seg>    seg
+%type <num>    backwards
 
 %defines
+%error-verbose
+%name-prefix="record_yy"
 
 %%
 
 file:          end
-       |       line NL file
+       |       line NL { record_tempzone_clear(); } file
 
 line:          /* empty */
-       |       MAXTRAINS NUM
-                { record_max_trains($2); }
-       |       TRAIN train AT sign SEG ':' NUM '+' '-' NUM
-                { record_train_at($2,$4,$5,$7,$10); }
        |       TRAIN train IS NUM NUM '+' NUM '+' NUM
-                { record_train_is($2,$4,$5,$7,$9); }
+       {         if ($2) record_train_is($2,$4,$5,$7,$9);
+       }
+       |       TRAIN train AT backwards seg ':' NUM '+' '-' NUM
+       {         if ($2) record_train_at($2,$4,$5,$7,$10);
+       }
        |       TRAIN train STEP NUM '=' NUM NUM '/' NUM
-                { record_train_step($2,$4,$6,$7,$9); }
-       |       SEG seg HAS sign train
-                { record_seg_has($2,$4,$5); }
-       |       SEG seg HAS '$'
-                { record_seg_has($2,0,0); }
-       |       SEG seg AT NUM
-                { record_seg_at($2,$4); }
-
-sign:          /* empty */ { return 1; }
-       |       '-' { return -1; }
+       {         if (!trains) record_train_step_count();
+                 else if ($2) record_train_step($2,$4,$6,$7,$9);
+       }
+       |       SEG seg HAS backwards train
+       {         if ($2 && $5) record_seg_has($2,$4,$5);
+       }
+       |       SEG seg AT ident
+       {         if ($2) record_seg_at($2,$4);
+       }
+
+backwards:     /* empty */ { return 0; }
+       |       '-' { return 1; }
 
 ident:         IDENT | TRAIN | SEG | IS | AT | STEP | END
 
-seg:           ident { $$= pname2seg($1); }
-train:         ident { $$= pname2train($1); }
+seg:           ident { $$= record_pname2seg($1); }
+train:         ident { $$= record_pname2train($1); }
 
 end:           END NL
 
index 429cee20069e02a64cdc644fb53feef1e44ccf28..1f357af3ef0b23a8fda963faac07bb91239bb3f0 100644 (file)
  *  seg <segpn> at <movposcomb>
  */
 
+#include <sys/mman.h>
+
+#include "record.h"
+#include "record-l.h"
+
+/*---------- input and error handling ----------*/
+
+static const char *filename;
+
+void record_yyerror(const char *m) {
+  die("config: %s:%d: %s\n", filename, record_yylineno, m);
+}
+
+/*---------- pname lookup (also handles train counting) ----------*/
+
+static char **train_pnames;
+
+Train *record_pname2train(const char *pname) {
+  int tran;
+  char **trap;
+  
+  for (tran=0, trap=train_pnames; tran<n_trains; tran++,trap++) {
+    if (!strcmp(*trap, pname)) goto found;
+  }
+  if (trains) record_yyerror("number of trains changed between passes!");
+  tran= n_trains++;
+  train_pnames= mrealloc(train_pnames, sizeof(*train_pnames)*n_trains);
+  train_pnames[tran]= mstrdup(pname);
+
+found:
+  if (!trains) return 0;
+  return trains + tran;
+}
+
+Segment *record_pname2seg(const char *pname) {
+  int i;
+  const SegmentInfo *segi;
+  
+  for (i=0, segi=info_segments;
+       i<NUM_SEGMENTS;
+       i++, segi++)
+    if (!strcmp(segi->pname, pname))
+      return segments + i;
+  
+  return 0; /* silently discard data for segments no longer in the layout */
+}
+
+/*---------- zone allocator for strings ----------*/
+
+typedef struct TempZoneBlock TempZoneBlock;
+struct TempZoneBlock {
+  TempZoneBlock *next; /* for deallocation */
+  char buf[1];
+};
+
+static TempZoneBlock *tempzones_head;
+static char *tempzone_ptr;
+static int tempzone_remain, tempzone_head_len;
+
+char *record_tempzone_strdup(const char *s) {
+  int l;
+  char *r;
+  
+  l= strlen(s) + 1;
+  if (l > tempzone_remain) {
+    TempZoneBlock *new;
+    assert(l < INT_MAX/20);
+    tempzone_head_len= tempzone_remain= l*10 + 65536;
+    new= mmalloc(sizeof(new) + tempzone_remain);
+    tempzone_ptr= (char*)new + sizeof(new);
+    new->next= tempzones_head;
+    tempzones_head= new;
+  }
+  r= tempzone_ptr;
+  tempzone_remain -= l;
+  tempzone_ptr += l;
+  memcpy(r,s,l);
+  return r;
+}
+
+void record_tempzone_clear(void) {
+  TempZoneBlock *clear, *clear_next;
+  if (!tempzones_head) return;
+
+  clear= tempzones_head->next;
+  while (clear) { clear_next= clear->next; free(clear); clear= clear_next; }
+  tempzones_head->next= 0;
+  tempzone_remain= tempzone_head_len;
+  tempzone_ptr= tempzones_head->buf;
+}
+
+/*---------- semantic actions ----------*/
+/*
+ * These are all called only during the second pass, when trains is non-0.
+ * Also, all Train* and Segment* arguments are known to be non-0.
+ */
+
+void record_train_is(Train *tra, int addr, int head, int det, int tail) {
+  tra->addr= addr;
+  tra->head= head;
+  tra->detectable= det;
+  tra->tail= tail;
+}
+
+void record_train_at(Train *tra, int backw, Segment *seg, int maxi, int unc) {
+  tra->foredetect= seg;
+  tra->maxinto= maxi;
+  tra->uncertainty= unc;
+  tra->backwards= backw;
+}
+  
+void record_seg_has(Segment *seg, int backw, Train *tra) {
+  seg->owner= tra;
+  seg->tr_backwards= backw;
+}
+
+void record_seg_at(Segment *seg, const char *movposcombpname) {
+  const SegPosCombInfo *spci;
+  int i;
+  
+  for (i=0, spci=seg->i->poscombs;
+       i<seg->i->n_poscombs;
+       i++, spci++)
+    if (!strcmp(spci->pname, movposcombpname))
+      goto found;
+  return;
+  
+found:
+  seg->movposcomb= i;
+}
+
+/*---------- speed curves ----------*/
+
+static SpeedCurveEntry *curvebuf;
+static int curvebufsz, curvebufused;
+
+void record_train_step_count(void) {
+  curvebufsz++;
+}
+
+void record_train_step(Train *tra, int step, int speed, int upw, int downw) {
+  Train *other;
+  SpeedCurveEntry *new;
+  int i;
+  
+  if (curvebufused >= curvebufsz) record_yyerror("more speed points on 2nd pass!");
+
+  if (!tra->accel.curve) {
+    tra->accel.curve= curvebuf + curvebufused;
+  }
+
+  /* Make room for an extra speed step point for this train,
+   * by moving all of the other trains up.  First move the data: */
+  memmove(tra->accel.curve + tra->accel.curvesz + 1,
+         tra->accel.curve + tra->accel.curvesz,
+         (char*)(curvebuf + curvebufused)
+         - (char*)(tra->accel.curve + tra->accel.curvesz));
+  /* Then adjust everyone's pointers: */
+  for (i=0, other=trains;
+       i<n_trains;
+       i++, other++)
+    if (other != tra && other->accel.curve &&
+       other->accel.curve >= tra->accel.curve)
+      other->accel.curve++;
+  /* ... that whole thing is O(n^2) if the speed points aren't sorted
+   * by train; we hope they are, in which case we are always adding
+   * to the last train in the list and there is then no data to copy,
+   * which makes it O(n*t) where n is the number of speed points and
+   * t is the number of trains.  If we cared we could optimise away
+   * the loop in the common case where this train is right at the end
+   * but a special case seems like asking for a bug when we do have
+   * out of order speed points. */
+
+  new= &tra->accel.curve[tra->accel.curvesz++];
+  curvebufsz++;
+
+  new->step= step;
+  new->speed= speed;
+  new->upwait= upw;
+  new->downwait= downw;
+}
+
+static int speedcurveentry_compare(const void *av, const void *bv) {
+  const SpeedCurveEntry *a= av, *b= bv;
+  if (a->step == b->step)
+    record_yyerror("multiple speed curve points at same step");
+  return a->step - b->step;
+}
+
+static void sort_curves(void) {
+  int i;
+  Train *tra;
+  
+  for (i=0, tra=trains;
+       i<n_trains;
+       i++, tra++) {
+    if (tra->accel.curve) {
+      if (tra->accel.curvesz < 2)
+       die("config: speed curve too short for %s", tra->pname);
+      qsort(tra->accel.curve, tra->accel.curvesz,
+           sizeof(*tra->accel.curve), speedcurveentry_compare);
+      if (tra->accel.curve[0].step || tra->accel.curve[0].speed)
+       die("config: speed curve missing zero point for %s", tra->pname);
+    }
+  }
+}
+
+/*---------- entrypoint from main, and its subroutines ----------*/
+
+static void alloc(void) {
+  Train *tra; Segment *seg; const SegmentInfo *segi;
+  char **trap;
+  int i;
+  
+  segments= mmap(0, sizeof(*segments)*NUM_SEGMENTS + sizeof(*trains)*n_trains,
+                PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1,0);
+  if (!segments) diee("mmap for shared region");
+
+  for (i=0, seg=segments, segi=info_segments;
+       i<NUM_SEGMENTS;
+       i++, seg++, segi++) {
+    seg->movposcomb= -1;
+    seg->i= segi;
+  }
+
+  trains= (void*)(segments + NUM_SEGMENTS);
+  for (i=0, tra=trains, trap=train_pnames;
+       i<n_trains;
+       i++, tra++, trap++) {
+    tra->pname= *trap;
+    tra->addr= -1;
+    tra->head= -1;
+  }
+
+  curvebuf= mmalloc(sizeof(*curvebuf) * curvebufsz);
+}
+
+static void parse_pass(const char **argv) {
+  FILE *f;
+  
+  while ((filename= *argv++)) {
+    f= fopen(filename,"r");
+    if (!f) diee("config: cannot open input file: %s", filename);
+    record_yyrestart(f);
+    record_yyparse();
+  }
+}
+
+void records_parse(const char **argv) {
+  parse_pass(argv); /* trains==0: counts trains and curve points. */
+  alloc();
+  parse_pass(argv); /* trains!=0: populates data area */
+  record_tempzone_clear();
+  sort_curves();
+}
diff --git a/hostside/record.h b/hostside/record.h
new file mode 100644 (file)
index 0000000..366bd29
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ */
+
+#ifndef RECORD_H
+#define RECORD_H
+
+#include "realtime.h"
+#include "record-y.h"
+
+void record_train_at(Train *tra, int backw, Segment *seg, int maxi, int unc);
+void record_train_is(Train *tra, int addr, int head, int det, int tail);
+void record_train_step(Train *tra, int step, int speed, int upw, int downw);
+void record_train_step_count(void);
+void record_seg_has(Segment *seg, int backw, Train *tra);
+void record_seg_at(Segment *seg, const char *movposcomb_pname);
+
+Train *record_pname2train(const char *pname);
+Segment *record_pname2seg(const char *pname);
+char *record_tempzone_strdup(const char *s);
+void record_yyerror(const char *m);
+void record_tempzone_clear(void);
+
+int record_yyparse(void);
+int record_yylex(void);
+extern int record_yylineno;
+
+#endif /*RECORD_H*/
diff --git a/hostside/rtmacros.h b/hostside/rtmacros.h
deleted file mode 100644 (file)
index 45d88be..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * macros which help some files in the realtime daemon
- */
-
-#ifndef RTMACROS_H
-#define RTMACROS_H
-
-#define S     State *s= &safety_state
-#define TRA   TrainState *tra= &s->trains[tran]
-#define TRAI  const TrainInfo *trai= &info_trains[tran];
-#define SEG   SegmentState *seg= &s->segments[segn]
-
-#endif /*RTMACROS_H*/
index 3e069acf714e757f3612baa70f520c22924560ec..179f0e4bbdaed52285d3a8dceeb42058719d1603 100644 (file)
@@ -8,18 +8,20 @@
 
 #include "realtime.h"
 
-State safety_state;
+int n_trains;
+Train *trains;
+Segment *segments;
 
-static void seg_clear_stale(SegmentState *seg) {
+static void seg_clear_stale(Segment *seg) {
   if (!seg->tr_updated) {
-    seg->owned= 0;
+    seg->owner= 0;
     seg->until_here= seg->until_detect= 0;
   }
 }
 
 typedef struct {
   /* constant inputs */
-  TrainNum tran;
+  Train *tra;
   /* modified in place by lay_train_pass: */
   ErrorCode ec;
   int invert_count[2]; /* count of (switchable) segments,
@@ -27,71 +29,64 @@ typedef struct {
                        *   iff train is backwards (ie, train not inverted)
                        * invert_count[1]: train is inverted
                        * set to -1 if any unswitchable is the other way */
-  SegmentNum invert_forcer; /* the unswitchable which forces */
+  Segment *invert_forcer; /* the unswitchable which forces */
 } LayTrainState;
 
 static void lay_train_pass(LayTrainState *l,
                           TrackLocation tloc, long advance,
                           long speed, unsigned backwards,
                           unsigned check_clash) {
-  S;
-  SegmentNum segn;
-  SegmentState *seg;
-  const SegmentInfo *segi;
+  Segment *seg;
   long overall, remain, dist_until, time_until;
   int *invert_likehere, train_inverted_here;
-  TrainState *tra= &s->trains[l->tran];
+  Train *tra= l->tra;
 
   if (l->ec) return;
 
-  segn= tra->foredetect;
-  seg= &s->segments[segn];
+  seg= tra->foredetect;
 
   remain= overall= advance + speed * SPEED_CLEAR_MULT;
 
   for (;;) {
-    segn= tloc.segn;
-    seg= &s->segments[segn];
-    segi= &info_segments[segn];
+    seg= tloc.seg;
 
     if (check_clash) {
       if (seg->tr_updated) {
-       l->ec= safety_problem(l->tran, tloc.segn, "self-collision");
+       l->ec= safety_problem(l->tra, tloc.seg, "self-collision");
        return;
       }
-      if (seg->owned) {
-       if (seg->owner != l->tran) {
-         l->ec= safety_problem(l->tran, tloc.segn, "collision with %s",
-                               info_trains[seg->owner].pname);
+      if (seg->owner) {
+       if (seg->owner != l->tra) {
+         l->ec= safety_problem(l->tra, tloc.seg, "collision with %s",
+                               seg->owner->pname);
          return;
        }
        seg_clear_stale(seg);
       }
     }
     
-    seg->owned= 1;
+    seg->owner= l->tra;
     seg->tr_backwards= tloc.backwards ^ backwards;
     seg->tr_updated= 1;
-    seg->owner= l->tran;
 
     train_inverted_here= seg->seg_inverted ^ seg->tr_backwards;
     invert_likehere= &l->invert_count[train_inverted_here];
 
-    if (segi->invertible) {
+    if (seg->i->invertible) {
       if (*invert_likehere >= 0)
        (*invert_likehere)++;
     } else {
       if (*invert_likehere < 0) {
-       l->ec= safety_problem(l->tran, NOTA(Segment), "train requires"
+       l->ec= safety_problem(l->tra,0, "train requires"
                              " noninvertible segments with opposite polarity:"
-                             " @%s, @%s", segi->pname,
-                             info_segments[l->invert_forcer].pname);
+                             " @%s, @%s", seg->i->pname,
+                             l->invert_forcer->i->pname);
        return;
       }
       assert(!seg->seg_inverted);
       (*invert_likehere)++;
       l->invert_count[!train_inverted_here]= -1;
-      l->invert_forcer= segn;
+      l->invert_forcer= seg;
     }
 
     dist_until= (overall - remain) - advance;
@@ -104,9 +99,8 @@ static void lay_train_pass(LayTrainState *l,
 }
 
 static void lay_train_inversions(LayTrainState *l) {
-  S;
   SegmentNum segn;
-  SegmentState *seg;
+  Segment *seg;
   const SegmentInfo *segi;
   int train_be_inverted, seg_be_inverted;
  
@@ -117,28 +111,27 @@ static void lay_train_inversions(LayTrainState *l) {
 
   actual_inversions_start();
   
-  for (segn=0, seg=s->segments, segi=info_segments;
+  for (segn=0, seg=segments, segi=info_segments;
        segn <= NUM_SEGMENTS;
-       segn++, seg++) {
+       segn++, seg++, segi++) {
     if (!seg->tr_updated) continue;
-    assert(seg->owner == l->tran);
+    assert(seg->owner == l->tra);
     seg_be_inverted= train_be_inverted ^ seg->tr_backwards;
     assert(!(seg_be_inverted && !segi->invertible));
     seg->seg_inverted= seg_be_inverted;
-    actual_inversions_segment(segn);
+    actual_inversions_segment(seg);
   }
   actual_inversions_done();
 }
 
 static void lay_train_done(LayTrainState *l) {
-  S;
   SegmentNum segn;
-  SegmentState *seg;
+  Segment *seg;
   
-  for (segn=0, seg=s->segments;
+  for (segn=0, seg=segments;
        segn <= NUM_SEGMENTS;
        segn++, seg++) {
-    if (seg->owner == l->tran) {
+    if (seg->owner == l->tra) {
       if (!seg->tr_updated) seg_clear_stale(seg);
       seg->tr_updated= 0;
     }
@@ -147,22 +140,19 @@ static void lay_train_done(LayTrainState *l) {
   }
 }
 
-static ErrorCode lay_train(TrainNum tran, long added_slop) {
-  S; TRA; TRAI;
-  SegmentNum segn;
-  SegmentState *seg;
+static ErrorCode lay_train(Train *tra, long added_slop) {
+  Segment *seg;
   TrackLocation tloc;
   long head, headslop, tail, taildet;
   LayTrainState l;
 
-  segn= tra->foredetect;
-  seg= &s->segments[segn];
+  seg= tra->foredetect;
 
-  tloc.segn= segn;
+  tloc.seg= seg;
   tloc.into= tra->maxinto;
   tloc.backwards= seg->tr_backwards ^ tra->backwards;
 
-  l.tran= tran;
+  l.tra= tra;
   l.ec= 0;
   l.invert_count[0]= l.invert_count[1]= 0;
   
@@ -198,30 +188,28 @@ static ErrorCode lay_train(TrainNum tran, long added_slop) {
   return l.ec;
 }
 
-void safety_notify_detection(SegmentNum segn) {
-  S; SEG;
-  TrainNum tran= seg->owner;
-  TRA;
+void safety_notify_detection(Segment *seg) {
+  Train *tra= seg->owner;
   ErrorCode ec;
   TrackLocation tloc;
 
-  if (!seg->owned)
-    safety_panic(NOTA(Train), segn, "unexpected detection");
+  if (!seg->owner)
+    safety_panic(0,seg, "unexpected detection");
 
   if (!seg->until_detect)
     return;
 
-  tloc.segn= segn;
+  tloc.seg= seg;
   tloc.into= 0;
   tloc.backwards= seg->tr_backwards;
 
-  tra->foredetect= segn;
+  tra->foredetect= seg;
   tra->maxinto= trackloc_remaininseg(&tloc);
 
   if (seg->cm_autostop) {
     seg->cm_autostop= 0;
     if (!tra->estopping) {
-      speedmanager_autostop(tran);
+      speedmanager_autostop(tra);
       if (!tra->speed && tra->maxinto > AUTOSTOP_UNCERTAINTY)
        /* At some point we may need to allow more slop when the
         * next segment is points than when this is the last segment
@@ -232,51 +220,51 @@ void safety_notify_detection(SegmentNum segn) {
   tra->uncertainty= tra->maxinto;
 
   if (!tra->estopping) {
-    ec= lay_train(tran, 0);
+    ec= lay_train(tra, 0);
     if (ec) {
-      logmsg(ec, tran, segn, "emergency stop");
-      safety_emergencystop(tran);
+      logmsg(ec,tra,seg->i, "emergency stop");
+      safety_emergencystop(tra);
     }
   }
 }
 
-void safety_emergencystop(TrainNum tran) {
-  S; TRA;
+void safety_emergencystop(Train *tra) {
   ErrorCode ec;
 
   if (tra->estopping) return;
 
-  ec= lay_train(tran, ESTOP_UNCERTAINTY);
-  if (ec) safety_panic(tran, NOTA(Segment), "emergency stop forbidden!");
-  speedmanager_emergencystop(tran);
+  ec= lay_train(tra, ESTOP_UNCERTAINTY);
+  if (ec) safety_panic(tra,0, "emergency stop forbidden!");
+  speedmanager_emergencystop(tra);
 }
 
-ErrorCode safety_requestspeed(TrainNum tran, long newspeed) {
-  S; TRA;
+ErrorCode safety_requestspeed(Train *tra, long newspeed) {
   long oldspeed;
   ErrorCode ec;
 
   oldspeed= tra->speed;
   tra->speed= newspeed;
 
-  ec= lay_train(tran, 0);
+  ec= lay_train(tra, 0);
 
   if (ec) {
+    ErrorCode revert_ec;
+    
     if (oldspeed && oldspeed < newspeed) {
-      logmsg(ec, tran, NOTA(Segment), "countermanded acceleration"
+      logmsg(ec,tra,0, "countermanded acceleration"
             " from %ld to %ld", oldspeed, newspeed);
     } else if (oldspeed) {
-      safety_panic(tran, NOTA(Segment), "deceleration forbidden!"
+      safety_panic(tra,0, "deceleration forbidden!"
                   " (from %ld to %ld", oldspeed, newspeed);
     } else {
-      logmsg(ec, tran, NOTA(Segment), "countermanded motion start");
+      logmsg(ec,tra,0, "countermanded motion start");
     }
     oprintf(UPO, "countermanded %s %ld %ld\n",
-           info_trains[tran].pname, oldspeed, newspeed);
-    ec= lay_train(tran, 0);
-    if (ec)
-      safety_panic(tran, NOTA(Segment), "countermanding"
+           tra->pname, oldspeed, newspeed);
+    revert_ec= lay_train(tra, 0);
+    if (revert_ec)
+      safety_panic(tra,0, "countermanding"
                   " speed change insufficient!");
-    return;
   }
+  return ec;
 }
index 2cb34c3adaa1c1e2894fe595f3019cfed5943dc4..d7411315e8d4dc5920e4d3ecddbd6d2bfe95c4a0 100644 (file)
@@ -27,65 +27,73 @@ typedef short TimeInterval; /*ms*/
 /*========== state of the layout ==========*/
 
 typedef struct {
-  fixme init location;
-  fixme call init_fixed_train;
+  int step;
+  long speed;
+  TimeInterval upwait, downwait; /* between this insn and next one */
+} SpeedCurveEntry;
+
+struct Train {
+  /* Configuration (excluding speed curve): */
+  char *pname;
   int addr;
   Distance head, detectable, tail;
+
+  /* Location: */
   Segment *foredetect;     /* train's detectable part is at most maxinto   */
   Distance maxinto, uncertainty;   /*   into foredetect but train may be   */
   unsigned                         /*   uncertainty less far advanced      */
     backwards:1, /* train is moving backwards wrt its own front and back */
+
+  /* Speed: */
     estopping:1; /* set and cleared by speed.c */
   Speed speed; /* when accelerating/decelerating, is maximum at this moment */
-  
+
   struct {
-    const SpeedCurveEntry *curve;
-    int curvesz;
     int target; /* index into curve */
     int commanded; /* when ac-/decel, eq last value xmitted */
     TimeoutEvent more; 
     RetransmitUrgentNode rn;
+
+    /* Configuration for acceleration: */
+    SpeedCurveEntry *curve;
+    int curvesz;
   } accel;
-} TrainState;
+};
 
-typedef struct {
+struct Segment {
+  Train *owner;                                  /* or 0 */
   unsigned
-    owned:1, /* this track segment is reserved for a train */
     tr_backwards:1, /* train's motion is (would be) backwards wrt track */
     movfeat_moving:1, /* feature(s) have been told to change to movposcomb */
     cm_autostop:1, /* train should stop on detection */
     seg_inverted:1, /* polarity is inverted */
     tr_updated:1; /* for use by safety.c:lay_train etc.; otherwise 0 */
-  TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but */
-    until_detect;          /* ) 0 if already */  /* )  only meaningful */
-  TrainNum owner;                                /* )  iff owned       */
+  TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but      */
+    until_detect;          /* ) 0 if already */  /* )  meaningful iff owner */
   MovPosComb movposcomb;
-  /*polarity?*/
-} SegmentState;
-
-typedef struct {
-  TrainState trains[NUM_TRAINS];
-  SegmentState segments[NUM_SEGMENTS];
-} State;
+  const SegmentInfo *i;
+};
 
-extern State safety_state;
+extern int n_trains;
+extern Train *trains;
+extern Segment *segments;
 
 /*========== embed.c ==========*/
 /* surrounds the algorithms and machinery in a program: logging, error
  * handling, arg parsing, etc.
  */
 
-void vlogmsg(ErrorCode ec, TrainNum tran, SegmentNum segn,
+void vlogmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
             const char *fmt, va_list al) __attribute__((format(printf,4,0)));
-void logmsg(ErrorCode ec, TrainNum tran, SegmentNum segn,
+void logmsg(ErrorCode ec, Train *tra, const SegmentInfo *segi,
            const char *fmt, ...) __attribute__((format(printf,4,5)));
 
-void safety_vpanic(TrainNum tran, SegmentNum segn, const char *fmt, va_list al)
+void safety_vpanic(Train *tra, Segment *seg, const char *fmt, va_list al)
      __attribute__((format(printf,3,0),noreturn));
-void safety_panic(TrainNum tran, SegmentNum segn, const char *fmt,...)
+void safety_panic(Train *tra, Segment *seg, const char *fmt,...)
      __attribute__((format(printf,3,4),noreturn));
 
-ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt, ...)
+ErrorCode safety_problem(Train *tra, Segment *seg, const char *fmt, ...)
      __attribute__((format(printf,3,4)));
      /* simple wrapper around vlogmsg; implies and returns EC_Safety */
 
@@ -96,28 +104,30 @@ ErrorCode safety_problem(TrainNum tran, SegmentNum segn, const char *fmt, ...)
  * etc.).
  */
 
-void safety_emergencystop(TrainNum);
+void safety_emergencystop(Train*);
   /* Callable directly in response to application command. */
 
-ErrorCode safety_requestspeed(TrainNum tran, long newspeed);
+ErrorCode safety_requestspeed(Train* tra, long newspeed);
   /* To be called only by the speed manager, thus indirectly from
    * user request.  Any error will have been logged.  On success,
    * ->speed has been updated.  Speed manager is responsible for
    * calling actual_setspeed.
    */
 
-void safety_setdirection(TrainNum tran, int sense_fixme_define_this_properly);
+void safety_setdirection(Train* tra, int sense_fixme_define_this_properly);
 
-void safety_notify_detection(SegmentNum segn);
+void safety_notify_detection(Segment *seg);
   /* Called by startup.c when new train detection occurs in state Run. */
 
 /*========== speedmgr.c ==========*/
 
-void speedmanager_speedchange_request(TrainNum tran, Speed speed);
-  /* Callable directly in response to application command. */
+void speedmanager_speedchange_request(Train *tra, long speed);
+  /* Callable directly in response to application command.
+   * speed may be LONG_MAX to mean maximum permitted.
+   */
 
-void speedmanager_emergencystop(TrainNum tran);
-void speedmanager_autostop(TrainNum tran);
+void speedmanager_emergencystop(Train *tra);
+void speedmanager_autostop(Train *tra);
   /* These are responsible for calling actual_setspeed.
    *
    * After speedmanager_autostop, ->speed will have been updated to a
@@ -125,6 +135,8 @@ void speedmanager_autostop(TrainNum tran);
    * been instructed to stop right now.
    */
 
+void speedmanager_reset_train(Train *tra);
+
 /*========== actual.c ==========*/
 /* actual.c should only be called from safety.c.
  * It is responsible for communicating with the PICs, including
@@ -135,11 +147,11 @@ void speedmanager_autostop(TrainNum tran);
  * will then call an actual_... function to notify the change.
  */
 
-void actual_setspeed(TrainNum tran);
-void actual_emergencystop(TrainNum tran);
+void actual_setspeed(Train *tra);
+void actual_emergencystop(Train *tra);
 
 void actual_inversions_start(void);
-void actual_inversions_segment(SegmentNum);
+void actual_inversions_segment(Segment *seg);
 void actual_inversions_done(void);
   /* safety.c will call these in this order: first start, then segment
    * for 0 or more segments (whose s.segments[segn].seg_inverted may
@@ -156,7 +168,7 @@ void actual_inversions_done(void);
 
 typedef struct TrackLocation TrackLocation;
 struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */
-  SegmentNum segn; /* current segment */
+  Segment *seg; /* current segment */
   long into; /* distance from start of segment */
   unsigned backwards:1; /* if 1, into is positive and measured from end */
 };
@@ -193,8 +205,9 @@ const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
 
 #define CLEAR_FORESIGHT_TIME 500 /*ms*/
 #define AUTOSTOP_MAXSPEED ((50 * SPEED_UNIT)/1000) /* 50 mm/s */
-#define AUTOSTOP_UNCERTAINTY 20
-#define ESTOP_UNCERTAINTY 300
+#define AUTOSTOP_UNCERTAINTY 20  /*mm*/
+#define ESTOP_UNCERTAINTY 300  /*mm*/
+#define ESTOP_DEADTIME    2000 /*ms*/
 
 #define SPEED_CLEAR_MULT SPEED_CALC_DIST(1,CLEAR_FORESIGHT_TIME,UP)
 
index dea39f02eccecd347f128536636e837077fd6c08..8f5a88de91d01d148e3bed0828e48d7027478ccb 100644 (file)
@@ -4,15 +4,14 @@
  */
 
 #include "realtime.h"
+#include "nmra.h"
 
-typedef struct {
-  SpeedStep step;
-  Speed speed;
-  TimeInterval upwait, downwait; /* between this insn and next one */
-} SpeedCurveEntry;
+static void changereq_internal(Train *tra, int newcommanded, int inautostop);
+static void accel_more(TimeoutEvent *toev);
 
-void reset_train(Train *tra) {
+void speedmanager_reset_train(Train *tra) {
   Nmra n;
+  ErrorCode ec;
   
   tra->estopping= 0;
   tra->speed= 0;
@@ -20,34 +19,22 @@ void reset_train(Train *tra) {
   toev_init(&tra->accel.more);
   enco_nmra_speed126(&n, tra->addr, 0, tra->backwards);
   retransmit_urgent_queue_relaxed(&tra->accel.rn, &n);
-  ec= safety_requestspeed(tran, 0);
+  ec= safety_requestspeed(tra, 0);
   if (ec)
     safety_panic(tra, 0, "position reset impossible!");
 }
 
-void init_fixed_train(Train *tra, const TrainInfo *trai) {
-  /* does not init location (ie foredetect, maxinto, uncertainty, backwards);
-   * at least backwards must already be valid */
-  tra->addr= trai->addr;
-  tra->head= trai->head;
-  tra->detectable= trai->detectable;
-  tra->tail= trai->tail;
-  tra->accel.curve= trai->curve;
-  tra->accel.curvesz= trai->curvesz;
-  reset_train(tra);
-}
-
-void xmit_speed(Train *tra) {
+static void xmit_speed(Train *tra) {
   Nmra n;
   enco_nmra_speed126(&n, tra->addr,
-                    tra->curve[tra->accel.commanded].step,
+                    tra->accel.curve[tra->accel.commanded].step,
                     tra->backwards);
   retransmit_urgent_requeue(&tra->accel.rn, &n);
 }
 
-void speedmanager_autostop(TrainNum tran) {
+void speedmanager_autostop(Train *tra) {
   if (tra->speed < AUTOSTOP_MAXSPEED) {
-    toev_stop(&tra->speedadjust);
+    toev_stop(&tra->accel.more);
     tra->accel.commanded= tra->accel.target= tra->speed= 0;
     xmit_speed(tra);
   } else {
@@ -58,14 +45,14 @@ void speedmanager_autostop(TrainNum tran) {
 static void estop_done(TimeoutEvent *toev) {
   Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
   retransmit_urgent_cancel(&tra->accel.rn);
-  reset_train(tra);
+  speedmanager_reset_train(tra);
 }
  
 void speedmanager_emergencystop(Train *tra) {
   Nmra n;
   tra->estopping= 1;
-  toev_stop(&tra->speedadjust);
-  enco_nmra_estop(&n, tra->addr);
+  toev_stop(&tra->accel.more);
+  enco_nmra_estop1(&n, tra->addr);
   retransmit_urgent_requeue(&tra->accel.rn, &n);
 
   toev_stop(&tra->accel.more);
@@ -74,29 +61,23 @@ void speedmanager_emergencystop(Train *tra) {
   toev_start(&tra->accel.more);
 }
 
-static void accel_more(TimeoutEvent *toev) {
-  Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
-  adjust_next(tra, 0);
-}
-
 static void adjust_next(Train *tra, int inautostop) {
-  int newold, xmit;
   long newspeed;
 
   if (tra->accel.target > tra->accel.commanded) {
     tra->accel.commanded++;
-    tra->accel.more.duration= tra->curve[tra->accel.commanded].upwait;
-    newspeed= tra->curve[tra->accel.commanded].speed;
+    tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].upwait;
+    newspeed= tra->accel.curve[tra->accel.commanded].speed;
   } else if (tra->accel.target < tra->accel.commanded) {
-    newspeed= tra->curve[tra->accel.commanded].speed;
+    newspeed= tra->accel.curve[tra->accel.commanded].speed;
     tra->accel.commanded--;
-    tra->accel.more.duration= tra->curve[tra->accel.commanded].downwait;
+    tra->accel.more.duration= tra->accel.curve[tra->accel.commanded].downwait;
   } else {
     return;
   }
 
   if (!inautostop) {
-    ec= safety_requestspeed(tra, newspeed);
+    ErrorCode ec= safety_requestspeed(tra, newspeed);
     if (ec) {
       assert(newspeed > tra->speed);
       assert(tra->accel.target >= tra->accel.commanded);
@@ -114,10 +95,15 @@ static void adjust_next(Train *tra, int inautostop) {
   xmit_speed(tra);
 }
 
-int changereq_internal(Train *tra, int newcommanded, int inautostop) {
+static void accel_more(TimeoutEvent *toev) {
+  Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
+  adjust_next(tra, 0);
+}
+
+static void changereq_internal(Train *tra, int newcommanded, int inautostop) {
   int reverse, newold;
 
-  if (!speedadjust->running) {
+  if (!tra->accel.more.running) {
     assert(tra->accel.commanded == tra->accel.target);
     adjust_next(tra, 0);
   } else {
@@ -134,24 +120,24 @@ int changereq_internal(Train *tra, int newcommanded, int inautostop) {
 
     if (reverse) {
       /* switch from accel to decel or vice versa */
-      toev_stop(&tra->speedadjust);
+      toev_stop(&tra->accel.more);
       tra->accel.commanded= newold;
       adjust_next(tra, 0);
     }
   }
 }
 
-void speedmanager_speedchange_request(TrainNum tran, Speed speed) {
+void speedmanager_speedchange_request(Train *tra, long speed) {
   changereq_internal(tra, speed, 0);
-  int a, b, found;
-  const SpeedCurveEntry *curve;
+  int a, b, try, found;
+  const SpeedCurveEntry *curve= tra->accel.curve;
 
   if (tra->estopping) {
     logmsg(EC_Invalid, tra, 0, "speed request ignored during emergency stop");
     return;
   }
   
-  for (a=0, b=trai->nsteps;
+  for (a=0, b=tra->accel.curvesz;
        a < b;
        ) {
     try= (a + b) >> 2;
@@ -168,10 +154,10 @@ void speedmanager_speedchange_request(TrainNum tran, Speed speed) {
    */
   found= a>1 ? a-1 : speed ? 1 : 0;
 
-  if (curve[found].speed < speed && !NOTA(speed))
-    logmsg(EC_Invalid, tran, NOTA(SegmentNum),
-          "requested speed %l excessive; capping at %l",
-          (long)speed, (long)curve[found].speed);
+  if (curve[found].speed < speed && speed != INT_MAX)
+    logmsg(EC_Invalid, tra,0,
+          "requested speed %ld excessive; capping at %ld",
+          speed, curve[found].speed);
 
   changereq_internal(tra, found, 0);
 }
index 9f8a0fe23a1fb4897d2bd77402ebbaa81a18f976..a580280009072271cef3056428a99a1c6ca1db89 100644 (file)
@@ -192,7 +192,7 @@ void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int segn) {
            info_segments[segn].pname);
     return;
   }
-  safety_notify_detection(segn);
+  safety_notify_detection(&segments[segn]);
 }
 
 /*---------- fixme move these to where they want to go ----------*/
index 4a1771448a2e110d3d3ba76251a70ad5db2eb09a..0818c6b751b976edf2cb54bf83c608539d505c27 100644 (file)
@@ -3,15 +3,13 @@
 
 #include <assert.h>
 
-#include "safety.h"
+#include "realtime.h"
 
 const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc) {
-  State *s= &safety_state;
-  SegmentState *seg= &s->segments[tloc->segn];
-  const SegmentInfo *segi= &info_segments[tloc->segn];
+  Segment *seg= tloc->seg;
 
-  assert(seg->movposcomb < segi->n_poscombs);
-  return &segi->poscombs[seg->movposcomb];
+  assert(seg->movposcomb < seg->i->n_poscombs);
+  return &seg->i->poscombs[seg->movposcomb];
 }
 
 const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
@@ -44,7 +42,7 @@ void trackloc_further(TrackLocation *tloc, long *remain_io) {
     pci= trackloc_segposcomb(tloc);
     lnki_far= trackloc_segmentlink(tloc, pci, 1);
     *remain_io -= segment_remain;
-    tloc->segn= lnki_far->next;
+    tloc->seg= &segments[lnki_far->next];
     tloc->into= 0;
     tloc->backwards ^= lnki_far->next_backwards;
   }
index 3b5e307dc454a3ab62c1bb851d6b3b9057ac483d..ce4bee93ef3c1162f5ab5b8dd03deeaa1a0cde3c 100644 (file)
@@ -34,6 +34,10 @@ void vdie(const char *fmt, int ev, va_list al) {
   exit(12);
 }
 
+void badusage(const char *why) {
+  fprintf(stderr,"%s: bad usage: %s\n",progname,why); exit(8);
+}
+
 void die(const char *fmt, ...)
   { va_list al; va_start(al,fmt); vdie(fmt,0,al); }
 void diee(const char *fmt, ...)
index c6037ca9f5dd5ef08d15cf7e5e4c4f30a61f9444..0bd5708a755180812c9622da8363c94c90ad8ecb 100755 (executable)
@@ -403,7 +403,6 @@ sub writeout () {
        push @segs, $seg;
     }
     o(sprintf
-      "#define NUM_TRAINS 1000000\n".
       "#define NUM_SEGMENTS %s\n\n".
       "#include \"layout-data.h\"\n\n",
       scalar @segs);
@@ -422,7 +421,7 @@ sub writeout () {
            }
            o("$delim\n");
            o(sprintf "  { %-8s %4d",
-             '"'.$seg.(length $pi ? '/' : '').$pi.'",',
+             '"'.$pi.'",',
              $segr->{Dist}[$comb]);
            for ($end=0; $end<2; $end++) {
                o(", { ");
@@ -470,7 +469,7 @@ sub writeout () {
            $ptv= $segr->{Feats}{$pt};
            next if exists $ptv->{Fixed};
            o("$delim\n");
-           o("  { \"$seg/$pt\", mfk_".lc($ptv->{Kind}).",".
+           o("  { \"$pt\", mfk_".lc($ptv->{Kind}).",".
              " $ptv->{Posns}, $ptv->{Weight}, mfbo_${seg}_$pt }");
            $delim=',';
        }
index 98796c647acbc4c104bc8393b67dece60c8485bd..4bb569a564bcdb8a9742dac8439680f52631f6c7 100644 (file)
 
 /*========== basic types etc. ==========*/
 
-typedef unsigned short TrainNum;
-typedef unsigned short SegmentNum;
-typedef unsigned short MovPosComb;
-typedef unsigned short BoardObject;
-
-typedef unsigned char Small;
-
-typedef short Distance;
-typedef char Speed;
-  /* for units, see safety.h */
+typedef int TrainNum;
+typedef int SegmentNum;
+typedef long MovPosComb;
+typedef long Speed;
+typedef int BoardObject;
+typedef int Small;
+typedef int Distance;
 
 typedef enum {
   mfk_none,
@@ -61,27 +58,18 @@ typedef struct {
   BoardObject sense, invert;
 } SegmentInfo;
 
-typedef struct {
-  Speed maxspeed;
-  Distance tail, detectable, head;
-  const char *pname;
-} TrainInfo;
-
-/* These data arrays have no sentinel members.  Use the info_nfoobars
- * constants.  Alternatively, it is legal to sed out everything from
+/* This data array has no sentinel member.  Use the info_nsegments
+ * constant.  Alternatively, it is legal to sed out everything from
  * <name-of-layout>.layout-data.c from the first #include onwards, and
- * this will give definitions of NUM_SEGMENTS and NUM_TRAINS.
+ * this will give a definition of NUM_SEGMENTS.
  */
 
 extern const SegmentNum info_nsegments;
 extern const SegmentInfo info_segments[];
 
-extern const TrainNum info_nsegments;
-extern const TrainInfo info_trains[];
-
 extern const BoardObject info_maxreverse; /* max. reverse + 1 */
 
-#define NOTA(x) (~(x##Num)0)
-#define SOMEP(x) (!!~(x))
+#define NOTA(x) (-1)
+#define SOMEP(x) ((x) >= 0)
 
 #endif /*LAYOUT_DATA_H*/