
/****************************************************************************/
/*      TMK for Windows. ELCUS, 1995,2008.                                  */
/****************************************************************************/

//#define ENG

//#define STEND

#define TMK_CONFIGURATION_TABLE

#include <conio.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <process.h>
#include <stdlib.h>

#include <windows.h>
#include "tmkinit.c"

#define CR 0x0D                 /* возврат каретки */
#define LF 0x0A
#define CTRL_C 0x03
#define ESCAPE 0x1B
#define BACKSPACE 0x08
#define TAB 0x09
                                /* расширенные коды ASCII */
#define F01 0x3B00
#define F02 0x3C00
#define F03 0x3D00
#define F04 0x3E00
#define F05 0x3F00
#define F06 0x4000
#define F07 0x4100
#define F08 0x4200
#define F09 0x4300
#define F10 0x4400
#define PGUP 0x4900
#define PGDN 0x5100
#define HOME 0x4700
#define END 0x4F00
#define LEFT 0x4B00
#define RIGHT 0x4D00
#define UP 0x4800
#define DOWN 0x5000
#define GPLUSW 0x4E2B
#define GPLUS 0x4E00

#define BC_BUF_SIZE 64                 /* размер буфера */
#define BC_DUMP_SIZE 36                 /* количество выводимых в дампе слов */
#define CC_SIZE 4                       /* количество битов в коде управления */
#define TIME_OUT 0x0300                 /* время ожидания прерывания от ТМК */

#define DUMP_WIDE 10                    /* количество слов в строке */

#define RT_BUF_SIZE 32                  /* размер буфера */
#define RT_DUMP_SIZE 32                 /* количество выводимых в дампе слов */
#define SW_SIZE 5                       /* количество битов в ответном слове */
#define ZONE_MASK 0x0020    /* маска для работы с битом приема/передачи */
#define RT_MASK 0x0080      /* маска установки режима ОУ */

/* общие функции */
#ifdef STEND
unsigned short lpt_data_port, lpt_status_port, lpt_ctrl_port;
int lpt_num = 1;                         /* номер используемого LPT */
void init_lpt();                         /* определение адресов портов */
void set_lpt_data(unsigned short char data);   /* вывод данных в порт LPT */
#endif
void in_cmd(char *str);                  /* прием командной строки */
int in_key();                            /* ввод символа с проверкой прерывания */
void check_int();                        /* обнаружение прерывания и оповещение */
void make_func(unsigned short key);      /* обработка функциональных клавиш */
void make_ctrl(int key);                 /* обработка управляющих кодов */
void make_cmd(char *str);                /* обработка командной строки */
void make_quit();                        /* поддержка выхода из отладчика */
void select_win(char *str);              /* выбор окна */
void select_tmk(char *str);              /* выбор платы для окна */
void mode_bc(char *str);                 /* установка режима КК */
void mode_rt(char *str);                 /* установка режима ОУ */
//void mode_mt(char *str);               /* установка режима МТ */
void select_tmk(char *str);              /* выбор платы для окна */
void comment(char *str);                 /* вывод коментария */
void kbd_pause(char *str);               /* программируемая пауза */
void fields_chg(char *str);              /* управление выделением полей */
// void prtscr_brk();                      /* обработчик прерывания PrtScr */
void cmds_open(char *str);               /* открытие командного файла */
void cmds_open2(char *str);              /* выполнение командного файла  в цикле */
void cmd_reset(char *str);               /* сброс контроллера */
void buf_fill(char *str);                /* заполнение буфера константой */
void buf_clear(char *str);               /* очистка буфера */
void buf_edit(char *str);                /* редактирование буферной памяти */
int mark_set(char *str, int *mark);       /* ввод текущего слова для редактирования */
int end_ctrl(char *str);                 /* контроль конца строки */
void msg_out(char *msg);                 /* вывод строки сообщения */
void all_screen();                       /* вывод всего экрана */
void out_func_str();                     /* назначение функциональных клавиш */
void out_mode();                         /* вывод режима работы */
void set_io_delay(char *str);
void out_port(unsigned short wPort);     /* вывод порта платы */
void out_irq(unsigned short wIrq);       /* вывод номера прерывания платы */
void out_type();                         /* вывод типа платы */
void out_fname();                        /* вывод имени последнего файла данных */
void out_inn();                          /* вывод номера прерывания */
void out_buffer();                       /* вывод дампа буфера */
void bin_unpack(int x, int y, int adr, int data);/* двоичная развертка */
void out_dump(unsigned short *data);           /* вывод дампа */
void out_bin(int data, int num_digits);   /* вывод в двоичной форме */
void select_window(int nwin);
void set_stat_len(char *str);            /* задание циклов накопления статистики
                                            в автоматических тестах */
void CheckTmkEvent(int fWaitEvent);

/* функции для КК */
void bc_help(char *str);                 /* вывод подсказки */
void bc_clear_ram();                     /* обнуление БЗУ КК */
int bc_ram_test(char *str);              /* тестирование БЗУ КК */
void bc_buf_rd(char *str);               /* чтение в буфер из файла */
void bc_buf_wr(char *str);               /* запись буфера в файл */
void sym(char *str);                     /* симметрирование */
void statistic_out(char *str);           /* вывод статистики канала */
void statistic_bad_out(char *str);       /* вывод статистики сбоев канала */
void statistic_clear(char *str);         /* очистка переменных статистики */
int start_loop(char *str);               /* запуск в цикле */
int start_loop_n(unsigned long counter); /* запуск в цикле */
int start_1(char *str);                  /* однократный запуск */
int start();                             /* запуск */
void set_base(char *str);                /* установка базы */
void set_count(char *str);               /* установка циклов повторения команды */
void set_pause(char *str);               /* установка паузы */
void set_ctrl_code(char *str);           /* команда установки кода управления */
void set_number(char *str);              /* команда установки номера канала */
void out_number();                       /* вывод номера канала */
void out_base();                         /* вывод базы */
void out_count();                        /* вывод значения счетчика повторений */
void out_pause();                        /* вывод значения паузы */
void out_ctrl_code();                    /* вывод кода управления */
void bc_out_sw();                        /* вывод регистра слова состояния */
void bc_out_ram(TMK_DATA base);               /* вывод дампа страницы БЗУ */
int correct_cc(int ctrl_code);           /* проверка корректности упр. кода */

/* функции для ОУ */
void block_data_irq(char *str);          /* блокировка прерывания данных */
void unblock_data_irq(char *str);        /* разблокировка прерывания данных */
void rt_clear_ram();                     /* обнуление БЗУ ОУ */
int rt_ram_test(char *str);              /* тестирование БЗУ ОУ */
void rt_help(char *str);                 /* вывод подсказки */
void rt_buf_rd(char *str);               /* чтение в буфер из файла */
void rt_buf_wr(char *str);               /* запись буфера в файл */
void set_flag(char *str);                /* установка флагов */
void rd_sw_loop(char *str);              /* чтение слова состояния в цикле */
void wr_mr_loop(char *str);              /* циклическая запись в РРЖ */
int set_subadr(char *str);               /* ввод подадреса */
void set_spage(char *str);               /* установка текущей страницы БЗУ */
void set_cpage(char *str);               /* установка текущей страницы МК */
void set_page(char *str);                /* установка текущей страницы */
void set_at(char *str);                  /* установка адреса терминала */
int wr_at(TMK_DATA at);                       /* запись адреса терминала в ОУ */
void set_subadr_r(char *str);            /* установка подадареса, зона приема */
void set_subadr_t(char *str);            /* установка подадареса, зона приема */
void set_status_word(char *str);         /* команда установки ответного слова (ОС) */
void set_sw_bits(char *str, TMK_DATA mask);    /* функции установки отдельных битов ОС */
void read_sw(char *str);                 /* чтение слова состояния */
void clear_sw_bits(char *str, TMK_DATA mask);  /* функции очистки отдельных битов ОС */
void wr_status_word();                   /* запись битов ОС */
void out_rt_mode();
void out_page();                         /* вывод номера страницы МК */
void out_subadr();                       /* вывод базы */
void out_at();                           /* вывод адреса терминала */
void out_status_word();                  /* вывод битов ОС */
void rt_out_sw();                        /* вывод слова состояния */
void rt_out_ram(TMK_DATA dir, TMK_DATA subadr);     /* вывод дампа подадреса БЗУ */

const BC_DUMP_STRINGS=BC_DUMP_SIZE/DUMP_WIDE+1;
const RT_DUMP_STRINGS=RT_DUMP_SIZE/DUMP_WIDE+1;
const BDUMP_X=10, BDUMP_Y=6;
int DUMP_STRINGS;
int DUMP_SIZE;

char cmd_str[80];               /* буфер введенной команды */
char old_cmd[80];               /* буфер старой командной строки */
char ex_fname[80];              /* буфер циклически выполняемого ком. файла */
long cmd_count=1;               /* счетчик повторения команды */
long cur_count;                 /* текущий счетчик цикла повторения */
int str_ptr=0;                  /* указатель в буфере ввода с консоли */

volatile unsigned short bc_sw=0xFFFF; /* слово состояния обмена */
volatile unsigned short bc_aw1=0xFFFF;/* первое ответное слово, если bc_sw != 0 */
volatile unsigned short bc_aw2=0xFFFF;/* второе ответное слово, если bc_sw != 0 */
TMK_DATA base;                       /* база в БЗУ */
TMK_DATA bus_num;                    /* номер канала */
unsigned short ctrl_code=0x0;         /* код управления */
unsigned short opause=0;              /* определяет время между стартами в мкс */
unsigned short pause=0;         /* определяет время между стартами в периодах
                                   таймера */

volatile int prtscr_flag=0;     /* флаг нажатия PrtScr */
volatile int int_num[MAX_TMK_NUMBER+1]; /* номер прерывания */
                                /* переменные статистики: */
#define BADLEN 100
volatile unsigned short bad_sws[BADLEN];
volatile unsigned short bad_aws[BADLEN];
volatile unsigned long bad_sts[BADLEN];
volatile unsigned long good_starts=0;/* количество нормальных */
volatile unsigned long bad_starts=0; /* и аварийных завершений обмена в МК, */
unsigned long to_errors=0;           /* стартов не завершившихся прерыванием */
unsigned long data_err=0;
unsigned long channel_err=0;
int fAAAA=1;

unsigned short buffer[64];            /* буфер ПЭВМ */
unsigned short vbuffer[64];           /* дополнительный буфер */
int buf_adr=0;                  /* база в буфере */
int buf_mark=0;                 /* номер слова в буфере выводимого в BIN */
int in_ed_word=3;               /* определяет текущую тетраду при редактировании */
int buf_size;                   /* текущий размер буфера */
int fields=1;                   /* режим вывода полей управляющего слова
                                   1 - поля выводятся, 0 - нет */

volatile unsigned short rt_sw=0xFFFF;/* слово состояния */
volatile unsigned short rt_cmd=0;    /* команда ОУ */
int fLock=0;
TMK_DATA dir;                       /* направление передачи подадреса */
TMK_DATA subadr;                    /* подадрес в БЗУ */
TMK_DATA terminal_adr;              /* адрес ОУ в канале */
TMK_DATA bram_page;                 /* текущая страница БЗУ со стороны ПЭВМ */
TMK_DATA cram_page;                 /* текущая страница БЗУ со стороны канала */

HANDLE hIn, hOut;

int nMaxTMK;
int fInitBad = 0;

#define WAIT_EVENT 1
#define NO_WAIT_EVENT 0
int fGlobalWaitEvent = WAIT_EVENT;

SECURITY_ATTRIBUTES sa4Event;
//HANDLE hvxd;
HANDLE hEvent[MAX_TMK_NUMBER+1], hStartEvent, hBcEvent, ahWaitEvents[MAX_TMK_NUMBER+2];
int anWaitTmks[MAX_TMK_NUMBER+1];
int nWaitEvents;

/*
int aTmkLock[MAX_TMK_NUMBER+1];
int aRtArbLock[MAX_TMK_NUMBER+1];
int aRtAnswLock[MAX_TMK_NUMBER+1];
*/

/*
#define WAIT_PROXY 1
#define NO_WAIT_PROXY 0

pid_t aTmkProxy[MAX_TMK_NUMBER+1];
pid_t aProxy[MAX_TMK_NUMBER+1];
int aProxyTmkNum[MAX_TMK_NUMBER+1];

int nProxies = 0;

TTmkProxyData TmkProxyData;
*/

int nwin;                      /* текущее выводимое окно */
int nmainwin = 0;              /* текущее рабочее окно */
/*const int nMaxWin = 1;*/
#define nMaxWin 1
int fInt = 0;
char chLU, chRU, chLD, chRD, chH, chV;

struct TW
{
 int nX;
 int nY;
 int nDX;
 int nDY;
 int nTMK;
 int nType;
 int nMode;
 int fVisible;
 int at_avail;
 char data_fname[13];
};

struct TW Window[nMaxWin+1] = { { 1, 1, 80, 11, 0, -1, UNDEFINED_MODE, 0, 0, "" }, 
                         { 1, 12, 80, 11, 0, -1, UNDEFINED_MODE, 0, 0, "" } };

// void (*oldvect3)();/* старое значение вектора PrtScr */

FILE *in_file;                  /* файл ввода данных в буфер */
FILE *out_file;                 /* файл вывода данных из буфер */
FILE *cmd_file;                 /* файл ввода команд */

char buf_str[100];              /* буфер для работы с файлом ввода */
int fSkipCmds=0;                /* флаг прер. выполнения командного файла */
int enter_mode=0;               /* режим ввода команд: 0 - с консоли, 
                                                       1 - из файла */
                                /* таблица корректности упр. кодов (1) */
char ccs[16]={1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0};
                                /* указатели на сообщения об ошибках */
#ifdef ENG
char *inp_err="Input error";
char *base_err="Wrong base number";
char *bus_num_err="Wrong bus number";
char *bad_ctrl_code="Wrong control code";
char *cc_no_def="Control code XXXX not defined";
char *mark_err="Wrong word address";
char *undef_cmd="Command doesn't exist";
char *const_err="Wrong constant";
char *cr_err="File creation error";
char *open_err="File open error";
char *format_err="File format error";
char *bc_reset_ok="Bus Controller reset OK";
char *rt_reset_ok="Remote Terminal reset OK";
char *subadr_err="Wrong subaddress";
char *bad_status_word="Error in status word";
char *no_int="Time-out exit";
char *int_ok="Interrupt";
char *kbd_break="Aborted by user";
#else
char *inp_err="Ошибка ввода";
char *base_err="Неверное значение базы";
char *bus_num_err="Неправильный номер канала";
char *bad_ctrl_code="Ошибка в коде управления";
char *cc_no_def="Код управления XXXX не определен";
char *mark_err="Некорректный адрес слова";
char *undef_cmd="Введена несуществующая команда";
char *const_err="Неверное значение константы";
char *cr_err="Ошибка создания файла";
char *open_err="Ошибка открытия файла";
char *format_err="Ошибка формата входного файла";
char *bc_reset_ok="Сброс контроллера канала";
char *rt_reset_ok="Сброс оконечного устройства";
char *subadr_err="Неверное значение подадреса";
char *bad_status_word="Ошибка в ответном слове";
char *no_int="Выход по тайм-ауту";
char *int_ok="Прерывание";
char *kbd_break="Цикл прерван";
#endif

#define TIMER_CTRL_PORT 0x43       /* порт управления таймером */
#define TIMER0_PORT 0x40           /* порт данных таймера 0 */
#define _30_MCSEC 36               /* задержка 30 мкс */
#define _660_MCSEC 790             /* задержка 660 мкс */
#define _5000_MCSEC 5966           /* задержка 5 мс */
#define TEST_RTFL 1
#define TEST_MASK_RTFL 2
#define TEST_UNMASK_RTFL 3
#define TEST_SSFL 4
#define TEST_BUSY 5
#define TEST_SREQ 6
#define TEST_DNBA_OFF 7
#define TEST_DNBA_ON 8
#define TEST_RESET 9
#define TEST_SYNC 10
#define TEST_GET_VECTOR 11
#define TEST_GET_SELFTEST 12
#define TEST_SYNC_DATA 13
#define TEST_AT 14
#define TEST_BUSY1 15
#define TEST_NOBUSY1 16
#define TEST_COUNTER 17
#define TEST_RT_RT_BRCST 18
#define TEST_COUNTER_RT_BC 19
#define TEST_COUNTER_BC_RT 20
#define TEST_DNBA 21
#define TEST_BRCST_CMD 22
#define TEST_BRCST_BIT 23
#define TEST_ERROR 24
#define TEST_SYNC_DATA1 25
#define TEST_SYNC_DATA_BRCST 26
#define TEST_NO_RT_15 27
#define TEST_RT_15 28
#define TEST_NO_RT_0A 29
#define TEST_RT_0A 30
#define TEST_OTHER_AT 31
#define TEST_BLOCK_TR 32
#define TEST_UNBLOCK_TR 33
#define TEST_BLOCKED_TR 34
#define TEST_UNBLOCKED_TR 35
#define TEST_RT_DATA_IRQ 36
#define TEST_RT_DATA_IRQ_BL 37

#define DNB 0x400                  /* Динамическое управление */
#define SYNC 0x401                 /* Синхронизация */
#define GET_SW 0x402               /* Передать ответное слово */
#define START_SELFTEST 0x403       /* Начать самоконтроль */
#define BLOCK_TRANSMIT 0x404       /* Блокировать передатчик */
#define UNBLOCK_TRANSMIT 0x405     /* Разблокировать передатчик */
#define MASK_RTFL 0x406            /* Подавить бит флага терминала */
#define UNMASK_RTFL 0x407          /* Отменить подавление бита флага терминала */
#define RESET 0x408                /* Установить исходное состояние ОУ */
#define GET_VECTOR 0x410           /* Передать векторное слово */
#define SYNC_DATA 0x011            /* Синхронизация с ИС */
#define GET_CMD 0x412              /* Передать последнее командное слово */
#define GET_SELFTEST 0x413         /* Передать слово встроенного контроля */
#define BLOCK_SEL_TRANSMIT 0x04    /* Блокировать выбранный передатчик */
#define UNBLOCK_SEL_TRANSMIT 0x015 /* Разблокировать выбранный передатчик */

int statistic_bc_rt(TMK_DATA st_base, TMK_DATA st_subadr, TMK_DATA st_data);
int statistic_rt_bc(TMK_DATA st_subadr, TMK_DATA st_base, TMK_DATA st_data);
void avt_bc(char *str);         /* поддержка проверки КК */
void avt_rt(char *str);         /* поддержка проверки ОУ */
void avt_ctrl(char *str);       /* управление выводом на экран */
int cmp_ram_buf(int offset, int voffset, int size);

char *err_msg;
int bcwin, rtwin;
int bcnum, rtnum;
TMK_DATA rtadr, rtadr1, rtadr2;
unsigned short ci_field;
int hb_mode = 1;
TMK_DATA subadr1, subadr2, subadr0, dir0, len;
int avt_out = 1;
int avt_ok;
int fReserv = 0;
unsigned short nMainBus = BUS_A, nReservBus = BUS_B;

  long GL_COUNTER = 500;                      /* счетчик стартов */
  long GL_COUNTER2 = 1000; /*GL_COUNTER * 2;         /* счетчик стартов 2 */
  long GL_COUNTER3 = 2000; /*GL_COUNTER * 4;         /* счетчик стартов 3 */

int avtomat=0;                  /* флаг работы в автоматическом режиме:
                                0 - выключен, 1 - включен */

unsigned long err_level=10;     /* количество предельно допустимых ошибок */

DWORD biostime1;
//struct timespec biostime1;

int WinXMin = 0x20, 
    WinXMax = 0x20 + 79, 
    WinYMin = 0x20, 
    WinYMax = 0x20 + 24;
int WinXSav, WinYSav;
int ForeColor = 7, BackColor = 0, ForeIntens = 0;

#define BLACK 0
#define BLUE 1
#define GREEN 2
#define CYAN 3
#define RED 4
#define MAGENTA 5
#define BROWN 6
#define LIGHTGRAY 7
#define DARKGRAY 8
#define LIGHTBLUE 9
#define LIGHTGREEN 10
#define LIGHTCYAN 11
#define LIGHTRED 12
#define LIGHTMAGENTA 13
#define YELLOW 14
#define WHITE 15

unsigned long biostime(int dummy1, long dummy2)
{
 return ((GetTickCount() - biostime1) / 55L);
}
/*
unsigned long biostime(int dummy1, long dummy2)
{
 struct timespec biostime2;

 getclock(TIMEOFDAY, &biostime2);
 return ((biostime2.tv_sec-biostime1.tv_sec)*1000L+
         biostime2.tv_nsec/1000000L-biostime1.tv_nsec/1000000L)/55L;
}
*/

void window(int xmin, int ymin, int xmax, int ymax)
{
 WinXMin = xmin - 1;
 WinYMin = ymin - 1;
 WinXMax = xmax - 1;
 WinYMax = ymax - 1;
}

void gotoxy(int x, int y)
{
 COORD xy;

 WinXSav = x;
 WinYSav = y;
 xy.X = WinXMin + x - 1;
 xy.Y = WinYMin + y - 1;
 SetConsoleCursorPosition(hOut, xy);
// printf("\x1B=%c%c", WinYMin+y+0x1E, WinXMin+x+0x1E);
}

void textcolor(int color)
{
 ForeColor = color;
 SetConsoleTextAttribute(hOut, ForeColor + BackColor);
/*
 ForeColor = color & 0x07;
 ForeIntens = color & 0x08;
 printf("\x1B@%c%c", ForeColor, BackColor);
 if (ForeIntens)
  printf("\x1B<");
 else
  printf("\x1B>");
*/ 
}

void textbackground(int color)
{
 BackColor = color;
 SetConsoleTextAttribute(hOut, ForeColor + BackColor);
/*
 BackColor = color & 0x07;
 printf("\x1B@%c%c", ForeColor, BackColor);
*/
}

void clrscr()
{
 int x, y;

 for (y = WinYMin; y<=WinYMax; y++)
 {
  gotoxy(1, y-WinYMin+1);
  for (x=WinXMin; x<=WinXMax; x++)
   putchar(' ');
 } 
 gotoxy(1, 1);
}

void clreol()
{
 int x;
 for (x=WinXMin; x<=WinXMax; x++)
  putchar(' ');
 gotoxy(1, WinYSav);
}

WORD awKeyBuffer[32];
int nKeyBufferStart = 0;
int nKeyBufferLength = 0;

void CheckInput()
{
 DWORD dwResult;
 INPUT_RECORD ir;

 while (WaitForSingleObject(hIn, 0) == WAIT_OBJECT_0)
 {
  ReadConsoleInput(hIn, &ir, 1, &dwResult);
  if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
  {
   if (ir.Event.KeyEvent.wVirtualScanCode == 0x58) //F12
   {
    prtscr_flag = 1;
    continue;
   }
   if (nKeyBufferLength < 32)
    awKeyBuffer[(nKeyBufferStart + nKeyBufferLength++) & 31] = (WORD)ir.Event.KeyEvent.uChar.AsciiChar | (ir.Event.KeyEvent.wVirtualScanCode << 8);
  }
 }
}

unsigned short bioskey()
{
 unsigned short key;

 while (nKeyBufferLength == 0)
  CheckInput();
 key = awKeyBuffer[nKeyBufferStart++];
 nKeyBufferStart &= 31;
 --nKeyBufferLength;
 return key;
}

int kbhit()
{
 CheckInput();
 return (nKeyBufferLength > 0);
}

unsigned short get_timer()
{
 unsigned short t;
/*
 outportb(TIMER_CTRL_PORT, 0x00);
 t = (unsigned short)inportb(TIMER0_PORT);
 t |= (unsigned short)inportb(TIMER0_PORT)<<8;
*/
 return t;
}

int test_start(int test_mode)
{
 int result = 1;
 unsigned short cmdw;
 int fWaitRtIntr;
 unsigned long p;

 switch (test_mode)
 {
// case TEST_RTFL:
// case TEST_SSFL:
// case TEST_BUSY:
// case TEST_SREQ:
 case TEST_DNBA_OFF:
 case TEST_DNBA_ON:
// case TEST_RESET:
 case TEST_SYNC:
 case TEST_GET_VECTOR:
 case TEST_GET_SELFTEST:
 case TEST_SYNC_DATA:
// case TEST_OTHER_AT:
 case TEST_RT_DATA_IRQ:
// case TEST_RT_DATA_IRQ_BL:
  fWaitRtIntr = 1;
  break;
 default:
  fWaitRtIntr = 0;
 }
 if (fWaitRtIntr)
   CheckTmkEvent(NO_WAIT_EVENT);
 int_num[rtnum] = 0;
 start_1("");
 if (fWaitRtIntr)
 {
//   printf("TEST%d", test_mode);
   p = biostime(0, 0L);  /* ожидание прерывания 2 (10) тика */
   do
   {
    if (int_num[rtnum] != 0) break;
    CheckTmkEvent(fGlobalWaitEvent);
//    CheckTmkProxy(NO_WAIT_PROXY);
   }
   while (biostime(0, 0L) - p < 10);
 }
 cmdw = bcgetw(0);
 switch (test_mode)
 {
 case TEST_RTFL:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | RTFL_MASK) && 1)
//      rt_cmd == SYNC)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_MASK_RTFL:
  if (int_num[bcnum] == 1 && 1)
//      rt_cmd == MASK_RTFL)
   result = 0;
  break;
 case TEST_UNMASK_RTFL:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | RTFL_MASK) && 1)
