// =====================================================================
//  $Id: software.cc,v 1.3 2003/10/06 04:03:39 goiwai Exp $
//  $Name: CLDAQ-1-14-03 $
//  $Log: software.cc,v $
//  Revision 1.3  2003/10/06 04:03:39  goiwai
//  TArgumentを使用するように全てのプログラムを修整しました.
//
//  Revision 1.2  2003/07/30 16:21:39  goiwai
//  ファイルにコミットログをつけることにしました.
//
// =====================================================================
#include "TDataRecord.hh"
#include "TReadoutList.hh"
#include "TReadoutSection.hh"
#include "TReadoutSegment.hh"
#include "TSoftwareAdcModule.hh"
#include "TSoftwareRunInformationModule.hh"
#include "TSoftwareClockModule.hh"
#include "TSoftwareScalerModule.hh"
#include "TSoftwareDataFileModule.hh"
#include "TSoftwareTdcModule.hh"
#include "TSoftwareFlashAdcModule.hh"
#include "TSoftwareTimerModule.hh"
#include "TSoftwareModule.hh"
#include "TSoftwareInterruptRegisterModule.hh"
#include "TOutputObjectFile.hh"
#include "TRunInformationTable.hh"
#include "TRunInformation.hh"
#include "TRunInformationList.hh"
#include "TBenchmark.hh"
#include "TOption.hh"
#include "TOptionTable.hh"
#include "TArgument.hh"

int main( int argc, char** argv, char** envv )
{
  TOption opev( "number-of-events", 1 );
  TOption opof( "output-record-name", 1 );
  const Tint noption = 2;
  TOption options[ noption ] = { opev, opof };
  TArgument arg( argc, argv, TOptionTable( options, noption ) );

  Tint nevent = 10;
  if ( arg.HasOption( opev ) ) {
    nevent = arg.GetIntegerParameter( opev );
  }

  Tstring filename = "software.drec";
  if ( arg.HasOption( opof ) ) {
    filename = arg[ opof ];
  }

  TOutputObjectFile ofile( filename );
  Tint datasize = 0;
  Tint nevents = 0;

  TSoftwareAdcModule adc;

  TstringList selectlist;
  selectlist.push_back( "SOURCE RUN" );
  selectlist.push_back( "DARK RUN" );
  selectlist.push_back( "TEST RUN" );
  selectlist.push_back( "DUMMY RUN" );
  TRunInformationList infolist;
  infolist.push_back( TRunInformation( "OPERATOR", tInfoFreeValue ) );
  infolist.push_back( TRunInformation( "RUN TYPE", selectlist ) );
  infolist.push_back( TRunInformation( "COMMENT", tInfoFreeText ) );
  TRunInformationTable table( infolist );
  TSoftwareRunInformationModule runinfo( table );

  TSoftwareClockModule clock;
  TSoftwareScalerModule scaler;
  const Tstring datafile = "sample.g4dat";
  const Tint nchannel = 2;
  TSoftwareDataFileModule g4module( datafile, nchannel );
  TSoftwareFlashAdcModule fadc;
  TSoftwareTimerModule timer;
  TSoftwareInterruptRegisterModule ir;

  Tstring adcelementid[ 16 ] =
  {
    "channel 0", "channel 1", "channel 2", "channel 3",
    "channel 4", "channel 5", "channel 6", "channel 7",
    "channel 8", "channel 9", "channel 10", "channel 11",
    "channel 12", "channel 13", "channel 14", "channel 15"
  };

  TReadoutList list( "This is a readout list." );
  TReadoutSection sec0( "This section is for run information." );
  TReadoutSection sec1( "This section is for software modules." );
  TReadoutSegment seg0( &scaler, "Scaler" );
  TReadoutSegment seg1( &runinfo, "Run information" );
  TReadoutSegment seg2( &clock, "Clock" );
  TReadoutSegment seg3( &timer, "Timer" );
  TReadoutSegment seg4( &adc, adcelementid, "ADC" );
  TReadoutSegment seg5( &fadc, "Flash ADC" );
  TReadoutSegment seg6( &g4module, "Geant4 production" );
  TReadoutSegment seg7( &ir, "Interrupt Register" );
  sec0.push_back( seg0 );
  sec0.push_back( seg1 );
  sec0.push_back( seg2 );
  sec0.push_back( seg3 );
  sec1.push_back( seg4 );
  sec1.push_back( seg5 );
  sec1.push_back( seg6 );
  sec1.push_back( seg7 );
  list.push_back( sec0 );
  list.push_back( sec1 );

  scaler.Initialize();
  clock.Initialize();
  timer.Initialize();
  adc.Initialize();
  fadc.Initialize();
  g4module.Initialize();
  ir.Initialize();
  ir.SetInterruptMaskRegister( 0x0000 );
  // ex) mask: 0x00fe -> register: 0 - 0x0001
  // ex) mask: 0x0002 -> register: 0x0000, 0x0001, 0x0003 - 0x00ff
  // ex) mask: 0x0006 -> register: 0x0000, 0x0001, 0x0004 - 0x00ff

  adc.Update();
  fadc.Update();
  g4module.Update();

  TBenchmark bench;
  bench.Start();
  for ( Tint i = 0; i < nevent; i ++ ) {
    TDataRecord record = list.Read();
    ofile << record;
    datasize += record.GetRecordSize();
    nevents ++;

    scaler.Update();
    adc.Update();
    fadc.Update();
    g4module.Update();
    ir.Update();
  }
  bench.Stop();
  Tcout << bench << Tendl;

  Tcout << nevents << " events, ";
  Tcout << datasize << Tslash << ofile.GetTotalDataSize();
  Tcout << " byte data has been written down " << filename << "." << Tendl;

  return 0;
}
