% ////////////////////////////////////////////////////////////////////
% FILE,     HBF2LModel.m
% PROJECT,  HBF2L
% AUTHOR,   weitao.du
% DATE,     2007.Jun.11th
% VERSION,  0.1
% ////////////////////////////////////////////////////////////////////
% DECRIPTION
% 2 Level Half Band Fir Filter Design and Simulation, filer model 
% ////////////////////////////////////////////////////////////////////

function simData = HBF2LModel(cfg, simData);
  fprintf(1, 'HBF2LModel(), run\n');
  truncOut      = 0;
  dataFlp       = ModelFlp(cfg, simData, truncOut);
  dataFxpLv1    = ModelFxpLv1(cfg, simData, truncOut);

  simData.dataFlp       = dataFlp       ;
  simData.dataFxpLv1    = dataFxpLv1    ;

end  % function HBF2LModel();

% ////////////////////////////////////////////////////////////////////
% function ModelFxpLv1(), HBF2L fixed point model, 
% level 1, fixed point algorithm Model
function dataFxpLv1 = ModelFxpLv1(cfg, simData, truncOut);
% if truncOut ~= 0, then delete the for-and-aft FIR output data
% get config param
  inputFs   = cfg.inputFs      ;
  inputBw   = cfg.inputBw      ;
  inputWL   = cfg.inputWL      ;
  coeffWL   = cfg.coeffWL      ;
  outputWL  = cfg.outputWL     ;
  K1        = cfg.K1           ;
  K2        = cfg.K2           ;
  passBand1 = cfg.passBand1    ;
  passBand2 = cfg.passBand2    ;

% get initial data
  filterInit   =  simData.filterInit   ;
  coeff1CdsFxp =  filterInit.coeff1CdsFxp;
  coeff2CdsFxp =  filterInit.coeff2CdsFxp;
  inputData    =  simData.inputData;

% HBF level 1 filter
  lenInput        =  length(inputData);
  lenOutLv1Part0  =  lenInput + 2*K1 - 1; 
  lenOutLv1Part1  =  lenOutLv1Part0;
% part0 gen by mult-add
  outLv1Part0     =  zeros(lenOutLv1Part0, 1);  
% part1 gen by copy
  outLv1Part1     =  zeros(lenOutLv1Part1, 1);  
% total output
  outLv1          =  zeros(lenOutLv1Part0*2,1);
% data sequence in the hbf, include the begining and end
% zero stuff
  lv1DataSeq      =  zeros(2*K1-1+lenInput+2*K1-1, 1);
  lv1DataSeq(2*K1:lenInput+2*K1-1) = inputData;
% data sequence read for MAC index
  lv1DataIdx      =  [2*K1:lenInput+K1*4-2].';
% output index
  lv1OutIdx       =  [1:lenOutLv1Part0].';
