3 * startup state machine
8 StartupState sta_state;
10 static TimeoutEvent sta_toev;
11 static TimeoutEvent ping_toev;
15 static void sta_goto(StartupState new_state);
17 static void timedout_onward(TimeoutEvent *toev) {
18 assert(sta_state != Sta_Run);
19 if (sta_state == Sta_Settling) {
21 serial_transmit(&piob);
23 sta_goto(sta_state == Sta_Flush ? Sta_Ping : sta_state + 1);
26 static void timedout_ping(TimeoutEvent *toev) {
27 assert(sta_state >= Sta_Ping);
31 static void timefor_ping(TimeoutEvent *toev) {
32 enco_pic_ping(&piob, ping_seq);
33 serial_transmit(&piob);
34 ping_toev.callback= timedout_ping;
35 toev_start(&ping_toev);
38 static void initial_ping(void) {
42 ping_seq= (now.tv_sec & 0x1fU) << 5; /* bottom 5bi of secs: period 32s */
43 ping_seq |= (now.tv_usec >> 15); /* top 5bi of 20bi us: res.~2^15us */
44 ping_toev.duration= 300;
48 void sta_startup(void) { sta_goto(Sta_Flush); }
50 static void sta_goto(StartupState new_state) {
52 sta_toev.callback= timedout_onward;
53 sta_toev.duration= -1;
55 if (new_state < Sta_Ping) {
56 toev_stop(&ping_toev);
57 } else if (new_state == Sta_Ping) {
60 assert(sta_state >= Sta_Ping);
64 case Sta_Flush: sta_toev.duration= 300; break;
67 case Sta_Fault: break;
68 case Sta_Settling: sta_toev.duration= 750; break;
69 case Sta_Resolving: sta_toev.duration= 500; break;
75 case Sta_Flush: break;
76 case Sta_Off: if (sta_state > Sta_Ping) enco_pic_off(&piob); break;
78 case Sta_Fault: break;
79 case Sta_Settling: enco_pic_off(&piob); break;
80 case Sta_Resolving: enco_pic_on(&piob); break;
83 if (piob.l) serial_transmit(&piob);
85 toev_start(&sta_toev);
88 /* notify various people: */
89 oprintf(UPO, "stastate %d\n", sta_state);
90 /* ... add others here. */
93 void serial_moredata(PicInsn *buf) {
94 const PicInsnInfo *pii;
98 /* Called when more data is received from PICs.
99 * On entry, buf->l is amount of data available.
100 * Does one of the following:
101 * - determines that there is no complete message; sets buf->l = 0
102 * - finds and handles one PicInsn message, sets buf->l = message length
103 * - handles some series of bytes structured some other way,
104 * sets buf->l to the numer of bytes handled.
108 if (sta_state == Sta_Flush) {
109 toev_start(&sta_toev);
110 ouhex("picioh in junk", buf->d, buf->l);
111 return; /* junk absolutely everything */
113 if (PICMSG_AAARGH_P(buf->d[0])) {
114 ouhex("picioh in aaargh", buf->d, buf->l);
115 die("PIC sent us AAARGH!");
117 if (PICMSG_HELLO_P(buf->d[0])) {
118 ouhex("picioh in hello", buf->d, 1);
124 if (sta_state == Sta_Off) {
125 ouhex("picioh in off", buf->d, 1);
130 assert(sta_state >= Sta_Ping);
131 /* So, we are expecting properly formed messages. */
133 for (ep= buf->d; ep < buf->d + buf->l; ep++)
137 if (buf->l == sizeof(buf->d)) {
138 ouhex("picioh in toolong", buf->d, buf->l);
139 die("PIC sent packet too long");
141 buf->l= 0; /* message not yet finished, so consume nothing */
146 buf->l= ep - buf->d + 1;
147 ouhex("picioh in msg", buf->d, buf->l);
148 picinsn_decode(buf, pic_reply_infos, &pii, &objnum);
149 if (!pii) { oprintf(UPO, "picio in unknown\n"); return; }
150 oupicio("in",pii,objnum);
151 pii->input_fn(pii,buf,objnum);
154 void on_pic_pong(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
155 if (objnum != ping_seq)
156 die("PIC sent wrong ping response (0x%x, wanted 0x%x)", objnum, ping_seq);
158 ping_toev.duration= 1000;
159 ping_toev.callback= timefor_ping;
160 toev_start(&ping_toev);
162 if (sta_state == Sta_Ping)
163 sta_goto(Sta_Settling);
166 void on_pic_fixed(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
167 if (sta_state >= Sta_Resolving) die("PIC sent unexpected FIXED");
168 if (sta_state == Sta_Fault) sta_goto(Sta_Resolving);
171 void on_pic_fault(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
172 if (sta_state <= Sta_Ping) return;
173 if (sta_state == Sta_Fault) die("PIC sent two FAULTs");
177 void on_pic_wtimeout(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
178 if (sta_state <= Sta_Settling) return;
179 if (sta_state == Sta_Resolving) die("PIC sent WTIMEOUT in Resolving");
180 oprintf(UPO, "warning watchdog \"PIC watchdog timer triggered\"\n");
183 void on_pic_hello(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
185 void on_pic_aaargh(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
188 void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int segn) {
189 if (segn >= NUM_SEGMENTS) die("PIC sent detect @#%d out of range",segn);
190 if (sta_state < Sta_Run) {
191 oprintf(UPO, "warning fixme ignored non-Run detection @%s\n",
192 info_segments[segn].pname);
195 safety_notify_detection(&segments[segn]);
198 /*---------- fixme move these to where they want to go ----------*/
200 void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
201 if (sta_state <= Sta_Settling) return;
202 if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
204 /* fixme transmit something else (move this to another file?) */
207 void on_pic_detect0(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
210 void abandon_run(void) {
211 /* fixme do something here */
214 const CmdInfo toplevel_cmds[]= {
217 { "nmra", cmd_nmra, },
218 { "noop", cmd_noop },