/*                                COMPLEX.C                           */
#include  "complex.h"
#include  "screen.h"
#include  "arh.h"
#include  "graf.h"
#include  "mnemos.h"
#include  "kadr.h"
#include  "dpmi.h"

#define VERSION "1.0pre2"

#define DI1   (DINA +N_D)->
char *complex = __FILE__;

void t_loct(long *t_l,struct tm *ttm_l);
//nearptr t_malloc(size_t size);
//void t_free(nearptr mem_ptr);
extern void input_DB(void);
void creatcom(void);
void startcom(void);
void   kz_com(word_s kz, controller *pc);
void kz_mem(char *file,word_s line);
//void   beep(long tiks);
void open_graph(void);
void cdecl gprintf(word_s row, word_s col, char *fmt, ...);
void cdecl eprintf(word_s c,char *fmt, ...);
void cdecl mesprintf(word_s c,char *fmt, ...);
void v24_sendask(sioptr port,byte *masask,word_s lask);
void   initport(controller *ptr_c);
float float_intel(byte *bufr);
float valtec(analog *pt, word_s cod);
void end_scan();
void beg_scan();
extern unsigned size_free_mem();
dword size_pool(poolptr pool_ptr);
void error_bd(char *str1);
dword cpu_frq();
word CalcHZ();

extern void enable_contr(void);
extern void disable_contr(void);
extern void create_task_contr(controller *ptr_c,char *name);
extern word_s kz_mesage_com(controller *pc,word_s kz,word_s chn,word_s kz_old);

void finish_complex();
void ptr_pool();
void cdecl fgtext(word_s c,word_s x,word_s y,char *fmt, ...);

extern void fgstr(word_s c,word_s x,word_s y,char *str);
extern void in_db(byte i);
extern void light_num_lock(byte cmd);

extern void   task_ar(void);
extern void   task_d_0(void);
extern void   signaliz(void);
extern word_s   Kadr_v(word_s k, word_s nscr);
extern void   dispat(word *scrn);
extern void   pr_zap(void);
extern void   for_otv(void);
extern void   per_otv(void);
extern void ss(void);
extern void install_arh_modem(void);
extern void install_modem_arh(void);
extern void input_order(void);
extern void loadpcxlib(char *flpcl);
extern void   comutator(void);
extern word_s inst_printer();
extern byte info_pc();
extern dword initPCIvid();
extern void EnVGA(dword);
extern void fix_err(char *text);

word ChOS();

#if (COUNT)
extern void   equip(void);
#endif

char namfn[] = "COMPLEX.C";

word_s tekygol[4][16][5];

extern nearptr pool;

g_graf * G_GRAF_PTR;
mpred *ptr_mpred;
controller * c_ptr;                    /* указ. на нач. описат. контpолл. */
word_s c_num;                             /* количество контpоллеpов */

byte  * W_PTR;
word_s  W_NUM;
word_s  N_MAN=0;

object * o_ptr;                        /* указ.на нач.опис.объектов упp. */
word_s o_num;                             /* количество объектов упp. */
word_s o_curr[4];                            /* текущ. ном. объекта */
word_s e_num;                             /* кол-во корр.расходов */
edit_q * e_ptr;

tcbptr sign;                           /* указат. на задачу SIGNAL      */
tcbptr arh_reg;                        /* указат. на задачу TASK_AR     */
tcbptr d_0_com;                        /* указат. на задачу TASK_D_0    */
tcbptr t_sp;                           /* указатель на задачу SS        */
tcbptr t_s_mes;                        /* указатель на задачу сообщений */
tcbptr t_eq;                           /* указатель на задачу EQUIP     */

gr_cont * gr_c_p;                      /* указ.на нач.опис.гpупп контуpов */
word_s gr_c_n=0;                          /* количество гpупп контуpов */

word_s gr_g_n=0;                          /* количество гpупп графиков */

pg_view *pg_v_p;                /* указат.на начало описания общего вида */
str_ov  *p_str_ov;
str_ov  *p_str_ovt;
par_ov  *p_par_ov;
par_ov  *p_par_ovt;

word_s k_str_ov;
word_s k_par_ov;

str_tab  *p_str_tab;
win_tab  *p_win_tab;
par_tab  *p_par_tab;

word_s k_str_tab;
word_s k_win_tab;
word_s k_par_tab;

speak_ds *sp_sert;              /* ук-ль на начало м-ва описателей pеч.сигн*/
struct sp_sk *speak_s;
struct sp_sk sp_s;

flagptr period_fl[4];              /* указат. на флаг пеpиодичности задач */
tlinkptr period_tm[4];             /* указат. на таймеp пеpиодичности задач */

flagptr peri_fl1[4];              /* указат. на флаг пеpиодичности задач */
tlinkptr peri_tm1[4];             /* указат. на таймеp пеpиодичности задач */

word_s kolreg[4],flag_din[4],kolzad[4];

