% iGp_gd            - Acquires iGp/iGp12 data and attendant variables
%
% Copyright (c) 2006-2010 Dimtel, Inc., All Rights Reserved
%
% $Id: iGp_gd.m,v 1.1.1.1 2010/10/05 16:43:02 dim Exp $
% $Date: 2010/10/05 16:43:02 $
% $Author: dim $
% $Revision: 1.1.1.1 $
% $Log: iGp_gd.m,v $
% Revision 1.1.1.1  2010/10/05 16:43:02  dim
% Initial import of iGp12
%
%

function [status, prm] = iGp_gd(prm)

t00 = clock;

pvnm = ['IGPF:', prm.sys, ':'];

prm.fpga_rev = lcaGet([pvnm, 'REVISION']);
prm.gpio_sel = lcaGet([pvnm, 'GPIO_SEL'], 1, 'long');

% Read out various parameters
prm.when = now;

pvl     = {[pvnm, 'CSET0']; [pvnm, 'CSET1']};
pvl{3}  = [pvnm, 'CR256'];
pvl{4}  = [pvnm, 'DELAY'];
pvl{7}  = [pvnm, 'RF_FREQ'];
pvl{8}  = [pvnm, 'HARM_NUM'];
pvl{9}  = [pvnm, 'REC_DS'];
pvl{10} = [pvnm, 'PROC_DS'];
if (prm.gpio_sel == 1)
  pvl{11} = [pvnm, 'FE_ATTEN'];
  pvl{12} = [pvnm, 'BE_ATTEN'];
end

if (prm.fpga_rev < 3)
  pvl{5}  = [pvnm, 'GDLEN'];
  pvl{6}  = [pvnm, 'WRT:HOLDOFF'];
  if (prm.gpio_sel == 1)
    pvl{13} = [pvnm, 'WRT:FE_PHASE'];
    pvl{14} = [pvnm, 'WRT:BE_PHASE'];
  end
else
  pvl{5}  = [pvnm, 'GDTIME'];
  pvl{6}  = [pvnm, 'HOLDTIME'];
  if (prm.gpio_sel == 1)
    pvl{13} = [pvnm, 'FE_PHASE'];
    pvl{14} = [pvnm, 'BE_PHASE'];
  elseif (prm.gpio_sel == 2)
    pvl{11} = [pvnm, 'FBE:Z_ATT'];
    pvl{12} = [pvnm, 'FBE:BE_ATT'];
    pvl{13} = [pvnm, 'FBE:Z_PHASE'];
    pvl{14} = [pvnm, 'FBE:BE_PHASE'];
    pvl{15} = [pvnm, 'FBE:X_ATT'];
    pvl{16} = [pvnm, 'FBE:Y_ATT'];
    pvl{17} = [pvnm, 'FBE:X_PHASE'];
    pvl{18} = [pvnm, 'FBE:Y_PHASE'];
  end
end


% If dcct field is defined, use it as beam current PV
if isfield(prm, 'dcct')
 pvl{end+1} = prm.dcct;
end

% Read the channels
data = lcaGet(pvl, 0);

% Parse the data
prm.coeff0     = data(1,:)/32768;
prm.coeff1     = data(2,:)/32768;
prm.Nc         = length(prm.coeff0);
prm.shift_gain = bitand(bitshift(data(3,1), -4), 7);
prm.delay      = data(4,1);
prm.setsel     = bitand(bitshift(data(3,1), -2), 1);
prm.gden       = bitand(bitshift(data(3,1), -8), 1);
prm.rf_freq    = data(7,1);
prm.ring_size  = data(8,1);
prm.ds         = data(9,1);
prm.proc_ds    = data(10,1);

if (prm.fpga_rev < 3)
  prm.gdlen    = data(5,1);
  prm.holdoff  = data(6,1);
else
  prm.gdlen    = data(5,1)/(prm.ds/prm.rf_freq)*1e3;
  prm.holdoff  = data(6,1)/(prm.ds/prm.rf_freq)*1e3;
end

if (prm.gpio_sel == 1)
  prm.fe_atten = data(11,1);
  prm.be_atten = data(12,1);
  prm.fe_phase = data(13,1);
  prm.be_phase = data(14,1);
elseif (prm.gpio_sel == 2)
  prm.fe_atten = data(11,1); % Z
  prm.be_atten = data(12,1);
  prm.fe_phase = data(13,1);
  prm.be_phase = data(14,1);
  prm.x_atten  = data(15,1);
  prm.y_atten  = data(16,1);
  prm.x_phase  = data(17,1);
  prm.y_phase  = data(18,1);
end

% If beam current PV is defined above, read out the current
if isfield(prm, 'dcct')
  prm.Io = data(end,1);
else
  prm.Io = 0;
end

clear pvl;
pvl = {[pvnm, 'DESC:CSET0']; [pvnm, 'DESC:CSET1']; [pvnm, 'EXTEN']};
desc = lcaGet(pvl);

prm.cset0 = desc{1};
prm.cset1 = desc{2};
prm.exten = desc{3};

if (prm.debug)
  t01 = clock;
  disp(['Parameters acquired after ', num2str(etime(t01, t00)), ' seconds']);
end

prm.data = get_data(pvnm);

if (prm.debug)
  t02 = clock;
  disp(['Data transferred after ', num2str(etime(t02, t00)), ' seconds']);
end

prm.st = [prm.sys, '; I_0 = ', num2str(prm.Io), ' mA; ', ...
          datestr(prm.when)];


% Save gd.mat file
M = floor(length(prm.data)/prm.ring_size);
bunches(1,:) = 1:prm.ring_size;
bunches(2:M+1,:) = zeros(M, prm.ring_size);
bunches(2:M+1,:) = reshape(prm.data(1:M*prm.ring_size), prm.ring_size, M)';

bunches(1,:) = 1:prm.ring_size;

ring_size = prm.ring_size;
rf_freq = prm.rf_freq;
shift_gain = prm.shift_gain;
downsamp = prm.ds;
if (prm.gden == 1)
  damp_brkpt = round(prm.gdlen/length(prm.data)*63);
else
  damp_brkpt = 1;
end
beamCurrent = prm.Io;
turn_offsets = zeros(ring_size, 1);

[sos0, g] = tf2sos(prm.coeff0, [1 zeros(1, prm.Nc-1)]);
num0=sos0(:,1:3)';
num0(:,1)=num0(:,1)*g;
den0 = sos0(:, 5:6)';
[sos1, g] = tf2sos(prm.coeff1, [1 zeros(1, prm.Nc-1)]);
num1=sos1(:,1:3)';
num1(:,1)=num1(:,1)*g;
den1 = sos1(:, 5:6)';
if (prm.setsel == 1)
  a = num0; num0=num1; num1=a;
  a = den0; den0=den1; den1=a;
end
num2=num0; num3=num0;
num4=num0; num5=num0; num6=num0; num7=num0;
den2=den0; den3=den0;
den4=den0; den5=den0; den6=den0; den7=den0;
sections(1:8)=size(num0, 2);
sections(2) = size(num1, 2);
scope = 2;
eval(['save ', prm.tm, '/gd bunches num0 num1 num2 num3 num4 num5 ', ...
      'num6 num7 den0 den1 den2 den3 den4 den5 den6 den7 damp_brkpt ' ...
      'turn_offsets beamCurrent downsamp shift_gain rf_freq ring_size ' ...
      'sections scope']);
eval(['save ', prm.tm, '/prm prm']);

status = 1;
