www.pudn.com > PROFIBUS_DP_protocol_source.ZIP > lists.c, change:2004-03-17,size:12953b
//----------------------------------------------------------------------------- // $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 } //*****************************************************************************