wpipeptr event_chn;             /* указатель на канал событий */
wpipeptr d_0_chn;               /* указатель на канал сбpоса команд */
resourceptr ekran;              /* указатель на pесуpс  ЭКРАН */
resourceptr memory;             /* указатель на pесуpс  ПАМЯТЬ */
resourceptr time_l;             /* указатель на pесуpс ВРЕМЯ */
#if (FONT==1)
unsigned char *im;              /* указатель на опpеделение шpифта */
#endif

va_list argptr;
byte t_kbd = 0, p_scan = 0, yes_P5=0, arh_sql=0, bl_bord=0 ,model_save=0;
byte video_mode=_ERESCOLOR, NDayArh=1, NMonsArh=1, FastFill=0;
word TStSize=100, TStSpeed=0;

int HZ = 18;                                //Количество прерываний сист. таймера за секунду
dword frq_cpu;
void (_interrupt _far *oldcom1)();
void (_interrupt _far *oldcom2)();
word_s PRI_OFF = 40;
byte *globDOS_DATE;                   //Глобальный указатель на DOS буфер
word header_b;                        //Селектор DOS буфера (для закрытия)

dword screen_run=0;                   //Экран с которого Complex был запущен (для PCI)
word_s screen=0;                      //Активный для модиификации экран
word numb_os=0;                       //0-DOS;
byte disp_amount=1;                   //Количество дисплеев в системе
byte PCIvid=0;                        //Признак наличия PCI VGA
wpipeptr scr_chn[4];    /* массив указателей на каналы команд дисплеев */
tcbptr disp_scr[4];
word_s endrun;

tcbptr z_a_an, z_a_nr, z_a_sb;        /* задача архивации */

char *tip_ekr = "NULL";                      //Тип экрана для копии экрана
word screns[4] = {0,1,2,3};
char NameWpipe[][8]={"SCR0","SCR1","SCR2","SCR3"};
char NameDisp[][8]={"DISP0","DISP1","DISP2","DISP3"};
char NameFlags[][8]={"T_FLAG0","T_FLAG1","T_FLAG2","T_FLAG3"};
char NameFlags1[][8]={"T_FLAG10","T_FLAG11","T_FLAG12","T_FLAG13"};

char *NameComand[]=
{"ALG:",
 "ALARM:",
 "ALG_FRM:",
 "DESCR_CNT:",
 "CONTR:",
 "!",
 "MNS_DOM:",
 "MNS_STAT:",
 "MNS_DIN:",
 "GR_CONT:",
 "GR_GRAF:",
 "SIGNAL:",
 "!",
 "VIEW:",
 "COMTABL:",
 "SPEAK:",
 "PCX_LB:",
 "WAV_LB:",
 "DFON:",
 "ARH_DAY:",
 "ARH_HOUR:",
 "ARH_MIN:",
 "ARH_SPRAV:",
 "ALG_STAT:",
 "MAN_STAT:",
 "EDIT_Q:",
 "TMAG:",
 "FGTG:",
 "TMAG_D:",
 "FGTG1:",
 "NO_UCH:",
 "EDIT:",
 "ARCH_OP:",
 "COMPL_ERR:",
 "A_MGN:",
};

char *NameFile[]=
{"alg.cfg",                 //0
 "alarm.dbf",               //1
 "alg_frm.cfg",             //2
 "descrcnt.dbf",            //3
 "contr.cfg",               //4
 "alg.err",                 //5
 "domine.mns",              //6
 "statika.mns",             //7
 "dinamika.mns",            //8
 "grc.dbf",                 //9
 "grg.dbf",                 //10
 "signal.cfg",              //11
 "sign.dbf",                //12
 "view.dbf",                //13
 "comtabl.dbf",             //14
 "speak.dbf",               //15
 "grad.pcl",                //16
 "wav.rs",                  //17
 "dfon.ozu",                //18
 "day.bin",                 //19
 "hour.bin",                //20
 "min.bin",                 //21
 "sprav.bin",               //22
 "alg_stat.cfg",            //23
 "man_stat.cfg",            //24
 "edit_q.dbf",              //25
 "tmag.dbf",                //26
 "fgtg.prt",                //27
 "tmag_d.dbf",              //28
 "fgtg1.prt",               //29
 "no_uch.bin",              //30
 "edit.bin",                //31
 "ar_op.aop",               //32
 "complex.er",              //33
 "a_mgn.bin",               //34
};

unsigned char *psvect=NULL;
/*--------------------------------------------------------------------*/

