#!/usr/bin/perl -w
###############################################################################
# D.Miskowiec, June 2000. DAQ control routines.
###############################################################################
use Tk;
use Tk::NoteBook;
use Term::ReadKey;
use Net::Telnet;

 Tk::CmdLine::SetResources('*font: -*-courier-*-r-*-*-12-*-*-*-*-*-*-*');
 Tk::CmdLine::SetResources('*background: #ffa050');
 Tk::CmdLine::SetResources('*background: wheat2');

$this_host = $ENV{"HOSTNAME"};
@this_host = split '\.', $this_host ;
$this_host = $this_host[0];
die "Run it on pcceres37, not on $this_host\n" unless ($this_host eq "pcceres37");

&initScript;
&initTk;
&loop;
MainLoop;
exit;

###############################################################################
sub initTk {
    $mw = new MainWindow(-fg => 'red');
    $mw->repeat(500, sub{&loop;} );

# common header

    $header = $mw->Frame()->pack(-fill => "x");
    $header->Label(-textvariable => \$now)->pack(-side => "left");
    $header->Button(-text => "exit", -command => sub {&endScript})->pack(-side => "right");

# NoteBook: pages of information:

    $nb = $mw->NoteBook();
    $cont = $nb->add("cont", -label => " run control     ");
    $ebst = $nb->add("ebst", -label => "eventb PC status ");
    $rlog = $nb->add("rlog", -label => "   run log       ");
    $blog = $nb->add("blog", -label => "  burst log      ");
    $init = $nb->add("init", -label => " init & config   ");

# individual pages: run control

    $cont_but = $cont->Frame()->pack(-padx => 20, -pady => 20);
    $cont_sta = $cont->Frame()->pack(-padx => 20, -pady => 10, -side => 'left');
#    $cont_noi = $cont->Frame()->pack(-padx => 20, -pady => 10, -side => 'left', -fill => 'y');
    $cont_exp = $cont->Frame()->pack(-padx => 20, -pady => 10, -side => 'right', -fill => 'y');
    $cont_run = $cont_sta->Frame()->pack(-fill => 'x', -pady => 10);

    $cont_but_tes = $cont_but->Button(-text => "start test run",    -command => sub {startRun("test")},
				      -width => 15)->pack(-side => "left");
    $cont_but_sta = $cont_but->Button(-text => "start regular run", -command => sub {startRun("regular")},
				      -width => 15)->pack(-side => "left");
    $cont_but_pau = $cont_but->Button(-text => "pause",             -command => sub {pauseRun()},
				      -width => 15)->pack(-side => "left");
    $cont_but_res = $cont_but->Button(-text => "resume",            -command => sub {resumeRun()},
				      -width => 15)->pack(-side => "left");
    $cont_but_sto = $cont_but->Button(-text => "stop run",          -command => sub {stopRun("stop")},
				      -width => 15)->pack(-side => "left");

    $cont_run->Label(-text => "run information", -justify => 'left', -fg => 'brown')->pack();
    tk_add_slice(\$cont_run, "run .................", \$run);
    tk_add_slice(\$cont_run, "status ..............", \$status);
    tk_add_slice(\$cont_run, "started on ..........", \$started_time);
    tk_add_slice(\$cont_run, "stopped on ..........", \$stopped_time);
    $cont_run->Label(-text => "\nthis run has:", -justify => 'left', -fg => 'brown')->pack();
    tk_add_slice(\$cont_run, "bursts ..............", \$coll_burst);
    tk_add_slice(\$cont_run, "good bursts .........", \$sent_burst);
    tk_add_slice(\$cont_run, "events ..............", \$runevents);
    tk_add_slice(\$cont_run, "MBytes ..............", \$runmbytes);
    tk_add_slice(\$cont_run, "events/good burst ...", \$evperburst);
    tk_add_slice(\$cont_run, "MBytes/good burst ...", \$mbperburst);
    $cont_run->Label(-text => "\nthis burst has:", -justify => 'left', -fg => 'brown')->pack();
    tk_add_slice(\$cont_run, "burst number ........", \$sent_burst);
    tk_add_slice(\$cont_run, "events ..............", \$burstevents);
    tk_add_slice(\$cont_run, "Mbytes ..............", \$burstmbytes);
    tk_add_slice(\$cont_run, "MBytes/event ........", \$mbperevent);

#    $cont_noi->Label(-text => "\n *** NOISE ***", -justify => 'left', -fg => 'brown')->pack();
#    $cont_noi->Button(-text => "   shut up    ", -command => sub {&shutup})->pack(-fill => 'x');
#    $cont_noi->Button(-text => "   volume -   ", -command => sub {&volume("-")})->pack(-fill => 'x');
#    $cont_noi->Button(-text => "   volume +   ", -command => sub {&volume("+")})->pack(-fill => 'x');

    $cont_exp->Label(-text => "*** EXPERT(S) ONLY ***", -fg => 'brown')->pack();
    $cont_exp->Checkbutton(-text => " DAQ busy  ", -variable => \$daq_busy, 
			   -command => sub {&flipDaqBusy})->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => " auto eob  ", -variable => \$auto_eob)->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => " auto evb  ", -variable => \$auto_evb)->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => " auto nep  ", -variable => \$auto_nep)->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => "auto sddfix", -variable => \$auto_sddfix)->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => "auto rchfix", -variable => \$auto_rchfix)->pack(-fill => 'x');
    $cont_exp->Checkbutton(-text => "auto tpcfix", -variable => \$auto_tpcfix)->pack(-fill => 'x');
    $cont_exp->Button(-text => "  manual eob  ", -command => sub {&handleEOB})->pack(-fill => 'x');
    $cont_exp->Button(-text => " getstat_ebpc ", -command => sub {&getstat_ebpc})->pack(-fill => 'x');
    $cont_exp->Button(-text => " zero daqmems ", -command => sub {&zero_daqmems})->pack(-fill => 'x');
    $cont_exp->Button(-text => " reset export ", -command => sub {&reset_export})->pack(-fill => 'x');
    $cont_exp->Button(-text => "    sddfix    ", -command => sub {&sddfix})->pack(-fill => 'x');
    $cont_exp->Button(-text => "   richfix    ", -command => sub {&rchfix})->pack(-fill => 'x');
    $cont_exp->Button(-text => "    tpcfix    ", -command => sub {&tpcfix})->pack(-fill => 'x');

    tk_add_slice(\$cont_exp, "burst ...............", \$now_burst);
    tk_add_slice(\$cont_exp, "noburst .............", \$now_noburst);
    tk_add_slice(\$cont_exp, "min_events ..........", \$min_nevents);
    tk_add_slice(\$cont_exp, "next_ebpc_please ....", \$next_ebpc_please);
    tk_add_slice(\$cont_exp, "next_ebpc......",       \$next_ebpc);
    tk_add_slice(\$cont_exp, "last_ebpc......",       \$last_ebpc);

