PS points:pointslave,points:pointmsg ; Firing point on nonexistent board
PF ::t ; Flash mentions point not on board
PX ; Host sent >2-byte POINT command
-PQ ; POINTED when already charging
PA ; POINTED when already firing
;--------------------
got_pointed @
tst_f_ifnz cducharging
- bra pointed_already_charging
+ return ; presumably we just turned off
bt_f_if0 pointmsg, 7
bra pointed_butnot_firing
goto serial_addbyte
pointed_butnot_firing panic morse_PA
-pointed_already_charging panic morse_PQ
;======================================================================
include final.inc
train santafe home -X5
-train shinkansen home -X9 -A5 -A6
+train shinkansen home -X7 -X9 -A5 -A6
+end
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 (segi || tra) oprintf(UPO, ":");
+ oprintf(UPO, "message %s", ec ? errorcodelist[ec] : "info");
if (segi) oprintf(UPO, " @%s", segi->pname);
if (tra) oprintf(UPO, " %s", tra->pname);
+ if (segi || tra) oprintf(UPO, ":");
+ oprintf(UPO," ");
+ ovprintf(UPO,fmt,al);
oprintf(UPO, "\n");
}
| TRAIN train AT backwards seg ':' NUM '+' '-' NUM
{ if ($2) record_train_at($2,$4,$5,$7,$10);
}
- | TRAIN train { cur_train=$2; } HOME segments
+ | TRAIN train HOME { cur_train=$2; } segments
{
}
| TRAIN train STEP NUM '=' NUM NUM '/' NUM
{ if ($2) record_seg_at($2,$4);
}
-backwards: /* empty */ { return 0; }
- | '-' { return 1; }
+backwards: /* empty */ { $$= 0; }
+ | '-' { $$= 1; }
-segments: { cur_train= 0; }
+segments: { cur_train= (void*)-1; }
| backwards seg { record_train_home(cur_train,$1,$2); } segments
ident: TRAIN | SEG | IS | AT | HAS | STEP | HOME | END | IDENT
static void parse_file(const char *why) {
FILE *f;
+ int r;
f= fopen(filename,"r");
if (!f) diee("config: cannot open %s: %s", why, filename);
record_yyrestart(f);
- record_yyparse();
+ r= record_yyparse();
+ assert(!r); /* we're supposed to call yyerror which dies */
}
static void parse_pass(const char **argv) {
oprintf(UPO, "resolving calculate-u\n");
- FOR_SEGMENT(d, NOOP, NOOP) { /* calculate U */
+ FOR_SEGMENT(d,NOOP,NOOP) { /* calculate U */
unsigned updated= 0;
#define ADDTO_U_EH(homeowner,HH_HE,string) \
MovPosComb target= -1;
- if (d->owner) {
+ if (d->home && d->home->resolution == RR_H) {
+ d->owner= d->home;
+ d->tr_backwards= d->ho_backwards;
+ target= 0; /* a bit kludgey */
+ } else if (d->owner) {
+ d->tr_backwards ^= d->owner->backwards;
+ target= d->movposcomb;
+ }
+
+ 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) {
problems++;
}
}
+ } else {
+ assert(!d->i->n_movfeats);
+ d->movposcomb= 0;
}
}
FOR_SEG {
if (seg->res_detect) {
- seg->res_detect= 0;
- safety_notify_detection(seg);
+ Segment *notify, *onwards;
+ const SegPosCombInfo *pci;
+ const SegmentLinkInfo *link;
+
+ notify= seg;
+ for (;;) {
+ seg->res_detect= 0;
+ assert(notify->movposcomb >= 0);
+
+ pci= ¬ify->i->poscombs[notify->movposcomb];
+ link= notify->tr_backwards ? &pci->backwards : &pci->forwards;
+
+ if (!SOMEP(link->next)) break;
+ onwards= &segments[link->next];
+ if (!onwards->res_detect) break;
+ if (onwards->owner != seg->owner) break;
+
+ notify= onwards;
+ }
+
+ safety_notify_detection(notify);
}
}
long overall, remain, dist_until, time_until;
int *invert_likehere, train_inverted_here;
Train *tra= l->tra;
+ const SegPosCombInfo *pci;
+ const SegmentLinkInfo *link;
if (l->ec) return;
remain= overall= advance + speed * SPEED_CLEAR_MULT;
+fprintf(stderr,"lay_train_pass %s @%s+%ld check_clash=%d"
+ " advance=%ld speed=%ld remain=%ld backwards=%u\n",
+ tra->pname, seg->i->pname, tloc.into,
+ check_clash, advance,speed,remain,
+ backwards);
+
for (;;) {
seg= tloc.seg;
+fprintf(stderr,"lay_train_pass loop @%s remain=%ld\n",
+ seg->i->pname, remain);
+
if (check_clash) {
lay_train_check_clash(l,seg,seg);
inter= interferes(seg);
seg->tr_backwards= tloc.backwards ^ backwards;
seg->tr_updated= 1;
+ if (backwards)
+ seg->until_detect= 0;
+
train_inverted_here= seg->seg_inverted ^ seg->tr_backwards;
invert_likehere= &l->invert_count[train_inverted_here];
if (!remain) break;
int r= trackloc_further(&tloc, &remain);
- if (r==-2) {
+fprintf(stderr,"lay_train_pass further=%d tloc=@%s+%ld remain=%ld\n",
+ r, tloc.seg->i->pname, tloc.into, remain);
+
+ switch (r) {
+ case -2:
l->ec= safety_problem(l->tra, seg, "end of track");
return;
- }
- if (r==-1) {
- l->ec= safety_problem(l->tra, seg, "track route not set");
+ case -1:
+ l->ec= safety_problem(l->tra, tloc.err, "track route not set");
return;
- }
- if (r>1) {
- const SegPosCombInfo *pci= trackloc_segposcomb(&tloc);
- const SegmentLinkInfo *link= trackloc_segmentlink(&tloc,pci,0);
+ case +1:
+ pci= trackloc_segposcomb(&tloc);
+ link= trackloc_segmentlink(&tloc,pci,0);
if (link->next+segments != seg) {
l->ec= safety_problem(l->tra, link->next+segments,
"track route set against us");
return;
}
+ break;
+ case 0:
+ return;
+ default:
+ abort();
}
}
}
assert(seg->owner == l->tra);
seg_be_inverted= train_be_inverted ^ seg->tr_backwards;
assert(!(seg_be_inverted && !segi->invertible));
+ if (!segi->invertible)
+ continue;
seg->seg_inverted= seg_be_inverted;
actual_inversions_segment(seg);
}
tloc.seg= seg;
tloc.into= tra->maxinto;
- tloc.backwards= seg->tr_backwards ^ tra->backwards;
+ tloc.backwards= seg->tr_backwards;
+
+fprintf(stderr,"lay_train %s @%s added_slop=%ld maxinto=%ld "
+ "tra->backwards=%d tloc.backwards=%d\n",
+ seg->i->pname, tra->pname, added_slop, (long)tra->maxinto,
+ tra->backwards, tloc.backwards);
l.tra= tra;
l.ec= 0;
trackloc_reverse(&tloc);
seg->tr_updated= 0; /* we're about to do this one again */
tail= tra->backwards ? tra->head : tra->tail;
- taildet= tra->detectable + tail;
+ taildet= tra->detectable + tail + tra->maxinto;
lay_train_pass(&l, tloc, taildet, 0, 1, 1);
}
tra->uncertainty= tra->maxinto;
- if (!(tra->estopping || tra->speed==0)) {
+ if (!tra->estopping) {
ec= lay_train(tra, 0);
if (ec) {
- logmsg(ec,tra,seg->i, "emergency stop");
+ logmsg(ec,tra,seg->i, "emergency stop on reaching here");
safety_emergencystop(tra);
}
}
typedef struct TrackLocation TrackLocation;
struct TrackLocation { /* transparent, and manipulable by trackloc_... fns */
Segment *seg; /* current segment */
+ Segment *err; /* segment where error happens (eg, movposcomb wrong) */
long into; /* distance from start of segment */
unsigned backwards:1; /* if 1, into is positive and measured from end */
};
long trackloc_remaininseg(const TrackLocation *tloc);
- /* Returns dist that tloc can advance before it goes into next segment. */
+ /* Returns dist that tloc can advance before it goes into next segment.
+ * Returns -1 if current track log has unknown movposcomb.
+ */
int trackloc_further(TrackLocation *tloc, long *remain_io);
/* Advances tloc, decrementing *remain_io, until one of the
- * following happens:
- * tloc->segn changes returns +1
- * *remain_io becomes zero returns 0
- * unknown movpos found returns -1
- * end of track reached returns -2
+ * following happens: err set to
+ * tloc->segn changes returns +1 unchanged
+ * *remain_io becomes zero returns 0 unchanged
+ * unknown movpos found returns -1 next segment
+ * end of track reached returns -2 seg
+ * current track segment unknown movpos! returns -3 seg
* Does _not_ check that the movposcomb of the segment we
* are moving into is correct.
*/
void speedmanager_reset_train(Train *tra) {
Nmra n;
- ErrorCode ec;
tra->estopping= 0;
tra->speed= 0;
tra->accel.target= tra->accel.commanded= 0;
+ if (tra->addr < 0)
+ return;
+
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(tra, 0);
- if (ec)
- safety_panic(tra, 0, "position reset impossible!");
}
static void xmit_speed(Train *tra) {
static void estop_done(TimeoutEvent *toev) {
Train *tra= (void*)((char*)toev - offsetof(Train, accel.more));
+ ErrorCode ec;
retransmit_urgent_cancel(&tra->accel.rn);
speedmanager_reset_train(tra);
+ ec= safety_requestspeed(tra, 0);
+ if (ec)
+ safety_panic(tra, 0, "position reset impossible!");
}
void speedmanager_emergencystop(Train *tra) {
int a, b, try, found;
const SpeedCurveEntry *curve= tra->accel.curve;
+ if (tra->addr < 0) {
+ logmsg(EC_Invalid, tra, 0, "speed request ignored, train address unknown");
+ return;
+ }
+
if (tra->estopping) {
logmsg(EC_Invalid, tra, 0, "speed request ignored during emergency stop");
return;
const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
const SegPosCombInfo *pci,
unsigned far) {
- return (tloc->backwards ^ far) ? &pci->backwards : &pci->forwards;
+ return (tloc->backwards ^ far) ? &pci->forwards : &pci->backwards;
}
long trackloc_remaininseg(const TrackLocation *tloc) {
long segment_len;
pci= trackloc_segposcomb(tloc);
+ if (!pci) return -1;
segment_len= pci->dist;
assert(tloc->into <= segment_len);
return segment_len - tloc->into;
int trackloc_further(TrackLocation *tloc, long *remain_io) {
const SegPosCombInfo *pci;
const SegmentLinkInfo *lnki_far;
+ Segment *nextseg;
long segment_remain;
segment_remain= trackloc_remaininseg(tloc);
+ if (segment_remain<0) { tloc->err=tloc->seg; return -3; }
if (*remain_io <= segment_remain) {
tloc->into += *remain_io;
*remain_io -= segment_remain;
tloc->into += segment_remain;
pci= trackloc_segposcomb(tloc);
- if (!pci) return -1;
+
lnki_far= trackloc_segmentlink(tloc, pci, 1);
- if (!SOMEP(lnki_far->next)) return -2;
- tloc->seg= &segments[lnki_far->next];
+ if (!SOMEP(lnki_far->next)) { tloc->err=tloc->seg; return -2; }
+
+ nextseg= &segments[lnki_far->next];
+ if (nextseg->movposcomb<0) { tloc->err=nextseg; return -1; }
+
+ tloc->seg= nextseg;
tloc->into= 0;
tloc->backwards ^= lnki_far->next_backwards;
return +1;