RSYNC_RSH=fsh rsync $^ $(BESSAR)
realtime: realtime.o startup.o cdumgr.o safety.o trackloc.o \
- speed.o actual.o retransmit.o persist.o \
+ speed.o actual.o retransmit.o persist.o resolve.o \
cmdinput.o commands.o obc.o eventhelp.o \
record.o record-l.o record-y.o \
utils.o serialio.o parseutils.o auproto-pic.o \
}
void persist_entrails_run_converter(void) {
- Train *tra; int tran;
- Segment *seg; const SegmentInfo *segi; int segn;
+ TRA_IV;
+ SEG_IV;
persist_mapread();
- for (tran=0, tra=trains; tran<n_trains; tran++, tra++) {
+ FOR_TRA {
if (!tra->pname || !tra->foredetect ||
!tra->foredetect->i || !tra->foredetect->i->pname)
continue;
tra->pname, tra->backwards ? "-" : "",
tra->foredetect->i->pname, tra->maxinto, tra->uncertainty);
}
- for (segn=0, seg=segments, segi=info_segments; segn<info_nsegments;
- segn++, seg++, segi++) {
-
+ FOR_SEG {
if (seg->i != segi || !segi->pname ||
!seg->owner || !seg->owner->pname)
continue;
int objnum, suppress=0;
if ((pi->d[0] & 0xf8) == 0x90) {
- SegmentNum segn;
- const SegmentInfo *segi;
+ SEG_IV;
const char *delim;
oprintf(UPO,"picio out polarity <");
- for (segn=0, segi=info_segments, delim="";
- segn < info_nsegments;
- segn++, segi++) {
+ delim="";
+ FOR_SEG {
if (!segi->invertible) continue;
if (!picinsn_polarity_testbit(pi,segi)) continue;
oprintf(UPO,"%s%s", delim, segi->pname);
extern StartupState sta_state;
extern const char *const stastatelist[];
+int resolve_failed(void); /* from resolve.c */
+
/*---------- from/for record.c and persist.c ----------*/
void records_parse(const char **argv);
}
Segment *record_pname2seg(const char *pname) {
- int i;
- const SegmentInfo *segi;
-
- for (i=0, segi=info_segments;
- i<NUM_SEGMENTS;
- i++, segi++)
+ SEG_IV;
+
+ FOR_SEG
if (!strcmp(segi->pname, pname))
- return segments + i;
+ return seg;
return 0; /* silently discard data for segments no longer in the layout */
}
void record_seg_at(Segment *seg, const char *movposcombpname) {
const SegPosCombInfo *spci;
- int i;
+ int poscomb;
- for (i=0, spci=seg->i->poscombs;
- i<seg->i->n_poscombs;
- i++, spci++)
+ for (poscomb=0, spci=seg->i->poscombs;
+ poscomb < seg->i->n_poscombs;
+ poscomb++, spci++)
if (!strcmp(spci->pname, movposcombpname))
goto found;
return;
found:
- seg->movposcomb= i;
+ seg->movposcomb= poscomb;
}
/*---------- speed curves ----------*/
}
static void sort_curves(void) {
- int i;
- Train *tra;
-
- for (i=0, tra=trains;
- i<n_trains;
- i++, tra++) {
+ TRA_IV;
+
+ FOR_TRA {
if (tra->accel.curve) {
if (tra->accel.curvesz < 2)
die("config: speed curve too short for %s", tra->pname);
}
static void alloc(void) {
- Train *tra; Segment *seg; const SegmentInfo *segi;
+ TRA_IV;
+ SEG_IV;
void *mapbase=0;
char **trap;
- int i, phase, offset, datalen=0;
+ int phase, offset, datalen=0;
#define ALLOC(array,count) \
((array)= alloc_some(mapbase,&offset,sizeof(*(array)),(count)))
break;
ALLOC(trains, n_trains);
- for (i=0, tra=trains, trap=train_pnames;
- i<n_trains;
- i++, tra++, trap++) {
+ FOR_TRAIN(tra, trap=train_pnames, trap++) {
char *pname;
ALLOC(pname, strlen(*trap)+1);
if (phase) {
ALLOC(segments, info_nsegments);
if (phase)
- for (i=0, seg=segments, segi=info_segments;
- i<NUM_SEGMENTS;
- i++, seg++, segi++) {
+ FOR_SEG {
seg->owner= 0;
seg->movposcomb= -1;
seg->i= segi;
--- /dev/null
+/*
+ * resolve detected trains into initial state
+ */
+
+#include "realtime.h"
+
+int resolve_failed(void) {
+ return 0;
+}
}
static void lay_train_inversions(LayTrainState *l) {
- SegmentNum segn;
- Segment *seg;
- const SegmentInfo *segi;
+ SEG_IV;
int train_be_inverted, seg_be_inverted;
if (l->ec) return;
assert(l->invert_count[train_be_inverted] >= 0);
actual_inversions_start();
-
- for (segn=0, seg=segments, segi=info_segments;
- segn <= NUM_SEGMENTS;
- segn++, seg++, segi++) {
+
+ FOR_SEG {
if (!seg->tr_updated) continue;
assert(seg->owner == l->tra);
seg_be_inverted= train_be_inverted ^ seg->tr_backwards;
}
static void lay_train_done(LayTrainState *l) {
- SegmentNum segn;
- Segment *seg;
+ SEG_IV;
- for (segn=0, seg=segments;
- segn <= NUM_SEGMENTS;
- segn++, seg++) {
+ FOR_SEG {
if (seg->owner == l->tra) {
if (!seg->tr_updated) seg_clear_stale(seg);
seg->tr_updated= 0;
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 */
+ tr_updated:1, /* for use by safety.c:lay_train etc.; otherwise 0 */
+ 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;
/*========== useful macros and declarations ==========*/
+/*---------- looping over trains and segments ----------*/
+
+#define SEGMENT_ITERVARS(seg) \
+ SegmentNum seg##n; \
+ Segment *seg; \
+ const SegmentInfo *seg##i
+
+#define TRAIN_ITERVARS(tra) \
+ Train *tra; \
+ int tra##n
+
+#define FOR_SEGMENT(seg, initx, stepx) \
+ for (seg##n=0, seg=segments, seg##i=info_segments; \
+ seg##n <= NUM_SEGMENTS; \
+ seg##n++, seg++, seg##i++, stepx)
+
+#define FOR_TRAIN(tra, initx, stepx) \
+ for (tra##n=0, tra=trains; \
+ tra##n < n_trains; \
+ tra##n++, tra++, stepx)
+
+#define SEG_IV SEGMENT_ITERVARS(seg)
+#define FOR_SEG FOR_SEGMENT(seg,(void)0,(void)0)
+
+#define TRA_IV TRAIN_ITERVARS(tra)
+#define FOR_TRA FOR_TRAIN(tra,(void)0,(void)0)
+
/*---------- calculations with fixed point speeds ----------*/
#define DIVIDE_ROUNDING_UP(num,den) (((num) + (den) - 1) / (den))
void sta_startup(void) { sta_goto(Sta_Flush); }
static void sta_goto(StartupState new_state) {
+ SEG_IV;
+
toev_stop(&sta_toev);
sta_toev.callback= timedout_onward;
sta_toev.duration= -1;
case Sta_Ping: break;
case Sta_Fault: break;
case Sta_Settling: enco_pic_off(&piob); break;
- case Sta_Resolving: enco_pic_on(&piob); break;
- case Sta_Run: persist_install(); retransmit_start(); break;
+ case Sta_Resolving:
+ FOR_SEG seg->res_detect= 0;
+ enco_pic_on(&piob);
+ break;
+ case Sta_Run:
+ if (resolve_failed)
+ /* in this case, we get stuck - user has to power cycle the layout */
+ return;
+ persist_install();
+ retransmit_start();
+ break;
}
if (piob.l) serial_transmit(&piob);
{ abort(); }
void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int segn) {
+ Segment *seg;
if (segn >= NUM_SEGMENTS) die("PIC sent detect @#%d out of range",segn);
- if (sta_state < Sta_Run) {
+
+ seg= &segments[segn];
+
+ switch (sta_state) {
+ case Sta_Flush:
+ case Sta_Off:
+ case Sta_Ping:
+ case Sta_Fault:
+ case Sta_Settling:
oprintf(UPO, "warning fixme ignored non-Run detection @%s\n",
info_segments[segn].pname);
- return;
+ break;
+ case Sta_Resolving: seg->res_detect= 1; break;
+ case Sta_Run: safety_notify_detection(seg); break;
}
- safety_notify_detection(&segments[segn]);
}
/*---------- fixme move these to where they want to go ----------*/