From: ian Date: Sat, 6 May 2006 12:23:37 +0000 (+0000) Subject: transplant branch hostside-wip-2006-01-01 to hostside-wip-2006-05-06; cvs up -j branc... X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=3cbdb3f2de55ac605e92df82a7aa4af2e5126b6b;p=trains.git transplant branch hostside-wip-2006-01-01 to hostside-wip-2006-05-06; cvs up -j branchpoint-hostside-wip-2006-01-01 -j branchend-hostside-wip-2006-01-01 --- diff --git a/cebpic/README.protocol b/cebpic/README.protocol index db21ad6..4de741e 100644 --- a/cebpic/README.protocol +++ b/cebpic/README.protocol @@ -62,7 +62,7 @@ From PIC to host: < 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 diff --git a/hostside/.cvsignore b/hostside/.cvsignore index e285fdd..7536abf 100644 --- a/hostside/.cvsignore +++ b/hostside/.cvsignore @@ -1,5 +1,6 @@ -hostside +realtime hostside-old +hostside safety t layoutinfo.h diff --git a/hostside/Makefile b/hostside/Makefile index a56c460..8650c61 100644 --- a/hostside/Makefile +++ b/hostside/Makefile @@ -1,12 +1,11 @@ # -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: @@ -15,10 +14,18 @@ all: $(TARGETS) 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 @@ -29,9 +36,8 @@ gui-plan-bot: gui-plan-%: gui-plan.o utils.o parseutils.o \ __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 @@ -40,11 +46,15 @@ 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 diff --git a/hostside/Structure b/hostside/Structure new file mode 100644 index 0000000..8694d1b --- /dev/null +++ b/hostside/Structure @@ -0,0 +1,52 @@ +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 + + - diff --git a/hostside/cdumgr.c b/hostside/cdumgr.c new file mode 100644 index 0000000..089d954 --- /dev/null +++ b/hostside/cdumgr.c @@ -0,0 +1,16 @@ +/* + * 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 */ +} diff --git a/hostside/client.c b/hostside/client.c index 989f782..8b3a24a 100644 --- a/hostside/client.c +++ b/hostside/client.c @@ -5,102 +5,23 @@ #include #include -#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); } diff --git a/hostside/cmdinput.c b/hostside/cmdinput.c new file mode 100644 index 0000000..51cec79 --- /dev/null +++ b/hostside/cmdinput.c @@ -0,0 +1,60 @@ +/* + * 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"); +} diff --git a/hostside/commands.c b/hostside/commands.c index b14ed03..2dccc25 100644 --- a/hostside/commands.c +++ b/hostside/commands.c @@ -6,7 +6,7 @@ #include #include -#include "hostside.h" +#include "realtime.h" #include "auproto-pic.h" #define NMRA_MAX_NARGS 10 @@ -33,6 +33,10 @@ struct NmraParseEncodeCaller { 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]; } @@ -130,6 +134,7 @@ static void cmd_nmra(ParseState *ps, const CmdInfo *ci) { } free(mrn->name); free(mrn); + ouack(ci); return; } @@ -145,19 +150,13 @@ static void cmd_nmra(ParseState *ps, const CmdInfo *ci) { 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; @@ -183,11 +182,5 @@ static void cmd_pic(ParseState *ps, const CmdInfo *ci) { 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 } -}; diff --git a/hostside/common.h b/hostside/common.h index a1b163d..7354b09 100644 --- a/hostside/common.h +++ b/hostside/common.h @@ -1,11 +1,22 @@ /* - * 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 +#include +#include + +typedef struct ParseState ParseState; +typedef struct CmdInfo CmdInfo; +typedef struct Client Client; + +extern const char *progname; /*---------- types ----------*/ @@ -24,7 +35,56 @@ typedef struct PicInsn { 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))); @@ -32,12 +92,17 @@ void die(const char *fmt, ...) __attribute__((noreturn,format(printf,1,2))); 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; diff --git a/hostside/daemons.h b/hostside/daemons.h new file mode 100644 index 0000000..dbe8c1c --- /dev/null +++ b/hostside/daemons.h @@ -0,0 +1,82 @@ +/* + * declarations common to + * - realtime daemon + * - multiplexer daemon + */ + +#ifndef DAEMONS_H +#define DAEMONS_H + +#include +#include + +#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*/ diff --git a/hostside/eventhelp.c b/hostside/eventhelp.c new file mode 100644 index 0000000..4471240 --- /dev/null +++ b/hostside/eventhelp.c @@ -0,0 +1,38 @@ +/* + * daemons + * helpers for event handling + */ + +#include +#include + +#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); +} diff --git a/hostside/gui-plan.c b/hostside/gui-plan.c index 1df8766..3f40f89 100644 --- a/hostside/gui-plan.c +++ b/hostside/gui-plan.c @@ -15,7 +15,7 @@ #include #include -#include "hostside.h" +#include "common.h" #include "../layout/plan-data-format.h" #include @@ -44,6 +44,7 @@ struct SegmovfeatState { }; oop_source *events; +const char *progname= "gui-plan"; static SegmovfeatState **state, *states_head; static Display *d; diff --git a/hostside/hostside.c b/hostside/hostside.c index 6b92d86..813cab3 100644 --- a/hostside/hostside.c +++ b/hostside/hostside.c @@ -8,47 +8,6 @@ #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(); -} diff --git a/hostside/hostside.h b/hostside/hostside.h index db981f5..b6fbdc6 100644 --- a/hostside/hostside.h +++ b/hostside/hostside.h @@ -1,4 +1,5 @@ /* + * OBSOLETE FILE * declarations for hostside controller daemon */ @@ -7,54 +8,6 @@ #include "common.h" -#include -#include - -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; @@ -64,54 +17,6 @@ struct 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 { @@ -123,18 +28,4 @@ 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 diff --git a/hostside/main.c b/hostside/main.c index 7f2cc6d..378c173 100644 --- a/hostside/main.c +++ b/hostside/main.c @@ -19,6 +19,7 @@ #include "common.h" +const char *progname= "hostside-old"; static FILE *dump_stream= 0; static int repeat_delay= -1, iterations= -1; diff --git a/hostside/multiplex.c b/hostside/multiplex.c new file mode 100644 index 0000000..1d30794 --- /dev/null +++ b/hostside/multiplex.c @@ -0,0 +1,4 @@ +void vbadcmd(ParseState *ps, const char *fmt, va_list al) { + voerror(&ps->ci->out,fmt,al); +} + diff --git a/hostside/multiplex.h b/hostside/multiplex.h new file mode 100644 index 0000000..0c66f2c --- /dev/null +++ b/hostside/multiplex.h @@ -0,0 +1,44 @@ +/* + * 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*/ diff --git a/hostside/obc.c b/hostside/obc.c index bc272de..7154d83 100644 --- a/hostside/obc.c +++ b/hostside/obc.c @@ -1,4 +1,7 @@ -/**/ +/* + * daemons + * output buffer chains + */ #include #include @@ -6,7 +9,7 @@ #include #include -#include "hostside.h" +#include "daemons.h" #include "../layout/dlist.h" struct OutBuffer { @@ -56,7 +59,10 @@ static void addlink(OutBufferChain *ch, OutBuffer *ob) { } 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); } @@ -75,6 +81,12 @@ void oprintf(OutBufferChain *ch, const char *msg, ...) { 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)); diff --git a/hostside/output.c b/hostside/output.c index b432222..e69de29 100644 --- a/hostside/output.c +++ b/hostside/output.c @@ -1,70 +0,0 @@ -/* - * transmissions to clients - */ - -#include -#include - -#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); -} diff --git a/hostside/parse-proto-spec b/hostside/parse-proto-spec index 1698eba..5564ca2 100755 --- a/hostside/parse-proto-spec +++ b/hostside/parse-proto-spec @@ -93,6 +93,7 @@ sub process_line () { $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); diff --git a/hostside/parseutils.c b/hostside/parseutils.c index 99e1385..7cb962a 100644 --- a/hostside/parseutils.c +++ b/hostside/parseutils.c @@ -1,11 +1,14 @@ -/**/ +/* + * common + * utilities for helping parsing + */ #include #include #include #include -#include "hostside.h" +#include "common.h" void badcmd(ParseState *ps, const char *fmt, ...) { va_list al; @@ -90,6 +93,27 @@ int ps_needhextoend(ParseState *ps, Byte *d, int *len_io) { 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; diff --git a/hostside/realtime.c b/hostside/realtime.c new file mode 100644 index 0000000..0c65026 --- /dev/null +++ b/hostside/realtime.c @@ -0,0 +1,154 @@ +/* + * 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(); +} diff --git a/hostside/realtime.h b/hostside/realtime.h new file mode 100644 index 0000000..473f415 --- /dev/null +++ b/hostside/realtime.h @@ -0,0 +1,47 @@ +/* + * declarations for multiplexer daemon + */ + +#ifndef REALTIME_H +#define REALTIME_H + +#include "daemons.h" +#include "auproto-pic.h" + +#include +#include +#include +#include +#include + +#include +#include + +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*/ diff --git a/hostside/selectors.h.gen b/hostside/selectors.h.gen index ec5dbb7..a997298 100755 --- a/hostside/selectors.h.gen +++ b/hostside/selectors.h.gen @@ -1,8 +1,10 @@ #!/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; diff --git a/hostside/selectout.c b/hostside/selectout.c new file mode 100644 index 0000000..4f470d0 --- /dev/null +++ b/hostside/selectout.c @@ -0,0 +1,33 @@ +/* + * mulitplexer daemon + * transmissions to clients of their selected messages + */ + +#include +#include + +#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) ); +} diff --git a/hostside/serialio.c b/hostside/serialio.c index 1075de9..f1b9a7c 100644 --- a/hostside/serialio.c +++ b/hostside/serialio.c @@ -1,4 +1,5 @@ /* + * common * general serial i/o and system interface etc. */ diff --git a/hostside/skelproto-pic.c b/hostside/skelproto-pic.c index 5e2339c..ec67fb6 100644 --- a/hostside/skelproto-pic.c +++ b/hostside/skelproto-pic.c @@ -7,29 +7,35 @@ * and related functions */ -#include "hostside.h" +#include + +#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; @@ -40,12 +46,33 @@ const PicInsnInfo *lookup_byopcode(Byte byte0, const PicInsnInfo *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 } }; diff --git a/hostside/skelproto-pic.h b/hostside/skelproto-pic.h index e42b48c..d30cad1 100644 --- a/hostside/skelproto-pic.h +++ b/hostside/skelproto-pic.h @@ -11,25 +11,31 @@ #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[]; diff --git a/hostside/startup.c b/hostside/startup.c new file mode 100644 index 0000000..6733506 --- /dev/null +++ b/hostside/startup.c @@ -0,0 +1,211 @@ +/* + * 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 } +}; diff --git a/hostside/utils.c b/hostside/utils.c index b6c4494..3a1cb42 100644 --- a/hostside/utils.c +++ b/hostside/utils.c @@ -1,4 +1,7 @@ -/**/ +/* + * common + * general utility functions + */ #include #include @@ -6,9 +9,10 @@ #include #include -#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); @@ -39,3 +43,9 @@ char *mstrdupl(const char *s, int l) { } 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"); +} diff --git a/layout/layout b/layout/layout index 3f5f6b5..fd226ef 100755 --- a/layout/layout +++ b/layout/layout @@ -647,7 +647,7 @@ sub segment_used__print ($) { sub segment_used__len ($$) { my ($used,$pt) = @_; - $segused_incurrent++; + $segused_incurrent += $used; return if @segments < 3; $segments[1] -= $used;