%% Exchange Structured and Enumerated Data Between Generated and External Code
% NOTE: This example to remain authored in XML until dev area settles down.
% This example shows how to generate code that exchanges data with some
% external, handwritten code. You construct and configure a model to
% match data types with the external code and to avoid duplicating type
% definitions and memory allocation (definition of global variables). You
% then compile the generated code together with the external code into a
% single application.
%% Inspect External Code
% Create the file |ex_cc_algorithm.c| in your current folder.
%
% <include>ex_cc_algorithm.c</include>
%
% The C code defines a function, |my_alg|, that uses global structure
% variables such as |inSigs| and |calPrms|. The code also allocates memory
% for |inSigs|.
%
% Create the file |ex_cc_algorithm.h| in your current folder.
%
% <include>ex_cc_algorithm.h</include>
%
% The file defines |float_32| as an alias of the C data type |float|. The
% file also defines an enumerated data type and two structure types.
%
% The function |my_alg| is designed to calculate a return value by using
% the fields of |inSigs| and |calPrms|, which are global structure
% variables of the types |inSigs_T| and |calPrms_T|. The function requires
% another algorithm to supply the signal data that |inSigs| stores. 
%
% This code allocates memory for |inSigs|, but not for |calPrms|. You must
% create a model whose generated code:
%
% * Defines and initializes |calPrms|.
% * Calculates values for the fields of |inSigs|.
% * Reuses the type definitions (such as |err_T| and |float_32|) that the
% external code defines. 
%% Create Simulink Model
% So that you can create enumerated and structured data in the Simulink
% model, first create Simulink representations of the data types that the
% external code defines. Store the Simulink types in a new data dictionary
% named |ex_cc_integ.sldd|.
%
%   Simulink.importExternalCTypes('ex_cc_algorithm.h',...
%       'DataDictionary','ex_cc_integ.sldd');
Simulink.importExternalCTypes('ex_cc_algorithm.h',...
    'DataDictionary','ex_cc_integ.sldd');
%%
% The data dictionary appears in your current folder.
%
% In your current folder, double-click the file to inspect the dictionary
% contents in the Model Explorer.
%
% The function |Simulink.importExternalCTypes| does not create a
% representation of the custom data type |float_32|. To create one, in the
% Model Explorer, select *Add > Simulink AliasType*. A
% |Simulink.AliasType| object named |Alias| appears in the *Contents* pane.
%
% Rename the object from |Alias| to |float_32|.
%
% In the right pane of the Model Explorer, set *Base type* to |single|. Set
% *Header file* to |ex_cc_algorithm.h|.
dictionaryObj = Simulink.data.dictionary.open('ex_cc_integ.sldd');
dDataSectObj = getSection(dictionaryObj,'Design Data');
%%
% In the *Contents* pane, select |inSigs_T|. In the right pane, click
% *Launch Bus Editor*.
%
% In the Bus Editor, for the bus
% elements (fields) |sig1| and |sig2|, set *Data Type* to |float_32|.
%
% Select |calPrms_T| and set the bus element data types to |float_32|.
%
% In the Model Explorer *Model Hierarchy* pane, right-click the dictionary node and select *Save
% Changes*.
entryObj = getEntry(dDataSectObj,'inSigs_T');
temp = getValue(entryObj);
temp.Elements(2).DataType = 'float_32';
temp.Elements(3).DataType = 'float_32';
setValue(entryObj,temp);

entryObj = getEntry(dDataSectObj,'calPrms_T');
temp = getValue(entryObj);
temp.Elements(1).DataType = 'float_32';
temp.Elements(2).DataType = 'float_32';
temp.Elements(3).DataType = 'float_32';
setValue(entryObj,temp);

