realtime: realtime.o startup.o cdumgr.o safety.o trackloc.o \
speed.o actual.o retransmit.o \
- cmdinput.o obc.o eventhelp.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 \
nmra.o encode.o \
Protocol over new hostside stdin:
Example (always the same msg):
- P> nmra [*<slot>] [<nmra-command [<nmra-args>...]] nmra speed28 3 13 1
- P> nmra [*<slot>] [=<nmra-bytes>] nmra =0348
- P> nmra [*<slot>] [:<nmra-bytes-with-csum>] nmra :03484b
- P> nmra [*<slot>] [_<pic-literal-bytes>] nmra _7f7f00644197
- in each case *<slot> indicates that the message should be put in
- the retransmission cycle, and cancels any previous message with the
- same *<slot>. <slot> may be empty.
- P> nmra *<slot>
+ P> nmra [<slot>] [<nmra-command [<nmra-args>...]] nmra speed28 3 13 1
+ P> nmra [<slot>] [=<nmra-bytes>] nmra =0348
+ P> nmra [<slot>] [:<nmra-bytes-with-csum>] nmra :03484b
+ P> nmra [<slot>] [_<pic-literal-bytes>] nmra _7f7f00644197
+ in each case <slot> (if present) is *<slotname> or %<slotname> and
+ indicates that the message should be put in the retransmission
+ cycle, and cancels any previous message with the same <slotname>.
+ <slotname> may be empty. * indicates urgent
+ P> nmra <slot>
cancels the relevant retransmission.
Example (always the same msg):
+before can test
+ commands for speed manager
+ create data files containing some train data
+ write trivial initial settlement to get data array right
+ write out layout data on crash
+ check that everything in Train and Segment is init'd
+
+dunno but maybe before can test
+ train speed curve measurements
+ wiring to gui display
+
things not yet considered at all in safety code
- polarity
+ coming up against points the wrong way
min. curve specifications
-put correct data in dummy-trains.c
initialise safety_state with appropriate stuff
ManualRetransmitNode *back, *next;
char *name;
int lname;
- RetransmitNode rn;
+ RetransmitUrgentNode rn;
};
#define bogus_volatile /*empty*/
longjmp(pec->jb, 1);
}
-static int cmd_nmra_command(ParseState *ps, RetransmitNode *rn) {
+static int cmd_nmra_command(ParseState *ps, PicInsn *pi) {
int hex;
const char *cmdarg;
int lcmdarg;
assert(ps->remain);
switch (ps->remain[0]) {
- case '_': ps->remain++; return ps_needhextoend(ps, rn->pi.d, &rn->pi.l);
+ case '_': ps->remain++; return ps_needhextoend(ps, pi->d, &pi->l);
case '=': hex=1; checksum=1; break;
case ':': hex=1; checksum=0; break;
default: hex=0; checksum=1; break;
if (checksum)
nmra_addchecksum(&nmra);
- nmra_encodeforpic(&nmra, &rn->pi);
+ nmra_encodeforpic(&nmra, pi);
return 1;
}
static void cmd_nmra(ParseState *ps, const CmdInfo *ci) {
static struct { ManualRetransmitNode *head, *tail; } mrns;
- ManualRetransmitNode *mrn;
- RetransmitNode *rn, rn_buf;
+ PicInsn *pi, pi_buf;
+ ManualRetransmitNode *mrn=0;
+ void (*retrans)(RetransmitUrgentNode *urg, const Nmra *n)= 0;
- if (ps->remain && ps->remain[0]=='*') {
+ if (ps->remain) {
+ if (ps->remain[0]=='*') retrans= retransmit_urgent_queue;
+ else if (ps->remain[0]=='%') retrans= retransmit_urgent_queue_relaxed;
+ }
+ if (retrans) {
const char *mrname;
int lmrname;
!memcmp(mrn->name, mrname, lmrname));
mrn= mrn->next);
if (mrn) {
- retransmit_cancel(&mrn->rn);
+ retransmit_urgent_cancel(&mrn->rn);
} else {
mrn= mmalloc(sizeof(*mrn));
mrn->name= mmalloc(lmrname);
memcpy(mrn->name, mrname, lmrname);
mrn->lname= lmrname;
}
- } else {
- mrn= 0;
}
if (!ps->remain) {
- if (!mrn) {
+ if (!retrans) {
badcmd(ps,"nmra must have slot to cancel or data to send");
return;
}
return;
}
- rn= mrn ? &mrn->rn : &rn_buf;
- rn->pi.l= sizeof(rn->pi.d);
+ pi= retrans ? &mrn->rn.pi : &pi_buf;
- if (!cmd_nmra_command(ps, rn)) {
- if (mrn) { free(mrn->name); free(mrn); }
+ if (!cmd_nmra_command(ps, pi)) {
+ if (retrans) { free(mrn->name); free(mrn); }
return;
}
- if (mrn)
- retransmit_queue(&mrn->rn);
+ if (retrans)
+ retrans(&mrn->rn, 0);
else
- serial_transmit(&rn->pi);
+ serial_transmit(pi);
ouack(ci);
}
}
if (!ps_neednoargs(ps))
return;
- enco_pic_anyinsn(&pi, pii, arg);
+ enco_pic_pii(&pi, pii, arg);
}
serial_transmit(&pi);
ouack(ci);
}
+
+const CmdInfo toplevel_cmds[]= {
+ { "pic", cmd_pic },
+ { "nmra", cmd_nmra, },
+ { "noop", cmd_noop },
+ { 0 }
+};
typedef union RetransmitUrgentNode RetransmitUrgentNode;
typedef unsigned Retransmit__Time;
-struct RetransmitRelaxedNode { /* all for use by retransmit.c only */
+ /* Contents of the retransmission nodes is generally all for use by
+ * retransmit.c only; as a special exception, caller may edit pi
+ * directly. Normally, though, pi is set by supplying an NMRA
+ * command to one of the _queue functions; _queue will update pi
+ * iff the Nmra* is non-null */
+struct RetransmitRelaxedNode {
PicInsn pi;
DLIST_NODE(RetransmitRelaxedNode) rr;
};
-union RetransmitUrgentNode { /* all for use by retransmit.c only */
+union RetransmitUrgentNode {
PicInsn pi;
struct {
RetransmitRelaxedNode relaxed;
} u;
};
+void retransmit_start(void);
+void retransmit_something(void);
+
void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, const Nmra *n);
void retransmit_relaxed_requeue(RetransmitRelaxedNode *rn, const Nmra *n);
void retransmit_relaxed_cancel(RetransmitRelaxedNode *rn);
*/
#include "realtime.h"
+#include "nmra.h"
#include "retransmit-table.h"
#define RETRANSMIT_TIME_SIGNED_MAX ((~(Retransmit__Time)0) >> 1)
-static const PicInsn linefill= { { 0xff, 0x7f }, 2 };
+static PicInsn linefill;
static DLIST2_HEAD(RetransmitRelaxedNode) relaxed;
-static elapsed;
+static Retransmit__Time elapsed;
static PerSpeedyTrans speedies[] = SPEEDIESINIT;
static void retransmit_this(const PicInsn *pi) {
elapsed++;
}
-static void retransmit_something(void) {
+void retransmit_start(void) {
+ Nmra n;
+
+ enco_nmra_idle(&n);
+ nmra_encodeforpic(&n, &linefill);
+
+ retransmit_something();
+ retransmit_something();
+ retransmit_something();
+}
+
+void retransmit_something(void) {
PerSpeedyTrans *spd;
RetransmitUrgentNode *urg;
RetransmitRelaxedNode *rlx;
+ int ix;
for (ix=0, spd=speedies;
- ix < RETRANS_SPEEDYCOUNT;
+ ix < SPEEDYCOUNT;
ix++, spd++) {
- urg= spd->head;
+ urg= spd->queue.head;
if (!urg) continue;
if (elapsed - urg->u.when > RETRANSMIT_TIME_SIGNED_MAX) continue;
/* found one to transmit: */
DLIST2_REMOVE(spd->queue,urg,u.queue);
- if (++ix < RETRANS_SPEEDYCOUNT) {
+ if (++ix < SPEEDYCOUNT) {
urg->u.ix= ix;
urg->u.when= elapsed + spd->interval;
spd++;
return;
}
- rlx= relaxed.head) {
+ rlx= relaxed.head;
if (rlx) {
DLIST2_REMOVE(relaxed,rlx,rr);
DLIST2_APPEND(relaxed,rlx,rr);
serial_transmit(&linefill);
}
-void retransmit_relaxed_queue(RetransmitRelaxedNode *rlx, const Nmra *n) {
- nmra_encodeforpic(n, &rlx->pi);
+void retransmit_relaxed_queue(RetransmitRelaxedNode *rn, const Nmra *n) {
+ if (n) nmra_encodeforpic(n, &rn->pi);
DLIST2_PREPEND(relaxed,rn,rr);
}
void retransmit_relaxed_requeue(RetransmitRelaxedNode *rn, const Nmra *n) {
- retransmit_relaxed_cancel(rlx);
- retransmit_relaxed_queue(rlx, n);
+ retransmit_relaxed_cancel(rn);
+ retransmit_relaxed_queue(rn, n);
}
void retransmit_relaxed_cancel(RetransmitRelaxedNode *rlx) {
DLIST2_REMOVE(relaxed,rlx,rr);
}
void retransmit_urgent_queue(RetransmitUrgentNode *urg, const Nmra *n) {
- nmra_encodeforpic(n, &urg->pi);
+ retransmit_relaxed_queue(&urg->u.relaxed, n);
urg->u.ix= 0;
urg->u.when= elapsed;
DLIST2_APPEND(speedies[0].queue,urg,u.queue);
- retransmit_relaxed_queue(&urg->u.relaxed);
}
void retransmit_urgent_queue_relaxed(RetransmitUrgentNode *urg, const Nmra *n){
- nmra_encodeforpic(n, &urg->pi);
+ retransmit_relaxed_queue(&urg->u.relaxed, n);
urg->u.ix= -1;
urg->u.when= elapsed;
- retransmit_relaxed_queue(&urg->u.relaxed);
}
void retransmit_urgent_requeue(RetransmitUrgentNode *rn, const Nmra *n) {
- retransmit_urgent_cancel(urg);
- retransmit_urgent_queue(urg, n);
+ retransmit_urgent_cancel(rn);
+ retransmit_urgent_queue(rn, n);
}
void retransmit_urgent_cancel(RetransmitUrgentNode *urg) {
if (urg->u.ix >= 0)
case Sta_Fault: break;
case Sta_Settling: enco_pic_off(&piob); break;
case Sta_Resolving: enco_pic_on(&piob); break;
- case Sta_Run: break;
+ case Sta_Run: retransmit_start(); break;
}
if (piob.l) serial_transmit(&piob);
void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
if (sta_state <= Sta_Settling) return;
if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
-
- /* fixme transmit something else (move this to another file?) */
+
+ while (objnum--)
+ retransmit_something();
}
void on_pic_detect0(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
void abandon_run(void) {
/* fixme do something here */
}
-
-const CmdInfo toplevel_cmds[]= {
-#if 0
- { "pic", cmd_pic },
- { "nmra", cmd_nmra, },
- { "noop", cmd_noop },
-#endif
- { 0 }
-};
return p;
}
+void *mrealloc(void *o, size_t sz) {
+ void *r;
+ if (!sz) { free(o); return 0; }
+ r= realloc(o,sz);
+ if (!r) diem();
+ return r;
+}
+
char *mstrdupl(const char *s, int l) {
char *p;
p= mmalloc(l+1);