⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lists.c

📁 profibus-dp主站源代码
💻 C
字号:
//-----------------------------------------------------------------------------
// $Id: lists.c,v 1.0.0                                             2004/01/13
//-----------------------------------------------------------------------------
//
//      ProfiM - PROFIBUS MASTER DRIVER FOR WINDOWS NT/2000
//
// Author:  
//      Pavel Trnka, CTU FEE
//      trnkap@seznam.cz
// With help and advices from:
//      Ing. Petr Smolik, CTU FEE
//      Ing. Pavel Pisa, CTU FEE
//      Ing. Pavel Burget, CTU FEE
//
//-----------------------------------------------------------------------------
//
// Popis:
// ------
// Definuje seznamy LAS a GAP pro Profibus.
//
// Vyznam seznamu LAS a GAP:
// -------------------------
//
//  LAS - ke kazde adrese (v celem rozsahu adres 0..HSA) uvadi jestli je:
//          Active - aktivni master v logickem podilejici se na predavani
//                   tokenu
//          Passive - stanice nepripojena, stanice typu slave nebo stanice
//                    typu master, ktera jeste neni v zaclenena logickemu
//                    ringu masteru predavajicich si token
//        LAS se aktualizuje s kazdym obehem tokenu (z datoveho toku na sbernici).
//
//  GAP - je mnohem konkretnejsi nez LAS, ale je udrzovan pouze pro adresy
//        v rozsahu TS+1..NS-1 (pro mono-master system ovsem pro cely
//        adresni prostor)
//        Stavy:
//           Slave
//           MasterNotReady
//           Unused
//        Cely se zaktualizuje vzdu az po nekolika obezich tokenu a to
//        podle hodnoty koeficientu G (priblizne po G*(pocet stanic mezi
//        TS a NS) )
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

#include "NTDDK.H"

#include "lists.h"
#include "vardef.h"


//*****************************************************************************

void LAS_Init( PTLAS LAS, int size )
{
  LAS->length = size;
  LAS_Clear( LAS );
  LAS->NewState = Stop;
  LAS->LastActive = -1;
}

//*****************************************************************************

void LAS_Close( PTLAS LAS )
{
}


//*****************************************************************************
//**  Zajistuje update LASu po jeho vytvoreni
//**
//*****************************************************************************

void LAS_Update( PTLAS LAS, int adr )
{
  int i;
  if ( adr < LAS->length && adr != LAS->LastActive )
  {
    LAS->LAS[adr] = LAS_Active;
    if ( adr > LAS->LastActive )
      for ( i = LAS->LastActive + 1; i < adr; i++ )
        LAS->LAS[i] = LAS_Passive;
    else
    {
      for ( i = LAS->LastActive + 1; i < LAS->length; i++ )
        LAS->LAS[i] = LAS_Passive;
      for ( i = 0; i < adr; i++ )
        LAS->LAS[i] = LAS_Passive;
    }
    LAS->LastActive = adr;
  }
}


//*****************************************************************************
//**  Vola se pri vytvareni LASu, pokud je master ve stavu Listen_Token.
//**  Vrati true pokud pridavane stanice vytvorili dva identicke cykly.
//**
//*****************************************************************************

int LAS_CreatingAdd( PTLAS LAS, int adr )
{
  int i;

  if ( adr < LAS->length )
  {
    LAS->LastActive = adr;  // pozor - spis by mel byt na konci

    if ( LAS->NewState == Stop )
    {
      LAS->NewState = First_Cycle;
    }
    if ( LAS->NewState == Done )
    {
      LAS_Clear( LAS );
      LAS->NewState = First_Cycle;
    }

    if ( LAS->LAS[adr] == LAS_Active )
    {
      if ( LAS->NewState == Second_Cycle )
      {
        int Equal = 1;
        for ( i = 0; i < LAS->length; i++ )
          Equal *= ( LAS->TestLAS[i] == LAS->LAS[i] );
        if ( Equal )                      // Oba pruchody jsou stejne
        {
          LAS->NewState = Done;
          return TRUE;
        }
        else                            // Pruchody se lisi
        {
          LAS->NewState = Second_Cycle;
          for ( i = 0; i < LAS->length; i++ )
            LAS->TestLAS[i] = LAS->LAS[i];
          LAS_Clear( LAS );
        }
      }
      if ( LAS->NewState == First_Cycle )
      {
        for ( i = 0; i < LAS->length; i++ )
          LAS->TestLAS[i] = LAS->LAS[i];
        LAS_Clear( LAS );
        LAS->NewState = Second_Cycle;
      }
    }

    LAS->LAS[adr] = LAS_Active;
  }
  return FALSE;
}