saveChanges(dictionaryObj)
%%
% Create a new, empty model named |ex_struct_enum_integ|.
%
% Link the model to the data dictionary. On the *Modeling* tab, under
% *Design*, click *Link to Data Dictionary*.
%
% Add algorithmic blocks that calculate the fields of
% |inSigs|.
open_system('ex_struct_enum_integ')
set_param('ex_struct_enum_integ','DataDictionary','ex_cc_integ.sldd')
%%
% Now that you have the basic algorithmic model, you must:
%
% * Organize the output signals into a structure variable named |inSigs|.
% * Create the structure variable |calPrms|.
% * Include |ex_cc_algorithm.c| in the build process that compiles the code
% after code generation.
%% Configure Generated Code to Store Outputs in Existing Structure Variable
% Add a Bus Creator block near the existing Outport blocks.
%
% In the Bus Creator block, set these parameters:
%
% * *Number of inputs* to |3|
% * *Output data type* to |Bus: inSigs_T|
% * *Output as nonvirtual bus* to selected
%
% Delete the three existing Outport blocks (but not the signals that enter
% the blocks).
%
% Connect the three remaining signal lines to the inputs of the Bus Creator
% block.
%
% Add an Outport block after the Bus Creator block. Connect the output of the Bus Creator to the Outport.
%
% In the Outport block, set the *Data type* parameter to |Bus: inSigs_T|.
%
% On the *Modeling* tab, click *Model Data Editor*.
%
% On the *Inports/Outports* tab, for the Inport blocks labeled |In2| and |In3|, change
% *Data Type* from |Inherit: auto| to |float_32|.
%
% Change the *Change View* drop-down list from |Design| to |Code|.
%
% For the Outport block, set *Signal Name* to |inSigs|. 
%
% Set *Storage Class*
% to |ImportFromFile|.
%
% Set *Header File* to |ex_cc_algorithm.h|.
%
% Inspect the *Signals* tab.
%
% In the model, select the output signal of the Multiport Switch block.%
%
% In the Model Data Editor, for the selected signal, set *Name* to |err|.
%
% Set the name of the output signal of the Gain block to |sig1|. Set the
% name of the output signal of the Gain1 block to |sig2|.
delete_line('ex_struct_enum_integ','Multiport Switch/1','Out1/1')
delete_line('ex_struct_enum_integ','Gain/1','Out2/1')
delete_line('ex_struct_enum_integ','Gain1/1','Out3/1')
delete_block('ex_struct_enum_integ/Out1')
delete_block('ex_struct_enum_integ/Out2')
delete_block('ex_struct_enum_integ/Out3')
add_block('simulink/Signal Routing/Bus Creator','ex_struct_enum_integ/Bus Creator',...
    'Position',[768   261   773   299],...
    'Inputs','3',...
    'NonVirtualBus','on',...
    'OutDataTypeStr','Bus: inSigs_T')
add_block('simulink/Sinks/Out1','ex_struct_enum_integ/Out1',...
    'Position',[830   273   860   287],...
    'OutDataTypeStr','Bus: inSigs_T')
add_line('ex_struct_enum_integ','Multiport Switch/1','Bus Creator/1','autorouting','on')
add_line('ex_struct_enum_integ','Gain/1','Bus Creator/2','autorouting','on')
add_line('ex_struct_enum_integ','Gain1/1','Bus Creator/3','autorouting','on')
add_line('ex_struct_enum_integ','Bus Creator/1','Out1/1','autorouting','on')
set_param('ex_struct_enum_integ/In2','OutDataTypeStr','float_32')
set_param('ex_struct_enum_integ/In3','OutDataTypeStr','float_32')
set_param('ex_struct_enum_integ/Out1','SignalName','inSigs')
temp = Simulink.Signal;
temp.CoderInfo.StorageClass = 'Custom';
temp.CoderInfo.CustomStorageClass = 'ImportFromFile';
temp.CoderInfo.CustomAttributes.HeaderFile = 'ex_cc_algorithm.h';
set_param('ex_struct_enum_integ/Out1','SignalObject',copy(temp))
portHandles = get_param('ex_struct_enum_integ/Multiport Switch','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','err')
portHandles = get_param('ex_struct_enum_integ/Gain','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','sig1')
portHandles = get_param('ex_struct_enum_integ/Gain1','portHandles');
outportHandle = portHandles.Outport;
set_param(outportHandle,'Name','sig2')
%%
% When you finish, the model stores output signal data (such as the signals |err| and |sig1|) in the fields of a structure variable named
% |inSigs|. 
open_system('ex_struct_enum_integ_end')
%%
% Because you set *Storage Class* to |ImportFromFile|, the
% generated code does not allocate memory for |inSigs|.
%% Configure Model to Generate Parameter Data
% In the Bus Editor, in the left pane, select the |Simulink.Bus| object |calPrms_T|. 
%
% On the toolbar, click the *Create/Edit a Simulink.Parameter Object from a Bus Object*
% button. 
%
% In the MATLAB Editor, copy the generated MATLAB code and run the code at
% the command prompt. The code creates a |Simulink.Parameter| object in the base workspace.
calPrms_T_MATLABStruct = struct;
calPrms_T_MATLABStruct.cal1 = 0;
calPrms_T_MATLABStruct.cal2 = 0;
calPrms_T_MATLABStruct.cal3 = 0;

