// DDC control 
//123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456*/
//===================================-======================================*/
//                         DDC STATE & DATA CONTROL                         */
//-----------------------------------=--------------------------------------*/
//   AUTHORs:        P.Ferrari & Heidi Sandaker
//
//   DESIGN ISSUEs: Clock Select
//
//   MODIF_HISTORY:  
//                   08.01.2004 -  H.Sandaker P.Ferrari
//                   14.07.2004 -  P W Phillips - rewritten with handshake
//                   20.07.2004 -  inhibit operation during Env. Alarm  PWP
//
//                   
//===================================-======================================*/

main()
{ 
  DebugN("Started ChangeClock script");
  dpConnect("clockSelect",FALSE, "ChangeClock.trigger:_original.._value");
}


void clockSelect(string triggerPath, bool trigger) {

   dyn_string para_split;

   int i, crate, select, ack;
   int channel, start, stop, dummy;
   
   string parameters, channelPath, sendCmdPath, recvAckPath;
   string allChannels;
   

   // If the trigger bit is not set, quit now! (This should never happen...)
   if (trigger!=1){
     return;
   }
   
   // Must not change clock if environmental alarm in progress
   dpGet("Fatl.Numb:_original.._value",fatal);
   if(fatal!=0){
      dpSet("Info.Name:_original.._value", "ChangeClock: Request Denied due to Environment Alarm (code "+fatal+")");
      DebugN("ChangeClock: Request Denied due to Environment Alarm (code "+fatal+")");
      return;     
   }


   //Get Parameters from DAQ
   dpGet("ChangeClock.parameters:_original.._value", parameters);
  
   //The format of the parameters send by DDC is Crate|Channel|Select
   para_split=strsplit(parameters,"|");
 
   sscanf(para_split[1],"%d", crate);
   sscanf(para_split[2],"%s", allChannels);
   sscanf(para_split[3],"%d", select);

   
   dpSet("Info.Name:_original.._value", "ChangeClock: triggered for crate " + crate + " chan " + allChannels + " select " + select);
   DebugN("ChangeClock: triggered for crate " + crate + " chan " + allChannels + " select " + select);

   if (allChannels == "all") {
      start = 0;
      stop = 47;
      channel = 0x3ff;
   } else {
      sscanf(para_split[2],"%d",channel);
      start = channel;
      stop = channel;
      channel += 0x300;
   }


   // Change the value of the LVchCLKS datapoint for the requested channel(s)
   for (i==start; i<=stop; i++) {
      sprintf(channelPath,"Crate%02d.Channel%02d.LVchCLKS.Send:_original.._value",crate, i);
      dpSet(channelPath,select);
   }
   delay(1);
      
      
   sprintf(sendCmdPath,"Crate%02d.Controller.CCch_Set.Send:_original.._value",crate);
   sprintf(recvAckPath,"Crate%02d.Controller.CCcf_Ack.Recv:_online.._value",crate);


   // Test the water - is CC Ack set to a value that may break our handshake?
   dpGet(recvAckPath,ack);
   
   i=0;
   if(ack==channel){
      // The CC ack code gives the expected answer before our command has been sent
      // - we force it to another value by sending a command to another channel

      if(channel == 0x300){
        dummy = 0x301;
      }else{
        dummy = 0x300;
      }
      dpSet(sendCmdPath, dummy);
   
      while ((ack!=dummy)&&(i<30)) {
         delay(1);
         dpGet(recvAckPath,ack);
         i++;
      }
   }


   // Now send the real command!

   dpSet(sendCmdPath, channel);
   
   while ((ack!=channel)&&(i<60)) {
      delay(1);
      dpGet(recvAckPath,ack);
      i++;
   }

   
   if(ack==channel){  

      // Now read all monitored parameters
      // (necessary for use during harness testsing, may be removed later)
      
      sprintf(sendCmdPath,"Crate%02d.Controller.CCchRead.Send:_original.._value",crate);
      
      // DebugN("ChangeClock: Reading monitored values after change of SELECT line");
      for(channel=start; channel<stop;channel++){
         //read LV
         dpSetWait(sendCmdPath,channel);
         delay(0,100);
      }
   
      //return success (0 means success)
      DebugN("ChangeClock: success in " + (2*i) + " seconds");
      dpSet("Info.Name:_original.._value", "ChangeClock: success in " + (2*i) + " seconds");
      dpSet("ChangeClock.response:_original.._value", 0);
      
   } else {   
      //return failure
      DebugN("ChangeClock: failure in " + (2*i) + " seconds");
      dpSet("Info.Name:_original.._value", "ChangeClock: failure in " + (2*i) + " seconds");
      dpSet("ChangeClock.response:_original.._value", 1);
   }
  
}