//      rt_cmd == UNMASK_RTFL)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_SSFL:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | SSFL_MASK) && 1)
//      rt_cmd == SYNC)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_BUSY:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | BUSY_MASK) && 1)
//      rt_cmd == SYNC)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_SREQ:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | SREQ_MASK) && 1)
//      rt_cmd == SYNC)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
 case TEST_DNBA_OFF:
  if (int_num[bcnum] == 1 &&
      rt_cmd == DNB)
   result = 0;
  break;
 case TEST_DNBA_ON:
  if (int_num[bcnum] == 2 &&
      bc_aw1 == ((rtadr<<11) | DNBA_MASK) &&
      rt_cmd == DNB)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_RESET:
  if (int_num[bcnum] == 1 && 1)
//      rt_cmd == RESET)
   result = 0;
  break;
 case TEST_SYNC:
  if (int_num[bcnum] == 1 &&
      rt_cmd == SYNC
      && int_num[rtnum] == 1)
   result = 0;
  break;
 case TEST_GET_VECTOR:
  if (int_num[bcnum] == 1 &&
      bcgetw(2) == 0xFACE &&
      rt_cmd == GET_VECTOR)
   result = 0;
  break;
 case TEST_GET_SELFTEST:
  if (int_num[bcnum] == 1 &&
      bcgetw(2) == 0xBABA &&
      rt_cmd == GET_SELFTEST)
   result = 0;
  break;
 case TEST_SYNC_DATA:
  if (int_num[bcnum] == 1 &&
      rt_cmd == SYNC_DATA)
  {
   tmkselect(rtnum);
   if (rtgetcmddata(SYNC_DATA) == 0xA5A5)
    result = 0;
   tmkselect(bcnum);
  }
  break;
 case TEST_OTHER_AT:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_TO_MASK)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_AT:
  if (int_num[bcnum] == 1 &&
      bcgetw(1) == (rtadr<<11))
   result = 0;
  break;
 case TEST_BUSY1:
  if (int_num[bcnum] == 2 &&
      ((dir == RT_RECEIVE && bc_sw == S_IB_MASK) ||
       (dir == RT_TRANSMIT && bc_sw == (S_IB_MASK | S_TO_MASK))) &&
        bc_aw1 == ((rtadr<<11) | BUSY_MASK))
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_NOBUSY1:
  if (int_num[bcnum] == 1)
  {
   result = 0;
  }
  break;
 case TEST_COUNTER:
  if (int_num[bcnum] == 1)
  {
   result = 0;
  }
  break;
 case TEST_COUNTER_RT_BC:
 case TEST_COUNTER_BC_RT:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_RT_RT_BRCST:
  if (int_num[bcnum] == 1 &&
      !cmp_ram_buf(0, 3, 32))
  {
   result = 0;
  }
  break;
 case TEST_DNBA:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_IB_MASK &&
      bc_aw1 == ((rtadr<<11) | DNBA_MASK))
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_BRCST_CMD:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_BRCST_BIT:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_IB_MASK &&
      bc_aw1 == ((rtadr<<11) | BRCST_MASK))
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_ERROR:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_IB_MASK &&
      bc_aw1 == ((rtadr<<11) | ERROR_MASK))
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_SYNC_DATA1:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_SYNC_DATA_BRCST:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_NO_RT_15:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_TO_MASK)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_RT_15:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_NO_RT_0A:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_TO_MASK)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_RT_0A:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_BLOCK_TR:
 case TEST_UNBLOCK_TR:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_BLOCKED_TR:
  if (int_num[bcnum] == 2 &&
      bc_sw == S_TO_MASK)
  {
   result = 0;
   good_starts++;
   bad_starts--;
  }
  break;
 case TEST_UNBLOCKED_TR:
  if (int_num[bcnum] == 1 &&
      bc_sw == 0)
  {
   result = 0;
  }
  break;
 case TEST_RT_DATA_IRQ:
  if (int_num[bcnum] == 1 &&
      int_num[rtnum] == 3)
  {
   result = 0;
  }
  break;
 case TEST_RT_DATA_IRQ_BL:
  if (int_num[bcnum] == 1 &&
      int_num[rtnum] == 0)
  {
   result = 0;
  }
  break;
 }
 return result;
}

void make_test1(int start)
{
 unsigned short data;
 int k;

 data = 0;
 for (k = start; k <= start+31; k++)
 {
  buffer[k] = data;
  switch (data)
  {
  case 0x0000:
   data = 0x0001;
   break;
  case 0x8000:
   data = 0xAAAA;
   break;
  case 0xAAAA:
   data = 0x5555;
   break;
  case 0x5555:
   data = 0xAAAA;
   break;
  default:
   data <<= 1;
  }
 }
}

/************************************************************************/
/*                      Начало секции для КК                            */
/*                      Bus Controller Tests                            */
/************************************************************************/

void avt_bc(char *str)                  /* поддержка проверки КК */
{
 int k, maxbase, err;
 unsigned long times, nBusSwapTime;

 while (*str == '\t' || *str == ' ') str++;
 if (*str)
 {
  if (sscanf(str, "%U", &times) != 1)
  {
   msg_out(inp_err);
   return;
  }
 }
 else
  times=1;
 if (Window[0].nMode == BC_MODE)
  bcwin = 0;
 else if (Window[1].nMode == BC_MODE)
  bcwin = 1;
 else
 {
#ifdef ENG
  msg_out("BC not defined");
#else
  msg_out("Не задан КК");
#endif
  return;
 }
 if (Window[0].nMode == RT_MODE)
  rtwin = 0;
 else if (Window[1].nMode == RT_MODE)
  rtwin = 1;
 else
 {
#ifdef ENG
  msg_out("RT not defined");
#else
  msg_out("Не задано ОУ");
#endif
  return;
 }
 bcnum = Window[bcwin].nTMK;
 rtnum = Window[rtwin].nTMK;
 avt_ctrl("1");
 avt_ok = 0;
 select_window(bcwin);
 if (fReserv)
 {
  nReservBus = ((nMainBus=bcgetbus()) == BUS_A) ? BUS_B : BUS_A;
  bus_num = nMainBus;
  out_number();
  nBusSwapTime = times+1;
  times <<= 1;
 }
 select_window(rtwin);
 wr_at(rtadr=0x0A); out_at();
 set_status_word("0"); /* сбросить все биты ОС */
 select_window(rtwin);
#ifdef ENG
 comment("Bus Controller automatic test.");
#else
 comment("Автоматический тест контроллера канала.");
#endif
 select_window(bcwin);
 statistic_clear("");
 if (hb_mode)
 {
  subadr1 = 0x10;
  subadr2 = 0x1E;
  ci_field = 0x1F<<5;
 }
 else
 {
  subadr1 = 0x01;
  subadr2 = 0x1E;
  ci_field = 0;
 }
 do
 {
  select_window(bcwin);
  maxbase = bcgetmaxbase();
  buf_clear("");
  srand(1);
  subadr = subadr1;
  for (base = 0; base <= maxbase; base++)
  {
   bcdefbase(base);
   buffer[0] = (rtadr<<11) | (RT_RECEIVE) | (subadr<<5);
   buffer[1] = base | (base<<8);
   for (k = 2; k <= 32; k++)
    buffer[k] = rand() + rand();
   bcputblk(0, buffer, 33);
   if (++subadr > subadr2)
    subadr = subadr1;
  }
  ctrl_code = DATA_BC_RT;
  subadr = subadr1;
  srand(1);
  err = 0;
  for (base = 0; base <= maxbase; base++)
  {
   select_window(bcwin);
   if (start_1(""))
   {
#ifdef ENG
    err_msg = "Transmitting of test array from BC to RT didn't pass";
#else
    err_msg = "Не прошла передача тестового массива из КК в ОУ";
#endif
    goto fin;
   }
   select_window(rtwin);
   rtdefsubaddr(RT_RECEIVE, subadr);
   rtgetblk(0, buffer, 32);
   if (buffer[0] != (unsigned short)(base | (base<<8)))
   {
    err = 1;
    break;
   }
   for (k = 1; k <= 31; k++)
    if (buffer[k] != rand() + rand())
    {
     err = 1;
     break;
    }
   if (err)
    break;
   if (++subadr > subadr2)
    subadr = subadr1;
  }
  if (err)
  {
#ifdef ENG
   err_msg = "Test array transmitted to RT with errors";
#else
   err_msg = "Тестовый массив передан в ОУ с ошибками";
#endif
   goto fin;
  }
  select_window(bcwin);
  bc_clear_ram();
  srand(1);
  subadr = subadr1;
  ctrl_code = DATA_RT_BC;
  for (base = 0; base <= maxbase; base++)
  {
   select_window(rtwin);
   rtdefsubaddr(RT_TRANSMIT, subadr);
   buffer[0] = base | (base<<8);
   for (k = 1; k <= 31; k++)
    buffer[k] = rand() + rand();
   rtputblk(0, buffer, 32);
   select_window(bcwin);
   bcdefbase(base);
   bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 32));
   if (start_1(""))
   {
#ifdef ENG
    err_msg = "Receiving of test array from RT to BC didn't pass";
#else
    err_msg = "Не прошел прием тестового массива из ОУ в КК";
#endif
    goto fin;
   }
   if (++subadr > subadr2)
    subadr = subadr1;
  }
  srand(1);
  select_window(bcwin);
  for (base = 0; base <= maxbase; base++)
  {
   bcdefbase(base);
   bcgetblk(2, buffer, 32);
   if (buffer[0] != (unsigned short)(base | (base<<8)))
   {
    err = 1;
    break;
   }
   for (k = 1; k <= 31; k++)
    if (buffer[k] != rand() + rand())
    {
     err = 1;
     break;
    }
   if (err)
    break;
   if (++subadr > subadr2)
    subadr = subadr1;
  }
  if (err)
  {
#ifdef ENG
   err_msg = "Test array received from RT with errors";
#else
   err_msg = "Тестовый массив принят из ОУ с ошибками";
#endif
   goto fin;
  }
 /* Тестирование счетчика ИС */
  select_window(rtwin);
  rtdefsubaddr(dir=RT_TRANSMIT, subadr=0x10);
  for (k = 0; k <= 31; k++)
   buffer[k] = k+1;
  rtputblk(0, buffer, 32);
  select_window(bcwin);
  bcdefbase(1);
  bcputblk(1, buffer, 32);
  bcdefbase(base=0);
  ctrl_code = DATA_RT_BC;
  for (len = 1; len <= 32; len++)
  {
   bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, len));
   if (test_start(TEST_COUNTER_RT_BC))
   {
#ifdef ENG
      err_msg = "Data counter test (RT->BC message) didn't pass";
#else
      err_msg = "Не прошел тест счетчика ИС в режиме ОУ->КК";
#endif
    goto fin;
   }
  }
  ctrl_code = DATA_BC_RT;
  bcdefbase(base=1);
  for (len = 1; len <= 32; len++)
  {
   bcputw(0, CW(rtadr, RT_RECEIVE, subadr, len));
   if (test_start(TEST_COUNTER_BC_RT))
   {
#ifdef ENG
      err_msg = "Data counter test (BC->RT message) didn't pass";
#else
      err_msg = "Не прошел тест счетчика ИС в режиме КК->ОУ";
#endif
    goto fin;
   }
  }
 /* Формат ОУ-ОУ (групповой режим), подадрес - 17 */
  make_test1(3);
  select_window(rtwin);
  rtdefsubaddr(dir=RT_TRANSMIT, subadr=0x17);
  rtputblk(0, buffer+3, 32);
  select_window(bcwin);
  ctrl_code = DATA_RT_RT_BRCST;
  bcdefbase(base=2);
  bcputw(0, CW(0x1F, RT_RECEIVE, subadr, 32));
  bcputw(1, CW(rtadr, RT_TRANSMIT, subadr, 32));
  if (start_loop_n(GL_COUNTER))
  {
#ifdef ENG
   err_msg = "Broadcast RT->RT message test didn't pass";
#else
   err_msg = "Не прошел тест формата ОУ->ОУ в групповом режиме";
#endif
   goto fin;
  }
  select_window(rtwin);
  if (cmp_ram_buf(3, 0, 32))
  {
#ifdef ENG
   err_msg = "Test array in RT->RT message received with errors";
#else
   err_msg = "Тестовый массив в формате ОУ->ОУ в групповом режиме принят с ошибками";
#endif
   goto fin;
  }
 /* Проверка битов ответного слова */
  select_window(bcwin);
  base = 3;
  bcdefbase(base);
  buf_clear("");
  select_window(rtwin);
  rtsetanswbits(RTFL); out_status_word();
  select_window(bcwin);
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr, ci_field, UNBLOCK_TRANSMIT));
  if (test_start(TEST_RTFL))
  {
#ifdef ENG
    err_msg = "Status with 'Terminal Flag' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Неисправность терминала'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(RTFL); rtsetanswbits(SSFL);
  select_window(bcwin);
  if (test_start(TEST_SSFL))
  {
#ifdef ENG
    err_msg = "Status with 'Subsystem Flag' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Неисправность подсистемы'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(SSFL); rtsetanswbits(BUSY);
  select_window(bcwin);
  if (test_start(TEST_BUSY))
  {
#ifdef ENG
    err_msg = "Status with 'Subsystem Busy' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Подсистема занята'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(BUSY); rtsetanswbits(SREQ);
  select_window(bcwin);
  if (test_start(TEST_SREQ))
  {
#ifdef ENG
    err_msg = "Status with 'Service Request' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Запрос обслуживания'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(SREQ); rtsetanswbits(DNBA);
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, DNB));
  if (test_start(TEST_DNBA))
  {
#ifdef ENG
    err_msg = "Status with 'Dynamic Bus Control Acceptance' bit test didn't pass";
#else
     err_msg = "Не прошел тест приема ОС с битом 'Принято управление каналом'";
#endif
   goto fin;
  }
 /* сброс ОУ в исходное состояние */
  select_window(rtwin);
  rtclranswbits(DNBA); out_status_word();
  select_window(bcwin);
  ctrl_code = CTRL_C_BRCST;
  bcputw(0, CWMC(0x1F, ci_field, RESET));
  if (test_start(TEST_BRCST_CMD))
  {
#ifdef ENG
    err_msg = "'Broadcast Reset Remote Terminal' test didn't pass";
#else
    err_msg = "Не прошел тест 'Уст.исходное состояние ОУ, групповой режим'";
#endif
   goto fin;
  }
 /* Проверка бита групповой команды */
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr, ci_field, GET_SW));
  if (test_start(TEST_BRCST_BIT))
  {
#ifdef ENG
    err_msg = "Status with 'Broadcast Command Received' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Принята групповая команда'";
#endif
   goto fin;
  }
 /* Проверка бита ошибки в сообщении */
  bcputw(0, (TMK_DATA)(~RT_DIR_MASK & CWMC(rtadr, ci_field, SYNC)));
  if (test_start(TEST_ERROR))
  {
#ifdef ENG
    err_msg = "Status with 'Message Error' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Ошибка сообщения'";
#endif
   goto fin;
  }
 /* Синхронизация со словом AAAA */
  ctrl_code = CTRL_CD_A;
  bcputw(0, CWMC(rtadr, ci_field, SYNC_DATA));
  bcputw(1, 0xAAAA);
  if (test_start(TEST_SYNC_DATA1))
  {
#ifdef ENG
    err_msg = "'Synchronize with Data AAAAh' test didn't pass";
#else
    err_msg = "Не прошел тест 'Синхронизация со словом AAAAh'";
#endif
   goto fin;
  }
  ctrl_code = CTRL_CD_BRCST;
  bcputw(0, CWMC(0x1F, ci_field, SYNC_DATA));
  bcputw(1, 0x5555);
  if (test_start(TEST_SYNC_DATA_BRCST))
  {
#ifdef ENG
    err_msg = "'Broadcast Synchronize with Data 5555h' test didn't pass";
#else
    err_msg = "Не прошел тест 'Синхронизация со словом 5555h, групповой режим'";
#endif
   goto fin;
  }
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr, ci_field, RESET));
  if (test_start(TEST_BRCST_CMD))
  {
#ifdef ENG
    err_msg = "Status with 'Broadcast Command Received' bit test didn't pass";
#else
    err_msg = "Не прошел тест приема ОС с битом 'Принята групповая команда'";
#endif
   goto fin;
  }
  all_screen();
  if (Window[rtwin].at_avail)
  {
   rtadr1 = 0x15;
   rtadr2 = 0x0A;
  }
  else
  {
 #ifdef STEND
   rtadr1 = 0x15;
   rtadr2 = 0x0A;
 #else
   rtadr1 = (rtadr == 0) ? 0x1E : rtadr ^ 0x1F;
   rtadr2 = rtadr;
 #endif
  }
 /* Обращениe к несуществующему ОУ c адресом 0x15 */
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr1, ci_field, UNBLOCK_TRANSMIT));
//  bcputw(0, CWMC(rtadr1, ci_field, GET_SW));
  if (test_start(TEST_NO_RT_15))
  {
#ifdef ENG
    err_msg = "Missing RT with address 15h (10101) access test didn't pass";
#else
    err_msg = "Не прошел тест обращения к несуществующему ОУ с адресом 15h (10101)";
#endif
   goto fin;
  }
 #ifndef STEND
  if (Window[rtwin].at_avail)
 #endif
  {
   select_window(rtwin);
   wr_at(rtadr = rtadr1);
   select_window(bcwin);
 /* Обращение к ОУ с адресом 0x15 */
   if (test_start(TEST_RT_15))
   {
#ifdef ENG
     err_msg = "RT with address 15h (10101) access test didn't pass";
#else
     err_msg = "Не прошел тест обращения к ОУ с адресом 15h (10101)";
#endif
    goto fin;
   }
 /* Обращениe к несуществующему ОУ c адресом 0x0A */
   bcputw(0, CWMC(rtadr2, ci_field, UNBLOCK_TRANSMIT));
//   bcputw(0, CWMC(rtadr2, ci_field, GET_SW));
   if (test_start(TEST_NO_RT_0A))
   {
#ifdef ENG
    err_msg = "Missing RT with address 0Ah (01010) access test didn't pass";
#else
     err_msg = "Не прошел тест обращения к несуществующему ОУ с адресом 0Ah (01010)";
#endif
    goto fin;
   }
  }
  select_window(rtwin);
  wr_at(rtadr = rtadr2);
  select_window(bcwin);
 /* Обращение к ОУ с адресом 0x0A */
  bcputw(0, CWMC(rtadr2, ci_field, UNBLOCK_TRANSMIT));
//  bcputw(0, CWMC(rtadr2, ci_field, GET_SW));
  if (test_start(TEST_RT_0A))
  {
#ifdef ENG
     err_msg = "RT with address 0Ah (01010) access test didn't pass";
#else
    err_msg = "Не прошел тест обращения к ОУ с адресом 0Ah (01010)";
#endif
   goto fin;
  }
  int_num[rtnum] = 0;
  select_window(rtwin);
  wr_at(rtadr);
  rt_clear_ram();
  select_window(bcwin);
  bc_clear_ram();
  if (fAAAA)
   if (statistic_rt_bc(0x10, 0, 0xAAAA)) goto bad_statistic;
  if (statistic_rt_bc(0x12, 2, 0x0000)) goto bad_statistic;
  if (statistic_rt_bc(0x14, 4, 0x5555)) goto bad_statistic;
  if (statistic_rt_bc(0x16, 6, 0xFFFF)) goto bad_statistic;
  if (fAAAA)
   if (statistic_rt_bc(0x18, 8, 0x8000)) goto bad_statistic;
  if (statistic_rt_bc(0x1A, 10, 0x7FFF)) goto bad_statistic;
  if (statistic_bc_rt(12, 0x10, 0xAAAA)) goto bad_statistic;
  if (statistic_bc_rt(14, 0x12, 0x0000)) goto bad_statistic;
  if (statistic_bc_rt(16, 0x14, 0x5555)) goto bad_statistic;
  if (statistic_bc_rt(18, 0x16, 0xFFFF)) goto bad_statistic;
  if (statistic_bc_rt(20, 0x18, 0x8000)) goto bad_statistic;
  if (statistic_bc_rt(22, 0x1A, 0x7FFF)) goto bad_statistic;
  select_window(bcwin);
  if (fReserv && (times == nBusSwapTime || times == 1))
  {
   unsigned short nTempBus;
   bcdefbus(nReservBus);
   nTempBus = nMainBus;
   nMainBus = nReservBus;
   nReservBus = nTempBus;
   bus_num = nMainBus;
   out_number();
  }
 }
 while (--times);
/* Конец теста */
 avt_ok = 1;
#ifdef ENG
 err_msg = "Bus Controller test completed";
#else
 err_msg = "Тест контроллера канала завершен";
#endif
 goto fin;
 bad_statistic:
#ifdef ENG
 err_msg = "'Statistics' test didn't pass";
#else
 err_msg = "Не прошел тест 'Накопление статистики'";
#endif
 fin:
 if (prtscr_flag)
 {
  prtscr_flag = 0;
#ifdef ENG
  err_msg = "Test aborted on PrtScr";
#else
  err_msg = "Тест прерван по PrtScr";
#endif
 }
 check_int();
 select_window(bcwin);
 all_screen();
 select_window(rtwin);
 putchar('\007');
 
 if (avt_ok)
  textcolor(GREEN);
 else
  textcolor(LIGHTRED);
 comment(err_msg);
 textcolor(LIGHTGRAY);
 select_window(nmainwin=bcwin);
 statistic_out("");
 avt_ctrl("0");
}

/************************************************************************/
/*                      Начало секции для ОУ                            */
/*                      Remote Terminal Tests                           */
/************************************************************************/

int test_rt_busy()
{
 int test_result;

 test_result = 1;
 rtdefsubaddr(dir = RT_TRANSMIT, subadr = 0x11);
// rtunlock();
 select_window(bcwin);
 bcdefbase(base);
 ctrl_code = DATA_RT_BC;
 bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 32));
 int_num[bcnum] = 0;
 bcstart(base, ctrl_code);
 tmkselect(rtnum);
 do
 {
  if (rtbusy()) test_result = 0;
  CheckTmkEvent(NO_WAIT_EVENT);
//  CheckTmkProxy(NO_WAIT_PROXY);
 }
 while (!int_num[bcnum]);
 select_window(rtwin);
 return test_result;
}

