/*          задача опpоса ADAM                      */

#include  "complex.h"
#include  "screen.h"

extern word_s setting(analog *a_ptr,float work_f);
extern void koeff_sc(analog *a_ptr);
extern byte * z_db(byte *x_db,int len);
extern word_s numrec, lenrec, fh, N_MAN;
extern char *recfil;

word_s ADAM4017_input( controller *port, word_s id, word_s param_num, float * value );
float Count_tech_value( float value, analog * ptr_a );
/*-------------------------------------------------------------------*/

void taskADAM(controller *ptr_c)
{
  word_s i,kz,begin,val;
  analog *ptr_a;
  float value,vf;

/*----------------------------  Цикл  опpоса  ------------*/
  begin = 1;
  while(!endrun) {
    wait_flag_set(ptr_c->flag, 0L);
    clear_flag(ptr_c->flag);

       for(i=0, ptr_a=ptr_c->a_ptr; i < ptr_c->num_ap; i++, ptr_a++) {
      if(ptr_a->mod_cod==M_INP) continue;
      if(ptr_a->nolog) continue;    /* если логич. запpет обpаб. */

         switch( ptr_a->param1 ) {
               case 17: kz=ADAM4017_input(ptr_c,ptr_a->nom_ab,ptr_a->nomin_var,&value);
                                break;
               default: kz = 1;
      }

         if( kz ) {
        ptr_a->novalid=1;
               kz=ptr_a->nom_ab+1;
               ptr_c->kz = kz;
               kz_com(kz,ptr_c);
        continue;
      }

      ptr_a->novalid = 0;                         /* достовеpность есть */
      value = Count_tech_value( value, ptr_a );

      if(ptr_a->var_tech == value && !begin) ptr_a->dif_var = 0;
         else {
          ptr_a->var_tech=value;
          vf=ptr_a->var_tech;
          if(ptr_a->var_tech < ptr_a->min_sc) {
                vf = ptr_a->min_sc;
                ptr_a->novalid=1;
         }

         if(ptr_a->var_tech > ptr_a->max_sc) {
               vf = ptr_a->max_sc;
               ptr_a->novalid=1;
         }

         if(!ptr_a->no_uchet)  ptr_a->var_tech=vf;       /*************/
               val=(float)ADC_SC*(vf-ptr_a->min_sc)/(ptr_a->max_sc-ptr_a->min_sc)+0.5;
               if(val < 0) val=0; else if(val > ADC_SC) val=ADC_SC;
        ptr_a->dif_var = 1;
        ptr_a->var_cod = val;
        if(ptr_a->min_reg && val < ptr_a->min_reg) ptr_a->bound_reg = 1;
        else if(ptr_a->max_reg && val > ptr_a->max_reg) ptr_a->bound_reg = 2;
        else ptr_a->bound_reg = 0;
        if(ptr_a->min_al && val < ptr_a->min_al) ptr_a->bound_al = 1;
        else if(ptr_a->max_al && val > ptr_a->max_al) ptr_a->bound_al = 2;
        else ptr_a->bound_al = 0;
      }
    }

    if(!kz) begin = 0;
    ptr_c->kz=kz;
  }
}
/*-----------------------------------------------------------------*/

float Count_tech_value( float value, analog * ptr_a )
{
  static float sensor_sc[5][2] = {
                                   { 4.0, 20.0 },
                                   { 0.0,  4.0 },
                                   { 0.0, 20.0 },
                                   { 0.0,  5.0 },
                                   { 0.0, 10.0 }
                                 };

#define sensor_sc_min sensor_sc[ ptr_a->type_set -1 ][0]
#define sensor_sc_max sensor_sc[ ptr_a->type_set -1 ][1]

  if( ptr_a->type_set == 0 ) {
    ptr_a->novalid = 1;
    return 0;
  }

  value = ( value - sensor_sc_min ) / ( sensor_sc_max - sensor_sc_min );
  value = value * ( ptr_a -> max_sc - ptr_a -> min_sc ) + ptr_a -> min_sc;
  return value;
}
/*-------------------------------------------------------------------*/

