3 * startup state machine
8 const char *const stastatelist[]= DEFINE_STASTATE_DATA;
9 StartupState sta_state;
11 static TimeoutEvent sta_toev;
12 static TimeoutEvent ping_toev;
16 static void sta_goto(StartupState new_state);
18 static void timedout_onward(TimeoutEvent *toev) {
19 assert(sta_state != Sta_Run);
20 if (sta_state == Sta_Settling) {
22 serial_transmit(&piob);
24 sta_goto(sta_state == Sta_Flush ? Sta_Ping : sta_state + 1);
27 static void timedout_ping(TimeoutEvent *toev) {
28 assert(sta_state >= Sta_Ping);
32 static void timefor_ping(TimeoutEvent *toev) {
33 enco_pic_ping(&piob, ping_seq);
34 serial_transmit(&piob);
35 ping_toev.callback= timedout_ping;
36 toev_start(&ping_toev);
39 static void initial_ping(void) {
43 ping_seq= (now.tv_sec & 0x1fU) << 5; /* bottom 5bi of secs: period 32s */
44 ping_seq |= (now.tv_usec >> 15); /* top 5bi of 20bi us: res.~2^15us */
45 ping_toev.duration= 300;
49 void sta_startup(void) { sta_goto(Sta_Flush); }
51 static void sta_goto(StartupState new_state) {
53 sta_toev.callback= timedout_onward;
54 sta_toev.duration= -1;
56 if (new_state < Sta_Ping) {
57 toev_stop(&ping_toev);
58 } else if (new_state == Sta_Ping) {
61 assert(sta_state >= Sta_Ping);
65 case Sta_Flush: sta_toev.duration= 300; break;
68 case Sta_Fault: break;
69 case Sta_Settling: sta_toev.duration= 750; break;
70 case Sta_Resolving: sta_toev.duration= 500; break;
76 case Sta_Flush: break;
77 case Sta_Off: if (sta_state > Sta_Ping) enco_pic_off(&piob); break;
79 case Sta_Fault: break;
80 case Sta_Settling: enco_pic_off(&piob); break;
81 case Sta_Resolving: enco_pic_on(&piob); break;
82 case Sta_Run: retransmit_start(); break;
84 if (piob.l) serial_transmit(&piob);
86 toev_start(&sta_toev);
89 /* notify various people: */
90 oprintf(UPO, "stastate %s\n", stastatelist[sta_state]);
91 /* ... add others here. */
94 void serial_moredata(PicInsn *buf) {
95 const PicInsnInfo *pii;
99 /* Called when more data is received from PICs.
100 * On entry, buf->l is amount of data available.
101 * Does one of the following:
102 * - determines that there is no complete message; sets buf->l = 0
103 * - finds and handles one PicInsn message, sets buf->l = message length
104 * - handles some series of bytes structured some other way,
105 * sets buf->l to the numer of bytes handled.
109 if (sta_state == Sta_Flush) {
110 toev_start(&sta_toev);
111 ouhex("picioh in junk", buf->d, buf->l);
112 return; /* junk absolutely everything */
114 if (PICMSG_AAARGH_P(buf->d[0])) {
115 ouhex("picioh in aaargh", buf->d, buf->l);
116 die("PIC sent us AAARGH!");
118 if (PICMSG_HELLO_P(buf->d[0])) {
119 ouhex("picioh in hello", buf->d, 1);
125 if (sta_state == Sta_Off) {
126 ouhex("picioh in off", buf->d, 1);
131 assert(sta_state >= Sta_Ping);
132 /* So, we are expecting properly formed messages. */
134 for (ep= buf->d; ep < buf->d + buf->l; ep++)
138 if (buf->l == sizeof(buf->d)) {
139 ouhex("picioh in toolong", buf->d, buf->l);
140 die("PIC sent packet too long");
142 buf->l= 0; /* message not yet finished, so consume nothing */
147 buf->l= ep - buf->d + 1;
148 picinsn_decode(buf, pic_reply_infos, &pii, &objnum);
149 suppress= pii && pii->noiselevel > picio_send_noise;
150 if (!suppress && picio_send_noise >= 2)
151 ouhex("picioh in msg", buf->d, buf->l);
152 if (!pii) { oprintf(UPO, "picio in unknown\n"); return; }
154 oupicio("in",pii,objnum);
155 pii->input_fn(pii,buf,objnum);
158 void on_pic_pong(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
159 if (objnum != ping_seq)
160 die("PIC sent wrong ping response (0x%x, wanted 0x%x)", objnum, ping_seq);
162 ping_toev.duration= 1000;
163 ping_toev.callback= timefor_ping;
164 toev_start(&ping_toev);
166 if (sta_state == Sta_Ping)
167 sta_goto(Sta_Settling);
170 void on_pic_fixed(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
171 if (sta_state >= Sta_Resolving) die("PIC sent unexpected FIXED");
172 if (sta_state == Sta_Fault) sta_goto(Sta_Resolving);
175 void on_pic_fault(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
176 if (sta_state <= Sta_Ping) return;
177 if (sta_state == Sta_Fault) die("PIC sent two FAULTs");
181 void on_pic_wtimeout(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
182 if (sta_state <= Sta_Settling) return;
183 if (sta_state == Sta_Resolving) die("PIC sent WTIMEOUT in Resolving");
184 oprintf(UPO, "warning watchdog \"PIC watchdog timer triggered\"\n");
187 void on_pic_hello(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
189 void on_pic_aaargh(const PicInsnInfo *pii, const PicInsn *pi, int objnum)
192 void on_pic_detect1(const PicInsnInfo *pii, const PicInsn *pi, int segn) {
193 if (segn >= NUM_SEGMENTS) die("PIC sent detect @#%d out of range",segn);
194 if (sta_state < Sta_Run) {
195 oprintf(UPO, "warning fixme ignored non-Run detection @%s\n",
196 info_segments[segn].pname);
199 safety_notify_detection(&segments[segn]);
202 /*---------- fixme move these to where they want to go ----------*/
204 void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
205 if (!objnum) die("PIC sent NUL!");
206 if (sta_state <= Sta_Settling) return;
207 if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
210 retransmit_something();
213 void on_pic_detect0(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
216 void abandon_run(void) {
217 /* fixme do something here */