void avt_rt(char *str)                   /* поддержка проверки ОУ */
{
 int maxpage, k;
 TMK_DATA page;
 unsigned long times, nBusSwapTime;

 while (*str == '\t' || *str == ' ') str++;
 if (*str)
 {
  if (sscanf(str, "%U", &times) != 1)
  {
   msg_out(inp_err);
   return;
  }
 }
 else
  times=1;
 if (Window[0].nMode == RT_MODE)
  rtwin = 0;
 else if (Window[1].nMode == RT_MODE)
  rtwin = 1;
 else
 {
#ifdef ENG
  msg_out("RT not defined");
#else
  msg_out("Не задано ОУ");
#endif
  return;
 }
 if (Window[0].nMode == BC_MODE)
  bcwin = 0;
 else if (Window[1].nMode == BC_MODE)
  bcwin = 1;
 else
 {
#ifdef ENG
  msg_out("BC not defined");
#else
  msg_out("Не задан КК");
#endif
  return;
 }
 bcnum = Window[bcwin].nTMK;
 rtnum = Window[rtwin].nTMK;
 statistic_clear("");
 avt_ctrl("1");
 avt_ok = 0;
 select_window(bcwin);
 if (fReserv)
 {
  nReservBus = ((nMainBus=bcgetbus()) == BUS_A) ? BUS_B : BUS_A;
  bus_num = nMainBus;
  out_number();
  nBusSwapTime = times+1;
  times <<= 1;
 }
 select_window(rtwin);
#ifdef ENG
 comment("Remote Terminal automatic test.");
#else
 comment("Автоматический тест оконечного устройства.");
#endif
 wr_at(rtadr=0x0A); out_at();
 set_status_word("0"); /* сбросить все биты ОС */
 maxpage = rtgetmaxpage();
 if (hb_mode)
 {
  subadr1 = 0x10;
  subadr2 = 0x1E;
  ci_field = CI_MASK;
 }
 else
 {
  subadr1 = 0x01;
  subadr2 = 0x1E;
  ci_field = 0;
 }
 do
 {
  select_window(rtwin);
  srand(1);
  for (page = 0; page <= maxpage; page++)
  {
   rtdefpage(page);
   for(subadr = subadr1; subadr <= subadr2; subadr++)
   {
    rtdefsubaddr(RT_TRANSMIT, subadr);
    buffer[0] = (page<<14) | (subadr<<8) | (page<<6) | subadr | 0x2020;
    for (k = 1; k <= 31; k++)
     buffer[k] = rand() + rand();
    rtputblk(0, buffer, 32);
   }
  }
  srand(1);
  for (page = 0; page <= maxpage; page++)
  {
   select_window(rtwin);
   rtdefpage(page);
   select_window(bcwin);
   bcdefbase(base=0);
   for(subadr = subadr1; subadr <= subadr2; subadr++)
   {
    ctrl_code = DATA_RT_BC;
    bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 32));
    if (start_1(""))
    {
#ifdef ENG
     err_msg = "Transmitting of test array from RT to BC didn't pass";
#else
     err_msg = "Не прошла передача тестового массива из ОУ в КК";
#endif
     goto fin;
    }
    vbuffer[0] = (page<<14) | (subadr<<8) | (page<<6) | subadr | 0x2020;
    for (k = 1; k <= 31; k++)
     vbuffer[k] = rand() + rand();
    if (cmp_ram_buf(2, -1, 32))
    {
#ifdef ENG
     err_msg = "Test array transmitted from RT with errors";
#else
     err_msg = "Тестовый массив передан из ОУ с ошибками";
#endif
     goto fin;
    }
   }
  }
  for (page = 0; page <= maxpage; page++)
  {
   select_window(rtwin);
   rtdefpage(page);
   select_window(bcwin);
   bcdefbase(base=1);
   for(subadr = subadr1; subadr <= subadr2; subadr++)
   {
    ctrl_code = DATA_BC_RT;
    buffer[0] = (rtadr<<11) | RT_RECEIVE | (subadr<<5);
    buffer[1] = (page<<14) | (subadr<<8) | (page<<6) | subadr;
    for (k = 2; k <= 32; k++)
     buffer[k] = rand() + rand();
    bcputblk(0, buffer, 33);
    if (start_1(""))
    {
#ifdef ENG
     err_msg = "Receiving of test array from BC to RT didn't pass";
#else
     err_msg = "Не прошел прием тестового массива в ОУ из КК";
#endif
     goto fin;
    }
   }
  }
  srand(1);
  select_window(rtwin);
  for (page = 0; page <= maxpage; page++)
  {
   rtdefpage(page);
   for (subadr = subadr1; subadr <= subadr2; subadr++)
   {
    buffer[0] = (page<<14) | (subadr<<8) | (page<<6) | subadr | 0x2020;
    for (k = 1; k <= 31; k++)
     buffer[k] = rand() + rand();
    rtdefsubaddr(RT_TRANSMIT, subadr);
    if (cmp_ram_buf(0, 0, 32))
    {
#ifdef ENG
     err_msg = "Data in Tx subaddress has changed while receiving test array";
#else
     err_msg = "При приеме тестового массива в ОУ изменились данные в подадресе передачи";
#endif
     goto fin;
    }
   }
  }
  for (page = 0; page <= maxpage; page++)
  {
   rtdefpage(page);
   for (subadr = subadr1; subadr <= subadr2; subadr++)
   {
    buffer[0] = (page<<14) | (subadr<<8) | (page<<6) | subadr;
    for (k = 1; k <= 31; k++)
     buffer[k] = rand() + rand();
    rtdefsubaddr(RT_RECEIVE, subadr);
    if (cmp_ram_buf(0, 0, 32))
    {
#ifdef ENG
     err_msg = "Test array received to RT with errors";
#else
     err_msg = "Тестовый массив принят в ОУ с ошибками";
#endif
     goto fin;
    }
   }
  }
  set_page("0");
 /* проверка битов ответного слова */
  rtsetanswbits(RTFL); /* TF */
  select_window(bcwin);
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr, ci_field, SYNC));
  if (test_start(TEST_RTFL))
  {
#ifdef ENG
    err_msg = "Status bit 'Terminal Flag' didn't set";
#else
    err_msg = "Не установился в ОС бит 'Неисправность терминала'";
#endif
   goto fin;
  }
  bcputw(0, CWMC(rtadr, ci_field, MASK_RTFL));
  if (test_start(TEST_MASK_RTFL))
  {
#ifdef ENG
    err_msg = "'Inhibit Terminal Flag Bit' command didn't pass";
#else
    err_msg = "Не прошла команда 'Подавить бит терминала'";
#endif
   goto fin;
  }
  bcputw(0, CWMC(rtadr, ci_field, UNMASK_RTFL));
  if (test_start(TEST_UNMASK_RTFL))
  {
#ifdef ENG
    err_msg = "'Override Inhibit Terminal Flag Bit' command didn't pass";
#else
    err_msg = "Не прошла команда 'Отменить подавление бита терминала'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(RTFL); /* TF */
  rtsetanswbits(SSFL); /* SF */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, SYNC));
  if (test_start(TEST_SSFL))
  {
#ifdef ENG
    err_msg = "Status bit 'Subsystem Flag' didn't set";
#else
    err_msg = "Не установился в ОС бит 'Неисправность подсистемы'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(SSFL); /* SF */
  rtsetanswbits(BUSY); /* BS */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, SYNC));
  if (test_start(TEST_BUSY))
  {
#ifdef ENG
    err_msg = "Status bit 'Subsystem Busy' didn't set";
#else
    err_msg = "Не установился в ОС бит 'Подсистема занята'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(BUSY); /* BS */
  rtsetanswbits(SREQ); /* SR */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, SYNC));
  if (test_start(TEST_SREQ))
  {
#ifdef ENG
    err_msg = "Status bit 'Service Request' didn't set";
#else
    err_msg = "Не установился в ОС бит 'Запрос обслуживания подсистемы'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(SREQ); /* SR */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, DNB));
  if (test_start(TEST_DNBA_OFF))
  {
#ifdef ENG
    err_msg = "Status bit 'Dynamic Bus Control Acceptance' set while RT disallowed it";
#else
    err_msg = "Установился в ОС бит 'Принято управление каналом' без разрешения ОУ";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtsetanswbits(DNBA); /* DN */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, DNB));
  if (test_start(TEST_DNBA_ON))
  {
#ifdef ENG
      err_msg = "Status bit 'Dynamic Bus Control Acceptance' didn't set";
#else
      err_msg = "Не установился в ОС бит 'Принято управление каналом'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtclranswbits(DNBA); /* Сброс DN */
  select_window(bcwin);
  bcputw(0, CWMC(rtadr, ci_field, RESET));
  if (test_start(TEST_RESET))
  {
#ifdef ENG
      err_msg = "Status bit 'Dynamic Bus Control Acceptance' didn't reset on 'Reset RT' cmd";
#else
    err_msg = "Не сбросился в ОС бит 'Принято управление каналом' после команды 'Сброс ОУ'";
#endif
   goto fin;
  }
  if (fReserv)
  {
   bcputw(0, CWMC(rtadr, ci_field, BLOCK_TRANSMIT));
   if (test_start(TEST_BLOCK_TR))
   {
#ifdef ENG
     err_msg = "'Transmitter shutdown' command1 didn't pass";
#else
     err_msg = "Не прошла команда1 блокировки передатчика";
#endif
    goto fin;
   }
   bcdefbus(nReservBus);
   ctrl_code = DATA_RT_BC;
   bcputw(0, CW(rtadr, RT_TRANSMIT, 0x10, 1));
   if (test_start(TEST_BLOCKED_TR))
   {
#ifdef ENG
     err_msg = "Disabled transmitter test1 didn't pass";
#else
     err_msg = "Не прошел тест1 заблокированного передатчика";
#endif
    goto fin;
   }
   ctrl_code = CTRL_C_A;
   bcputw(0, CWMC(rtadr, ci_field, RESET));
   if (test_start(TEST_RESET))
   {
#ifdef ENG
     err_msg = "RT reset on disabled bus didn't pass";
#else
     err_msg = "Не прошел сброс ОУ по заблокированной ЛПИ";
#endif
    goto fin;
   }
   ctrl_code = DATA_RT_BC;
   bcputw(0, CW(rtadr, RT_TRANSMIT, 0x10, 1));
   if (test_start(TEST_UNBLOCKED_TR))
   {
#ifdef ENG
     err_msg = "Enabled transmitter test1 didn't pass";
#else
     err_msg = "Не прошел тест1 разблокированного передатчика";
#endif
    goto fin;
   }
   bcdefbus(nMainBus);
   ctrl_code = CTRL_C_A;
   bcputw(0, CWMC(rtadr, ci_field, BLOCK_TRANSMIT));
   if (test_start(TEST_BLOCK_TR))
   {
#ifdef ENG
     err_msg = "'Transmitter shutdown' command2 didn't pass";
#else
     err_msg = "Не прошла команда2 блокировки передатчика";
#endif
    goto fin;
   }
   bcdefbus(nReservBus);
   ctrl_code = DATA_RT_BC;
   bcputw(0, CW(rtadr, RT_TRANSMIT, 0x10, 1));
   if (test_start(TEST_BLOCKED_TR))
   {
#ifdef ENG
     err_msg = "Disabled transmitter test2 didn't pass";
#else
     err_msg = "Не прошел тест2 заблокированного передатчика";
#endif
    goto fin;
   }
   bcdefbus(nMainBus);
   ctrl_code = CTRL_C_A;
   bcputw(0, CWMC(rtadr, ci_field, UNBLOCK_TRANSMIT));
   if (test_start(TEST_UNBLOCK_TR))
   {
#ifdef ENG
     err_msg = "'Override Transmitter shutdown' command2 didn't pass";
#else
     err_msg = "Не прошла команда2 разблокировки передатчика";
#endif
    goto fin;
   }
   bcdefbus(nReservBus);
   ctrl_code = DATA_RT_BC;
   bcputw(0, CW(rtadr, RT_TRANSMIT, 0x10, 1));
   if (test_start(TEST_UNBLOCKED_TR))
   {
#ifdef ENG
     err_msg = "Enabled transmitter test2 didn't pass";
#else
     err_msg = "Не прошел тест2 разблокированного передатчика";
#endif
    goto fin;
   }
   bcdefbus(nMainBus);
  }
  ctrl_code = CTRL_C_A;
  bcputw(0, CWMC(rtadr, ci_field, SYNC));
  if (test_start(TEST_SYNC))
  {
#ifdef ENG
    err_msg = "'Synchronize' command didn't pass";
#else
    err_msg = "Не прошла команда 'Синхронизация'";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtputcmddata(GET_VECTOR, 0xFACE);
  rtputcmddata(GET_SELFTEST, 0xBABA);
  select_window(bcwin);
  ctrl_code = CTRL_C_AD;
  bcputw(0, CWMC(rtadr, ci_field, GET_VECTOR));
  if (test_start(TEST_GET_VECTOR))
  {
#ifdef ENG
    err_msg = "'Transmit Vector Word' command didn't pass";
#else
    err_msg = "Не прошла команда 'Дать векторное слово'";
#endif
   goto fin;
  }
  bcputw(0, CWMC(rtadr, ci_field, GET_SELFTEST));
  if (test_start(TEST_GET_SELFTEST))
  {
#ifdef ENG
    err_msg = "'Transmit BIT Word' command didn't pass";
#else
   err_msg = "Не прошла команда 'Дать слово встроенного контроля'";
#endif
   goto fin;
  }
 /* Синхронизация со словом A5A5 */
  ctrl_code = CTRL_CD_A;
  bcputw(0, CWMC(rtadr, ci_field, SYNC_DATA));
  bcputw(1, 0xA5A5);
  if (test_start(TEST_SYNC_DATA))
  {
#ifdef ENG
    err_msg = "'Synchronize with Data A5A5h' command didn't pass";
#else
    err_msg = "Не прошла команда 'Синхронизация со словом A5A5h'";
#endif
   goto fin;
  }
 /* Проверка регистра адреса терминала */
  ctrl_code = CTRL_C_A;
  for (rtadr1 = 1; rtadr1 != 32; rtadr1 <<= 1)
  {
   if (rtadr == rtadr1) continue;
   bcputw(0, CWMC(rtadr1, ci_field, SYNC));
   if (test_start(TEST_OTHER_AT))
   {
#ifdef ENG
     err_msg = "Other address RT access test didn't pass";
#else
     err_msg = "Не прошел тест 'Обращение по `чужому` адресу ОУ'";
#endif
    goto fin;
   }
  }
 #ifndef STEND
  if (Window[rtwin].at_avail)
 #endif
  {
   ctrl_code = CTRL_C_A;
   for (rtadr = 1; rtadr != 32; rtadr <<= 1)
   {
    select_window(rtwin);
    wr_at(rtadr);
    select_window(bcwin);
    bcputw(0, CWMC(rtadr, ci_field, SYNC));
    if (test_start(TEST_AT))
    {
#ifdef ENG
      err_msg = "RT address test didn't pass";
#else
      err_msg = "Не прошел тест адреса ОУ";
#endif
     goto fin;
    }
   }
  }
  select_window(rtwin);
  wr_at(rtadr = 0x0A);
  avt_out = 0;
 /* Проверка арбитра доступа к БЗУ */
  for (subadr0 = subadr1; subadr0 <= subadr2; subadr0++)
  {
   rtdefsubaddr(RT_TRANSMIT, subadr0);
   rtputw(0, 0x0000);
  }
  for (dir = RT_RECEIVE; ; dir = RT_TRANSMIT)
  {
   for (subadr = subadr1; ;)
   {
    for (subadr0 = subadr1; subadr0 <= subadr2; subadr0++)
    {
     rtdefsubaddr(RT_RECEIVE, subadr0);
     rtputw(0, 0x0000);
    }
    rtlock(dir, subadr);
    fLock=1;
    out_subadr();
    if (rtbusy())
    {
#ifdef ENG
      err_msg = "Subaddress access disable bit didn't reset";
#else
      err_msg = "Не сбрасывается бит запрета доступа к подадресу ОУ";
#endif
     goto fin;
    }
    select_window(bcwin);
    for (dir0 = RT_RECEIVE; ; dir0 = RT_TRANSMIT)
    {
     ctrl_code = (dir0 == RT_TRANSMIT) ? DATA_RT_BC : DATA_BC_RT;
     for (subadr0 = subadr1; subadr0 <= subadr2; subadr0++)
     {
      bcputw(0, CW(rtadr, dir0, subadr0, 1));
      bcputw(1, 0xFFFF);
      bcputw(2, 0xFFFF);
      if (dir0 == dir && subadr0 == subadr)
      {
       if (test_start(TEST_BUSY1))
       {
#ifdef ENG
          err_msg = "'BC access to locked subaddress' RAM arbiter test didn't pass";
#else
          err_msg = "Не прошел тест арбитра БЗУ 'Обращение КК в блокированный подадрес'";
#endif
        goto fin;
       }
      }
      else
      {
       if (test_start(TEST_NOBUSY1))
       {
#ifdef ENG
          err_msg = "'BC access to unlocked subaddress' RAM arbiter test didn't pass";
#else
          err_msg = "Не прошел тест арбитра БЗУ 'Обращение КК в неблокированный подадрес'";
#endif
        goto fin;
       }
      }
     }
     if (dir0 == RT_TRANSMIT) break;
    }
    select_window(rtwin);
    if (dir == RT_RECEIVE)
     if (rtgetw(0) != 0x0000)
     {
#ifdef ENG
       err_msg = "'BC access to locked subaddress' RAM arbiter test didn't pass";
#else
       err_msg = "Не прошел тест арбитра БЗУ 'Обращение КК в блокированный подадрес'";
#endif
      goto fin;
     }
    rtdefsubaddr(dir, subadr);
//    rtunlock();
//    rtunlock(dir, subadr);
    fLock=0;
    select_window(bcwin);
    dir0 = dir; subadr0 = subadr;
    ctrl_code = (dir0 == RT_TRANSMIT) ? DATA_RT_BC : DATA_BC_RT;
    bcputw(0, CW(rtadr, dir0, subadr0, 1));
    bcputw(1, 0xFFFF);
    bcputw(2, 0xFFFF);
    if (test_start(TEST_NOBUSY1))
    {
#ifdef ENG
       err_msg = "'BC access to unlocked subaddress' RAM arbiter test1 didn't pass";
#else
       err_msg = "Не прошел тест1 арбитра БЗУ 'Обращение КК в разблокированный подадрес'";
#endif
     goto fin;
    }
    select_window(rtwin);
    for (subadr0 = subadr1; subadr0 <= subadr2; subadr0++)
    {
     rtdefsubaddr(RT_RECEIVE, subadr0);
     if (rtgetw(0) != 0xFFFF)
     {
#ifdef ENG
       err_msg = "'BC access to unlocked subaddress' RAM arbiter test2 didn't pass";
#else
       err_msg = "Не прошел тест2 арбитра БЗУ 'Обращение КК в разблокированный подадрес'";
#endif
      goto fin;
     }
    }
    if (subadr == 0x18)
     break;
    if (subadr == 0x10)
     subadr = 0x11;
    else
     subadr = ((subadr & 0x0F) << 1) | (subadr & 0x10);
   }
   if (dir == RT_TRANSMIT) break;
  }
 /* Проверка запрета доступа к БЗУ при обмене с КК */
  if (test_rt_busy())
  {
#ifdef ENG
      err_msg = "Subaddress access disable bit didn't set during BC access";
#else
      err_msg = "Не устанавливается бит запрета доступа к подадресу при обмене с КК";
#endif
   goto fin;
  }
  avt_out = 1;
 /* Тестирование счетчика ИС */
  select_window(rtwin);
  rtdefsubaddr(dir=RT_TRANSMIT, subadr=0x10);
  for (k = 0; k <= 31; k++)
   buffer[k] = k+1;
  rtputblk(0, buffer, 32);
  select_window(bcwin);
  ctrl_code = DATA_RT_BC;
  for (len = 1; len <= 32; len++)
  {
   bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, len));
   if (test_start(TEST_COUNTER))
   {
#ifdef ENG
     err_msg = "Data counter test didn't pass";
#else
     err_msg = "Не прошел тест счетчика ИС";
#endif
    goto fin;
   }
  }
  select_window(rtwin);
  if (rtdefirqmode(RT_GENER1_BL|RT_GENER2_BL) == 0)
  {
   int_num[rtnum]=0;
   select_window(bcwin);
   ctrl_code = DATA_BC_RT;
   bcputw(0, CW(rtadr, RT_RECEIVE, subadr, 32));
   if (test_start(TEST_RT_DATA_IRQ))
   {
//    err_msg = "Не прошел тест прерывания ОУ при приеме данных";
    int sav_int = int_num[rtnum];
    CheckTmkEvent(NO_WAIT_EVENT);
//    CheckTmkProxy(NO_WAIT_PROXY);
#ifdef ENG
     err_msg = "RT data receiving interrupt test didn't pass";
#else
     err_msg = "Не прошел тест прерывания ОУ при приеме данных";
//    sprintf(err_msg, "Не прошел тест прерывания ОУ при приеме данных %d %d.", sav_int, int_num[rtnum]);
#endif
    goto fin;
   }
   select_window(rtwin);
   rtdefirqmode(RT_GENER1_BL|RT_GENER2_BL|RT_DATA_BL);
   int_num[rtnum]=0;
   select_window(bcwin);
   if (test_start(TEST_RT_DATA_IRQ_BL))
   {
#ifdef ENG
     err_msg = "RT data receiving interrupt mask test didn't pass";
#else
     err_msg = "Не прошел тест блокировки прерывания ОУ при приеме данных";
#endif
    goto fin;
   }
   select_window(rtwin);
   rtdefirqmode(RT_GENER1_BL|RT_GENER2_BL);
   int_num[rtnum]=0;
   select_window(bcwin);
   ctrl_code = DATA_RT_BC;
   bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 32));
   if (test_start(TEST_RT_DATA_IRQ))
   {
#ifdef ENG
     err_msg = "RT data transmitting interrupt test didn't pass";
#else
     err_msg = "Не прошел тест прерывания ОУ при передаче данных";
#endif
    goto fin;
   }
   select_window(rtwin);
   rtdefirqmode(RT_GENER1_BL|RT_GENER2_BL|RT_DATA_BL);
   int_num[rtnum]=0;
   select_window(bcwin);
   if (test_start(TEST_RT_DATA_IRQ_BL))
   {
#ifdef ENG
     err_msg = "RT data transmitting interrupt mask test didn't pass";
#else
     err_msg = "Не прошел тест блокировки прерывания ОУ при прередаче данных";
#endif
    goto fin;
   }
  }
 /* Тест гр.ОУ-ОУ */
  select_window(rtwin);
  rtdefsubaddr(dir=RT_TRANSMIT, subadr=0x10);
  make_test1(0);
  rtputblk(0, buffer, 32);
  select_window(bcwin);
  bcdefbase(base=3);
  ctrl_code = DATA_RT_RT_BRCST;
  bcputw(0, CW(0x1F, RT_RECEIVE, subadr, 32));
  bcputw(1, CW(rtadr, RT_TRANSMIT, subadr, 32));
  if (start_loop_n(GL_COUNTER))
  {
#ifdef ENG
   err_msg = "Broadcast RT->RT message test didn't pass";
#else
   err_msg = "Не прошел тест формата ОУ->ОУ в групповом режиме";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtgetblk(0, buffer, 32);
  select_window(bcwin);
  if (cmp_ram_buf(0, 3, 32))
  {
#ifdef ENG
   err_msg = "Test array in RT->RT message transmitted with errors";
#else
   err_msg = "Тестовый массив в формате ОУ->ОУ в групповом режиме передан с ошибкой";
#endif
   goto fin;
  }
  int_num[rtnum] = 0;
  select_window(rtwin);
  wr_at(rtadr);
  rt_clear_ram();
  select_window(bcwin);
  bc_clear_ram();
  if (fAAAA)
   if (statistic_rt_bc(0x10, 0, 0xAAAA)) goto bad_statistic;
  if (statistic_rt_bc(0x12, 2, 0x0000)) goto bad_statistic;
  if (statistic_rt_bc(0x14, 4, 0x5555)) goto bad_statistic;
  if (statistic_rt_bc(0x16, 6, 0xFFFF)) goto bad_statistic;
  if (fAAAA)
   if (statistic_rt_bc(0x18, 8, 0x8000)) goto bad_statistic;
  if (statistic_rt_bc(0x1A, 10, 0x7FFF)) goto bad_statistic;
  if (statistic_bc_rt(12, 0x10, 0xAAAA)) goto bad_statistic;
  if (statistic_bc_rt(14, 0x12, 0x0000)) goto bad_statistic;
  if (statistic_bc_rt(16, 0x14, 0x5555)) goto bad_statistic;
  if (statistic_bc_rt(18, 0x16, 0xFFFF)) goto bad_statistic;
  if (statistic_bc_rt(20, 0x18, 0x8000)) goto bad_statistic;
  if (statistic_bc_rt(22, 0x1A, 0x7FFF)) goto bad_statistic;
  select_window(bcwin);
  if (fReserv && (times == nBusSwapTime || times == 1))
  {
   unsigned short nTempBus;
   bcdefbus(nReservBus);
   nTempBus = nMainBus;
   nMainBus = nReservBus;
   nReservBus = nTempBus;
   bus_num = nMainBus;
   out_number();
  }
 }
 while (--times);
/* Конец теста */
 avt_ok = 1;
#ifdef ENG
 err_msg = "Remote Terminal test completed";
#else
 err_msg = "Тест оконечного устройства завершен";
#endif
 goto fin;
 bad_statistic:
#ifdef ENG
 err_msg = "'Statistics' test didn't pass";
#else
 err_msg = "Не прошел тест 'Накопление статистики'";
#endif
 fin:
 if (prtscr_flag)
 {
  prtscr_flag = 0;
#ifdef ENG
  err_msg = "Test aborted on PrtScr";
#else
  err_msg = "Тест прерван по PrtScr";
#endif
 }
 select_window(rtwin);
 check_int();
 all_screen();
 putchar('\007');
 if (avt_ok)
  textcolor(GREEN);
 else
  textcolor(LIGHTRED);
 comment(err_msg);
 textcolor(LIGHTGRAY);
 select_window(bcwin);
 statistic_out("");
 select_window(nmainwin=rtwin);
 avt_ctrl("0");
}

int statistic_bc_rt(TMK_DATA st_base, TMK_DATA st_subadr, TMK_DATA st_data)
{
 long cnt;
// unsigned short time1;
 long ltime1;
 int k;

 select_window(bcwin);
 gotoxy(1, 11);
 textcolor(CYAN);
#ifdef ENG
 printf("Statistics accumulation"/*. Press PrtScr to abort*/"...");
#else
 printf("Накопление статистики"/*. Нажмите PrtScr для выхода*/"...");
#endif
 textcolor(LIGHTGRAY);
 ctrl_code = DATA_BC_RT;
 out_ctrl_code();
 base = st_base;
 out_base();
 for (k = 1; k <= 32; k++)
  buffer[k] = st_data;
 bcdefbase(st_base);
 buffer[0] = (rtadr)<<11 | RT_RECEIVE | (st_subadr<<5);
 bcputblk(0, buffer, 33);
 out_buffer();
 bcdefbase((TMK_DATA)(st_base^1));
 buffer[0] = (rtadr)<<11 | RT_RECEIVE | ((st_subadr ^ 1)<<5);
 bcputblk(0, buffer, 33);
 for (cnt = 0; cnt <= GL_COUNTER; cnt++)
 {
  if (prtscr_flag)
   cnt = GL_COUNTER;
  if (cnt < GL_COUNTER)
  {
   tmkselect(bcnum);
   int_num[bcnum] = 0;
   bcstart(st_base, DATA_BC_RT);
   st_base ^= 1;
//   time1 = get_timer();
   ltime1 = biostime(0, 0L);
  }
  else
   good_starts--;
  if (cnt > 0)
  {
   tmkselect(rtnum);
   rtdefsubaddr(RT_RECEIVE, st_subadr);
   rtgetblk(0, buffer, 32);
   if (cnt == 1)
   {
    select_window(rtwin);
    out_subadr();
    out_buffer();
    select_window(bcwin);
   }
   for (k = 0; k <= 31; k++)
    if (buffer[k] != st_data) channel_err++;
   st_subadr ^= 1;
  }
//  while (time1 - get_timer() < _5000_MCSEC)
  while (biostime(0, 0L) - ltime1 < 10)
  {
   CheckTmkEvent(fGlobalWaitEvent);
//   CheckTmkProxy(NO_WAIT_PROXY);
   if (int_num[bcnum])
    break;
  }
  if (!int_num[bcnum] && cnt < GL_COUNTER)
   to_errors++;
 }
 if (nwin == nmainwin)
  textcolor(WHITE);
 gotoxy(1, 11);
 printf("──────────────────────────────────────────────────────");
 textcolor(LIGHTGRAY);
 statistic_out("");
 return (bad_starts > 0 || prtscr_flag);
}