word_s ADAM4017_input( controller *port, word_s id, word_s param_num, float * value )
{
  word_s kz,rep,j;
  char buf[12];

  rep=3;
  do {
       tsk_outp(port->basaddr+2,0x87);       /* enable and clear fifo */
       sprintf( buf, "#%02d%1d\015", id, param_num );
       for(j=0; j<strlen(buf); j++) tsk_outp(port->basaddr,buf[j]);  /* запpос */

       for(kz=1,j=0; j<10;) {         /* Receive data */
         if((tsk_inp(port->basaddr+5) & 1)==0) t_delay(1L); /* Check data ready */
         if((buf[j++]=tsk_inp(port->basaddr))==0x0d) { kz=0; break; }
       }
       buf[j]=0;
       if(strlen(buf) != 9) kz=1;
  } while(kz && --rep);

  if( kz ) return kz;

  kz = !sscanf( buf, ">%f", value );
  return kz;
}
/*-------------------------------------------------------------------*/
void insert_A_ADAM(analog * a_ptr)
{
  word_s i, work_i;
  float work_f;
  byte *x_db;

  for(i=0; i < numrec; i++, a_ptr++) {
    read(fh, recfil, lenrec);
    a_ptr->novalid = 1;
    strncpy(a_ptr->cipher, (x_db = recfil + 1), 9);
//----------------------------
//    gprintf(15,2,"Шифр = %s",a_ptr->cipher);
//    t_delay(100);
//----------------------------
    strncpy(a_ptr->name, (x_db+= 9), 25);
    strncpy(a_ptr->unit, (x_db+= 25), 9);
    sscanf(x_db+= 9, "%1hd", &work_i);    a_ptr->type_sc = (byte)work_i;
    sscanf(z_db(x_db+= 1,8), "%8f", &a_ptr->min_sc);
    sscanf(z_db(x_db+= 8,8), "%8f", &a_ptr->max_sc);
    koeff_sc(a_ptr);
    sscanf(z_db(x_db+= 8,8),"%8f",&work_f);    a_ptr->min_reg = setting(a_ptr,work_f);
    sscanf(z_db(x_db+= 8,8),"%8f",&work_f);    a_ptr->max_reg = setting(a_ptr,work_f);
    sscanf(z_db(x_db+= 8,8),"%8f",&work_f);    a_ptr->min_al = setting(a_ptr,work_f);
    sscanf(z_db(x_db+= 8,8),"%8f",&work_f);    a_ptr->max_al = setting(a_ptr,work_f);
    sscanf(x_db+= 8,"%1hd",&work_i);    a_ptr->sum_ysr = work_i;
    sscanf(x_db+= 1,"%1hd",&work_i);    a_ptr->type_mech=(byte)work_i;
    sscanf(z_db(x_db+= 1,2),"%2hd",&work_i);
    sscanf(z_db(x_db+= 2,2),"%2hd",&work_i);    a_ptr->param1 = (byte)(work_i);
    sscanf(z_db(x_db+= 2,3),"%3hd",&work_i);    a_ptr->nom_ab = (byte)(work_i-1);
    sscanf(z_db(x_db+= 3,2),"%2hd",&work_i);    a_ptr->nomin_var = (byte)(work_i-1);
    sscanf(z_db(x_db+= 2,2),"%2hd",&work_i);    a_ptr->type_set = (byte)(work_i);
    if(a_ptr->type_mech==M_INP) {
      if(a_ptr->k_scale > 0) a_ptr->novalid = 0;
      a_ptr->type_mech=0; a_ptr->mod_cod=M_INP;
      N_MAN += 1;
    }
  }
}
//--------------------- Включение контроллера ---------------------------
void enable_ADAM(void)
{
 word_s l_chan,i;
 controller * ptr_c;

 for(i = 0, ptr_c = c_ptr; i < c_num; i++, ptr_c++)
 {
  if(ptr_c->period==0 || ptr_c->typcontr!=ADAM ) continue;
  if(tsk_inp(ptr_c->basaddr+3)==0xff)
  {
   eprintf(RED_,"Hет порта для АДАМ'а");
   ptr_c->kz=-1;
   continue;
  }
  tsk_outp( ptr_c->basaddr + 2, 0xc9 ); /* FIFO on */
  tsk_outp( ptr_c->basaddr + 3, 0x80 ); /* DLAB := 1 */
  switch( ptr_c->baud )
  {
   case  1200: l_chan=96;break;
   case  2400: l_chan=48;break;
   case  4800: l_chan=24;break;
   case  9600: l_chan=12;break;
   case 19200: l_chan=6; break;
   default   : l_chan=12;
  }
  tsk_outp(ptr_c->basaddr,(byte)l_chan);  /* SPEED divisor */
  tsk_outp(ptr_c->basaddr+1,0);           /* SPEED divisor */
  tsk_outp(ptr_c->basaddr+3,0x03 );    /* data=8 stop=1 parity=none */
  tsk_outp(ptr_c->basaddr+1,0);        /* NO INTERRUPTS */
 }
}
//----------------------- Выдача сообщения об ошибке ---------------------------
word_s kz_mesage_ADAM(controller *pc,word_s kz,word_s chn,word_s kz_old)
{
 if(pc->nom_ord!=chn || kz_old!= kz) fgtext(RED_,280,337,"Порт %4X,  ADAM  %2d: Нет связи",pc->basaddr,kz);
 return(pc->nom_ord);
}