< 1 0001 XXX 0 XXXXXXX (88+) PONG Pong `X' (reply to Ping `X')
< 0 000 1001 (HT) HELLO I am booted
< 0 000 1011 (VT) AAARGH Followed by debug chars (only)
- < 0 000 1101 (CR) WATCHDOG Timeout happened
+ < 0 000 1101 (CR) WTIMEOUT Watchdog timeout happened
< 0 000 0111 (BEL) FAULT Fault exists
< 0 000 0110 (ACK) FIXED Fault now fixed
< 0 0100 PPP (20+) POINTED Point change done using capacitor P
-hostside
+realtime
hostside-old
+hostside
safety
t
layoutinfo.h
#
-AUTOINCS= selectors.h
+AUTOINCS= auproto-pic.h layoutinfo.h selectors.h
+TARGETS= hostside-old gui-plan-bot realtime
include ../common.make
include ../cprogs.make
-TARGETS= hostside hostside-old gui-plan-bot
-
default: all
recurse: all
for-pic:
hostside-old: serialio.o nmra.o main.o encode.o utils.o
$(LINK)
-hostside: hostside.o serialio.o client.o obc.o commands.o utils.o \
- nmra.o encode.o retransmit.o output.o auproto-pic.o \
- parseutils.o \
- -loop
+BESSAR=bessar:things/trains-bessar/hostside/.
+
+on-bessar: $(TARGETS)
+ RSYNC_RSH=fsh rsync $(TARGETS) $(BESSAR)
+
+%.on-bessar: %
+ RSYNC_RSH=fsh rsync $^ $(BESSAR)
+
+realtime: realtime.o startup.o cdumgr.o \
+ cmdinput.o obc.o eventhelp.o \
+ utils.o serialio.o parseutils.o auproto-pic.o \
+ __oop-read-copy.o -loop
$(LINK)
proto-expanded: ../cebpic/README.protocol
__oop-read-copy.o -loop
$(LINK) -L/usr/X11R6/lib -lXpm -lX11
-commands.o auproto-pic.o: auproto-pic.h
-
-auproto-%: parse-proto-spec proto-expanded skelproto-%
+auproto-pic.c auproto-pic.h: auproto-%: \
+ parse-proto-spec proto-expanded skelproto-%
./$+ $o
layoutinfo.h: ../layout/ours.layout-data.c Makefile
selectors.h: selectors.h.gen
./$< $o
-safety.o trackloc.o: layoutinfo.h
-
safety: safety.o utils.o trackloc.o ../layout/ours.layout-data.o
$(LINK)
+hostside: hostside.o serialio.o client.o obc.o commands.o utils.o \
+ nmra.o encode.o retransmit.o output.o auproto-pic.o \
+ parseutils.o \
+ -loop
+ $(LINK)
+
clean:
rm -f *.o *.d $(TARGETS) selectors.h
rm -f auproto-pic.h *~ core proto-expanded
--- /dev/null
+pic
+ talks pic protocol to safety
+
+safety
+ rtprio
+ passes on all pic traffic
+ safety incl polarity, no collisions, curvature, etc.
+ converts instructions to/from text
+ takes instructions only from multiplex
+all real-time stuff so clients can be confident of no misthings ?
+ on-event for point changing, stopping, etc. ?
+ specify intended path and speed profile for each train ?
+ - list of points, in order, with setting
+ this is good enough to be in time for shinkansen on inner loop
+ inner loop is 3589mm
+ minus longest section for slop -657mm (X10)
+ minus length of the train -1118mm
+ -------
+ spare 1813mm
+ or at 1m/s 1813ms
+ minus safety delay -500ms
+ -------
+ 1313ms
+
+ optimistic path change
+ - optimistic change request recorded on some point
+ - when we find it we check
+ is point free
+ is another set request recorded
+ if so check whether we'll be out of the way
+ plot new path for this train
+
+ deadline scheduler for point change and cdu
+
+ for points autochanging
+ lay train an extra 600ms or so
+
+
+commsn between realtime and multiplexer
+ each command produces `ack' or `error'
+ multiplexer counts responses for flow control
+
+multiplex
+ talks to all clients
+ access control
+ message mux/demux incl filtering
+
+
+
+startup state machine
+
+ -
--- /dev/null
+/*
+ * realtime
+ * cdu and point charge control and scheduler
+ */
+
+#include "realtime.h"
+
+void on_pic_charged(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (sta_state <= Sta_Settling) return;
+ /* fixme do something here */
+}
+
+void on_pic_pointed(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (sta_state <= Sta_Settling) return;
+ /* fixme do something here */
+}
#include <stdlib.h>
#include <errno.h>
-#include "hostside.h"
+#include "multiplex.h"
#include "../layout/dlist.h"
struct ClientList clients;
-void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
- oprintf(&ps->cl->ch,"error ");
- ovprintf(&ps->cl->ch,fmt,al);
- owrite(&ps->cl->ch,"\n",1);
-}
-
-const void *any_lookup(ParseState *ps, const void *inf, size_t sz) {
- const char *tname;
-
- for (;
- (tname= *(const char *const*)inf);
- inf= (const char*)inf + sz)
- if (!thiswordstrcmp(ps,tname))
- return inf;
- return 0;
-}
-
-const void *any_needword_lookup(ParseState *ps, const void *infs,
- size_t sz, const char *what) {
- const void *r;
- if (!ps_needword(ps)) return 0;
- r= any_lookup(ps,infs,sz);
- if (!r) { badcmd(ps,"unknown %s",what); return 0; }
- return r;
-}
-
-void ps_callword(ParseState *ps, const CmdInfo *infs, const char *what) {
- const CmdInfo *ci;
- ci= some_needword_lookup(ps,infs,what);
- if (ci) ci->fn(ps,ci);
-}
-
-static void *client_iferr(oop_source *evts, oop_read *cl_read,
- oop_rd_event evt, const char *errmsg, int errnoval,
- const char *data, size_t recsz, void *cl_v) {
- Client *cl= cl_v;
-
- cl->ch.error(&cl->ch, "read",
- oop_rd_errmsg(cl_read, evt,
- errnoval, OOP_RD_STYLE_GETLINE));
- return OOP_CONTINUE;
-}
-
-static void *client_ifok(oop_source *evts, oop_read *cl_read,
- oop_rd_event evt, const char *errmsg, int errnoval,
- const char *data, size_t recsz, void *cl_v) {
- Client *cl= cl_v;
- ParseState ps;
-
- if (evt == OOP_RD_EOF) {
- cl->ch.error(&cl->ch,0,0);
- return OOP_CONTINUE;
- }
-
- if (evt != OOP_RD_OK)
- return client_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
-
- ps.cl= cl;
- ps.remain= data;
- ps_callword(&ps, toplevel_cmds, "command");
- return OOP_CONTINUE;
-}
-
-static void *client_exception(oop_source *evts, int fd,
- oop_event evt, void *cl_v) {
- Client *cl= cl_v;
- cl->ch.error(&cl->ch,"comms error","exception");
- return OOP_CONTINUE;
-}
-
static void new_client(int fd, OutBufferError error,
char *desc, Selector default_selectors) {
Client *cl;
int r;
cl= mmalloc(sizeof(*cl));
-
cl->sel= default_selectors;
- cl->ch.desc= desc;
- cl->ch.fd= fd;
- cl->ch.error= error;
- obc_init(&cl->ch);
-
- events->on_fd(events, fd, OOP_EXCEPTION, client_exception, cl);
-
- cl->rd= oop_rd_new_fd(events, fd, 0,0);
- if (!cl->rd) diee("oop_rd_new_fd");
- r= oop_rd_read(cl->rd, OOP_RD_STYLE_GETLINE, 1024,
- client_ifok, cl,
- client_iferr, cl);
- if (r) diee("oop_rd_read");
+
+ cl->ci.out.desc= desc;
+ cl->ci.out.fd= fd;
+ cl->ci.out.error= error;
+ cmdin_new(&cl->ci);
LIST_LINK_TAIL(clients, cl);
}
--- /dev/null
+/*
+ * realtime & multiplexer
+ * reading and parsing commands from some fd
+ */
+
+#include "daemons.h"
+
+static void *cmdi_exception(oop_source *evts, int fd,
+ oop_event evt, void *cmdi_v) {
+ CommandInput *cmdi= cmdi_v;
+ cmdi->out.error(&cmdi->out, "error by command source",
+ "exceptional condition");
+ return OOP_CONTINUE;
+}
+
+static void *cmdi_iferr(oop_source *evts, oop_read *cl_read,
+ oop_rd_event evt, const char *errmsg, int errnoval,
+ const char *data, size_t recsz, void *cmdi_v) {
+ CommandInput *cmdi= cmdi_v;
+
+ cmdi->out.error(&cmdi->out, "read",
+ oop_rd_errmsg(cl_read, evt,
+ errnoval, OOP_RD_STYLE_GETLINE));
+ return OOP_CONTINUE;
+}
+
+static void *cmdi_ifok(oop_source *evts, oop_read *cl_read,
+ oop_rd_event evt, const char *errmsg, int errnoval,
+ const char *data, size_t recsz, void *cmdi_v) {
+ CommandInput *cmdi= cmdi_v;
+ ParseState ps;
+
+ if (evt == OOP_RD_EOF) {
+ cmdi->out.error(&cmdi->out,0,0);
+ return OOP_CONTINUE;
+ }
+
+ if (evt != OOP_RD_OK)
+ return cmdi_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cmdi_v);
+
+ ps.cl= 0;
+ ps.remain= data;
+ cmdi->doline(&ps, cmdi);
+ return OOP_CONTINUE;
+}
+
+void cmdin_new(CommandInput *cmdi, int readfd) {
+ int r;
+
+ obc_init(&cmdi->out);
+
+ events->on_fd(events, readfd, OOP_EXCEPTION, cmdi_exception, cmdi);
+
+ cmdi->rd= oop_rd_new_fd(events, readfd, 0,0);
+ if (!cmdi->rd) diee("oop_rd_new_fd");
+ r= oop_rd_read(cmdi->rd, OOP_RD_STYLE_GETLINE, 1024,
+ cmdi_ifok, cmdi,
+ cmdi_iferr, cmdi);
+ if (r) diee("oop_rd_read");
+}
#include <assert.h>
#include <string.h>
-#include "hostside.h"
+#include "realtime.h"
#include "auproto-pic.h"
#define NMRA_MAX_NARGS 10
jmp_buf jb;
};
+static void ouack(const CmdInfo *ci) {
+ oprintf(UPO, "ack %s\n", ci->name);
+}
+
unsigned long nmra_argnumber(NmraParseEncodeCaller *pec, int argi) {
return pec->arg[argi];
}
}
free(mrn->name);
free(mrn);
+ ouack(ci);
return;
}
retransmit_queue(&mrn->rn);
else
serial_transmit(&rn->pi);
+ ouack(ci);
}
static void cmd_noop(ParseState *ps, const CmdInfo *ci) {
- oprintf(&ps->cl->ch,"noop successful\n");
+ ouack(ci);
}
-typedef struct PicCmdInfo PicCmdInfo;
-struct PicCmdInfo {
- const char *name;
- Byte opcode;
- int argbits;
-};
-
static void cmd_pic(ParseState *ps, const CmdInfo *ci) {
const PicInsnInfo *pii;
PicInsn pi;
enco_pic_anyinsn(&pi, pii, arg);
}
serial_transmit(&pi);
+ ouack(ci);
}
-
-const CmdInfo toplevel_cmds[]= {
- { "pic", cmd_pic },
- { "nmra", cmd_nmra, },
- { "noop", cmd_noop },
- { 0 }
-};
/*
- * declarations common to simple test program and real controller daemon
+ * declarations common to
+ * - simple test program
+ * - realtime daemon
+ * - multiplexer daemon
*/
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+typedef struct ParseState ParseState;
+typedef struct CmdInfo CmdInfo;
+typedef struct Client Client;
+
+extern const char *progname;
/*---------- types ----------*/
int l;
} PicInsn;
-/*---------- from serialio.c ----------*/
+/*---------- from parseutils.c ----------*/
+
+struct ParseState {
+ Client *cl; /* used only by multiplexer */
+ const char *remain;
+ const char *thisword;
+ int lthisword;
+};
+
+void vbadcmd(ParseState *ps, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void badcmd(ParseState *ps, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+
+int lstrstrcmp(const char *a, int la, const char *b);
+int thiswordstrcmp(ParseState *ps, const char *b);
+
+int ps_word(ParseState *ps);
+int ps_needword(ParseState *ps);
+int ps_needhextoend(ParseState *ps, Byte *dbuf, int *len_io);
+int ps_neednumber(ParseState *ps, long *r, long min, long max, const char *wh);
+int ps_neednoargs(ParseState *ps);
+
+/*---------- macro for table lookups, with help from parseutils.c ----------*/
+
+#define some_lookup(ps, infos) \
+ ((const typeof(infos[0])*) \
+ any_lookup((ps),(infos),sizeof((infos)[0])))
+
+#define some_needword_lookup(ps, infos, what) \
+ ((const typeof(infos[0])*) \
+ any_needword_lookup((ps),(infos),sizeof((infos)[0]),(what)))
+
+const void *any_lookup(ParseState *ps, const void *infos, size_t infosz);
+const void *any_needword_lookup(ParseState *ps, const void *infos,
+ size_t sz, const char *what);
+
+/*---------- from client.c ----------*/
+
+struct CmdInfo {
+ const char *name;
+ void (*fn)(ParseState *ps, const CmdInfo *ci);
+ int xarg;
+};
+
+void stdin_client(void);
+
+extern const CmdInfo toplevel_cmds[]; /* defined in commands.c*/
+
+/*---------- from utils.c ----------*/
void vdie(const char *fmt, int ev, va_list al)
__attribute__((noreturn,format(printf,1,0)));
void diee(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2)));
void diem(void) __attribute__((noreturn));
-void serial_open(const char *device);
-void serial_transmit_now(const Byte *command, int length);
-
void *mmalloc(size_t sz);
char *mstrdupl(const char *s, int l);
char *mstrdup(const char *s);
+void mgettimeofday(struct timeval *tv);
+
+#define massert(x) ((x) ? (void)0 : diem())
+
+/*---------- from serialio.c ----------*/
+
+void serial_open(const char *device);
+void serial_transmit_now(const Byte *command, int length);
extern int serial_fd, serial_fudge_delay;
--- /dev/null
+/*
+ * declarations common to
+ * - realtime daemon
+ * - multiplexer daemon
+ */
+
+#ifndef DAEMONS_H
+#define DAEMONS_H
+
+#include <oop.h>
+#include <oop-read.h>
+
+#include "common.h"
+
+typedef struct CommandInput CommandInput;
+
+/*---------- from obc.c ----------*/
+
+typedef struct OutBuffer OutBuffer;
+typedef struct OutBufferChain OutBufferChain;
+typedef void OutBufferError(OutBufferChain*, const char *e1, const char *e2
+ /* on error: both e1 and e2 non-0. say `$e1: $e2'
+ * on eof: both e1 and e2 =0. */);
+
+struct OutBufferChain {
+ /* set by user: */
+ char *desc;
+ int fd;
+ OutBufferError *error;
+ /* set/used by obc_..., oprintf, etc., only */
+ int done_of_head;
+ struct { OutBuffer *head, *tail; } obs;
+};
+
+void obc_init(OutBufferChain *ch);
+
+void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void oprintf(OutBufferChain *ch, const char *msg, ...)
+ __attribute__((format(printf,2,3)));
+void owrite(OutBufferChain *ch, const char *data, int l);
+void voerror(OutBufferChain *ch, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+
+/*---------- from cmdinput.c ----------*/
+
+typedef void CommandInputCallback(ParseState *ps, CommandInput *cmdi);
+
+struct CommandInput {
+ OutBufferChain out;
+ CommandInputCallback *doline;
+ oop_read *rd;
+};
+
+void cmdin_new(CommandInput *cmdi, int readfd);
+ /* fill in cmdi->out's `set by user' fields before calling cmdin_new,
+ * as cmdin_new will call obc_init and will use cmdi->out->fd. */
+
+/*---------- from eventhelp.c ----------*/
+
+extern oop_source *events;
+
+typedef struct TimeoutEvent TimeoutEvent;
+typedef void TimeoutEventFn(TimeoutEvent*);
+struct TimeoutEvent { /* Undefined Idle Running set by */
+ int running; /* any 0 1 toev_ */
+ int duration; /*ms*/ /* any any[1] any[1] caller */
+ TimeoutEventFn *callback; /* any any valid[2] caller */
+ struct timeval abs; /* any any valid toev_ */
+}; /* [1] duration must be >=0 or -1 when toev_start is called;
+ * [2] callback may be modified while timeout is running;
+ * value used is that prevailing when timeout happens
+ * when the timeout happens, TimeoutEvent's state goes from R to I
+ * and then callback member is read and the function called
+ */
+
+void toev_init(TimeoutEvent*); /* U -> I */
+void toev_start(TimeoutEvent*); /* IR -> R; reads duration */
+ /* if duration is -1 then is same as toev_stop */
+void toev_stop(TimeoutEvent*); /* IR -> I */
+
+#endif /*DAEMONS_H*/
--- /dev/null
+/*
+ * daemons
+ * helpers for event handling
+ */
+
+#include <assert.h>
+#include <limits.h>
+
+#include "daemons.h"
+
+oop_source *events;
+
+static void *toev_callback(oop_source *source, struct timeval tv, void *t_v) {
+ TimeoutEvent *toev= t_v;
+ toev->running= 0;
+ toev->callback(toev);
+ return OOP_CONTINUE;
+}
+
+void toev_init(TimeoutEvent *toev) { toev->running= 0; }
+
+void toev_start(TimeoutEvent *toev) {
+ toev_stop(toev);
+ if (toev->duration==-1) return;
+ toev->running= 1;
+ mgettimeofday(&toev->abs);
+ assert(toev->duration < INT_MAX/1000);
+ toev->abs.tv_usec += toev->duration * 1000;
+ toev->abs.tv_sec += toev->abs.tv_usec / 1000000;
+ toev->abs.tv_usec %= 1000000;
+ events->on_time(events, toev->abs, toev_callback, toev);
+}
+
+void toev_stop(TimeoutEvent *toev) {
+ if (!toev->running) return;
+ toev->running= 0;
+ events->cancel_time(events, toev->abs, toev_callback, toev);
+}
#include <X11/Xlib.h>
#include <X11/xpm.h>
-#include "hostside.h"
+#include "common.h"
#include "../layout/plan-data-format.h"
#include <oop.h>
};
oop_source *events;
+const char *progname= "gui-plan";
static SegmovfeatState **state, *states_head;
static Display *d;
#include "../layout/dlist.h"
#include "hostside.h"
+#include "auproto-pic.h"
-oop_source *events;
FILE *dump_stream= 0;
-
-static void serial_error(OutBufferChain *ch, const char *e1, const char *e2) {
- abort();
-}
-
-static OutBufferChain serial_ochain= { (char*)"serial", -1, serial_error };
-
-static void *serial_exception(oop_source *evts, int fd,
- oop_event evt, void *cl_v) {
- die("serial port - exception");
-}
-
-static void *serial_readable(oop_source *evts, int fd,
- oop_event evt, void *u0) {
- events->cancel_fd(events, serial_fd, OOP_READ);
- return OOP_CONTINUE;
-}
-
-const char *device;
-
-int main(int argc, const char **argv) {
- oop_source_sys *sys_events;
- int r;
-
- device= argv[1];
- if (!device) device= "/dev/ttyS0";
-
- sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
- events= oop_sys_source(sys_events); assert(events);
-
- serial_open(device);
- r= oop_fd_nonblock(serial_fd, 1); if (r) diee("nonblock(serial_fd,1)");
- serial_ochain.fd= serial_fd;
-
- stdin_client();
-
- events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0);
- events->on_fd(events, serial_fd, OOP_EXCEPTION, serial_exception, 0);
- oop_sys_run(sys_events);
- abort();
-}
/*
+ * OBSOLETE FILE
* declarations for hostside controller daemon
*/
#include "common.h"
-#include <oop.h>
-#include <oop-read.h>
-
-typedef struct Client Client;
-typedef struct ParseState ParseState;
-typedef struct CmdInfo CmdInfo;
-typedef struct RetransmitNode RetransmitNode;
-
-/*---------- from obc.c ----------*/
-
-typedef struct OutBuffer OutBuffer;
-typedef struct OutBufferChain OutBufferChain;
-typedef void OutBufferError(OutBufferChain*, const char *e1, const char *e2);
-
-struct OutBufferChain {
- /* set by user: */
- char *desc;
- int fd;
- OutBufferError *error;
- /* set/used by obc_..., oprintf, etc., only */
- int done_of_head;
- struct { OutBuffer *head, *tail; } obs;
-};
-
-void obc_init(OutBufferChain *ch);
-
-void ovprintf(OutBufferChain *ch, const char *fmt, va_list al)
- __attribute__((format(printf,2,0)));
-void oprintf(OutBufferChain *ch, const char *msg, ...)
- __attribute__((format(printf,2,3)));
-void owrite(OutBufferChain *ch, const char *data, int l);
-
-/*---------- from output.c ----------*/
-
-typedef unsigned long Selector;
-#include "selectors.h"
-
-void oovprintf(Selector sel, const char *fmt, va_list al)
- __attribute__((format(printf,2,0)));
-void ooprintf(Selector sel, const char *fmt, ...)
- __attribute__((format(printf,2,3)));
-void oowrite(Selector sel, const char *data, int l);
-
-void serial_transmit(const PicInsn *pi);
-
-void output_hex(Selector sel, const char *work,
- const Byte *command, int length);
-
/*---------- from protocol.c ----------*/
typedef struct OrdinaryPicMessage OrdinaryPicMessage;
int operand_bits; /* 0: no operand. >=7, insn is a 2-byte message */
};
-/*---------- from hostside.c ----------*/
-
-extern oop_source *events;
-
-/*---------- from client.c ----------*/
-
-struct ClientList { Client *head, *tail; };
-extern struct ClientList clients;
-
-struct Client {
- OutBufferChain ch;
- Client *back, *next;
- Selector sel;
- oop_read *rd;
-};
-
-struct ParseState {
- Client *cl;
- const char *remain;
- const char *thisword;
- int lthisword;
-};
-
-struct CmdInfo {
- const char *name;
- void (*fn)(ParseState *ps, const CmdInfo *ci);
- int xarg;
-};
-
-int lstrstrcmp(const char *a, int la, const char *b);
-int thiswordstrcmp(ParseState *ps, const char *b);
-
-int ps_word(ParseState *ps);
-int ps_needword(ParseState *ps);
-int ps_needhextoend(ParseState *ps, Byte *dbuf, int *len_io);
-void ps_callword(ParseState *ps, const CmdInfo *infs, const char *what);
-int ps_neednumber(ParseState *ps, long *r, long min, long max, const char *wh);
-int ps_neednoargs(ParseState *ps);
-
-void vbadcmd(ParseState *ps, const char *fmt, va_list al)
- __attribute__((format(printf,2,0)));
-void badcmd(ParseState *ps, const char *fmt, ...)
- __attribute__((format(printf,2,3)));
-
-void stdin_client(void);
-
-extern const CmdInfo toplevel_cmds[]; /* defined in commands.c*/
-
/*---------- from retransmit.c ----------*/
struct RetransmitNode {
void retransmit_queue(RetransmitNode *rn);
void retransmit_cancel(RetransmitNode *rn);
-/*---------- macro for table lookups, with help from client.c ----------*/
-
-#define some_lookup(ps, infos) \
- ((const typeof(infos[0])*) \
- any_lookup((ps),(infos),sizeof((infos)[0])))
-
-#define some_needword_lookup(ps, infos, what) \
- ((const typeof(infos[0])*) \
- any_needword_lookup((ps),(infos),sizeof((infos)[0]),(what)))
-
-const void *any_lookup(ParseState *ps, const void *infos, size_t infosz);
-const void *any_needword_lookup(ParseState *ps, const void *infos,
- size_t sz, const char *what);
-
-#endif /*HOSTSIDE_H*/
+#endif
#include "common.h"
+const char *progname= "hostside-old";
static FILE *dump_stream= 0;
static int repeat_delay= -1, iterations= -1;
--- /dev/null
+void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
+ voerror(&ps->ci->out,fmt,al);
+}
+
--- /dev/null
+/*
+ * multiplexer daemon
+ * declarations
+ */
+
+#ifndef MULTIPLEX_H
+#define MULTIPLEX_H
+
+#include "daemons.h"
+
+/*---------- from output.c ----------*/
+
+typedef unsigned long Selector;
+#include "selectors.h"
+
+void sovprintf(Selector sel, const char *fmt, va_list al)
+ __attribute__((format(printf,2,0)));
+void soprintf(Selector sel, const char *fmt, ...)
+ __attribute__((format(printf,2,3)));
+void sowrite(Selector sel, const char *data, int l);
+
+void serial_transmit(const PicInsn *pi);
+
+void output_hex(Selector sel, const char *work,
+ const Byte *command, int length);
+
+
+
+
+ unredacted
+
+struct ClientList { Client *head, *tail; };
+extern struct ClientList clients;
+
+struct Client {
+ CommandInput ci;
+ Client *back, *next;
+ Selector sel;
+};
+
+
+
+
+#endif /*MULTIPLEX_H*/
-/**/
+/*
+ * daemons
+ * output buffer chains
+ */
#include <assert.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
-#include "hostside.h"
+#include "daemons.h"
#include "../layout/dlist.h"
struct OutBuffer {
}
void obc_init(OutBufferChain *ch) {
+ int r;
ch->done_of_head= 0;
+ r= oop_fd_nonblock(ch->fd, 1);
+ if (r) diee("nonblock(OutBufferChain->fd,1)");
LIST_INIT(ch->obs);
}
va_end(al);
}
+void voerror(OutBufferChain *ch, const char *fmt, va_list al) {
+ oprintf(ch,"error ");
+ ovprintf(ch,fmt,al);
+ owrite(ch,"\n",1);
+}
+
void owrite(OutBufferChain *ch, const char *data, int l) {
OutBuffer *ob;
ob= mmalloc(sizeof(*ob));
-/*
- * transmissions to clients
- */
-
-#include <string.h>
-#include <stdarg.h>
-
-#include "hostside.h"
-#include "auproto-pic.h"
-
-#define FOR_OOS(s) do{ \
- Client *cl, *next_cl; \
- for (cl= clients.head; \
- cl; \
- cl= next_cl) { \
- OutBufferChain *ch= &cl->ch; \
- next_cl= cl->next; \
- if (!(sel & cl->sel)) continue; \
- s; \
- } \
- }while(0)
-
-void oovprintf(Selector sel, const char *fmt, va_list al) {
- FOR_OOS( ovprintf(ch, fmt, al) );
-}
-
-void ooprintf(Selector sel, const char *fmt, ...)
- { va_list al; va_start(al,fmt); oovprintf(sel,fmt,al); va_end(al); }
-
-void oowrite(Selector sel, const char *data, int l) {
- FOR_OOS( owrite(ch, data, l) );
-}
-
-void output_hex(Selector sel, const char *word,
- const Byte *command, int length) {
- ooprintf(sel, "%s", word);
- while (length) {
- ooprintf(sel, " %02x", *command++);
- length--;
- }
- ooprintf(sel, "\n");
-}
-
-void serial_transmit(const PicInsn *pi) {
- const PicInsnInfo *pii;
- unsigned val;
-
- pii= pi->l > 0 ? lookup_byopcode(pi->d[0], pic_command_infos) : 0;
-
- if (pii) {
- val= pi->d[0];
- if (pii->argbits <= 6) {
- if (pi->l != 1) pii= 0;
- } else {
- if (pi->l == 2) { val <<= 8; val |= pi->d[1]; }
- else pii= 0;
- }
- }
-
- if (!pii)
- ooprintf(sel_picio, "picio out unknown\n");
- else if (!pii->argbits)
- ooprintf(sel_picio, "picio out %s\n", pii->name);
- else
- ooprintf(sel_picio, "picio out %s %u\n", pii->name,
- val & ((1u << pii->argbits) - 1));
-
- output_hex(sel_picioh, "picioh out", pi->d, pi->l);
- serial_transmit_now(pi->d, pi->l);
-}
$v{dname}= $dname;
$v{cname}= $cname;
$v{cnameyn}= $cname.$yval;
+ $v{cnameynu}= uc($cname.$yval);
$v{opcode}= b2xh($opcode, 0);
$v{opcodeyn}= b2xh($opcode, $ybit * $yval);
$v{opcodemask}= b2xh($opcodemask, 0);
-/**/
+/*
+ * common
+ * utilities for helping parsing
+ */
#include <stdarg.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
-#include "hostside.h"
+#include "common.h"
void badcmd(ParseState *ps, const char *fmt, ...) {
va_list al;
return 1;
}
+
+const void *any_lookup(ParseState *ps, const void *inf, size_t sz) {
+ const char *tname;
+
+ for (;
+ (tname= *(const char *const*)inf);
+ inf= (const char*)inf + sz)
+ if (!thiswordstrcmp(ps,tname))
+ return inf;
+ return 0;
+}
+
+const void *any_needword_lookup(ParseState *ps, const void *infs,
+ size_t sz, const char *what) {
+ const void *r;
+ if (!ps_needword(ps)) return 0;
+ r= any_lookup(ps,infs,sz);
+ if (!r) { badcmd(ps,"unknown %s",what); return 0; }
+ return r;
+}
+
int lstrstrcmp(const char *a, int la, const char *b) {
int lb, minl, r;
--- /dev/null
+/*
+ * main program for realtime control
+ */
+
+#include "realtime.h"
+
+const char *progname= "realtime";
+
+/*---------- global variables ----------*/
+
+CommandInput cmdi;
+
+static const char *device;
+
+/*---------- general event handling ----------*/
+
+static void comms_error(const char *ch, const char *e1,
+ const char *e2 /* may be 0 */) {
+ if (!e1 && !e2) e1= "end of file";
+ die("communications error: %s: %s%s%s", ch, e1, e2?": ":"", e2?e2:"");
+}
+
+static void *read_exception(oop_source *evts, int fd,
+ oop_event evt, void *cl_v) {
+ const char *ch;
+ char bufc;
+ int r;
+
+ ch= (fd==UPO->fd ? UPO->desc :
+ fd==serial_fd ? "serial port" :
+ 0);
+
+ r= read(fd, &bufc, 1);
+ if (r==-1) comms_error(ch, "read error", strerror(errno));
+ else if (r==0) comms_error(ch, "reports exception, reads EOF", 0);
+ else comms_error(ch, "reports exception, but readable", 0);
+
+ return OOP_CONTINUE;
+}
+
+/*---------- command channel handling (oop_read, obc) ----------*/
+
+static void command_doline(ParseState *ps, CommandInput *cmdi) {
+ const CmdInfo *ci;
+ ci= some_needword_lookup(ps, toplevel_cmds, "command");
+ if (ci) ci->fn(ps,ci);
+}
+
+void oupicio(const char *dirn, const PicInsnInfo *pii, int objnum) {
+ if (!pii->argbits)
+ oprintf(UPO, "picio %s %s\n", dirn, pii->name);
+ else
+ oprintf(UPO, "picio %s %s %u\n", dirn, pii->name, objnum);
+}
+
+void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
+ voerror(UPO,fmt,al);
+}
+
+static void obc_error(OutBufferChain *ch, const char *e1, const char *e2) {
+ comms_error(ch->desc, e1, e2);
+}
+
+void ouhex(const char *word, const Byte *command, int length) {
+ oprintf(UPO, "%s", word);
+ while (length) {
+ oprintf(UPO, " %02x", *command++);
+ length--;
+ }
+ oprintf(UPO, "\n");
+}
+
+/*---------- serial input (via oop) ----------*/
+
+static PicInsn serial_buf;
+
+static void *serial_readable(oop_source *evts, int fd,
+ oop_event evt, void *u0) {
+ int r, buf_used;
+
+ r= read(serial_fd, &serial_buf.d, sizeof(serial_buf.d) - serial_buf.l);
+ if (r==0) die("serial port - eof");
+ if (r==-1) {
+ if (errno == EWOULDBLOCK || errno == EINTR)
+ return OOP_CONTINUE;
+ diee("serial port - read error");
+ }
+ assert(r>0);
+
+ buf_used= serial_buf.l;
+ buf_used += r;
+
+ for (;;) {
+ serial_buf.l= buf_used;
+ serial_moredata(&serial_buf);
+ if (!serial_buf.l) break;
+ buf_used -= serial_buf.l;
+ memmove(serial_buf.d, serial_buf.d + serial_buf.l, buf_used);
+ if (!buf_used) break;
+ }
+ serial_buf.l= buf_used;
+ return OOP_CONTINUE;
+}
+
+/*---------- serial port output (not via liboop) ----------*/
+
+void serial_transmit(const PicInsn *pi) {
+ const PicInsnInfo *pii;
+ int objnum;
+
+ picinsn_decode(pi, pic_command_infos, &pii, &objnum);
+
+ if (!pii)
+ oprintf(UPO, "picio out unknown\n");
+ else
+ oupicio("out",pii,objnum);
+
+ ouhex("picioh out", pi->d, pi->l);
+
+ /* note that the serial port is still in nonblocking mode. if
+ * we ever buffer up far enough that the kernel wants to make us
+ * block, we should die! */
+ serial_transmit_now(pi->d, pi->l);
+}
+
+/*---------- initialisation ----------*/
+
+int main(int argc, const char **argv) {
+ oop_source_sys *sys_events;
+ int r;
+
+ device= argv[1];
+ if (!device) device= "/dev/ttyS0";
+
+ sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
+ events= oop_sys_source(sys_events); massert(events);
+
+ cmdi.out.desc= (char*)"command";
+ cmdi.out.fd= 1;
+ cmdi.out.error= obc_error;
+ cmdi.doline= command_doline;
+
+ cmdin_new(&cmdi, 0);
+
+ serial_open(device);
+ r= oop_fd_nonblock(serial_fd, 1); if (r) diee("nonblock(serial_fd,1)");
+
+ events->on_fd(events, serial_fd, OOP_READ, serial_readable, 0);
+ events->on_fd(events, serial_fd, OOP_EXCEPTION, read_exception, 0);
+
+ sta_startup();
+ oop_sys_run(sys_events);
+ abort();
+}
--- /dev/null
+/*
+ * declarations for multiplexer daemon
+ */
+
+#ifndef REALTIME_H
+#define REALTIME_H
+
+#include "daemons.h"
+#include "auproto-pic.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+typedef struct RetransmitNode RetransmitNode;
+
+extern CommandInput cmdi;
+
+typedef enum { /* sta_toev ping_toev */
+ Sta_Flush, /* R 300 I ? */
+ Sta_Off, /* I ? I ? */
+ Sta_Ping, /* I ? I ? */
+ Sta_Fault, /* I ? R set */
+ Sta_Settling, /* I ? R set */
+ Sta_Resolving, /* I ? R set */
+ Sta_Run /* I ? R set */
+} StartupState;
+
+#define UPO (&(cmdi.out))
+
+void oupicio(const char *dirn, const PicInsnInfo *pii, int objnum);
+void ouhex(const char *word, const Byte *command, int length);
+
+void serial_moredata(PicInsn *buf);
+void serial_transmit(const PicInsn *pi);
+
+void sta_startup(void);
+extern StartupState sta_state;
+
+void abandon_run(void);
+
+#endif /*REALTIME_H*/
#!/usr/bin/perl
$bit= 1;
+printf "/* autogenerated - do not edit */\n" or die $!;
foreach $f (qw(
picio
picioh
+ picdebug
)) {
printf "#define sel_%-10s 0x%08lxLU\n", $f, $bit;
$bit <<= 1;
--- /dev/null
+/*
+ * mulitplexer daemon
+ * transmissions to clients of their selected messages
+ */
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "multiplex.h"
+#include "auproto-pic.h"
+
+#define FOR_CLS(s) do{ \
+ Client *cl, *next_cl; \
+ for (cl= clients.head; \
+ cl; \
+ cl= next_cl) { \
+ OutBufferChain *ch= &cl->ch; \
+ next_cl= cl->next; \
+ if (!(sel & cl->sel)) continue; \
+ s; \
+ } \
+ }while(0)
+
+void sovprintf(Selector sel, const char *fmt, va_list al) {
+ FOR_CLS( ovprintf(ch, fmt, al) );
+}
+
+void soprintf(Selector sel, const char *fmt, ...)
+ { va_list al; va_start(al,fmt); sovprintf(sel,fmt,al); va_end(al); }
+
+void sowrite(Selector sel, const char *data, int l) {
+ FOR_CLS( owrite(ch, data, l) );
+}
/*
+ * common
* general serial i/o and system interface etc.
*/
* and related functions
*/
-#include "hostside.h"
+#include <assert.h>
+
+#include "common.h"
#include "auproto-pic.h"
-extern void enco_pic_anyinsn(PicInsn *out, const PicInsnInfo *pii,
- int objnum) {
+extern void enco_pic_any(PicInsn *out, int opcode, int argbits, int objnum) {
unsigned long as= objnum;
int i;
- out->l= 1 + pii->argbits/7;
+ assert(!(as & (~0UL << argbits)));
+ out->l= 1 + argbits/7;
for (i= out->l - 1;
i >= 0;
i--, as >>= 7)
out->d[i]= (as & 0x07fUL) | 0x080UL;
out->d[out->l - 1] &= ~0x080UL;
- out->d[0] |= pii->opcode;
+ out->d[0] |= opcode;
}
-#if 0
-const char *pi_getarg(const PicInsn *pi, const PicInsnInfo *pi, long *a_r) {
-
-const PicInsn *pi, long *arg_o,
-#endif
-
+#define C ,
+#define ENCO(w, xa, opcode, argbits, objnum) \
+ extern void enco_pic_##w(PicInsn *out xa) { \
+ return enco_pic_any(out, opcode, argbits, objnum); \
+ }
+
+ENCO(pii, C const PicInsnInfo *pii C int objn,pii->opcode,pii->argbits,objn)
+ENCO(@cnameyn@, , @opcodeyn@, 0,0) @h2p@ @arglentf=0@
+ENCO(@cnameyn@, C int objnum, @opcodeyn@, @arglen@,objnum) @h2p@ @arglentf=1@
+
const PicInsnInfo *lookup_byopcode(Byte byte0, const PicInsnInfo *table) {
const PicInsnInfo *pi;
for (pi= table;
return 0;
}
+void picinsn_decode(const PicInsn *pi, const PicInsnInfo *table,
+ const PicInsnInfo **pii_r, int *objnum_r) {
+ const PicInsnInfo *pii;
+ unsigned val= 0;
+
+ pii= pi->l > 0 ? lookup_byopcode(pi->d[0], table) : 0;
+
+ if (pii) {
+ val= pi->d[0];
+ if (pii->argbits <= 6) {
+ if (pi->l != 1) pii= 0;
+ } else {
+ if (pi->l == 2) { val <<= 8; val |= pi->d[1]; }
+ else pii= 0;
+ }
+ }
+
+ if (objnum_r && pii) *objnum_r= val & ((1u << pii->argbits) - 1);
+ *pii_r= pii;
+}
+
const PicInsnInfo pic_command_infos[]= {
- { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@ }, @h2p@
+ { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@, 0 }, @h2p@
{ 0 }
};
const PicInsnInfo pic_reply_infos[]= {
- { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@ }, @p2h@
+ { "@cnameyn@", @opcodeyn@, @opcodemaskyn@, @arglen@, on_pic_@cnameyn@ },@p2h@
{ 0 }
};
#define AUPROTO_PIC_H
typedef struct PicInsnInfo PicInsnInfo;
+typedef void PicInputFn(const PicInsnInfo *pii, const PicInsn *pi, int objnum);
-void enco_pic_@cname@(PicInsn *out); @h2p@ @arglentf=0@
-void enco_pic_@cname@(PicInsn *out, int objum); @h2p@ @arglentf=1@
-
-void on_pic_@cnameyn@(void); @p2h@ @arglentf=0@
-void on_pic_@cnameyn@(int objnum); @p2h@ @arglentf=1@
+void enco_pic_@cnameyn@(PicInsn *out); @h2p@ @arglentf=0@
+void enco_pic_@cnameyn@(PicInsn *out, int objum); @h2p@ @arglentf=1@
+PicInputFn on_pic_@cnameyn@; @p2h@
+#define PICMSG_@cnameynu@ @opcodeyn@
+#define PICMSG_@cnameynu@_M @opcodemaskyn@
+#define PICMSG_@cnameynu@_P(v) (((v) & @opcodemaskyn@) == @opcodeyn@)
extern void enco_pic_polarity_begin(PicInsn *out);
extern void enco_pic_polarity_setbit(PicInsn *out, int objnum);
-extern void on_pic_debug(int ch);
-extern void enco_pic_anyinsn(PicInsn *out, const PicInsnInfo *pii, int objnum);
+extern void enco_pic_pii(PicInsn *out, const PicInsnInfo *pii, int objnum);
+extern void enco_pic_any(PicInsn *out, int opcode, int argbits, int objnum);
const PicInsnInfo *lookup_byopcode(Byte byte0, const PicInsnInfo *table);
+void picinsn_decode(const PicInsn *pi, const PicInsnInfo *table,
+ const PicInsnInfo **pii_r, int *objnum_r);
+void oopicio(const char *dirn, const PicInsnInfo *pii, int objnum);
struct PicInsnInfo {
const char *name;
Byte opcode, mask;
int argbits;
+ PicInputFn *input_fn;
};
extern const PicInsnInfo pic_command_infos[], pic_reply_infos[];
--- /dev/null
+/*
+ * realtime
+ * startup state machine
+ */
+
+#include "realtime.h"
+
+StartupState sta_state;
+
+static TimeoutEvent sta_toev;
+static TimeoutEvent ping_toev;
+
+static int ping_seq;
+static PicInsn piob;
+static void sta_goto(StartupState new_state);
+
+static void timedout_onward(TimeoutEvent *toev) {
+ assert(sta_state != Sta_Run);
+ sta_goto(sta_state == Sta_Flush ? Sta_Ping : sta_state + 1);
+}
+
+static void timedout_ping(TimeoutEvent *toev) {
+ assert(sta_state >= Sta_Ping);
+ sta_goto(Sta_Off);
+}
+
+static void timefor_ping(TimeoutEvent *toev) {
+ enco_pic_ping(&piob, ping_seq);
+ serial_transmit(&piob);
+ ping_toev.callback= timedout_ping;
+ toev_start(&ping_toev);
+}
+
+static void initial_ping(void) {
+ struct timeval now;
+
+ mgettimeofday(&now);
+ ping_seq= (now.tv_sec & 0x1fU) << 5; /* bottom 5bi of secs: period 32s */
+ ping_seq |= (now.tv_usec >> 15); /* top 5bi of 20bi us: res.~2^15us */
+ ping_toev.duration= 300;
+ timefor_ping(0);
+}
+
+void sta_startup(void) { sta_goto(Sta_Flush); }
+
+static void sta_goto(StartupState new_state) {
+ toev_stop(&sta_toev);
+ sta_toev.callback= timedout_onward;
+ sta_toev.duration= -1;
+
+ if (new_state < Sta_Ping) {
+ toev_stop(&ping_toev);
+ } else if (new_state == Sta_Ping) {
+ initial_ping();
+ } else {
+ assert(sta_state >= Sta_Ping);
+ }
+
+ switch (new_state) {
+ case Sta_Flush: sta_toev.duration= 300; break;
+ case Sta_Off: break;
+ case Sta_Ping: break;
+ case Sta_Fault: break;
+ case Sta_Settling: sta_toev.duration= 2000; break;
+ case Sta_Resolving: sta_toev.duration= 500; break;
+ case Sta_Run: break;
+ }
+
+ piob.l= 0;
+ switch (new_state) {
+ case Sta_Flush: break;
+ case Sta_Off: if (sta_state > Sta_Ping) enco_pic_off(&piob); break;
+ 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: break;
+ }
+ if (piob.l) serial_transmit(&piob);
+
+ toev_start(&sta_toev);
+ sta_state= new_state;
+
+ /* notify various people: */
+ oprintf(UPO, "stastate %d\n", sta_state);
+ /* ... add others here. */
+}
+
+void serial_moredata(PicInsn *buf) {
+ const PicInsnInfo *pii;
+ int objnum;
+ Byte *ep;
+
+ /* Called when more data is received from PICs.
+ * On entry, buf->l is amount of data available.
+ * Does one of the following:
+ * - determines that there is no complete message; sets buf->l = 0
+ * - finds and handles one PicInsn message, sets buf->l = message length
+ * - handles some series of bytes structured some other way,
+ * sets buf->l to the numer of bytes handled.
+ */
+ assert(buf->l > 0);
+
+ if (sta_state == Sta_Flush) {
+ toev_start(&sta_toev);
+ ouhex("picioh in junk", buf->d, buf->l);
+ return; /* junk absolutely everything */
+ }
+ if (PICMSG_AAARGH_P(buf->d[0])) {
+ ouhex("picioh in aaargh", buf->d, buf->l);
+ die("PIC sent us AAARGH!");
+ }
+ if (PICMSG_HELLO_P(buf->d[0])) {
+ ouhex("picioh in hello", buf->d, 1);
+ abandon_run();
+ sta_goto(Sta_Flush);
+ buf->l= 1;
+ return;
+ }
+ if (sta_state == Sta_Off) {
+ ouhex("picioh in off", buf->d, 1);
+ buf->l= 1;
+ return;
+ }
+
+ assert(sta_state >= Sta_Ping);
+ /* So, we are expecting properly formed messages. */
+
+ for (ep= buf->d; ep < buf->d + buf->l; ep++)
+ if (!(*ep & 0x80u))
+ goto found_end;
+
+ if (buf->l == sizeof(buf->d)) {
+ ouhex("picioh in toolong", buf->d, buf->l);
+ die("PIC sent packet too long");
+ }
+ buf->l= 0; /* message not yet finished, so consume nothing */
+ return;
+
+ found_end:
+ /* Aha! */
+ buf->l= ep - buf->d + 1;
+ ouhex("picioh in msg", buf->d, buf->l);
+ picinsn_decode(buf, pic_reply_infos, &pii, &objnum);
+ if (!pii) { oprintf(UPO, "picio in unknown\n"); return; }
+ oupicio("in",pii,objnum);
+ pii->input_fn(pii,buf,objnum);
+}
+
+void on_pic_pong(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (objnum != ping_seq)
+ die("PIC sent wrong ping response (0x%x, wanted 0x%x)", objnum, ping_seq);
+
+ if (sta_state == Sta_Ping) {
+ sta_goto(Sta_Settling);
+ } else {
+ ping_toev.duration= 1000;
+ ping_toev.callback= timefor_ping;
+ toev_start(&ping_toev);
+ }
+}
+
+void on_pic_fixed(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (sta_state >= Sta_Resolving) die("PIC sent unexpected FIXED");
+ if (sta_state == Sta_Fault) sta_goto(Sta_Settling);
+}
+
+void on_pic_fault(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (sta_state <= Sta_Ping) return;
+ if (sta_state == Sta_Fault) die("PIC sent two FAULTs");
+ sta_goto(Sta_Fault);
+}
+
+void on_pic_wtimeout(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ if (sta_state <= Sta_Settling) return;
+ if (sta_state == Sta_Resolving) die("PIC sent WTIMEOUT in Resolving");
+ oprintf(UPO, "warning watchdog \"PIC watchdog timer triggered\"\n");
+}
+
+void on_pic_hello(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
+ { abort(); }
+void on_pic_aaargh(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
+ { abort(); }
+
+/*---------- fixme move these to where they want to go ----------*/
+
+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?) */
+}
+
+void on_pic_detect0(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+}
+
+void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+ /* fixme do something here */
+}
+
+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 }
+};
-/**/
+/*
+ * common
+ * general utility functions
+ */
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
-#include "hostside.h"
+#include "common.h"
void vdie(const char *fmt, int ev, va_list al) {
+ fprintf(stderr, "%s: fatal: ", progname);
vfprintf(stderr,fmt,al);
if (ev) fprintf(stderr,": %s",strerror(ev));
fputc('\n',stderr);
}
char *mstrdup(const char *s) { return mstrdupl(s,strlen(s)); }
+
+void mgettimeofday(struct timeval *tv) {
+ int r;
+ r= gettimeofday(tv,0);
+ if (r) diee("gettimeofday failed");
+}
sub segment_used__len ($$) {
my ($used,$pt) = @_;
- $segused_incurrent++;
+ $segused_incurrent += $used;
return if @segments < 3;
$segments[1] -= $used;