main(word_s narg, char *argum[])
{
 FILE *fil_nam;
 word scre,i,tmp;
 char str[80];

 //numb_os = ChOS();
 //eprintf(RED_,"OS_ID=%XH",numb_os);

 if(narg > 1)
 {
  for (i=1;i<narg;i++)
  {
   if(argum[i][0]=='/'||argum[i][0]=='-')
   {
    if(!strncmp(argum[i]+1,"tm",2)) { if(argum[i][3] >= '1' && argum[i][3] <= '9') into = argum[i][3]-0x30; }
    else if(!strcmp(argum[i]+1,"vga")) video_mode=_VRES16COLOR;
    else if(!strcmp(argum[i]+1,"sv"))  model_save=1;
    else if(!strcmp(argum[i]+1,"as"))  arh_sql=1;
    else if(!strcmp(argum[i]+1,"bl_border"))  bl_bord = 1;
    else if(!strcmp(argum[i]+1,"fast_fill"))  FastFill = 1;
    else if(!strcmp(argum[i]+1,"PCIVideo"))   PCIvid = 1;
    else if(!strcmp(argum[i]+1,"DayArh"))  { if(atoi(argum[i+1])>1 && atoi(argum[i+1])<1000) NDayArh =atoi(argum[i+1]); i++;}
    else if(!strcmp(argum[i]+1,"MonsArh")) { if(atoi(argum[i+1])>1 && atoi(argum[i+1])<1000) NMonsArh=atoi(argum[i+1]); i++;}
    else if(!strcmp(argum[i]+1,"tstack"))  { if(atoi(argum[i+1]) > 10) TStSize = atoi(argum[i+1]); i++; }
    else if(!strcmp(argum[i]+1,"speedup")) { if(atoi(argum[i+1]) > 0)  TStSpeed = atoi(argum[i+1]); i++; }
    else if(!strcmp(argum[i]+1,"Version")) { _clearscreen(0); printf("Complex2 версия: %s",VERSION); exit(0); }
    else if(argum[i][1]=='d') {if(argum[i][2]>'1'  &&  argum[i][2]<'5') disp_amount = argum[i][2]-0x30;}
    else if(argum[i][1]=='f') {if(i+1<narg) ReloadNameFile(argum[++i]); }
    else if(argum[i][1]=='t') {if(argum[i][2]>='0' && argum[i][2]<='3') t_kbd = argum[i][2]-0x30; if(t_kbd==1) p_scan=1; }
//    {if(argum[i][2]=='0') t_kbd=1; if(argum[i][2]=='1') t_kbd=2; }
    else //if(argum[i][1]=='h'||argum[i][1]=='?')
    {
     _clearscreen(0);
     printf("Complex2 (DOS32) Copyright (c) 2000-2003 DIYA Software,\n");
     printf("/h,/?,-?,-h - Это сообщение;\n");
     printf("/d[n]  - Количество дисплеев (n=1-4) для мультиплексора;\n");
     printf("/t[n]  - Тип клавиатуры:\n");
     printf("      n = 0 - Класическая инжинерная (по умолчанию);\n");
     printf("      n = 1 - Стандартная технологическая v1.0;\n");
     printf("      n = 2 - Стандартная технологическая v2.0;\n");
     printf("      n = 3 - Инжинерная (ноутбук);\n");
     printf("/f FileName - Подключение файла конфигурации имен;\n");
     printf("/as    - Генерировать архивы для SQL;\n");
     printf("/tm[n] - Период архивации мгновенных (n=1-9с);\n");
     printf("/sv    - Сохранение результатов работы вычеслителя и ручного ввода;\n");
     printf("/DayArh n  - Определние количества архивируемых дней (n=1-1000);\n");
     printf("/MonsArh n - Определние количества архивируемых месяцев (n=1-1000);\n");
     printf("/Version   - Версия программы;\n");
     printf("/vga       - Работать в VGA режиме;\n");
     printf("/bl_border - Включить мигание бордюра активного монитора в многомониторном режиме;\n");
     printf("/fast_fill - Использовать метод быстрой заливки поллигонов (системные функции);\n");
     printf("/tstack n  - Размер стэка задач <n>кб (по умолчанию 100);\n");
     printf("/speedup n - Ускорение системного таймера (0:55ms; 1:27ms; 2:13ms; 3:6.8ms);\n");
     printf("/PCIVideo  - Искать дополнительные PCI видеоконтроллеры.\n");
     exit(0);
    }
   }
  }
 }
 if(PCIvid && (i=initPCIvid()) > 1) disp_amount=i;
 else                               PCIvid = 0;
 HZ = 1193180*(1<<TStSpeed)/65536;

 eprintf(GRAY_,"Day %d; Mons %d",NDayArh,NMonsArh);
 putenv("TZ=ABC8");
 tzset();
 if(t_kbd){Kbd_AllLight_OFF(); Kbd_Light_ON(50);}
 if(info_pc()>4) yes_P5  = 1;                  //Тип процессора более 486
 if(yes_P5)      frq_cpu = cpu_frq();
 dpmi_dos_allc(16,&header_b,&tmp); globDOS_DATE=(byte *)(tmp<<4); //Выделения буфера DOS 256 байт
// header_b=d_alc_DPMI(256,&globDOS_DATE);
 SB_Initialize();
 set_kbd();
 if(p_scan) beg_scan();

 memset(tekygol,0xff,320);

#if (FONT==1)
 int fh;
 im=(unsigned char*)malloc(2560);
 if((fh=open_fh("fon1008.pat",0)) != -1) {
   read(fh,im,2560);
   close(fh);
 }
#else
 if(p_scan) end_scan();
 setfont(0);
 if(p_scan) beg_scan();
#endif

 screen=0;
 loadpcxlib("grad.pcl");

 for(scre=0;scre<disp_amount;scre++)
 {
  set_screen(scre);
  _setvideomode(video_mode);   /*****************************/
  _setcolor(15);
  setpcxvideo("complex.pcx",0,0,640);
  _settextcolor(7);
  gprintf(20,27," ЗАГРУЗКА  БАЗЫ  ДАННЫХ \n\n");
 }
 set_screen(0);

 input_DB();                              /* загpузка БД */

 for(scre=0;scre<disp_amount;scre++)
 {
  set_screen(scre);
  _clearscreen(_GCLEARSCREEN);
  open_graph();
 }
 set_screen(0);

 W_PTR = (byte *)c_ptr;
 W_NUM = c_num;

 tsk_init_pool(TStSize*1024);
 install_tasker(0,TStSpeed);                /* инициализация TCTASK */
 endrun=0;

 for(scre=0;scre<disp_amount;scre++)
 {
  scr_chn[scre] = create_wpipe(NULL, NULL, 2, NameWpipe[scre]);  /* канал дисп scre*/
  disp_scr[scre] = create_task(NULL,(funcptr)dispat,NULL,5000,PRI_STD-PRI_OFF+14,&screns[scre],NameDisp[scre]);
  period_fl[scre] = create_flag(NULL, NameFlags[scre]);
  period_tm[scre] = create_timer(NULL, 200*HZ, period_fl[scre], TKIND_FLAG, 1);
  peri_fl1[scre] = create_flag(NULL, NameFlags1[scre]);
  peri_tm1[scre] = create_timer(NULL, 20*HZ, peri_fl1[scre], TKIND_FLAG, 1);
 }

 event_chn = create_wpipe(NULL, NULL, 512, "EVENT");  /* канал событий */
 d_0_chn = create_wpipe(NULL, NULL, 64, "D_0_CHN");   /* канал команд */
 ekran = create_resource(NULL,"EKRAN");
 memory = create_resource(NULL,"MEMORY");
 time_l = create_resource(NULL,"TIME_L");

 r_mgn=create_resource(NULL,"R_MGN");  /* созд. ресурсов файлов архивов */
 r_cut=create_resource(NULL,"R_CUT");
 r_mec=create_resource(NULL,"R_MEC");
 r_nr =create_resource(NULL,"R_NR");
 r_sb =create_resource(NULL,"R_SB");
 r_eq =create_resource(NULL,"R_EQ");

//#if (IMIT_AN)
//  imit_an();
//#endif

 sign = create_task(NULL,(funcptr)signaliz,NULL,1500,PRI_STD-PRI_OFF+20,NULL,"SIGNAL");

#if (GRAFIK + PROTOC)
 z_a_an=create_task(NULL,(funcptr)Arh_an,NULL,1500,PRI_STD-PRI_OFF+25,NULL,"ARH_AN");  /*задачи*/
#endif
#if (PROTOC)
 z_a_nr=create_task(NULL,(funcptr)Arh_nr,NULL,1500,PRI_STD-PRI_OFF+15,NULL,"ARH_NR");
 z_a_sb=create_task(NULL,(funcptr)Arh_sb,NULL,1500,PRI_STD-PRI_OFF+15,NULL,"ARH_SB");
#endif
#if (REGULAT)
 arh_reg = create_task(NULL,(funcptr)task_ar,NULL,1500,PRI_STD-PRI_OFF+15,NULL,"TASK_AR");
#endif
#if (SPEAK)                       /* создание задачи pечевой сигнализации */
 t_sp = create_task(NULL,(funcptr)ss,NULL,1500,PRI_STD-PRI_OFF,NULL,"SS");
#endif
#if (COUNT)                       /* создание задачи учета pаботы обоpуд. */
 t_eq = create_task(NULL,(funcptr)equip,NULL,1500,PRI_STD,NULL,"EQUIP");
#endif
//#if (REM110 + LOM110 + REM130 + DAM512)
//   d_0_com = create_task(NULL,(funcptr)task_d_0,NULL,1500,PRI_STD-PRI_OFF+30,NULL,"TASK_D");
//#endif


#if (!MOD_ARH)
 enable_contr();                       //Инициаллизация контроллеров
 creatcom();                           /* создание задач опpоса */
 startcom();                           /* запуск задач опpоса */
#endif

 gprintf(4,29,"ИНИЦИАЛИЗАЦИЯ  СИСТЕМЫ");
 if((fil_nam = fopen("nam_sect.txt", "rt")) != NULL)
 {
  fgets(str, 80, fil_nam);
  gprintf(6,(80-strlen(str)) >> 1,str);
  fclose(fil_nam);
 }

#if (GRAFIK + PROTOC)
 start_task(z_a_an);        /* запуск задачи аpхивиpования анал.паp. */
#if (ARH_MOD)
 install_arh_modem();
#endif
#if (MOD_ARH)
 install_modem_arh();
#endif
#if (ORDER)
 input_order();
#endif
#endif

#if (PROTOC)
 start_task(z_a_sb);        /* запуск задачи аpхивиpования событий */
 start_task(z_a_nr); /* запуск задачи аpхивиpования наpушен. */
 arc_op1("НАЧАЛО");    /* начало аpхива действий опеpатоpа */
#endif
#if (COUNT)                  /* запуск задачи учета pаботы обоpудования */
 start_task(t_eq);
#endif
 start_task(sign);                    /* запуск задачи сигнализации */
 for(scre=0;scre<disp_amount;scre++) { start_task(disp_scr[scre]);}

#if (REGULAT)
 start_task(arh_reg);                /* запуск задачи аpхив. pегул. */
#endif
//#if (REM110 + LOM110 + REM130 + DAM512)
//   start_task(d_0_com);               /* запуск задачи сбpоса команд */
//#endif
#if (SPEAK)
 start_task(t_sp);                /* запуск задачи pечевой сигнализации */
#endif
//   set_new_int24();
 inst_printer();
 set_priority(NULL,PRI_STD-PRI_OFF+20);

// SB_Lib_via("START.WAV");
 comutator();

 finish_complex();
if(!t_kbd) light_num_lock(0);
}
/*---------------------------------------------------------------*/
#if (!MOD_ARH)
void creatcom()
{
 controller *ptr_c;
// nearptr p_chan;
 word_s i;// l_chan;
 char name[10];

 name[1] = 0;

 for(i = 0, ptr_c = c_ptr; i < c_num; i++, ptr_c++)
 {
  ptr_c->port_rsc = create_resource(NULL, name);
  if(ptr_c->period==0) continue;
//-------------------- Проверка, инициализация COM -------------------------
//  switch(ptr_c->typcontr)
//  {
//   case S711 : l_chan = 900; break;
//   case UMCM :
//   case U800 :
//   case L110 : l_chan = 512; break;
//   case M612 :
//   case Y170 :
//   case D512 :
//   case B130 :
//   case R130 :
//   case R110 : l_chan = 256; break;
//  }

//  if(ptr_c->typcontr != VIRT && ptr_c->typcontr != A813 && ptr_c->typcontr !=
//     HART && ptr_c->typcontr != S300 && ptr_c->typcontr != S400)
//  {
//    p_chan=t_malloc(l_chan);
//    if(ptr_c->typcontr==D512 || ptr_c->typcontr==Y170 || ptr_c->typcontr==U800 ||
//       ptr_c->typcontr==UMCM || ptr_c->typcontr==M612)
//    {
//     if(ptr_c->typcontr==D512 || ptr_c->typcontr==U800 || ptr_c->typcontr==UMCM)
//      tsk_outp(ptr_c->basaddr+7,3);                // on port
//     ptr_c->nomport=v24_define_port(ptr_c->basaddr,ptr_c->IRQ_line,ptr_c->vector);
//     ptr_c->port=v24_install(ptr_c->nomport,0,p_chan,l_chan,NULL,256);
//     if(!ptr_c->port){ ptr_c->period=0;eprintf(15,"Не могу инициализ. COM%d",ptr_c->nomport);continue;}
//    }
//    else
//    if(ptr_c->nomport >= 0x80)       // COM
//     ptr_c->port=v24_install(ptr_c->nomport,0,p_chan,l_chan,NULL,64);
//     if(!ptr_c->port){ptr_c->period=0;eprintf(15,"Не могу инициализ. COM%d",ptr_c->nomport-80);continue;}
//    else
//    if(ptr_c->nomport == 0)
//    {        // MPO8
//     ptr_c->nomport=ad8_define_port(ptr_c->basaddr,ptr_c->IRQ_line,ptr_c->vector);
//     ptr_c->port=ad8_install(ptr_c->nomport,p_chan,l_chan);
//     if(!ptr_c->port){ptr_c->period=0;eprintf(15,"Не могу инициализ. MPO8_%d",ptr_c->nomport);continue;}
//    }
//    else
//    {                                // RS485
//     ptr_c->nomport=v24_define_port(ptr_c->basaddr,ptr_c->IRQ_line,ptr_c->vector);
//     ptr_c->port=v24_install(ptr_c->nomport,0,p_chan,l_chan,NULL,64);
//     if(!ptr_c->port){ptr_c->period=0;eprintf(15,"Не могу инициализ. RS485_%d",ptr_c->nomport);continue;}
//     ptr_c->nomport=0x80;

//    }
//    initport(ptr_c);
//  }
//--------------------------------------------------------------------------

  create_task_contr(ptr_c,name);

  if(ptr_c->task==NULL) { ptr_c->kz=-1; continue; }
  ptr_c->flag = create_flag(NULL, name);
  ptr_c->timer= create_timer(NULL,ptr_c->period,ptr_c->flag,TKIND_FLAG,1);
  t_delay(0.5*HZ);
  set_flag(ptr_c->flag);
 }
}
/*---------------------------------------------------------------*/