//*****************************************************************************

void LAS_Clear( PTLAS LAS )
{
  int i;
  if ( LAS->length > 1 )
    for ( i = 0; i < LAS->length; i++ )
      LAS->LAS[i] = LAS_Passive;
}

//*****************************************************************************

int LAS_Complete( PTLAS LAS )
{
  return ( LAS->NewState == Done );
}


//*****************************************************************************
//**  Vraci adresu predchoziho mastera k TS podle LASu. Pokud neexistuje
//**  tak vraci TS.
//**
//**  Predchozi stanice PS podle aktualniho LAS - nikoliv podle Mastera.
//**
//*****************************************************************************

int LAS_PreviousStation( PTLAS LAS, int TS )       
{
  /*
  int i;
  if ( TS < LAS->length )
  {
    if ( TS > 0 )
      for ( i = TS - 1; i >= 0; i-- )
        if ( LAS->LAS[i] == LAS_Active )
          return i;
    if ( TS < LAS->length - 1 )
      for ( i = LAS->length - 1; i > TS; i-- )
        if ( LAS->LAS[i] == LAS_Active )
          return i;
  }
  */
  
  int i;  
  
  if ( TS < 0 || TS >= LAS->length )
    return 0;   // TS ma chybnou hodnotu 
  
  i = TS-1;
  if ( i < 0 )
    i = LAS->length - 1;  

  while ( LAS->LAS[i] != LAS_Active && i != TS )  
  {  
    i--;
    if ( i < 0 )
      i = LAS->length - 1;      
  }
  
  if ( LAS->LAS[i] == LAS_Active )
    return i;  
    
  return TS;      // zadna jina aktivni stanice v LAS neni
}


//*****************************************************************************
//**  Vraci adresu mastera mastera k TS podle LASu. Pokud neexistuje
//**  tak vraci TS.
//**
//**  Nasledujici stanice PS podle aktualniho LAS - nikoliv podle Mastera.
//**
//*****************************************************************************

int LAS_NextStation( PTLAS LAS, int TS )       
{
  /*
  int i;
  if ( TS < LAS->length )
  {
    if ( TS < LAS->length - 1 )
      for ( i = TS + 1; i < LAS->length; i++ )
        if ( LAS->LAS[i] == LAS_Active )
          return i;
    if ( TS > 0 )
      for ( i = 0; i < TS; i++ )
        if ( LAS->LAS[i] == LAS_Active )
          return i;
  }
  */
  
  int i;
  
  if ( TS < 0 || TS >= LAS->length )
    return 0;   // TS ma chybnou hodnotu
  
  i = TS+1;
  if ( i >= LAS->length )
    i = 0;  

  while ( LAS->LAS[i] != LAS_Active && i != TS )  
  {  
    i++;
    if ( i >= LAS->length )
      i = 0;
  }
  
  if ( LAS->LAS[i] == LAS_Active )
    return i;  
  
  return TS;      // zadna jina aktivni stanice v LAS neni
}


//*****************************************************************************
//**  Prevede LAS na retezec - vypise ty adresy, kterym odpovida aktivni
//**  master.
//**
//*****************************************************************************

/*
Z puvodni verze - neprevedeno

String TLAS::ToString()
{
        String  S="";
        for (int i=0; i<length; i++)
         if (LAS[i]==LAS_Active) S+=" "+IntToStr(i);
          else S+="  ";

        return S;
}
*/

//*****************************************************************************
//**  Vymaze vsechny zaznamy aktivnich stanic mezi TS a PS (pro PS<TS i PS>TS)
//**
//*****************************************************************************

void LAS_VymazStanice( PTLAS LAS, int TS, int PS )
{
  int i;
  if ( PS < TS )
  {
    for ( i = PS + 1; i < TS; i++ )
      LAS->LAS[i] = LAS_Passive;
  }
  else if ( PS > TS )
  {
    for ( i = 0; i < TS; i++ )
      LAS->LAS[i] = LAS_Passive;
    for ( i = PS + 1; i < LAS->length; i++ )
      LAS->LAS[i] = LAS_Passive;
  }
  else  // PS=TS
  {
    LAS_Clear( LAS );
    LAS->LAS[TS] = LAS_Active;             // snad OK - zalezi odkud se mazani TS,TS vola
  }
}


