From 2e302edd49b4ca85b6a794a10737d301193260b3 Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 15 Apr 2008 01:15:08 +0000 Subject: [PATCH] do not panic if host fires a point and then immediately turns off --- detpic/morse.messages | 1 - detpic/points.asm | 3 +-- hostside/homes.record | 3 ++- hostside/realtime.c | 7 +++--- hostside/record-y.y | 8 +++---- hostside/record.c | 4 +++- hostside/resolve.c | 54 ++++++++++++++++++++++++++++--------------- hostside/safety.c | 52 +++++++++++++++++++++++++++++++---------- hostside/safety.h | 16 ++++++++----- hostside/speed.c | 16 +++++++++---- hostside/trackloc.c | 15 ++++++++---- 11 files changed, 123 insertions(+), 56 deletions(-) diff --git a/detpic/morse.messages b/detpic/morse.messages index 8194ad3..823df32 100644 --- a/detpic/morse.messages +++ b/detpic/morse.messages @@ -96,5 +96,4 @@ PC ; Firing point when CDU empty 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 diff --git a/detpic/points.asm b/detpic/points.asm index ac50cff..1c5be4a 100644 --- a/detpic/points.asm +++ b/detpic/points.asm @@ -390,7 +390,7 @@ near_gots code ;-------------------- 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 @@ -401,7 +401,6 @@ got_pointed @ goto serial_addbyte pointed_butnot_firing panic morse_PA -pointed_already_charging panic morse_PQ ;====================================================================== include final.inc diff --git a/hostside/homes.record b/hostside/homes.record index 808cb37..cf8735c 100644 --- a/hostside/homes.record +++ b/hostside/homes.record @@ -1,2 +1,3 @@ train santafe home -X5 -train shinkansen home -X9 -A5 -A6 +train shinkansen home -X7 -X9 -A5 -A6 +end diff --git a/hostside/realtime.c b/hostside/realtime.c index 125a3af..fbeb8c5 100644 --- a/hostside/realtime.c +++ b/hostside/realtime.c @@ -66,11 +66,12 @@ static char *transegn2suffixstring(Train *tra, Segment *seg) { 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"); } diff --git a/hostside/record-y.y b/hostside/record-y.y index 2a3cb7a..8d50a68 100644 --- a/hostside/record-y.y +++ b/hostside/record-y.y @@ -39,7 +39,7 @@ line: /* empty */ | 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 @@ -53,10 +53,10 @@ line: /* empty */ { 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 diff --git a/hostside/record.c b/hostside/record.c index 0bd150b..363350d 100644 --- a/hostside/record.c +++ b/hostside/record.c @@ -312,11 +312,13 @@ static void alloc(void) { 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) { diff --git a/hostside/resolve.c b/hostside/resolve.c index 14f8aeb..cd5cc6a 100644 --- a/hostside/resolve.c +++ b/hostside/resolve.c @@ -181,7 +181,7 @@ int resolve_complete(void) { 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) \ @@ -296,22 +296,18 @@ int resolve_complete(void) { 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) { @@ -323,6 +319,9 @@ int resolve_complete(void) { problems++; } } + } else { + assert(!d->i->n_movfeats); + d->movposcomb= 0; } } @@ -352,8 +351,27 @@ void resolve_motioncheck(void) { 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); } } diff --git a/hostside/safety.c b/hostside/safety.c index cca1f99..13d1a1f 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -82,6 +82,8 @@ static void lay_train_pass(LayTrainState *l, 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; @@ -89,9 +91,18 @@ static void lay_train_pass(LayTrainState *l, 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); @@ -102,6 +113,9 @@ static void lay_train_pass(LayTrainState *l, 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]; @@ -129,22 +143,29 @@ static void lay_train_pass(LayTrainState *l, 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(); } } } @@ -165,6 +186,8 @@ static void lay_train_inversions(LayTrainState *l) { 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); } @@ -194,7 +217,12 @@ static ErrorCode lay_train(Train *tra, long added_slop) { 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; @@ -222,7 +250,7 @@ static ErrorCode lay_train(Train *tra, long added_slop) { 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); @@ -263,10 +291,10 @@ void safety_notify_detection(Segment *seg) { } 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); } } diff --git a/hostside/safety.h b/hostside/safety.h index 4d895a4..4d22969 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -234,20 +234,24 @@ void actual_inversions_done(void); 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. */ diff --git a/hostside/speed.c b/hostside/speed.c index 336d87b..83befdc 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -11,17 +11,16 @@ static void accel_more(TimeoutEvent *toev); 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) { @@ -44,8 +43,12 @@ void speedmanager_autostop(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) { @@ -132,6 +135,11 @@ void speedmanager_speedchange_request(Train *tra, long speed) { 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; diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 4d0ba11..20c6770 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -16,7 +16,7 @@ const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc) { 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) { @@ -24,6 +24,7 @@ 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; @@ -32,9 +33,11 @@ long trackloc_remaininseg(const TrackLocation *tloc) { 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; @@ -44,10 +47,14 @@ int trackloc_further(TrackLocation *tloc, long *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; -- 2.30.2