void startcom(void)
{
   controller *ptr_c;
   word_s i;

   for(i = 0, ptr_c = c_ptr; i < c_num; i++, ptr_c++) {
     if(ptr_c->task == NULL) continue;      /* если нет пасп. */
     start_task(ptr_c->task);
   }
}
#endif
/*-------------------------------------------------------------------*/

void error_bd(char *str1)
{
  _settextcolor(12);
  eprintf(RED_,"ОШИБКА ЗАГРУЗКИ БД (%s)! Нажмите любую клавишу.",str1);
  _settextposition(3,2);
  _bios_keybrd(_KEYBRD_READ);
  if(p_scan) end_scan();
  exit(3);
}
/*-------------------------------------------------------------------*/

void kz_mem(char *file,word_s line)
{
 char str1[50];
//  gprintf(20,30," %s, строка %d: НЕТ ПАМЯТИ",file,line);
  sprintf(str1,"%s, строка %d: НЕТ ПАМЯТИ",file,line);
  error_bd(str1);
}
/*-------------------------------------------------------------------*/

void kz_com(word_s kz, controller *pc)
{
 word_s chn,pos,scre;
 static word_s oldchn, oldkz;
 byte col;
 static byte oldcol[30];

 pos = pc->nom_ord;

// eprintf(GRAY_,"ERROR_KZ2 TEST %x - %x",kz,oldkz[DISPLAY]);

 if(pc->period==0) col = YELLOW_;
 else
 {
  if(kz)
  {
   col = RED_;
   request_resource(ekran,0*HZ);
   for(scre=0;scre<disp_amount;scre++)
   {
    set_screen(scre);
    chn=kz_mesage_com(pc,kz,oldchn,oldkz);
   }
   set_screen(screen);
   release_resource(ekran);
   oldchn = chn; oldkz = kz;
  }
  else
  {
   col = GREEN_;
   if(pc->nom_ord==oldchn)
   {
    request_resource(ekran,0*HZ);
    for(scre=0;scre<disp_amount;scre++)
    {
     set_screen(scre);
     bar_(0,278,337,559,346);
    }
    set_screen(screen);
    release_resource(ekran);
    oldchn = 0xff;
   }
  }
 }
 if(oldcol[pos] != col)
 {
   request_resource(ekran,0*HZ);
   for(scre=0;scre<disp_amount;scre++)
   {
    set_screen(scre);
    fgtext(col,568+pos*8,337,"%1d",pc->nomcontr);
   }
   set_screen(screen);
   release_resource(ekran);
   oldcol[pos] = col;
 }
}
/*-------------------------------------------------------------------*/
/*
void   beep(long tiks)
{
   tsk_cli();
   tsk_outp(0x61,(byte)(tsk_inp(0x61) | 0x03));
   tsk_sti();
   t_delay(tiks);
   tsk_cli();
   tsk_outp(0x61,(byte)(tsk_inp(0x61) & 0xfc));
   tsk_sti();
}
*/
/*--------------------------------------------------------------------*/