//*****************************************************************************
//**  Vola se pri Claim_Token - master je na sbernici sam.
//**
//*****************************************************************************

void LAS_NoStations( PTLAS LAS )
{
  LAS_Clear( LAS );
  LAS->NewState = Done;
}




//*****************************************************************************
//*****************************************************************************
//*****************************************************************************




//*****************************************************************************
//**  Inicializce GAPListu - dulezite predani adresy TS
//**
//*****************************************************************************

void GAPL_Init( PTGAPL GAPL, int _length, int _TS )
{
  GAPL->length = _length;
  GAPL->TS = _TS;
  GAPL->NS = -1;
  GAPL_Clear( GAPL );
  GAPL->LastTested = GAPL->TS;  // pristi testovanou tak bude nasledujici po TS
}

//*****************************************************************************

void GAPL_Close( PTGAPL GAPL )
{
}

//*****************************************************************************

void GAPL_Clear( PTGAPL GAPL )
{
  int i;
  for ( i = 0; i < GAPL->length; i++ )
  {
    GAPL->GAPL[i].StationState = GAP_Unused;
    GAPL->GAPL[i].FCV = FALSE;
    GAPL->GAPL[i].FCB = TRUE;
  }
}


//*****************************************************************************
//**  Zajisti aby dalsi testovanou stanici z GAPL byla TS+1
//**
//*****************************************************************************

void GAPL_RestartTest( PTGAPL GAPL )
{
  GAPL->LastTested = GAPL->TS;  // pristi testovanou tak bude nasledujici po TS
}

//*****************************************************************************

void GAPL_UpdateNS( PTGAPL GAPL, int _NS )
{
  GAPL->NS = _NS;
}


//*****************************************************************************
//**  Vybere z GAPu adresu dalsi stanice, ktera by se mela testovat dotazem
//**  FDL Status.
//**  Opetovne volani vrati uz dalsi adresu.
//**
//*****************************************************************************

int GAPL_NextToTest( PTGAPL GAPL )
{
  int next;
  
  if ( (GAPL->TS+1 == GAPL->NS) ||
       ((GAPL->TS == GAPL->length-1) && (GAPL->NS==0)) )
  {
    //
    // mezi TS a NS nelezi zadne stanice
    //
    return -1;   
  }
  
  next = GAPL->LastTested + 1;
  
  if ( next >= GAPL->length - 1 )
    next = 0;
      
  if ( next == GAPL->NS )
    next = GAPL->TS + 1;
    
  if ( next == GAPL->TS )
    next = GAPL->TS + 1;  
   
/*  
  //
  // je-li master na sbernici sam - potom NS=-1, spis NS=TS
  //

  
  if ( GAPL->NS > GAPL->TS )              
  {
    if ( GAPL->LastTested < ( GAPL->NS - 1 ) )
      next = GAPL->LastTested + 1;
    else
      next = GAPL->TS + 1;
  }
  else
  {
    if ( GAPL->LastTested >= GAPL->TS )                 // i = ???
    {
      if ( GAPL->LastTested >= GAPL->length - 1 )
        next = 0;
      else
        next = GAPL->LastTested + 1;
    }
    else
    {
      if ( GAPL->LastTested == GAPL->TS - 1 )
        next = GAPL->TS + 1;
      else
        next = GAPL->LastTested + 1;
    }
  }
*/

  return next;
}


//*****************************************************************************
//**  Ulozi do GAPu aktualizovany stav stanice na adrese adr. A zaznamena jeji
//**  adresu jako posledni testovanou.
//**
//*****************************************************************************

void GAPL_Update( PTGAPL GAPL, int adr, TGAPState _StationState )
{
  //        if ( adr!=NextToTest() ) ToByNemeloNastat !!!
  if ( adr >= 0 && adr < GAPL->length )
  {
    GAPL->GAPL[adr].StationState = _StationState;

    GAPL->LastTested = adr;
  }
}


//*****************************************************************************
//** Invertuje FCB
//** Pokud je FCV==false predpoklada, ze doslo k vyslani prvni ramce s urcenim
//** pocatecni hodnoty FCB a tak nastavuje FCV=true
//**
//*****************************************************************************

void GAPL_FCBToggle( PTGAPL GAPL, int adr )
{
  if ( !GAPL->GAPL[adr].FCV )
    GAPL->GAPL[adr].FCV = TRUE;
  GAPL->GAPL[adr].FCB = !GAPL->GAPL[adr].FCB;  // nemusi tady fungovat
}

//*****************************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -