function varargout = quantize_cbs(fun,varargin)
%QUANTIZE_CBS Callbacks for Quantization.
%    [A,B,...] = QUANTIZE_CBS(FUN,X,Y,...) calls the local function FUN with
%    input parameters X,Y,... and output parameters A,B,....

%   Thomas A. Bryan
%   Copyright 1988-2000 The MathWorks, Inc.
%   $Revision: 1.14 $  $Date: 2000/08/03 23:15:39 $ 

if nargin==0
  fun = 'getfunctionpointers';
end
[varargout{1:nargout}] = feval(fun,varargin{:});
%----------------------------------------------------------------------
function cb = getfunctionpointers
%GETFUNCTIONPOINTERS Get function pointers to all local functions.
cb.exportqfilt = @exportqfilt;
cb.getmode = @getmode;
cb.getpopupstring = @getpopupstring;
cb.importqfilt = @importqfilt;
cb.buttonpress = @buttonpress;
cb.setdouble = @setdouble;
cb.setfixed = @setfixed;
cb.setfloat = @setfloat;
cb.setlengths = @setlengths;
cb.setmode = @setmode;
cb.setscalevalues = @setscalevalues;
cb.setsingle = @setsingle;
cb.storemodes = @storemodes;
cb.normalizefilter = @normalizefilter;
cb.ui2qfilt = @ui2qfilt;
cb.ui2quantizer = @ui2quantizer;

%----------------------------------------------------------------------
% Callback functions from the GUI
%----------------------------------------------------------------------
function buttonpress(hcbo,eventstruct,hFig)
%BUTTONPRESS Log that a button was pressed.
set_flagsdirty(hFig);
update_actionbtn('update_enablestate',hFig);  % Calls update_titlebar()

%----------------------------------------------------------------------
function setmode(hcbo,eventstruct,hFig,k)
%SETMODE Set the mode of quantizer k.
%   SETMODE(HCBO,EVENTSTRUCT,HFIG,K) sets the mode of quantizer k.  HCBO is
%   the handle to the current callback.  EVENTSTRUCT is a dummy input
%   argument required by using function pointers in callbacks.  HFIG is the
%   handle to the current figure.
%   The quantizers are displayed on the gui by lines (k).  They are: 
%     ------------------------------------------------------------
%     (k) Data path    Quantizer  Mode Roundmode Overflowmode Format
%     ------------------------------------------------------------
%     (1) Coefficient
%     (2) Input
%     (3) Output
%     (4) Multiplicand
%     (5) Product
%     (6) Sum
%     ------------------------------------------------------------
%   All of the properties of a quantizer are stored in the user data of its
%   mode property.
%   When the mode is 'fixed' or 'float', then we need to store the values
%   that the user sets.  When the modes are 'double' or 'single', we don't
%   have to store their values because double and single have pre-set values.
%   When toggling back from single or double to fixed or float, the
%   user-input values are remembered and restored.
set_flagsdirty(hFig);
update_actionbtn('update_enablestate',hFig);  % Calls update_titlebar()
ud = get(hFig,'userdata');
switch get(hcbo,'value')
  case 1  % fixed
    setfixed(ud.h.quantize_params.quantizerprops,k);
  case 2  % float
    setfloat(ud.h.quantize_params.quantizerprops,k);
  case 3  % double
    setdouble(ud.h.quantize_params.quantizerprops,k);
  case 4  % single
    setsingle(ud.h.quantize_params.quantizerprops,k);
end
storeenablestates(hFig,k);

%----------------------------------------------------------------------
function setlengths(hcbo,eventstruct,hFig,k)
%SETLENGTHS Set wordlength, fractionlength of quantizer k.
%   See local function SETMODE for more information.
set_flagsdirty(hFig);
update_actionbtn('update_enablestate',hFig);  % Calls update_titlebar()
ud = get(hFig,'userdata');
switch getmode(ud.h.quantize_params.quantizerprops,k)
  case 1  % fixed
    storemodes(ud.h.quantize_params.quantizerprops,k);
    setfixed(ud.h.quantize_params.quantizerprops,k);
  case 2  % float
    storemodes(ud.h.quantize_params.quantizerprops,k);
    setfloat(ud.h.quantize_params.quantizerprops,k);
end
storeenablestates(hFig,k);

%----------------------------------------------------------------------
% Utility functions & functions called from private
%----------------------------------------------------------------------
function storemodes(hcbo,k)
%STOREMODES Store quantizer modes.
%   STOREMODES(HCBO,K) stores the Kth quantizer mode.  HCBO is the handle to
%   the current callback.  All of the settings of a quantizer are stored in
%   it's 'mode' property.
%   See local function SETMODE for more information.
mode = get(hcbo.modes(k),'value');
lud = get(hcbo.modes(k),'userdata');
lud.roundmode = get(hcbo.roundmodes(k),'value');
% Store the user-set information for fixed and float.  Don't store the
% pre-set values for single and double.
switch mode
  case 1  % Fixed.  Store the overflowmode and format. 
    lud.overflowmode = get(hcbo.overflowmodes(k),'value');
    lud.format = get(hcbo.formats(k),'string');
  case 2  % Float.  Store the format.
    lud.format = get(hcbo.formats(k),'string');
