// =====================================================================
//  $Id: TSoftwareInterruptRegisterModule.cc,v 1.4 2004/03/07 10:30:31 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: TSoftwareInterruptRegisterModule.cc,v $
//  Revision 1.4  2004/03/07 10:30:31  goiwai
//  ROOTに組みこむためのおまじないマクロを埋めこみました。
//  全てにおいて完全に動作するわけではありません。
//
//  Revision 1.3  2003/10/06 17:02:40  goiwai
//  *** empty log message ***
//
//  Revision 1.2  2003/07/30 16:19:11  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TSoftwareInterruptRegisterModule.hh"
#include "TDataSegment.hh"
#include "TDataElement.hh"
#include "TRandomFlat.hh"
#include "TRandomEngine.hh"

static TRandomEngine _engine = TRandomEngine( ( (Tlong)time( 0 ) ) );
static TRandomFlat _register( _engine );
static TRandomFlat _nanosec( _engine );
static const Tint initmask = 0x00ff;
static const Tint initscale = 0x00ff;

TSoftwareInterruptRegisterModule::TSoftwareInterruptRegisterModule( Tint nch, Tint frequency )
  : TSoftwareModule( nch ), 
    theInterruptRegister( 0 ), theInterruptMaskRegister( initmask ), 
    theFrequency( frequency )
{;}

TSoftwareInterruptRegisterModule::TSoftwareInterruptRegisterModule( const TSoftwareInterruptRegisterModule& right )
  : TSoftwareModule( right ),
    theInterruptRegister( 0 ),
    theInterruptMaskRegister( right.theInterruptMaskRegister ),
    theFrequency( right.theFrequency )
{;}

TSoftwareInterruptRegisterModule::~TSoftwareInterruptRegisterModule()
{;}

const TSoftwareInterruptRegisterModule& TSoftwareInterruptRegisterModule::operator=( const TSoftwareInterruptRegisterModule& right )
{
  *( (TSoftwareModule*)this ) = *( (TSoftwareModule*)(&right) );
  theInterruptMaskRegister = 0;
  theInterruptMaskRegister = right.theInterruptMaskRegister;
  theFrequency = right.theFrequency;
  return *this;
}

Tbool TSoftwareInterruptRegisterModule::operator==( const TSoftwareInterruptRegisterModule& right ) const
{
  Tbool retval = Ttrue;
  retval &= ( *( (TSoftwareModule*)this ) == *( (TSoftwareModule*)(&right) ) );
  retval &= ( theInterruptMaskRegister == right.theInterruptMaskRegister );
  retval &= ( theFrequency == right.theFrequency );
  return retval;
}

Tbool TSoftwareInterruptRegisterModule::operator!=( const TSoftwareInterruptRegisterModule& right ) const
{
  Tbool retval = Tfalse;
  retval |= ( *( (TSoftwareModule*)this ) != *( (TSoftwareModule*)(&right) ) );
  retval |= ( theInterruptMaskRegister != right.theInterruptMaskRegister );
  retval |= ( theFrequency != right.theFrequency );
  return retval;
}

Tvoid TSoftwareInterruptRegisterModule::FillData( TDataElement& element, Tint channel )
{
  if ( channel < 0 || channel >= theNumberOfChannels ) {
    Tcerr << "TSoftwareInterruptRegisterModule::FillData: invalid ID " << channel << Tendl;
    theStatus = -EFAULT;
    element.FillData( &theStatus, tTypeInt, 1 );
  } else if ( channel == 0 ) {
    element.FillData( &theInterruptRegister, tTypeInt, 1 );
  } else if ( channel == 1 ) {
    element.FillData( &theInterruptMaskRegister, tTypeInt, 1 );
  } else {
    // status filled
    theStatus = -EFAULT;
    ( (TDataElement*)(&element) ) -> FillData( &theStatus, tTypeInt, 1 );
  }
  return;
}

Tint TSoftwareInterruptRegisterModule::Clear()
{
  theInterruptRegister = 0;
  return theStatus = tStatusSuccess;
}

Tint TSoftwareInterruptRegisterModule::Update()
{
  theInterruptRegister = _register.fireInt( initscale );
  theInterruptRegister &= ~theInterruptMaskRegister;
  return theStatus = tStatusSuccess;
}

Tint TSoftwareInterruptRegisterModule::Initialize()
{
  theInterruptRegister = 0;
  theInterruptMaskRegister = initmask;
  theFrequency = 1;
  return theStatus = tStatusSuccess;
}

Tint TSoftwareInterruptRegisterModule::ReadInterruptRegister()
{
  static struct timespec req;
  req.tv_sec = 0;
  req.tv_nsec = _nanosec.fireInt( 1000000000 / theFrequency );
  nanosleep( &req, 0 );
  Update();
  return theInterruptRegister;
}

#ifdef __CLDAQ_ROOT_DLL
    ClassImp(TSoftwareInterruptRegisterModule)
#endif