void open_graph()
{
   _setcolor(WHITE_BR_);
   line(0,YT_ER,X_SCR,YT_ER);
   line(XL_ER-1,YT_ER,XL_ER-1,YB_ER);
   line(XR_ER+1,YT_ER,XR_ER+1,YB_ER);
   _rectangle(_GBORDER,0,30,X_SCR,YB_ER);
}
/*-------------------------------------------------------------------*/
word_s set_screen(word_s n)
{
  byte reply;
  if(!(disp_amount-1)) return screen;
m1:
  if(PCIvid){EnVGA(n);return n;}

  outp(0x360,n);
  tsk_nop();
  reply=inp(0x360);

  if(reply==0xfc && n==0) return n;
  if(reply==0xfe && n==1) return n;
  if(reply==0xfd && n==2) return n;
  if(reply==0xff && n==3) return n;
  goto m1;
//  if(reply==0xfc && n==0) screen=n;
//  else if(reply==0xfe && n==1) screen=n;
}
/*-------------------------------------------------------------------*/

void cdecl gprintf(word_s row,word_s col,char *fmt, ...)    /* пп граф.печати */
{
   char str[256];
   word_s c, x, y;

   va_start (argptr,fmt);
   vsprintf(str,fmt,argptr);
   va_end(argptr);

   c=_gettextcolor();
   x=(col-1)*8;  if(col == 1) x++;
   y=(row-1)*14;
   bar_(0, x,y, x+strlen(str)*8, y+13);
   fgstr(c,x,y+2,str);
}
/*-------------------------------------------------------------------*/