int statistic_rt_bc(TMK_DATA st_subadr, TMK_DATA st_base, TMK_DATA st_data)
{
 long cnt;
// unsigned short time1;
 long ltime1;
 int k;

 select_window(rtwin);
 for (k = 0; k <= 31; k++)
  buffer[k] = st_data;
 dir = RT_TRANSMIT;
 subadr = st_subadr;
 out_subadr();
 rtdefsubaddr(RT_TRANSMIT, st_subadr);
 rtputblk(0, buffer, 32);
 out_buffer();
 rtdefsubaddr(RT_TRANSMIT, (TMK_DATA)(st_subadr^1));
 rtputblk(0, buffer, 32);
 select_window(bcwin);
 gotoxy(1, 11);
 textcolor(CYAN);
#ifdef ENG
 printf("Statistics accumulation"/*. Press PrtScr to abort*/"...");
#else
 printf("Накопление статистики"/*. Нажмите PrtScr для выхода*/"...");
#endif
 textcolor(LIGHTGRAY);
 ctrl_code = DATA_RT_BC;
 out_ctrl_code();
 base = st_base;
 out_base();
 bcdefbase(st_base);
 bcputw(0, CW(rtadr, RT_TRANSMIT, st_subadr, 32));
 bcdefbase((TMK_DATA)(st_base^1));
 bcputw(0, CW(rtadr, RT_TRANSMIT, st_subadr^1, 32));
 for (cnt = 0; cnt <= GL_COUNTER; cnt++)
 {
  if (prtscr_flag)
   cnt = GL_COUNTER;
  if (cnt < GL_COUNTER)
  {
   int_num[bcnum] = 0;
   bcstart(st_base, DATA_RT_BC);
   st_base ^= 1;
//   time1 = get_timer();
   ltime1 = biostime(0, 0L);
  }
  else
   good_starts--;
  if (cnt > 0)
  {
   bcdefbase(st_base);
   bcgetblk(0, buffer, 34);
   if (cnt == 1)
    out_buffer();
   for (k = 2; k <= 33; k++)
    if (buffer[k] != st_data) channel_err++;
  }
//  while (time1 - get_timer() < _5000_MCSEC)
  while (biostime(0, 0L) - ltime1 < 10)
  {
   CheckTmkEvent(fGlobalWaitEvent);
//   CheckTmkProxy(NO_WAIT_PROXY);
   if (int_num[bcnum])
    break;
  }
  if (!int_num[bcnum] && cnt < GL_COUNTER)
   to_errors++;
 }
 if (nwin == nmainwin)
  textcolor(WHITE);
 gotoxy(1, 11);
 printf("──────────────────────────────────────────────────────");
 textcolor(LIGHTGRAY);
 statistic_out("");
 return (bad_starts > 0 || prtscr_flag);
}

void avt_va996(char *str)        /* поддержка проверки приемопередатчика */
{
 int i;
 long ltime1;

 if (end_ctrl(str)) return;
 if (Window[0].nMode == BC_MODE)
  bcwin = 0;
 else if (Window[1].nMode == BC_MODE)
  bcwin = 1;
 else
 {
#ifdef ENG
  msg_out("BC not defined");
#else
  msg_out("Не задан КК");
#endif
  return;
 }
 if (Window[0].nMode == RT_MODE)
  rtwin = 0;
 else if (Window[1].nMode == RT_MODE)
  rtwin = 1;
 else
 {
#ifdef ENG
  msg_out("RT not defined");
#else
  msg_out("Не задано ОУ");
#endif
  return;
 }
 bcnum = Window[bcwin].nTMK;
 rtnum = Window[rtwin].nTMK;
 avt_ctrl("1");
 avt_ok = 0;
 select_window(rtwin);
 wr_at(rtadr=0x0A); out_at();
 set_status_word("0"); /* сбросить все биты ОС */
 select_window(rtwin);
#ifdef ENG
 comment("Transceiver automatic test.");
#else
 comment("Автоматический тест приемопередатчика.");
#endif
 select_window(bcwin);
 statistic_clear("");
 if (hb_mode)
 {
  subadr1 = 0x10;
  subadr2 = 0x1E;
  ci_field = 0x1F<<5;
 }
 else
 {
  subadr1 = 0x01;
  subadr2 = 0x1E;
  ci_field = 0;
 }
 ctrl_code = DATA_BC_RT; /* уст. кода управления */
                         /* занесение констант в базы */
 set_base("0"); buf_fill("1, 32, AAAA");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 set_base("1"); buf_fill("1, 32, 0000");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 set_base("2"); buf_fill("1, 32, 5555");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 set_base("3"); buf_fill("1, 32, FFFF");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 set_base("4"); buf_fill("1, 32, 8000");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 set_base("5"); buf_fill("1, 32, 7FFF");
 bcputw(0, CW(rtadr, RT_RECEIVE, 0x11, 32));
 ltime1=biostime(0, 0L);
 prtscr_flag = 0;
 while ((biostime(0, 0L)-ltime1)<18000L && !prtscr_flag && bad_starts<100L)
 {
  for (i=0;i<GL_COUNTER && !prtscr_flag;)
  {
   for (base=0; base<=5; base++)
   {
    int_num[bcnum] = 0;
    bcstart(base, ctrl_code);
    while (!int_num[bcnum] && !prtscr_flag)
     CheckTmkEvent(fGlobalWaitEvent);
//     CheckTmkProxy(NO_WAIT_PROXY);
    i++;
   }
  }
  statistic_out("");
 }
 set_base("0");
 out_ctrl_code();
 out_base();
 bc_out_ram(base);
/* Конец теста */
 if (bad_starts>=100L)
 {
#ifdef ENG
  err_msg = "Transceiver test didn't pass";
#else
  err_msg = "Тест приемопередатчика не прошел";
#endif
 }
 else if (prtscr_flag)
 {
#ifdef ENG
  err_msg = "Test aborted on PrtScr";
#else
  err_msg = "Тест прерван по PrtScr";
#endif
 }
 else
 {
  avt_ok = 1;
#ifdef ENG
  err_msg = "Transceiver test completed";
#else
  err_msg = "Тест приемопередатчика завершен";
#endif
 }
 check_int();
 select_window(bcwin);
 all_screen();
 select_window(rtwin);
 putchar('\007');
 if (avt_ok)
  textcolor(GREEN);
 else
  textcolor(LIGHTRED);
 comment(err_msg);
 textcolor(LIGHTGRAY);
 select_window(nmainwin=bcwin);
 statistic_out("");
 avt_ctrl("0");
}

void avt_flags(char *str)            /* поддержка проверки флагов ОУ */
{
 TMK_DATA page;
 TMK_DATA tsubadr;

 if (end_ctrl(str)) return;
 if (Window[0].nMode == RT_MODE)
  rtwin = 0;
 else if (Window[1].nMode == RT_MODE)
  rtwin = 1;
 else
 {
#ifdef ENG
  msg_out("RT not defined");
#else
  msg_out("Не задано ОУ");
#endif
  return;
 }
 if (Window[0].nMode == BC_MODE)
  bcwin = 0;
 else if (Window[1].nMode == BC_MODE)
  bcwin = 1;
 else
 {
#ifdef ENG
  msg_out("BC not defined");
#else
  msg_out("Не задан КК");
#endif
  return;
 }
 bcnum = Window[bcwin].nTMK;
 rtnum = Window[rtwin].nTMK;
 statistic_clear("");
 avt_ctrl("1");
 avt_ok = 0;
 select_window(rtwin);
 rtreset();
 rt_clear_ram();
#ifdef ENG
 comment("Remote Terminal flag mode automatic test.");
#else
 comment("Автоматический тест флагового режима оконечного устройства.");
#endif
 wr_at(rtadr=0x0A); out_at();
 set_status_word("0"); /* сбросить все биты ОС */
 rtdefmode((TMK_DATA)(rtgetmode()|RT_FLAG_MODE));
 rtdefpage(page=0);
 if (hb_mode)
 {
  subadr1 = 0x10;
  subadr2 = 0x1E;
  ci_field = CI_MASK;
 }
 else
 {
  subadr1 = 0x01;
  subadr2 = 0x1E;
  ci_field = 0;
 }
 for (subadr = subadr1; subadr <= subadr2; subadr++)
 {
  rtdefsubaddr(RT_TRANSMIT, subadr);
  buffer[0] = (page<<14) | (subadr<<8) | (page<<6) | subadr | 0x2020;
  rtputblk(0, buffer, 1);
  rtsetflag();
 }
 select_window(bcwin);
 bcreset();
 bc_clear_ram();
 bcdefbase(base=0);
 for (subadr = subadr1; subadr <= subadr2; subadr++)
 {
  ctrl_code = DATA_RT_BC;
  bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 1));
  start_1("");
  if (int_num[bcnum] != 1)
  {
#ifdef ENG
   err_msg = "RT->BC:Transmitting from subaddress with set flag didn't pass";
#else
   err_msg = "ОУ->КК:Не прошла передача из подадреса с установленным флагом";
#endif
   goto fin;
  }
  select_window(rtwin);
  for (tsubadr = subadr1; tsubadr < subadr; tsubadr++)
  {
   if ((rtgetflag(RT_TRANSMIT, tsubadr)&RT_FLAG) != 0)
   {
#ifdef ENG
    err_msg = "RT->BC:Earlier transmitted subaddress flag set";
#else
    err_msg = "ОУ->КК:Установился флаг для ранее переданного подадреса";
#endif
    goto fin;
   }
  }
  if ((rtgetflag(RT_TRANSMIT, subadr)&RT_FLAG) != 0)
  {
#ifdef ENG
   err_msg = "RT->BC:Transmitted subaddress flag didn't reset";
#else
   err_msg = "ОУ->КК:Не сбросился флаг для переданного подадреса";
#endif
   goto fin;
  }
  for (tsubadr = subadr+1; tsubadr < subadr2; tsubadr++)
  {
   if ((rtgetflag(RT_TRANSMIT, tsubadr)&RT_FLAG) == 0)
   {
#ifdef ENG
    err_msg = "RT->BC:Not yet transmitted subaddress flag reset";
#else
    err_msg = "ОУ->КК:Сбросился флаг для еще не переданного подадреса";
#endif
    goto fin;
   }
  }
  select_window(bcwin);
 }
 bcdefbase(base=0);
 for(subadr = subadr1; subadr <= subadr2; subadr++)
 {
  ctrl_code = DATA_RT_BC;
  bcputw(0, CW(rtadr, RT_TRANSMIT, subadr, 1));
  start_1("");
  if (int_num[bcnum] != 2 || bc_sw != (S_TO_MASK|S_IB_MASK))
  {
#ifdef ENG
   err_msg = "RT->BC:Transmitting from subaddress with reset flag test didn't pass";
#else
   err_msg = "ОУ->КК:Не прошел тест передачи из подадреса со сброшенным флагом";
#endif
   goto fin;
  }
  select_window(rtwin);
  for (tsubadr = subadr1; tsubadr <= subadr2; tsubadr++)
  {
   if ((rtgetflag(RT_TRANSMIT, tsubadr)&RT_FLAG) != 0)
   {
#ifdef ENG
    err_msg = "RT->BC:Earlier transmitted subaddress flag set";
#else
    err_msg = "ОУ->КК:Установился флаг для ранее переданного подадреса";
#endif
    goto fin;
   }
  }
  select_window(bcwin);
 }
 select_window(rtwin);
 rt_clear_ram();
 for (subadr = subadr1; subadr <= subadr2; subadr++)
 {
  rtdefsubaddr(RT_RECEIVE, subadr);
  rtclrflag();
 }
 select_window(bcwin);
 bcdefbase(base=1);
 for (subadr = subadr1; subadr <= subadr2; subadr++)
 {
  ctrl_code = DATA_BC_RT;
  buffer[0] = (rtadr<<11) | RT_RECEIVE | (subadr<<5) | 1;
  buffer[1] = (page<<14) | (subadr<<8) | (page<<6) | subadr;
  bcputblk(0, buffer, 2);
  start_1("");
  if (int_num[bcnum] != 1)
  {
#ifdef ENG
   err_msg = "BC->RT:Receiving to subaddress with reset flag didn't pass";
#else
   err_msg = "КК->ОУ:Не прошел прием в подадрес со сброшенным флагом";
#endif
   goto fin;
  }
  select_window(rtwin);
  for (tsubadr = subadr1; tsubadr < subadr; tsubadr++)
  {
   if ((rtgetflag(RT_RECEIVE, tsubadr)&RT_FLAG) == 0)
   {
#ifdef ENG
    err_msg = "BC->RT:Earlier received subaddress flag reset";
#else
    err_msg = "КК->ОУ:Сбросился флаг для ранее принятого подадреса";
#endif
    goto fin;
   }
  }
  if ((rtgetflag(RT_RECEIVE, subadr)&RT_FLAG) == 0)
  {
#ifdef ENG
   err_msg = "BC->RT:Received subaddress flag didn't set";
#else
   err_msg = "КК->ОУ:Не установился флаг для принятого подадреса";
#endif
   goto fin;
  }
  if (rtgetw(0) != ((page<<14) | (subadr<<8) | (page<<6) | subadr))
  {
#ifdef ENG
   err_msg = "BC->RT:Data in Rx subaddress didn't change";
#else
   err_msg = "КК->ОУ:Данные в подадресе приема не изменились";
#endif
   goto fin;
  }
  for (tsubadr = subadr+1; tsubadr < subadr2; tsubadr++)
  {
   if ((rtgetflag(RT_RECEIVE, tsubadr)&RT_FLAG) != 0)
   {
#ifdef ENG
    err_msg = "BC->RT:Not yet received subaddress flag set";
#else
    err_msg = "КК->ОУ:Установился флаг для еще не принятого подадреса";
#endif
    goto fin;
   }
  }
  select_window(bcwin);
 }
 for (subadr = subadr1; subadr <= subadr2; subadr++)
 {
  ctrl_code = DATA_BC_RT;
  buffer[0] = (rtadr<<11) | RT_RECEIVE | (subadr<<5) | 1;
  buffer[1] = 0xFFFF;
  bcputblk(0, buffer, 2);
  start_1("");
  if (int_num[bcnum] != 2 || bc_sw != S_IB_MASK)
  {
#ifdef ENG
   err_msg = "BC->RT:Receiving to subaddress with set flag test didn't pass";
#else
   err_msg = "КК->ОУ:Не прошел тест приема в подадрес с установленным флагом";
#endif
   goto fin;
  }
  select_window(rtwin);
  rtdefsubaddr(RT_RECEIVE, subadr);
  if (rtgetw(0) == 0xFFFF)
  {
#ifdef ENG
   err_msg = "BC->RT:Data were written in Rx subaddress with set flag";
#else
   err_msg = "КК->ОУ:При приеме в подадрес с установленным флагом записались данные";
#endif
   goto fin;
  }
  for (tsubadr = subadr1; tsubadr <= subadr2; tsubadr++)
  {
   if ((rtgetflag(RT_RECEIVE, tsubadr)&RT_FLAG) == 0)
   {
#ifdef ENG
    err_msg = "BC->RT:Earlier received subaddress flag reset";
#else
    err_msg = "КК->ОУ:Сбросился флаг для ранее принятого подадреса";
#endif
    goto fin;
   }
  }
  select_window(bcwin);
 }
/* Конец теста */
 avt_ok = 1;
#ifdef ENG
 err_msg = "Remote Terminal flag mode test completed";
#else
 err_msg = "Тест флагового режима оконечного устройства завершен";
#endif
 fin:
/*
 if (prtscr_flag)
 {
  prtscr_flag = 0;
  err_msg = "Тест прерван по PrtScr";
 }
*/
 select_window(rtwin);
 rtdefmode((TMK_DATA)(rtgetmode()&(~RT_FLAG_MODE)));
 check_int();
 all_screen();
 putchar('\007');
 if (avt_ok)
  textcolor(GREEN);
 else
  textcolor(LIGHTRED);
 comment(err_msg);
 textcolor(LIGHTGRAY);
 select_window(bcwin);
 statistic_out("");
 select_window(nmainwin=rtwin);
 avt_ctrl("0");
}

int cmp_ram_buf(int offset, int voffset, int size)
/* сравнение буфера и ram_window: 0 - все ОК, 1 - ошибка
offset - смещение, size - размер сравниваемых массивов */
{
 int i;

 if (voffset >= 0)
 {
  switch (tmkgetmode())
  {
  case BC_MODE:
   bcgetblk(0, vbuffer, (TMK_DATA)(size+voffset));
   break;
  case RT_MODE:
   rtgetblk(0, vbuffer, (TMK_DATA)(size+voffset));
  }
 }
 else
  voffset = 0;
 for (i=0; i < size; i++)
  if (buffer[i+offset]!=vbuffer[i+voffset]) return 1;
 return 0;
}

void avt_ctrl(char *str)                /* управление выводом на экран */
{
 unsigned short a;

 if (sscanf(str, "%u", &a)!=1)
 {
  msg_out(inp_err);
  return;
 }
 if (a!=0 && a!=1)
 {
#ifdef ENG
  msg_out("Wrong variable value");
#else
  msg_out("Неверное значение переменной");
#endif
  return;
 }
 avtomat=a;
}

#ifdef STEND
void init_lpt()
/*
       Вычисление номеров портов по таблице данных BIOS .
*/
{
 lpt_data_port=peek(0x0040, 8+(lpt_num-1)*2); /* адреса портов LPT */
 lpt_status_port=lpt_data_port+1;
 lpt_ctrl_port=lpt_data_port+2;
}

void set_lpt_data(unsigned short char data)
{
 outportb(lpt_data_port, data);
}
#endif

void buf_fill(char *str)   /* заполнение буфера константой */
{
 unsigned short start, end, len, constant;

 while (*str == '\t' || *str == ' ') str++;
 if (sscanf(str, "%u", &start) != 1)
 {
  msg_out(mark_err); return;
 }
 if (start > buf_size-1)
 {
  msg_out(mark_err); return;
 }
 while (*str != ' ' && *str != ', ') str++;
 while (*str == ' ' || *str == ', ') str++;
 if (sscanf(str, "%u", &end) != 1)
 {
  msg_out(mark_err); return;
 }
 if (end < start || end > buf_size-1)
 {
  msg_out(mark_err); return;
 }
 while (*str != ' ' && *str != ', ') str++;
 while (*str == ' ' || *str == ', ') str++;
 if (sscanf(str, "%x", &constant) != 1)
 {
  msg_out(const_err); return;
 }
 len = end - start + 1;
 while (end >= start) buffer[end--]=constant;
 out_buffer();
 switch (Window[nwin].nMode)
 {
 case BC_MODE:
  bcdefbase(base);
  bcputblk(start, buffer+start, len);
  break;
 case RT_MODE:
  rtdefsubaddr(dir, subadr);
  rtputblk(start, buffer+start, len);
 }
}

void buf_clear(char *str)  /* очистка буфера */
{
 int i;

 if (end_ctrl(str)) return;
 for (i=64; i-- != 0; buffer[i]=0);
 buf_mark=0;
 in_ed_word=3;
 out_buffer();
 switch(Window[nwin].nMode)
 {
 case BC_MODE:
  bcdefbase(base);
  bcputblk(0, buffer, 36);
  break;
 case RT_MODE:
  rtdefsubaddr(dir, subadr);
  rtputblk(0, buffer, 32);
 }
}

int end_ctrl(char *str)
  /* контроль конца строки(для команд без аргументов):
     1 - в строке еще что-то значащее есть, 
     0 - в строке пусто                 */
{
 while (*str == '\t' || *str == ' ') str++;
 if (*str)
 {
  msg_out(undef_cmd);
  return 1;
 }
 else
  return 0;
}

void clear_dump()
{
 int y, maxy;

 maxy = (avtomat) ? BDUMP_Y + 3 : BDUMP_Y + 4;
 for (y = BDUMP_Y - 1; y <= maxy; y++)
 {
  gotoxy(1, y);
  clreol();
 }
}

void buf_edit(char *str)                   /* редактирование буферной памяти */
{
 static int in_word=3;    /* номер текущей тетрады для редактирования */
 static int edit_mode=0;  /* текущий режим редактирования: 0 - HEX, 1 - BIN */
 static int bit_num=15;   /* текущий бит при редактировании */
 unsigned short key, tetrada, bit;
 int tmkmode;

 switch (tmkmode = Window[nwin].nMode)
 {
 case BC_MODE:
  bc_out_ram(base);
  break;
 case RT_MODE:
  rt_out_ram(dir, subadr);
 }
 while (*str == '\t' || *str == ' ') str++;
 if (!mark_set(str, &buf_mark))
 {
   do
   {
    if (edit_mode)
    {
     bin_unpack(62, BDUMP_Y, buf_mark, buffer[buf_mark]);
     gotoxy(BDUMP_X-1+5*(buf_mark%DUMP_WIDE+1)-3, BDUMP_Y+buf_mark/DUMP_WIDE);
     printf("%04X", buffer[buf_mark]);
     gotoxy(61+(16-bit_num), BDUMP_Y+1);
    }
    else
    {
     bin_unpack(62, BDUMP_Y, buf_mark, buffer[buf_mark]);
     gotoxy(BDUMP_X-1+5*(buf_mark%DUMP_WIDE+1)-in_word, BDUMP_Y+buf_mark/DUMP_WIDE);
    }
    while (kbhit() == 0)
     WaitForMultipleObjects(nWaitEvents+1, ahWaitEvents, FALSE, 0);
    key=bioskey();
    if ((key & 0x00FF) && key != GPLUSW)
    {
     switch (key = toupper(key&0x00FF))       /* обычные и символы управления */
     {
     case 'Q':
     case ESCAPE:
                    key='Q';
                    break;
     case TAB:
                    if (edit_mode)
                    {
                     edit_mode=0;
                     in_word=bit_num/4;
                    }
                    else
                    {
                     edit_mode=1;
                     bit_num=in_word*4+3;
                    }
                    break;
     case CR:
     case LF:
                    edit_mode=0;
                    if (buf_mark != DUMP_SIZE-1)
                     ++buf_mark;
                    else
                     buf_mark=0;
                    break;
                   case ' ':
                    if (edit_mode) break;
                    if (in_word == 0)
                    {
                     if (buf_mark != DUMP_SIZE-1)
                     {
                      in_word=3;
                      buf_mark++;
                     }
                    }
                    else
                     in_word--;
                    break;
     case BACKSPACE:
                    if (edit_mode) break;
                    if (in_word == 3)
                    {
                     if (buf_mark != 0)
                     {
                      in_word=0;
                      buf_mark--;
                     }
                    }
                    else
                     in_word++;
                    break;
     default:
                    if (edit_mode)
                    {
                     if (key != '0' && key != '1') break;
                     bit=key-'0';
                     buffer[buf_mark]&=~(0x0001<<bit_num);
                     buffer[buf_mark]|=(bit<<bit_num);
                     if (bit_num != 0) bit_num--;
                     break;
                    }
                    if (key >= '0' && key <= '9')
                     tetrada=key-'0';
                    else if (key >= 'A' && key <= 'F')
                     tetrada=key-'A'+10;
                    else
                     break;
                    putchar(key);
                    buffer[buf_mark]&=~(0x000F<<in_word*4);
                    buffer[buf_mark]|=(tetrada<<in_word*4);
                    if (in_word == 0)
                    {
                     if (buf_mark != DUMP_SIZE-1)
                     {
                      in_word=3;
                      buf_mark++;
                     }
                    }
                    else
                     in_word--;
                    break;
                   }
    }
    else
    {
     switch (key)                            /* функциональные клавиши */
     {
     case F01:
                clear_dump();
  #ifdef ENG
                 gotoxy(1, BDUMP_Y);
                 printf("  \x1E     SPACE - tetrada right, \x11--(BACKSPACE) - tetrada left, ");
                 gotoxy(1, BDUMP_Y+1);
                 printf("\x11   \x10 - go to words, HOME - buffer begin, END - buffer end, ");
                 gotoxy(1, BDUMP_Y+2);
                 printf("  \x1F     TAB - HEX/BIN mode, Q(F10) - finish editing.");
                 gotoxy(1, BDUMP_Y+3);
                 switch (tmkmode)
                 {
                 case BC_MODE:
                  printf("        PGUP, PGDN - change base.");
                  break;
                 case RT_MODE:
                  printf("        PGUP, PGDN - change subaddress, GRAY PLUS - Tx/Rx.");
                 }
  #else
                 gotoxy(1, BDUMP_Y);
                 printf("  \x1E     ПРОБЕЛ - на тетраду вправо, \x11--(BACKSPACE) - на тетраду влево, ");
                 gotoxy(1, BDUMP_Y+1);
                 printf("\x11   \x10 - перемещение по словам, HOME - в начало буфера, END - в конец буфера, ");
                 gotoxy(1, BDUMP_Y+2);
                 printf("  \x1F     TAB - HEX/BIN режим, Q(F10) - завершить редактирование.");
                 gotoxy(1, BDUMP_Y+3);
                 switch (tmkmode)
                 {
                 case BC_MODE:
                  printf("        PGUP, PGDN - изменение базы.");
                  break;
                 case RT_MODE:
                  printf("        PGUP, PGDN - изменение подадреса, СЕРЫЙ ПЛЮС - Прием/Передача.");
                 }
  #endif
                while (!kbhit())
                 WaitForMultipleObjects(nWaitEvents+1, ahWaitEvents, FALSE, 0);
                bioskey();
                clear_dump();
                out_buffer();
                break;
     case LEFT:
                if (edit_mode)
                {
                 if (bit_num != 15)
                  bit_num++;
                 break;
                }
                if (buf_mark != 0) --buf_mark;
                else buf_mark=DUMP_SIZE-1;
                in_word = 3;
                break;
     case RIGHT:
                if (edit_mode)
                {
                 if (bit_num != 0) bit_num--;
                 break;
                }
                if (buf_mark != DUMP_SIZE-1) ++buf_mark;
                else buf_mark=0;
                in_word = 3;
                break;
     case UP:
                if (edit_mode)
                {
                 if (buf_mark != 0) --buf_mark;
                 else buf_mark=DUMP_SIZE-1;
                 break;
                }
                if (buf_mark-DUMP_WIDE >= 0) buf_mark-=DUMP_WIDE;
                else
                {
                 buf_mark+=(DUMP_WIDE*(DUMP_STRINGS-1));
                 if (buf_mark > DUMP_SIZE-1) buf_mark-=DUMP_WIDE;
                }
                in_word = 3;
                break;
     case DOWN:
                if (edit_mode)
                {
                 if (buf_mark != DUMP_SIZE-1) ++buf_mark;
                 else buf_mark=0;
                 break;
                }
                if (buf_mark+DUMP_WIDE <= DUMP_SIZE-1) buf_mark+=DUMP_WIDE;
                else
                {
                 buf_mark-=(DUMP_WIDE*(DUMP_STRINGS-1));
                 if (buf_mark < 0) buf_mark+=DUMP_WIDE;
                }
                in_word = 3;
                break;
     case HOME:
                if (edit_mode)
                {
                 bit_num=15;
                 break;
                }
                buf_mark=0;
                in_word = 3;
                break;
     case END:
                if (edit_mode)
                {
                 bit_num=0;
                 break;
                }
                buf_mark=DUMP_SIZE-1;
                in_word = 3;
                break;
     case GPLUS:
                if (tmkmode == RT_MODE)
                {
                 rtputblk(0, buffer, 32);
                 dir = (dir == RT_TRANSMIT) ? RT_RECEIVE : RT_TRANSMIT;
                 rtdefsubaddr(dir, subadr);
                 rtgetblk(0, buffer, 32);
                 out_subadr();
                 out_buffer();
                }
                break;
     case PGUP:
                switch (tmkmode)
                {
                case BC_MODE:
                 if (base > 0)
                 {
                  bcputblk(0, buffer, 36);
                  bcdefbase(--base);
                  bcgetblk(0, buffer, 36);
                  out_base();
                  out_buffer();
                 }
                 break;
                case RT_MODE:
                 if (subadr > 0)
                 {
                  rtputblk(0, buffer, 32);
                  rtdefsubaddr(dir, --subadr);
                  rtgetblk(0, buffer, 32);
                  out_subadr();
                  out_buffer();
                 }
                }
                in_word = 3;
                break;
     case PGDN:
                switch (tmkmode)
                {
                case BC_MODE:
                 if (base < bcgetmaxbase())
                 {
                  bcputblk(0, buffer, 36);
                  bcdefbase(++base);
                  bcgetblk(0, buffer, 36);
                  out_base();
                  out_buffer();
                 }
                 break;
                case RT_MODE:
                 if (subadr < 31)
                 {
                  rtputblk(0, buffer, 32);
                  rtdefsubaddr(dir, ++subadr);
                  rtgetblk(0, buffer, 32);
                  out_subadr();
                  out_buffer();
                 }
                }
                in_word = 3;
                break;
     case F10:
                key='Q';
                break;
     }
     continue;
    }
   }
   while (key != 'Q');
 }
 switch (tmkmode)
 {
 case BC_MODE:
  bcputblk(0, buffer, 36);
  break;
 case RT_MODE:
  rtputblk(0, buffer, 32);
 }
}

