#include <tack.h>
#include <time.h>
MODULE_ID("$Id: sync.c,v 1.1.1.1 2001/11/29 20:40:59 jevans Exp $")
static void sync_home(struct test_list *, int *, int *);
static void sync_lines(struct test_list *, int *, int *);
static void sync_clear(struct test_list *, int *, int *);
static void sync_summary(struct test_list *, int *, int *);
struct test_list sync_test_list[] = {
{MENU_NEXT, 0, 0, 0, "b) baud rate test", sync_home, 0},
{MENU_NEXT, 0, 0, 0, "l) scroll performance", sync_lines, 0},
{MENU_NEXT, 0, 0, 0, "c) clear screen performance", sync_clear, 0},
{MENU_NEXT, 0, 0, 0, "p) summary of results", sync_summary, 0},
{0, 0, 0, 0, txt_longer_test_time, longer_test_time, 0},
{0, 0, 0, 0, txt_shorter_test_time, shorter_test_time, 0},
{MENU_LAST, 0, 0, 0, 0, 0, 0}
};
struct test_menu sync_menu = {
0, 'n', 0,
"Performance tests", "perf", "n) run standard tests",
sync_test, sync_test_list, 0, 0, 0
};
int tty_can_sync;
int tty_newline_rate;
int tty_clear_rate;
int tty_cps;
#define TTY_ACK_SIZE 64
int ACK_terminator;
int ACK_length;
const char *tty_ENQ;
char tty_ACK[TTY_ACK_SIZE];
int
tty_sync_error(void)
{
int ch, trouble, ack;
trouble = FALSE;
for (;;) {
tt_putp(tty_ENQ);
ch = getnext(STRIP_PARITY);
event_start(TIME_SYNC);
for (ack = 0; ; ) {
if (ack < TTY_ACK_SIZE - 2) {
tty_ACK[ack] = ch;
tty_ACK[ack + 1] = '\0';
}
if (ch == ACK_terminator) {
return trouble;
}
if (++ack >= ACK_length) {
return trouble;
}
ch = getnext(STRIP_PARITY);
if (event_time(TIME_SYNC) > 400000) {
break;
}
}
set_attr(0);
put_crlf();
if (trouble) {
return TRUE;
}
put_str(" -- sync -- ");
trouble = TRUE;
}
}
void
flush_input(void)
{
if (tty_can_sync == SYNC_TESTED && ACK_terminator >= 0) {
(void) tty_sync_error();
} else {
spin_flush();
}
}
static void
probe_enq_ok(void)
{
int tc, len, ulen;
put_str("Testing ENQ/ACK, standby...");
fflush(stdout);
can_test("u8 u9", FLAG_TESTED);
#ifdef user9
tty_ENQ = user9 ? user9 : "\005";
#else
tty_ENQ = "\005";
#endif
tc_putp(tty_ENQ);
event_start(TIME_SYNC);
read_key(tty_ACK, TTY_ACK_SIZE - 1);
if (event_time(TIME_SYNC) > 400000 || tty_ACK[0] == '\0') {
tty_can_sync = SYNC_FAILED;
ptext("\nThis program expects the ENQ sequence to be");
ptext(" answered with the ACK character. This will help");
ptext(" the program reestablish synchronization when");
ptextln(" the terminal is overrun with data.");
ptext("\nENQ sequence from (u9): ");
putln(expand(tty_ENQ));
ptext("ACK received: ");
putln(expand(tty_ACK));
#ifdef user8
len = user8 ? strlen(user8) : 0;
#else
len = 0;
#endif
sprintf(temp, "Length of ACK %d. Expected length of ACK %d.",
(int) strlen(tty_ACK), len);
ptextln(temp);
#ifdef user8
if (len) {
temp[0] = user8[len - 1];
temp[1] = '\0';
ptext("Terminating character found in (u8): ");
putln(expand(temp));
}
#endif
return;
}
tty_can_sync = SYNC_TESTED;
if ((len = strlen(tty_ACK)) == 1) {
ACK_terminator = tty_ACK[0];
ACK_length = 4096;
return;
}
tc = tty_ACK[len - 1];
#ifdef user8
if (user8) {
ulen = strlen(user8);
if (tc == user8[ulen - 1]) {
ACK_terminator = tc;
ACK_length = 4096;
return;
}
}
#endif
ACK_length = len;
ACK_terminator = -2;
}
void
verify_time(void)
{
int status, ch;
if (tty_can_sync == SYNC_FAILED) {
return;
}
probe_enq_ok();
put_crlf();
if (tty_can_sync == SYNC_TESTED) {
put_crlf();
if (ACK_terminator >= 0) {
ptext("ACK terminating character: ");
temp[0] = ACK_terminator;
temp[1] = '\0';
ptextln(expand(temp));
} else {
sprintf(temp, "Fixed length ACK, %d characters",
ACK_length);
ptextln(temp);
}
}
if (tty_baud_rate == 0) {
sync_home(&sync_test_list[0], &status, &ch);
}
}
void
sync_home(
struct test_list *t,
int *state,
int *ch)
{
int j, k;
unsigned long rate;
if (!cursor_home && !cursor_address && !row_address) {
ptext("Terminal can not home cursor. ");
generic_done_message(t, state, ch);
return;
}
if (skip_pad_test(t, state, ch,
"(home) Start baudrate search")) {
return;
}
pad_test_startup(1);
do {
go_home();
for (j = 1; j < lines; j++) {
for (k = 0; k < columns; k++) {
if (k & 0xF) {
put_this(letter);
} else {
put_this('.');
}
}
SLOW_TERMINAL_EXIT;
}
NEXT_LETTER;
} while(still_testing());
pad_test_shutdown(t, auto_right_margin == 0);
rate = (tx_cps * tty_frame_size) >> 1;
if (rate > tty_baud_rate) {
tty_baud_rate = rate;
}
if (tx_cps > tty_cps) {
tty_cps = tx_cps;
}
sprintf(temp, "%d characters per second. Baudrate %d ", tx_cps, j);
ptext(temp);
generic_done_message(t, state, ch);
}
static void
sync_lines(
struct test_list *t,
int *state,
int *ch)
{
int j;
if (skip_pad_test(t, state, ch,
"(nel) Start scroll performance test")) {
return;
}
pad_test_startup(0);
repeats = 100;
do {
sprintf(temp, "%d", test_complete);
put_str(temp);
put_newlines(repeats);
} while(still_testing());
pad_test_shutdown(t, 0);
j = sliding_scale(tx_count[0], 1000000, usec_run_time);
if (j > tty_newline_rate) {
tty_newline_rate = j;
}
sprintf(temp, "%d linefeeds per second. ", j);
ptext(temp);
generic_done_message(t, state, ch);
}
static void
sync_clear(
struct test_list *t,
int *state,
int *ch)
{
int j;
if (!clear_screen) {
ptext("Terminal can not clear-screen. ");
generic_done_message(t, state, ch);
return;
}
if (skip_pad_test(t, state, ch,
"(clear) Start clear-screen performance test")) {
return;
}
pad_test_startup(0);
repeats = 20;
do {
sprintf(temp, "%d", test_complete);
put_str(temp);
for (j = 0; j < repeats; j++) {
put_clear();
}
} while(still_testing());
pad_test_shutdown(t, 0);
j = sliding_scale(tx_count[0], 1000000, usec_run_time);
if (j > tty_clear_rate) {
tty_clear_rate = j;
}
sprintf(temp, "%d clear-screens per second. ", j);
ptext(temp);
generic_done_message(t, state, ch);
}
static void
sync_summary(
struct test_list *t,
int *state,
int *ch)
{
char size[32];
put_crlf();
ptextln("Terminal size characters/sec linefeeds/sec clears/sec");
sprintf(size, "%dx%d", columns, lines);
sprintf(temp, "%-10s%-11s%11d %11d %11d", tty_basename, size,
tty_cps, tty_newline_rate, tty_clear_rate);
ptextln(temp);
generic_done_message(t, state, ch);
}
void
sync_test(
struct test_menu *menu)
{
control_init();
if (tty_can_sync == SYNC_NOT_TESTED) {
verify_time();
}
if (menu->menu_title) {
put_crlf();
ptextln(menu->menu_title);
}
}
void
sync_handshake(
struct test_list *t GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
tty_can_sync = SYNC_NOT_TESTED;
verify_time();
}