Ignore:
Timestamp:
01/23/03 13:32:58 (22 years ago)
Author:
tbretz
Message:
*** empty log message ***
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/MagicSoft/Cosy/candrv/nodedrv.cc

    r1703 r1727  
    3333//  virtual void StopDevice()
    3434//  virtual void HandleSDO(WORD_t idx, BYTE_t subidx, LWORD_t val, timeval_t *tv)
    35 //  virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx)
     35//  virtual void HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv)
    3636//  virtual void HandleSDOError(LWORD_t data)
    3737//  virtual void HandlePDO1(BYTE_t *data, timeval_t *tv)
     
    4848#include <iostream.h>
    4949
     50#include <TTimer.h>
     51
     52#include "base/timer.h"
    5053#include "network.h"
    5154#include "MLogManip.h"
     
    7679    }
    7780
     81    fTimerOn = kFALSE;
     82    fTimeout = new TTimer(this, 100, kFALSE); // 100ms, asynchronous
     83
    7884    lout << "- Node #" << (int)nodeid << " (" << name << ") initialized." << endl;
    79 }
    80 
    81 // --------------------------------------------------------------------------
    82 //
    83 // Empty destructor
     85
     86}
     87
     88// --------------------------------------------------------------------------
     89//
     90// destructor
    8491//
    8592NodeDrv::~NodeDrv()
    8693{
     94    fTimerOn = kFALSE;
     95    delete fTimeout;
    8796}
    8897
     
    122131    EnableCanMsg(kSDO_RX);
    123132    EnableCanMsg(kSDO_TX);
     133    EnableCanMsg(kNodeguard);
     134    EnableCanMsg(kEMERGENCY);
    124135
    125136    fIsZombie = kFALSE;
     
    135146// This output is never redirected to the GUI
    136147//
    137 void NodeDrv::HandleSDOOK(WORD_t idx, BYTE_t subidx)
     148void NodeDrv::HandleSDOOK(WORD_t idx, BYTE_t subidx, timeval_t *tv)
    138149{
    139150    const Bool_t gui = lout.IsOutputDeviceEnabled(MLog::eGui);
     
    367378// --------------------------------------------------------------------------
    368379//
    369 // Send an NMT message (command) to this device
     380// Send a NMT message (command) to this device
    370381//
    371382// The message is not send if the node has the status Zombie.
     
    377388        fNetwork->SendNMT(fId, cmd);
    378389    return !fIsZombie;
     390}
     391
     392// --------------------------------------------------------------------------
     393//
     394// Send a Nodeguard message (command) to this device
     395//
     396void NodeDrv::SendNodeguard()
     397{
     398    fNetwork->SendNodeguard(fId);
    379399}
    380400
     
    404424
    405425    if (!rc)
     426    {
     427        lout << "NodeDrv::WaitForSdo: 0x" << hex << idx << "/" << dec << (int)subidx << " " << GetNodeName() << " --> ZOMBIE!" << endl;
     428        SetZombie();
     429    }
     430/*
     431    if (HasError())
     432    {
     433        lout << "NodeDrv::WaitForSdo: HasError 0x" << hex << idx << "/" << dec << (int)subidx << " " << GetNodeName() << " --> ZOMBIE!" << endl;
    406434        fIsZombie = kTRUE;
    407 
     435    }
     436*/
    408437    return fIsZombie ? false : rc;
    409438}
     
    453482}
    454483
     484// --------------------------------------------------------------------------
     485//
     486// Start the standard CANopen guarding of the device.
     487// While ms is the guard time in millisec. This is the time between
     488// two requests for a Nodeguard message.
     489// ltf is the LifeTimeFactor. This means how often it is checked, that at
     490// least one Nodeguard message was answered.
     491//
     492void NodeDrv::StartGuarding()
     493{
     494    if (fTimerOn)
     495        return;
     496
     497    SendNodeguard();
     498
     499    fTimerOn = kTRUE;
     500    fTimeout->SetTime(fGuardTime);
     501    fTimeout->Reset();
     502    fTimeout->TurnOn();
     503    //fTimeout->Start(fGuardTime, kTRUE);
     504
     505    lout << "- " << GetNodeName() << ": Guarding (" << dec;
     506    lout << fLifeTimeFactor << "*" << fGuardTime << "ms) started." << endl;
     507}
     508
     509void NodeDrv::StartGuarding(Int_t ms, Int_t ltf)
     510{
     511    if (fTimerOn)
     512    {
     513        lout << "- " << GetNodeName() << ": ERROR - Guarding already started." << endl;
     514        return;
     515    }
     516    fGuardTime      = ms;
     517    fLifeTimeFactor = ltf;
     518
     519    StartGuarding();
     520}
     521
     522void NodeDrv::StopGuarding()
     523{
     524    fTimeout->TurnOff();
     525    fTimerOn = kFALSE;
     526
     527    lout << "- " << GetNodeName() << ": Guarding stopped." << endl;
     528}
     529
     530// --------------------------------------------------------------------------
     531//
     532// Handle the Nodeguard-Timer Event.
     533// It checks whether the node timed out. If it timed out it is set to
     534// the Zombie state.
     535// A new Nodeguard request is send and a new timer event is triggered.
     536//
     537Bool_t NodeDrv::HandleTimer(TTimer *t)
     538{
     539    //
     540    // WARNING:
     541    //           It seems, that you should never access ANY output from
     542    //           here. Neither the GUI, nor COUT. This can result in
     543    //           'unexpected async reply'
     544    //
     545
     546   /*
     547     Fons:
     548     -----
     549
     550     timers never trigger at the same time or when in a TTimer::Notify.
     551     Little explanation:
     552
     553     - there are two types of timers synchronous and a-synchronous.
     554     - synchronous timers are only handled via the ROOT eventloop
     555       (see TUnixSystem::DispatchOneEvent()). If there are no mouse/keyboard
     556       events then the synchronous timer queue is checked. So if the processing
     557       of a mouse/keyboard event takes a long time synchronous timers are not
     558       called for a while. To prevent this from happening one can call in long
     559       procedures gSystem->ProcessEvents(). The system schedules only the
     560       next timer in the queue when the current one's Notify() has finished.
     561     - a-synchronous timers are triggered via SIGALARM, i.e. the program is
     562       interupted and execution jumps to the Notify() function. When the
     563       notify is finished the next a-sync timer is scheduled and the system
     564       resumes from the place where it was initially interrupted. One of the
     565       things to remember when using a-sync timers is don't make any graphics
     566       calls in them. X11 is not re-entrant and it might be that the SIGALARM
     567       signal interrupted the system while being in X11. A-sync timers are best
     568       used to set flags that you can test at a convenient and controlled
     569       time.
     570       */
     571    if (fIsZombie)
     572        return kTRUE;
     573
     574    Timer time;
     575    Double_t now = time.Now();
     576    if (now > fTimeoutTime)
     577    {
     578        //cout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
     579        //lout << "ERROR - " << GetNodeName() << " didn't respond in timeout window." << endl;
     580        //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(now, 500) << endl;
     581        //cout << dec << "+" << (int)GetId() << ": Handle: " << fmod(fTimeoutTime, 500) << endl;
     582        //cout << fGuardTime << endl;
     583        fIsZombie = true;
     584        //SetZombie();
     585
     586        return kTRUE;
     587    }
     588
     589    SendNodeguard();
     590
     591    return kTRUE;
     592}
     593
     594// --------------------------------------------------------------------------
     595//
     596// Set the timeout timer to the time the event was received plus the
     597// guard time times lifetimefactor.
     598//
     599void NodeDrv::HandleNodeguard(timeval_t *tv)
     600{
     601    Timer t(tv);
     602    fTimeoutTime = t + (fGuardTime*fLifeTimeFactor/1000.);
     603}
     604
     605void NodeDrv::SetZombie()
     606{
     607    fIsZombie = true;
     608    StopGuarding();
     609}
Note: See TracChangeset for help on using the changeset viewer.