int mark_set(char *str, int *mark)
/* ввод номера текущего слова для редактирования
1 - ошибка, 0 - все в порядке
*/
{
 unsigned short i, constant;

 if (*str == '\0') return 0;
 if ((sscanf(str, "%u", &i)) != 1)
 {
  msg_out(inp_err);
  return 1;
 }
 if (i > DUMP_SIZE-1)
 {
  msg_out(mark_err);
  return 1;
 }
 *mark=i;
 while (*str != ' ' && *str != ', ' && *str != '\0') str++;
 if (!*str) return 0;
 while (*str == ' ' || *str == ', ') str++;
 if (sscanf(str, "%x", &constant) != 1) { msg_out(const_err); return 1; }
 buffer[*(mark)]=constant;
 out_buffer();
 return 1;
}


void out_func_str()   /* Вывод подсказки о назначении функциональных клавиш */
{
 int i;

#ifdef ENG
 static char *bc_func_str[10]={  " Help ",  /* F01 */
                                 "  RAM ",  /* F02 */
                                 "Set RT",  /* F03 */
                                 "Window",  /* F04 */
                                 " LoopF",  /* F05 */
                                 " Start",  /* F06 */
                                 " Loop ",  /* F07 */
                                 " Reset",  /* F08 */
                                 "Fields",  /* F09 */
                                 "Exit"    /* F10 */
                              };
 static char *rt_func_str[10]={  " Help ",  /* F01 */
                                 "  RAM ",  /* F02 */
                                 "Set BC",  /* F03 */
                                 "Window",  /* F04 */
                                 "      ",  /* F05 */
                                 "  RSW ",  /* F06 */
                                 "  RM  ",  /* F07 */
                                 " Reset",  /* F08 */
                                 "Fields",  /* F09 */
                                 "Exit"    /* F10 */
                              };
#else
 static char *bc_func_str[10]={  "Помощь",  /* F01 */
                                 "  БЗУ ",  /* F02 */
                                 "Уст.ОУ",  /* F03 */
                                 " Окно ",  /* F04 */
                                 " ЦиклФ",  /* F05 */
                                 " Старт",  /* F06 */
                                 " Цикл ",  /* F07 */
                                 " Сброс",  /* F08 */
                                 " Поля ",  /* F09 */
                                 "Вых."    /* F10 */
                              };
 static char *rt_func_str[10]={  "Помощь",  /* F01 */
                                 "  БЗУ ",  /* F02 */
                                 "Уст.КК",  /* F03 */
                                 " Окно ",  /* F04 */
                                 "      ",  /* F05 */
                                 "  РСС ",  /* F06 */
                                 "  РРЖ ",  /* F07 */
                                 " Сброс",  /* F08 */
                                 " Поля ",  /* F09 */
                                 "Вых."    /* F10 */
                              };
#endif

 gotoxy(1, 25);
 for (i=1; i <= 10; i++)
 {
  printf("%u", i);
  textbackground(LIGHTGRAY);
  textcolor(BLACK);
  switch (Window[nwin].nMode)
  {
  case BC_MODE: printf("%s", bc_func_str[i-1]);
                break;
  case RT_MODE: printf("%s", rt_func_str[i-1]);
                break;
  }
  textbackground(BLACK);
  textcolor(LIGHTGRAY);
  putchar(' ');
 }
}

void hor_line(int maxi)
{
 register i;
 for (i = 1; i <= maxi; i++)
  putchar(chH);
 
}

void all_screen()                                   /* Вывод полного экрана */
{
 int savenwin, nDX, nDY, i;

 savenwin = nwin;
 clrscr();
 window(1, 1, 80, 25);
 out_func_str();
 for (nwin = 0; nwin <= nMaxWin; nwin++)
 {
  if (!Window[nwin].fVisible)
   continue;
  select_window(nwin);
  if (nwin == savenwin)
  {
   textcolor(WHITE);
   chLU = '╔';
   chRU = '╗';
   chLD = '╚';
   chRD = '╝';
   chV = '║';
   chH = '═';
  }
  else
  {
   textcolor(LIGHTGRAY);
   chLU = '┌';
   chRU = '┐';
   chLD = '└';
   chRD = '┘';
   chV = '│';
   chH = '─';
  }
  nDX = Window[nwin].nDX;
  nDY = Window[nwin].nDY;
  window(Window[nwin].nX, Window[nwin].nY, 
          Window[nwin].nX + nDX - 1, 
          Window[nwin].nY + nDY - 1);
  gotoxy(1, 1);
  putchar(chLU);
  hor_line(nDX - 2);
  putchar(chRU);
  for (i = 2; i < nDY; i++)
  {
   gotoxy(1, i);
   putchar(chV);
   gotoxy(nDX, i);
   putchar(chV);
  }
  gotoxy(1, nDY);
  putchar(chLD);
  hor_line(nDX - 2);
  putchar(chRD);
  window(Window[nwin].nX + 1, Window[nwin].nY, 
          Window[nwin].nX + nDX - 2, 
          Window[nwin].nY + nDY - 1);
  textcolor(LIGHTGRAY);
  out_mode();
  out_type();
  out_fname();
  out_inn();
  switch(Window[nwin].nMode)
  {
  case BC_MODE:
   out_count();
   out_number();
   out_base();
   out_pause();
   out_ctrl_code();
   bc_out_sw();
   bc_out_ram(base);
   break;
  case RT_MODE:
   out_subadr();
   out_at();
   out_page();
   out_rt_mode();
   out_status_word();
   rt_out_sw();
   rt_out_ram(dir, subadr);
   break;
  }
 }
 nwin = savenwin;
 select_window(nwin);
 window(Window[nwin].nX + 1, Window[nwin].nY, 
         Window[nwin].nX + Window[nwin].nDX - 2, 
         Window[nwin].nY + Window[nwin].nDY - 1);
}

void bc_out_ram(TMK_DATA base)
  /* чтение и вывод дампа базы БЗУ */
{
 bcdefbase(base);
 bcgetblk(0, buffer, 36);
 out_buffer();
}

void rt_out_ram(TMK_DATA dir, TMK_DATA subadr)
  /* чтение и вывод дампа подадреса БЗУ */
{
 if (fLock)
   rtlock(dir, subadr);
 else
   rtdefsubaddr(dir, subadr);
 rtgetblk(0, buffer, 32);
 out_buffer();
}


void out_buffer()      /* вывод дампа буфера */
{
 gotoxy(1, BDUMP_Y-1);
#ifdef ENG
 printf("     RAM");
#else
 printf("     БЗУ");
#endif
 gotoxy(BDUMP_X, BDUMP_Y-1);
 out_dump(buffer);
 bin_unpack(62, BDUMP_Y, buf_mark, buffer[buf_mark]);
}

void bin_unpack(int x, int y, int adr, int data)
/*
вывод адреса и содержимого(двоичная форма)
x, y - место расположения
*/
{
 gotoxy(x, y);
 printf("%03Xh:%02u: %04X", adr, adr, data);
 gotoxy(x, y+1);
 out_bin(data, 16);
 gotoxy(x, y+2);
 printf("FEDCBA9876543210");
}

void bc_out_sw()                    /* вывода слова состояния (bc_sw) */
{
 char *pszRes;
 gotoxy(2, 4);
#ifdef ENG
 printf("   Result: ");
#else
 printf("Результат: ");
#endif
 if (int_num[Window[nwin].nTMK])
  out_bin(bc_sw, 7);
 else
 {
  printf("XXXXXXX");
  bc_sw = 0;
 }
#ifdef ENG
 if (bc_sw & S_ERAO_MASK)
  pszRes = "RT address error           ";
 else if (bc_sw & S_MEO_MASK)
  pszRes = "Manchester code error      ";
 else if (bc_sw & S_TO_MASK)
  pszRes = "No Status word/Data word(s)";
 else if (bc_sw & S_EM_MASK)
  pszRes = "Internal device error      ";
 else if (bc_sw & S_EBC_MASK)
  pszRes = "Echocheck error            ";
 else if (bc_sw & S_ELN_MASK)
  pszRes = "Extra Data word(s)         ";
 else
  pszRes = "                           ";
 if (bc_sw & S_IB_MASK)
  printf(" Set bit.  %s |", pszRes);
 else
  printf(" %s           |", pszRes);
#else
 if (bc_sw & S_ERAO_MASK)
  pszRes = "Ошибка адреса ОУ           ";
 else if (bc_sw & S_MEO_MASK)
  pszRes = "Ошибка кода 'Манчестер-2'  ";
 else if (bc_sw & S_TO_MASK)
  pszRes = "Нет ОС или мало слов данных";
 else if (bc_sw & S_EM_MASK)
  pszRes = "Ошибка обмена в плате      ";
 else if (bc_sw & S_EBC_MASK)
  pszRes = "Ошибка эхоконтроля передачи";
 else if (bc_sw & S_ELN_MASK)
  pszRes = "Много слов данных          ";
 else
  pszRes = "                           ";
 if (bc_sw & S_IB_MASK)
  printf(" Бит в ОС. %s |", pszRes);
 else
  printf(" %s           |", pszRes);
#endif
}

void out_inn()                        /* вывод номера прерывания (int_num) */
{
 gotoxy(65, 4);
#ifdef ENG
 printf(" Interrupt: ");
#else
 printf("Прерывание: ");
#endif
 if (int_num[Window[nwin].nTMK])
  printf("%u", int_num[Window[nwin].nTMK]);
 else
  putchar('X');
 
}

void out_mode()     /* вывод текущего режима (mode) */
{
 gotoxy(2, 1);
 if (nwin == nmainwin)
  textcolor(WHITE);
 else
  textcolor(LIGHTGRAY);
 printf("%d%c", Window[nwin].nTMK, chH);
#ifdef ENG
 if (Window[nwin].nMode == BC_MODE)
  printf("BUS CONTROLLER");
 else if (Window[nwin].nMode == RT_MODE)
  printf("REMOTE TERMINAL");
#else
 if (Window[nwin].nMode == BC_MODE)
  printf("КОНТРОЛЛЕР КАНАЛА");
 else if (Window[nwin].nMode == RT_MODE)
  printf("ОКОНЕЧНОЕ УСТРОЙСТВО");
#endif
 textcolor(LIGHTGRAY);
 
}

void out_port(unsigned short wPort)
{
 if (wPort && wPort != 0xFFFF)
 {
  printf("%03Xh%c", wPort, chH);
  
 }
}

void out_irq(unsigned short wIrq)
{
 if (wIrq && ~wIrq && wIrq != 255 && wIrq != 65535)
 {
  printf("Irq %d%c", wIrq, chH);
  
 }
}

/*
void out_iodelay()
{
 printf("IOD%3d%c", tmkiodelay(GET_IO_DELAY), chH);
}
*/

void out_type()
{
 int nTMK = Window[nwin].nTMK;
 gotoxy(26, 1);
 if (nwin == nmainwin)
  textcolor(WHITE);
 else
  textcolor(LIGHTGRAY);
 printf("%s%c", aTmkConfig[nTMK].szName, chH);
 out_port(aTmkConfig[nTMK].wPorts1);
 out_port(aTmkConfig[nTMK].wPorts2);
 out_irq(aTmkConfig[nTMK].wIrq1);
 out_irq(aTmkConfig[nTMK].wIrq2);
// out_iodelay();
 textcolor(LIGHTGRAY);
}

void out_count()   /* вывод значения счетчика повторений */
{
 gotoxy(52, 2);
// printf("Циклы: %010lu", cmd_count);
// gotoxy(47, 2);
#ifdef ENG
 if (cmd_count <= 9999L)
   printf("Cycle: %04lu |", cmd_count);
 else
   printf("Cycle:>9999 |");
#else
 if (cmd_count <= 9999L)
   printf("Циклы: %04lu |", cmd_count);
 else
   printf("Циклы:>9999 |");
#endif
}

void out_fname()                      /* вывод имени последнего файла данных */
{
 gotoxy(61, 1);
#ifdef ENG
 printf("File:");
#else
 printf("Файл:");
#endif
 if (nwin == nmainwin)
 {
  textcolor(WHITE);
  printf("═════════════");
  textcolor(LIGHTGRAY);
 }
 else
  printf("─────────────");
 
 if (*Window[nwin].data_fname != '\0')
 {
  gotoxy(66, 1);
  printf("%s", Window[nwin].data_fname);
 }
}

void out_pause()               /* вывод значения времени ожидания прерывания */
{
// gotoxy(28, 2);
 gotoxy(32, 2);
#ifdef ENG
 printf("Pause: %5u us  |", opause);
#else
 printf("Пауза: %5u мкс |", opause);
#endif
}

void out_base()           /* вывод значения базы, используемого при запуске */
{
 gotoxy(20, 2);
#ifdef ENG
 printf("Base: %03X", base);
#else
 printf("База: %03X", base);
#endif
}

void out_number()                          /* вывод номера канала (bus_num) */
{
 gotoxy(1, 2);
#ifdef ENG
 printf("BUS: %1u |", bus_num+1);
#else
 printf("ЛПИ: %1u |", bus_num+1);
#endif
}

void out_ctrl_code()                    /* вывод кода управления (ctrl_code) */
{
 char *pszFmt;
 gotoxy(1, 3);
#ifdef ENG
 printf("  Control Code: ");
#else
 printf("Код управления: ");
#endif
 if (correct_cc(ctrl_code))
  out_bin(ctrl_code, CC_SIZE);
 else
  printf("XXXX");
 switch (ctrl_code)
 {
#ifdef ENG
 case 0x0: pszFmt = "(BC->RT)       ";
           break;
 case 0x1: pszFmt = "(RT->BC)       ";
           break;
 case 0x2: pszFmt = "(RT->RT)       ";
           break;
 case 0x3: pszFmt = "(CW - SW)      ";
           break;
 case 0x4: pszFmt = "(CW+DW - SW)   ";
           break;
 case 0x5: pszFmt = "(CW - SW+DW)   ";
           break;
 case 0x8: pszFmt = "(BC->all RTs)  ";
           break;
 case 0xA: pszFmt = "(RT->all RTs)  ";
           break;
 case 0xB: pszFmt = "(CW,all RTs)   ";
           break;
 case 0xC: pszFmt = "(CW+DW,all RTs)";
           break;
 default:  pszFmt = "(Not defined)  ";
           break;
#else
 case 0x0: pszFmt = "(КК->ОУ)       ";
           break;
 case 0x1: pszFmt = "(ОУ->КК)       ";
           break;
 case 0x2: pszFmt = "(ОУ->ОУ)       ";
           break;
 case 0x3: pszFmt = "(КС - ОС)      ";
           break;
 case 0x4: pszFmt = "(КС+ИС - ОС)   ";
           break;
 case 0x5: pszFmt = "(КС - ОС+ИС)   ";
           break;
 case 0x8: pszFmt = "(КК->всем ОУ)  ";
           break;
 case 0xA: pszFmt = "(ОУ->всем ОУ)  ";
           break;
 case 0xB: pszFmt = "(КС,всем ОУ)   ";
           break;
 case 0xC: pszFmt = "(КС+ИС,всем ОУ)";
           break;
 default:  pszFmt = "(Не определен) ";
           break;
#endif
 }
 printf(" %s |", pszFmt);
}

int correct_cc(int ctrl_code)
/*
проверка корректности кода управления:
0 - несуществующий, 1 - нормальный.
*/
{
 return ccs[ctrl_code&=0x000F];
}

void out_page()                               /* вывод номера страницы БЗУ */
{
 gotoxy(54, 3);
#ifdef ENG
 printf("   Page  Bus:%2u  PC:%2u", rtgetpagebus(), rtgetpagepc());
#else
 printf("Страница  МК:%2u  ПЭВМ:%2u", rtgetpagebus(), rtgetpagepc());
#endif
}

void out_rt_mode()
{
 gotoxy(52, 2);
#ifdef ENG
 printf(" Mode: ");
#else
 printf("Режим: ");
#endif
 if (rtgetmode() & RT_FLAG_MODE && tmkError == 0)
  printf("FLAG ");
 else
  printf("     ");
 if (hb_mode)
  printf("HBIT ");
 else
  printf("     ");
 if ((rtgetmode() & RT_BRCST_MODE) && tmkError == 0)
  printf("BCST ");
 else
  printf("     ");
 if ((rtgetirqmode() & RT_DATA_BL) && tmkError == 0)
  printf("DTBL");
 else
  printf("    ");
}

void out_at()                                   /* вывод адреса терминала */
{
 gotoxy(27, 2);
 if (Window[nwin].at_avail)
  terminal_adr = rtgetaddress();
#ifndef STEND
 else
 {
#ifdef ENG
  printf("RT Address: UNKNOWN  |");
#else
  printf("Адрес ОУ: НЕДОСТУПЕН |");
#endif
  return;
 }
#endif
#ifdef ENG
 printf("RT Addr.: %02u (", terminal_adr);
#else
 printf("Адрес ОУ: %02u (", terminal_adr);
#endif
 out_bin(terminal_adr, 5);
 putchar(')');
 
}

void rt_out_sw()                          /* вывод слова состояния (rt_sw) */
{
 gotoxy(1, 4);
#ifdef ENG
 printf("     State word: ");
#else
 printf("Слово состояния: ");
#endif
 out_bin(rt_sw, 16);
}

void out_subadr()                 /* вывод значения базы, используемого при запуске */
{
 gotoxy(1, 2);
#ifdef ENG
 printf("Subaddr.: ");
 if (dir == RT_TRANSMIT)
  printf("%02X (Transm.)  |", subadr);
 else
  printf("%02X (Recv.)    |", subadr);
#else
 printf("Подадрес: ");
 if (dir == RT_TRANSMIT)
  printf("%02X (Передача) |", subadr);
 else
  printf("%02X (Прием)    |", subadr);
#endif
}

void out_status_word()                  /* вывод битов ОС (status_word) */
{
  unsigned short status_word;

  status_word = rtgetanswbits();
  gotoxy(1, 3);
#ifdef ENG
  printf(" Status: ");
#else
  printf("Биты ОС: ");
#endif
  out_bin(status_word, SW_SIZE);
  if (status_word&DNBA)
   printf(" (DN ");
  else
   printf(" (-- ");
  if (status_word&RTFL)
   printf("TF ");
  else
   printf("-- ");
  if (status_word&SSFL)
   printf("SF ");
  else
   printf("-- ");
  if (status_word&BUSY)
   printf("BS ");
  else
   printf("-- ");
  if (status_word&SREQ)
   printf("SR)");
  else
   printf("--)");
  
}

void out_dump(unsigned short *data)
/*
Вывод пословного дампа:
adr - значение адреса используемое при выводе
data - указатель на слово, с которого происходит вывод дампа
*/
{
 int i;                 /* счетчик */
 int offset;            /* текущее смещение в массиве отн. data */
 int dump_y;

 gotoxy(BDUMP_X, BDUMP_Y-1);
 for (i=0; i != DUMP_WIDE; printf("  %01X  ", i++));
 dump_y = BDUMP_Y;
 for (offset=0; offset != DUMP_SIZE;)
 {
  gotoxy(1, dump_y);
  printf("     %02u: ", offset);
//  gotoxy(BDUMP_X, dump_y);
  for (i=0; (i != DUMP_WIDE) && (offset != DUMP_SIZE); i++, offset++)
   printf(" %04X", *(data+offset));
  dump_y++;
 }
 
}

void out_bin(int data, int num_digits)
/*
Вывод в двоичной форме:
data - выводимое значение
num_digits - число выводимых цифр, начиная справа
*/
{
 char string[16];
 int mask;
 int count;

 for (count=0, mask=1; count != 16; count++, mask<<= 1)
  string[count]=(data&mask)?'1':'0';
 if (fields && num_digits == 16)
 {
  count=num_digits;    /* вывод слова с выделением полей */
  textcolor(CYAN);
  for (; count != 11; putchar(string[--count]));
  textcolor(LIGHTRED);
  putchar(string[--count]);
  textcolor(YELLOW);
  for (; count != 5; putchar(string[--count]));
  textcolor(GREEN);
  for (; count != 0; putchar(string[--count]));
  textcolor(LIGHTGRAY);
 }
 else       /* вывод без выделения полей */
 {
  for (count=num_digits; --count >= 0; putchar(string[count]));
 }
}

void cmds_open(char *str)   /* открытие командного файла */
{
 while (*str == ' ' || *str == '\t') str++;
 if (enter_mode)             /* если командный файл вызывается из командного */
 {
  fclose(cmd_file);
  enter_mode=0;
 }
 if ((cmd_file=fopen(str, "rt")) == NULL)
 {
  msg_out(open_err);
  return;
 }
 enter_mode=1;
}

void bc_buf_rd(char *str) /* чтение кода управления и буфера из файла */
{
 int ch;
 char *ptr;

 int ctrl_code2, offset;
 static unsigned short buffer2[BC_BUF_SIZE];

 while (*str == ' ' || *str == '\t') str++;
 if ((in_file=fopen(str, "rt")) == NULL)
 {
  msg_out(open_err);
  return;
 }
 while (*str != '\0') str++;
 str--;
 for (; *str != ':' && *str != '\\' && *str != ' ' && *str != '\t'; str--);
 str++;
 strcpy(Window[nwin].data_fname, str);
 out_fname();
 fgets(buf_str, 80, in_file); /* пропустить пустую строку */
                              /* чтение кода управления из файла */
 fgets(buf_str, 80, in_file); /* пропустить строку подсказки */
 if ((fgets(buf_str, 80, in_file)) == NULL)
 {
  msg_out(format_err);
  return;
 }
 str=buf_str;
 while (*str == '\t' || *str == ' ') str++;
 ptr=str;
 while ((ch=*(ptr++)) != ' ')
 {
  if (ch != '0' && ch != '1')
  {
   msg_out(bad_ctrl_code);
   return;
  }
 }
 --ptr;
 if (ptr-str > CC_SIZE)
 {
  msg_out(bad_ctrl_code);
  return;
 }
 ptr=str;
 for (ctrl_code2=0; *ptr != ' '; ptr++)
 {
  ctrl_code2<<= 1;
  if (*ptr == '1') ctrl_code2++;
 }
 if (!correct_cc(ctrl_code2))
 {
#ifdef ENG
  sprintf(cc_no_def, "Wrong control code");
#else
  sprintf(cc_no_def, "Неверный код управления");
#endif
  msg_out(cc_no_def);
  return;
 }
                              /* Чтение в буфер из файла */
 fgets(buf_str, 80, in_file); /* пропустить строку подсказки */
 offset=0;
 while (offset != BC_DUMP_SIZE)
 {
  if (fscanf(in_file, "%x ", &buffer2[offset]) != 1)
  {
   msg_out(format_err);
   return;
  }
  if ((++offset%DUMP_WIDE) == 0)
   while ((ch=fgetc(in_file)) != '\n')
    if (ch == EOF)
    {
     msg_out(format_err);
     return;
    }
 }
 ctrl_code=ctrl_code2;
 out_ctrl_code();
 for (offset=0; offset != BC_DUMP_SIZE; offset++)
  buffer[offset]=buffer2[offset];
 bcputblk(0, buffer, 36);
 out_buffer();
 fclose(in_file);
}