end
set(hcbo.modes(k),'userdata',lud);

%----------------------------------------------------------------------
function setdouble(hcbo,index)
%SETDOUBLE Set quantizers to double.
%   SETDOUBLE(HCBO,INDEX) sets the quantizers indicated by INDEX to double.
%   HCBO is the handle to the current callback.
%   See local function SETMODE for more information.
for k=index
  set(hcbo.modes(k),'value',3,'enable','on')               % Mode='double'
  set(hcbo.roundmodes(k),'value',5,'enable','off')         % Roundmode='round'
  set(hcbo.overflowmodes(k),'value',1,'enable','off')      % Overflowmode='saturate'
  set(hcbo.formats(k),'string','[64,  11]','enable','off') % Format=[64 11]         
end

%----------------------------------------------------------------------
function setsingle(hcbo,index)
%SETSINGLE Set quantizers to single.
%   SETSINGLE(HCBO,INDEX) sets the quantizers indicated by INDEX to single.
%   HCBO is the handle to the current callback.
%   See local function SETMODE for more information.
for k=index
  set(hcbo.modes(k),'value',4,'enable','on')              % Mode='single'
  set(hcbo.roundmodes(k),'value',5,'enable','off')        % Roundmode='round'
  set(hcbo.overflowmodes(k),'value',1,'enable','off')     % Overflowmode='saturate'
  set(hcbo.formats(k),'string','[32,  8]','enable','off') % Format=[32 8]
end

%----------------------------------------------------------------------
function setfixed(hcbo,index)
%SETFIXED Set quantizers to fixed.
%   SETFIXED(HCBO,INDEX) sets the quantizers indicated by INDEX to fixed.
%   HCBO is the handle to the current callback.
%   See local function SETMODE for more information.
for k=index
  lud = get(hcbo.modes(k),'userdata');
  set(hcbo.modes(k),'value',1,'enable','on')                       % Mode='fixed'
  set(hcbo.roundmodes(k),'value',lud.roundmode,'enable','on')      % Roundmode=from lud
  set(hcbo.overflowmodes(k),'value',lud.overflowmode,'enable','on')% Overflowmode=from lud
  set(hcbo.formats(k),'string',lud.format,'enable','on')           % Format=from lud      
  storemodes(hcbo,k)
end

%----------------------------------------------------------------------
function setfloat(hcbo,index)
%SETFLOAT Set quantizers to float.
%   SETFLOAT(HCBO,INDEX) sets the quantizers indicated by INDEX to float.
%   HCBO is the handle to the current callback.
%   See local function SETMODE for more information.
for k=index
  lud = get(hcbo.modes(k),'userdata');
  set(hcbo.modes(k),'value',2,'enable','on')                       % Mode='float'
  set(hcbo.roundmodes(k),'value',lud.roundmode,'enable','on')      % Roundmode=from lud   
  set(hcbo.overflowmodes(k),'value',1,'enable','off')     % Overflowmode='saturate'
  set(hcbo.formats(k),'string',lud.format,'enable','on')           % Format=from lud      
  storemodes(hcbo,k)
end

%----------------------------------------------------------------------
function setscalevalues(hcbo,eventstruct,hFig)
set_flagsdirty(hFig);
update_actionbtn('update_enablestate',hFig);  % Calls update_titlebar()
% Get the user data
ud = get(hFig,'userdata');
% Get the scale values from the edit box.
scale = getscale(ud.h.quantize_params.qfiltobjs.scalevalues);

% Set the scale values in tempqfilt
wrn = warning('off');
tempqfilt = gettempqfilt(ud);
ud.specs.quantize.tempqfilt = set(tempqfilt,'scalevalues',scale);
warning(wrn)

% Set the user data
set(hFig,'userdata',ud)

%----------------------------------------------------------------------
function m=getmode(hcbo,k)
%GETMODE Get the mode of quantizer k.
m=get(hcbo.modes(k),'value');
%   See local function SETMODE for more information.

%----------------------------------------------------------------------
function normalizefilter(hcbo,eventstruct,hFig)
wrn = warning('off');
lastwarn('');
ud = get(hFig,'userdata');
% QFILTOBJS is a structure of handles to the QFILT object properties
% uicontrols. 
qfiltobjs = ud.h.quantize_params.qfiltobjs;
% Start with the existing filter + reference qfilt and modify its parameters.
currentfilter = ud.filter;  % Make a local copy in case ud changes
Hq = dfilt2qfilt(currentfilter,gettempqfilt(ud));

Hq = updatescalevalues(Hq,qfiltobjs);

Hq = normalize(Hq);


% Update the scaling
set(qfiltobjs.scalevalues,'string',mat2str(scalevalues(Hq)));

% Update the reference qfilt and the current filter after scaling
ud.specs.quantize.tempqfilt = Hq;
if isa(ud.filter,'qfilt')
  ud.filter = Hq;
else
  ud.filter = qfilt2dfilt(Hq);
