/////////////////////////////////////////////////////////////////////////////////////////////////////////////////    
// Алгоритм анализа UART протокола    
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////    
   
 var Setup = CreateConfigure("UART protocol analyse");       
    
 TxChannel = "Канал TX";    
 RxChannel = "Канал RX (RX=TX)";    
 Speed     = "Скорость [бод]";    
 DataBits  = "Количество бит данных";    
 Parity    = "Паритет";    
 StopBits  = "Стоп бит";    
//Inversion = "Инверсия";    
 Speeds    = Array(9600, 75, 110, 134, 150, 300, 600, 1200, 1800, 2400, 4800, 7200, 14400, 19200, 38400, 57600, 115200);    
 NDataBits = Array(8,7,6,5);    
 ParityT   = Array("Нет","Чет","Нечет");    
       
 Setup.AddItem(TxChannel, 1);       
 Setup.AddItem(RxChannel, 2);       
 Setup.AddItem(Speed, NumArrayToString(Speeds));       
 Setup.AddItem(DataBits, NumArrayToString(NDataBits));          
 Setup.AddItem(Parity, StrArrayToString(ParityT));          
 Setup.AddItem(StopBits, "1\n2");          
 Setup.Configure();       
    
 TxChannel = Setup.GetValue(TxChannel);          
 RxChannel = Setup.GetValue(RxChannel);          
 Speed     = Speeds[Setup.GetValue(Speed)];          
 DataBits  = NDataBits[Setup.GetValue(DataBits)];          
 Parity    = Setup.GetValue(Parity);    
 StopBits  = Setup.GetValue(StopBits)+1;    
 TotalSize = NumberOfSamples;          
    
 ReportOut("Выбрана конфигурация:\nСкорость:\t" + Speed.toString(10) + " бод\n");          
 ReportOut("Бит данных:\t" + DataBits.toString(10) + "\n");          
 ReportOut("Паритет:\t\t" + ParityT[Parity] + "\n");          
 ReportOut("Ко-во стоп бит:\t" + StopBits.toString(10) + "\n================================================================\n");          
    
 if (Frequency >= 2*Speed)    
 {    
  if (TxChannel > 0 && TxChannel <= Channels)    
  {    
   if (RxChannel > 0 && RxChannel <= Channels)    
   {    
    var TxData = new Array();    
    var TxPos = new Array();    
    var PrefixComment = ""; 
     
    if (TxChannel != RxChannel)    
     PrefixComment = "Tx="; 
        
    ReadChannel(TxChannel, PrefixComment, TxData, TxPos );    
     
    if (TxChannel != RxChannel)    
    {    
     var RxData = new Array();    
     var RxPos = new Array();    
      
     PrefixComment = "Rx=" 
        
     ReadChannel(RxChannel, PrefixComment, RxData, RxPos );    
        
     var TxInd = 0;    
     var RxInd = 0;    
      
     //ReportOut("Tx array:" + TxPos.length + " Rx array:" + RxPos.length + "\n");             
    
     while(TxInd < TxPos.length || RxInd < RxPos.length)         
     {    
      if (TxInd < TxPos.length && (RxInd >= RxPos.length || TxPos[TxInd] <= RxPos[RxInd]))    
      {    
        ReportOut("Tx = 0x" + TxData[TxInd].toString(16) + CodeToChar( TxData[TxInd] ) + "\n");             
        TxInd++;    
      }    
      else    
      {    
        ReportOut("Rx = 0x" + RxData[RxInd].toString(16) + CodeToChar( RxData[RxInd] ) + "\n");             
        RxInd++;    
      }           
     } 
    }    
    else  
    {    
     for (i=0; i<TxData.length; i++)    
      ReportOut("0x"+TxData[i].toString(16) + "\n");             
    }    
        
    ReportOut("Анализ завершен\n");          
   }    
   else    
    ReportOut("Неверный номер RX канала");             
  }    
  else    
   ReportOut("Неверный номер TX канала");          
 }    
 else    
 {    
  DFreq = Speed * 2;    
  ReportOut("Чатота дескритизации мала для проведения анализа.\nДля выбраной скорости:" + Speed.toString(10) + "бод\nнеобходима частота не менее: " + DFreq.toString(10) + "Гц\n");          
 }    
     
 function ReadChannel( iChannel, StrPrefix, DataArray, PosArray )    
 {    
  HiSynLevel = 1;    
  LoSynLevel = 0;    
  BkFront = -1;    
  FvFront = 1;         
      
  if (DataType == "ANA")    
  {    
   HiSynLevel = +5;    
   LoSynLevel = -5;    
  }    
      
  CurValue = ValueAt(iChannel, 0);    
        
  if (CurValue <= LoSynLevel)    
  {// has inversion    
   CurValue = HiSynLevel;    
   HiSynLevel = LoSynLevel;    
   LoSynLevel = CurValue;     
   BkFront = 1;    
   FvFront = -1;         
  }    
      
  //CurDelay = 0;    
  StartPos = 0;    
  ParBit = 0; 
  ParCount = 0;    
      
  if (Parity != 0)    
   ParBit = 1;    
       
  TotalBits = 1+DataBits+StopBits+ParBit;       
       
  MaxDelay = Math.round(Frequency/(Speed/(TotalBits + 0.5)));    
  BitDelay = Frequency/Speed;    
/*   
  ReportOut("TotalBits:" + TotalBits.toString(10) + "\n");          
  ReportOut("Start reading channel:" +  iChannel.toString(10) + "\n");          
  ReportOut("Start front:" +  BkFront.toString(10) + "\n");          
  ReportOut("Start level:" +  LoSynLevel.toString(10) + "\n");          
  ReportOut("Max delay:" +  MaxDelay.toString(10) + "\n");          
*/        
  for (CurPos = 0, iData = 0; CurPos < TotalSize; iData++)    
  {    
   StartPos = SynchBy(iChannel, BkFront, LoSynLevel, CurPos, TotalSize);      
   Data = 0;    
 
   if (Parity == 1)    
    ParCount = 1;    
 
   //ReportOut("Pos:" +  StartPos.toString(10) + "\n");          
       
   if (StartPos > 0 && (StartPos + MaxDelay) < TotalSize)    
   {    
    //SetMarker(StartPos, "Start detected");    
     
    for (iBit = 0; iBit < DataBits; iBit++)    
    {    
     CurPos = StartPos + Math.round((1+iBit+0.5)*BitDelay);    
     CurValue = ValueAt(iChannel, CurPos);    
     Data >>= 1;    
         
     if(GetBit(CurValue, HiSynLevel)) 
     { 
      Data |= 0x80;    
      ParCount++;    
     } 
    }    
 
    if (Parity != 0)    
    {    
     CurPos = StartPos + Math.round((1+DataBits+0.5)*BitDelay);    
     CurValue = ValueAt(iChannel, CurPos);    
      
     if (GetBit(CurValue, HiSynLevel)) 
      ParCount++;    
    }    
        
    for (iBit = 0; iBit < StopBits; iBit++)    
    {    
     CurPos = StartPos + Math.round((1+DataBits+ParBit+iBit+0.5)*BitDelay);    
     CurValue = ValueAt(iChannel, CurPos);    
         
     if(!GetBit(CurValue, HiSynLevel))    
     {    
      ReportOut("Канал:" + iChannel.toString(10) + " ошибка стоп бита\n");          
      SetMarker(CurPos, "Error stop bit");    
      return 0;    
     }    
    }    
        
    //CurPos = Math.round(CurPos + BitDelay);    
    DataArray[iData] = Data;    
    PosArray[iData] = StartPos;    
    SetMarker(StartPos, StrPrefix + " 0x" + Data.toString(16) + CodeToChar( Data ));    
   }    
   else    
    break;    
     
   //ReportOut("Cur Pos:" + CurPos.toString(10) + "\n");          
  }    
      
  ReportOut("Канал:" + iChannel.toString(10) + " анализ завершен\n");          
  return -1;    
 }    
     
 function GetBit( Value, HiLevel)    
 {    
  if (HiLevel > 0)    
   return (Value >= HiLevel); 
  else     
   return (Value <= HiLevel); 
 }    
    
 function NumArrayToString( DataArray )          
 {          
  var strOutput = "";    
      
  for (i = 0; i < DataArray.length; i++)    
  {    
   strOutput += DataArray[i].toString(10);    
    
   if (i < (DataArray.length-1))    
    strOutput += "\n";    
  }    
      
  return strOutput;    
 }    
    
 function StrArrayToString( DataArray )          
 {         
  var strOutput = "";    
      
  for (i = 0; i < DataArray.length; i++)    
  {    
   strOutput += DataArray[i];    
    
   if (i < (DataArray.length-1))    
    strOutput += "\n";    
  }    
      
  return strOutput;    
 } 
  
 function CodeToChar( Data ) 
 { 
  if (Data >= 0x20 && Data < 0x0FF ) 
   return " - \'" + String.fromCharCode(Data) + "\'"; 
    
  return " - \'\'"; 
 }