}
 }
 
+void waggle_startup_manual(void) {
+  waggle.f.ready= 1;
+}
+
 void waggle_settle(void) {
   waggle.f.ready= 1;
   waggle_settle_check();
 }
   
 void on_pic_waggled(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
-  if (sta_state < Sta_Settling) return;
-
-  waggle.f.ready= 1;
-  if (sta_state >= Sta_Resolving) { fsq_check_action(&waggle); return; }
-
-  assert(sta_state == Sta_Settling);
-  waggle_settle_check();
+  if (sta_state == Sta_Settling) {
+    waggle.f.ready= 1;
+    waggle_settle_check();
+  } else if (sta_state >= Sta_Resolving || sta_state == Sta_Manual) {
+    waggle.f.ready= 1;
+    fsq_check_action(&waggle);
+    return;
+  }
 }
 
 static FsqMethod relays_method= {
 
 static Change *mp_allocate(Method *meth, Segment *move,
                           int alloc_motions, MovPosComb target) {
-  assert(sta_state >= Sta_Resolving);
+  assert(sta_state >= Sta_Resolving || sta_state == Sta_Manual);
   Change *chg= meth->allocate(meth, alloc_motions);
   chg->meth=      meth;
   chg->move=      move;
 
     case 's': device= arg; break;
     case 'p': persist_fn= arg; break;
     case 'v': picio_send_noise= atoi(arg); break;
+    case 'm': sta_state= Sta_Manual; break;
     case 'L': logcopy_fn= arg; break;
     case 'S': simulate= arg; break;
     default: badusage("unknown option");
 
 void resolve_motioncheck(void);
 
 void waggle_settle(void); /* from movpos.c */
+void waggle_startup_manual(void);
 
 /*---------- from/for record.c and persist.c ----------*/
 
 
 
 void on_pic_nmradone(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
   if (!objnum) die("PIC sent NUL!");
-  if (sta_state <= Sta_Settling) return;
-  if (sta_state != Sta_Run) die("PIC sent NMRADONE in Resolving");
-
-  while (objnum--)
-    retransmit_something();
+  if (sta_state == Sta_Run || sta_state == Sta_Manual)
+    while (objnum--)
+      retransmit_something();
+  else
+    if (sta_state > Sta_Settling)
+      die("PIC sent NMRADONE in %s", stastatelist[sta_state]);
 }
 
   timefor_ping(0);
 }
 
-void sta_startup(void) { sta_goto(Sta_Flush); }
+void sta_startup(void) {
+  if (sta_state != Sta_Manual) {
+    sta_goto(Sta_Flush);
+  } else {
+    waggle_startup_manual();
+    retransmit_start();
+  }
+}
 void sta_finalising_done(void) { sta_goto(Sta_Run); }
 
 static void sta_goto(StartupState new_state) {
   switch (new_state) {
   case Sta_Flush:      sta_toev.duration=   300;   break;
   case Sta_Off:                                    break;
+  case Sta_Manual:                                 abort();
   case Sta_Ping:                                   break;
   case Sta_Fault:                                  break;
   case Sta_Settling:   sta_toev.duration=   750;   break;
   switch (new_state) {
   case Sta_Flush:                                                  break;
   case Sta_Off:   if (sta_state > Sta_Ping) enco_pic_off(&piob);   break;
+  case Sta_Manual:                                                 abort();
   case Sta_Ping:                                                   break;
   case Sta_Fault:                                                  break;
   case Sta_Settling:   waggle_settle();     enco_pic_off(&piob);   break;
   }
   if (PICMSG_HELLO_P(buf->d[0])) {
     ouhexi("picioh in hello", buf->d, 1);
-    sta_goto(Sta_Flush);
+    if (sta_state != Sta_Manual)
+      sta_goto(Sta_Flush);
     buf->l= 1;
     return;
   }
     return;
   }
 
-  assert(sta_state >= Sta_Ping);
+  assert(sta_state >= Sta_Manual);
   /* So, we are expecting properly formed messages. */
   
   for (ep= buf->d; ep < buf->d + buf->l; ep++)
 }
 
 void on_pic_pong(const PicInsnInfo *pii, const PicInsn *pi, int objnum) {
+  if (sta_state == Sta_Manual)
+    return;
+
   if (objnum != ping_seq)
     die("PIC sent wrong ping response (0x%x, wanted 0x%x)", objnum, ping_seq);
 
   switch (sta_state) {
   case Sta_Flush:
   case Sta_Off:
+  case Sta_Manual:
   case Sta_Ping:
   case Sta_Fault:
   case Sta_Settling:
 
 
   Sta Flush
   Sta Off
+  Sta Manual
   Sta Ping
   Sta Fault
   Sta Settling