2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
4 ** This file is part of TACK.
6 ** TACK is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2, or (at your option)
11 ** TACK is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
16 ** You should have received a copy of the GNU General Public License
17 ** along with TACK; see the file COPYING. If not, write to
18 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, USA.
25 MODULE_ID("$Id: sync.c,v 1.3 2001/06/16 17:55:48 tom Exp $")
27 /* terminal-synchronization and performance tests */
29 static void sync_home(struct test_list *, int *, int *);
30 static void sync_lines(struct test_list *, int *, int *);
31 static void sync_clear(struct test_list *, int *, int *);
32 static void sync_summary(struct test_list *, int *, int *);
34 struct test_list sync_test_list[] = {
35 {MENU_NEXT, 0, 0, 0, "b) baud rate test", sync_home, 0},
36 {MENU_NEXT, 0, 0, 0, "l) scroll performance", sync_lines, 0},
37 {MENU_NEXT, 0, 0, 0, "c) clear screen performance", sync_clear, 0},
38 {MENU_NEXT, 0, 0, 0, "p) summary of results", sync_summary, 0},
39 {0, 0, 0, 0, txt_longer_test_time, longer_test_time, 0},
40 {0, 0, 0, 0, txt_shorter_test_time, shorter_test_time, 0},
41 {MENU_LAST, 0, 0, 0, 0, 0, 0}
44 struct test_menu sync_menu = {
46 "Performance tests", "perf", "n) run standard tests",
47 sync_test, sync_test_list, 0, 0, 0
50 int tty_can_sync; /* TRUE if tty_sync_error() returned FALSE */
51 int tty_newline_rate; /* The number of newlines per second */
52 int tty_clear_rate; /* The number of clear-screens per second */
53 int tty_cps; /* The number of characters per second */
55 #define TTY_ACK_SIZE 64
57 int ACK_terminator; /* terminating ACK character */
58 int ACK_length; /* length of ACK string */
59 const char *tty_ENQ; /* enquire string */
60 char tty_ACK[TTY_ACK_SIZE]; /* ACK response, set by tty_sync_error() */
62 /*****************************************************************************
64 * Terminal synchronization.
66 * These functions handle the messy business of enq-ack handshaking
67 * for timing purposes.
69 *****************************************************************************/
78 tt_putp(tty_ENQ); /* send ENQ */
79 ch = getnext(STRIP_PARITY);
80 event_start(TIME_SYNC); /* start the timer */
83 The timer doesn't start until we get the first character.
84 After that I expect to get the remaining characters of
85 the acknowledge string in a short period of time. If
86 that is not true then these characters are coming from
87 the user and we need to send the ENQ sequence out again.
90 if (ack < TTY_ACK_SIZE - 2) {
92 tty_ACK[ack + 1] = '\0';
94 if (ch == ACK_terminator) {
97 if (++ack >= ACK_length) {
100 ch = getnext(STRIP_PARITY);
101 if (event_time(TIME_SYNC) > 400000) {
106 set_attr(0); /* just in case */
109 /* The terminal won't sync. Life is not good. */
112 put_str(" -- sync -- ");
120 ** Throw away any output.
125 if (tty_can_sync == SYNC_TESTED && ACK_terminator >= 0) {
126 (void) tty_sync_error();
135 ** does the terminal do enq/ack handshaking?
142 put_str("Testing ENQ/ACK, standby...");
144 can_test("u8 u9", FLAG_TESTED);
147 tty_ENQ = user9 ? user9 : "\005";
152 event_start(TIME_SYNC); /* start the timer */
153 read_key(tty_ACK, TTY_ACK_SIZE - 1);
155 if (event_time(TIME_SYNC) > 400000 || tty_ACK[0] == '\0') {
156 /* These characters came from the user. Sigh. */
157 tty_can_sync = SYNC_FAILED;
158 ptext("\nThis program expects the ENQ sequence to be");
159 ptext(" answered with the ACK character. This will help");
160 ptext(" the program reestablish synchronization when");
161 ptextln(" the terminal is overrun with data.");
162 ptext("\nENQ sequence from (u9): ");
163 putln(expand(tty_ENQ));
164 ptext("ACK received: ");
165 putln(expand(tty_ACK));
167 len = user8 ? strlen(user8) : 0;
171 sprintf(temp, "Length of ACK %d. Expected length of ACK %d.",
172 (int) strlen(tty_ACK), len);
176 temp[0] = user8[len - 1];
178 ptext("Terminating character found in (u8): ");
185 tty_can_sync = SYNC_TESTED;
186 if ((len = strlen(tty_ACK)) == 1) {
187 /* single character acknowledge string */
188 ACK_terminator = tty_ACK[0];
192 tc = tty_ACK[len - 1];
195 ulen = strlen(user8);
196 if (tc == user8[ulen - 1]) {
197 /* ANSI style acknowledge string */
204 /* fixed length acknowledge string */
212 ** verify that the time tests are ready to run.
213 ** If the baud rate is not set then compute it.
220 if (tty_can_sync == SYNC_FAILED) {
225 if (tty_can_sync == SYNC_TESTED) {
227 if (ACK_terminator >= 0) {
228 ptext("ACK terminating character: ");
229 temp[0] = ACK_terminator;
231 ptextln(expand(temp));
233 sprintf(temp, "Fixed length ACK, %d characters",
238 if (tty_baud_rate == 0) {
239 sync_home(&sync_test_list[0], &status, &ch);
243 /*****************************************************************************
245 * Terminal performance tests
247 * Find out how fast the terminal can:
248 * 1) accept characters
249 * 2) scroll the screen
250 * 3) clear the screen
252 *****************************************************************************/
255 ** sync_home(test_list, status, ch)
268 if (!cursor_home && !cursor_address && !row_address) {
269 ptext("Terminal can not home cursor. ");
270 generic_done_message(t, state, ch);
273 if (skip_pad_test(t, state, ch,
274 "(home) Start baudrate search")) {
280 for (j = 1; j < lines; j++) {
281 for (k = 0; k < columns; k++) {
291 } while(still_testing());
292 pad_test_shutdown(t, auto_right_margin == 0);
293 /* note: tty_frame_size is the real framesize times two.
294 This takes care of half bits. */
295 rate = (tx_cps * tty_frame_size) >> 1;
296 if (rate > tty_baud_rate) {
297 tty_baud_rate = rate;
299 if (tx_cps > tty_cps) {
302 sprintf(temp, "%d characters per second. Baudrate %d ", tx_cps, j);
304 generic_done_message(t, state, ch);
308 ** sync_lines(test_list, status, ch)
310 ** How many newlines/second?
320 if (skip_pad_test(t, state, ch,
321 "(nel) Start scroll performance test")) {
327 sprintf(temp, "%d", test_complete);
329 put_newlines(repeats);
330 } while(still_testing());
331 pad_test_shutdown(t, 0);
332 j = sliding_scale(tx_count[0], 1000000, usec_run_time);
333 if (j > tty_newline_rate) {
334 tty_newline_rate = j;
336 sprintf(temp, "%d linefeeds per second. ", j);
338 generic_done_message(t, state, ch);
342 ** sync_clear(test_list, status, ch)
344 ** How many clear-screens/second?
355 ptext("Terminal can not clear-screen. ");
356 generic_done_message(t, state, ch);
359 if (skip_pad_test(t, state, ch,
360 "(clear) Start clear-screen performance test")) {
366 sprintf(temp, "%d", test_complete);
368 for (j = 0; j < repeats; j++) {
371 } while(still_testing());
372 pad_test_shutdown(t, 0);
373 j = sliding_scale(tx_count[0], 1000000, usec_run_time);
374 if (j > tty_clear_rate) {
377 sprintf(temp, "%d clear-screens per second. ", j);
379 generic_done_message(t, state, ch);
383 ** sync_summary(test_list, status, ch)
385 ** Print out the test results.
396 ptextln("Terminal size characters/sec linefeeds/sec clears/sec");
397 sprintf(size, "%dx%d", columns, lines);
398 sprintf(temp, "%-10s%-11s%11d %11d %11d", tty_basename, size,
399 tty_cps, tty_newline_rate, tty_clear_rate);
401 generic_done_message(t, state, ch);
407 ** Run at the beginning of the pad tests and function key tests
411 struct test_menu *menu)
414 if (tty_can_sync == SYNC_NOT_TESTED) {
417 if (menu->menu_title) {
419 ptextln(menu->menu_title);
424 ** sync_handshake(test_list, status, ch)
426 ** Test or retest the ENQ/ACK handshake
430 struct test_list *t GCC_UNUSED,
431 int *state GCC_UNUSED,
434 tty_can_sync = SYNC_NOT_TESTED;