void   v24_sendask(sioptr port,byte *masask,word_s lask)
{
  word_s i;

  for(i = 0; i < lask; i++)  v24_send(port, masask[i], 20L);
}
/*-------------------------------------------------------------------*/

//void   initport(controller *ptr_c)
//{
// word_s len;

// if(ptr_c->port==NULL) { ptr_c->kz=-1; return; }
// if(ptr_c->typcontr==D512 || ptr_c->typcontr==Y170 || ptr_c->typcontr==M612 ||
//    ptr_c->typcontr==U800 || ptr_c->typcontr==UMCM)
// {
//  v24_change_baud(ptr_c->port,(long)ptr_c->baud);
//  if(ptr_c->typcontr==M612) v24_change_parity(ptr_c->port, PAR_EVEN);
//  else v24_change_parity(ptr_c->port, PAR_NONE);
//  v24_change_wordlength(ptr_c->port, 8);
//  v24_change_stopbits(ptr_c->port, 1);
//  v24_receive(ptr_c->port,2L);
//  return;
// }
// if(ptr_c->typcontr==S711) len=7; else len=8;
// if(ptr_c->nomport < 0x80)
// {
//  ad8_change_baud(ptr_c->port, ptr_c->baud);
//  ad8_change_mode(ptr_c->port,len,EVEN,2);
//  tsk_outp(ptr_c->basaddr + 1, 0x14);  /* откр.прер. по вводу */
// }
// else
// {
//  v24_change_baud(ptr_c->port, (long)ptr_c->baud);
//  v24_change_parity(ptr_c->port, PAR_EVEN);
//  v24_change_wordlength(ptr_c->port, len);
//  v24_change_stopbits(ptr_c->port, 2);
// }

