📄 lists.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 + -