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 @@
+
@@ -116,6 +119,9 @@
+
@@ -126,7 +132,7 @@
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="1"
OmitFramePointers="true"
- WholeProgramOptimization="true"
+ WholeProgramOptimization="false"
AdditionalIncludeDirectories="./;../;../VAX/;../pdp11/;"../../windows-build/winpcap/Wpdpack/Include";"../../windows-build/PCRE/include/";"../../windows-build/pthreads""
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; itxbsz)
- 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; iunits[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; ireg_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; ireg_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; ireg_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);