Compare commits
	
		
			3 Commits
		
	
	
		
			99ec69324d
			...
			ead46d7d82
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ead46d7d82 | |||
| a6c5a9edab | |||
| fffd725d91 | 
							
								
								
									
										159
									
								
								config_reader.asv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								config_reader.asv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					clear; clc; close all;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					model = 'mcu_test_r2023';
 | 
				
			||||||
 | 
					block = [model '/MCU_UPP'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					load_system(model);  % если модель ещё не загружена
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					update_mask_from_config(block);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					disp('Маска обновлена по конфигу.');
 | 
				
			||||||
 | 
					function update_mask_from_config(blockPath)
 | 
				
			||||||
 | 
					    config = load_periph_config();
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tabPrompt = 'Config Peripheral';  % Имя вкладки (Prompt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    tabCtrl = find_tab_by_prompt(allControls, tabPrompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(tabCtrl)
 | 
				
			||||||
 | 
					        error('Вкладка с названием "%s" не найдена в маске', tabPrompt);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Удаляем все контролы внутри вкладки
 | 
				
			||||||
 | 
					    children = tabCtrl.DialogControls;
 | 
				
			||||||
 | 
					    while ~isempty(children)
 | 
				
			||||||
 | 
					        tabCtrl.removeControl(children(1));
 | 
				
			||||||
 | 
					        children = tabCtrl.DialogControls; % обновляем список после удаления
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    periphs = fieldnames(config);
 | 
				
			||||||
 | 
					    for i = 1:numel(periphs)
 | 
				
			||||||
 | 
					        periph = periphs{i};
 | 
				
			||||||
 | 
					        defines = config.(periph).Defines;
 | 
				
			||||||
 | 
					        defNames = fieldnames(defines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for j = 1:numel(defNames)
 | 
				
			||||||
 | 
					            defPrompt = defNames{j};
 | 
				
			||||||
 | 
					            def = defines.(defPrompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Обрабатываем только checkbox и edit
 | 
				
			||||||
 | 
					            switch lower(def.Type)
 | 
				
			||||||
 | 
					                case 'checkbox'
 | 
				
			||||||
 | 
					                    paramType = 'checkbox';
 | 
				
			||||||
 | 
					                case 'edit'
 | 
				
			||||||
 | 
					                    paramType = 'edit';
 | 
				
			||||||
 | 
					                otherwise
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            paramName = matlab.lang.makeValidName([periph '_' defPrompt]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            val = def.Default;
 | 
				
			||||||
 | 
					            if islogical(val)
 | 
				
			||||||
 | 
					                if val
 | 
				
			||||||
 | 
					                    valStr = 'on';
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    valStr = 'off';
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            elseif isnumeric(val)
 | 
				
			||||||
 | 
					                valStr = num2str(val);
 | 
				
			||||||
 | 
					            elseif ischar(val)
 | 
				
			||||||
 | 
					                valStr = val;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Добавляем параметр в маску (без TabName)
 | 
				
			||||||
 | 
					            mask.addParameter(...
 | 
				
			||||||
 | 
					                'Type', paramType, ...
 | 
				
			||||||
 | 
					                'Prompt', defPrompt, ...
 | 
				
			||||||
 | 
					                'Name', paramName, ...
 | 
				
			||||||
 | 
					                'Value', valStr, ...
 | 
				
			||||||
 | 
					                'Container', tabPrompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            disp(['paramType = ', paramType]);
 | 
				
			||||||
 | 
					            disp(['paramName = ', paramName]);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function config = load_periph_config()
 | 
				
			||||||
 | 
					    jsonText = fileread('periph_config.json');
 | 
				
			||||||
 | 
					    config = jsondecode(jsonText);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function clear_params_from_tab(blockPath, tabPrompt)
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockPath);
 | 
				
			||||||
 | 
					    controls = mask.getDialogControls;
 | 
				
			||||||
 | 
					    tabs = controls(strcmp({controls.Type}, 'tab'));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    tabName = '';
 | 
				
			||||||
 | 
					    for i = 1:numel(tabs)
 | 
				
			||||||
 | 
					        if strcmp(tabs(i).Prompt, tabPrompt)
 | 
				
			||||||
 | 
					            tabName = tabs(i).Name; % внутреннее имя вкладки
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(tabName)
 | 
				
			||||||
 | 
					        error('Вкладка с названием "%s" не найдена.', tabPrompt);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Удаляем параметры с TabName == tabName
 | 
				
			||||||
 | 
					    i = 1;
 | 
				
			||||||
 | 
					    while i <= numel(mask.Parameters)
 | 
				
			||||||
 | 
					        if strcmp(mask.Parameters(i).TabName, tabName)
 | 
				
			||||||
 | 
					            mask.removeParameter(i);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            i = i + 1;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% поиск вкладки
 | 
				
			||||||
 | 
					function tab = find_tab_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    tab = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, вкладка ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            tab = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это контейнер — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            tab = find_tab_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(tab)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function children = get_children(ctrl)
 | 
				
			||||||
 | 
					    if isprop(ctrl, 'DialogControls')
 | 
				
			||||||
 | 
					        children = ctrl.DialogControls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Controls')
 | 
				
			||||||
 | 
					        children = ctrl.Controls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Children')
 | 
				
			||||||
 | 
					        children = ctrl.Children;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        children = [];
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										134
									
								
								config_reader.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								config_reader.m
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					clear; clc; close all;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					model = 'mcu_test_r2023';
 | 
				
			||||||
 | 
					block = [model '/MCU_UPP'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					load_system(model);  % если модель ещё не загружена
 | 
				
			||||||
 | 
					config = load_periph_config();
 | 
				
			||||||
 | 
					update_mask_from_config(block, config);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					disp('Маска обновлена по конфигу');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% чтение конфигов
 | 
				
			||||||
 | 
					function config = load_periph_config()
 | 
				
			||||||
 | 
					    jsonText = fileread('periph_config.json');
 | 
				
			||||||
 | 
					    config = jsondecode(jsonText);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% запись дефайнов по конфигу
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% обновление маски
 | 
				
			||||||
 | 
					function update_mask_from_config(blockPath, config)
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tabName = 'configTab';  % Имя вкладки (Prompt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    tabCtrl = find_tab_by_name(allControls, tabName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(tabCtrl)
 | 
				
			||||||
 | 
					        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Удаляем все контролы внутри вкладки
 | 
				
			||||||
 | 
					    children = tabCtrl.DialogControls;
 | 
				
			||||||
 | 
					    while ~isempty(children)
 | 
				
			||||||
 | 
					        mask.removeParameter(children(1).Name);
 | 
				
			||||||
 | 
					        children = tabCtrl.DialogControls; % обновляем список после удаления
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    periphs = fieldnames(config);
 | 
				
			||||||
 | 
					    for i = 1:numel(periphs)
 | 
				
			||||||
 | 
					        periph = periphs{i};
 | 
				
			||||||
 | 
					        defines = config.(periph).Defines;
 | 
				
			||||||
 | 
					        defNames = fieldnames(defines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for j = 1:numel(defNames)
 | 
				
			||||||
 | 
					            defPrompt = defNames{j};
 | 
				
			||||||
 | 
					            def = defines.(defPrompt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Обрабатываем только checkbox и edit
 | 
				
			||||||
 | 
					            switch lower(def.Type)
 | 
				
			||||||
 | 
					                case 'checkbox'
 | 
				
			||||||
 | 
					                    paramType = 'checkbox';
 | 
				
			||||||
 | 
					                case 'edit'
 | 
				
			||||||
 | 
					                    paramType = 'edit';
 | 
				
			||||||
 | 
					                otherwise
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            paramName = matlab.lang.makeValidName([defPrompt]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            val = def.Default;
 | 
				
			||||||
 | 
					            if islogical(val)
 | 
				
			||||||
 | 
					                if val
 | 
				
			||||||
 | 
					                    valStr = 'on';
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                    valStr = 'off';
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            elseif isnumeric(val)
 | 
				
			||||||
 | 
					                valStr = num2str(val);
 | 
				
			||||||
 | 
					            elseif ischar(val)
 | 
				
			||||||
 | 
					                valStr = val;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Добавляем параметр в маску (без TabName)
 | 
				
			||||||
 | 
					            mask.addParameter(...
 | 
				
			||||||
 | 
					                'Type', paramType, ...
 | 
				
			||||||
 | 
					                'Prompt', defPrompt, ...
 | 
				
			||||||
 | 
					                'Name', paramName, ...
 | 
				
			||||||
 | 
					                'Value', valStr, ...
 | 
				
			||||||
 | 
					                'Container', tabName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            param = mask.getParameter(paramName);
 | 
				
			||||||
 | 
					            param.Alias = def.Def;           
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% поиск вкладки
 | 
				
			||||||
 | 
					function tab = find_tab_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    tab = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, вкладка ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            tab = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это контейнер — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            tab = find_tab_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(tab)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function children = get_children(ctrl)
 | 
				
			||||||
 | 
					    if isprop(ctrl, 'DialogControls')
 | 
				
			||||||
 | 
					        children = ctrl.DialogControls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Controls')
 | 
				
			||||||
 | 
					        children = ctrl.Controls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Children')
 | 
				
			||||||
 | 
					        children = ctrl.Children;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        children = [];
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										458
									
								
								mexing.asv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										458
									
								
								mexing.asv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,458 @@
 | 
				
			|||||||
 | 
					% Компилирует S-function
 | 
				
			||||||
 | 
					clear, clc
 | 
				
			||||||
 | 
					close;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Ts = 0.00001;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					delete("*.mexw64")
 | 
				
			||||||
 | 
					delete("*.mexw64.pdb")
 | 
				
			||||||
 | 
					delete(".\MCU_Wrapper\Outputs\*.*");
 | 
				
			||||||
 | 
					set_param(gcb, 'consoleOutput', '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					% Флаг режима отладки
 | 
				
			||||||
 | 
					definesWrapperArg = buildWrapperDefinesString();
 | 
				
			||||||
 | 
					definesUserArg = parseDefinesMaskText();
 | 
				
			||||||
 | 
					definesConfigArg = buildConfigDefinesString();
 | 
				
			||||||
 | 
					definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if read_checkbox('enableDebug')
 | 
				
			||||||
 | 
					    modeArg = "debug";
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    modeArg = "release";
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if read_checkbox('fullOutput') || read_checkbox('extConsol') 
 | 
				
			||||||
 | 
					    echoArg = 'echo_enable';
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    echoArg = 'echo_disable';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					% Вызов батника с двумя параметрами: includes и code
 | 
				
			||||||
 | 
					cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if read_checkbox('extConsol')
 | 
				
			||||||
 | 
					    cmdout = runBatAndShowOutput(cmd);
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    [status, cmdout]= system(cmd);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					% Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
				
			||||||
 | 
					set_param(gcb, 'consoleOutput', cmdout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					% % Обновим Mask Display для показа
 | 
				
			||||||
 | 
					% maskDisplayStr = sprintf('disp(''%s'')', cmdout);
 | 
				
			||||||
 | 
					% set_param(gcb, 'MaskDisplay', maskDisplayStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					beep
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% COMPILE PARAMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
				
			||||||
 | 
					%MAKE_MEX_ARGUMENTS Формирует строки аргументов для вызова mex-компиляции через батник
 | 
				
			||||||
 | 
					%
 | 
				
			||||||
 | 
					% [includesArg, codeArg] = make_mex_arguments(includesCell, codeCell)
 | 
				
			||||||
 | 
					%
 | 
				
			||||||
 | 
					% Вход:
 | 
				
			||||||
 | 
					%   includesCell — ячейковый массив путей к директориям include
 | 
				
			||||||
 | 
					%   codeCell     — ячейковый массив исходных файлов
 | 
				
			||||||
 | 
					%
 | 
				
			||||||
 | 
					% Выход:
 | 
				
			||||||
 | 
					%   includesArg  — строка для передачи в батник, например: "-I"inc1" -I"inc2""
 | 
				
			||||||
 | 
					%   codeArg      — строка с исходниками, например: ""src1.c" "src2.cpp""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Здесь пример получения из маски текущего блока (замени по своему)
 | 
				
			||||||
 | 
					    blockHandle = gcbh;  % или замени на нужный блок
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    includesCell = parseCellString(get_param(blockHandle, incTableName));
 | 
				
			||||||
 | 
					    codeCell = parseCellString(get_param(blockHandle, srcTableame));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Оборачиваем пути в кавычки и добавляем -I
 | 
				
			||||||
 | 
					    includesStr = strjoin(cellfun(@(f) ['-I"' f '"'], includesCell, 'UniformOutput', false), ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Оборачиваем имена файлов в кавычки
 | 
				
			||||||
 | 
					    codeStr = strjoin(cellfun(@(f) ['"' f '"'], codeCell, 'UniformOutput', false), ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Удаляем символ переноса строки и пробел в конце, если вдруг попал
 | 
				
			||||||
 | 
					    codeStr = strtrim(codeStr);
 | 
				
			||||||
 | 
					    includesStr = strtrim(includesStr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Оборачиваем всю строку в кавычки, чтобы батник корректно понял
 | 
				
			||||||
 | 
					    % includesArg = ['"' includesStr '"'];
 | 
				
			||||||
 | 
					    % codeArg = ['"' codeStr '"'];
 | 
				
			||||||
 | 
					    includesArg = includesStr;
 | 
				
			||||||
 | 
					    codeArg = codeStr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesWrapperArg = buildWrapperDefinesString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    definesWrapperArg = '';
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % blockHandle = gcbh;
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Получаем MaskValues и MaskNames
 | 
				
			||||||
 | 
					    % maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
 | 
					    % paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Индексы параметров
 | 
				
			||||||
 | 
					    % idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
				
			||||||
 | 
					    % idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Значения
 | 
				
			||||||
 | 
					    % cyclesVal = maskValues{idxCycles};
 | 
				
			||||||
 | 
					    % clkMHz    = str2double(maskValues{idxClk});
 | 
				
			||||||
 | 
					    % clkHz     = round(clkMHz * 1e6);
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Формируем defines в формате: -D"NAME=VALUE"
 | 
				
			||||||
 | 
					    % if read_checkbox('enableThreading')
 | 
				
			||||||
 | 
					    %     def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def1 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % if read_checkbox('enableDeinit')
 | 
				
			||||||
 | 
					    %     def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def2 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
 | 
				
			||||||
 | 
					    % def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesUserArg = parseDefinesMaskText()
 | 
				
			||||||
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Получаем MaskValues и MaskNames
 | 
				
			||||||
 | 
					    maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
 | 
					    paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Индекс параметра userDefs
 | 
				
			||||||
 | 
					    idxUserDefs = find(strcmp(paramNames, 'userDefs'));
 | 
				
			||||||
 | 
					    definesText = maskValues{idxUserDefs}; % Текст с пользовательскими определениями
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Убираем буквальные символы \n и \r
 | 
				
			||||||
 | 
					    definesText = strrep(definesText, '\n', ' ');
 | 
				
			||||||
 | 
					    definesText = strrep(definesText, '\r', ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Разбиваем по переносам строк
 | 
				
			||||||
 | 
					    lines = split(definesText, {'\n', '\r\n', '\r'});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parts = strings(1,0); % пустой массив строк
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for k = 1:numel(lines)
 | 
				
			||||||
 | 
					        line = strtrim(lines{k});
 | 
				
			||||||
 | 
					        if isempty(line)
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Разбиваем по пробелам, чтобы получить отдельные определения в строке
 | 
				
			||||||
 | 
					        tokens = split(line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for t = 1:numel(tokens)
 | 
				
			||||||
 | 
					            token = strtrim(tokens{t});
 | 
				
			||||||
 | 
					            if isempty(token)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            eqIdx = strfind(token, '=');
 | 
				
			||||||
 | 
					            if isempty(eqIdx)
 | 
				
			||||||
 | 
					                % Просто ключ без значения
 | 
				
			||||||
 | 
					                parts(end+1) = sprintf('-D"%s"', token);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                key = strtrim(token(1:eqIdx(1)-1));
 | 
				
			||||||
 | 
					                val = strtrim(token(eqIdx(1)+1:end));
 | 
				
			||||||
 | 
					                parts(end+1) = sprintf('-D"%s__EQ__%s"', key, val);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    definesUserArg = strjoin(parts, ' ');
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesWrapperArg = buildConfigDefinesString()
 | 
				
			||||||
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tabName = 'configTab';  % Имя вкладки (Prompt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    tabCtrl = find_tab_by_name(allControls, tabName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(tabCtrl)
 | 
				
			||||||
 | 
					        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    definesWrapperArg = '';
 | 
				
			||||||
 | 
					    % Получаем все контролы внутри вкладки
 | 
				
			||||||
 | 
					    children = tabCtrl.DialogControls;
 | 
				
			||||||
 | 
					    for i = 1:numel(children)
 | 
				
			||||||
 | 
					        ctrl = children(i);
 | 
				
			||||||
 | 
					isprop(ctrl, 'Type')
 | 
				
			||||||
 | 
					isprop(ctrl, 'Name')
 | 
				
			||||||
 | 
					        if isprop(ctrl, 'Type') && isprop(ctrl, 'Name')
 | 
				
			||||||
 | 
					            switch lower(ctrl.Type)
 | 
				
			||||||
 | 
					                case 'checkbox'
 | 
				
			||||||
 | 
					                    definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 0);
 | 
				
			||||||
 | 
					                case 'edit'
 | 
				
			||||||
 | 
					                    definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 1);
 | 
				
			||||||
 | 
					                otherwise
 | 
				
			||||||
 | 
					                    % Пропускаем другие типы
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % blockHandle = gcbh;
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Получаем MaskValues и MaskNames
 | 
				
			||||||
 | 
					    % maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
 | 
					    % paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Индексы параметров
 | 
				
			||||||
 | 
					    % idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
				
			||||||
 | 
					    % idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Значения
 | 
				
			||||||
 | 
					    % cyclesVal = maskValues{idxCycles};
 | 
				
			||||||
 | 
					    % clkMHz    = str2double(maskValues{idxClk});
 | 
				
			||||||
 | 
					    % clkHz     = round(clkMHz * 1e6);
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Формируем defines в формате: -D"NAME=VALUE"
 | 
				
			||||||
 | 
					    % if read_checkbox('enableThreading')
 | 
				
			||||||
 | 
					    %     def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def1 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % if read_checkbox('enableDeinit')
 | 
				
			||||||
 | 
					    %     def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def2 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
 | 
				
			||||||
 | 
					    % def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% PARSE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function out = parseCellString(str)
 | 
				
			||||||
 | 
					    str = strtrim(str);
 | 
				
			||||||
 | 
					    if startsWith(str, '{') && endsWith(str, '}')
 | 
				
			||||||
 | 
					        str = str(2:end-1);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parts = split(str, ';');
 | 
				
			||||||
 | 
					    out = cell(numel(parts), 1);
 | 
				
			||||||
 | 
					    for i = 1:numel(parts)
 | 
				
			||||||
 | 
					        el = strtrim(parts{i});
 | 
				
			||||||
 | 
					        if startsWith(el, '''') && endsWith(el, '''')
 | 
				
			||||||
 | 
					            el = el(2:end-1);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					        out{i} = el;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(out) || (numel(out) == 1 && isempty(out{1}))
 | 
				
			||||||
 | 
					        out = {};
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function str = cellArrayToString(cellArray)
 | 
				
			||||||
 | 
					    quoted = cellfun(@(s) ['''' s ''''], cellArray, 'UniformOutput', false);
 | 
				
			||||||
 | 
					    str = ['{' strjoin(quoted, ';') '}'];
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
 | 
				
			||||||
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Получаем MaskValues, MaskNames
 | 
				
			||||||
 | 
					    maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
 | 
					    paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
 | 
					    param = mask.getParameter(paramName); % для alias
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Найдём индекс нужного параметра
 | 
				
			||||||
 | 
					    idxParam = find(strcmp(paramNames, paramName), 1);
 | 
				
			||||||
 | 
					    if isempty(idxParam)
 | 
				
			||||||
 | 
					        error('Parameter "%s" not found in block mask parameters.', paramName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Берём alias из маски
 | 
				
			||||||
 | 
					    alias = param.Alias;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if val_define ~= 0
 | 
				
			||||||
 | 
					        % Значение параметра
 | 
				
			||||||
 | 
					        val = maskValues{idxParam};
 | 
				
			||||||
 | 
					        % Формируем define с кавычками и значением
 | 
				
			||||||
 | 
					        newDefine = ['-D"' alias '__EQ__' val '"'];
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        if read_checkbox(paramName)
 | 
				
			||||||
 | 
					            % Формируем define с кавычками без значения
 | 
				
			||||||
 | 
					            newDefine = ['-D"' alias '"'];
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            newDefine = '';
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Добавляем новый define к существующему (string)
 | 
				
			||||||
 | 
					    if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
 | 
				
			||||||
 | 
					        definesWrapperArg = newDefine;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        definesWrapperArg = definesWrapperArg + " " + newDefine;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function checkbox_state = read_checkbox(checkboxName)
 | 
				
			||||||
 | 
					    maskValues = get_param(gcbh, 'MaskValues');
 | 
				
			||||||
 | 
					    paramNames = get_param(gcbh, 'MaskNames');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    inxCheckBox = find(strcmp(paramNames, checkboxName));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    checkbox_state_str = maskValues{inxCheckBox};
 | 
				
			||||||
 | 
					    if strcmpi(checkbox_state_str, 'on')
 | 
				
			||||||
 | 
					        checkbox_state = 1;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        checkbox_state = 0;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function tab = find_tab_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    tab = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, вкладка ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            tab = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это контейнер — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            tab = find_tab_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(tab)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function children = get_children(ctrl)
 | 
				
			||||||
 | 
					    if isprop(ctrl, 'DialogControls')
 | 
				
			||||||
 | 
					        children = ctrl.DialogControls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Controls')
 | 
				
			||||||
 | 
					        children = ctrl.Controls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Children')
 | 
				
			||||||
 | 
					        children = ctrl.Children;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        children = [];
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% CONSOLE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function cmdret = runBatAndShowOutput(cmd)
 | 
				
			||||||
 | 
					    import java.io.*;
 | 
				
			||||||
 | 
					    import java.lang.*;
 | 
				
			||||||
 | 
					    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
				
			||||||
 | 
					    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
				
			||||||
 | 
					    pb.redirectErrorStream(true);
 | 
				
			||||||
 | 
					    process = pb.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while true
 | 
				
			||||||
 | 
					        if reader.ready()
 | 
				
			||||||
 | 
					            line = char(reader.readLine());
 | 
				
			||||||
 | 
					            if isempty(line)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
				
			||||||
 | 
					            % Здесь выводим только новую строку
 | 
				
			||||||
 | 
					            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
				
			||||||
 | 
					            logWindow_append(safeLine);
 | 
				
			||||||
 | 
					            drawnow; % обновляем GUI
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            if ~process.isAlive()
 | 
				
			||||||
 | 
					                % дочитываем оставшиеся строки
 | 
				
			||||||
 | 
					                while reader.ready()
 | 
				
			||||||
 | 
					                    line = char(reader.readLine());
 | 
				
			||||||
 | 
					                    if isempty(line)
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    end
 | 
				
			||||||
 | 
					                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
				
			||||||
 | 
					                    safeLine = strrep(line, '''', '''''');
 | 
				
			||||||
 | 
					                    logWindow_append(safeLine);
 | 
				
			||||||
 | 
					                    drawnow;
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            pause(0.2);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    process.waitFor();
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function logWindow_append(line)
 | 
				
			||||||
 | 
					    persistent fig hEdit jScrollPane jTextArea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(fig) || ~isvalid(fig)
 | 
				
			||||||
 | 
					        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
				
			||||||
 | 
					        hEdit = uicontrol('Style', 'edit', ...
 | 
				
			||||||
 | 
					            'Max', 2, 'Min', 0, ...
 | 
				
			||||||
 | 
					            'Enable', 'on', ...
 | 
				
			||||||
 | 
					            'FontName', 'Courier New', ...
 | 
				
			||||||
 | 
					            'Position', [10 10 580 380], ...
 | 
				
			||||||
 | 
					            'HorizontalAlignment', 'left', ...
 | 
				
			||||||
 | 
					            'BackgroundColor', 'white', ...
 | 
				
			||||||
 | 
					            'Tag', 'LogWindowFigure');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
				
			||||||
 | 
					        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    oldText = get(hEdit, 'String');
 | 
				
			||||||
 | 
					    if ischar(oldText)
 | 
				
			||||||
 | 
					        oldText = {oldText};
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set(hEdit, 'String', [oldText; {line}]);
 | 
				
			||||||
 | 
					    drawnow;
 | 
				
			||||||
 | 
					    % Автоскролл вниз:
 | 
				
			||||||
 | 
					    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
				
			||||||
 | 
					    drawnow;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										441
									
								
								mexing.m
									
									
									
									
									
								
							
							
						
						
									
										441
									
								
								mexing.m
									
									
									
									
									
								
							@ -8,30 +8,22 @@ Ts = 0.00001;
 | 
				
			|||||||
delete("*.mexw64")
 | 
					delete("*.mexw64")
 | 
				
			||||||
delete("*.mexw64.pdb")
 | 
					delete("*.mexw64.pdb")
 | 
				
			||||||
delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					delete(".\MCU_Wrapper\Outputs\*.*");
 | 
				
			||||||
 | 
					set_param(gcb, 'consoleOutput', '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
% Флаг режима отладки
 | 
					% Флаг режима отладки
 | 
				
			||||||
definesArg = buildDefinesString();
 | 
					definesWrapperArg = buildWrapperDefinesString();
 | 
				
			||||||
definesUserArg = parseDefinesMaskText();
 | 
					definesUserArg = parseDefinesMaskText();
 | 
				
			||||||
definesAllArg = [definesArg + " " + definesUserArg];    
 | 
					definesConfigArg = buildConfigDefinesString();
 | 
				
			||||||
 | 
					definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
maskValues = get_param(gcbh, 'MaskValues');
 | 
					 | 
				
			||||||
paramNames = get_param(gcbh, 'MaskNames');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
inxDebug = find(strcmp(paramNames, 'enableDebug'));
 | 
					if read_checkbox('enableDebug')
 | 
				
			||||||
idxExtConsole = find(strcmp(paramNames, 'extConsol'));
 | 
					 | 
				
			||||||
idxFullOutput = find(strcmp(paramNames, 'fullOutput'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
isDebug = maskValues{inxDebug};
 | 
					 | 
				
			||||||
isExtConsole = maskValues{idxExtConsole};
 | 
					 | 
				
			||||||
isFullOutput = maskValues{idxFullOutput};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if strcmpi(isDebug, 'on')
 | 
					 | 
				
			||||||
    modeArg = "debug";
 | 
					    modeArg = "debug";
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
    modeArg = "release";
 | 
					    modeArg = "release";
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if strcmpi(isFullOutput, 'on')
 | 
					if read_checkbox('fullOutput') || read_checkbox('extConsol') 
 | 
				
			||||||
    echoArg = 'echo_enable';
 | 
					    echoArg = 'echo_enable';
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
    echoArg = 'echo_disable';
 | 
					    echoArg = 'echo_disable';
 | 
				
			||||||
@ -40,13 +32,12 @@ end
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
					[includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set_param(gcb, 'consoleOutput', '');
 | 
					 | 
				
			||||||
% Вызов батника с двумя параметрами: includes и code
 | 
					% Вызов батника с двумя параметрами: includes и code
 | 
				
			||||||
cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
					cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(strcmpi(isExtConsole, 'on'))
 | 
					if read_checkbox('extConsol')
 | 
				
			||||||
    cmdout = runBatAndShowOutput(cmd);
 | 
					    cmdout = runBatAndShowOutput(cmd);
 | 
				
			||||||
else
 | 
					else
 | 
				
			||||||
    [status, cmdout]= system(cmd);
 | 
					    [status, cmdout]= system(cmd);
 | 
				
			||||||
@ -63,7 +54,7 @@ beep
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
%%
 | 
					%% COMPILE PARAMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
					function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
				
			||||||
@ -104,126 +95,47 @@ function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					 | 
				
			||||||
    import java.io.*;
 | 
					 | 
				
			||||||
    import java.lang.*;
 | 
					 | 
				
			||||||
    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
					 | 
				
			||||||
    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
					 | 
				
			||||||
    pb.redirectErrorStream(true);
 | 
					 | 
				
			||||||
    process = pb.start();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
					function definesWrapperArg = buildWrapperDefinesString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
					    definesWrapperArg = '';
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
				
			||||||
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while true
 | 
					    % blockHandle = gcbh;
 | 
				
			||||||
        if reader.ready()
 | 
					    % 
 | 
				
			||||||
            line = char(reader.readLine());
 | 
					    % % Получаем MaskValues и MaskNames
 | 
				
			||||||
            if isempty(line)
 | 
					    % maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
                break;
 | 
					    % paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
            end
 | 
					    % 
 | 
				
			||||||
            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					    % % Индексы параметров
 | 
				
			||||||
            % Здесь выводим только новую строку
 | 
					    % idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
				
			||||||
            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
					    % idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
				
			||||||
            logWindow_append(safeLine);
 | 
					    % 
 | 
				
			||||||
            drawnow; % обновляем GUI
 | 
					    % % Значения
 | 
				
			||||||
        else
 | 
					    % cyclesVal = maskValues{idxCycles};
 | 
				
			||||||
            if ~process.isAlive()
 | 
					    % clkMHz    = str2double(maskValues{idxClk});
 | 
				
			||||||
                % дочитываем оставшиеся строки
 | 
					    % clkHz     = round(clkMHz * 1e6);
 | 
				
			||||||
                while reader.ready()
 | 
					    % 
 | 
				
			||||||
                    line = char(reader.readLine());
 | 
					    % % Формируем defines в формате: -D"NAME=VALUE"
 | 
				
			||||||
                    if isempty(line)
 | 
					    % if read_checkbox('enableThreading')
 | 
				
			||||||
                        break;
 | 
					    %     def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
 | 
				
			||||||
                    end
 | 
					    % else
 | 
				
			||||||
                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					    %     def1 = [''];
 | 
				
			||||||
                    safeLine = strrep(line, '''', '''''');
 | 
					    % end
 | 
				
			||||||
                    logWindow_append(safeLine);
 | 
					    % 
 | 
				
			||||||
                    drawnow;
 | 
					    % if read_checkbox('enableDeinit')
 | 
				
			||||||
                end
 | 
					    %     def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
 | 
				
			||||||
                break;
 | 
					    % else
 | 
				
			||||||
            end
 | 
					    %     def2 = [''];
 | 
				
			||||||
            pause(0.2);
 | 
					    % end
 | 
				
			||||||
        end
 | 
					    % 
 | 
				
			||||||
    end
 | 
					    % def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
 | 
				
			||||||
    process.waitFor();
 | 
					    % def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
 | 
				
			||||||
end
 | 
					    % 
 | 
				
			||||||
 | 
					    % definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
 | 
				
			||||||
 | 
					 | 
				
			||||||
function logWindow_append(line)
 | 
					 | 
				
			||||||
    persistent fig hEdit jScrollPane jTextArea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(fig) || ~isvalid(fig)
 | 
					 | 
				
			||||||
        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
					 | 
				
			||||||
        hEdit = uicontrol('Style', 'edit', ...
 | 
					 | 
				
			||||||
            'Max', 2, 'Min', 0, ...
 | 
					 | 
				
			||||||
            'Enable', 'on', ...                   % Включаем взаимодействие
 | 
					 | 
				
			||||||
            'FontName', 'Courier New', ...
 | 
					 | 
				
			||||||
            'Position', [10 10 580 380], ...
 | 
					 | 
				
			||||||
            'HorizontalAlignment', 'left', ...
 | 
					 | 
				
			||||||
            'BackgroundColor', 'white', ...
 | 
					 | 
				
			||||||
            'Tag', 'LogWindowFigure');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
					 | 
				
			||||||
        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    oldText = get(hEdit, 'String');
 | 
					 | 
				
			||||||
    if ischar(oldText)
 | 
					 | 
				
			||||||
        oldText = {oldText};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    set(hEdit, 'String', [oldText; {line}]);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Автоскролл вниз:
 | 
					 | 
				
			||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesArg = buildDefinesString()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Индексы параметров
 | 
					 | 
				
			||||||
    idxThreading = find(strcmp(paramNames, 'enableThreading'));
 | 
					 | 
				
			||||||
    idxDeinit = find(strcmp(paramNames, 'enableDeinit'));
 | 
					 | 
				
			||||||
    idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
					 | 
				
			||||||
    idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if any([isempty(idxThreading), isempty(idxDeinit),isempty(idxCycles), isempty(idxClk)])
 | 
					 | 
				
			||||||
        error('Один или несколько параметров не найдены в маске');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Значения
 | 
					 | 
				
			||||||
    ThreadingVal = maskValues{idxThreading};
 | 
					 | 
				
			||||||
    DeinitVal = maskValues{idxDeinit};
 | 
					 | 
				
			||||||
    cyclesVal = maskValues{idxCycles};
 | 
					 | 
				
			||||||
    clkMHz    = str2double(maskValues{idxClk});
 | 
					 | 
				
			||||||
    clkHz     = round(clkMHz * 1e6);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Формируем defines в формате: -D"NAME=VALUE"
 | 
					 | 
				
			||||||
    if strcmpi(ThreadingVal, 'on')
 | 
					 | 
				
			||||||
        def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        def1 = [''];
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if strcmpi(DeinitVal, 'on')
 | 
					 | 
				
			||||||
        def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        def2 = [''];
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
 | 
					 | 
				
			||||||
    def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesArg = strjoin({def1, def2, def3, def4}, ' ');
 | 
					 | 
				
			||||||
    % definesArg = ['"' definesStr ''];
 | 
					 | 
				
			||||||
    % definesArg = definesStr;
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -279,6 +191,79 @@ end
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesWrapperArg = buildConfigDefinesString()
 | 
				
			||||||
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tabName = 'configTab';  % Имя вкладки (Prompt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    tabCtrl = find_tab_by_name(allControls, tabName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(tabCtrl)
 | 
				
			||||||
 | 
					        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    definesWrapperArg = '';
 | 
				
			||||||
 | 
					    % Получаем все контролы внутри вкладки
 | 
				
			||||||
 | 
					    children = tabCtrl.DialogControls;
 | 
				
			||||||
 | 
					    for i = 1:numel(children)
 | 
				
			||||||
 | 
					        ctrl = children(i);
 | 
				
			||||||
 | 
					        % Получаем имя параметра из контрола
 | 
				
			||||||
 | 
					        paramName = ctrl.Name;
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					                % Получаем объект параметра по имени
 | 
				
			||||||
 | 
					                param = mask.getParameter(paramName);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					                % Определяем тип параметра
 | 
				
			||||||
 | 
					                switch lower(param.Type)
 | 
				
			||||||
 | 
					                    case 'checkbox'
 | 
				
			||||||
 | 
					                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
 | 
				
			||||||
 | 
					                    case 'edit'
 | 
				
			||||||
 | 
					                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
 | 
				
			||||||
 | 
					                    otherwise
 | 
				
			||||||
 | 
					                        % Необрабатываемые типы
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            catch ME
 | 
				
			||||||
 | 
					                warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % blockHandle = gcbh;
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Получаем MaskValues и MaskNames
 | 
				
			||||||
 | 
					    % maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
 | 
					    % paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Индексы параметров
 | 
				
			||||||
 | 
					    % idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
				
			||||||
 | 
					    % idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Значения
 | 
				
			||||||
 | 
					    % cyclesVal = maskValues{idxCycles};
 | 
				
			||||||
 | 
					    % clkMHz    = str2double(maskValues{idxClk});
 | 
				
			||||||
 | 
					    % clkHz     = round(clkMHz * 1e6);
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % % Формируем defines в формате: -D"NAME=VALUE"
 | 
				
			||||||
 | 
					    % if read_checkbox('enableThreading')
 | 
				
			||||||
 | 
					    %     def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def1 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % if read_checkbox('enableDeinit')
 | 
				
			||||||
 | 
					    %     def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
 | 
				
			||||||
 | 
					    % else
 | 
				
			||||||
 | 
					    %     def2 = [''];
 | 
				
			||||||
 | 
					    % end
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
 | 
				
			||||||
 | 
					    % def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
 | 
				
			||||||
 | 
					    % 
 | 
				
			||||||
 | 
					    % definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% PARSE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function out = parseCellString(str)
 | 
					function out = parseCellString(str)
 | 
				
			||||||
    str = strtrim(str);
 | 
					    str = strtrim(str);
 | 
				
			||||||
@ -307,23 +292,173 @@ function str = cellArrayToString(cellArray)
 | 
				
			|||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
 | 
				
			||||||
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
% % Компилирует S-function
 | 
					    % Получаем MaskValues, MaskNames
 | 
				
			||||||
% clear, clc,
 | 
					    maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
% 
 | 
					    paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
% set = mex.getCompilerConfigurations('C', 'Selected');
 | 
					    param = mask.getParameter(paramName); % для alias
 | 
				
			||||||
% 
 | 
					
 | 
				
			||||||
% Ts = 0.00001;
 | 
					    % Найдём индекс нужного параметра
 | 
				
			||||||
% 
 | 
					    idxParam = find(strcmp(paramNames, paramName), 1);
 | 
				
			||||||
% delete("*.mexw64")
 | 
					    if isempty(idxParam)
 | 
				
			||||||
% delete("*.mexw64.pdb")
 | 
					        error('Parameter "%s" not found in block mask parameters.', paramName);
 | 
				
			||||||
% delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					    end
 | 
				
			||||||
% 
 | 
					
 | 
				
			||||||
% status=system('.\MCU_Wrapper\run_mex.bat debug');
 | 
					    % Берём alias из маски
 | 
				
			||||||
% 
 | 
					    alias = param.Alias;
 | 
				
			||||||
% if status==0
 | 
					
 | 
				
			||||||
%     beep
 | 
					    if val_define ~= 0
 | 
				
			||||||
% else
 | 
					        % Значение параметра
 | 
				
			||||||
%     error('Error!');
 | 
					        val = maskValues{idxParam};
 | 
				
			||||||
% end
 | 
					        % Формируем define с кавычками и значением
 | 
				
			||||||
% 
 | 
					        newDefine = ['-D"' alias '__EQ__' val '"'];
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        if read_checkbox(paramName)
 | 
				
			||||||
 | 
					            % Формируем define с кавычками без значения
 | 
				
			||||||
 | 
					            newDefine = ['-D"' alias '"'];
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            newDefine = '';
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Добавляем новый define к существующему (string)
 | 
				
			||||||
 | 
					    if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
 | 
				
			||||||
 | 
					        definesWrapperArg = newDefine;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        definesWrapperArg = definesWrapperArg + " " + newDefine;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function checkbox_state = read_checkbox(checkboxName)
 | 
				
			||||||
 | 
					    maskValues = get_param(gcbh, 'MaskValues');
 | 
				
			||||||
 | 
					    paramNames = get_param(gcbh, 'MaskNames');
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    inxCheckBox = find(strcmp(paramNames, checkboxName));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    checkbox_state_str = maskValues{inxCheckBox};
 | 
				
			||||||
 | 
					    if strcmpi(checkbox_state_str, 'on')
 | 
				
			||||||
 | 
					        checkbox_state = 1;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        checkbox_state = 0;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function tab = find_tab_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    tab = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, вкладка ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            tab = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это контейнер — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            tab = find_tab_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(tab)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function children = get_children(ctrl)
 | 
				
			||||||
 | 
					    if isprop(ctrl, 'DialogControls')
 | 
				
			||||||
 | 
					        children = ctrl.DialogControls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Controls')
 | 
				
			||||||
 | 
					        children = ctrl.Controls;
 | 
				
			||||||
 | 
					    elseif isprop(ctrl, 'Children')
 | 
				
			||||||
 | 
					        children = ctrl.Children;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        children = [];
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% CONSOLE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function cmdret = runBatAndShowOutput(cmd)
 | 
				
			||||||
 | 
					    import java.io.*;
 | 
				
			||||||
 | 
					    import java.lang.*;
 | 
				
			||||||
 | 
					    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
				
			||||||
 | 
					    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
				
			||||||
 | 
					    pb.redirectErrorStream(true);
 | 
				
			||||||
 | 
					    process = pb.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while true
 | 
				
			||||||
 | 
					        if reader.ready()
 | 
				
			||||||
 | 
					            line = char(reader.readLine());
 | 
				
			||||||
 | 
					            if isempty(line)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
				
			||||||
 | 
					            % Здесь выводим только новую строку
 | 
				
			||||||
 | 
					            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
				
			||||||
 | 
					            logWindow_append(safeLine);
 | 
				
			||||||
 | 
					            drawnow; % обновляем GUI
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            if ~process.isAlive()
 | 
				
			||||||
 | 
					                % дочитываем оставшиеся строки
 | 
				
			||||||
 | 
					                while reader.ready()
 | 
				
			||||||
 | 
					                    line = char(reader.readLine());
 | 
				
			||||||
 | 
					                    if isempty(line)
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                    end
 | 
				
			||||||
 | 
					                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
				
			||||||
 | 
					                    safeLine = strrep(line, '''', '''''');
 | 
				
			||||||
 | 
					                    logWindow_append(safeLine);
 | 
				
			||||||
 | 
					                    drawnow;
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					            pause(0.2);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					    process.waitFor();
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function logWindow_append(line)
 | 
				
			||||||
 | 
					    persistent fig hEdit jScrollPane jTextArea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(fig) || ~isvalid(fig)
 | 
				
			||||||
 | 
					        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
				
			||||||
 | 
					        hEdit = uicontrol('Style', 'edit', ...
 | 
				
			||||||
 | 
					            'Max', 2, 'Min', 0, ...
 | 
				
			||||||
 | 
					            'Enable', 'on', ...
 | 
				
			||||||
 | 
					            'FontName', 'Courier New', ...
 | 
				
			||||||
 | 
					            'Position', [10 10 580 380], ...
 | 
				
			||||||
 | 
					            'HorizontalAlignment', 'left', ...
 | 
				
			||||||
 | 
					            'BackgroundColor', 'white', ...
 | 
				
			||||||
 | 
					            'Tag', 'LogWindowFigure');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
				
			||||||
 | 
					        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    oldText = get(hEdit, 'String');
 | 
				
			||||||
 | 
					    if ischar(oldText)
 | 
				
			||||||
 | 
					        oldText = {oldText};
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    set(hEdit, 'String', [oldText; {line}]);
 | 
				
			||||||
 | 
					    drawnow;
 | 
				
			||||||
 | 
					    % Автоскролл вниз:
 | 
				
			||||||
 | 
					    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
				
			||||||
 | 
					    drawnow;
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								mycode.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								mycode.c
									
									
									
									
									
								
							@ -1,14 +0,0 @@
 | 
				
			|||||||
void app_init() {
 | 
					 | 
				
			||||||
    // code of foo
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_step() {
 | 
					 | 
				
			||||||
    // code of foo
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_readInputs() {
 | 
					 | 
				
			||||||
    // code of foo
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
void app_writeOutputBuffer() {
 | 
					 | 
				
			||||||
    // code of foo
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										38
									
								
								periph_config.asv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								periph_config.asv
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "ADC": {
 | 
				
			||||||
 | 
					    "Defines": {
 | 
				
			||||||
 | 
					      "ADC1 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC1_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "ADC2 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC2_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "SAMPLE_RATE": {
 | 
				
			||||||
 | 
					        "Type": "edit",
 | 
				
			||||||
 | 
					        "Default": 48000
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "TIM": {
 | 
				
			||||||
 | 
					    "Defines": {
 | 
				
			||||||
 | 
					      "TIM1 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC1_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "TIM2 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC2_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "AHB Buf Clock Rate": {
 | 
				
			||||||
 | 
					        "Type": "edit",
 | 
				
			||||||
 | 
					        "Default": 72
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										40
									
								
								periph_config.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								periph_config.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "ADC": {
 | 
				
			||||||
 | 
					    "Defines": {
 | 
				
			||||||
 | 
					      "ADC1 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC1_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "ADC2 Enable": {
 | 
				
			||||||
 | 
					        "Def": "ADC2_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "Sample Rate (Hz)": {
 | 
				
			||||||
 | 
					        "Def": "SAMPLE_RATE",
 | 
				
			||||||
 | 
					        "Type": "edit",
 | 
				
			||||||
 | 
					        "Default": 48000
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "TIM": {
 | 
				
			||||||
 | 
					    "Defines": {
 | 
				
			||||||
 | 
					      "TIM1 Enable": {
 | 
				
			||||||
 | 
					        "Def": "TIM1_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "TIM2 Enable": {
 | 
				
			||||||
 | 
					        "Def": "TIM2_ENABLE",
 | 
				
			||||||
 | 
					        "Type": "checkbox",
 | 
				
			||||||
 | 
					        "Default": true
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "AHB Buf Clock Rate (MHz)": {
 | 
				
			||||||
 | 
					        "Def": "AHB_BUS_FREQ",
 | 
				
			||||||
 | 
					        "Type": "edit",
 | 
				
			||||||
 | 
					        "Default": 72
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user