void bc_buf_wr(char *str)   /* запись буфера и кода управления в файл */
{

 int i, offset;

 while (*str == ' ' || *str == '\t') str++;
 if ((out_file=fopen(str, "wt")) == NULL)
 {
  msg_out(cr_err);
  return;
 }
 strcpy(Window[nwin].data_fname, str);
 out_fname();
 {
  int mask;
  int count;
  fprintf(out_file, "\n");
#ifdef ENG
  fprintf(out_file, "Control Code:\n");
#else
  fprintf(out_file, "Код управления:\n");
#endif
  if (correct_cc(ctrl_code))
   for (count=0, mask=8; count != 4; count++, mask>>= 1)
    fprintf(out_file, "%c", ((ctrl_code&mask)?'1':'0'));
  else
  {
#ifdef ENG
   fprintf(out_file, "XXXX (Not defined)\n");
#else
   fprintf(out_file, "XXXX (Не определен)\n");
#endif
   goto out_data;
  }
  switch (ctrl_code & 0x0007)
  {
#ifdef ENG
  case 0x0: fprintf(out_file, " (BC->RT");
            break;
  case 0x1: fprintf(out_file, " (RT->BC");
            break;
  case 0x2: fprintf(out_file, " (RT->RT");
            break;
  case 0x3: fprintf(out_file, " (CW->SW");
            break;
  case 0x4: fprintf(out_file, " (CW+DW->SW");
            break;
  case 0x5: fprintf(out_file, " (CW->SW+DW");
            break;
#else
  case 0x0: fprintf(out_file, " (КК->ОУ");
            break;
  case 0x1: fprintf(out_file, " (ОУ->КК");
            break;
  case 0x2: fprintf(out_file, " (ОУ->ОУ");
            break;
  case 0x3: fprintf(out_file, " (КС->ОС");
            break;
  case 0x4: fprintf(out_file, " (КС+ИС->ОС");
            break;
  case 0x5: fprintf(out_file, " (КС->ОС+ИС");
            break;
#endif
  }
  if (ctrl_code & 0x0008)
#ifdef ENG
   fprintf(out_file, ", broadcast)\n");
#else
   fprintf(out_file, ", групповая посылка)\n");
#endif
   else fprintf(out_file, ")\n");
 }
 out_data:;
#ifdef ENG
 fprintf(out_file, "Buffer:\n");
#else
 fprintf(out_file, "Буфер:\n");
#endif
 for (offset=0; offset < BC_DUMP_SIZE;)
  {
    for (i=0; i < DUMP_WIDE; i++, ++offset)
      if (offset < BC_DUMP_SIZE)
        fprintf(out_file, "%04X ", buffer[offset]);
      else
        fprintf(out_file, "     ");
    fprintf(out_file, "   : %02u", offset-DUMP_WIDE);
    fprintf(out_file, "\n");
  }
 for (i=0; i != DUMP_WIDE;  fprintf(out_file, "  %01X  ", i++));
 fprintf(out_file, "\n");
 fclose(out_file);
}

void rt_buf_rd(char *str)                               /* чтение в буфер из файла */
{
 int ch;

 int offset;
 unsigned short buffer2[RT_BUF_SIZE];

 while (*str == ' ' || *str == '\t') str++;
 if ((in_file=fopen(str, "rt")) == NULL)
 {
  msg_out(open_err);
  return;
 }
 strcpy(Window[nwin].data_fname, str);
 out_fname();
 fgets(buf_str, 80, in_file); /* пропустить строку подсказки */
 fgets(buf_str, 80, in_file); /* пропустить строку подсказки */
 offset=0;
 while (offset != RT_DUMP_SIZE)
 {
  if (fscanf(in_file, "%x ", &buffer2[offset]) != 1)
  {
   msg_out(format_err);
   return;
  }
  if ((++offset%DUMP_WIDE) == 0)
   while ((ch=fgetc(in_file)) != '\n')
    if (ch == EOF)
    {
     msg_out(format_err);
     return;
    }
 }
 for (offset=0; offset != RT_DUMP_SIZE; offset++)
  buffer[offset]=buffer2[offset];
 out_buffer();
 fclose(in_file);
}

void rt_buf_wr(char *str)                  /* запись буфера и кода управления в файл */
{

 int i, offset;

 while (*str == ' ' || *str == '\t') str++;
 if ((out_file=fopen(str, "wt")) == NULL)
 {
  msg_out(cr_err);
  return;
 }
 strcpy(Window[nwin].data_fname, str);
 out_fname();
#ifdef ENG
 fprintf(out_file, "\nBuffer:\n");
#else
 fprintf(out_file, "\nБуфер:\n");
#endif
 for (offset=0; offset < RT_DUMP_SIZE;)
 {
  for (i=0; i < DUMP_WIDE; i++, ++offset)
   if (offset < RT_DUMP_SIZE)
    fprintf(out_file, "%04X ", buffer[offset]);
   else
    fprintf(out_file, "     ");
  fprintf(out_file, "   : %02u", offset-DUMP_WIDE);
  fprintf(out_file, "\n");
 }
 for (i=0; i != DUMP_WIDE;  fprintf(out_file, "  %01X  ", i++));
 fprintf(out_file, "\n");
 fclose(out_file);
}

