classdef targetHardware < coder.matlabtarget.Hardware & matlab.mixin.CustomDisplay & coder.matlabtarget.deploytohardware
% TARGETHARDWARE Create a hardware configuration object to deploy a MATLAB® function on the hardware.
% 
% TARGETHARDWARE(hardwareName) returns the configuration object of the hardware, hardwareName.
% 
% Example: Create a targetHardware object of the Raspberry Pi™ hardware.
% 
% hw = targetHardware('Raspberry Pi')
% 
% See also deploy 

%   Copyright 2018-2021 The MathWorks, Inc.
    
    properties
        CoderConfig
    end
    
    properties(Hidden)
        codeGenFolder
        customMainObj
    end
    
    methods
        function obj = targetHardware(hardwareName)
            name = convertStringsToChars(hardwareName);
            % Return an object representing hardware with given name
            hwList = coder.internal.getHardwareNames;
            if isempty(hwList)
                error('coder:hardware:NoHardware', i_getSpkgInstallMsg);
            end
            name = validatestring(name,hwList);
            obj = obj@coder.matlabtarget.Hardware(name);
            
            % Customize coder.config for the hardware specified
            obj.CoderConfig = coder.config('exe','ecoder',false);
            obj.CoderConfig.Hardware = coder.matlabtarget.Hardware(name);
            
            % Use example main file
            obj.CoderConfig.GenerateExampleMain = 'GenerateCodeAndCompile';
            
            % Update CoderConfig with required options
            obj.customMainObj = coder.matlabtarget.internal.customizeExampleMain(obj.CoderConfig);
            includeList = getIncludeList(obj.customMainObj);
            if ~contains(obj.CoderConfig.CustomHeaderCode,includeList)
                obj.CoderConfig.CustomHeaderCode = strtrim([obj.CoderConfig.CustomHeaderCode, newline, includeList]);
            end
            
            targetInitFunc = getTargetInitFunc(obj.customMainObj);
            if ~contains(obj.CoderConfig.CustomInitializer,targetInitFunc)
                obj.CoderConfig.CustomInitializer = strtrim([obj.CoderConfig.CustomInitializer, newline, targetInitFunc]);
            end
            
            targetTerminateFunc = getTargetTerminateFunc(obj.customMainObj);
            if ~contains(obj.CoderConfig.CustomTerminator,targetTerminateFunc)
                obj.CoderConfig.CustomTerminator = strtrim([obj.CoderConfig.CustomTerminator, newline, targetTerminateFunc]);
            end
            
            %Enable launch report
            obj.CoderConfig.LaunchReport = true;
        end
        
        function set.CoderConfig(obj, value)
            if ~(isa(value,'coder.EmbeddedCodeConfig')||isa(value,'coder.CodeConfig'))
                try
                  error(message('codertarget:build:UnsupportedMATLABCoderBuild','CoderConfig'))
                catch me
                    throwAsCaller(me);
                end
            end
            obj.CoderConfig = value;
        end
        

        function deploy(obj, fcnName, varargin)
            % DEPLOY Deploy a MATLAB® function on the hardware.
            %             
            % DEPLOY(hwObj, fcnName) deploys a standalone executable on the hardware.
            % The executable is generated from the MATLAB function, fcnName, and is
            % deployed on the hardware specified in the targetHardware object, hwObj.
            %
            % NOTE: The MATLAB function must not have any input and output arguments.
            %
            % Example:
            % hw = targetHardware('Raspberry Pi');
            % deploy(hw, 'raspberrypi_edgedetection');
            %
            % See also targetHardware
            
            if ~isequal(obj.CoderConfig.OutputType, 'EXE') && ~isequal(obj.BuildAction, 'Build')
                error(message('codertarget:build:UnsupportedBuildAction',obj.CoderConfig.OutputType))
            end
            
            try
            deploy@coder.matlabtarget.deploytohardware(obj,fcnName, varargin{:});
            catch me
                throwAsCaller(me);
            end
        end
    end
    
    methods(Access = protected)
        function displayScalarObject(obj)
            %setup the header
            className = matlab.mixin.CustomDisplay.getClassNameForHeader(obj);
            scalarHeader = [className, ' with properties:' newline];
            %display the header
            fprintf('%s\n',scalarHeader);
            %get the property list
            props = getPropertyGroups(obj);
            %Remove the 'CPUClockRate' fields if it exists
            if isfield(props.PropertyList,'CPUClockRate')
                props.PropertyList = rmfield(props.PropertyList,'CPUClockRate');
            end
            %Remove the 'EnableParallelBuild' fields if it exists
            if isfield(props.PropertyList,'EnableParallelBuild')
                props.PropertyList = rmfield(props.PropertyList,'EnableParallelBuild');
            end
            %Fetch the list of properties from the MATLAB props
            requiredProps = feval(obj.HardwareInfo.MATLABPILInfo.GetPropsFcn);
            [~, idx] = coder.matlabtarget.getTargetVersion(requiredProps);
            if ~isempty(idx)
                % Delete TargetVersion property
                requiredProps(idx) = [];
            end
            %Remove 'EnableParallelBuild' as it can be set from
            %obj.CoderConfig.Hardware
            idx = find(arrayfun(@(x)isequal(x.Name,'EnableParallelBuild'),requiredProps));
            if ~isempty(idx)
                % Delete EnableParallelBuild property
                requiredProps(idx) = [];
            end
            orderList = cell(1,(numel(requiredProps)+3));
            orderList{1} = 'Name';
            if ~isempty(requiredProps)
                %Prepare the order list
                for i = 1:numel(requiredProps)
                    orderList{i+1} = requiredProps(i).Name;
                end
            end
            orderList{end - 1} = 'BuildAction';
            orderList{end} = 'CoderConfig';
            %re-order the props according to the order list
            props.PropertyList = orderfields(props.PropertyList,orderList);
            if isfield(props.PropertyList,'Password')
                %replace the password with '*'
                props.PropertyList.Password(1:length(props.PropertyList.Password)) = '*';
            end
            %Display the ordered property list
            matlab.mixin.CustomDisplay.displayPropertyGroups(obj,props);
        end
        
    end
end

% LocalWords:  HARDWARENAME