end
set(hFig,'userdata',ud);
update_plot(hFig);
% Revert the warning state.

if ~isa(ud.filter,'qfilt') & prod(scalevalues(Hq)) ~=1
  warning('Scale values are not applied to unquantized filter',...
      'FDATool Warning');
  fdatoolwarning(hFig);
end
warning(wrn)


%----------------------------------------------------------------------
function Hq = ui2qfilt(hFig)
%UI2QFILT  Convert uicontrol settings to qfilt object.
%
%    Hq = UI2QFILT converts the FDTOOL uicontrol settings to a qfilt
%    object Hq.
%   The quantizers are displayed on the gui by lines (k).  They are: 
%     ------------------------------------------------------------
%     (k) Data path    Quantizer  Mode Roundmode Overflowmode Format
%     ------------------------------------------------------------
%     (1) Coefficient
%     (2) Input
%     (3) Output
%     (4) Multiplicand
%     (5) Product
%     (6) Sum
%     ------------------------------------------------------------
%   All of the properties of a quantizer are stored in the user data of its
%   mode property.
%   When the mode is 'fixed' or 'float', then we need to store the values
%   that the user sets.  When the modes are 'double' or 'single', we don't
%   have to store their values because double and single have pre-set values.
%   When toggling back from single or double to fixed or float, the
%   user-input values are remembered and restored.

wrn = warning('off');
ud = get(hFig,'userdata');
% Construct a qfilt that has all of the parameters of tempqfilt + the
% reference coefficients from ud.filter.
Hq = gettempqfilt(ud);
temp = dfilt2qfilt(ud.filter,Hq);
Hq = set(Hq,'referencecoefficients',referencecoefficients(temp));


% QFILTOBJS is a structure of handles to the QFILT object properties
% uicontrols. 
qfiltobjs = ud.h.quantize_params.qfiltobjs;
set(qfiltobjs.scalevalues,'string',mat2str(scalevalues(Hq)));
warning(wrn)

%----------------------------------------------------------------------
function Hq = updatescalevalues(Hq,qfiltobjs)
%UPDATESCALEVALUES Update qfilt scale values
%    Hq = updatescalevalues(Hq,qfiltobjs) updates the scale values in Hq with
%    the scale values that were entered in the Input/Output scaling edit box
%    after auto-correcting for the length of the vector.
%    QFILTOBJS is a structure of handles to the QFILT object properties
%    uicontrols.  

% Initialize scale values.
Hq = set(Hq,'scalevalues',1);

% Autocorrect for wrong length scale values
Hq = scalevaluefixup(Hq);

%----------------------------------------------------------------------
function q = ui2quantizer(hcbo,k,hFig,q)
%UI2QUANTIZER Create a quantizer from settings on UI.
%   See local function SETMODE for more information.
quantizertype = getpopupstring(hcbo.quantizers(k));
mode = getpopupstring(hcbo.modes(k));
roundmode = getpopupstring(hcbo.roundmodes(k));
overflowmode = getpopupstring(hcbo.overflowmodes(k));

try
  fmt = evaluatevars(get(hcbo.formats(k),'string'));
  q = feval(quantizertype,mode,roundmode,overflowmode,fmt);
catch
  fdatoolerror(hFig);
  return;
end
%----------------------------------------------------------------------
function s = getpopupstring(hcbo);
%GETPOPUPSTRING Get the popup string from the current callback.
lud = get(hcbo,'userdata');
v = get(hcbo,'value');
s = lud.labels{v};

%----------------------------------------------------------------------
function storeenablestates(hFig,k)
%STOREENABLESTATES Store the enable states of the quantize page.
%   storeenablestates(hcbo) stores the enable states of the quantize page.
%   The user data is modified.

% Get the user data
ud = get(hFig,'userdata');

% Store the current values of the enable states
ud.specs.quantize.enablestates = ...
    get(ud.h.quantize_params.enablehandles,'enable');

quantizerprops = ud.h.quantize_params.quantizerprops;
tempqfilt = gettempqfilt(ud);
formats = {'coefficientformat','inputformat',...
      'outputformat','multiplicandformat','productformat',...
      'sumformat'};

% Get the current quantizer.
qcurrent = feval(formats{k},tempqfilt);
% Read the gui and set the quantizer properties.
q = ui2quantizer(quantizerprops,k,hFig,qcurrent);

wrn = warning('off');
ud.specs.quantize.tempqfilt = set(tempqfilt,formats{k},q);
warning(wrn)

% Set the user data
set(hFig,'userdata',ud)

%----------------------------------------------------------------------
function scale = getscale(hscale)
%GETSCALE Get scale values from edit box.
%   GETSCALE(HSCALE) returns a numeric vector from the scalevalues edit
%   box.  HSCALE is the handle to the edit box.
scale = get(hscale,'string');
if isempty(scale) 
  % If there were no scale values entered, then default = 1.
  scale=1;
else
  % Otherwise, get the scale values from the edit box.
  scale = evaluatevars(scale);
end
scale = scale(:).';  % Make a row vector.