# individual pages: event builder PC status

    $ebst_but = $ebst->Frame()->pack(-padx => 20, -pady => 40);
    $ebst_sta = $ebst->Frame()->pack(-padx => 20, -pady => 20);
    foreach $host (@ebpc) {
	$ebst_but->Checkbutton(-text => "$host", 
			       -variable => \$ebpc_enabled{$host}, 
			       -command => sub {&save_ebpc_list})->pack(-padx => 10, side => 'left');
    }
    $ebst_sta->Label(-justify => 'left', -textvariable => \$ebpc_dump)->pack(-padx => 20, -pady => 20);

# individual pages: run log

    $rlog_lab  = $rlog->Frame()->pack(-pady => 10);
    $rlog_lab->Label(-text => "run log file")->pack(-side => "left");
    $rlog_lab->Label(-textvariable => \$runlogfile)->pack(-side => "left");
    $rlog_scry = $rlog->Scrollbar(-orient => "vertical")->pack(-side => "right", -fill => "y");
    $rlog_text = $rlog->Text(-wrap => "none", -yscrollcommand => ['set' => $rlog_scry])->pack(-fill => 'x');
    $rlog_scry->configure(-command => ['yview' => $rlog_text]); 

# individual pages: burst log

    $blog_lab  = $blog->Frame()->pack(-pady => 10);
    $blog_lab->Label(-text => "burst log file")->pack(-side => "left");
    $blog_lab->Label(-textvariable => \$burstlogfile)->pack(-side => "left");
#    $blog_head = $blog->Frame()->pack(-expand => 1, -pady => 1);
#    $blog_head->Label(-text => "        date                run  gburst  burst events       bytes")
#	->pack(-side => "left");
    $blog_scry = $blog->Scrollbar(-orient => "vertical")->pack(-side => "right", -fill => "y");
    $blog_text = $blog->Text(-wrap => "none", -yscrollcommand => ['set' => $blog_scry])->pack(-fill => 'x');
    $blog_scry->configure(-command => ['yview' => $blog_text]); 

# individual pages: init

    tk_add_buts(\$init,"SD init camdelay","rsh o-ceres07 /os9/SIDC/CMDS/set_delay",                                                           2, 0, 0);
    tk_add_buts(\$init,"SD init scanners","rsh wppc1 -l online \"scrun s 16 1\"",                                                             2, 0, 1);
    tk_add_buts(\$init,"SD init recvrs  ","rsh o-ceres05 \"chx /os9/PADMEN/CMDS; chd /os9/PADMEN/MH; sddinit -csr -init -active=1 -edge=1\"", 2, 0, 2);
    tk_add_buts(\$init,"  RICH 1 rdelay ","rsh o-ceres08 \"chx /os9/PADMEN/CMDS;clearlocalrun;r_delay rich1 -lx -disp -ripple=0 -setclk\"",   2, 2, 0);
    tk_add_buts(\$init,"  RICH 2 rdelay ","rsh o-ceres08 \"chx /os9/PADMEN/CMDS; clearlocalrun; r_delay rich2 -lx -disp -ripple=0 -setclk\"", 2, 4, 0);
    tk_add_butr(\$init," RICH 1 newpeds ","rich_pedestals1",                                                                                  2, 2, 1);
    tk_add_butr(\$init," RICH 2 newpeds ","rich_pedestals2",                                                                                  2, 4, 1);
    tk_add_buts(\$init,"RICH 1 init     ","rsh o-ceres08 \"chx /os9/PADMEN/CMDS; clearlocalrun; initrun rich1 -puls=0 -zsup=1\"",             1, 2, 2);
    tk_add_buts(\$init,"RICH 2 init     ","rsh o-ceres08 \"chx /os9/PADMEN/CMDS; clearlocalrun; initrun rich2 -puls=0 -zsup=1\"",             1, 4, 2);
    tk_add_buts(\$init,"RICH 1 init puls","rsh o-ceres08 \"chx /os9/PADMEN/CMDS; clearlocalrun; initrun rich1 -puls=2 -zsup=1\"",             1, 3, 2);
    tk_add_buts(\$init,"RICH 2 init puls","rsh o-ceres08 \"chx /os9/PADMEN/CMDS; clearlocalrun; initrun rich2 -puls=2 -zsup=1\"",             1, 5, 2);
    tk_add_buts(\$init," kill collector ","rsh $cpc_ropc killer.pl collector",                                                                6, 0, 3);
    tk_add_butr(\$init,"     getIt      ","getIt",                                                                                            6, 0, 4);
    tk_add_butr(\$init,"start collector ","start_cpci_collector",                                                                             6, 0, 5);
#    tk_add_buts(\$init,"   TPC init     ","TPCinit",                                                                                          2, 6, 0);
    tk_add_buts(\$init,"                ","rsh pcceres5 \"/data/noise/snowb </dev/null &>/dev/null &\"",                                      2, 6, 0);
    tk_add_butr(\$init,"  TPC newpeds   ","tpc_pedestals",                                                                                    2, 6, 1);
    tk_add_butr(\$init,"     resman     ","resman",                                                                                           2, 6, 2);
    tk_add_butr(\$init," kill collectors","kill_tpc_collectors",                                                                              2, 6, 3);
    tk_add_butr(\$init,"     vxiclean   ","vxiclean",                                                                                         2, 6, 4);
    tk_add_butr(\$init,"start collectors","start_tpc_collectors",                                                                             1, 6, 5);
    tk_add_butr(\$init,"  start fakers  ","startFakers",                                                                                      1, 7, 5);
    tk_add_buts(\$init,"                ","/usr/games/fortune",                                                                               2, 8, 0);
    tk_add_buts(\$init,"                ","/usr/games/fortune",                                                                               2, 8, 1);
    tk_add_buts(\$init,"                ","/usr/games/fortune",                                                                               2, 8, 2);
    tk_add_buts(\$init," kill collector ","rsh $gri_ropc killer.pl collector",                                                                2, 8, 3);
    tk_add_buts(\$init," init PVIC gril ","rsh $gri_ropc pvic.pcceres16",                                                                     2, 8, 4);
    tk_add_butr(\$init,"start collector ","start_gril_collector",                                                                             2, 8, 5);

