diff --git a/Visual Studio Projects/FrontPanelTest.vcproj b/Visual Studio Projects/FrontPanelTest.vcproj
index e684a37d..95c97aaa 100644
--- a/Visual Studio Projects/FrontPanelTest.vcproj	
+++ b/Visual Studio Projects/FrontPanelTest.vcproj	
@@ -35,6 +35,9 @@
 			<Tool
 				Name="VCXMLDataGeneratorTool"
 			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
 			<Tool
 				Name="VCMIDLTool"
 			/>
@@ -116,6 +119,9 @@
 			<Tool
 				Name="VCXMLDataGeneratorTool"
 			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
 			<Tool
 				Name="VCMIDLTool"
 			/>
@@ -126,7 +132,7 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
-				WholeProgramOptimization="true"
+				WholeProgramOptimization="false"
 				AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;&quot;../../windows-build/winpcap/Wpdpack/Include&quot;;&quot;../../windows-build/PCRE/include/&quot;;&quot;../../windows-build/pthreads&quot;"
 				PreprocessorDefinitions="_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS;PTW32_STATIC_LIB"
 				StringPooling="true"
diff --git a/frontpanel/FrontPanelTest.c b/frontpanel/FrontPanelTest.c
index 9537ada4..612b4313 100644
--- a/frontpanel/FrontPanelTest.c
+++ b/frontpanel/FrontPanelTest.c
@@ -148,11 +148,10 @@ if ((argc > 1) && ((!strcmp("-d", argv[1])) || (!strcmp("-D", argv[1])) || (!str
 if ((f = fopen (sim_config, "w"))) {
     if (debug) {
         fprintf (f, "set verbose\n");
-        fprintf (f, "set log simulator.dbg\n");
-        fprintf (f, "set debug -n -a log\n");
+        fprintf (f, "set debug -n -a simulator.dbg\n");
         fprintf (f, "set cpu conhalt\n");
         fprintf (f, "set remote telnet=2226\n");
-        fprintf (f, "set rem-con debug=XMT;RCV\n");
+        fprintf (f, "set rem-con debug=XMT;RCV;MODE;REPEAT;CMD\n");
         fprintf (f, "set remote notelnet\n");
         }
     fprintf (f, "set cpu autoboot\n");
@@ -184,9 +183,8 @@ if (!panel) {
     }
 
 if (debug) {
-    sim_panel_set_debug_mode (panel, DBG_XMT|DBG_RCV);
+    sim_panel_set_debug_mode (panel, DBG_XMT|DBG_RCV|DBG_REQ|DBG_RSP);
     }
-
 tape = sim_panel_add_device_panel (panel, "TAPE DRIVE");
 
 if (!tape) {
@@ -313,7 +311,7 @@ if (sim_panel_get_registers (panel, NULL)) {
     printf ("Error getting register data: %s\n", sim_panel_get_error());
     goto Done;
     }
-if (sim_panel_set_display_callback (panel, &DisplayCallback, NULL, 5)) {
+if (sim_panel_set_display_callback_interval (panel, &DisplayCallback, NULL, 200000)) {
     printf ("Error setting automatic display callback: %s\n", sim_panel_get_error());
     goto Done;
     }
@@ -336,19 +334,27 @@ if (sim_panel_dismount (panel, "RL0")) {
     }
 remove ("TEST-RL.DSK");
 if (sim_panel_break_set (panel, "400")) {
-    printf ("Unexpected establishing a breakpoint: %s\n", sim_panel_get_error());
+    printf ("Unexpected error establishing a breakpoint: %s\n", sim_panel_get_error());
     goto Done;
     }
 if (sim_panel_break_clear (panel, "400")) {
-    printf ("Unexpected clearing a breakpoint: %s\n", sim_panel_get_error());
+    printf ("Unexpected error clearing a breakpoint: %s\n", sim_panel_get_error());
     goto Done;
     }
 if (sim_panel_break_output_set (panel, "\"32..31..30\"")) {
-    printf ("Unexpected establishing an output breakpoint: %s\n", sim_panel_get_error());
+    printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
     goto Done;
     }
 if (sim_panel_break_output_clear (panel, "\"32..31..30\"")) {
-    printf ("Unexpected clearing an output breakpoint: %s\n", sim_panel_get_error());
+    printf ("Unexpected error clearing an output breakpoint: %s\n", sim_panel_get_error());
+    goto Done;
+    }
+if (sim_panel_break_output_set (panel, "-P \"Normal operation not possible.\"")) {
+    printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
+    goto Done;
+    }
+if (sim_panel_break_output_set (panel, "-P \"Device? [XQA0]: \"")) {
+    printf ("Unexpected error establishing an output breakpoint: %s\n", sim_panel_get_error());
     goto Done;
     }
 sim_panel_clear_error ();
diff --git a/sim_console.c b/sim_console.c
index 11f55c23..5553fa73 100644
--- a/sim_console.c
+++ b/sim_console.c
@@ -114,6 +114,9 @@
    sim_ttisatty                 called to determine if running interactively
    sim_os_poll_kbd              poll for keyboard input
    sim_os_putchar               output character to console
+   sim_set_noconsole_port       Enable automatic WRU console polling
+   sim_set_stable_registers_state Declare that all registers are always stable
+
 
    The first group is OS-independent; the second group is OS-dependent.
 
@@ -172,6 +175,7 @@ int32 sim_del_char = '\b';                              /* delete character */
 #else
 int32 sim_del_char = 0177;
 #endif
+extern TMLN *sim_oline;                                 /* global output socket */
 
 static t_stat sim_con_poll_svc (UNIT *uptr);                /* console connection poll routine */
 static t_stat sim_con_reset (DEVICE *dptr);                 /* console reset routine */
@@ -243,6 +247,16 @@ sim_con_console_port = FALSE;
 return SCPE_OK;
 }
 
+static t_bool sim_con_stable_registers = FALSE;
+
+/* Enable automatic WRU console polling */
+
+t_stat sim_set_stable_registers_state (void)
+{
+sim_con_stable_registers = TRUE;
+return SCPE_OK;
+}
+
 /* Unit service for console connection polling */
 
 static t_stat sim_con_poll_svc (UNIT *uptr)
@@ -409,18 +423,28 @@ while (*cptr != 0) {
 return SCPE_OK;
 }
 
+#define MAX_REMOTE_SESSIONS 40                          /* Arbitrary Session Limit */
+
 t_stat sim_rem_con_poll_svc (UNIT *uptr);               /* remote console connection poll routine */
 t_stat sim_rem_con_data_svc (UNIT *uptr);               /* remote console connection data routine */
+t_stat sim_rem_con_repeat_svc (UNIT *uptr);             /* remote auto repeat command console timing routine */
 t_stat sim_rem_con_reset (DEVICE *dptr);                /* remote console reset routine */
-UNIT sim_rem_con_unit[2] = {
+UNIT sim_rem_con_unit[2+MAX_REMOTE_SESSIONS] = {
     { UDATA (&sim_rem_con_poll_svc, UNIT_IDLE, 0)  },   /* remote console connection polling unit */
     { UDATA (&sim_rem_con_data_svc, UNIT_IDLE|UNIT_DIS, 0)  }};  /* console data handling unit */
 
+#define DBG_MOD  0x00000004                             /* Remote Console Mode activities */
+#define DBG_REP  0x00000008                             /* Remote Console Repeat activities */
+#define DBG_CMD  0x00000010                             /* Remote Console Command activities */
+
 DEBTAB sim_rem_con_debug[] = {
   {"TRC",    DBG_TRC, "routine calls"},
   {"XMT",    DBG_XMT, "Transmitted Data"},
   {"RCV",    DBG_RCV, "Received Data"},
   {"CON",    DBG_CON, "connection activity"},
+  {"CMD",    DBG_CMD, "Remote Console Command activity"},
+  {"MODE",   DBG_MOD, "Remote Console Mode activity"},
+  {"REPEAT", DBG_REP, "Remote Console Repeat activity"},
   {0}
 };
 
@@ -439,10 +463,15 @@ DEVICE sim_remote_console = {
     NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL, 
     NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
     NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
-#define MAX_REMOTE_SESSIONS 40          /* Arbitrary Session Limit */
 static int32 *sim_rem_buf_size = NULL;
 static int32 *sim_rem_buf_ptr = NULL;
 static char **sim_rem_buf = NULL;
+static char **sim_rem_act_buf = NULL;
+static size_t *sim_rem_act_buf_size = NULL;
+static char **sim_rem_act = NULL;
+static uint32 *sim_rem_repeat_interval = NULL;
+static t_bool *sim_rem_repeat_pending = NULL;
+static char **sim_rem_repeat_action = NULL;
 static t_bool *sim_rem_single_mode = NULL;  /* per line command mode (single command or must continue) */
 static TMXR sim_rem_con_tmxr = { 0, 0, 0, NULL, NULL, &sim_remote_console };/* remote console line mux */
 static uint32 sim_rem_read_timeout = 30;    /* seconds before automatic continue */
@@ -523,6 +552,10 @@ for (i=connections=0; i<sim_rem_con_tmxr.lines; i++) {
         else
             fprintf (st, "Remote Console Input on connection %d does not continue automatically\n", i);
         }
+    if (sim_rem_repeat_action[i]) {
+        fprintf (st, "The Command: %s\n", sim_rem_repeat_action[i]);
+        fprintf (st, "    is repeated every %s\n", sim_fmt_secs (sim_rem_repeat_interval[i] / 1000000.0));
+        }
     }
 return SCPE_OK;
 }
@@ -567,17 +600,22 @@ return SCPE_OK;
 
 static t_stat x_continue_cmd (int32 flag, CONST char *cptr)
 {
-return SCPE_IERR;           /* This routine should never be called */
+return 1+SCPE_IERR;         /* This routine should never be called */
+}
+
+static t_stat x_repeat_cmd (int32 flag, CONST char *cptr)
+{
+return 2+SCPE_IERR;         /* This routine should never be called */
 }
 
 static t_stat x_step_cmd (int32 flag, CONST char *cptr)
 {
-return SCPE_IERR;           /* This routine should never be called */
+return 3+SCPE_IERR;         /* This routine should never be called */
 }
 
 static t_stat x_run_cmd (int32 flag, CONST char *cptr)
 {
-return SCPE_IERR;           /* This routine should never be called */
+return 4+SCPE_IERR;         /* This routine should never be called */
 }
 
 static t_stat x_help_cmd (int32 flag, CONST char *cptr);
@@ -591,6 +629,7 @@ static CTAB allowed_remote_cmds[] = {
     { "ASSIGN",   &assign_cmd,        0 },
     { "DEASSIGN", &deassign_cmd,      0 },
     { "CONTINUE", &x_continue_cmd,    0 },
+    { "REPEAT",   &x_repeat_cmd,      0 },
     { "STEP",     &x_step_cmd,        0 },
     { "PWD",      &pwd_cmd,           0 },
     { "SAVE",     &save_cmd,          0 },
@@ -612,6 +651,7 @@ static CTAB allowed_master_remote_cmds[] = {
     { "ASSIGN",   &assign_cmd,        0 },
     { "DEASSIGN", &deassign_cmd,      0 },
     { "CONTINUE", &x_continue_cmd,    0 },
+    { "REPEAT",   &x_repeat_cmd,      0 },
     { "STEP",     &x_step_cmd,        0 },
     { "PWD",      &pwd_cmd,           0 },
     { "SAVE",     &save_cmd,          0 },
@@ -629,6 +669,9 @@ static CTAB allowed_master_remote_cmds[] = {
     { "BOOT",     &x_run_cmd,   RU_BOOT },
     { "BREAK",    &brk_cmd,      SSH_ST },
     { "NOBREAK",  &brk_cmd,      SSH_CL },
+    { "EXPECT",   &expect_cmd,        1 },
+    { "NOEXPECT", &expect_cmd,        0 },
+    { "SEND",     &send_cmd,          0 },
     { NULL,       NULL }
     };
 
@@ -637,6 +680,7 @@ static CTAB allowed_single_remote_cmds[] = {
     { "DETACH",   &detach_cmd,        0 },
     { "EXAMINE",  &exdep_cmd,      EX_E },
     { "EVALUATE", &eval_cmd,          0 },
+    { "REPEAT",   &x_repeat_cmd,      0 },
     { "PWD",      &pwd_cmd,           0 },
     { "DIR",      &dir_cmd,           0 },
     { "LS",       &dir_cmd,           0 },
@@ -646,6 +690,11 @@ static CTAB allowed_single_remote_cmds[] = {
     { NULL,       NULL }
     };
 
+static CTAB remote_only_cmds[] = {
+    { "REPEAT",   &x_repeat_cmd,      0 },
+    { NULL,       NULL }
+    };
+
 static t_stat x_help_cmd (int32 flag, CONST char *cptr)
 {
 CTAB *cmdp, *cmdph;
@@ -690,23 +739,27 @@ return stat;
 static void _sim_rem_log_out (TMLN *lp)
 {
 char cbuf[4*CBUFSIZE];
+int line = (int)(lp - sim_rem_con_tmxr.ldsc);
 
-if (sim_log) {
-    int32 unwritten;
-
+if ((!sim_oline) && (sim_log)) {
     fflush (sim_log);
     sim_fseeko (sim_log, sim_rem_cmd_log_start, SEEK_SET);
     cbuf[sizeof(cbuf)-1] = '\0';
     while (fgets (cbuf, sizeof(cbuf)-1, sim_log))
         tmxr_linemsgf (lp, "%s", cbuf);
-    if (!tmxr_input_pending_ln (lp)) {
-        do {
-            unwritten = tmxr_send_buffered_data (lp);
-            if (unwritten == lp->txbsz)
-                sim_os_ms_sleep (100);
-            } while (unwritten == lp->txbsz);
-        }
     }
+sim_oline = NULL;
+if ((sim_rem_act[line] == NULL) && 
+    (!tmxr_input_pending_ln (lp))) {
+    int32 unwritten;
+
+    do {
+        unwritten = tmxr_send_buffered_data (lp);
+        if (unwritten == lp->txbsz)
+            sim_os_ms_sleep (100);
+        } while (unwritten == lp->txbsz);
+    }
+
 }
 
 void sim_remote_process_command (void)
@@ -724,17 +777,152 @@ cptr = cbuf;
 cptr = get_glyph (cptr, gbuf, 0);               /* get command glyph */
 sim_rem_active_command = find_cmd (gbuf);       /* find command */
 
-sim_ttcmd ();                                   /* restore console */
+if (!sim_processing_event)
+    sim_ttcmd ();                               /* restore console */
 stat = sim_rem_active_command->action (sim_rem_active_command->arg, cptr);/* execute command */
 if (stat != SCPE_OK)
     stat = _sim_rem_message (gbuf, stat);       /* display results */
 sim_last_cmd_stat = SCPE_BARE_STATUS(stat);
-sim_ttrun ();                                   /* set console mode */
-sim_cancel (&sim_rem_con_unit[1]);              /* force immediate activation of sim_rem_con_data_svc */
-sim_activate (&sim_rem_con_unit[1], -1);
+if (!sim_processing_event) {
+    sim_ttrun ();                               /* set console mode */
+    sim_cancel (&sim_rem_con_unit[1]);          /* force immediate activation of sim_rem_con_data_svc */
+    sim_activate (&sim_rem_con_unit[1], -1);
+    }
 sim_switches = saved_switches;                  /* restore original switches */
 }
 
+/* Clear pending actions */
+
+static char *sim_rem_clract (int32 line)
+{
+TMLN *lp = &sim_rem_con_tmxr.ldsc[line];
+
+tmxr_send_buffered_data (lp);                   /* flush any buffered data */
+return sim_rem_act[line] = NULL;
+}
+
+/* Set up pending actions */
+
+static void sim_rem_setact (int32 line, const char *action)
+{
+if (action) {
+    size_t act_size = strlen (action) + 1;
+
+    if (act_size > sim_rem_act_buf_size[line]) {/* expand buffer if necessary */
+        sim_rem_act_buf[line] = (char *)realloc (sim_rem_act_buf[line], act_size);
+        sim_rem_act_buf_size[line] = act_size;
+        }
+    strcpy (sim_rem_act_buf[line], action);     /* populate buffer */
+    sim_rem_act[line] = sim_rem_act_buf[line];  /* start at beginning of buffer */
+    }
+else
+    sim_rem_clract (line);
+}
+
+/* Get next pending action, if any */
+
+static char *sim_rem_getact (int32 line, char *buf, int32 size)
+{
+char *ep;
+size_t lnt;
+
+if (sim_rem_act[line] == NULL)                  /* any action? */
+    return NULL;
+while (sim_isspace (*sim_rem_act[line]))        /* skip spaces */
+    sim_rem_act[line]++;
+if (*sim_rem_act[line] == 0)                    /* now empty? */
+    return sim_rem_clract (line);
+if ((ep = strchr (sim_rem_act[line], ';'))) {   /* cmd delimiter? */
+    lnt = ep - sim_rem_act[line];               /* cmd length */
+    memcpy (buf, sim_rem_act[line], lnt + 1);   /* copy with ; */
+    buf[lnt] = 0;                               /* erase ; */
+    sim_rem_act[line] += lnt + 1;               /* adv ptr */
+    }
+else {
+    strncpy (buf, sim_rem_act[line], size);     /* copy action */
+    sim_rem_act[line] += strlen (sim_rem_act[line]);/* adv ptr to end */
+    }
+return buf;
+}
+
+/* 
+    Parse and setup Remote Console REPEAT command:
+       REPEAT EVERY nnn USECS Command {; command...}
+ */
+static t_stat _rem_repeat_cmd_setup (int32 line, CONST char **iptr)
+{
+char gbuf[CBUFSIZE];
+int32 val;
+t_bool all_stop = FALSE;
+t_stat stat = SCPE_OK;
+CONST char *cptr = *iptr;
+
+sim_debug (DBG_REP, &sim_remote_console, "Repeat Setup: %s\n", cptr);
+if (*cptr == 0)         /* required argument? */
+    stat = SCPE_2FARG;
+else {
+    cptr = get_glyph (cptr, gbuf, 0);               /* get next glyph */
+    if (MATCH_CMD (gbuf, "EVERY") == 0) {
+        cptr = get_glyph (cptr, gbuf, 0);           /* get next glyph */
+        val = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
+        if ((stat != SCPE_OK) || (val <= 0))        /* error? */
+            stat = SCPE_ARG;
+        else {
+            cptr = get_glyph (cptr, gbuf, 0);       /* get next glyph */
+            if ((MATCH_CMD (gbuf, "USECS") != 0) || (*cptr == 0))
+                stat = SCPE_ARG;
+            else
+                sim_rem_repeat_interval[line] = val;
+            }
+        }
+    else {
+        if (MATCH_CMD (gbuf, "STOP") == 0) {
+            if (*cptr) {                            /* more command arguments? */
+                cptr = get_glyph (cptr, gbuf, 0);   /* get next glyph */
+                if ((MATCH_CMD (gbuf, "ALL") != 0) ||   /*  */
+                    (*cptr != 0)                   ||   /*  */
+                    (line != 0))                        /* master line? */
+                    stat = SCPE_ARG;
+                else
+                    all_stop = TRUE;
+                }
+            else
+                sim_rem_repeat_interval[line] = 0;
+            }
+        else
+            stat = SCPE_ARG;
+        }
+    }
+if (stat == SCPE_OK) {
+    if (all_stop) {
+        for (line = 0; line < sim_rem_con_tmxr.lines; line++) {
+            free (sim_rem_repeat_action[line]);
+            sim_rem_repeat_action[line] = NULL;
+            sim_cancel (&sim_rem_con_unit[line + 2]);
+            sim_rem_repeat_pending[line] = FALSE;
+            sim_rem_clract (line);
+            }
+        }
+    else {
+        if (sim_rem_repeat_interval[line] != 0) {
+            sim_rem_repeat_action[line] = (char *)realloc (sim_rem_repeat_action[line], 1 + strlen (cptr));
+            strcpy (sim_rem_repeat_action[line], cptr);
+            cptr += strlen (cptr);
+            stat = sim_activate_after (&sim_rem_con_unit[line + 2], sim_rem_repeat_interval[line]);
+            }
+        else {
+            free (sim_rem_repeat_action[line]);
+            sim_rem_repeat_action[line] = NULL;
+            sim_cancel (&sim_rem_con_unit[line + 2]);
+            }
+        sim_rem_repeat_pending[line] = FALSE;
+        sim_rem_clract (line);
+        }
+    }
+*iptr = cptr;
+return stat;
+}
+
 /* Unit service for remote console data polling */
 
 t_stat sim_rem_con_data_svc (UNIT *uptr)
@@ -760,8 +948,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
     t_bool master_session = (sim_rem_master_mode && (i == 0));
 
     lp = &sim_rem_con_tmxr.ldsc[i];
-    if (!lp->conn)
+    if (!lp->conn) {
+        if (sim_rem_repeat_interval[i]) {    /* was repeated enabled? */
+            cptr = strcpy (gbuf, "STOP");
+            _rem_repeat_cmd_setup (i, &cptr);  /* make sure it is now disabled */
+            }
         continue;
+        }
     if (master_session && !sim_rem_master_was_connected) {
         tmxr_linemsgf (lp, "\nMaster Mode Session\r\n");
         tmxr_send_buffered_data (lp);                   /* flush any buffered data */
@@ -770,6 +963,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
     stat = SCPE_OK;
     if ((was_active_command) ||
         (master_session && !sim_rem_single_mode[i])) {
+        sim_debug (DBG_MOD, &sim_remote_console, "Session: %d %s %s\n", i, was_active_command ? "Was Active" : "", (master_session && !sim_rem_single_mode[i]) ? "master_session && !sim_rem_single_mode[i]" : "");
         if (was_active_command) {
             sim_rem_cmd_active_line = -1;               /* Done with active command */
             if (!sim_rem_active_command) {              /* STEP command? */
@@ -792,58 +986,59 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
                 tmxr_linemsgf (lpj, "\nRemote Master Console(%s) Entering Commands\n", lp->ipad);
                 tmxr_send_buffered_data (lpj);         /* flush any buffered data */
                 }
-            lp = &sim_rem_con_tmxr.ldsc[i];
             }
         }
     else {
-        c = tmxr_getc_ln (lp);
-        if (!(TMXR_VALID & c))
-            continue;
-        c = c & ~TMXR_VALID;
-        if (sim_rem_single_mode[i]) {
-            if (c == sim_int_char) {                    /* ^E (the interrupt character) must start continue mode console interaction */
-                sim_rem_single_mode[i] = FALSE;         /* enter multi command mode */
-                sim_is_running = 0;
-                sim_stop_timer_services ();
-                stat = SCPE_STOP;
-                _sim_rem_message ("RUN", stat);
-                _sim_rem_log_out (lp);
-                for (j=0; j < sim_rem_con_tmxr.lines; j++) {
-                    TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
-                    if ((i == j) || (!lpj->conn))
-                        continue;
-                    tmxr_linemsgf (lpj, "\nRemote Console %d(%s) Entering Commands\n", i, lp->ipad);
-                    tmxr_send_buffered_data (lpj);      /* flush any buffered data */
-                    }
-                lp = &sim_rem_con_tmxr.ldsc[i];
-                if (!master_session)
-                    tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
-                if (!master_session && sim_rem_read_timeouts[i]) {
-                    tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeouts[i]);
-                    tmxr_linemsgf (lp, "\r\n");
-                    tmxr_send_buffered_data (lp);       /* flush any buffered data */
-                    }
-                }
-            else {
-                if ((sim_rem_buf_ptr[i] == 0) &&        /* At beginning of input line */
-                    ((c == '\n') ||                     /* Ignore bare LF between commands (Microsoft Telnet bug) */
-                     (c == '\r')))                      /* Ignore empty commands */
-                    continue;
-                if ((c == '\004') || (c == '\032')) {   /* EOF character (^D or ^Z) ? */
-                    tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
-                    tmxr_send_buffered_data (lp);       /* flush any buffered data */
-                    tmxr_reset_ln (lp);
-                    continue;
-                    }
-                if (sim_rem_buf_ptr[i] == 0) {
-                    /* we just picked up the first character on a command line */
+        if ((!sim_rem_repeat_pending[i]) || (sim_rem_buf_ptr[i] != 0)) {
+            c = tmxr_getc_ln (lp);
+            if (!(TMXR_VALID & c))
+                continue;
+            c = c & ~TMXR_VALID;
+            if (sim_rem_single_mode[i]) {
+                if (c == sim_int_char) {                    /* ^E (the interrupt character) must start continue mode console interaction */
+                    sim_rem_single_mode[i] = FALSE;         /* enter multi command mode */
+                    sim_is_running = 0;
+                    sim_stop_timer_services ();
+                    stat = SCPE_STOP;
+                    _sim_rem_message ("RUN", stat);
+                    _sim_rem_log_out (lp);
+                    for (j=0; j < sim_rem_con_tmxr.lines; j++) {
+                        TMLN *lpj = &sim_rem_con_tmxr.ldsc[j];
+                        if ((i == j) || (!lpj->conn))
+                            continue;
+                        tmxr_linemsgf (lpj, "\nRemote Console %d(%s) Entering Commands\n", i, lp->ipad);
+                        tmxr_send_buffered_data (lpj);      /* flush any buffered data */
+                        }
+                    lp = &sim_rem_con_tmxr.ldsc[i];
                     if (!master_session)
-                        tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
-                    else
-                        tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
-                    sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
-                    if (!tmxr_input_pending_ln (lp))
-                        tmxr_send_buffered_data (lp);   /* flush any buffered data */
+                        tmxr_linemsg (lp, "\r\nSimulator paused.\r\n");
+                    if (!master_session && sim_rem_read_timeouts[i]) {
+                        tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeouts[i]);
+                        tmxr_linemsgf (lp, "\r\n");
+                        tmxr_send_buffered_data (lp);       /* flush any buffered data */
+                        }
+                    }
+                else {
+                    if ((sim_rem_buf_ptr[i] == 0) &&        /* At beginning of input line */
+                        ((c == '\n') ||                     /* Ignore bare LF between commands (Microsoft Telnet bug) */
+                         (c == '\r')))                      /* Ignore empty commands */
+                        continue;
+                    if ((c == '\004') || (c == '\032')) {   /* EOF character (^D or ^Z) ? */
+                        tmxr_linemsgf (lp, "\r\nGoodbye\r\n");
+                        tmxr_send_buffered_data (lp);       /* flush any buffered data */
+                        tmxr_reset_ln (lp);
+                        continue;
+                        }
+                    if (sim_rem_buf_ptr[i] == 0) {
+                        /* we just picked up the first character on a command line */
+                        if (!master_session)
+                            tmxr_linemsgf (lp, "\r\n%s", sim_prompt);
+                        else
+                            tmxr_linemsgf (lp, "\r\n%s", sim_is_running ? "SIM> " : "sim> ");
+                        sim_debug (DBG_XMT, &sim_remote_console, "Prompt Written: %s\n", sim_is_running ? "SIM> " : "sim> ");
+                        if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
+                            tmxr_send_buffered_data (lp);   /* flush any buffered data */
+                        }
                     }
                 }
             }
@@ -861,6 +1056,31 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
             tmxr_send_buffered_data (lp);               /* flush any buffered data */
             }
         do {
+            if (sim_rem_buf_ptr[i] == 0) {
+                if (sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i])) {
+                    if (!master_session)
+                        tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]);
+                    else
+                        tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
+                    sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
+                    got_command = TRUE;
+                    break;
+                    }
+                else {
+                    if (sim_rem_repeat_pending[i]) {
+                        sim_rem_repeat_pending[i] = FALSE;
+                        sim_rem_setact (i, sim_rem_repeat_action[i]);
+                        sim_rem_getact (i, sim_rem_buf[i], sim_rem_buf_size[i]);
+                        if (!master_session)
+                            tmxr_linemsgf (lp, "%s%s\n", sim_prompt, sim_rem_buf[i]);
+                        else
+                            tmxr_linemsgf (lp, "%s%s\n", sim_is_running ? "SIM> " : "sim> ", sim_rem_buf[i]);
+                        sim_rem_buf_ptr[i] = strlen (sim_rem_repeat_action[i]);
+                        got_command = TRUE;
+                        break;
+                        }
+                    }
+                }
             if (!sim_rem_single_mode[i]) {
                 c = tmxr_getc_ln (lp);
                 if (!(TMXR_VALID & c)) {
@@ -957,12 +1177,13 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
                 c = c & ~TMXR_VALID;
                 }
             } while ((!got_command) && ((!sim_rem_single_mode[i]) || c));
-        if (!tmxr_input_pending_ln (lp))
+        if ((sim_rem_act[i] == NULL) && (!tmxr_input_pending_ln (lp)))
             tmxr_send_buffered_data (lp);               /* flush any buffered data */
         if ((sim_rem_single_mode[i]) && !got_command) {
             break;
             }
-        sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
+        if (!sim_rem_master_mode)
+            sim_printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]);
         got_command = FALSE;
         if (strlen(sim_rem_buf[i]) >= sizeof(cbuf)) {
             sim_printf ("\r\nLine too long. Ignored.  Continuing Simulator execution\r\n");
@@ -1000,6 +1221,8 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
             }
         sim_rem_cmd_log_start = sim_ftell (sim_log);
         basecmdp = find_cmd (gbuf);                     /* validate basic command */
+        if (basecmdp == NULL)
+            basecmdp = find_ctab (remote_only_cmds, gbuf);/* validate basic command */
         if (basecmdp == NULL) {
             if ((gbuf[0] == ';') || (gbuf[0] == '#')) { /* ignore comment */
                 sim_rem_cmd_active_line = i;
@@ -1013,39 +1236,64 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
             }
         else {
             if ((cmdp = find_ctab (sim_rem_single_mode[i] ? allowed_single_remote_cmds : (master_session ? allowed_master_remote_cmds : allowed_remote_cmds), gbuf))) {/* lookup command */
-                if (cmdp->action == &x_continue_cmd)
+                sim_debug (DBG_CMD, &sim_remote_console, "gbuf='%s', basecmd='%s', cmd='%s', action=%p, continue_cmd=%p, repeat_cmd=%p\n", gbuf, basecmdp->name, cmdp->name, cmdp->action, &x_continue_cmd, &x_repeat_cmd);
+                if (cmdp->action == &x_continue_cmd) {
+                    sim_debug (DBG_CMD, &sim_remote_console, "continue_cmd executing\n");
                     stat = SCPE_OK;
+                    }
                 else {
                     if (cmdp->action == &exit_cmd)
                         return SCPE_EXIT;
                     if (cmdp->action == &x_step_cmd) {
+                        sim_debug (DBG_CMD, &sim_remote_console, "step_cmd executing\n");
                         steps = 1;                      /* default of 1 instruction */
                         stat = SCPE_OK;
                         if (*cptr != 0) {               /* argument? */
-                             cptr = get_glyph (cptr, gbuf, 0);/* get next glyph */
-                             if (*cptr != 0)            /* should be end */
-                                 stat = SCPE_2MARG;
-                             else {
-                                 steps = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
-                                 if ((stat != SCPE_OK) || (steps <= 0)) /* error? */
-                                     stat = SCPE_ARG;
-                                 }
-                             }
+                            cptr = get_glyph (cptr, gbuf, 0);/* get next glyph */
+                            if (*cptr != 0)            /* should be end */
+                                stat = SCPE_2MARG;
+                            else {
+                                steps = (int32) get_uint (gbuf, 10, INT_MAX, &stat);
+                                if ((stat != SCPE_OK) || (steps <= 0)) /* error? */
+                                    stat = SCPE_ARG;
+                                }
+                            }
                         if (stat != SCPE_OK)
                             cmdp = NULL;
                         }
                     else {
                         if (cmdp->action == &x_run_cmd) {
-                            sim_switches |= SIM_SW_HIDE;/* Request Setup only */
+                            sim_debug (DBG_CMD, &sim_remote_console, "run_cmd executing\n");
+                            if (sim_con_stable_registers &&     /* can we process command now? */
+                                sim_rem_master_mode)
+                                sim_oline = lp;                 /* specify output socket */
+                            sim_switches |= SIM_SW_HIDE;        /* Request Setup only */
                             stat = basecmdp->action (cmdp->arg, cptr);
-                            sim_switches &= ~SIM_SW_HIDE;/* Done with Setup only mode */
+                            sim_switches &= ~SIM_SW_HIDE;       /* Done with Setup only mode */
                             if (stat == SCPE_OK) {
                                 /* switch to CONTINUE after x_run_cmd() did RUN setup */
                                 cmdp = find_ctab (allowed_master_remote_cmds, "CONTINUE");
                                 }
                             }
-                        else
-                            stat = SCPE_REMOTE;         /* force processing outside of sim_instr() */
+                        else {
+                            if (cmdp->action == &x_repeat_cmd) {
+                                sim_debug (DBG_CMD, &sim_remote_console, "repeat_cmd executing\n");
+                                stat = _rem_repeat_cmd_setup (i, &cptr);
+                                }
+                            else {
+                                if (sim_con_stable_registers && 
+                                    sim_rem_master_mode) {          /* can we process command now? */
+                                    sim_debug (DBG_CMD, &sim_remote_console, "Processing Command directly\n");
+                                    sim_oline = lp;                 /* specify output socket */
+                                    sim_remote_process_command ();
+                                    stat = SCPE_OK;                 /* any message has already been emitted */
+                                    }
+                                else {
+                                    sim_debug (DBG_CMD, &sim_remote_console, "Processing Command via SCPE_REMOTE\n");
+                                    stat = SCPE_REMOTE;             /* force processing outside of sim_instr() */
+                                    }
+                                }
+                            }
                         }
                     }
                 }
@@ -1136,14 +1384,36 @@ else
     return SCPE_OK;                                     /* keep going */
 }
 
+t_stat sim_rem_con_repeat_svc (UNIT *uptr)
+{
+int line = uptr - (sim_rem_con_unit + 2);
+
+sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_repeat_svc(line=%d) - interval=%d\n", line, sim_rem_repeat_interval[line]);
+if (sim_rem_repeat_interval[line]) {
+    sim_rem_repeat_pending[line] = TRUE;
+    sim_activate_after (uptr, sim_rem_repeat_interval[line]);       /* reschedule */
+    sim_activate_abs (&sim_rem_con_unit[1], -1);                    /* wake up to process */
+    }
+return SCPE_OK;
+}
+
 t_stat sim_rem_con_reset (DEVICE *dptr)
 {
 if (sim_rem_con_tmxr.lines) {
     int32 i;
 
-    for (i=0; i<sim_rem_con_tmxr.lines; i++)
-        if (sim_rem_con_tmxr.ldsc[i].conn)
-            break;
+    sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(lines=%d)\n", sim_rem_con_tmxr.lines);
+    for (i=0; i<MAX_REMOTE_SESSIONS; i++) {
+        sim_rem_con_unit[i + 2].flags = UNIT_DIS;
+        sim_rem_con_unit[i + 2].action = &sim_rem_con_repeat_svc;
+        }
+    for (i=0; i<sim_rem_con_tmxr.lines; i++) {
+        if (!sim_rem_con_tmxr.ldsc[i].conn)
+            continue;
+        sim_debug (DBG_REP, &sim_remote_console, "sim_rem_con_reset(line=%d, usecs=%d)\n", i, sim_rem_repeat_interval[i]);
+        if (sim_rem_repeat_interval[i])
+            sim_activate_after (sim_rem_con_unit + 2 + i, sim_rem_repeat_interval[i]);/* schedule */
+        }
     if (i != sim_rem_con_tmxr.lines)
         sim_activate_after (&dptr->units[1], 100000);   /* continue polling for open sessions */
     return sim_rem_con_poll_svc (&dptr->units[0]);      /* establish polling as needed */
@@ -1208,10 +1478,22 @@ sim_rem_con_tmxr.ldsc = (TMLN *)realloc (sim_rem_con_tmxr.ldsc, sizeof(*sim_rem_
 memset (sim_rem_con_tmxr.ldsc, 0, sizeof(*sim_rem_con_tmxr.ldsc)*lines);
 sim_rem_buf = (char **)realloc (sim_rem_buf, sizeof(*sim_rem_buf)*lines);
 memset (sim_rem_buf, 0, sizeof(*sim_rem_buf)*lines);
+sim_rem_act_buf = (char **)realloc (sim_rem_act_buf, sizeof(*sim_rem_act_buf)*lines);
+memset (sim_rem_act_buf, 0, sizeof(*sim_rem_act_buf)*lines);
+sim_rem_act_buf_size = (size_t *)realloc (sim_rem_act_buf_size, sizeof(*sim_rem_act_buf_size)*lines);
+memset (sim_rem_act_buf_size, 0, sizeof(*sim_rem_act_buf_size)*lines);
+sim_rem_act = (char **)realloc (sim_rem_act, sizeof(*sim_rem_act)*lines);
+memset (sim_rem_act, 0, sizeof(*sim_rem_act)*lines);
 sim_rem_buf_size = (int32 *)realloc (sim_rem_buf_size, sizeof(*sim_rem_buf_size)*lines);
 memset (sim_rem_buf_size, 0, sizeof(*sim_rem_buf_size)*lines);
 sim_rem_buf_ptr = (int32 *)realloc (sim_rem_buf_ptr, sizeof(*sim_rem_buf_ptr)*lines);
 memset (sim_rem_buf_ptr, 0, sizeof(*sim_rem_buf_ptr)*lines);
+sim_rem_repeat_interval = (uint32 *)realloc (sim_rem_repeat_interval, sizeof(*sim_rem_repeat_interval)*lines);
+memset (sim_rem_repeat_interval, 0, sizeof(*sim_rem_repeat_interval)*lines);
+sim_rem_repeat_pending = (t_bool *)realloc (sim_rem_repeat_pending, sizeof(*sim_rem_repeat_pending)*lines);
+memset (sim_rem_repeat_pending, 0, sizeof(*sim_rem_repeat_pending)*lines);
+sim_rem_repeat_action = (char **)realloc (sim_rem_repeat_action, sizeof(*sim_rem_repeat_action)*lines);
+memset (sim_rem_repeat_action, 0, sizeof(*sim_rem_repeat_action)*lines);
 sim_rem_single_mode = (t_bool *)realloc (sim_rem_single_mode, sizeof(*sim_rem_single_mode)*lines);
 memset (sim_rem_single_mode, 0, sizeof(*sim_rem_single_mode)*lines);
 sim_rem_read_timeouts = (uint32 *)realloc (sim_rem_read_timeouts, sizeof(*sim_rem_read_timeouts)*lines);
@@ -1346,7 +1628,8 @@ t_stat sim_show_kmap (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char
 {
 if (sim_devices[0]->dradix == 16)
     fprintf (st, "%s = %X\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
-else fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
+else
+    fprintf (st, "%s = %o\n", show_con_tab[flag].name, *(cons_kmap[flag & KMAP_MASK]));
 return SCPE_OK;
 }
 
@@ -1376,7 +1659,8 @@ t_stat sim_show_pchar (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST cha
 {
 if (sim_devices[0]->dradix == 16)
     fprintf (st, "pchar mask = %X", sim_tt_pchar);
-else fprintf (st, "pchar mask = %o", sim_tt_pchar);
+else
+    fprintf (st, "pchar mask = %o", sim_tt_pchar);
 if (sim_tt_pchar) {
     static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)", 
                                    "BS(^H)" , "HT(^I)",  "LF(^J)",  "VT(^K)",  "FF(^L)",  "CR(^M)",  "SO(^N)",  "SI(^O)",
@@ -1433,7 +1717,7 @@ r = sim_open_logfile (gbuf, FALSE, &sim_log, &sim_log_ref); /* open log */
 if (r != SCPE_OK)                                       /* error? */
     return r;
 if (!sim_quiet)
-    printf ("Logging to file \"%s\"\n", 
+    fprintf (stdout, "Logging to file \"%s\"\n", 
              sim_logfile_name (sim_log, sim_log_ref));
 fprintf (sim_log, "Logging to file \"%s\"\n", 
              sim_logfile_name (sim_log, sim_log_ref));  /* start of log */
@@ -1451,7 +1735,7 @@ if (cptr && (*cptr != 0))                               /* now eol? */
 if (sim_log == NULL)                                    /* no log? */
     return SCPE_OK;
 if (!sim_quiet)
-    printf ("Log file closed\n");
+    fprintf (stdout, "Log file closed\n");
 fprintf (sim_log, "Log file closed\n");
 sim_close_logfile (&sim_log_ref);                       /* close log */
 sim_log = NULL;
@@ -1467,7 +1751,8 @@ if (cptr && (*cptr != 0))
 if (sim_log)
     fprintf (st, "Logging enabled to \"%s\"\n", 
                  sim_logfile_name (sim_log, sim_log_ref));
-else fprintf (st, "Logging disabled\n");
+else
+    fprintf (st, "Logging disabled\n");
 return SCPE_OK;
 }
 
@@ -1591,7 +1876,8 @@ if (sim_deb) {
             }
         }
     }
-else fprintf (st, "Debug output disabled\n");
+else
+    fprintf (st, "Debug output disabled\n");
 return SCPE_OK;
 }
 
diff --git a/sim_console.h b/sim_console.h
index a36d452e..7f2d4901 100644
--- a/sim_console.h
+++ b/sim_console.h
@@ -113,6 +113,7 @@ SEND *sim_cons_get_send (void);
 EXPECT *sim_cons_get_expect (void);
 t_stat sim_show_cons_send_input (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char *cptr);
 t_stat sim_set_noconsole_port (void);
+t_stat sim_set_stable_registers_state (void);
 t_stat sim_poll_kbd (void);
 t_stat sim_putchar (int32 c);
 t_stat sim_putchar_s (int32 c);
diff --git a/sim_frontpanel.c b/sim_frontpanel.c
index f8ff5aab..fde13a2f 100644
--- a/sim_frontpanel.c
+++ b/sim_frontpanel.c
@@ -134,6 +134,7 @@ struct PANEL {
     size_t                  reg_count;
     REG                     *regs;
     char                    *reg_query;
+    int                     new_register;
     size_t                  reg_query_size;
     unsigned long long      array_element_data;
     OperationalState        State;
@@ -143,6 +144,8 @@ struct PANEL {
     int                     io_thread_running;
     pthread_mutex_t         io_lock;
     pthread_mutex_t         io_send_lock;
+    pthread_mutex_t         io_command_lock;
+    int                     command_count;
     int                     io_reg_query_pending;
     int                     io_waiting;
     char                    *io_response;
@@ -154,7 +157,7 @@ struct PANEL {
     pthread_t               callback_thread;
     int                     callback_thread_running;
     void                    *callback_context;
-    int                     callbacks_per_second;
+    int                     usecs_between_callbacks;
     int                     debug;
     char                    *simulator_version;
     int                     radix;
@@ -167,10 +170,16 @@ struct PANEL {
     };
 
 static const char *sim_prompt = "sim> ";
+static const char *register_repeat_prefix = "repeat every ";
+static const char *register_repeat_stop = "repeat stop";
+static const char *register_repeat_stop_all = "repeat stop all";
+static const char *register_repeat_units = " usecs ";
 static const char *register_get_prefix = "show time";
 static const char *register_get_echo = "# REGISTERS-DONE";
+static const char *register_repeat_echo = "# REGISTERS-REPEAT-DONE";
 static const char *register_dev_echo = "# REGISTERS-FOR-DEVICE:";
 static const char *register_ind_echo = "# REGISTER-INDIRECT:";
+static const char *command_status = "ECHO Status:%STATUS%-%TSTATUS%";
 static const char *command_done_echo = "# COMMAND-DONE";
 static int little_endian;
 static void *_panel_reader(void *arg);
@@ -209,7 +218,18 @@ if (p == NULL)
 return p;
 }
 
-static void _panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
+/* Allow compiler to help validate printf style format arguments */
+#if !defined __GNUC__
+#define GCC_FMT_ATTR(n, m)
+#endif
+#if !defined(GCC_FMT_ATTR)
+#define GCC_FMT_ATTR(n, m) __attribute__ ((format (__printf__, n, m)))
+#endif
+
+static void __panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...) GCC_FMT_ATTR(3, 6);
+#define _panel_debug(p, dbits, fmt, buf, bufsize, ...) do { if (p && p->Debug && (dbits & p->debug)) __panel_debug (p, dbits, fmt, buf, bufsize, ##__VA_ARGS__);} while (0)
+
+static void __panel_debug (PANEL *p, int dbits, const char *fmt, const char *buf, int bufsize, ...)
 {
 if (p && p->Debug && (dbits & p->debug)) {
     int i;
@@ -300,6 +320,7 @@ sim_panel_set_debug_file (PANEL *panel, const char *debug_file)
 if (!panel)
     return;
 panel->Debug = fopen(debug_file, "w");
+setvbuf (panel->Debug, NULL, _IOFBF, 65536);
 }
 
 void
@@ -348,13 +369,13 @@ return sent;
 }
 
 static int
-_panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...);
+_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...);
 
 static int
 _panel_register_query_string (PANEL *panel, char **buf, size_t *buf_size)
 {
 size_t i, j, buf_data, buf_needed = 0;
-char *dev;
+const char *dev;
 
 pthread_mutex_lock (&panel->io_lock);
 buf_needed = 2 + strlen (register_get_prefix);  /* SHOW TIME */
@@ -381,7 +402,7 @@ sprintf (*buf + buf_data, "%s\r", register_get_prefix);
 buf_data += strlen (*buf + buf_data);
 dev = "";
 for (i=j=0; i<panel->reg_count; i++) {
-    char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
+    const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
 
     if (panel->regs[i].indirect)
         continue;
@@ -412,9 +433,9 @@ for (i=j=0; i<panel->reg_count; i++) {
         }
     else {
         if (j == 0)
-            sprintf (*buf + buf_data, "E -H %s %s[0:%d]", dev, panel->regs[i].name, panel->regs[i].element_count-1);
+            sprintf (*buf + buf_data, "E -H %s %s[0:%d]", dev, panel->regs[i].name, (int)(panel->regs[i].element_count-1));
         else
-            sprintf (*buf + buf_data, ",%s[0:%d]", panel->regs[i].name, panel->regs[i].element_count-1);
+            sprintf (*buf + buf_data, ",%s[0:%d]", panel->regs[i].name, (int)(panel->regs[i].element_count-1));
         }
     ++j;
     buf_data += strlen (*buf + buf_data);
@@ -424,7 +445,7 @@ if (buf_data && ((*buf)[buf_data-1] != '\r')) {
     buf_data += strlen (*buf + buf_data);
     }
 for (i=j=0; i<panel->reg_count; i++) {
-    char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
+    const char *reg_dev = panel->regs[i].device_name ? panel->regs[i].device_name : "";
 
     if (!panel->regs[i].indirect)
         continue;
@@ -495,6 +516,7 @@ FILE *fOut = NULL;
 struct stat statb;
 char *buf = NULL;
 int port;
+int cmd_stat;
 size_t i, device_num;
 char hostport[64];
 union {int i; char c[sizeof (int)]; } end_test;
@@ -540,7 +562,6 @@ else {
             }
         else
             break;
-        
         }
     if (stat (sim_config, &statb) < 0) {
         sim_panel_set_error ("Can't stat simulator configuration '%s': %s", sim_config, strerror(errno));
@@ -599,6 +620,30 @@ if (debug_file) {
     sim_panel_set_debug_file (p, debug_file);
     sim_panel_set_debug_mode (p, DBG_XMT|DBG_RCV);
     _panel_debug (p, DBG_XMT|DBG_RCV, "Creating Simulator Process %s\n", NULL, 0, sim_path);
+
+    if (stat (p->temp_config, &statb) < 0) {
+        sim_panel_set_error ("Can't stat temporary simulator configuration '%s': %s", p->temp_config, strerror(errno));
+        goto Error_Return;
+        }
+    buf = (char *)_panel_malloc (statb.st_size+1);
+    if (buf == NULL)
+        goto Error_Return;
+    buf[statb.st_size] = '\0';
+    fIn = fopen (p->temp_config, "r");
+    if (fIn == NULL) {
+        sim_panel_set_error ("Can't open temporary configuration file '%s': %s", p->temp_config, strerror(errno));
+        goto Error_Return;
+        }
+    _panel_debug (p, DBG_XMT|DBG_RCV, "Using Temporary Configuration File '%s' containing:", NULL, 0, p->temp_config);
+    i = 0;
+    while (fgets (buf, statb.st_size, fIn)) {
+        ++i;
+        buf[strlen(buf) - 1] = '\0';
+        _panel_debug (p, DBG_XMT|DBG_RCV, "Line %2d: %s", NULL, 0, (int)i, buf);
+        }
+    free (buf);
+    buf = NULL;
+    fclose (fIn);
     }
 if (!simulator_panel) {
 #if defined(_WIN32)
@@ -659,9 +704,10 @@ if (p->sock == INVALID_SOCKET) {
         }
     goto Error_Return;
     }
-_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator at %s after %dms\n", NULL, 0, p->hostport, i*100);
+_panel_debug (p, DBG_XMT|DBG_RCV, "Connected to simulator on %s after %dms\n", NULL, 0, p->hostport, (int)i*100);
 pthread_mutex_init (&p->io_lock, NULL);
 pthread_mutex_init (&p->io_send_lock, NULL);
+pthread_mutex_init (&p->io_command_lock, NULL);
 pthread_cond_init (&p->io_done, NULL);
 pthread_cond_init (&p->startup_cond, NULL);
 if (sizeof(mantra) != _panel_send (p, (char *)mantra, sizeof(mantra))) {
@@ -696,7 +742,7 @@ else {
     if (p->State == Error)
         goto Error_Return;
     /* Validate sim_frontpanel API version */
-    if (_panel_sendf (p, 1, &p->simulator_version, "SHOW VERSION\r"))
+    if (_panel_sendf (p, &cmd_stat, &p->simulator_version, "SHOW VERSION\r"))
         goto Error_Return;
     if (1) {
         int api_version = 0;
@@ -712,7 +758,7 @@ else {
     if (1) {
         char *radix = NULL;
 
-        if (_panel_sendf (p, 1, &radix, "SHOW %s RADIX\r", p->device_name ? p->device_name : "")) {
+        if (_panel_sendf (p, &cmd_stat, &radix, "SHOW %s RADIX\r", p->device_name ? p->device_name : "")) {
             free (radix);
             goto Error_Return;
             }
@@ -807,18 +853,23 @@ if (panel) {
         int wait_count;
 
         /* First, wind down the automatic register queries */
-        sim_panel_set_display_callback (panel, NULL, NULL, 0);
-        /* Next, attempt a simulator shutdown */
-        _panel_send (panel, "\005\rEXIT\r", 7);
+        sim_panel_set_display_callback_interval (panel, NULL, NULL, 0);
+        /* Next, attempt a simulator shutdown only with the master panel */
+        if (panel->parent == NULL) {
+            if (panel->State == Run)
+                _panel_send (panel, "\005\r", 2);
+            _panel_send (panel, "EXIT\r", 5);
+            }
         /* Wait for up to 2 seconds for a graceful shutdown */
         for (wait_count=0; panel->io_thread_running && (wait_count<20); ++wait_count)
             msleep (100);
-        /* Now close the socket which should stop a pending read which hasn't completed */
+        /* Now close the socket which should stop a pending read that hasn't completed */
         panel->sock = INVALID_SOCKET;
         sim_close_sock (sock);
         pthread_join (panel->io_thread, NULL);
         pthread_mutex_destroy (&panel->io_lock);
         pthread_mutex_destroy (&panel->io_send_lock);
+        pthread_mutex_destroy (&panel->io_command_lock);
         pthread_cond_destroy (&panel->io_done);
         }
 #if defined(_WIN32)
@@ -881,11 +932,16 @@ _panel_add_register (PANEL *panel,
 REG *regs, *reg;
 char *response = NULL;
 size_t i;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
     }
+if (panel->State == Run) {
+    sim_panel_set_error ("Not Halted");
+    return -1;
+    }
 regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs)); 
 if (regs == NULL) {
     panel->State = Error;
@@ -953,7 +1009,7 @@ reg->size = size;
 reg->element_count = element_count;
 pthread_mutex_unlock (&panel->io_lock);
 /* Validate existence of requested register/array */
-if (_panel_sendf (panel, 1, &response, "EXAMINE %s %s%s\r", device_name? device_name : "", name, (element_count > 0) ? "[0]" : "")) {
+if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE %s %s%s\r", device_name? device_name : "", name, (element_count > 0) ? "[0]" : "")) {
     free (reg->name);
     free (reg->device_name);
     free (regs);
@@ -969,7 +1025,7 @@ if (!strcmp ("Invalid argument\r\n", response)) {
     }
 free (response);
 if (element_count > 0) {
-    if (_panel_sendf (panel, 1, &response, "EXAMINE %s %s[%d]\r", device_name? device_name : "", name, element_count-1)) {
+    if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE %s %s[%d]\r", device_name? device_name : "", name, element_count-1)) {
         free (reg->name);
         free (reg->device_name);
         free (regs);
@@ -989,6 +1045,7 @@ pthread_mutex_lock (&panel->io_lock);
 ++panel->reg_count;
 free (panel->regs);
 panel->regs = regs;
+panel->new_register = 1;
 pthread_mutex_unlock (&panel->io_lock);
 /* Now build the register query string for the whole register list */
 if (_panel_register_query_string (panel, &panel->reg_query, &panel->reg_query_size))
@@ -1028,14 +1085,14 @@ sim_panel_add_register_indirect (PANEL *panel,
 return _panel_add_register (panel, name, device_name, size, addr, 1, 0);
 }
 
-int
-sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
+static int
+_panel_get_registers (PANEL *panel, int calledback, unsigned long long *simulation_time)
 {
 if ((!panel) || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
     }
-if (panel->callback) {
+if ((!calledback) && (panel->callback)) {
     sim_panel_set_error ("Callback provides register data");
     return -1;
     }
@@ -1043,11 +1100,18 @@ if (!panel->reg_count) {
     sim_panel_set_error ("No registers specified");
     return -1;
     }
+pthread_mutex_lock (&panel->io_command_lock);
 pthread_mutex_lock (&panel->io_lock);
 if (panel->reg_query_size != _panel_send (panel, panel->reg_query, panel->reg_query_size)) {
     pthread_mutex_unlock (&panel->io_lock);
+    pthread_mutex_unlock (&panel->io_command_lock);
     return -1;
     }
+while (panel->io_reg_query_pending != 0) {
+    pthread_mutex_unlock (&panel->io_lock);
+    msleep (100);
+    pthread_mutex_lock (&panel->io_lock);
+    }
 ++panel->io_reg_query_pending;
 panel->io_waiting = 1;
 while (panel->io_waiting)
@@ -1055,14 +1119,21 @@ while (panel->io_waiting)
 if (simulation_time)
     *simulation_time = panel->simulation_time;
 pthread_mutex_unlock (&panel->io_lock);
+pthread_mutex_unlock (&panel->io_command_lock);
 return 0;
 }
 
 int
-sim_panel_set_display_callback (PANEL *panel, 
-                                PANEL_DISPLAY_PCALLBACK callback, 
-                                void *context, 
-                                int callbacks_per_second)
+sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time)
+{
+return _panel_get_registers (panel, 0, simulation_time);
+}
+
+int
+sim_panel_set_display_callback_interval (PANEL *panel, 
+                                         PANEL_DISPLAY_PCALLBACK callback, 
+                                         void *context, 
+                                         int usecs_between_callbacks)
 {
 if (!panel) {
     sim_panel_set_error ("Invalid Panel");
@@ -1071,10 +1142,10 @@ if (!panel) {
 pthread_mutex_lock (&panel->io_lock);
 panel->callback = callback;
 panel->callback_context = context;
-if (callbacks_per_second && (0 == panel->callbacks_per_second)) { /* Need to start callbacks */
+if (usecs_between_callbacks && (0 == panel->usecs_between_callbacks)) { /* Need to start/enable callbacks */
     pthread_attr_t attr;
 
-    panel->callbacks_per_second = callbacks_per_second;
+    panel->usecs_between_callbacks = usecs_between_callbacks;
     pthread_cond_init (&panel->startup_cond, NULL);
     pthread_attr_init(&attr);
     pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
@@ -1084,8 +1155,8 @@ if (callbacks_per_second && (0 == panel->callbacks_per_second)) { /* Need to sta
         pthread_cond_wait (&panel->startup_cond, &panel->io_lock); /* Wait for thread to stabilize */
     pthread_cond_destroy (&panel->startup_cond);
     }
-if ((callbacks_per_second == 0) && panel->callbacks_per_second) { /* Need to stop callbacks */
-    panel->callbacks_per_second = 0;
+if ((usecs_between_callbacks == 0) && panel->usecs_between_callbacks) { /* Need to stop callbacks */
+    panel->usecs_between_callbacks = 0;
     pthread_mutex_unlock (&panel->io_lock);
     pthread_join (panel->callback_thread, NULL);
     pthread_mutex_lock (&panel->io_lock);
@@ -1127,7 +1198,7 @@ if (panel->State == Run) {
     sim_panel_set_error ("Not Halted");
     return -1;
     }
-if (_panel_sendf (panel, 0, NULL, "BOOT %s\r", device))
+if (_panel_sendf (panel, NULL, NULL, "BOOT %s\r", device))
     return -1;
 panel->State = Run;
 return 0;
@@ -1148,7 +1219,7 @@ if (panel->State == Run) {
     sim_panel_set_error ("Not Halted");
     return -1;
     }
-if (_panel_sendf (panel, 0, NULL, "CONT\r", 5))
+if (_panel_sendf (panel, NULL, NULL, "CONT\r", 5))
     return -1;
 panel->State = Run;
 return 0;
@@ -1179,6 +1250,9 @@ return 0;
 int
 sim_panel_break_set (PANEL *panel, const char *condition)
 {
+char *response = NULL;
+int cmd_stat;
+
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
@@ -1192,14 +1266,22 @@ if (panel->State == Run) {
     return -1;
     }
     
-if (_panel_sendf (panel, 1, NULL, "BREAK %s\r", condition))
+if ((_panel_sendf (panel, &cmd_stat, &response, "BREAK %s\r", condition)) ||
+    (*response)) {
+        sim_panel_set_error ("Error establishing breakpoint at '%s': %s", condition, response ? response : "");
+    free (response);
     return -1;
+    }
+free (response);
 return 0;
 }
 
 int
 sim_panel_break_clear (PANEL *panel, const char *condition)
 {
+char *response = NULL;
+int cmd_stat;
+
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
@@ -1213,14 +1295,22 @@ if (panel->State == Run) {
     return -1;
     }
     
-if (_panel_sendf (panel, 1, NULL, "NOBREAK %s\r", condition))
+if ((_panel_sendf (panel, &cmd_stat, &response, "NOBREAK %s\r", condition)) ||
+    (*response)) {
+    sim_panel_set_error ("Error clearing breakpoint at '%s': %s", condition, response ? response : "");
+    free (response);
     return -1;
+    }
+free (response);
 return 0;
 }
 
 int
 sim_panel_break_output_set (PANEL *panel, const char *condition)
 {
+char *response = NULL;
+int cmd_stat;
+
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
@@ -1234,14 +1324,22 @@ if (panel->State == Run) {
     return -1;
     }
     
-if (_panel_sendf (panel, 1, NULL, "EXPECT %s\r", condition))
+if ((_panel_sendf (panel, &cmd_stat, &response, "EXPECT %s\r", condition)) ||
+    (*response)) {
+    sim_panel_set_error ("Error establishing output breakpoint for '%s': %s", condition, response ? response : "");
+    free (response);
     return -1;
+    }
+free (response);
 return 0;
 }
 
 int
 sim_panel_break_output_clear (PANEL *panel, const char *condition)
 {
+char *response = NULL;
+int cmd_stat;
+
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
@@ -1255,8 +1353,13 @@ if (panel->State == Run) {
     return -1;
     }
     
-if (_panel_sendf (panel, 1, NULL, "NOEXPECT %s\r", condition))
+if ((_panel_sendf (panel, &cmd_stat, &response, "NOEXPECT %s\r", condition)) ||
+    (*response)) {
+    sim_panel_set_error ("Error clearing output breakpoint for '%s': %s", condition, response ? response : "");
+    free (response);
     return -1;
+    }
+free (response);
 return 0;
 }
 
@@ -1279,6 +1382,7 @@ sim_panel_gen_examine (PANEL *panel,
 {
 char *response = NULL, *c;
 unsigned long long data = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
@@ -1288,7 +1392,7 @@ if (panel->State == Run) {
     sim_panel_set_error ("Not Halted");
     return -1;
     }
-if (_panel_sendf (panel, 1, &response, "EXAMINE -H %s", name_or_addr)) {
+if (_panel_sendf (panel, &cmd_stat, &response, "EXAMINE -H %s", name_or_addr)) {
     free (response);
     return -1;
     }
@@ -1325,6 +1429,7 @@ sim_panel_gen_deposit (PANEL *panel,
                        const void *value)
 {
 unsigned long long data = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
@@ -1338,7 +1443,7 @@ if (little_endian)
     memcpy (&data, value, size);
 else
     memcpy (((char *)&data) + sizeof(data)-size, value, size);
-if (_panel_sendf (panel, 1, NULL, "DEPOSIT -H %s %llx", name_or_addr, data))
+if (_panel_sendf (panel, &cmd_stat, NULL, "DEPOSIT -H %s %llx", name_or_addr, data))
     return -1;
 return 0;
 }
@@ -1367,6 +1472,7 @@ sim_panel_mem_examine (PANEL *panel,
 {
 char *response = NULL, *c;
 unsigned long long data = 0, address = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
@@ -1380,7 +1486,7 @@ if (little_endian)
     memcpy (&address, addr, addr_size);
 else
     memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
-if (_panel_sendf (panel, 1, &response, (panel->radix == 16) ? "EXAMINE -H %llx" : "EXAMINE -H %llo", address)) {
+if (_panel_sendf (panel, &cmd_stat, &response, (panel->radix == 16) ? "EXAMINE -H %llx" : "EXAMINE -H %llo", address)) {
     free (response);
     return -1;
     }
@@ -1422,6 +1528,7 @@ sim_panel_mem_deposit (PANEL *panel,
                        const void *value)
 {
 unsigned long long data = 0, address = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
@@ -1439,7 +1546,7 @@ else {
     memcpy (((char *)&data) + sizeof(data)-value_size, value, value_size);
     memcpy (((char *)&address) + sizeof(address)-addr_size, addr, addr_size);
     }
-if (_panel_sendf (panel, 1, NULL, (panel->radix == 16) ? "DEPOSIT -H %llx %llx" : "DEPOSIT -H %llo %llx", address, data))
+if (_panel_sendf (panel, &cmd_stat, NULL, (panel->radix == 16) ? "DEPOSIT -H %llx %llx" : "DEPOSIT -H %llo %llx", address, data))
     return -1;
 return 0;
 }
@@ -1460,6 +1567,8 @@ sim_panel_set_register_value (PANEL *panel,
                               const char *name,
                               const char *value)
 {
+int cmd_stat;
+
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
@@ -1468,7 +1577,7 @@ if (panel->State == Run) {
     sim_panel_set_error ("Not Halted");
     return -1;
     }
-if (_panel_sendf (panel, 1, NULL, "DEPOSIT %s %s", name, value))
+if (_panel_sendf (panel, &cmd_stat, NULL, "DEPOSIT %s %s", name, value))
     return -1;
 return 0;
 }
@@ -1487,30 +1596,42 @@ sim_panel_mount (PANEL *panel,
                  const char *switches,
                  const char *path)
 {
-char *response = NULL, *status = NULL;
+char *response = NULL;
+OperationalState OrigState;
+int stat = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
     }
-if (_panel_sendf (panel, 1, &response, "ATTACH %s %s %s", switches, device, path)) {
-    free (response);
-    return -1;
-    }
-if (_panel_sendf (panel, 1, &status, "ECHO %%STATUS%%")) {
-    free (response);
-    free (status);
-    return -1;
-    }
-if (!status || (strcmp (status, "00000000\r\n"))) {
-    sim_panel_set_error (response);
-    free (response);
-    free (status);
-    return -1;
+pthread_mutex_lock (&panel->io_lock);
+OrigState = panel->State;
+if (OrigState == Run) {
+    sim_panel_exec_halt (panel);
+    while (panel->State == Run) {
+        pthread_mutex_unlock (&panel->io_lock);
+        msleep (100);
+        pthread_mutex_lock (&panel->io_lock);
+        }
     }
+pthread_mutex_unlock (&panel->io_lock);
+do {
+    if (_panel_sendf (panel, &cmd_stat, &response, "ATTACH %s %s %s", switches, device, path)) {
+        stat = -1;
+        break;
+        }
+    if (cmd_stat) {
+        sim_panel_set_error (response);
+        stat = -1;
+        }
+    } while (0);
+pthread_mutex_lock (&panel->io_lock);
+if (OrigState == Run)
+    sim_panel_exec_run (panel);
+pthread_mutex_unlock (&panel->io_lock);
 free (response);
-free (status);
-return 0;
+return stat;
 }
 
 /**
@@ -1523,30 +1644,42 @@ int
 sim_panel_dismount (PANEL *panel,
                     const char *device)
 {
-char *response = NULL, *status = NULL;
+char *response = NULL;
+OperationalState OrigState;
+int stat = 0;
+int cmd_stat;
 
 if (!panel || (panel->State == Error)) {
     sim_panel_set_error ("Invalid Panel");
     return -1;
     }
-if (_panel_sendf (panel, 1, &response, "DETACH %s", device)) {
-    free (response);
-    return -1;
-    }
-if (_panel_sendf (panel, 1, &status, "ECHO %%STATUS%%")) {
-    free (response);
-    free (status);
-    return -1;
-    }
-if (!status || (strcmp (status, "00000000\r\n"))) {
-    sim_panel_set_error (response);
-    free (response);
-    free (status);
-    return -1;
+pthread_mutex_lock (&panel->io_lock);
+OrigState = panel->State;
+if (OrigState == Run) {
+    sim_panel_exec_halt (panel);
+    while (panel->State == Run) {
+        pthread_mutex_unlock (&panel->io_lock);
+        msleep (100);
+        pthread_mutex_lock (&panel->io_lock);
+        }
     }
+pthread_mutex_unlock (&panel->io_lock);
+do {
+    if (_panel_sendf (panel, &cmd_stat, &response, "DETACH %s", device)) {
+        stat = -1;
+        break;
+        }
+    if (cmd_stat) {
+        sim_panel_set_error (response);
+        stat = -1;
+        }
+    } while (0);
+pthread_mutex_lock (&panel->io_lock);
+if (OrigState == Run)
+    sim_panel_exec_run (panel);
+pthread_mutex_unlock (&panel->io_lock);
 free (response);
-free (status);
-return 0;
+return stat;
 }
 
 
@@ -1683,8 +1816,7 @@ while ((p->sock != INVALID_SOCKET) &&
                 else {
                     size_t name_len = strlen (p->regs[i].name);
 
-                    if ((0 == memcmp (p->regs[i].name, s, name_len), s) &&
-                        (s[name_len] == '[')) {
+                    if ((0 == memcmp (p->regs[i].name, s, name_len)) && (s[name_len] == '[')) {
                         size_t array_index = (size_t)atoi (s + name_len + 1);
                         size_t end_index = array_index;
                         char *end = strchr (s + name_len + 1, '[');
@@ -1714,22 +1846,23 @@ while ((p->sock != INVALID_SOCKET) &&
             *e = ':';
             /* Unexpected Register Data Found (or other output containing a : character) */
             }
-        if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
-            pthread_mutex_lock (&p->io_lock);
-            --p->io_reg_query_pending;
+        if (!strcmp (s + strlen (sim_prompt), register_repeat_echo)) {
             if (p->callback) {
                 pthread_mutex_unlock (&p->io_lock);
                 p->callback (p, p->simulation_time, p->callback_context);
                 }
-            else {
-                p->io_waiting = 0;
-                pthread_cond_signal (&p->io_done);
-                pthread_mutex_unlock (&p->io_lock);
-                }
+            }
+        if (!strcmp (s + strlen (sim_prompt), register_get_echo)) {
+            pthread_mutex_lock (&p->io_lock);
+            --p->io_reg_query_pending;
+            p->io_waiting = 0;
+            pthread_cond_signal (&p->io_done);
+            pthread_mutex_unlock (&p->io_lock);
             }
         else {
             pthread_mutex_lock (&p->io_lock);
             if (!strcmp (s + strlen (sim_prompt), command_done_echo)) {
+                _panel_debug (p, DBG_RCV, "Received Command Complete", NULL, 0);
                 p->io_waiting = 0;
                 pthread_cond_signal (&p->io_done);
                 }
@@ -1751,11 +1884,14 @@ while ((p->sock != INVALID_SOCKET) &&
                         p->io_response = t;
                         p->io_response_size = p->io_response_data + strlen (s) + 3;
                         }
+                    _panel_debug (p, DBG_RCV, "Receive Data Accumulated: '%s'", NULL, 0, s);
                     strcpy (p->io_response + p->io_response_data, s);
                     p->io_response_data += strlen(s);
                     strcpy (p->io_response + p->io_response_data, "\r\n");
                     p->io_response_data += 2;
                     }
+                else
+                    _panel_debug (p, DBG_RCV, "Receive Data Discarded: '%s'", NULL, 0, s);
                 }
             pthread_mutex_unlock (&p->io_lock);
             }
@@ -1794,6 +1930,7 @@ struct sched_param sched_priority;
 char *buf = NULL;
 size_t buf_data = 0;
 unsigned int callback_count = 0;
+int cmd_stat;
 
 /* 
    Boost Priority for timer thread so it doesn't compete 
@@ -1810,31 +1947,78 @@ pthread_cond_signal (&p->startup_cond);   /* Signal we're ready to go */
 msleep (100);
 pthread_mutex_lock (&p->io_lock);
 while ((p->sock != INVALID_SOCKET) && 
-       (p->callbacks_per_second) &&
+       (p->usecs_between_callbacks) &&
        (p->State != Error)) {
-    int rate = p->callbacks_per_second;
+    int interval = p->usecs_between_callbacks;
+    int new_register = p->new_register;
 
+    p->new_register = 0;
     pthread_mutex_unlock (&p->io_lock);
 
-    ++callback_count;
-    if (1 == callback_count%rate) {     /* once a second update the query string */
+    if (new_register)           /* need to get and send updated register info */
         _panel_register_query_string (p, &buf, &buf_data);
-        }
-    msleep (1000/rate);
+
+    /* twice a second activities:                                               */
+    /*  1) update the query string if it has changed                            */
+    /*     (only really happens at startup)                                     */
+    /*  2) update register state by polling if the simulator is halted          */
+    msleep (500);
     pthread_mutex_lock (&p->io_lock);
-    if (((p->State == Run) || ((p->State == Halt) && (0 == callback_count%(5*rate)))) &&
-        (p->io_reg_query_pending == 0)) {
-        ++p->io_reg_query_pending;
+    if (new_register) {
+        if (p->io_reg_query_pending == 0) {
+            size_t repeat_data = strlen (register_repeat_prefix) +  /* prefix */
+                                 20                              +  /* max int width */
+                                 strlen (register_repeat_units)  +  /* units and spacing */
+                                 buf_data                        +  /* command contents */
+                                 1                               +  /* carriage return */
+                                 strlen (register_repeat_echo)   +  /* auto repeat completion */
+                                 1                               +  /* carriage return */
+                                 1;                                 /* NUL */
+            char *repeat = (char *)malloc (repeat_data);
+            char *c;
+
+            sprintf (repeat, "%s%d%s%*.*s", register_repeat_prefix, 
+                                         p->usecs_between_callbacks, 
+                                         register_repeat_units, 
+                                         (int)buf_data, (int)buf_data, buf);
+            pthread_mutex_unlock (&p->io_lock);
+            for (c = strchr (repeat, '\r'); c != NULL; c = strchr (c, '\r'))
+                *c = ';';                               /* replace carriage returns with semicolons */
+            c = strstr (repeat, register_get_echo);     /* remove register_done_echo string and */
+            strcpy (c, register_repeat_echo);           /* replace it with the register_repeat_echo string */
+            if (_panel_sendf (p, &cmd_stat, NULL, "%s", repeat)) {
+                pthread_mutex_lock (&p->io_lock);
+                free (repeat);
+                break;
+                }
+            pthread_mutex_lock (&p->io_lock);
+            free (repeat);
+            }
+        else {                              /* already busy */
+            p->new_register = 1;            /* retry later */
+            _panel_debug (p, DBG_XMT, "Waiting on prior command completion before specifying repeat interval", NULL, 0);
+            }
+        }
+    /* when halted, we directly poll the halted system to get updated */
+    /* register state which may have changed due to panel activities */
+    if (p->State == Halt) {
         pthread_mutex_unlock (&p->io_lock);
-        if (buf_data != _panel_send (p, buf, buf_data)) {
+        if (_panel_get_registers (p, 1, NULL)) {
             pthread_mutex_lock (&p->io_lock);
             break;
             }
         pthread_mutex_lock (&p->io_lock);
         }
-    else
-        _panel_debug (p, DBG_XMT, "Waiting for prior register query completion", NULL, 0);
     }
+pthread_mutex_unlock (&p->io_lock);
+/* stop any established repeating activity in the simulator */
+if (p->parent == NULL)          /* Top level panel? */
+    _panel_sendf (p, &cmd_stat, NULL, "%s", register_repeat_stop_all);
+else {
+    if (p->State == Run)
+        _panel_sendf (p, &cmd_stat, NULL, "%s", register_repeat_stop);
+    }
+pthread_mutex_lock (&p->io_lock);
 p->callback_thread_running = 0;
 pthread_mutex_unlock (&p->io_lock);
 free (buf);
@@ -1905,13 +2089,13 @@ return;
 }
 
 static int
-_panel_sendf (PANEL *p, int wait_for_completion, char **response, const char *fmt, ...)
+_panel_sendf (PANEL *p, int *completion_status, char **response, const char *fmt, ...)
 {
 char stackbuf[1024];
 int bufsize = sizeof(stackbuf);
 char *buf = stackbuf;
-int len;
-int post_fix_len = wait_for_completion ? 5 + strlen (command_done_echo): 1;
+int len, status_echo_len = 0;
+int post_fix_len = completion_status ? 7 + sizeof (command_done_echo) + sizeof (command_status) : 1;
 va_list arglist;
 int ret;
 
@@ -1938,20 +2122,23 @@ while (1) {                                         /* format passed string, arg
     }
 
 if (len && (buf[len-1] != '\r')) {
-    strcat (buf, "\r");                 /* Make sure command line is terminated */
+    strcpy (&buf[len], "\r");           /* Make sure command line is terminated */
     ++len;
     }
 
-if (wait_for_completion) {
-    strcat (buf, command_done_echo);
-    strcat (buf, "\r");
+pthread_mutex_lock (&p->io_command_lock);
+++p->command_count;
+if (completion_status) {
+    sprintf (&buf[len], "%s\r%s\r", command_status, command_done_echo);
+    status_echo_len = strlen (&buf[len]);
     pthread_mutex_lock (&p->io_lock);
     p->io_response_data = 0;
     }
 
-ret = (strlen (buf) == _panel_send (p, buf, strlen (buf))) ? 0 : -1;
+_panel_debug (p, DBG_REQ, "Command %d Request%s: %*.*s", NULL, 0, p->command_count, completion_status ? " (with response)" : "", len, len, buf);
+ret = ((len + status_echo_len) == _panel_send (p, buf, len + status_echo_len)) ? 0 : -1;
 
-if (wait_for_completion) {
+if (completion_status) {
     if (!ret) {                                     /* Sent OK? */
         p->io_waiting = 1;
         while (p->io_waiting)
@@ -1959,16 +2146,33 @@ if (wait_for_completion) {
         if (response) {
             *response = (char *)_panel_malloc (p->io_response_data + 1);
             if (0 == memcmp (buf, p->io_response + strlen (sim_prompt), len)) {
+                char *eol, *status;
                 memcpy (*response, p->io_response + strlen (sim_prompt) + len + 1, p->io_response_data + 1 - (strlen (sim_prompt) + len + 1));
+                *completion_status = -1;
+                status = strstr (*response, command_status);
+                if (status) {
+                    *(status - strlen (sim_prompt)) = '\0';
+                    status += strlen (command_status) + 2;
+                    eol = strchr (status, '\r');
+                    if (eol)
+                        *eol = '\0';
+                    sscanf (status, "Status:%08X-", completion_status);
+                    }
                 }
             else
                 memcpy (*response, p->io_response, p->io_response_data + 1);
+            _panel_debug (p, DBG_RSP, "Command %d Response(Status=%d): '%s'", NULL, 0, p->command_count, *completion_status, *response);
+            }
+        else {
+            if (p->io_response_data)
+                _panel_debug (p, DBG_RSP, "Discarded Unwanted Command %d Response Data:", p->io_response, p->io_response_data, p->command_count);
             }
-        p->io_response_data = 0;
-        p->io_response[0] = '\0';
         }
+    p->io_response_data = 0;
+    p->io_response[0] = '\0';
     pthread_mutex_unlock (&p->io_lock);
     }
+pthread_mutex_unlock (&p->io_command_lock);
 
 if (buf != stackbuf)
     free (buf);
diff --git a/sim_frontpanel.h b/sim_frontpanel.h
index c01cc5b4..86aa4d6d 100644
--- a/sim_frontpanel.h
+++ b/sim_frontpanel.h
@@ -57,7 +57,7 @@ extern "C" {
 
 #if !defined(__VAX)         /* Unsupported platform */
 
-#define SIM_FRONTPANEL_VERSION   2
+#define SIM_FRONTPANEL_VERSION   3
 
 /**
 
@@ -128,7 +128,7 @@ sim_panel_destroy (PANEL *panel);
    simulator.
 
    The registers that a particular frontpanel application mught need 
-   access to are described by the application by calling: 
+   access to are described by the application when it calls: 
    
    sim_panel_add_register
    sim_panel_add_register_array
@@ -175,10 +175,10 @@ sim_panel_add_register_indirect (PANEL *panel,
     
        1)  The values can be polled (when ever it is desired) by calling
            sim_panel_get_registers().
-       2)  The panel can call sim_panel_set_display_callback() to specify a
-           callback routine and a periodic rate that the callback routine
-           should be called.  The panel API will make a best effort to deliver
-           the current register state at the desired rate.
+       2)  The panel can call sim_panel_set_display_callback_interval() to 
+           specify a callback routine and a periodic rate that the callback 
+           routine should be called.  The panel API will make a best effort 
+           to deliver the current register state at the desired rate.
 
 
    Note 1: The buffers described in a panel's register set will be 
@@ -203,10 +203,10 @@ typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
                                         void *context);
 
 int
-sim_panel_set_display_callback (PANEL *panel, 
-                                PANEL_DISPLAY_PCALLBACK callback, 
-                                void *context, 
-                                int callbacks_per_second);
+sim_panel_set_display_callback_interval (PANEL *panel, 
+                                         PANEL_DISPLAY_PCALLBACK callback, 
+                                         void *context, 
+                                         int usecs_between_callbacks);
 
 /**
 
@@ -450,6 +450,8 @@ sim_panel_set_debug_file (PANEL *panel, const char *debug_file);
 
 #define DBG_XMT         1   /* Transmit Data */
 #define DBG_RCV         2   /* Receive Data */
+#define DBG_REQ         4   /* Request Data */
+#define DBG_RSP         8   /* Response Data */
 
 void
 sim_panel_set_debug_mode (PANEL *panel, int debug_bits);