classdef helperRBDSController < comm.internal.ExampleController
%helperRBDSController RDS/RBDS-specific controller

%   Copyright 2016-2019 The MathWorks, Inc.
  properties (SetObservable, AbortSet)
    %CenterFrequency FM channel frequency (Hz)
    CenterFrequency = 98.5e6
    PlaybackAudio  = true
    OpenScopes = false
  end
  
  properties (Access=protected, Constant)
    ExampleName = 'RBDSExample'
    ModelName = ' ';
    CodeGenCallback = @generateCodeCallback;
    
    MinContainerWidth = 300
    MinContainerHeight = 380 % 500

    Column1Width = 130
    Column2Width = 130
  end
  
  properties (Constant)
    ScopeNames = {'RDS/RBDS Spectrum Analyzer', ...
                  'RDS/RBDS Demodulation', ...
                  'RDS/RBDS Biphase Decoding #1', ...
                  'RDS/RBDS Biphase Decoding #2'}
  end

  properties (Access=protected)
    HTMLFilename
    RunFunction = 'runRBDSReceiver'
  end
  
  methods
    function obj = helperRBDSController(varargin)
      obj@comm.internal.ExampleController(varargin{:});
      obj.HTMLFilename = fullfile(matlabroot, ...
        'toolbox','comm','commdemos','html','RBDSExample.html');
      obj.SignalFilename = 'rbds_capture.bb';
      obj.Duration = 10.8;
      obj.ExampleTitle = 'RDS/RBDS';
    end
    
    function set.CenterFrequency(obj, aFrequency)
        try
            validateattributes(aFrequency,{'numeric'},...
                {'scalar','real','finite','nonnan','positive'},...
                '', 'CenterFrequency');
            obj.CenterFrequency = aFrequency;
        catch me
            handleErrorsInApp(obj.SignalSourceController,me)
            
        end
    end
  end
  
  methods 
    function flag = isInactiveProperty(obj,prop)
        if (strcmp(obj.SignalSourceController.SignalSource, 'File') && strcmp(prop, 'CenterFrequency'))
            flag = true;
        else
             flag = isInactiveProperty@comm.internal.ExampleController(obj, prop);
        end
    end
  end
  methods (Access = protected)
    
    function addWidgets(obj)
      % Register settings:
      obj.addRow('Duration',        'Duration',         'edit',     'numeric');
      obj.addRow('SignalSource',    'Signal source',    'popupmenu');
      obj.addRow('RadioAddress',    'Radio address',    'popupmenu');
      obj.addRow('SignalFilename',  'Signal file name', 'edit',    'text');
      obj.addRow('CenterFrequency', 'Center frequency', 'edit',    'numeric');
      obj.addRow('PlaybackAudio',   'Playback audio',   'checkbox');
      obj.addRow('OpenScopes',      'Open scopes',      'checkbox');
    end
    
    function enableNontunableProperties(obj)
      % Frequency units only in MHz:
      for p=1:obj.RowCount
        if ~strcmp(obj.Input(p).Tag, 'CenterFrequencyUnit')
          obj.Input(p).Enable = 'on';
        end
      end
    end
  end
end

function generateCodeCallback(userInput)
  % generate mex files for computation-intensive operations, i.e., PHY and
  % error correction and detection
  
  if isempty(which('RBDSPhyDecoder_mex'))
    rbdsParam = helperRBDSConfig(userInput);
    % remove fields that may affect the constant nature of the struct:
    fields = {'isSourceRadio', 'isSourcePlutoSDR', 'Duration', 'LogData', 'LogFileName', 'OpenScopes'};
    rbdsParamPhy = rmfield(rbdsParam, fields);
    codegen(which('RBDSPhyDecoder'), '-args', {complex(zeros(rbdsParamPhy.SamplesPerFrame, 1)), coder.Constant(rbdsParamPhy), false})
  end
  if isempty(which('RBDSErrorDetection_mex'))
    codegen(which('RBDSErrorDetection'), '-args', {zeros(26, 1), zeros(26, 1)});
  end
  if isempty(which('RBDSErrorCorrection_mex'))
    codegen(which('RBDSErrorCorrection'), '-args', {zeros(1, 26), zeros(1, 26)});
  end
end