void set_base(char *str)
/* ввод подадреса из командной строки: 1 - ошибка, 0 - все в порядке */
{
 unsigned short i;

 if (sscanf(str, "%x", &i) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (i > bcgetmaxbase())
 {
  msg_out(base_err);
  return;
 }
 base=i;
 out_base();
 bc_out_ram(base);
}

void set_ctrl_code(char *str)           /* команда установки кода управления */
{
 char ch, *ptr;
 int ctrl_code2;

 while (*str == '\t' || *str == ' ') str++;
 ptr=str;
 while ((ch=*(ptr++)) != '\0')
  if (ch != '0' && ch != '1')
  {
   msg_out(bad_ctrl_code);
   return;
  }
 --ptr;
 if (ptr-str > CC_SIZE)
 {
  msg_out(bad_ctrl_code);
  return;
 }
 ptr=str;
 for (ctrl_code2=0; *ptr != '\0'; ptr++)
 {
  ctrl_code2<<= 1;
  if (*ptr == '1') ctrl_code2++;
 }
 if (!correct_cc(ctrl_code2))
 {
#ifdef ENG
  sprintf(cc_no_def, "Control code %s not defined", str);
#else
  sprintf(cc_no_def, "Код управления %s не определен", str);
#endif
  msg_out(cc_no_def);
  return;
 }
 ctrl_code=ctrl_code2;
 out_ctrl_code();
}

void set_number(char *str)               /* команда установки номера канала */
{
 unsigned short i;

 if (sscanf(str, "%01x", &i) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (i > 2 || i == 0)
 {
  msg_out(bus_num_err);
  return;
 }
 bus_num = (i == 1) ? BUS_1 : BUS_2;
 if (bcdefbus(bus_num))
 {
  bus_num = BUS_1;
  msg_out(bus_num_err);
  return;
 }
 out_number();
}

void set_count(char *str)       /* установка циклов повторения команды */
{
 unsigned long c;

 if (sscanf(str, "%U", &c) != 1)
 {
  msg_out(inp_err);
  return;
 }
 cmd_count=c;
 out_count();
}

void set_pause(char *str)            /* команда установки длины тайм-аута */
{
 unsigned short p;

 if (sscanf(str, "%U", &p) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (p > 27461)
 {
#ifdef ENG
  msg_out("Maximum allowable pause - 27461 us.");
#else
  msg_out("Максимальное значение паузы - 27461 мкс.");
#endif
  return;
 }
 opause = p;
 pause = (unsigned short)((unsigned long)p * 2L * 11932L / 10000L);
 out_pause();
}

void set_cpage(char *str)                 /* установка текущей страницы МК */
{
 unsigned short p;

 if (sscanf(str, "%u", &p) != 1)
 {
  msg_out(inp_err);
  return;
 }
 switch (rtdefpagebus(p))
 {
 case RT_BAD_FUNC:
#ifdef ENG
  msg_out("Can not define separate page for bus channel");
#else
  msg_out("Невозможно задать отдельно страницу БЗУ для МК");
#endif
  break;
 case RT_BAD_PAGE:
#ifdef ENG
  msg_out("Wrong page number");
#else
  msg_out("Неверное значение страницы БЗУ");
#endif
  break;
 case 0:
  cram_page=p;
  out_page();
  break;
 }
}

void set_spage(char *str)                 /* установка текущей страницы БЗУ */
{
 unsigned short p;

 if (sscanf(str, "%u", &p) != 1)
 {
  msg_out(inp_err);
  return;
 }
 switch (rtdefpagepc(p))
 {
 case RT_BAD_FUNC:
#ifdef ENG
  msg_out("Can not define separate page for PC");
#else
  msg_out("Невозможно задать отдельно страницу БЗУ для ПЭВМ");
#endif
  break;
 case RT_BAD_PAGE:
#ifdef ENG
  msg_out("Wrong page number");
#else
  msg_out("Неверное значение страницы БЗУ");
#endif
  break;
 case 0:
  bram_page=p;
  out_page();
  rtdefsubaddr(dir, subadr);
  rt_out_ram(dir, subadr);
  break;
 }
}

void set_page(char *str)       /* установка текущей страницы БЗУ */
{
 unsigned short p;

 if (sscanf(str, "%u", &p) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (rtdefpage(p))
#ifdef ENG
  msg_out("Wrong page number");
#else
  msg_out("Неверное значение страницы БЗУ");
#endif
 else
 {
  cram_page=bram_page=p;
  out_page();
  rtdefsubaddr(dir, subadr);
  rt_out_ram(dir, subadr);
 }
}

int wr_at(TMK_DATA at)
{
 int res;

 switch (res = rtdefaddress(at))
 {
 case RT_BAD_FUNC:
#ifdef STEND
  set_lpt_data(at);
  terminal_adr = at;
  res = 0;
#endif
 case RT_BAD_ADDRESS:
  break;
 case 0:
  terminal_adr = at;
 }
// rtenable(RT_ENABLE);
 return res;
}

void set_at(char *str)                          /* установка адреса ОУ */
{
 unsigned short p;

 if (sscanf(str, "%u", &p) != 1)
 {
  msg_out(inp_err);
  return;
 }
#ifndef STEND
 if (Window[nwin].at_avail)
#endif
  if (wr_at(p))
#ifdef ENG
   msg_out("Wrong RT address");
#else
   msg_out("Неверное значение адреса ОУ");
#endif
  else
   out_at();
#ifndef STEND
 else
#ifdef ENG
  msg_out("Can not define RT address program");
#else
  msg_out("Невозможно программно задать адрес ОУ");
#endif
#endif
}

void set_subadr_r(char *str)      /* установка подадареса, зона приема */
{
 if (set_subadr(str)) return;
 dir = RT_RECEIVE;
 rtdefsubaddr(dir, subadr);
 out_subadr();
 rt_out_ram(dir, subadr);
}

void set_subadr_t(char *str)      /* установка подадареса, зона передачи */
{
 if (set_subadr(str)) return;
 dir = RT_TRANSMIT;
 rtdefsubaddr(dir, subadr);
 out_subadr();
 rt_out_ram(dir, subadr);
}

int set_subadr(char *str)            /* ввод подадреса из командной строки */
{                                    /* 1 - ошибка, 0 - все в порядке */
 unsigned short i;

 if (sscanf(str, "%x", &i) != 1)
 {
  msg_out(inp_err);
  return 1;
 }
 if (i > 31)
 {
  msg_out(subadr_err);
  return 1;
 }
 subadr=i;
 return 0;
}

void set_sw_bits(char *str, TMK_DATA mask)                    /* установка битов ОС */
{
 if (end_ctrl(str)) return;
 rtsetanswbits(mask);
 out_status_word();
}


void clear_sw_bits(char *str, TMK_DATA mask)                  /* сброс битов ОС */
{
 if (end_ctrl(str)) return;
 rtclranswbits(mask);
 out_status_word();
}

void set_status_word(char *str)         /* команда установки ответного слова */
{
 char ch, *ptr;
 TMK_DATA status_word;

 while (*str == '\t' || *str == ' ') str++;
 ptr=str;
 while ((ch=*(ptr++)) != '\0')
  if (ch != '0' && ch != '1')
  {
   msg_out(bad_status_word);
   return;
  }
 --ptr;
 if (ptr-str > SW_SIZE)
 {
  msg_out(bad_status_word);
  return;
 }
 ptr=str;
 for (status_word=0; *ptr != '\0'; ptr++)
 {
  status_word<<= 1;
  if (*ptr == '1') status_word++;
 }
 rtclranswbits((TMK_DATA)(~status_word));
 rtsetanswbits(status_word);
 out_status_word();
}

void select_window(int nwindow)
{
 nwin = nwindow;
/*
 if (avtomat)
  nmainwin = nwin;
*/
 tmkselect(Window[nwin].nTMK);
 switch (Window[nwin].nMode)
 {
 case BC_MODE:
  if (!avtomat)
   base = bcgetbase();
  DUMP_STRINGS = BC_DUMP_STRINGS;
  DUMP_SIZE = BC_DUMP_SIZE;
  buf_size = BC_BUF_SIZE;
  break;
 case RT_MODE:
  if (!avtomat)
  {
   subadr = rtgetsubaddr();
   dir = subadr & RT_TRANSMIT;
   subadr &= ~RT_TRANSMIT;
  }
  DUMP_STRINGS = RT_DUMP_STRINGS;
  DUMP_SIZE = RT_DUMP_SIZE;
  buf_size = RT_BUF_SIZE;
 }
 if (avtomat || fInt)
  window(Window[nwin].nX + 1, Window[nwin].nY, 
         Window[nwin].nX + Window[nwin].nDX - 3, 
         Window[nwin].nY + Window[nwin].nDY - 1);
}

void my_wait(unsigned short pause)
{
/*
 unsigned short time1, dtime;

 time1 = get_timer();
 while (time1-get_timer() < pause);
*/
// struct timespec time1, time2;
 unsigned long ltime1, ltime2, d_usec;
 
 ltime1 = GetTickCount();
// getclock(TIMEOFDAY, &time1);
 do
 {
  ltime2 = GetTickCount();
  d_usec = (ltime2 - ltime1) * 1000L;
/*
  getclock(TIMEOFDAY, &time2);
  d_usec=(time2.tv_sec-time1.tv_sec)*1000000L+
         time2.tv_nsec/1000L-time1.tv_nsec/1000L;
*/
 }
 while (d_usec < (unsigned long)pause); 
}

void CheckTmkEvent(int fWaitEvent)
{
 TTmkEventData tmkEvD;
 DWORD dwEvent;
 int nSaveTmk;
 int nTmk;

// if (fWaitEvent == NO_WAIT_EVENT)
 {
//  while (1)
//  {
   if (fWaitEvent == NO_WAIT_EVENT)
     dwEvent = WaitForMultipleObjects(nWaitEvents, ahWaitEvents, FALSE, 0) - WAIT_OBJECT_0;
   else
     dwEvent = WaitForMultipleObjects(nWaitEvents, ahWaitEvents, FALSE, 100) - WAIT_OBJECT_0;
   if (dwEvent < (DWORD)nWaitEvents)
   {
    ResetEvent(ahWaitEvents[dwEvent]);
    nSaveTmk = tmkselected();
    nTmk = anWaitTmks[dwEvent];
    if (nSaveTmk != nTmk)
     tmkselect(nTmk);
//    printf("TMK%d", nTmk);
    while (1)
    {
     tmkgetevd(&tmkEvD);
     if (tmkEvD.nInt == 0)
      break;
//     printf("INT%d ", tmkEvD.nInt);
     int_num[nTmk] = tmkEvD.nInt;
     switch (tmkEvD.wMode)
     {
     case BC_MODE:
      bc_sw = tmkEvD.bc.wResult;
      if (tmkEvD.nInt == 1)
       ++good_starts;
      else
      {
       bc_aw1 = tmkEvD.bc.wAW1;
       bc_aw2 = tmkEvD.bc.wAW2;
       if (bad_starts < (unsigned long)BADLEN)
       {
        bad_sts[(unsigned)bad_starts] = bad_starts + good_starts + 1L;
        bad_sws[(unsigned)bad_starts] = bc_sw;
        bad_aws[(unsigned)bad_starts] = bc_aw1;
       }
       ++bad_starts;
      }
      break;
     case RT_MODE:
      if (tmkEvD.nInt == 1)
      {
       rt_cmd = tmkEvD.rt.wCmd;
       rt_sw = rtgetstate();
      }
      else if (tmkEvD.nInt == 2)
      {
       rt_sw = tmkEvD.rt.wStatus;
      }
      else
      {
       rt_sw = rtgetstate();
      }
      break;
     }
    }
    if (nSaveTmk != nTmk)
     tmkselect(nSaveTmk);
   }
//   break;
//  }
//  tmkselect(nSaveTmk);
 }
 CheckInput();
}
/*
int GetProxyTmkNum(pid_t msg)
{
 int i;

 for (i=0; i<nProxies; i++)
 {
  if (msg == aProxy[i])
   return aProxyTmkNum[i];
 }
 return -1;
}

int ProcessMsg(pid_t msg)
{
 int nSavTMK, nTMK;

 if ((nTMK = GetProxyTmkNum(msg)) != -1)
 { 
  nSavTMK = tmkselected();
  tmkselect(nTMK);
  tmkgetpxd(&TmkProxyData);
  switch(TmkProxyData.wMode)
  {
  case BC_MODE:
   switch(int_num[nTMK] = TmkProxyData.nInt)
   {
   case 1:
    bc_sw = TmkProxyData.bc.wResult;
    good_starts++;
    break;
   case 2:
    bc_sw = TmkProxyData.bc.wResult;
    bc_aw1 = TmkProxyData.bc.wAW1;
    bc_aw2 = TmkProxyData.bc.wAW2;
    if (bad_starts < (unsigned long)BADLEN)
    {
     bad_sts[(unsigned short)bad_starts] = bad_starts + good_starts + 1L;
     bad_sws[(unsigned short)bad_starts] = bc_sw;
     bad_aws[(unsigned short)bad_starts] = bc_aw1;
    }
    bad_starts++;
    break;
   }
   break;
  case RT_MODE:
   switch(int_num[nTMK] = TmkProxyData.nInt)
   {
   case 1:
    rt_cmd = TmkProxyData.rt.wCmd;
    rt_sw = rtgetstate();
    break;
   case 2:
   case 3:
    rt_sw = TmkProxyData.rt.wStatus;
    break;
   }
  }
  tmkselect(nSavTMK);
 }
 return nTMK;
}

void CheckTmkProxy(int fWaitProxy)
{
 pid_t proxy;
 int msg[1];

 if (fWaitProxy == WAIT_PROXY)
 {
  do
   if ((proxy = Receive(0, &msg, 0)) == -1)
    return; 
  while(ProcessMsg(proxy) == -1);
 }
 while ((proxy = Creceive(0, &msg, 0)) != -1)
  ProcessMsg(proxy);
}
*/

/*
void far BCIntNorm(unsigned short nResult, unsigned short nothing1, unsigned short nothing2)
{
 int_num[tmkselected()] = 1;
 bc_sw = nResult;
 good_starts++;
 bcrestore();
}

void far BCIntExc(unsigned short nResult, unsigned short AW1, unsigned short AW2)
{
 int_num[tmkselected()] = 2;
 bc_sw = nResult;
 bc_aw1 = AW1;
 bc_aw2 = AW2;
 if (bad_starts < (unsigned long)BADLEN)
 {
  bad_sts[(unsigned short)bad_starts] = bad_starts + good_starts + 1L;
  bad_sws[(unsigned short)bad_starts] = bc_sw;
  bad_aws[(unsigned short)bad_starts] = bc_aw1;
 }
 bad_starts++;
 bcrestore();
}

void far RTIntCmd(unsigned short nCmd)
{
 int_num[tmkselected()] = 1;
 rt_cmd = nCmd;
 rt_sw = rtgetstate();
 rtrestore();
}

void far RTIntErr(unsigned short nStatus)
{
 int_num[tmkselected()] = 2;
 rt_sw = nStatus;
 rtrestore();
}

void far RTIntData(unsigned short nStatus)
{
 int_num[tmkselected()] = 3;
 rt_sw = nStatus;
 rtrestore();
}
*/

void reset_mode()
{
 int mode = tmkgetmode();
 *Window[nwin].data_fname = '\0';
 if (mode == BC_MODE)
 {
  Window[nwin].nMode = BC_MODE;
  bus_num=bcgetbus();
  base=bcgetbase();
  buf_size = BC_BUF_SIZE;
 }
 else if (mode == RT_MODE)
 {
  Window[nwin].nMode = RT_MODE;
  if (hb_mode)
   rtdefmode((TMK_DATA)(rtgetmode()|RT_HBIT_MODE));
  else
   rtdefmode((TMK_DATA)(rtgetmode()&(~RT_HBIT_MODE)));
  rt_sw = rtgetstate();
  bram_page=cram_page=rtgetpage();
  subadr = rtgetsubaddr();
  dir = RT_TRANSMIT&subadr;
  subadr &= ~RT_TRANSMIT;
  Window[nwin].at_avail = (rtdefaddress(rtgetaddress())) ? 0 : 1;
//  rtenable(RT_ENABLE);
  buf_size = RT_BUF_SIZE;
 }
}

int set_mode(int mode)
{
// int result;

 *Window[nwin].data_fname = '\0';
/*
 if (tmkgetmode() != UNDEFINED_MODE)
  tmkundefmode();
 if (!(result=tmkdefmode(mode)))
 {
*/
 if (mode != tmkgetmode())
 {
  if (mode == BC_MODE)
  {
   bcreset();
   Window[nwin].nMode = BC_MODE;
   int_num[Window[nwin].nTMK] = 0;
   bcdefbus(bus_num=BUS_1);
   bcdefbase(base=0);
   buf_size = BC_BUF_SIZE;
  }
  else if (mode == RT_MODE)
  {
   rtreset();
   Window[nwin].nMode = RT_MODE;
   int_num[Window[nwin].nTMK] = 0;
   if (hb_mode)
    rtdefmode((TMK_DATA)(rtgetmode()|RT_HBIT_MODE));
   else
    rtdefmode((TMK_DATA)(rtgetmode()&(~RT_HBIT_MODE)));
   rt_sw = rtgetstate();
   rtdefpage(bram_page=cram_page=0);
   rtdefsubaddr(dir=RT_RECEIVE, subadr=1);
   Window[nwin].at_avail = (rtdefaddress(0)) ? 0 : 1;
//   rtenable(RT_ENABLE);
   buf_size = RT_BUF_SIZE;
   wr_at(10);
  }
 }
 else
  reset_mode();
// return result;
 return 0;
}

void main()
{
 int iTMK;

 hIn = GetStdHandle(STD_INPUT_HANDLE);
 hOut = GetStdHandle(STD_OUTPUT_HANDLE);
// textmode(C80);        /* параметры экрана */
 textcolor(LIGHTGRAY);
 textbackground(BLACK);
 clrscr();
/* _wscroll = 0;*/

/* oldvect3=getvect(0x05);      /* сохранить старое значение вектора */
/* setvect(0x05, prtscr_brk);     /* установить новые значения вектора */

 setbuf(stdout, 0);
 biostime1 = GetTickCount();
// getclock(TIMEOFDAY, &biostime1);

 if (TmkOpen())
 {
#ifdef ENG
  printf("Driver open error\n");
#else
  printf("Ошибка при открытии драйвера\n");
#endif
  exit(0);
 }
 if (TmkInit("tmk.cfg"))
 {
#ifdef ENG
  printf("Configuration load error from the file TMK.CFG\n");
#else
  printf("Ошибка загрузки конфигурации из файла TMK.CFG\n");
#endif
  tmkdone(ALL_TMKS);
  TmkClose();
  exit(0);
 }
#ifdef STEND
 init_lpt();
#endif
 nwin = 0;
// nProxies = 0;
 fInitBad = 0;
 sa4Event.nLength = sizeof(sa4Event);
 sa4Event.lpSecurityDescriptor = NULL;
 sa4Event.bInheritHandle = TRUE;
 nMaxTMK = tmkgetmaxn();
 for (iTMK = 0; iTMK <= nMaxTMK; iTMK++)
 {
  int_num[iTMK] = 0;
  if (tmkselect(iTMK))
   continue;
  tmkgetinfo(&(aTmkConfig[iTMK]));

  if (!(hEvent[iTMK] = CreateEvent(&sa4Event, TRUE, FALSE, NULL)))
  {
   printf("CreateEvent failed!\n");
   fInitBad = 1;
  }
  else
  {
   tmkdefevent(hEvent[iTMK], TRUE);
   ahWaitEvents[nWaitEvents] = hEvent[iTMK];
   anWaitTmks[nWaitEvents++] = iTMK;
  }
  ahWaitEvents[nWaitEvents] = hIn;
/*
  if (aTmkLock[iTMK] = tmk_lock())
  {
   fInitBad = 1;
   printf("TMK%d: Can't tmk_lock\n", iTMK);
  }
  if (aRtArbLock[iTMK] = rtarb_lock())
  {
   fInitBad = 1;
   printf("TMK%d: Can't rtarb_lock\n", iTMK);
  }
  if (aRtAnswLock[iTMK] = rtansw_lock())
  {
   fInitBad = 1;
   printf("TMK%d: Can't rtansw_lock\n", iTMK);
  }
*/
/*
  aTmkProxy[iTMK] = qnx_proxy_attach(0, 0, 0, -1);
  if (aTmkProxy[iTMK] == -1)
  {
   fInitBad = 1;
   printf("TMK%d: Can't attach proxy\n", iTMK);
  }
  else
  {
   tmkdefproxy(aTmkProxy[iTMK]);
   aProxy[nProxies] = aTmkProxy[iTMK];
   aProxyTmkNum[nProxies] = iTMK;
   ++nProxies;
  }
*/
/*
   bcdefintnorm(BCIntNorm);
   bcdefintexc(BCIntExc);
   rtdefintcmd(RTIntCmd);
   rtdefinterr(RTIntErr);
   rtdefintdata(RTIntData);
*/
 }
 if (fInitBad)
  make_quit();
 for (iTMK = 0; iTMK <= nMaxTMK; iTMK++)
 {
  if (tmkselect(iTMK))
   continue;
  if (nwin > nMaxWin)
   continue;
  if (nwin == 0)
   set_mode(BC_MODE);
  else
   set_mode(RT_MODE);
  Window[nwin].fVisible = 1;
  Window[nwin].nTMK = iTMK;
  Window[nwin].nType = -1;
  ++nwin;
 }
 select_window(nmainwin);
 all_screen();
 while (1)
 {                   /* ввод и выполнение команд */
  window(1, 1, 80, 25);
  in_cmd(cmd_str);
  window(Window[nwin].nX + 1, Window[nwin].nY, 
          Window[nwin].nX + Window[nwin].nDX - 2, 
          Window[nwin].nY + Window[nwin].nDY - 1);
  make_cmd(cmd_str);
 }
}

void block_data_irq(char *str)    /* блокировка прерывания данных */
{
 if (end_ctrl(str)) return;
 rtdefirqmode((TMK_DATA)(rtgetirqmode()|RT_DATA_BL));
//  out_mode();
}

void unblock_data_irq(char *str)    /* разблокировка прерывания данных */
{
 if (end_ctrl(str)) return;
 rtdefirqmode((TMK_DATA)(rtgetirqmode()&(~RT_DATA_BL)));
//  out_mode();
}

void set_hbit_mode(char *str)    /* команда управления режимом
                                    аппаратного бита */
  {
  int res;

  while (*str=='\t' || *str==' ') str++;
  switch (*str)
  {
  case '0': res = rtdefmode((TMK_DATA)(rtgetmode()&(~RT_HBIT_MODE)));
            hb_mode = 0;
            break;
  case '1': res = rtdefmode((TMK_DATA)(rtgetmode()|RT_HBIT_MODE));
            hb_mode = 1;
            break;
  }
  out_rt_mode();
  }

void set_flag_mode(char *str)    /* команда управления режимом флагов */
  {
  int res;

  while (*str=='\t' || *str==' ') str++;
  switch (*str)
  {
  case '0': res = rtdefmode((TMK_DATA)(rtgetmode()&(~RT_FLAG_MODE)));
            break;
  case '1': res = rtdefmode((TMK_DATA)(rtgetmode()|RT_FLAG_MODE));
            break;
  }
  out_rt_mode();
//  out_mode();
  }

void set_brcst_mode(char *str)    /* команда управления режимом
                                     групповых команд */
  {
  int res;

  while (*str=='\t' || *str==' ') str++;
  switch (*str)
  {
  case '0': res = rtdefmode((TMK_DATA)(rtgetmode()&(~RT_BRCST_MODE)));
            break;
  case '1': res = rtdefmode((TMK_DATA)(rtgetmode()|RT_BRCST_MODE));
            break;
  }
  out_rt_mode();
//  out_mode();
  }


void make_cmd(char *str)
/* обработка командной строки, переход к выполнению команд */
{
 strcpy(old_cmd, cmd_str);
 while (*str == ' ' || *str == '\t') str++;
 if (!strcmp(str, "Q"))
  make_quit();
 else if (!strncmp(str, "IOD ", 4))
  set_io_delay(str+4);
 else if (!strcmp(str, "I"))
  cmd_reset(str+1);
 else if (!strcmp(str, "F"))
  fields_chg(str+1);
 else if (!strcmp(str, "BE"))
  buf_edit(str+2);
 else if (!strncmp(str, "BE ", 3))
  buf_edit(str+3);
 else if (!strcmp(str, "BC"))
  buf_clear(str+2);
 else if (!strncmp(str, "BF ", 3))
  buf_fill(str+3);
 else if (!strncmp(str, "SL ", 3))
  set_stat_len(str+3);
 else if (!strncmp(str, "WIN ", 4))
  select_win(str+4);
 else if (!strncmp(str, "TMK ", 4))
  select_tmk(str+4);
 else if (!strcmp(str, "MBC"))
  mode_bc(str+3);
 else if (!strcmp(str, "MRT"))
  mode_rt(str+3);
// else if (!strncmp(str, "MMT", 3))
//  mode_mt(str+3);
 else if (!strncmp(str, "AVT ", 4))
  avt_ctrl(str+4);
 else if (!strncmp(str, "ATBC", 4))
 {
  fReserv=0;
  avt_bc(str+4);
 }
 else if (!strncmp(str, "RATBC", 5))
 {
  fReserv=1;
  avt_bc(str+5);
 }
 else if (!strncmp(str, "ATRT", 4))
 {
  fReserv=0;
  avt_rt(str+4);
 }
 else if (!strncmp(str, "RATRT", 5))
 {
  fReserv=1;
  avt_rt(str+5);
 }
 else if (!strncmp(str, "BA", 2))
  avt_va996(str+2);
 else if (!strncmp(str, "ATFL", 4))
  avt_flags(str+4);
 else if (!strncmp(str, "STOP?", 4))
 {
  if (enter_mode && bad_starts>0L)
   fSkipCmds=1;
 }
 else if (!strncmp(str, ";", 1))
  comment(str+1);
 else if (!strncmp(str, "#", 1))
  ;
 else
 if (Window[nwin].nMode == BC_MODE)
 {
  if (!strncmp(str, "SB ", 3))
   set_base(str+3);
  else if (!strncmp(str, "SN ", 3))
   set_number(str+3);
  else if (!strncmp(str, "SP ", 3))
   set_pause(str+3);
  else if (!strncmp(str, "SC ", 3))
   set_ctrl_code(str+3);
  else if (!strncmp(str, "P", 1))
   kbd_pause(str+1);
  else if (!strncmp(str, "GL", 2))
   start_loop(str+2);
  else if (!strncmp(str, "G", 1))
   start_1(str+1);
  else if (!strncmp(str, "STO", 3))
   statistic_out(str+3);
  else if (!strncmp(str, "STBO", 4))
   statistic_bad_out(str+4);
  else if (!strncmp(str, "STC", 3))
   statistic_clear(str+3);
  else if (!strncmp(str, "A+", 2))
   fAAAA=1;
  else if (!strncmp(str, "A-", 2))
   fAAAA=0;
  else if (!strncmp(str, "R ", 2))
   bc_buf_rd(str+2);
  else if (!strncmp(str, "W ", 2))
   bc_buf_wr(str+2);
  else if (!strncmp(str, "R<", 2) && cmd_count == 1)
   cmds_open(str+3);
  else if (!strncmp(str, "R<", 2) && cmd_count != 1)
   cmds_open2(str+3);
  else if (!strncmp(str, "C ", 2))
   set_count(str+2);
  else if (!strncmp(str, "T", 1))
   bc_ram_test(str+1);
  else if (!strncmp(str, "H", 1))
   bc_help(str+1);
  else if (!strncmp(str, "SYM", 3))
   sym(str+3);
  else if (*str != '\0')
   msg_out(undef_cmd);
 }
 else if (Window[nwin].nMode == RT_MODE)
 {
  if (!strncmp(str, "SW ", 3))
   set_status_word(str+3);
  else if (!strncmp(str, "HBIT ", 5))
    set_hbit_mode(str+5);
  else if (!strncmp(str, "FLAG ", 5))
    set_flag_mode(str+5);
  else if (!strncmp(str, "BCST ", 5))
    set_brcst_mode(str+5);
  else if (!strncmp(str, "SB1", 3))
    block_data_irq(str+3);
  else if (!strncmp(str, "CB1", 3))
    unblock_data_irq(str+3);
  else if (!strcmp(str, "DTBL 1"))
  {
    block_data_irq("");
    out_rt_mode();
  }
  else if (!strcmp(str, "DTBL 0"))
  {
    unblock_data_irq("");
    out_rt_mode();
  }
  else if (!strncmp(str, "SFL", 3))
   set_flag(str+3);
  else if (!strncmp(str, "WRC", 3))
   wr_mr_loop(str+3);
  else if (!strncmp(str, "RDC", 4))
   rd_sw_loop(str+4);
  else if (!strncmp(str, "SSR", 3))
   set_sw_bits(str+3, SREQ);
  else if (!strncmp(str, "SBS", 3))
   set_sw_bits(str+3, BUSY);
  else if (!strncmp(str, "SSF", 3))
   set_sw_bits(str+3, SSFL);
  else if (!strncmp(str, "STF", 3))
   set_sw_bits(str+3, RTFL);
  else if (!strncmp(str, "SDN", 3))
   set_sw_bits(str+3, DNBA);
  else if (!strncmp(str, "CSR", 3))
   clear_sw_bits(str+3, SREQ);
  else if (!strncmp(str, "CBS", 3))
   clear_sw_bits(str+3, BUSY);
  else if (!strncmp(str, "CSF", 3))
   clear_sw_bits(str+3, SSFL);
  else if (!strncmp(str, "CTF", 3))
   clear_sw_bits(str+3, RTFL);
  else if (!strncmp(str, "CDN", 3))
   clear_sw_bits(str+3, DNBA);
  else if (!strncmp(str, "SMR", 3))
  {
   rtlock(dir, subadr);
   fLock=1;
  }
  else if (!strncmp(str, "CMR", 3))
  {
   rtdefsubaddr(dir, subadr);
//   rtunlock(dir, subadr);
   fLock=0;
  }
  else if (!strncmp(str, "SR ", 3))
   set_subadr_r(str+3);
  else if (!strncmp(str, "ST ", 3))
   set_subadr_t(str+3);
  else if (!strncmp(str, "SPG ", 4))
   set_spage(str+4);
  else if (!strncmp(str, "CPG ", 4))
   set_cpage(str+4);
  else if (!strncmp(str, "PG ", 3))
   set_page(str+3);
  else if (!strncmp(str, "P", 1))
   kbd_pause(str+1);
  else if (!strncmp(str, "SAT ", 4))
   set_at(str+4);
  else if (!strncmp(str, "RSW", 3))
   read_sw(str+3);
  else if (!strncmp(str, "R ", 2))
   rt_buf_rd(str+2);
  else if (!strncmp(str, "W ", 2))
   rt_buf_wr(str+2);
  else if (!strncmp(str, "R<", 2))
   cmds_open(str+3);
  else if (!strncmp(str, "T", 1))
   rt_ram_test(str+1);
  else if (!strncmp(str, "H", 1))
   rt_help(str+1);
  else if (*str != '\0')
   msg_out(undef_cmd);
 }
}

void make_quit()                    /* поддержка выхода из отладчика */
{
 int iTMK;
/* setvect(0x05, oldvect3);*/    /* восстановить вектор */
 for (iTMK = 0; iTMK <= nMaxTMK; ++iTMK)
 {
  if (tmkselect(iTMK))
   continue;
  if (hEvent[iTMK])
   CloseHandle(hEvent[iTMK]);
/*
  tmkundefmode();
  if (!aTmkLock[iTMK])
   tmk_unlock();
  if (!aRtArbLock[iTMK])
   rtarb_unlock();
  if (!aRtAnswLock[iTMK])
   rtansw_unlock();
  if (aTmkProxy[iTMK] != -1)
   qnx_proxy_detach(aTmkProxy[iTMK]);
*/
 }
 tmkdone(ALL_TMKS);
 TmkClose();
 window(1, 1, 80, 25);
 if (!fInitBad)
  clrscr();
#ifdef ENG
 printf("Program has finished.");
#else
 printf("Работа программы закончена.");
#endif
 exit(0);
}

void set_io_delay(char *str)
{
 unsigned short nDelay;

 while (*str == '\t' || *str == ' ') str++;
 if (*str == '\0' || sscanf(str, "%d", &nDelay) != 1)
 {
  msg_out(inp_err);
  return;
 }
// tmkiodelay(nDelay);
 out_type();
}

void select_win(char *str)
{
 int nwin;

 while (*str == '\t' || *str == ' ') str++;
 if (*str == '\0' || sscanf(str, "%d", &nwin) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (nwin > 1)
 {
#ifdef ENG
  msg_out("Window number range is from 0 to 1");
#else
  msg_out("Допустимый диапазон номеров окон от 0 до 1");
#endif
  return;
 }
 nmainwin = nwin;
// int_num[Window[0].nTMK] = 0;
// int_num[Window[1].nTMK] = 0;
 select_window(nmainwin);
 all_screen();
}

void mode_bc(char *str)
{
 if (end_ctrl(str)) return;
 int_num[Window[nwin].nTMK] = 0;
 if (set_mode(BC_MODE))
 {
  msg_out("Can't set BC_MODE");
  return;
 }
 base = 0;
 bcdefbase(0);
 all_screen();
}

void mode_rt(char *str)
{
 if (end_ctrl(str)) return;
 if (set_mode(RT_MODE))
 {
  msg_out("Can't set RT_MODE");
  return;
 }
 cram_page = bram_page = 0;
 rtdefpage(0);
 dir = RT_RECEIVE;
 subadr = 1;
 rtdefsubaddr(dir, subadr);
 all_screen();
}

void select_tmk(char *str)
{
 int ntmk;

 while (*str == '\t' || *str == ' ') str++;
 if (*str == '\0' || sscanf(str, "%U", &ntmk) != 1)
 {
  msg_out(inp_err);
  return;
 }
 if (ntmk > MAX_TMK_NUMBER)
 {
#ifdef ENG
  msg_out("Device number range is from 0 to 3");
#else
  msg_out("Допустимый диапазон номеров устройств от 0 до MAX");
#endif
  return;
 }
 if (tmkselect(ntmk))
 {
#ifdef ENG
  msg_out("Device with specified number has not defined in configuration file");
#else
  msg_out("Устройство с таким номером не задано в файле конфигурации");
#endif
  return;
 }
 if (ntmk == Window[!nmainwin].nTMK)
 {
//  set_mode(Window[!nmainwin].nMode);
#ifdef ENG
  msg_out("Can not define same board in both windows");
#else
  msg_out("Нельзя задать одну и ту же плату для обоих окон");
#endif
  return;
 }
 nwin = nmainwin;
 switch (tmkgetmode())
 {
 case BC_MODE:
 case RT_MODE:
  reset_mode();
  break;
 case UNDEFINED_MODE:
  set_mode(BC_MODE);
  break;
 }
 Window[nmainwin].nTMK = ntmk;
 Window[nmainwin].nType = -1;
 select_window(nmainwin);
 all_screen();
}

void set_stat_len(char *str)
{
 unsigned long cnt;

 while (*str == '\t' || *str == ' ') str++;
 if (*str != '\0')
 {
  if (sscanf(str, "%U", &cnt) != 1)
  {
   msg_out(inp_err);
   return;
  }
  GL_COUNTER = cnt;
  GL_COUNTER2 = cnt * 2;
  GL_COUNTER3 = cnt * 4;
 }
}

void sym(char *str)                                      /* симметрирование */
{
 int cur_base, cur_ctrl_code;

 if (end_ctrl(str)) return;
 cur_base=base;
 cur_ctrl_code=ctrl_code;
 ctrl_code = DATA_BC_RT_BRCST; /* уст. кода управления */
                               /* занесение констант в базы */
 set_base("0"); buf_fill("1, 32, AAAA");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 set_base("1"); buf_fill("1, 32, 0000");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 set_base("2"); buf_fill("1, 32, 5555");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 set_base("3"); buf_fill("1, 32, FFFF");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 set_base("4"); buf_fill("1, 32, 8000");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 set_base("5"); buf_fill("1, 32, 7FFF");
 bcputw(0, (0x1F<<11) | RT_RECEIVE | (0x11<<5));
 gotoxy(1, Window[nwin].nDY);
 textcolor(CYAN);
#ifdef ENG
 printf("Symmetry test"/*. Press PrtScr to abort*/"...");
#else
 printf("Поддержка симметрирования"/*. Нажмите PrtScr для выхода*/"...");
#endif
 textcolor(LIGHTGRAY);
 while (!prtscr_flag)
 {
  base=0; start();
  base=1; start();
  base=2; start();
  base=3; start();
  base=4; start();
  base=5; start();
 }
 prtscr_flag = 0;
 textcolor(WHITE);
 gotoxy(1, Window[nwin].nDY);
 hor_line(Window[nwin].nDX-2);
 textcolor(LIGHTGRAY);
 ctrl_code=cur_ctrl_code;
 base=cur_base;
 out_ctrl_code();
 out_base();
 bc_out_ram(base);
}

void bc_clear_ram()
{
 int k, maxbase;

 maxbase = bcgetmaxbase();
 for (k = 0; k <= 63; k++)
  buffer[k] = 0;
 for (base = 0; base <= maxbase; base++)
 {
  bcdefbase(base);
  bcputblk(0, buffer, 64);
 }
 base = 0;
 bcdefbase(0);
 out_base();
 out_buffer();
}

void rt_clear_ram()
{
 int k, maxpage;
 TMK_DATA page;

 maxpage = rtgetmaxpage();
 for (k = 0; k <= 31; k++)
  buffer[k] = 0;
 for (page = 0; page <= maxpage; page++)
 {
  rtdefpage(page);
  for (subadr = 0; subadr <= 31; subadr++)
  {
   rtdefsubaddr(RT_RECEIVE, subadr);
   rtputblk(0, buffer, 32);
   rtdefsubaddr(RT_TRANSMIT, subadr);
   rtputblk(0, buffer, 32);
  }
 }
 cram_page = bram_page = 0;
 rtdefpage(0);
 dir = RT_RECEIVE;
 subadr = 1;
 rtdefsubaddr(dir, subadr);
 out_page();
 out_subadr();
 out_buffer();
}

int bc_ram_test(char *str)                         /* тестирование БЗУ */
{
 int k, error, bases;

 if (end_ctrl(str)) return 0;
 bases = bcgetmaxbase() + 1;
 clear_dump();
 gotoxy(1, BDUMP_Y-3);
 hor_line(78);
 gotoxy(1, BDUMP_Y-2);
 clreol();
 printf("      0               1               2               3");
 gotoxy(1, BDUMP_Y-1);
#ifdef ENG
 printf("Base: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
#else
 printf("База: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
#endif
 gotoxy(1, BDUMP_Y);
 printf("  00:");
 gotoxy(1, BDUMP_Y+1);
 printf("  40:");
 gotoxy(1, BDUMP_Y+2);
 printf("  80:");
 gotoxy(1, BDUMP_Y+3);
 printf("  C0:");
 gotoxy(1, BDUMP_Y+4);
#ifdef ENG
 printf("      Memory map: \xB0, \xB1 - test passed, ");
 textcolor(RED); putch('B');
 textcolor(LIGHTGRAY); printf(" - test failed.");
#else
 printf("      Карта памяти: \xB0, \xB1 - тест прошел, ");
 textcolor(RED); putch('B');
 textcolor(LIGHTGRAY); printf(" - сбойный участок.");
#endif
 
 srand(1);
 for (base = 0; base < bases; base++)
 {
  for (k = 0; k <= 63; k++)
   buffer[k] = rand() + rand();
  bcdefbase(base);
  bcputblk(0, buffer, 64);
  if (base % 64 == 0)
   gotoxy(7, base / 64 + BDUMP_Y);
  putchar('.');
 }
 
 srand(1);
 for (base = 0; base < bases; base++)
 {
  bcdefbase(base);
  bcgetblk(0, buffer, 64);
  error = 0;
  for (k = 0; k <= 63; k++)
  {
   if (buffer[k] != (unsigned short)(rand() + rand()))
   {
    error = 1;
    break;
   }
  }
  if (base % 64 == 0)
   gotoxy(7, base / 64 + BDUMP_Y);
  if (error)
  {
   textcolor(RED); putchar('B'); textcolor(LIGHTGRAY);
  }
  else
   putchar('\xB0');
 }
#ifdef ENG
  msg_out("Normal RAM test completed");
#else
  msg_out("Прямой тест БЗУ завершен");
#endif
 for (base = 0; base < bases; base++)
 {
  bcdefbase(base);
  bcgetblk(0, buffer, 64);
  for (k = 0; k <= 63; k++)
   buffer[k] = ~buffer[k];
  bcputblk(0, buffer, 64);
  if (base % 64 == 0)
   gotoxy(7, base / 64 + BDUMP_Y);
  putchar('.');
 }
 srand(1);
 for (base = 0; base < bases; base++)
 {
  bcdefbase(base);
  bcgetblk(0, buffer, 64);
  error = 0;
  for (k = 0; k <= 63; k++)
  {
   if (buffer[k] != (unsigned short)~(rand() + rand()))
   {
    error = 1;
    break;
   }
  }
  if (base % 64 == 0)
   gotoxy(7, base / 64 + BDUMP_Y);
  if (error)
  {
   textcolor(RED); putchar('B'); textcolor(LIGHTGRAY);
  }
  else
   putchar('\xB1');
 }
#ifdef ENG
  msg_out("Inverse RAM test completed");
#else
  msg_out("Инверсный тест БЗУ завершен");
#endif
 gotoxy(1, BDUMP_Y-3);
 clreol();
 gotoxy(1, BDUMP_Y-2);
 clreol();
 clear_dump();
// bc_clear_ram();
 base = 0;
 out_base();
 bc_out_ram(base);
 out_ctrl_code();
 bc_out_sw();
 out_inn();
}

int rt_ram_test(char *str)                         /* тестирование БЗУ */
{
 int k, error;
 TMK_DATA page, pages;

 if (end_ctrl(str)) return 0;
 pages = rtgetmaxpage() + 1;
 clear_dump();
 gotoxy(1, BDUMP_Y-3);
 hor_line(78);
 gotoxy(1, BDUMP_Y-2);
 clreol();
#ifdef ENG
 printf("          0    RECEIVE    1    RECEIVE    0    TRANSMIT   1    TRANSMIT");
 gotoxy(1, BDUMP_Y-1);
 printf("Subaddr.: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
 gotoxy(1, BDUMP_Y);
 printf("  Page 0:");
 gotoxy(1, BDUMP_Y+1);
 printf("  Page 1:");
 gotoxy(1, BDUMP_Y+2);
 printf("  Page 2:");
 gotoxy(1, BDUMP_Y+3);
 printf("  Page 3:");
 gotoxy(1, BDUMP_Y+4);
 printf("          Memory map: \xB0, \xB1 - test passed, ");
 textcolor(RED); putch('B');
 textcolor(LIGHTGRAY); printf(" - test failed.");
#else
 printf("          0     ПРИЕМ     1     ПРИЕМ     0    ПЕРЕДАЧА   1    ПЕРЕДАЧА");
 gotoxy(1, BDUMP_Y-1);
 printf("Подадрес: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
 gotoxy(1, BDUMP_Y);
 printf("  Стр. 0:");
 gotoxy(1, BDUMP_Y+1);
 printf("  Стр. 1:");
 gotoxy(1, BDUMP_Y+2);
 printf("  Стр. 2:");
 gotoxy(1, BDUMP_Y+3);
 printf("  Стр. 3:");
 gotoxy(1, BDUMP_Y+4);
 printf("          Карта памяти: \xB0, \xB1 - тест прошел, ");
 textcolor(RED); putch('B');
 textcolor(LIGHTGRAY); printf(" - сбойный участок.");
#endif
 
 srand(1);
 for (page = 0; page < pages; page++)
 {
  rtdefpage(page);
  gotoxy(11, page + BDUMP_Y);
  for (dir = RT_RECEIVE; ; dir = RT_TRANSMIT)
  {
   for (subadr = 0; subadr <= 31; subadr++)
   {
    for (k = 0; k <= 31; k++)
     buffer[k] = rand() + rand();
    rtdefsubaddr(dir, subadr);
    rtputblk(0, buffer, 32);
    putchar('.');
   }
   if (dir == RT_TRANSMIT)
    break;
  }
 }
 srand(1);
 for (page = 0; page < pages; page++)
 {
  rtdefpage(page);
  gotoxy(11, page + BDUMP_Y);
  for (dir = RT_RECEIVE; ; dir = RT_TRANSMIT)
  {
   for (subadr = 0; subadr <= 31; subadr++)
   {
    rtdefsubaddr(dir, subadr);
    rtgetblk(0, buffer, 32);
    error = 0;
    for (k = 0; k <= 31; k++)
    {
     if (buffer[k] != (unsigned short)(rand() + rand()))
     {
      error = 1;
      break;
     }
    }
    if (error)
    {
     textcolor(RED); putchar('B'); textcolor(LIGHTGRAY);
    }
    else
     putchar('\xB0');
   }
   if (dir == RT_TRANSMIT)
    break;
  }
 }
#ifdef ENG
  msg_out("Normal RAM test completed");
#else
  msg_out("Прямой тест БЗУ завершен");
#endif
 for (page = 0; page < pages; page++)
 {
  rtdefpage(page);
  gotoxy(11, page + BDUMP_Y);
  for (dir = RT_RECEIVE; ; dir = RT_TRANSMIT)
  {
   for (subadr = 0; subadr <= 31; subadr++)
   {
    rtdefsubaddr(dir, subadr);
    rtgetblk(0, buffer, 32);
    for (k = 0; k <= 31; k++)
     buffer[k] = ~buffer[k];
    rtputblk(0, buffer, 32);
    putchar('.');
   }
   if (dir == RT_TRANSMIT)
    break;
  }
 }
 srand(1);
 for (page = 0; page < pages; page++)
 {
  rtdefpage(page);
  gotoxy(11, page + BDUMP_Y);
  for (dir = RT_RECEIVE; ; dir = RT_TRANSMIT)
  {
   for (subadr = 0; subadr <= 31; subadr++)
   {
    rtdefsubaddr(dir, subadr);
    rtgetblk(0, buffer, 32);
    error = 0;
    for (k = 0; k <= 31; k++)
    {
     if (buffer[k] != (unsigned short)~(rand() + rand()))
     {
      error = 1;
      break;
     }
    }
    if (error)
    {
     textcolor(RED); putchar('B'); textcolor(LIGHTGRAY);
    }
    else
     putchar('\xB1');
   }
   if (dir == RT_TRANSMIT)
    break;
  }
 }
#ifdef ENG
  msg_out("Inverse RAM test completed");
#else
  msg_out("Инверсный тест БЗУ завершен");
#endif
 gotoxy(1, BDUMP_Y-3);
 clreol();
 gotoxy(1, BDUMP_Y-2);
 clreol();
 clear_dump();
// rt_clear_ram();
 dir = RT_RECEIVE;
 subadr = 0x10;
 out_subadr();
 rt_out_ram(dir, subadr);
 out_status_word();
 rt_out_sw();
 out_inn();
}

void comment(char *str)                          /* вывод коментария */
{
 gotoxy(1, 10);
 clreol();
 printf(str);
 
}

void kbd_pause(char *str)                        /* программируемая пауза */
{
 unsigned long p;

 while (*str == '\t' || *str == ' ') str++;
 if (*str != '\0')
 {                                  /* пауза программируемой длительности */
  if (sscanf(str, "%U", &p) != 1)
  {
   msg_out(inp_err);
   return;
  }
  for (; p-- ;);
  return;
 }
 gotoxy(1, 10);                          /* ожидание нажатия клавиши */
 textcolor(CYAN);
#ifdef ENG
 printf("Pause. ESC - return to command mode, other - continue execution.");
#else
 printf("Пауза. ESC - возврат в командный режим, другая - продолжить выполнение.");
#endif
 textcolor(LIGHTGRAY);
 while (kbhit() == 0)
  WaitForMultipleObjects(nWaitEvents+1, ahWaitEvents, FALSE, 0);
 gotoxy(1, 10);
 clreol();
 if ((bioskey()&0x00FF) == ESCAPE)
  if (enter_mode)
  {
   fclose(cmd_file);
   enter_mode=0;
  }
}

void statistic_bad_out(char *str)                        /* вывод статистики канала */
{
 int savenDY;
 unsigned short i;

 if (end_ctrl(str)) return;
 window(1, 1, 80, 23);
 clrscr();
#ifdef ENG
 printf(" N start  │ State W.│   Status Word    ║ N start  │ State W.│   Status Word\015\012");
#else
 printf(" N старта │ Сл.сост.│    Отв.слово     ║ N старта │ Сл.сост.│    Отв.слово\015\012");
#endif
 for (i = 0; (unsigned long)i < bad_starts && i < 42; i++)
 {
  printf("%9u │ ", bad_sts[i]);
  out_bin(bad_sws[i], 7);
  printf(" │ ");
  out_bin(bad_aws[i], 16);
  if (i & 1)
   printf(" \015\012");
  else
   printf(" ║");
 }
 savenDY = Window[nwin].nDY;
 Window[nwin].nDY = 23;
 
#ifdef ENG
 msg_out("End of exceptions statistics");
#else
 msg_out("Конец статистики сбоев");
#endif
 Window[nwin].nDY = savenDY;
 all_screen();
}

void statistic_out(char *str)                    /* вывод статистики канала */
{
 if (end_ctrl(str)) return;
 gotoxy(1, 10); clreol();
#ifdef ENG
 printf("    Starts - %lu, interrupts_2 - %lu, ", good_starts+bad_starts+to_errors, bad_starts);
 printf("errors - %lu, TO_errors - %lu.", channel_err, to_errors);
 if (avtomat) return;
 msg_out("Bus channel statistics");
#else
 printf("    Cтартов - %lu, прерываний_2 - %lu, ", good_starts+bad_starts+to_errors, bad_starts);
 printf("ошибок - %lu, TO_ошибок - %lu.", channel_err, to_errors);
 if (avtomat) return;
 msg_out("Статистика канала");
#endif
}

void statistic_clear(char *str)          /* очистка переменных статистики */
{
 if (end_ctrl(str)) return;
 to_errors=channel_err=good_starts=bad_starts=0;
 gotoxy(1, 10); clreol();
}

void fields_chg(char *str)                    /* управление выделением полей */
{
 if (end_ctrl(str)) return;
 fields = !fields;
 all_screen();
}

void bc_help(char *str)                                  /* вывод подсказки */
{
 int savenDY;

 if (end_ctrl(str)) return;
 window(1, 1, 80, 23);
 clrscr();
#ifdef ENG
 printf("               Main commands in BC mode :\015\012");
 printf("TMK number_D - select device in current window\015\012");
 printf("ERR num_D, SL num_D, ATBC, ATRT, ATS - automatic test commands\015\012");
 printf("SC code_B   - set control code\015\012");
 printf("SB base_H   - set base\015\012");
 printf("SN number_D - set bus\015\012");
 printf("BE [adr_D, data_H] - edit buffer\015\012");
 printf("BC - clear buffer\015\012");
 printf("BF start_D, end_D, data_H - fill buffer\015\012");
 printf("I - reset Bus Controller\015\012");
 printf("G - single start\015\012");
 printf("GL - loop start\015\012");
 printf("SP pause_D - set pause between starts in a loop\015\012");
 printf("STO/STBO/STC - output/clear statistics\015\012");
 printf("T - test all RAM bases\015\012");
 printf("R filename - read buffer from file        W filename - write buffer to file\015\012");
 printf("R< filename - execute command file\015\012");
 printf("P [pause_D] - programmable pause\015\012");
 printf("C count_D - set command file counter\015\012");
 printf(";... - comment\015\012");
 printf("Q  - exit from program                    H  - help\015\012");
 savenDY = Window[nwin].nDY;
 Window[nwin].nDY = 23;
 msg_out("Help end");
#else
 printf("               Основные команды в режиме КК :\015\012");
 printf("TMK number_D - выбор устройства в текущем окне\015\012");
 printf("ERR num_D, SL num_D, ATBC, ATRT, ATS - команды автоматического тестирования\015\012");
 printf("SC code_B   - задание кода управления\015\012");
 printf("SB base_H   - задание базы\015\012");
 printf("SN number_D - задание номера канала\015\012");
 printf("BE [adr_D, data_H] - редактирование буфера\015\012");
 printf("BC - очистка буфера\015\012");
 printf("BF start_D, end_D, data_H - заполнение буфера константой\015\012");
 printf("I - сброс (инициализация) контроллера канала\015\012");
 printf("G - старт обмена\015\012");
 printf("GL - старт обмена в цикле\015\012");
 printf("SP pause_D - задание паузы между стартами в цикле\015\012");
 printf("STO/STBO/STC - вывод/очистка статистики обмена\015\012");
 printf("T - тест всех баз БЗУ\015\012");
 printf("R filename - чтение в буфер из файла        W filename - запись буфера в файл\015\012");
 printf("R< filename - ввод команд из файла\015\012");
 printf("P [pause_D] - пауза программируемой длительности\015\012");
 printf("C count_D - установка числа повторов командного файла\015\012");
 printf(";... - коментарий\015\012");
 printf("Q  - выход из программы                     H  - помощь\015\012");
 savenDY = Window[nwin].nDY;
 Window[nwin].nDY = 23;
 msg_out("Конец подсказки");
#endif
 Window[nwin].nDY = savenDY;
 all_screen();
}

void rt_help(char *str)                                  /* вывод подсказки */
{
 int savenDY;

 if (end_ctrl(str)) return;
 window(1, 1, 80, 23);
 clrscr();
#ifdef ENG
 printf("                  Main commands in RT mode :\015\012");
 printf("TMK number_D - select device in current window\015\012");
 printf("SAT adr_D - set RT address\015\012");
 printf("FLAG 0/1, HBIT 0/1, BCST 0/1, DTBL 0/1 - set modes\015\012");
 printf("SW code_B - set status word\015\012");
 printf("Sbit_name/Cbit_name - set/clear status word bit, \015\012");
 printf("                      bit_name - BS, SR, TF, SF, DN\015\012");
 printf("PG/SPG/CPG page_D - set page/PC page/bus page\015\012");
 printf("SMR/CMR - lock/unlock current subaddress\015\012");
 printf("SR/ST subadr_H - set subaddress Rx/Tx\015\012");
 printf("BE [adr_D, data_H] - edit buffer\015\012");
 printf("BF start_D, end_D, data_H - fill buffer\015\012");
 printf("BC - clear buffer\015\012");
 printf("I - reset Remote Terminal\015\012");
 printf("RSW - read state word\015\012");
 printf("SFL - flag writing loop\015\012");
 printf("R filename - read buffer from file        W filename - write buffer to file\015\012");
 printf("R< filename - execute command file\015\012");
 printf("P [pause_D] - programmable pause\015\012");
 printf(";... - comment\015\012");
 printf("Q  - exit from program                    H  - help\015\012");
 savenDY = Window[nwin].nDY;
 Window[nwin].nDY = 23;
 msg_out("Help end");
#else
 printf("                  Основные команды в режиме ОУ :\015\012");
 printf("TMK number_D - выбор устройства в текущем окне\015\012");
 printf("SAT adr_D - задание адреса ОУ в МК\015\012");
 printf("FLAG 0/1, HBIT 0/1, BCST 0/1, DTBL 0/1 - установка режимов\015\012");
 printf("SW code_B - задание ответного слова\015\012");
 printf("Sbit_name/Cbit_name - установка/сброс бита ответного слова, \015\012");
 printf("                      где bit_name - BS, SR, TF, SF, DN\015\012");
 printf("PG/SPG/CPG page_D - задание страницы БЗУ со стороны ПЭВМ/МК\015\012");
 printf("SMR/CMR - блокировка/разблокировка текущего подадреса\015\012");
 printf("SR/ST subadr_H - задание подадреса в зоне приема/передачи\015\012");
 printf("BE [adr_D, data_H] - редактирование буфера\015\012");
 printf("BF start_D, end_D, data_H - заполнение буфера константой\015\012");
 printf("BC - очистка буфера\015\012");
 printf("I - сброс (инициализация) оконечного устройства\015\012");
 printf("RSW - чтение слова состояния\015\012");
 printf("SFL - циклическая запись флагов\015\012");
 printf("R filename - чтение в буфер из файла        W filename - запись буфера в файл\015\012");
 printf("R< filename - ввод команд из файла\015\012");
 printf("P [pause_D] - пауза программируемой длительности\015\012");
 printf(";... - коментарий\015\012");
 printf("Q  - выход из программы                     H  - помощь\015\012");
 savenDY = Window[nwin].nDY;
 Window[nwin].nDY = 23;
 msg_out("Конец подсказки");
#endif
 Window[nwin].nDY = savenDY;
 all_screen();
}

void cmds_open2(char *str)           /* выполнение командного файла  в цикле */
{
 if (cmd_count == 0) return;
 strcpy(ex_fname, str);
 cur_count=cmd_count;
 cmds_open(ex_fname);
}

int start_loop_n(unsigned long counter)
{
 int ps_f;

 if (counter == 1) goto one_start;
 gotoxy(1, 11);
 textcolor(CYAN);
#ifdef ENG
 printf("Loop start"/*. Press PrtScr to abort*/"...");
#else
 printf("Циклический запуск"/*. Нажмите PrtScr для выхода*/"...");
#endif
 textcolor(LIGHTGRAY);
 while (counter == 0 || counter > 1)   /* повторять пока не нажата клавиша */
 {
  start();
  if (pause) my_wait(pause);
  if (prtscr_flag) break;
  if (kbhit()) break;
  if (counter) counter--;
 }
 if (kbhit())
  bioskey();
 if (nwin == nmainwin)
  textcolor(WHITE);
 gotoxy(1, 11);
 printf("──────────────────────────────────────────────────────");
 textcolor(LIGHTGRAY);
 ps_f=prtscr_flag;
 prtscr_flag=0;
 one_start:
 start_1("");
 statistic_out("");
 if ((to_errors+channel_err+bad_starts) < err_level && !(ps_f && counter)) return 0;
 else return 1;
}

int start_1(char *str)                                  /* единичный запуск */
{
 if (end_ctrl(str)) return 0;
 if (!avtomat)
 {
  gotoxy(1, 10);
  clreol();
 }
 out_base();
 out_ctrl_code();
 start();
 if (avtomat)
 {
  select_window(rtwin);
  out_at();
  out_inn();
  out_status_word();
  out_page();
  out_subadr();
  rt_out_sw();
  if (avt_out)
   rt_out_ram(dir, subadr);
  select_window(bcwin);
 }
 out_inn();
 bc_out_sw();
 bc_out_ram(base);
 if (avtomat) statistic_out("");
 if ((to_errors+channel_err+bad_starts) < 1) return 0;
 else return 1;
}

int start_loop(char *str)            /* запуск в цикле */
/* Поддержка старта: 0 - выход по завершению, 
                     1 - выход по PrtScr или по ERR_LEVEL */
{
 unsigned long counter;

 while (*str == '\t' || *str == ' ') str++;
 counter=0;
 if (*str != '\0')
 {                                       /* циклический запуск по счетчику */
  if (sscanf(str, "%U", &counter) != 1)
  {
   msg_out(inp_err);
   return 1;
  }
 }
 else counter = 0;
 return start_loop_n(counter);
}

int start()
/* Поддержка старта: 0 - выход по тайм-ауту, 1 - выход по прерыванию */
{
 unsigned long p;

 int_num[Window[nwin].nTMK] = 0;
 bcstart(base, ctrl_code);
 p = biostime(0, 0L);  /* ожидание прерывания 2 (10) тика */
 do
 {
  CheckTmkEvent(fGlobalWaitEvent);
//  CheckTmkProxy(NO_WAIT_PROXY);
  if (int_num[Window[nwin].nTMK] != 0) return 1;
 }
 while (biostime(0, 0L) - p < 10);
 bc_sw = 0;
 to_errors++;
 return 0;
}

void prtscr_brk()                /* обработчик прерывания от PrtScr */
{
 prtscr_flag = 1;
}

void cmd_reset(char *str)                               /* сброс контроллера */
{
 if (end_ctrl(str)) return;
 switch (Window[nwin].nMode)
 {
 case BC_MODE:
  bcreset();
  bcdefbase(base);
  msg_out(bc_reset_ok);
  break;
 case RT_MODE:
  rtreset();
  wr_at(terminal_adr);
  rtdefpage(bram_page);
  rtdefsubaddr(dir, subadr);
  msg_out(rt_reset_ok);
  break;
 }
}


void msg_out(char *msg)                  /* вывод строки сообщения */
{
 gotoxy(1, Window[nwin].nDY);
 textcolor(CYAN);
#ifdef ENG
 printf("%s. Press any key...", msg);
#else
 printf("%s. Нажмите любую клавишу...", msg);
#endif
 while (!kbhit())
  WaitForMultipleObjects(nWaitEvents+1, ahWaitEvents, FALSE, 0);
 bioskey();
 if (nwin == nmainwin)
 {
  textcolor(WHITE);
  chH = '═';
 }
 else
 {
  textcolor(LIGHTGRAY);
  chH = '─';
 }
 gotoxy(1, Window[nwin].nDY);
 hor_line(Window[nwin].nDX-2);
 textcolor(LIGHTGRAY);
}

void rd_sw_loop(char *str)               /* чтение слова состояния в цикле */
{
 if (end_ctrl(str)) return;
 gotoxy(1, 10);
 textcolor(CYAN);
#ifdef ENG
 printf("Reading State Word Register. Press any key to abort...");
#else
 printf("Чтение регистра состояния. Нажмите любую клавишу для выхода...");
#endif
 textcolor(LIGHTGRAY);
 while (kbhit() == 0)                   /* повторять пока не нажата клавиша */
  rt_sw = rtgetstate();
 bioskey();
 gotoxy(1, 10);
 clreol();
 rt_out_sw();
}

void wr_mr_loop(char *str)                     /* циклическая запись в РРЖ */
{
 if (end_ctrl(str)) return;
 gotoxy(1, 10);
 textcolor(CYAN);
#ifdef ENG
 printf("Writing Mode Register. Press any key to abort...");
#else
 printf("Запись в регистр режима. Нажмите любую клавишу для выхода...");
#endif
 textcolor(LIGHTGRAY);
 while (kbhit() == 0)                   /* повторять пока не нажата клавиша */
  rtunlock();
 fLock=0;
 bioskey();
 gotoxy(1, 10);
 clreol();
}

void set_flag(char *str)         /* установка флагов */
{
 if (end_ctrl(str)) return;
 gotoxy(1, 10);
 textcolor(CYAN);
#ifdef ENG
 printf("Writing Flags. Press any key to abort...");
#else
 printf("Запись флагов. Нажмите любую клавишу для выхода...");
#endif
 textcolor(LIGHTGRAY);
 while (!kbhit())                   /* повторять пока не нажата клавиша */
 {
  if (dir == RT_TRANSMIT)
   rtsetflag();
  else
   rtclrflag();
 }
 bioskey();
 gotoxy(1, 10);
 clreol();
}

void read_sw(char *str)                 /* чтение регистра состояния */
{
 if (end_ctrl(str)) return;
 rt_sw = rtgetstate();
 rt_out_sw();
}

void check_int()         /* обнаружение прохождения прерывания и оповещение */
{
// int cx, cy;
 int fRestore, savenwin;

 fRestore = 0;
 savenwin = nwin;
 CheckTmkEvent(NO_WAIT_EVENT);
 for (nwin = 0; nwin <= nMaxWin; nwin++)
 {
  if (Window[nwin].nMode == RT_MODE && int_num[Window[nwin].nTMK])
  {
   if (Window[nwin].fVisible)
   {
    if (!fRestore)
    {
     fRestore = 1;
//     cx=wherex(); cy=wherey();
    }
    fInt = 1;
    select_window(nwin);
    out_inn();
    rt_out_sw();
#ifdef ENG
    if (!avtomat) msg_out("Interrupt");
#else
    if (!avtomat) msg_out("Прерывание");
#endif
    fInt = 0;
    int_num[Window[nwin].nTMK]=0;
   }
  }
 }
 nwin = savenwin;
 if (fRestore)
 {
  select_window(nwin);
  window(1, 1, 80, 25);
  gotoxy(1, 23);
 }
}

int in_key()                    /* ввод символа с проверкой прерывания */
{
 int key;
 int cx, cy;

 if (enter_mode)
 {
  check_int();
  key=fgetc(cmd_file);          /* чтение символа из командного файла */
  if (key == EOF || fSkipCmds)
  {
   fclose(cmd_file);
   if (Window[nwin].nMode == BC_MODE && cmd_count != 1 && --cur_count != 0 && !fSkipCmds)
   {
//    cx=wherex(); cy=wherey();  /* циклическое выполнение */
    select_window(nwin);
    gotoxy(59, 2);
    printf("%010lu", cur_count);
    window(1, 1, 80, 25);
    gotoxy(cx, cy);
    cmds_open(ex_fname);
    check_int();
    key=fgetc(cmd_file);
   }
   else
   {
    if (Window[nwin].nMode == BC_MODE)
    {
//     cx=wherex(); cy=wherey(); /* завершение цикла */
     select_window(nwin);
     gotoxy(59, 2);
     printf("%010lu", cmd_count);
     window(1, 1, 80, 25);
     gotoxy(1, 23);
    }
    enter_mode=0;
    fSkipCmds=0;
    while (kbhit() == 0)
    {
     WaitForMultipleObjects(nWaitEvents+1, ahWaitEvents, FALSE, 0);
     check_int();
    }
    key=bioskey();
   }
  }
 }
 else
 {
  while (kbhit() == 0)
  {
   WaitForMultipleObjects(nWaitEvents + 1, ahWaitEvents, FALSE, INFINITE);
   check_int();
  }
  key=bioskey();
 }
 return key;
}

void in_cmd(char *str)
/* ввод командной строки в str, селектирование управляющих и функциональных */
{
 unsigned short key;                       /* код принятый с клавиатуры, ... */
 int fInCmd;
// char ch;

 str_ptr = 0;
 fInCmd = 0;
 do
 {
  if (!fInCmd)
  {
   window(1, 1, 80, 25);
   gotoxy(1, 23);
   clreol();
#ifdef ENG
   printf("Command: ");
#else
   printf("Команда: ");
#endif
   cmd_str[str_ptr]='\0';
   printf(cmd_str);
  }
  fInCmd = 0;
  key = in_key();
  if ((key & 0x00FF) && key != GPLUSW)
  {
   if ((key&=0x00FF) < 0x20 && key != CR && key != LF)
   {
    make_ctrl(key);
    continue;
   }
   key=str[str_ptr++]=toupper(key&=0x00FF);
   putchar(key);
   fInCmd = 1;
  }
  else
  {
   window(Window[nwin].nX + 1, Window[nwin].nY, 
           Window[nwin].nX + Window[nwin].nDX - 2, 
           Window[nwin].nY + Window[nwin].nDY - 1);
   make_func(key);
   continue;
  }
 }
 while (key != CR && key != LF);
 str[--str_ptr]='\0';
}

void make_ctrl(int key)
/* обработка управляющих кодов, key - управляющий код. */
{
 switch (key)
 {
 case BACKSPACE:
  if (str_ptr != 0)     /* забой */
  {
   --str_ptr;
   printf("\x08 \x08");
  }
  break;
 case ESCAPE:       /* отмена всей строки */
  str_ptr=0;
  break;
 case TAB:
  str_ptr=0;
  nmainwin = !nmainwin;
  int_num[Window[0].nTMK] = 0;
  int_num[Window[1].nTMK] = 0;
  select_window(nmainwin);
  all_screen();
  break;
 }
}

void make_func(unsigned short key)
/*
обработка функциональных клавиш, F1..F10
key - расширенный код ASCII
*/
{
 switch (key)
 {
 case UP:   /* возврат к предыдущей команде */
            strcpy(cmd_str, old_cmd);
            str_ptr=strlen(cmd_str);
            break;
 case F01:  switch (Window[nwin].nMode)
            {
            case BC_MODE:
             bc_help("");
             break;
            case RT_MODE:
             rt_help("");
             break;
            }
            break;
 case F02:  buf_edit("");
            break;
 case F03:  int_num[Window[nwin].nTMK] = 0;
            switch (Window[nwin].nMode)
            {
            case RT_MODE:
             if (!set_mode(BC_MODE))
             {
              base = 0;
              bcdefbase(0);
             }
             all_screen();
             break;
            case BC_MODE:
             if (!set_mode(RT_MODE))
             {
              cram_page = bram_page = 0;
              rtdefpage(0);
              dir = RT_RECEIVE;
              subadr = 1;
              rtdefsubaddr(dir, subadr);
              }
             all_screen();
             break;
            }
            break;
 case F04:
            str_ptr=0;
            nmainwin = !nmainwin;
            int_num[Window[0].nTMK] = 0;
            int_num[Window[1].nTMK] = 0;
            select_window(nmainwin);
            all_screen();
            break;
 case F05:
            break;
 case F06:  switch (Window[nwin].nMode)
            {
            case BC_MODE:
             start_1("");
             break;
            case RT_MODE:
             read_sw("");
             break;
            }
            break;
 case F07:  switch (Window[nwin].nMode)
            {
            case BC_MODE:
             start_loop("");
             break;
            case RT_MODE:
             rtlock(dir, subadr);
             fLock=1;
             break;
            }
            break;
 case F08:  cmd_reset("");
            break;
 case F09:  fields_chg("");
            break;
 case F10:  make_quit();
            break;
 case GPLUS:if (Window[nwin].nMode == RT_MODE)
            {
             dir = (dir == RT_TRANSMIT) ? RT_RECEIVE : RT_TRANSMIT;
             out_subadr();
             rt_out_ram(dir, subadr);
            }
            break;
 case PGUP: switch (Window[nwin].nMode)
            {
            case BC_MODE:
             if (base > 0)
             {
              base--;
              out_base();
              bc_out_ram(base);
             }
             break;
            case RT_MODE:
             if (subadr > 0)
             {
              subadr--;
              out_subadr();
              rt_out_ram(dir, subadr);
             }
            }
            break;
 case PGDN: switch (Window[nwin].nMode)
            {
            case BC_MODE:
             if (base < bcgetmaxbase())
             {
              base++;
              out_base();
              bc_out_ram(base);
             }
             break;
            case RT_MODE:
             if (subadr < 31)
             {
              subadr++;
              out_subadr();
              rt_out_ram(dir, subadr);
             }
            }
            break;
 }
}