//}
/*-------------------------------------------------------------------*/

float float_intel(byte *bufr)
{
  byte flt[4];

  flt[0]=bufr[3]; flt[1]=bufr[2]; flt[2]=bufr[1]; flt[3]=bufr[0];
  return *(float *)flt;
}
/*-------------------------------------------------------------------*/

float valtec(analog *pt, word_s cod)
{
  if(pt->type_sc == SC_SQRT) return (pt->min_sc + (float)sqrt((double)cod)*pt->k_scale);
  else return  (pt->min_sc + cod*pt->k_scale);
}
/*-------------------------------------------------------------------*/

void cdecl eprintf(word_s c,char *fmt, ...)
{
   char str[256];

   va_start (argptr,fmt);
   vsprintf(str,fmt,argptr);
   va_end(argptr);
   if(c==RED_ || c==GRAY_) fix_err(str);
   sprintf(str,"%.34s",str);
   if(c!=GRAY_)
   {
     if(c == RED_)
     {
       bar_(0,278,337,565,346);
       fgstr(c,278,337,str);
     }
     else
     {
       bar_(0,3,337,275,346);
       fgstr(c,3,337,str);
     }
   }
}
//____________________________________________________________________
void cdecl mesprintf(word_s c,char *fmt, ...)
{
 char str[256];

 va_start (argptr,fmt); vsprintf(str,fmt,argptr); va_end(argptr);
 sprintf(str,"%.35s",str); bar_(0,278,337,565,346); fgstr(c,278,337,str);
}
/*-------------------------------------------------------------------*/

void t_loct(long *t_l,struct tm *ttm_l)
{
 if(*t_l==0L) memset(ttm_l,0,sizeof(struct tm));
 else {
   request_resource(time_l,0*HZ);
   memcpy(ttm_l,localtime(t_l),sizeof(struct tm));
   release_resource(time_l);
 }
}
/*-------------------------------------------------------------------*/

void cdecl fgtext(word_s c,word_s x,word_s y,char *fmt, ...)
{
  char str[100];

  va_start (argptr,fmt);
  vsprintf(str,fmt,argptr);
  va_end(argptr);
  fgstr(c,x,y,str);
}
/*-------------------------------------------------------------------*/

dword size_pool(poolptr pool_ptr)
{
  poolptr tmp;
  unsigned sm;

  tmp=pool_ptr;
  sm=0;
  request_resource (&alloc_resource, 0*HZ);
  do
         if(tmp->size&1 && tmp->size > sm) sm = tmp->size;
  while((tmp=tmp->next) != pool_ptr);
  release_resource (&alloc_resource);
  return sm >> 10;
}
/*-------------------------------------------------------------------*/

void ptr_pool()
{
  extern dword time_virt[MAX_CONTR];
  word_s i = 0;

  gprintf(3,2,"CPU-%1d86,FRQ-%3dMHz,MEM-%5dKb,SysTime=%.1f(%.1f)ms,Displ-%1d,TStack-%2dKb\n"
              ,info_pc(),frq_cpu,(size_free_mem()/1024),1000./(float)HZ,1000./(float)CalcHZ(),disp_amount,size_pool(pool));
  if(yes_P5)for (i=0;i<c_num;i++) gprintf(4,2+(i*10)," %1d-%6d;",i,time_virt[i]/frq_cpu);
}
/*-------------------------------------------------------------------*/

void list_task(void)
{
  nameptr curr;
  tcbptr tsk;
  dword stk_size, i, j;

  i=0;
  for(curr=tsk_name_list.follow; curr->nkind; curr=curr->follow)
    if(curr->nkind == TKIND_TASK) {
      tsk=(tcbptr)curr->strucp;
      stk_size=tsk->stack - tsk->stkbot;
      for(j=2; tsk->stkbot[j]=='S'   &&
               tsk->stkbot[j-1]=='S' &&
               tsk->stkbot[j-2]=='S' &&
               j < stk_size;              j++);
      gprintf(8+i%14,i/14*42+2,"%8s pr=%5hu  st=%4hu  fr=%4hu",
                     curr->name,tsk->prior,stk_size,j);
      i++;
    }
}
/*-------------------------------------------------------------------*/

