TMXR: Support input speed limits with a multiplier factor

Many simulators run instructions one or more orders of magnitude faster
than the original systems did.  Limiting simulated serial port input speeds
to legacy bits per second values presents the arriving data much slower
than the original systems ever saw it.  Given the processing capacity of the
simulated systems and the fact that the software and device interfaces
only know how to deal with the legacy speed values there is a need to
provide a way to allow input to arrive faster.  This problem is solved by
providing a speed factor as a part of a speed specification.  For example
a speed can be specified as "speed*factor" or "9600*10".
This commit is contained in:
Mark Pizzolato 2015-11-27 13:47:53 -08:00
parent a18a4f42b9
commit f322f4b044
3 changed files with 51 additions and 14 deletions

View file

@ -1333,8 +1333,12 @@ return tmxr_set_line_speed (&sim_con_ldsc, cptr);
t_stat sim_show_cons_speed (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
{
if (sim_con_ldsc.rxbps)
fprintf (st, "Speed = %dbps\n", sim_con_ldsc.rxbps);
if (sim_con_ldsc.rxbps) {
fprintf (st, "Speed = %d", sim_con_ldsc.rxbps);
if (sim_con_ldsc.rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE)
fprintf (st, "*%.0f", sim_con_ldsc.rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE);
fprintf (st, " bps\n");
}
return SCPE_OK;
}
@ -1923,7 +1927,7 @@ if (sim_send_poll_data (&sim_con_send, &c)) /* injected input ch
return c;
if (!sim_rem_master_mode) {
if ((sim_con_ldsc.rxbps) && /* rate limiting && */
(sim_con_ldsc.rxnexttime > sim_gtime ())) /* too soon? */
(sim_gtime () < sim_con_ldsc.rxnexttime)) /* too soon? */
return SCPE_OK; /* not yet */
c = sim_os_poll_kbd (); /* get character */
if (c == SCPE_STOP) { /* ^E */
@ -1934,7 +1938,7 @@ if (!sim_rem_master_mode) {
(sim_con_ldsc.serport == 0)) { /* and not serial? */
if (c && sim_con_ldsc.rxbps) /* got something && rate limiting? */
sim_con_ldsc.rxnexttime = /* compute next input time */
sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/1000000.0);
sim_gtime () + ((sim_con_ldsc.rxdelta * sim_timer_inst_per_sec ())/sim_con_ldsc.rxbpsfactor);
return c; /* in-window */
}
if (!sim_con_ldsc.conn) { /* no telnet or serial connection? */
@ -2196,6 +2200,7 @@ return NULL;
t_stat sim_ttinit (void)
{
sim_con_tmxr.ldsc->mp = &sim_con_tmxr;
sim_register_internal_device (&sim_con_telnet);
tmxr_startup ();
return sim_os_ttinit ();

View file

@ -1565,7 +1565,7 @@ if ((lp->conn && lp->rcve) && /* conn & enb & */
if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */
lp->rxbpi = lp->rxbpr = 0;
if (val && lp->rxbps)
lp->rxnexttime = sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ())/1000000.0);
lp->rxnexttime = sim_gtime () + ((lp->rxdelta * sim_timer_inst_per_sec ())/lp->rxbpsfactor);
tmxr_debug_return(lp, val);
return val;
}
@ -2187,10 +2187,10 @@ struct {
{"115200", TMLN_SPD_115200_BPS},
{"0", 0}}; /* End of List, last valid value */
int nspeed;
char speed[20];
char speed[24];
nspeed = (uint32)strtotv (cptr, &cptr, 10);
if ((*cptr != '\0') && (*cptr != '-'))
if ((*cptr != '\0') && (*cptr != '-') && (*cptr != '*'))
return -1;
sprintf (speed, "%d", nspeed);
@ -2208,12 +2208,20 @@ return -1;
t_stat tmxr_set_line_speed (TMLN *lp, const char *speed)
{
UNIT *uptr;
const char *cptr;
t_stat r;
if (!speed || !*speed)
return SCPE_2FARG;
if (_tmln_speed_delta (speed) < 0)
return SCPE_ARG;
lp->rxbps = atoi (speed);
lp->rxbps = (uint32)strtotv (speed, &cptr, 10);
if (*cptr == '*') {
uint32 rxbpsfactor = (uint32) get_uint (cptr+1, 10, 32, &r);
if (r != SCPE_OK)
return r;
lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE * rxbpsfactor;
}
lp->rxdelta = _tmln_speed_delta (speed);
lp->rxnexttime = 0;
uptr = lp->uptr;
@ -2221,6 +2229,8 @@ if ((!uptr) && (lp->mp))
uptr = lp->mp->uptr;
if (uptr)
uptr->wait = lp->rxdelta;
if (lp->rxbpsfactor == 0.0)
lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE;
return SCPE_OK;
}
@ -2256,6 +2266,8 @@ for (i = 0; i < mp->lines; i++) { /* initialize lines */
lp = mp->ldsc + i;
lp->mp = mp; /* set the back pointer */
lp->modem_control = mp->modem_control;
if (lp->rxbpsfactor == 0.0)
lp->rxbpsfactor = TMXR_RX_BPS_UNIT_SCALE;
}
tmxr_debug_trace (mp, "tmxr_open_master()");
while (*tptr) {
@ -3567,6 +3579,14 @@ else {
free (attach);
tmxr_show_summ(st, NULL, 0, mp);
fprintf(st, ", sessions=%d", mp->sessions);
if (mp->lines == 1) {
if (mp->ldsc->rxbps) {
fprintf(st, ", Speed=%d", mp->ldsc->rxbps);
if (mp->ldsc->rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE)
fprintf(st, "*%.0f", mp->ldsc->rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE);
fprintf(st, " bps");
}
}
fprintf(st, "\n");
for (j = 0; j < mp->lines; j++) {
lp = mp->ldsc + j;
@ -3582,13 +3602,14 @@ else {
fprintf(st, ", ModemControl=%s", lp->modem_control ? "enabled" : "disabled");
if (lp->loopback)
fprintf(st, ", Loopback");
if (lp->rxbps)
fprintf(st, ", Speed=%dbps", lp->rxbps);
if (lp->rxbps) {
fprintf(st, ", Speed=%d", lp->rxbps);
if (lp->rxbpsfactor != TMXR_RX_BPS_UNIT_SCALE)
fprintf(st, "*%.0f", lp->rxbpsfactor/TMXR_RX_BPS_UNIT_SCALE);
fprintf(st, " bps");
}
fprintf (st, "\n");
}
else
if (lp->rxbps)
fprintf(st, ", Speed=%dbps", lp->rxbps);
if ((!lp->sock) && (!lp->connecting) && (!lp->serport) && (!lp->master)) {
if (lp->modem_control)
tmxr_fconns (st, lp, -1);
@ -3858,13 +3879,22 @@ fprintf (st, "port as fast as it arrives.\n\n");
fprintf (st, "If a simulated multiplexor devices can programmatically set a serial\n");
fprintf (st, "port line speed, the programmatically specified speed will take precidence\n");
fprintf (st, "over any input speed specified on an attach command.\n");
fprintf (st, "Some simulated systems run very much faster than the original system\n");
fprintf (st, "which is being simulated. To accomodate this, the speed specified may\n");
fprintf (st, "include a factor which will increase the input data delivery rate by\n");
fprintf (st, "the specified facctor. A factor is specified with a speed value of the\n");
fprintf (st, "form \"speed*factor\". Factor values can range from 1 thru 32.\n");
fprintf (st, "Example:\n\n");
fprintf (st, " sim> ATTACH %s 1234,SPEED=2400\n", dptr->name);
fprintf (st, " sim> ATTACH %s 1234,SPEED=9600*8\n", dptr->name);
if (!single_line)
fprintf (st, " sim> ATTACH %s Line=2,SPEED=2400\n", dptr->name);
fprintf (st, "\n");
fprintf (st, "The SPEED parameter only influences the rate at which data is deliverd\n");
fprintf (st, "into the simulated multiplexor port. Output data rates are unaffected\n\n");
fprintf (st, "into the simulated multiplexor port. Output data rates are unaffected\n");
fprintf (st, "If an attach command specifies a speed multiply factor, that value will\n");
fprintf (st, "persist independent of any programatic action by the simulated system to\n");
fprintf (st, "change the port speed.\n\n");
fprintf (st, "An optional serial port configuration string may be present after the port\n");
fprintf (st, "name. If present, it must be separated from the port name with a semicolon\n");
fprintf (st, "and has this form:\n\n");

View file

@ -167,6 +167,8 @@ struct tmln {
uint32 rxpbsize; /* rcv packet buffer size */
uint32 rxpboffset; /* rcv packet buffer offset */
uint32 rxbps; /* rcv bps speed (0 - unlimited) */
double rxbpsfactor; /* receive speed factor (scaled to usecs) */
#define TMXR_RX_BPS_UNIT_SCALE 1000000.0
uint32 rxdelta; /* rcv inter character min time (usecs) */
double rxnexttime; /* min time for next receive character */
uint8 *txpb; /* xmt packet buffer */