# pack it all:

    $nb->pack();

# open log files for reading

    open RUNLOG_R,"<$runlogfile" or die ("Could not open $runlogfile\n");
    
# enable and disable buttons

    &enableButtons;

}
#==============================================================================
sub tk_add_butr {        # add a button on a grid, $com is subroutine reference
    (scalar(@_) >= 3) or die "but1 needs 3 arguments\n";
    my $parent = $_[0];  # pointer to parent
    my $label  = $_[1];  # label string
    my $com    = $_[2];  # command
    my $height = $_[3];  # height, 1 or 2
    my $row    = $_[4];
    my $column = $_[5];
    my $but = $$parent->Button(-text => $label, 
			       -command => sub {$com->()});
    $but->grid(-rowspan=>$height, -row=>$row, -column=>$column, -sticky=>'ns');
}
#==============================================================================
sub tk_add_buts {              # add a button on a grid, command is system $com
    (scalar(@_) >= 3) or die "but1 needs 3 arguments\n";
    my $parent = $_[0];  # pointer to parent
    my $label  = $_[1];  # label string
    my $com    = $_[2];  # command
    my $height = $_[3];  # height, 1 or 2
    my $row    = $_[4];
    my $column = $_[5];
    my $but = $$parent->Button(-text => $label, 
			       -command => sub {printf "$com\n";system($com)});
    $but->grid(-rowspan=>$height, -row=>$row, -column=>$column, -sticky=>'ns');
}
#==============================================================================
sub tk_add_slice {  # make a horiz. slice in parent, containing label and value
    (scalar(@_) >= 3) or die "tk_add_slice needs 3 arguments\n";
    my $parent = $_[0];  # pointer to parent
    my $label  = $_[1];  # label string
    my $value  = $_[2];  # pointer to variable
    my $label2 = $_[3] || "";
    my $col    = $_[4] || "black";
    $slice = $$parent->Frame()->pack(-fill => 'x', -side => 'top');
    $slice->Label(-fg => $col, -text => $label)        ->pack(-side => 'left');
    $slice->Label(-fg => $col, -textvariable => $value)->pack(-side => 'left');
    $slice->Label(-fg => $col, -text => $label2)       ->pack(-side => 'left');
}
#==============================================================================
sub enableButtons {
    if ($status eq "started") {
	$cont_but_tes->configure(-state => "disabled");
	$cont_but_sta->configure(-state => "disabled");
	$cont_but_pau->configure(-state => "normal");
	$cont_but_res->configure(-state => "disabled");
	$cont_but_sto->configure(-state => "normal");
    }
    if ($status eq "paused") {
	$cont_but_tes->configure(-state => "disabled");
	$cont_but_sta->configure(-state => "disabled");
	$cont_but_pau->configure(-state => "disabled");
	$cont_but_res->configure(-state => "normal");
	$cont_but_sto->configure(-state => "normal");
    } 
    if ($status eq "stopped") {
	$cont_but_tes->configure(-state => "normal");
	$cont_but_sta->configure(-state => "normal");
	$cont_but_pau->configure(-state => "disabled");
	$cont_but_res->configure(-state => "disabled");
	$cont_but_sto->configure(-state => "disabled");
    }
}
###############################################################################
sub volume {
    my $what = $_[0] || return;
    if ($what eq '-') {
	printf "lowering volume\n";
	system "rsh pcceres5 \"aumix -v -20 </dev/null &>/dev/null &\" ";
    } 
    if ($what eq '+') {
	printf "rising volume\n";
	system "rsh pcceres5 \"aumix -v +20 </dev/null &>/dev/null &\" ";
    }

}
#==============================================================================
sub play {
    my $song = $_[0] || return;
    my $start = $_[1] || 0;
    my $duration = $_[2] || 10000;
    $song = "/data/noise/".$song.".mp3";
    printf "playing $song: $duration frames from frame $start\n";
    system "rsh pcceres5 \"mpg123 -k $start -n $duration $song </dev/null &>/dev/null &\" ";
}
#==============================================================================
sub shutup {
    printf "shut up\n";
    system "rsh pcceres5 \"/data/noise/shutup </dev/null &>/dev/null &\"";
}
###############################################################################
sub loop {

# update global variables

    $now = localtime();
    $daq_busy = &isDaqBusy;

    $evperburst = "";
    $mbperburst = "";
    if ($sent_burst > 0) {
	$evperburst = sprintf("%0.2f",$runevents/$sent_burst);
	$mbperburst = sprintf("%0.2f",$runmbytes/$sent_burst);
    }
    if ($burstevents>0) {
	$mbperevent = sprintf("%0.2f",$burstmbytes/$burstevents);
    }

# update run log and burst log display

    seek(RUNLOG_R, 0, 1);
    seek(BURSTLOG_R, 0, 1);
    while (<RUNLOG_R>) {
	$rlog_text->configure(-state => 'normal');
	$rlog_text->insert('end',$_);
	$rlog_text->see('end');
	$rlog_text->configure(-state => 'disabled');
    }
    while (<BURSTLOG_R>) {
	$blog_text->configure(-state => 'normal');
	$blog_text->insert('end',$_,'normal');
	$blog_text->see('end');
	$blog_text->configure(-state => 'disabled');
    }

# cdr status and next ebpc

    if ($next_ebpc_please) {
	&getstat_ebpc;
	$next_ebpc_please = 0;
    }

# burst detection

    my $pc36pattern = `pc36 -r`;
    my @pc36pattern = split ' ',$pc36pattern;
    $now_burst   = $pc36pattern[0];
    $now_noburst = $pc36pattern[1];    
    if ($old_now_burst >= 0) {  # first time does not work
	my $startOfBurst = $now_burst && !$old_now_burst;
	my $endOfBurst = !$now_burst && $old_now_burst;
	my $startOfNoburst = $now_noburst && !$old_now_noburst;
	my $endOfNoburst = !$now_noburst && $old_now_noburst;
#	if ($startOfBurst)   {printf "start of burst\n";}
#	if ($endOfBurst)     {printf "end of burst\n";}
#	if ($startOfNoburst) {printf "start of noburst\n";}
#	if ($endOfNoburst)   {printf "end of noburst\n";}
	if ($startOfNoburst && $auto_eob) {&handleEOB;}
#	if ($startOfBurst)   {&getstat_ebpc;}
    }
    $old_now_burst   = $now_burst;
    $old_now_noburst = $now_noburst;
}
###############################################################################
sub initScript  {

# define names of the logfiles and scripts

    $runlogfile          = "/home/daq/log/runs.log";
    $burstlogfile_prefix = "/home/daq/log/run";
    $burstlogfile_sufix  = ".log";
    $sorgenhost          = "na45pc12";
    $sorgenscript        = "/cdrShare01/cerescdr/cdr2k/scripts/makeSOR.pl";
    $ebscript            = "/cdrShare01/cerescdr/cdr2k/evb/doEvb.pl";
    $recescript          = "/cdrShare01/cerescdr/scripts/start_receivers";
    $ebpclistfile        = "/home/daq/runctrl/ebpclist.txt";
    $killerlogfile       = "/home/daq/log/killer.log";
    $sddfixlogfile       = "/home/daq/log/sddfix.log";
    $rchfixlogfile       = "/home/daq/log/rchfix.log";
    $tpcfixlogfile       = "/home/daq/log/tpcfix.log";


# global variables

#    $run;
#    $status;
#    $daq_busy = ...

#    $coll_burst;
#    $sent_burst;
#    $runevents;
#    $runmbytes;

    $evperburst = "";
    $mbperburst = "";
    $burstevents = 0;
    $burstbytes = 0;
    $burstmbytes = 0.00;
    $auto_eob = 0;
    $auto_evb = 0;
    $auto_nep = 0;
    $auto_sddfix = 0;
    $auto_rchfix = 0;
    $auto_tpcfix = 0;
    $ropc_dump = "";
    $ebpc_dump = "";
    $next_ebpc = "none";
    $last_ebpc = "none2";
    $min_nevents = 10; # minimum number of events required in a good burst; 
                       # burst with less events will not be exported to CDR
    $old_now_burst = -1;
    $old_now_noburst = -1;
    $sddfix_tries = 0;
    $rchfix_tries = 0;
    $tpcfix_tries = 0;

# define names of the readout PCs

    $cpc_ropc = pcceres12;
    $gri_ropc = pcceres16;
    @tpc_ropc = qw(
		 pcceres41
		 pcceres42
		 pcceres43
		 pcceres44
		 pcceres45
		 pcceres46
		 pcceres47
		 pcceres48
		 );
    
    @vme_ropc = (@tpc_ropc, $gri_ropc);
    @all_ropc = (@vme_ropc, $cpc_ropc);
    &read_ebpc_list;
    @all_machines = (@all_ropc, @ebpc, "na45pc01");

# Check if the remote machines are pingable

    printf "Checking availability of machines:\n";
    my $missing = 0;
    foreach $host (@all_machines) {
	my $stat = `ping -c 1 $host 2>&1 |grep "1 packets received" | wc -l`;
	chomp $stat;
	if ($stat == 0) {$missing++;}
	printf "$host $stat\n";
    }
    if ($missing > 0) {
	printf "$missing missing; bombing\n";
	exit;
    } else {
	printf "all strategic machines are pingable\n";
    }

# Open telnet sessions to the ropc and ebpc machines

    foreach $host (@all_ropc) {
	$telnet{$host} = new Net::Telnet (Prompt => '/\[daq.*daq\]\$/', Host => $host);
	$telnet{$host}->timeout(30);
	$telnet{$host}->cmd_remove_mode(1);
	$telnet{$host}->errmode("return");
	$ok = $telnet{$host}->login("daq","dackel");
	$telnet{$host}->errmode("die");
	unless (defined $ok) {
	    printf "Login to $host failed ... trying one more time.\n";
	    $telnet{$host}->close();
	    $telnet{$host}->open();
	    $telnet{$host}->login("daq","dackel");
	}
	printf "telnet session to $host opened\n";
    }
    
    foreach $host (@ebpc) {
	$telnet{$host} = new Net::Telnet (Prompt => '/\[na45pc.*\/home\/cerescdr \>/', Host => $host);
	$telnet{$host}->timeout(30);
	$telnet{$host}->cmd_remove_mode(1);
	$telnet{$host}->errmode("return");
	$ok = $telnet{$host}->login("cerescdr","cer/na45");
	$telnet{$host}->errmode("die");
	unless (defined $ok) {
	    printf "Login to $host failed ... trying once more time.\n";
	    $telnet{$host}->close();
	    $telnet{$host}->open();
	    $telnet{$host}->login("cerescdr","cer/na45");
	}
	printf "telnet session to $host opened\n";
    }

    &getRun;
    &reopenBurstlogfile("old");    
    &getBurst;    
    &zero_daqmems;

    $auto_nep = 1;
    $next_ebpc_please = 1;
    &getstat_ebpc;
    $auto_nep = 0;
    $next_ebpc_please = 0;
}
###############################################################################
sub endScript {
    my @hostlist = (@all_ropc, @ebpc);
    foreach $host (@hostlist) {
	$telnet{$host}->close;
	printf "telnet session to $host closed\n";
    }
    exit;
}
###############################################################################
sub getIt {
    &play("money", 250, 44);
    system "rsh $cpc_ropc getIt < /home/daq/runctrl/getIt.inp &";
    system "rsh $cpc_ropc \" killer.pl getIt \" ";
}
###############################################################################
sub resman {
    &vxiclean;
    system "mlaunch.pl \"resman\" @tpc_ropc";
}
###############################################################################
sub vxiclean {
    system "mlaunch.pl \"vxiclean\" @tpc_ropc";
}
###############################################################################
sub kill_tpc_collectors {
    system "mlaunch.pl \"killer.pl collector\" @tpc_ropc";
    &vxiclean;
}
###############################################################################
sub start_tpc_collectors {
    &vxiclean;
    system "mlaunch.pl \"silent.pl tpc_collector\" @tpc_ropc";
    sleep 6;
}
###############################################################################
sub startFakers {
    system "mlaunch.pl \"silent.pl fake_collector\" @tpc_ropc";
}
###############################################################################
sub start_cpci_collector {
    system "rsh $cpc_ropc silent.pl cpci_collector";
    printf "\n";
    sleep 2;
}
###############################################################################
sub start_gril_collector {
    system "rsh $gri_ropc silent.pl gril_collector";
    printf "\n";
    sleep 2;
}
###############################################################################
sub rich_pedestals1 {
    printf "Taking pedestals for rich1. Be patient.\n";
    &play("rich_man", 1030);
    $remcom = "chx /os9/PADMEN/CMDS; ";
    $remcom .= "clearlocalrun; ";
    $remcom .= "fixthres rich1 -pedval=0; ";
    $remcom .= "vorspiel rich1 -newpeds";
    printf "rsh o-ceres08 \"$remcom\"\n";
    system "rsh o-ceres08 \"$remcom\"";
    &shutup;
}
#==============================================================================
sub rich_pedestals2 {
    printf "Taking pedestals for rich2. Be patient.\n";
    &play("rich_man", 4720);
    $remcom = "chx /os9/PADMEN/CMDS; ";
    $remcom .= "clearlocalrun; ";
    $remcom .= "fixthres rich2 -pedval=0; ";
    $remcom .= "vorspiel rich2 -newpeds";
    printf "rsh o-ceres08 \"$remcom\"\n";
    system "rsh o-ceres08 \"$remcom\"";
    &shutup;
}
###############################################################################
sub tpc_pedestals {
    my $key;
    if ($status ne "stopped") {
	printf "please stop the run before taking TPC pedestals\n";
	return;
    }
    system "rm -f /home/daq/TPC/Pedestals";
    system "ln -s /home/daq/TPC/Pedestals_zero /home/daq/TPC/Pedestals";
    &kill_tpc_collectors;
    &vxiclean;
    system "setThreshold 0";
    &setDaqBusy;
    &start_tpc_collectors;

    ReadMode 'cbreak';
    while (ReadKey(-1)) {;}
    printf "please remember the current trigger settings\n";
    printf "please enable MT out-of-burst and disable other triggers\n";
    printf "please lower the MT downscaling (for example set it to 9)\n";
    printf "please press any key when done\n";
    $key = ReadKey(0);
    ReadMode 'normal';
    printf "OK, going on\n";

    system "mwrite.pl \"run 1000\" /dev/daqctrl @all_ropc";
    system "mwrite.pl \"burst 0\" /dev/daqctrl @all_ropc";

    printf "how many bursts you want to use to warm up the TPC?\n";
    printf "recommended number is between 5 (if warm) and 30 (if cold)\n";
    my $n = 4;
    my $iter = 0;
    while (1) {
	$iter++;
	$n = <STDIN>;
	chomp $n;
	$n = $n+0;
	if ($n>0) {last;}
	if ($iter==1) {printf "positive numerical value, please\n";}
	if ($iter>1) {printf "baby, tell me a positive number\n";}
    }
    &play("rawhide");
    for ($i=0; $i<$n+1; $i++) {
	$burstevents = 0;
	$sent_burst = 0;
	&zero_daqmems;
	&clearDaqBusy;
	if ($i<$n) {printf "warming up burst $i (requested $n)\n";}
	else {printf "now seriously taking data\n";}
	while (1) {
	    $mw->idletasks;
	    &dump_ropc;
	    printf "$burstevents events taken\n";
 	    if ($burstevents>=126) {last;}
	    sleep(2);
	} 
	&setDaqBusy;
    }
    $mw->idletasks;
    &shutup;
    printf "sending data to pcceres37\n";
    system "mlaunch.pl \"exporter.pl pcceres37\" @all_ropc";
    printf "please check the pedestals by starting 'Dataview' on pcceres37\n";
    while (1) {
	ReadMode 'cbreak';
	while (ReadKey(-1)) {;}
	printf " - are the pedestals OK? Press 'y' to accept or 'n' to cancel\n";
	$key = ReadKey(0);
	ReadMode 'normal';
	if ($key eq 'y') {last;}
	if ($key eq 'n') {last;}
    }
    printf "OK, going on\n";
    $mw->idletasks;
    if ($key eq 'y') {
	printf "starting TPCpedestals...\n";
	system "TPCpedestals 2.5 1";
	printf "TPCpedestals done.\n";
	system "ped_archiver";
	printf "starting Stability\n";
	system "Stability";
	printf "Stability done\n";
    }
    $mw->idletasks;
    system "rm -f /home/daq/TPC/Pedestals";
    system "ln -s /home/daq/TPC/Pedestals_true /home/daq/TPC/Pedestals";
    system "setThreshold 1";
    &kill_tpc_collectors;
    &vxiclean;
    &start_tpc_collectors;
    ReadMode 'cbreak';
    while (ReadKey(-1)) {;}
    printf "please restore the normal trigger settings\n";
    printf "please press any key when done\n";
    $key = ReadKey(0);
    ReadMode 'normal';
    printf "Thanks, baby. It was nice to interact with you. \a\n";
}
###############################################################################
sub zero_daqmems {
    printf "zeroing daqmems\n";
#    system "mlaunch.pl \"zero_daqmem.pl $sent_burst\" @all_ropc";
    system "mlaunch.pl \"zero_daqmem.pl $sent_burst\" @all_ropc </dev/null &>/dev/null";
}
###############################################################################
sub zero_daqmems_t {
    printf "zeroing daqmems via telnet\n";
    foreach $host (@all_ropc) {
	$telnet{$host}->print("zero_daqmem.pl $sent_burst");
    }
    foreach $host (@all_ropc) {
	my $matchop = $telnet{$host}->prompt;
#	$telnet{$host}->waitfor($matchop);
	$telnet{$host}->waitfor('/daqmem reset/');
    }
}
###############################################################################
sub reset_export {
    system "date >> $killerlogfile";
    foreach $host (@all_ropc) {
	$telnet{$host}->buffer_empty;
    }
    system "mlaunch.pl \"killer.pl daqmem_sender\" @all_ropc | tee -a $killerlogfile";
    system "mlaunch.pl \"-l cerescdr /cdrShare01/cerescdr/scripts/kill_receivers\" @ebpc";
    system "mlaunch.pl \"-l cerescdr /cdrShare01/cerescdr/scripts/killer.pl /cdr2k/evb/evb \" @ebpc";
    foreach $host (@ebpc) {
	system "rsh -l cerescdr $host \"rm -f /cdrShare01/cerescdr/cdr2k/evb/sta/$host\" ";
    }
}
###############################################################################
sub dump_ropc {    
    my $host;
    my $stat;
    my $buf = `mlaunch.pl \"head -n 1 /dev/daqctrl\" @all_ropc`;
    my @bufrow = split '\n',$buf;
    my $nbufrow = @bufrow;

# for each readout PC, extract number of collected events and bytes

    $burstevents = 0;
    $burstbytes = 0.00;
    for (my $i=0; $i<$nbufrow; $i++) {
	my @line = split ' ',$bufrow[$i];
	my $events = $line[4];
	my $bytes = $line[5];
	if ($events > $burstevents) {$burstevents = $events;}
	$burstbytes += $bytes;
    }
    $burstmbytes = sprintf("%.2f",$burstbytes/1048576);
    $ropc_dump = $buf;
}
###############################################################################
sub read_ebpc_list {
    open EBPCLIST,"<$ebpclistfile" or die ("Could not open $ebpclistfile\n");
    while (<EBPCLIST>) { 
	(my $host, my $enabled) = split ' ',$_;
	push(@ebpc, $host);
	$ebpc_enabled{$host} = $enabled;
    }
    close EBPCLIST;
}
#==============================================================================
sub save_ebpc_list {
    my $host;
    open EBPCLIST,">$ebpclistfile" or die ("Could not open $ebpclistfile\n");
    foreach $host (@ebpc) {printf EBPCLIST "$host $ebpc_enabled{$host}\n";}
    close EBPCLIST;    
}
#==============================================================================
sub getstat_ebpc {
    my $host;
    my $eb_status_line;
    my $eb_status;
    my @free_ebpcs;
    my @best_ebpcs;
    my $command;
    my $buf;
    my $n;
    my $ntap;

# scan the eb machines
    
    $ebpc_dump = "Event builder status:\n\n";
    $command = "rsh -l cerescdr $ebpc[0] \" ";
    foreach $host (@ebpc) {$command .= "echo $host; cat /cdrShare01/cerescdr/cdr2k/evb/sta/$host 2>&1; ";}
    $command .= " \" ";
    $buf = `$command`;
    my @bufrow = split '\n',$buf;
    my $nbufrow = @bufrow;
    for (my $i=0; $i<$nbufrow; $i+=2) {
	$host = $bufrow[$i];
	$eb_status_line = $bufrow[$i+1] || "no info available";
	$_ = $eb_status_line;
	($eb_out, $eb_status) = /(\w+).*(submitted|started|succeeded|failed|No such file).*/;
	$eb_out    ||= "unknown";    # set to "unknown" if undefined
	$eb_status ||= "unknown";    # set to "unknown" if undefined
	
# make list of free eb machines
	
	if ($ebpc_enabled{$host}) {
	    if ($eb_status eq "succeeded"   ) {push(@free_ebpcs, $host);}
	    if ($eb_status eq "failed"      ) {push(@free_ebpcs, $host);}
	    if ($eb_status eq "No such file") {push(@free_ebpcs, $host);}
	}

# prepare the eb status message to appear in the run control window
	
	chomp $eb_status_line;
	$ebpc_dump .= $host."  ";
	$ebpc_dump .= $eb_status."   (";
	$ebpc_dump .= $eb_status_line.")\n";
    }
    
    $ebpc_dump .= "\n";
    $ebpc_dump .= "Available machines:   ".(join " ",@free_ebpcs)."\n\n";
    
# make a list of machines with least taper processes

    $ebpc_dump .= "Taping status:\n\n";

    foreach $host (@ebpc) {
	$telnet{$host}->errmode("return");
	$telnet{$host}->print("echo tapers; ps ax | grep tpwrite | grep -v grep | wc -l");
    }
    foreach $host (@ebpc) {
	(my $pre, my $match) = $telnet{$host}->waitfor(Match => '/tapers\n.*[0-9]\n/', Timeout => 1);
	$telnet{$host}->errmode("die");
	my @tapers_list;
	my $taps;
	if ($match) {
	    @tapers_list = split '\n',$match;
	    $taps = $tapers_list[1];
	    chomp $taps;
	} else {
	    $taps = '      ?';
	}
	$tapers{$host} = $taps;
	print "$host $taps\n";
	$ebpc_dump .= "$host has $tapers{$host} taper processes running\n";
    }
    $ebpc_dump .= "\n";

    $ntap = 0;
#    for ($ntap = 0; $ntap < 6; $ntap++) {
#        foreach $host (@free_ebpcs) {
#	    if ($tapers{$host} == $ntap) {push(@best_ebpcs, $host);}
#	} 
#	if (scalar(@best_ebpcs) > 0) {last;}
#    }
#    $ebpc_dump .= "$ntap taper processes on @best_ebpcs\n\n";

    foreach $host (@free_ebpcs) {
	if ($tapers{$host} eq "      0") {push(@best_ebpcs, $host);}
    }

    $ebpc_dump .= "least taper processes on @best_ebpcs\n\n";
    if (scalar(@best_ebpcs) < 1) {@best_ebpcs = @free_ebpcs;}

#    if ($ntap > 3) {
#	print $ebpc_dump;
#	print "Event builder PC are too busy with taping, cannot send data.\n";
#	print "Call Dariusz.\n";
#	&endScript;
#    }

# propose one machine
    
    if ($auto_nep) {
	$n = @best_ebpcs;
	if ($n > 0) {
	    my $i = int rand ($n);
	    $next_ebpc = $best_ebpcs[$i];
	} else {
	    $next_ebpc = 'none';
	}
	$ebpc_dump .= "Next burst will go to $next_ebpc\n";
    }    
}
###############################################################################
sub isDaqBusy {
    my $pc36pattern = `pc36 -r`;
    my @pc36pattern = split ' ',$pc36pattern;
    $daq_busy = $pc36pattern[8];
    return $daq_busy;
}
#==============================================================================
sub setDaqBusy {
    system "pc36 -w 1";   # set DAQ busy
}
#==============================================================================
sub clearDaqBusy {
    system "pc36 -w 0";
}
#==============================================================================
sub flipDaqBusy {
    if ($daq_busy) {&setDaqBusy;}
    else {&clearDaqBusy};
}
###############################################################################
sub handleEOB {
    my $rate;
    &setDaqBusy; 
    printf "*** events collected in this burst:\n";
    &dump_ropc; 
    printf "$ropc_dump"; 
    $mw->idletasks;
    if ($burstevents >= $min_nevents && $burstevents < 600 
	&& $next_ebpc ne "none" && $next_ebpc ne $last_ebpc) {
	$last_ebpc = $next_ebpc;
	my $start = time();
	my $send_log = "/home/daq/log/send.log";
	printf "*** starting export of burst $sent_burst to $next_ebpc\n";

#	printf "stopping rfiod on $next_ebpc\n";
#	$telnet{$next_ebpc}->print("killer.pl rfiod 19");
#	$telnet{$next_ebpc}->print("rfiod_chiller.pl");

	printf "stopping collector on $cpc_ropc\n";
	$telnet{$cpc_ropc}->print("killer.pl collector 19");

#	system "rsh -l cerescdr $next_ebpc \"  $recescript  </dev/null &>/dev/null &\" ";
	printf "starting receivers on $next_ebpc\n";
	$telnet{$next_ebpc}->print("nohup $recescript > /dev/null");

#	system "mlaunch.pl \"daqmem_sender $next_ebpc\" @all_ropc < /dev/null &";
	foreach $host (@all_ropc) {
	    $telnet{$host}->print("daqmem_sender $next_ebpc");
	}
	printf "senders started\n";	

	&fix_busy_detectors;
	printf "busy checked\n";

	my $fifos = 0;
	my $diff = 0;
	while (1) {
	    $fifos = `rsh -l cerescdr $next_ebpc ls ebinp|wc -l`;
	    chomp $fifos;
	    printf "fifos $fifos\n";
	    $diff = time() - $start;
	    if ($fifos >= 10) {last;}
	    if ($diff > 25) {last;} 
	    sleep 1;
	}

#	printf "restarting rfiod on $next_ebpc\n";
#	$telnet{$next_ebpc}->print("killer.pl rfiod 18");

	printf "restarting collector on $cpc_ropc\n";
	$telnet{$cpc_ropc}->print("killer.pl collector 18");

	if ($fifos == 10) {
	    &logBurst("- burst sent to $next_ebpc");
	    $runevents += $burstevents;
	    $runmbytes += $burstmbytes;
	    if ($diff>0) {$rate = int($burstmbytes/$diff);}
	    else {$rate = '?';}
	    printf "$burstmbytes MB sent to $next_ebpc in $diff seconds ($rate MB/s)\n";
	    foreach $host (@all_ropc) {
		(my $prematch, my $match) = $telnet{$host}->waitfor('/\n.*bytes.*\n/');
		$match = substr $match, 1;
		chomp $match;
		print "$host:   $match\n";
	    }	
	    if ($auto_evb) {
		printf "starting event builder on $next_ebpc\n";
		my $ebstfile =  "/cdrShare01/cerescdr/cdr2k/evb/sta/$next_ebpc";
		my $ebstinfo = sprintf("%s %4d %4d %4d %d submitted", 
				       $next_ebpc, $run, $sent_burst, $burstevents, $burstmbytes);
		$telnet{$next_ebpc}->print("rm -f $ebstfile; echo $ebstinfo > $ebstfile");
		$telnet{$next_ebpc}->print("nohup $ebscript $run $sent_burst > /dev/null");
	    }
	    $sent_burst++;
	} else {
	    printf "timeout - killing\n";
	    &play("harmonica");
	    system "pc36 -w 129";
	    &logBurst("- burst killed on its way to $next_ebpc");
	    &reset_export;
#	    &getstat_ebpc;
	    system "pc36 -w 1";
	    &shutup;
	}
    } else {
	&fix_busy_detectors;
	&logBurst("- burst skipped");
	printf "*** burst with $burstevents events - skipped\n";
    }
    $next_ebpc_please = 1;
    $next_ebpc = 'none';

    &zero_daqmems_t;
    &clearDaqBusy;
    if ($sddfix_tries || $rchfix_tries || $tpcfix_tries) {&shutup;}
    $coll_burst++;

    printf "ready for new burst\n";
}
###############################################################################
sub fix_busy_detectors {
    printf "checking SDD, RICH, and TPC busy: \n";
    my $pc36pattern = `pc36 -r`;
    my @pc36pattern = split ' ',$pc36pattern;
    if ($pc36pattern[7]) {	
	printf "SDD  is busy\n";
	if ($auto_sddfix and ($sddfix_tries < 3)) {
	    printf "trying to fix it automatically\n";
	    &sddfix;
	} else {
	    printf "please fix it\n";
	    &play("karel_gott", 5924);
	    printf "please fix it\n";
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
	    sleep 1;
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
	    sleep 1;
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
#	    if ($status eq "started") {&pauseRun;}
	}
	$sddfix_tries++;
    } else {
	printf "SDD  is not busy\n";
	$sddfix_tries = 0;
    }
    my $pc36pattern = `pc36 -r`;
    my @pc36pattern = split ' ',$pc36pattern;
    if ($pc36pattern[4] | $pc36pattern[5]) {	
	printf "RICH is busy\n";
	if ($auto_rchfix and ($rchfix_tries < 3)) {
	    printf "trying to fix it automatically\n";
	    &rchfix;
	} else {
	    printf "please fix it\n";
	    &play("rich_man", 0, 100);
#	    if ($status eq "started") {&pauseRun;}
	    sleep 1;
	}
	$rchfix_tries++;
    } else {
	printf "RICH is not busy\n";
	$rchfix_tries = 0;
    }
    if ($pc36pattern[6]) {	
	printf "TPC  is busy\n";
	if ($auto_tpcfix and ($tpcfix_tries < 3)) {
	    printf "trying to fix it automatically\n";
	    &tpcfix;
	} else {
	    printf "please fix it\n";
	    &play("astral");
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
	    sleep 1;
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
	    sleep 1;
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
	    sleep 1;
	    system "pc36 -w 129";
	    sleep 1;
	    system "pc36 -w 1";
#	    if ($status eq "started") {&pauseRun;}
	}
	$tpcfix_tries++;
    } else {
	printf "TPC  is not busy\n";
	$tpcfix_tries = 0;
    }
}
###############################################################################
sub sddfix {
    system "date >> $sddfixlogfile";
    system "rsh $cpc_ropc \"killer.pl collector\" ";    
#    system "rsh o-ceres05 \"chx /os9/PADMEN/CMDS; chd /os9/PADMEN/MH; sddinit -csr -init -active=1 -edge=1\"";
    &getIt;
    &getIt;
    &getIt;
    &start_cpci_collector;
}
#==============================================================================
sub rchfix {
    system "date >> $rchfixlogfile";
    system "rsh $cpc_ropc \"killer.pl collector\" ";    
    &getIt;
    &getIt;
    &getIt;
    &start_cpci_collector;
}
#==============================================================================
sub tpcfix {
    system "date >> $tpcfixlogfile";
    &kill_tpc_collectors;
    &vxiclean;
    &start_tpc_collectors;
}
###############################################################################
sub logRun {
    my $comment = "";
    if (scalar(@_)>0) {$comment = $_[0];}
    open RUNLOG,">> $runlogfile" or die ("Could not open $runlogfile\n");
    printf RUNLOG "$now run $run $status $comment\n";
    printf        "$now run $run $status $comment\n";
    close RUNLOG;
}
#==============================================================================
sub reopenBurstlogfile {
    close(BURSTLOG_R);
    $burstlogfile = "$burstlogfile_prefix".$run."$burstlogfile_sufix";
    if (!-e $burstlogfile) {
	printf "Creating $burstlogfile\n";
	open   BURSTLOG_R,">$burstlogfile" or die "Cannot open $burstlogfile\n";
	printf BURSTLOG_R "burst log file for run $run\n";
	close  BURSTLOG_R;
    }
    open BURSTLOG_R,"<$burstlogfile" or die "Cannot open $burstlogfile\n";
    if (defined $blog_text) {
	printf "cleaning\n";
	$blog_text->configure(-state => 'normal');
	$blog_text->delete('1.0', 'end');
	$blog_text->configure(-state => 'disabled');
    }
}
#==============================================================================
sub getRun {         # read runlogfile and figure out the actual run number etc.
    my $ttime;
    my $trun;
    my $tstatus;
    my $tcomment;
    my $last_regular_run = 1000;

    open RUNLOG,"tail -n 100 $runlogfile|" or die ("Could not open $runlogfile\n");
    while (<RUNLOG>) {
	($ttime,$trun,$tstatus) = 
	    /(.*2000)\s+run\b\s+(\b\w+)\s+(started|stopped|paused|resumed)\s+.*/;
	if (defined $trun) {
	    $run = $trun;
	    $status = $tstatus;
	    if ($status eq "started") {$started_time = $ttime;}
	    if ($status eq "stopped") {$stopped_time = $ttime;}
	    if ($run > $last_regular_run) {$last_regular_run = $run;}
	} else {
	    printf "unexpected entry in $runlogfile:\n";
	    printf $_;
	}
    }
    close RUNLOG;
    if ($status ne "stopped") {$stopped_time = "";}
    if ($status eq "resumed") {$status = "started";}
    return $last_regular_run;
}
#==============================================================================
sub logBurst {
    open BURSTLOG,">> $burstlogfile" or die ("Could not open $burstlogfile\n");
    my $line = sprintf("%s %6d %6d %6d %6d %12d", 
		       $now, $run, $sent_burst, $coll_burst, $burstevents, $burstbytes);
    printf BURSTLOG "$line $_[0]\n";
    close BURSTLOG;
}
#==============================================================================
sub getBurst {   # read burstlogfile and figure out the next burst number etc. 
    my $trun;
    my $tcoll_burst;
    my $tsent_burst;
    my $tevents;
    my $tbytes;
    $coll_burst = 0;
    $sent_burst = 0;
    $runevents = 0;
    $runmbytes = 0.00;

    open BURSTLOG,"<$burstlogfile" or die ("Could not open $burstlogfile\n");
    while (<BURSTLOG>) { 
	($trun, $tsent_burst, $tcoll_burst, $tevents, $tbytes) = 
	    /\.*2000\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)/;
	if (defined $trun) {
	    if ($tsent_burst>$sent_burst) {$sent_burst = $tsent_burst;}
	    if ($tcoll_burst>$coll_burst) {$coll_burst = $tcoll_burst;}
	    $runevents += $tevents;
	    $runmbytes += $tbytes;
	}
    }
    close BURSTLOG;
    $runmbytes = sprintf("%0.2f", $runmbytes/1048576);
    $burstevents = 0;
    $burstbytes = 0;
    $coll_burst++;
    $sent_burst++;
}
###############################################################################
sub startRun {
    $run_type = $_[0];
    die "usage: startRun(\"regular\"||\"test\")" unless (defined $run_type);
    
# set DAQ busy

    printf "startRun: setting DAQ busy...\n";
    &setDaqBusy;
    $auto_eob = 0;
    $auto_evb = 0;
    $auto_nep = 0;
    $auto_sddfix = 0;
    $auto_rchfix = 0;
    $auto_tpcfix = 0;
    printf "startRun: done\n";

# figure out the run type (regular or test) and run number

    if ($run_type eq "regular") {
	&play("ryde_of_the_valkyries", 50);
	$run = &getRun+1;
	# generate SOR file
	printf "startRun: generating SOR...\n";
	system "rsh -l cerescdr $sorgenhost $sorgenscript $run";
	printf "startRun: done\n";
    } else {
	play("strauss_polka", 50);
	$run = 1000;
	$status = "";
	$burstlogfile = "$burstlogfile_prefix".$run."$burstlogfile_sufix";
	system "rm $burstlogfile";
    }
    &reopenBurstlogfile("new");

# set global variables

    $status = "started";
    $stopped_time = "";
    $coll_burst = 0;
    $sent_burst = 0;
    $runevents = 0;
    $runmbytes = 0.00;

# set run and burst numbers, reset daqmems

    printf "startRun: resetting daqmems...\n";
    system "mwrite.pl \"run $run\" /dev/daqctrl @all_ropc";	
    &zero_daqmems;
    printf "startRun: done\n";

# log start of regular run

    printf "startRun: updating $runlogfile...\n";
    &logRun;
    printf "startRun: done\n";

# clear DAQ busy

    printf "startRun: clearing DAQ busy...\n";
    $auto_eob = 1;
    $auto_evb = 1;
    $auto_nep = 1;
    $auto_sddfix = 1;
    $auto_rchfix = 1;
    $auto_tpcfix = 1;
    &clearDaqBusy;
    printf "startRun: done\n";

# update run info; enable and disable buttons

    &getRun;
    &enableButtons;
    &shutup;
}
#==============================================================================
sub stopRun {
    $status = "stopping";
    $auto_eob = 0;
    $auto_evb = 0;
    $auto_nep = 0;
    $auto_sddfix = 0;
    $auto_rchfix = 0;
    $auto_tpcfix = 0;
    &setDaqBusy;
    $status = "stopped";
    logRun("with $runevents events $sent_burst bursts $runmbytes MB");
    &getRun;
    &enableButtons;
}
#==============================================================================
sub pauseRun {
    $status = "pausing";
    $auto_eob = 0;
    $auto_evb = 0;
    $auto_nep = 0;
    $auto_sddfix = 0;
    $auto_rchfix = 0;
    $auto_tpcfix = 0;
    &setDaqBusy;
    $status = "paused ";
    logRun("with $runevents events $sent_burst bursts $runmbytes MB");
    &getRun;
    &enableButtons;
}
#==============================================================================
sub resumeRun {
    $status = "resumed";
    &zero_daqmems;
    &logRun;
    &clearDaqBusy;
    $auto_eob = 1;
    $auto_evb = 1;
    $auto_nep = 1;
    $auto_sddfix = 1;
    $auto_rchfix = 1;
    $auto_tpcfix = 1;
    $status = "started";
    &getRun;
    &enableButtons;
}
###############################################################################