void finish_complex()
{
  word scre;

   endrun=1;
   t_delay(1*HZ);

#if (DOG_TIMER==1)
  tsk_inp(0x43);
#elif (DOG_TIMER==2)
  tsk_inp(0x43);
#endif

//   set_old_int24();
#if (PROTOC)
   arc_op1("КОНЕЦ");            /* конец аpхива действий опеpатоpа */
#endif
#if (!MOD_ARH)
  disable_contr();
#endif

   remove_tasker();
   tsk_cli();
   tsk_outp(0x61,(byte)(tsk_inp(0x61) & 0xfc));
   tsk_sti();

   for(scre=0;scre<disp_amount;scre++)
   {
    set_screen(scre);
    _setvideomode(_DEFAULTMODE);
   }
   set_screen(screen_run);

   SB_DeInitialize();
   if(p_scan) end_scan();
   dpmi_dos_free(header_b);
//   d_free_DPMI(header_b);
}
/*-------------------------------------------------------------------*/
void light_num_lock(byte cmd)
 {
  tsk_outp(0x60,0xED);
  tsk_outp(0x60,cmd );
 }
//------------------------------------------------------------------------

void ReloadNameFile(char *name)
{
 int hd,len,i,ii,k;
 char *str1;

 if((hd=open_fh(name,0)) != -1)
 {
  len=filelength(hd);
  str1=(char *)calloc(len,1); read(hd,str1,len); close(hd);
  for(i=0;i<len;i++)
  {
   if(*(word_s *)&(str1[i])=='//') for(;(i<len && str1[i]!=0x0D);i++);
   if(str1[i]=='#')
    for(ii=0;ii<sizeof(NameComand)/4;ii++)
     if(!strncmp(str1+i+1,NameComand[ii],strlen(NameComand[ii])))
     {
      i+=strlen(NameComand[ii])+1;
      for(k=0;(i+k)<len;k++) if(str1[i+k]==0x0D || *(word_s *)&(str1[i+k])=='//') break;
      NameFile[ii]=calloc(k+1,1);
      strncpy(NameFile[ii],&str1[i],k); NameFile[ii][k]=0; i+=k;
      break;
     }
  }
  free(str1);
 }
}

//Инициализация Serial портов

void init_Serial(int tip_C, char len_b, char len_can)
{
 int i;
 controller *ptr_c;
 nearptr p_chan;

 for(i=0,ptr_c=c_ptr;i<c_num;i++,ptr_c++)
 {
  if(ptr_c->period==0||ptr_c->typcontr!=tip_C) continue;
  p_chan=malloc(len_can);
  if(ptr_c->nomport >= 0x80)                                  // COM
  {
   ptr_c->port=v24_install(ptr_c->nomport,0,p_chan,len_can,NULL,64);
   if(!ptr_c->port){ptr_c->period=0;eprintf(RED_,"Не могу инициализ. COM%d",ptr_c->nomport-80);continue;}
  }
  else if(ptr_c->nomport == 0)                                // MPO8
  {
   ptr_c->nomport=ad8_define_port(ptr_c->basaddr,ptr_c->IRQ_line,ptr_c->vector);
   ptr_c->port=ad8_install(ptr_c->nomport,p_chan,len_can);
   if(!ptr_c->port){ptr_c->period=0;eprintf(RED_,"Не могу инициализ. MPO8_%d",ptr_c->nomport);continue;}
  }
  else                                                        // RS485
  {
   ptr_c->nomport=v24_define_port(ptr_c->basaddr,ptr_c->IRQ_line,ptr_c->vector);
   ptr_c->port=v24_install(ptr_c->nomport,0,p_chan,len_can,NULL,64);
   if(!ptr_c->port){ptr_c->period=0;eprintf(RED_,"Не могу инициализ. RS485_%d",ptr_c->nomport);continue;}
   ptr_c->nomport=0x80;
  }
  if(ptr_c->port==NULL) { ptr_c->kz=-1; return; }
  if(ptr_c->nomport < 0x80)
  {
   ad8_change_baud(ptr_c->port, ptr_c->baud);
   ad8_change_mode(ptr_c->port,8,EVEN,2);
   tsk_outp(ptr_c->basaddr + 1, 0x14);                        // откр.прер. по вводу
  }
  else
  {
   v24_change_baud(ptr_c->port, (long)ptr_c->baud);
   v24_change_parity(ptr_c->port, PAR_EVEN);
   v24_change_wordlength(ptr_c->port, len_b);
   v24_change_stopbits(ptr_c->port, 2);
  }
 }
}
//Check OS
word ChOS()
{
   word os_id=0;
   _asm
   {
     mov  ax,1600h
     int  2Fh
     mov  os_id,ax
   }
   return(os_id);
}

dword RDTSC()
{
   dword cnt=0;
   _asm
   {
     rdtsc
     mov cnt,eax
   }
   return(cnt);
}

dword cpu_frq()
{
   dword frq;
   frq = RDTSC();
   sleep(1);
   return( (RDTSC()-frq)/1000000 );
}

word CalcHZ()
{
  dword cnt;
  cnt = RDTSC();
  t_delay(10L);
  return( (10*frq_cpu*1000000)/(RDTSC()-cnt) );
}