calPrms_T_Param = Simulink.Parameter;
calPrms_T_Param.Value = calPrms_T_MATLABStruct;
calPrms_T_Param.CoderInfo.StorageClass = 'Auto';
calPrms_T_Param.Description = '';
calPrms_T_Param.DataType = 'Bus: calPrms_T';
calPrms_T_Param.Min = [];
calPrms_T_Param.Max = [];
calPrms_T_Param.DocUnits = '';

clear calPrms_T_MATLABStruct;
%%
% At the command prompt, set the field values in the parameter object. For the fields |cal1| and
% |cal2|, use the same values as the Gain blocks in the model. For |cal3|,
% use a nonzero number such as |15.2299995|.
%
%   calPrms_T_Param.Value.cal1 = 13.8900013;
%   calPrms_T_Param.Value.cal2 = 0.9983001;
%   calPrms_T_Param.Value.cal3 = 15.2299995;
calPrms_T_Param.Value.cal1 = 13.8900013;
calPrms_T_Param.Value.cal2 = 0.9983001;
calPrms_T_Param.Value.cal3 = 15.2299995;
%%
% In the Model Explorer *Model Hierarchy* pane, select *Base Workspace*.
%
% Move the parameter object from the base workspace to the Design Data
% section of the data dictionary, |ex_cc_integ|.
%
% With the data dictionary selected, in the *Contents* pane, rename the
% parameter object as |calPrms|.
%
% In the right pane, set *Storage class* to |ExportedGlobal|. 
%
% Save the changes that you made to the dictionary.
calPrms_T_Param.StorageClass = 'ExportedGlobal';
addEntry(dDataSectObj,'calPrms',copy(calPrms_T_Param));
saveChanges(dictionaryObj);
%%
% In the model Data Editor, select the *Parameters* tab.
%
% For the Gain block, replace the value |13.8900013| with
% |calPrms.cal1|.
%
% In the other Gain block, use |calPrms.cal2|.
set_param('ex_struct_enum_integ/Gain','Gain','calPrms.cal1')
set_param('ex_struct_enum_integ/Gain1','Gain','calPrms.cal2')
%% Generate, Compile, and Inspect Code
% Configure the model to include |ex_cc_algorithm.c| in the build process.
% Set *Configuration Parameters > Code Generation > Custom Code >
% Additional build information > Source files* to |ex_cc_algorithm.c|.
set_param('ex_struct_enum_integ','CustomSource','ex_cc_algorithm.c')
%%
% Generate code from the model.
rtwbuild('ex_struct_enum_integ')
%%
% Inspect the generated file |ex_struct_enum_integ.c|. The file defines
% and initializes |calPrms|.
file = fullfile('ex_struct_enum_integ_ert_rtw',...
    'ex_struct_enum_integ.c');
rtwdemodbtype(file,'/* Exported block parameters */','/* Variable: calPrms',1,1)
%%
% The generated algorithm calculates and stores data in the fields of
% |inSig|.
rtwdemodbtype(file,'switch (rtU.In1)','inSigs.sig2 =',1,1)
%% Replace Data Type Names Throughout Model
% To generate code that uses |float_32| instead of the default, |real32_T|,
% instead of manually specifying the data types of block output signals and
% bus elements, you can use data type replacement (*Configuration
% Parameters > Code Generation > Data Type Replacement*). For more
% information, see <docid:ecoder_ug.bvk18ed>.
bdclose('ex_struct_enum_integ')
bdclose('ex_struct_enum_integ_end')
Simulink.data.dictionary.closeAll('ex_cc_integ.sldd','-discard')
% Copyright 2019 The MathWorks, Inc.