/*********************************  iarc_controller.c ******************************/

globals
CArcPCIe *pArcDev = NULL;        // handle to ARC controller device driver
unsigned short *raw_data[10];    //  4 *  [100 x NAXIS1 x NAXIS2  * sizeof(short)] 

ic_open_device( int init_controller, char *dsp_filename ) called at application startup. 

   set default for iarc_setup.

   for( i=0; i<4; i++)
		raw_data[i] = malloc(100*2048*2048*sizeof(unsigned short));

   FindDevices()

	pArcDev = new CArcPCIe();

	pArcDev->Open()

   if( init_controller )    // note: default is 0.
		pArcDev->LoadControllerFile(dsp_filename, true);

		pArcDev->Command(TIM_ID, PON);  // POWER_ON

		pArcDev->Command(TIM_ID, GNL); or GNH   // GAIN_LOW or GAIN_HIGH 

   create thread: readout_permo_thread() 
   create thread: idh_data_handler_thread() 

   return 0

ic_close_device() called at application termination. 
	pArcDev->Close();
	pArcDev = NULL;

ic_init_controller( char *dsp_filename ) Called via "init"/ic_init() command.

   pArcDev->LoadControllerFile(dsp_filename, true);

	pArcDev->Command(TIM_ID, PON);

   ic_set_controller_state(READY);

ic_readout( ) .
   char *fn,                       // copied to iarc_setup.str_filename
   int ndr_cnt,                    // copied to iarc_setup.ndr_cnt
	int itime_ndr,                  // copied to iarc_setup.itime_ndrs
	int coadd,                      // copied to iarc_setup.n_coadd_count
	enum data_handling_mode_t dhm,  // copied to iarc_setup.dhm 
	int pixtime,                    // copied to iarc_setup.n_pixel_time
	int saveall,                    // Not used.
	int x, int y, int w, int h      // Not used.

   n_image_count = f( dhm, ndr_cnt, itime_ndr, coadd);  // cal image count

   // setup call backs.
	pArcDev->SetCallbacks(ReadoutCallback, ExposeCallback, FrameCallback);
	if(tdl_test(pArcDev) < 0)
	   error;

    update_controller_voltages(pArcDev); // queries controller bias and video board offset values. >
	 
	 update_fits_cards() - update a FITS data area.

	 iarc_setup.n_readout_number = 0;
	 
	 signal pth_cond_readout to continue readout_permo_thread()
	   This thread contines the readout, call of ic_readout() is the iarc_server so 
		it can go back serving the socket.

     return.


update_controller_voltages( ) Reads controller Bias voltages, and reads 32 Video Offset values.

   Data stored in
	   iarc_setup.voffset, vdd, vdda, vbg, vbp, vdsub, vrst
		iarc_setup.offset[0..32]. 

readout_permo_thread( ) Continue the readout started by ic_readout()
   while( 1 )
	{
	   blocks on pth_cond_readout - // signal by ic_readout()

		update_controller_voltages(pArcDev);   // queries controller bias and video board offset values
		update_fits_cards();                   // update a FITS data area

      // set gain
		if(iarc_setup.n_gain_flag == LOW_GAIN)
			pArcDev->Command(TIM_ID, GNL  
		else
			pArcDev->Command(TIM_ID, GNH);

      idh_start_data_handling() // signal pth_cond_data_handler to continue 
		                          // idh_data_handler_thread(), a thead create in ic_open_device.

      read time for time stamp.

      // Continue to tell controller to start data acquistion
		// argument depend on dhm, etc....
		pArcDev->Continuous( );

		// return from Continuous()  or data handleing fails..
		prints("IARC STATUS done\n"); // notifies APP via socket GO the
		Sm_iarc->status.done_cnt++;   // tony also increment shared memory.

	} // while(1)

CArcDevice->Continuous( ) what happen in this routine?


/*********************************  iarc_data_handler.c ******************************/

idh_data_handler_thread( ) 
   Started by ic_open_device()
	Signaled by readout_permo_thread() just before pArcDev->Continuous( ) is called.

	while( 1 )
	{
	   block until pth_cond_data_handler is signal (by readout_permo_thread ).

		// zero out some local buffers.

	   while( did_not_process_all_data  )
		{
		   // block until new data arives.
		   block_on_A_less...

			// call data hander based on iarc_setup.dhm
			RAW     handle_data_raw_threaded()
			SINGLE  handle_data_single_threaded()
			DOUBLE  handle_data_double_threaded()
			RAMP    handle_data_ramp_threaded()

         break on n_controller_continue==0
		}
	}

idh_new_data( unsigned short *buffer, int rows, int cols ) 
   The called by FrameCallback() when an new readout is avalible.
	copy buffer to pU16buffer (a static array).
	signals dh_cond -> wake up idh_data_handler_thread() block_on_A_less..


handle_data_raw_threaded()  
   call by dh_data_handler_thread when new data arrives and in RAW mode,
	add readout are saved to individual files.
	Data is in pU16buffer.

   descrambleU16 to temp_data_buf[]

	data save (raw saves each readout)
	send to DV.

handle_data_single_threaded()   
   call by dh_data_handler_thread when new data arrives and in SINGLE mode,
	all readout are coadd and 1 image is saved.
	Data is in pU16buffer.

	while( frames_handled < iarc_setup.n_readout_number) ) // >
	{
	   sig_buf[] += pU16buffer;  // all SINGLE readouts are added 

		when all data added,
		   descrambleU32() from sig_buf to ul_temp_data_buf.
	      data a single file. 
	      send to DV.
	}

handle_data_double_threaded()   
   call by dh_data_handler_thread when new data arrives and in DOUBLE mode,
	Pedestals are summed into ped_buf;
	Samples   are summed into sam_buf;
	coad_buf = ped_buf - sam_buf;
	descrambleU32( coad_buf to ul_temp_data_buf)

	save ul_temp_data_buf to file   
	send to DV.

handle_data_ramp_threaded()   
   call by dh_data_handler_thread when new data arrives and in RAMP mode,
	copy pU16Buffer to rdata.

	Caculates linear regression,  y = a + b*x :
	
	      sum(y)*sum(x^2) - sum(x)*sum(xy)
	 a = ----------------------------------
	         n * sum(x^2) - sum(x)*sum(x)
	 
	         n * sum(xy) - sum(x)*sum(y)
	 b = ----------------------------------
	         n * sum(x^2) - sum(x)*sum(x)


    Save 'b'(slope)  as fits files.
    Send to DV