% r1 is hbf level 1 sum index
  r1Idx           =  [0:K1-1];
  data0Idx0Trace   = zeros(lenOutLv1Part0,K1);
  data0Idx1Trace   = zeros(lenOutLv1Part0,K1);
  data1IdxTrace    = zeros(lenOutLv1Part1,1);

  for(idx1=1:lenOutLv1Part0)
  % level1 output part0, gen by add-mult-sum
    % the algorithm is explained in the design report
    data0Idx0  = lv1DataIdx(idx1)-r1Idx;
    data0Idx1  = lv1DataIdx(idx1)-2*K1+1 + r1Idx;
    dataPart0 = lv1DataSeq(data0Idx0);
    dataPart1 = lv1DataSeq(data0Idx1);
    dataAdd   = dataPart1+dataPart0;
    dataMult  = dataAdd .* coeff1CdsFxp;
    dataSum   = sum(dataMult);
    outLv1Part0(lv1OutIdx(idx1)) = dataSum; 
  % level1 output part1, gen by copy
    maxCoeffVal = 2^(coeffWL-1) - 1;    % coeffWL include the sign bit
    data1Idx  = lv1DataIdx(idx1)+1-K1;
    outLv1Part1(lv1OutIdx(idx1)) = lv1DataSeq(data1Idx) * maxCoeffVal;
    data0Idx0Trace(idx1,:)  = data0Idx0; 
    data0Idx1Trace(idx1,:)  = data0Idx1; 
    data1IdxTrace(idx1)     = data1Idx;
  end % for(idx1=1:lenOutLv1Part0)

  outLv1(1:2:2*lenOutLv1Part0-1) = outLv1Part0;
  outLv1(2:2:2*lenOutLv1Part0)   = outLv1Part1;
  if(truncOut ~= 0)
  % delete the pipe stuff data 
    outLv1(1:2*K1-1) = [];
    tmp = length(outLv1);
    outLv1(tmp-2*K1+2:tmp) = [];
  end
  cfftwinplot(outLv1, inputFs*2, 'HBF FIXED POINT LV1 output', 'green');
  

  dbg.outLv1Part0 = outLv1Part0;
  dbg.outLv1Part1 = outLv1Part1;
  dbg.lv1DataSeq  = lv1DataSeq;
  dbg.lv1DataIdx  = lv1DataIdx;
  dbg.lv1OutIdx   = lv1OutIdx;
  dbg.data0Idx0Trace = data0Idx0Trace;
  dbg.data0Idx1Trace = data0Idx1Trace;
  dbg.data1IdxTrace  = data1IdxTrace;


  dataFxpLv1.outLv1 = outLv1;
  dataFxpLv1.dbg    = dbg;    

end % fucntion ModelFxpLv1()
% ////////////////////////////////////////////////////////////////////
% function ModelFlp(), HBF2L floating point model
function dataFlp = ModelFlp(cfg, simData, truncOut);
% if truncOut ~= 0, then delete the for-and-aft FIR output data

% get config param
  inputFs   = cfg.inputFs      ;
  inputBw   = cfg.inputBw      ;
  inputWL   = cfg.inputWL      ;
  coeffWL   = cfg.coeffWL      ;
  outputWL  = cfg.outputWL     ;
  K1        = cfg.K1           ;
  K2        = cfg.K2           ;
  passBand1 = cfg.passBand1    ;
  passBand2 = cfg.passBand2    ;

% get initial data
  filterInit   =  simData.filterInit   ;
  coeff1AllFxp =  filterInit.coeff1AllFxp ;
  coeff2AllFxp =  filterInit.coeff2AllFxp ;
  inputData    =  simData.inputData;

% HBF Level 1 input data interpolation and Filter
  lenIn1 = length(inputData); 
  dataLv1Itp = zeros(lenIn1*2, 1);
  dataLv1Itp(1:2:lenIn1*2-1) = inputData; 
  hbfLv1Out = conv(coeff1AllFxp, dataLv1Itp);
  
  if(truncOut ~= 0)
  % delete the pipe stuff data 
    hbfLv1Out(1:2*K1-1) = [];
    tmp = length(hbfLv1Out);
    hbfLv1Out(tmp-2*K1+2:tmp) = [];
  end
  cfftwinplot(hbfLv1Out, inputFs*2, 'HBF LV1 output', 'black');

% HBF Level 2 input data interpolation and Filter
  lenIn2 = length(hbfLv1Out); 
  dataLv2Itp = zeros(lenIn2*2, 1);
  dataLv2Itp(1:2:lenIn2*2-1) = hbfLv1Out; 
  hbfLv2Out = conv(coeff2AllFxp, dataLv2Itp);

  if(truncOut ~= 0)
    % delete the pipe stuff data 
    hbfLv2Out(1:2*K2-1) = [];
    tmp = length(hbfLv2Out);
    hbfLv2Out(tmp-2*K2+2:tmp) = [];
  end
  cfftwinplot(hbfLv2Out, inputFs*4, 'HBF LV2 output', 'black');
   
  dataFlp.hbfLv1Out     = hbfLv1Out;
  dataFlp.hbfLv2Out     = hbfLv2Out;
  dataFlp.dataLv1Itp    = dataLv1Itp;
end % function ModelFlp();
