From 225086ac45f4bdcbd77346f2d916a3892872ad03 Mon Sep 17 00:00:00 2001 From: ian Date: Sat, 29 Mar 2008 12:29:26 +0000 Subject: [PATCH] WIP movpos.c --- hostside/errorcodes.h.gen | 2 + hostside/movpos.c | 217 ++++++++++++++++++++++++++++++++++++++ hostside/safety.h | 39 ++++++- 3 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 hostside/movpos.c diff --git a/hostside/errorcodes.h.gen b/hostside/errorcodes.h.gen index 7608367..630e7ec 100755 --- a/hostside/errorcodes.h.gen +++ b/hostside/errorcodes.h.gen @@ -4,6 +4,8 @@ OK Invalid Safety + Points + MovFeatKindsCombination ); diff --git a/hostside/movpos.c b/hostside/movpos.c new file mode 100644 index 0000000..61ba390 --- /dev/null +++ b/hostside/movpos.c @@ -0,0 +1,217 @@ +/* + * Handling of points and other moveable features. + */ + +#include "realtime.h" + +/*---------- declarations ----------*/ + +typedef struct SomeChange SomeChange; + +typedef struct { + MoveFeatInfo *i; + Small posn; +} Motion; + +typedef struct { + /* call flow is: allocate [[reserve] request] cancel + * error from reserve or request causes call to destroy + */ + SomeChange *(*allocate)(int n_motions); /* always succeeds */ + ErrorCode (*reserve)(SomeChange*, Segment *move, int maxdelay_ms); + ErrorCode (*request)(SomeChange*, Segment *move, + int n_motions, const Motion*, int maxdelay_ms); + void (*destroy)(SomeChange*); +} MethodInfo; + +typedef struct MovPosChangeDetails { + const MethodInfo *mi; + Segment *move; + MovPosCallback *on_moving, *on_done; + void *u; +} ChangeHeader; + + +/*---------- method-independent machinery ----------*/ + +static const MethodInfo methodinfos[]= { + { nomove_allocate, nomove_reserve, nomove_request, nomove_cancel } + { point_allocate, point_reserve, point_request, point_cancel } +}; + +ErrorCode +movpos_requestchange(Segment *back, Segment *move, *Segment *fwd, + int maxdelay_ms, MovPosChangeRequest *req_io, + MovPosCallback *on_moving, MovPosCallback *on_done, *u) { + const SegmentInfo *movei= move->i; + SegPosCombInfo *pci; + MovPosComb tcomb, bestcomb=0; + int tchanges, bestchanges=INT_MAX; + ErrorCode ec; + + for (tcomb=0, pci=movei->poscombs; + tcombn_poscombs; + tcomb++, pci++) { + Segment *tback= &segments[pci->backwards.next]; + Segment *tfwd= &segments[pci->forwards .next]; + if (back && !(back==tback || back=tfwd)) continue; + if (fwd && !(fwd ==tback || fwd =tfwd)) continue; + + if (movei->n_movfeats>1) { + /* we have to search for the one which is least effort, then */ + for (feat=0, feati=movei->movfeats, tchanges=0; + featn_movfeats; + feat++) + if ((tcomb - move->movposcomb) / feati->weight % feati->posns) + tchanges++; + if (tchanges > bestchanges) + continue; + } + tcomb= bestcomb; + tchanges= bestchanges; + } + + if (bestchanges==INT_MAX) { ec= EC_Invalid; goto x; } + + int n_motions=0; + Motion motions[movei->n_movfeats]; + MovFeatKind kind= mfk_none; + + for (feat=0, feati=movei->movfeats; + featn_movfeats; + feat++, feati++) { + if ((bestcomb - move->movposcomb) / feati->weight % feati->posns) + continue; + if (kind) { + if (feati->kind != kind) { ec= EC_MovFeatKindsCombination; goto x; } + kind= feati->kind; + } + motions[n_motions].i= feati; + motions[n_motions].posn= bestcomb / feati->weight % feati->posns; + n_motions++; + } + + const MethodInfo *mi= methodinfos[kind]; + + if (!*req_io) { + (*req_io)= (ChangeHeader*)mi->allocate(n_motions); + (*req_io)->mi= mi; + (*req_io)->move= move; + (*req_io)->on_moving= on_moving; + (*req_io)->on_done= on_done; + (*req_io)->u= u; + } + + ec= mi->request((SomeChange*)*req_io, move, n_motions, motions, maxdelay_ms); + if (ec) goto x; + + return 0; + + x: + movpos_cancelchange(*req_io); + return ec; +} + +void movpos_cancelchange(MovPosChangeRequest *req) { + if (!req) return; + req->mi->cancel((SomeChange*)req); +} + +ErrorCode +movpos_reservechange(Segment *move, int maxdelay_ms, + MovPosChangeRequest *res_r) { + MovFeatKind kind= mfk_none; + + for (feat=0; feati=movei->movfeats; + featn_movfeats; + feat++, feati++) + if (kind) { + if (feati->kind != kind) return EC_MovFeatKindsCombination; + kind= feati->kind; + } + + const MethodInfo *mi= methodinfos[kind]; + SomeChange *chg= mi->allocate(movei->n_movfeats); + ec= mi->reserve(chg, move, maxdelay_ms); + if (ec) goto x; + + *res_r= (ChangeHeader*)chg; + return 0; + + x: + movpos_cancelchange((ChangeHeader*)chg); + return ec; +} + + + + } + + + } + + + (*req_io)->move= move; + (*req_io)->move= move; + + ChangeHeader *change= method(move, n_motions, motions, *req_io); + if (!change) + return EC_Point; + + change + change.on_moving= on_moving; + change.on_done= on_done; + change.u= u; + + *req_io= + + + + MovFeatKind tkind + if (tchanges + + unsigned diff= ( + + + / feati->weight + + unsigned posold= (move->movposcomb / feati->weight) % feati->posns; + + } + + for (feat=0, feati=movei->movfeats, result=0; + featn_movfeats; + feat++) { + unsigned posold= (move->movposcomb / feati->weight) % feati->posns; + for (poschange=0; poschangeposns; poschange++) { + unsigned posnew= poschange % feati->posns; + + +/* + * Currently there is only one queue for the one CDU. + * + * We maintain a queue of change requests. The queue can also contain + * reservations. We divide time into discrete slots, numbered with + * clock arithmetic. + * + * cslot cslot+1 cslot+2 + * + * currently next in after + * changing line that + */ + +typedef unsigned Slot; + +typedef struct PointChangeQueueEntry { + struct PointChangeQueueEntry *next, *back; + + Slot latest, needs; + Segment *move; + Motion motions[]; +} QE; + +static Slot cslot; +static struct { QE *head, *tail; } queue; + +convert incoming latest's into queue lengths as simple counts +maintain latest count number for each diff --git a/hostside/safety.h b/hostside/safety.h index 9d96fb0..65faf2d 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -73,7 +73,7 @@ struct Segment { unsigned tr_backwards:1, /* train's motion is (would be) backwards wrt track */ ho_backwards:1, /* home train has its front and rear backwards wrt track */ - movfeat_moving:1, /* feature(s) have been told to change to movposcomb */ + points_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 */ @@ -129,6 +129,43 @@ void safety_setdirection(Train* tra, int sense_fixme_define_this_properly); void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ +/*========== movpos.c ==========*/ +/* + * movpos.c manages the CDU and points and other moveable features. + * Only safety.c should request changes. + */ + +typedef struct MovPosChangeDetails *MovPosChangeRequest; +typedef void MovPosCallback(Segment*, MovPosChangeRequest, void *u); + +ErrorCode +movpos_requestchange(Segment *back, Segment *move, Segment *fwd, + int maxdelay_ms, MovPosChangeRequest *req_io, + MovPosCallback *on_moving, MovPosCallback *on_done, + void *u); + /* back and fwd may be 0 if we don't care (and must be if there is + * no track in that direction. It is immaterial which is back and + * which fwd. *req_io should be 0 on entry, or the results of + * movpos_reservechange; on successful exit it is non-0. req_io may + * be 0. Updates seg->movposcomb and seg->points_moving. Returns + * EC_Invalid if there is no movposcomb of move matching back/fwd, + * or EC_MovPos if the maxdelay_ms could not be met; on error any + * reservation is destroyed and *req_io is undefined. */ + +void movpos_cancelchange(MovPosChangeRequest /* 0 OK */); + /* Cancels any movements not yet done; may leave movposcomb in an + * unknown or invalid physical state. For a reservation, just + * discards it without doing anything. */ + +ErrorCode +movpos_reservechange(Segment *move, int maxdelay_ms, + MovPosChangeRequest *res_r); + /* Returns EC_Points if the maxdelay_ms could not be met. The resulting + * MovPosChangeRequest is a reservation which is guaranteed to be + * useable successfully later for any movpos_requestchange for the + * same move and a greater or equal maxdelay_ms. On successful + * exit *res_r is set to non-0. */ + /*========== speedmgr.c ==========*/ void speedmanager_speedchange_request(Train *tra, long speed); -- 2.30.2