чуть ранее работало идеально, но ща решил сделать парс конфига по вкладкам
This commit is contained in:
		
							parent
							
								
									ead46d7d82
								
							
						
					
					
						commit
						0a4a87038e
					
				@ -1,159 +0,0 @@
 | 
				
			|||||||
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
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								config_reader.m
									
									
									
									
									
								
							@ -1,134 +0,0 @@
 | 
				
			|||||||
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.
										
									
								
							
							
								
								
									
										503
									
								
								mexing.asv
									
									
									
									
									
								
							
							
						
						
									
										503
									
								
								mexing.asv
									
									
									
									
									
								
							@ -1,59 +1,54 @@
 | 
				
			|||||||
% Компилирует S-function
 | 
					% Компилирует S-function
 | 
				
			||||||
clear, clc
 | 
					function mexing(compile_mode)
 | 
				
			||||||
close;
 | 
					    global Ts
 | 
				
			||||||
 | 
					    Ts = 0.00001;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    if compile_mode == 1
 | 
				
			||||||
 | 
					        delete("*.mexw64")
 | 
				
			||||||
 | 
					        delete("*.mexw64.pdb")
 | 
				
			||||||
 | 
					        delete(".\MCU_Wrapper\Outputs\*.*");
 | 
				
			||||||
 | 
					        set_param(gcb, 'consoleOutput', '');    
 | 
				
			||||||
 | 
					        % Дефайны
 | 
				
			||||||
 | 
					        definesWrapperArg = buildWrapperDefinesString();
 | 
				
			||||||
 | 
					        definesUserArg = parseDefinesMaskText();
 | 
				
			||||||
 | 
					        definesConfigArg = buildConfigDefinesString();
 | 
				
			||||||
 | 
					        definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
Ts = 0.00001;
 | 
					        %режимы компиляции
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
delete("*.mexw64")
 | 
					        [includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
				
			||||||
delete("*.mexw64.pdb")
 | 
					 | 
				
			||||||
delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					 | 
				
			||||||
set_param(gcb, 'consoleOutput', '');
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
% Флаг режима отладки
 | 
					        % Вызов батника с двумя параметрами: includes и code
 | 
				
			||||||
definesWrapperArg = buildWrapperDefinesString();
 | 
					        cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
				
			||||||
definesUserArg = parseDefinesMaskText();
 | 
					 | 
				
			||||||
definesConfigArg = buildConfigDefinesString();
 | 
					 | 
				
			||||||
definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
 | 
					        if read_checkbox('extConsol')
 | 
				
			||||||
 | 
					            cmdout = runBatAndShowOutput(cmd);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            [status, cmdout]= system(cmd);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
if read_checkbox('enableDebug')
 | 
					        % Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
				
			||||||
    modeArg = "debug";
 | 
					        set_param(gcb, 'consoleOutput', cmdout);
 | 
				
			||||||
else
 | 
					        
 | 
				
			||||||
    modeArg = "release";
 | 
					        beep
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        blockPath = bdroot;
 | 
				
			||||||
 | 
					        config = load_periph_config();
 | 
				
			||||||
 | 
					        update_mask_from_config(blockPath, config);
 | 
				
			||||||
 | 
					        % set_param(gcb, 'consoleOutput', 'Peripheral configuration file loaded. Re-open Block Parameters');
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
end
 | 
					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
 | 
					%% COMPILE PARAMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,45 +98,11 @@ function definesWrapperArg = buildWrapperDefinesString()
 | 
				
			|||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 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
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function definesUserArg = parseDefinesMaskText()
 | 
					function definesUserArg = parseDefinesMaskText()
 | 
				
			||||||
    blockHandle = gcbh;
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					    % Получаем MaskValues и MaskNames
 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					    maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					    paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
@ -208,52 +169,25 @@ function definesWrapperArg = buildConfigDefinesString()
 | 
				
			|||||||
    children = tabCtrl.DialogControls;
 | 
					    children = tabCtrl.DialogControls;
 | 
				
			||||||
    for i = 1:numel(children)
 | 
					    for i = 1:numel(children)
 | 
				
			||||||
        ctrl = children(i);
 | 
					        ctrl = children(i);
 | 
				
			||||||
isprop(ctrl, 'Type')
 | 
					        % Получаем имя параметра из контрола
 | 
				
			||||||
isprop(ctrl, 'Name')
 | 
					        paramName = ctrl.Name;
 | 
				
			||||||
        if isprop(ctrl, 'Type') && isprop(ctrl, 'Name')
 | 
					            try
 | 
				
			||||||
            switch lower(ctrl.Type)
 | 
					                % Получаем объект параметра по имени
 | 
				
			||||||
                case 'checkbox'
 | 
					                param = mask.getParameter(paramName);
 | 
				
			||||||
                    definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 0);
 | 
					 | 
				
			||||||
                case 'edit'
 | 
					 | 
				
			||||||
                    definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 1);
 | 
					 | 
				
			||||||
                otherwise
 | 
					 | 
				
			||||||
                    % Пропускаем другие типы
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    % blockHandle = gcbh;
 | 
					                % Определяем тип параметра
 | 
				
			||||||
    % 
 | 
					                switch lower(param.Type)
 | 
				
			||||||
    % % Получаем MaskValues и MaskNames
 | 
					                    case 'checkbox'
 | 
				
			||||||
    % maskValues = get_param(blockHandle, 'MaskValues');
 | 
					                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
 | 
				
			||||||
    % paramNames = get_param(blockHandle, 'MaskNames');
 | 
					                    case 'edit'
 | 
				
			||||||
    % 
 | 
					                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
 | 
				
			||||||
    % % Индексы параметров
 | 
					                    otherwise
 | 
				
			||||||
    % idxCycles = find(strcmp(paramNames, 'threadCycles'));
 | 
					                        % Необрабатываемые типы
 | 
				
			||||||
    % idxClk    = find(strcmp(paramNames, 'mcuClk'));
 | 
					                end
 | 
				
			||||||
    % 
 | 
					            catch ME
 | 
				
			||||||
    % % Значения
 | 
					                warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
				
			||||||
    % cyclesVal = maskValues{idxCycles};
 | 
					            end
 | 
				
			||||||
    % clkMHz    = str2double(maskValues{idxClk});
 | 
					    end
 | 
				
			||||||
    % 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
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -344,42 +278,6 @@ function checkbox_state = read_checkbox(checkboxName)
 | 
				
			|||||||
    end
 | 
					    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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONSOLE FUNCTIONS
 | 
					%% CONSOLE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					function cmdret = runBatAndShowOutput(cmd)
 | 
				
			||||||
@ -456,3 +354,284 @@ function logWindow_append(line)
 | 
				
			|||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
				
			||||||
    drawnow;
 | 
					    drawnow;
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% READ CONFIGS
 | 
				
			||||||
 | 
					function config = load_periph_config()
 | 
				
			||||||
 | 
					    jsonText = fileread('periph_config.json');
 | 
				
			||||||
 | 
					    config = jsondecode(jsonText);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% CONFIG MASK TOOLS
 | 
				
			||||||
 | 
					function update_mask_from_config(blockPath, config)
 | 
				
			||||||
 | 
					    blockPath = [blockPath '/MCU'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Проверяем, была ли маска открыта
 | 
				
			||||||
 | 
					    wasOpen = isMaskDialogOpen(blockPath);
 | 
				
			||||||
 | 
					    close_system(blockPath, 0);
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockPath);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    tableNames = {'incTable', 'srcTable'};
 | 
				
			||||||
 | 
					    columns_backup = clear_tables(blockPath, tableNames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    containerName = 'configTabAll';
 | 
				
			||||||
 | 
					    clear_all_from_container(mask, containerName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Ищем контейнер, в который будем добавлять вкладки
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    container = find_container_by_name(allControls, containerName);
 | 
				
			||||||
 | 
					    if isempty(container)
 | 
				
			||||||
 | 
					        error('Контейнер "%s" не найден в маске.', containerName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Проходим по каждому модулю (ADC, TIM...)
 | 
				
			||||||
 | 
					    periphs = fieldnames(config);
 | 
				
			||||||
 | 
					    for i = 1:numel(periphs)
 | 
				
			||||||
 | 
					        periph = periphs{i};
 | 
				
			||||||
 | 
					        defines = config.(periph).Defines;
 | 
				
			||||||
 | 
					        defNames = fieldnames(defines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Создаём вкладку для модуля
 | 
				
			||||||
 | 
					        tabCtrl = mask.addDialogControl( ...
 | 
				
			||||||
 | 
					            'Type', 'Tab', ...
 | 
				
			||||||
 | 
					            'Prompt', periph, ...
 | 
				
			||||||
 | 
					            'Name', [periph '_Tab'], ...
 | 
				
			||||||
 | 
					            'Container', containerName ...
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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)
 | 
				
			||||||
 | 
					                valStr = logical(val) * "on" + ~val * "off";
 | 
				
			||||||
 | 
					            elseif isnumeric(val)
 | 
				
			||||||
 | 
					                valStr = num2str(val);
 | 
				
			||||||
 | 
					            elseif ischar(val)
 | 
				
			||||||
 | 
					                valStr = val;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Добавляем параметр в соответствующую вкладку
 | 
				
			||||||
 | 
					            mask.addParameter( ...
 | 
				
			||||||
 | 
					                'Type', paramType, ...
 | 
				
			||||||
 | 
					                'Prompt', defPrompt, ...
 | 
				
			||||||
 | 
					                'Name', paramName, ...
 | 
				
			||||||
 | 
					                'Value', valStr, ...
 | 
				
			||||||
 | 
					                'Container', periph ...
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            param = mask.getParameter(paramName);
 | 
				
			||||||
 | 
					            param.Alias = def.Def;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Восстанавливаем таблицы
 | 
				
			||||||
 | 
					    restore_tables(blockPath, tableNames, columns_backup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Повторно открываем маску, если она была открыта
 | 
				
			||||||
 | 
					    if wasOpen
 | 
				
			||||||
 | 
					        open_system(blockPath, 'mask');
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function clear_all_from_container(mask, containerName)
 | 
				
			||||||
 | 
					% Очищает все параметры и вкладки внутри указанного контейнера
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    container = find_container_by_name(allControls, containerName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isempty(container)
 | 
				
			||||||
 | 
					        error('Контейнер с именем "%s" не найден.', containerName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    children = container.DialogControls;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = numel(children):-1:1
 | 
				
			||||||
 | 
					        ctrl = children(i);
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					            % Пытаемся удалить как контрол (вкладка, контейнер и пр.)
 | 
				
			||||||
 | 
					            mask.removeDialogControl(ctrl.Name);
 | 
				
			||||||
 | 
					        catch
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					                % Если не получилось — пробуем как параметр
 | 
				
			||||||
 | 
					                res = mask.removeParameter(ctrl.Name);
 | 
				
			||||||
 | 
					            catch
 | 
				
			||||||
 | 
					                warning('Не удалось удалить "%s".', ctrl.Name);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isOpen = isMaskDialogOpen(blockPath)
 | 
				
			||||||
 | 
					    isOpen = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try
 | 
				
			||||||
 | 
					        % Получаем имя блока
 | 
				
			||||||
 | 
					        blockName = get_param(blockPath, 'Name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Получаем список окон MATLAB GUI
 | 
				
			||||||
 | 
					        jWindows = java.awt.Window.getWindows();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for i = 1:numel(jWindows)
 | 
				
			||||||
 | 
					            win = jWindows(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Проверка, что окно видимое и активно
 | 
				
			||||||
 | 
					            if win.isShowing()
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
 | 
					                    title = char(win.getTitle());
 | 
				
			||||||
 | 
					                    % Проверка по ключевому слову, соответствующему заголовку маски
 | 
				
			||||||
 | 
					                    if contains(title, ['Mask Editor: ' blockName]) || ...
 | 
				
			||||||
 | 
					                       contains(title, ['Mask: ' blockName]) || ...
 | 
				
			||||||
 | 
					                       contains(title, blockName)
 | 
				
			||||||
 | 
					                        isOpen = true;
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    end
 | 
				
			||||||
 | 
					                catch
 | 
				
			||||||
 | 
					                    % Окно не имеет заголовка — пропускаем
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    catch
 | 
				
			||||||
 | 
					        isOpen = false;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function column_titles = clear_tables(block, table_names)
 | 
				
			||||||
 | 
					    % Очищает столбцы в каждой таблице из массива имен table_names
 | 
				
			||||||
 | 
					    % Возвращает cell-массив с названиями первых столбцов каждой таблицы
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Получить объект маски блока
 | 
				
			||||||
 | 
					    maskObj = Simulink.Mask.get(block);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Инициализировать cell-массив для хранения названий столбцов
 | 
				
			||||||
 | 
					    column_titles = cell(size(table_names));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for k = 1:numel(table_names)
 | 
				
			||||||
 | 
					        table_name = table_names{k};
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить объект управления таблицей
 | 
				
			||||||
 | 
					        tableControl = maskObj.getDialogControl(table_name);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить количество столбцов
 | 
				
			||||||
 | 
					        nCols = tableControl.getNumberOfColumns;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if nCols > 0
 | 
				
			||||||
 | 
					            % Получить первый столбец (который будем удалять)
 | 
				
			||||||
 | 
					            column = tableControl.getColumn(1);
 | 
				
			||||||
 | 
					            column_titles{k} = column.Name;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            % Удаляем все столбцы
 | 
				
			||||||
 | 
					            % Важно: при удалении столбцов индексы меняются, 
 | 
				
			||||||
 | 
					            % поэтому удаляем всегда первый столбец nCols раз
 | 
				
			||||||
 | 
					            for i = 1:nCols
 | 
				
			||||||
 | 
					                tableControl.removeColumn(1);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            % Если столбцов нет, возвращаем пустую строку
 | 
				
			||||||
 | 
					            column_titles{k} = '';
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function restore_tables(block, table_names, column_titles)
 | 
				
			||||||
 | 
					    % Восстанавливает первый столбец в каждой таблице из массива имен
 | 
				
			||||||
 | 
					    % Использует массив column_titles для установки имени столбца
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Получить объект маски блока
 | 
				
			||||||
 | 
					    maskObj = Simulink.Mask.get(block);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for k = 1:numel(table_names)
 | 
				
			||||||
 | 
					        table_name = table_names{k};
 | 
				
			||||||
 | 
					        title = column_titles{k};
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить объект управления таблицей
 | 
				
			||||||
 | 
					        tableControl = maskObj.getDialogControl(table_name);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Добавить новый столбец
 | 
				
			||||||
 | 
					        column = tableControl.addColumn(Name='title', Type='edit');
 | 
				
			||||||
 | 
					        column.Name = title;
 | 
				
			||||||
 | 
					    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 container = find_container_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    container = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, контейнер ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Container') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            container = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это вложенный контрол — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            container = find_container_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(container)
 | 
				
			||||||
 | 
					                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
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										499
									
								
								mexing.m
									
									
									
									
									
								
							
							
						
						
									
										499
									
								
								mexing.m
									
									
									
									
									
								
							@ -1,59 +1,54 @@
 | 
				
			|||||||
% Компилирует S-function
 | 
					% Компилирует S-function
 | 
				
			||||||
clear, clc
 | 
					function mexing(compile_mode)
 | 
				
			||||||
close;
 | 
					    global Ts
 | 
				
			||||||
 | 
					    Ts = 0.00001;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    if compile_mode == 1
 | 
				
			||||||
 | 
					        delete("*.mexw64")
 | 
				
			||||||
 | 
					        delete("*.mexw64.pdb")
 | 
				
			||||||
 | 
					        delete(".\MCU_Wrapper\Outputs\*.*");
 | 
				
			||||||
 | 
					        set_param(gcb, 'consoleOutput', '');    
 | 
				
			||||||
 | 
					        % Дефайны
 | 
				
			||||||
 | 
					        definesWrapperArg = buildWrapperDefinesString();
 | 
				
			||||||
 | 
					        definesUserArg = parseDefinesMaskText();
 | 
				
			||||||
 | 
					        definesConfigArg = buildConfigDefinesString();
 | 
				
			||||||
 | 
					        definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
Ts = 0.00001;
 | 
					        %режимы компиляции
 | 
				
			||||||
 | 
					        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
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
delete("*.mexw64")
 | 
					        [includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
				
			||||||
delete("*.mexw64.pdb")
 | 
					 | 
				
			||||||
delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					 | 
				
			||||||
set_param(gcb, 'consoleOutput', '');
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
% Флаг режима отладки
 | 
					        % Вызов батника с двумя параметрами: includes и code
 | 
				
			||||||
definesWrapperArg = buildWrapperDefinesString();
 | 
					        cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
				
			||||||
definesUserArg = parseDefinesMaskText();
 | 
					 | 
				
			||||||
definesConfigArg = buildConfigDefinesString();
 | 
					 | 
				
			||||||
definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
					 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
 | 
					        if read_checkbox('extConsol')
 | 
				
			||||||
 | 
					            cmdout = runBatAndShowOutput(cmd);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            [status, cmdout]= system(cmd);
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
if read_checkbox('enableDebug')
 | 
					        % Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
				
			||||||
    modeArg = "debug";
 | 
					        set_param(gcb, 'consoleOutput', cmdout);
 | 
				
			||||||
else
 | 
					        
 | 
				
			||||||
    modeArg = "release";
 | 
					        beep
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        blockPath = bdroot;
 | 
				
			||||||
 | 
					        config = load_periph_config();
 | 
				
			||||||
 | 
					        update_mask_from_config(blockPath, config);
 | 
				
			||||||
 | 
					        % set_param(gcb, 'consoleOutput', 'Peripheral configuration file loaded. Re-open Block Parameters');
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
end
 | 
					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
 | 
					%% COMPILE PARAMS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,45 +98,11 @@ function definesWrapperArg = buildWrapperDefinesString()
 | 
				
			|||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
					    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 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
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function definesUserArg = parseDefinesMaskText()
 | 
					function definesUserArg = parseDefinesMaskText()
 | 
				
			||||||
    blockHandle = gcbh;
 | 
					    blockHandle = gcbh;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					    % Получаем MaskValues и MaskNames
 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					    maskValues = get_param(blockHandle, 'MaskValues');
 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					    paramNames = get_param(blockHandle, 'MaskNames');
 | 
				
			||||||
@ -227,39 +188,6 @@ function definesWrapperArg = buildConfigDefinesString()
 | 
				
			|||||||
                warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
					                warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
				
			||||||
            end
 | 
					            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
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -350,42 +278,6 @@ function checkbox_state = read_checkbox(checkboxName)
 | 
				
			|||||||
    end
 | 
					    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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONSOLE FUNCTIONS
 | 
					%% CONSOLE FUNCTIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					function cmdret = runBatAndShowOutput(cmd)
 | 
				
			||||||
@ -462,3 +354,310 @@ function logWindow_append(line)
 | 
				
			|||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
				
			||||||
    drawnow;
 | 
					    drawnow;
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% READ CONFIGS
 | 
				
			||||||
 | 
					function config = load_periph_config()
 | 
				
			||||||
 | 
					    jsonText = fileread('periph_config.json');
 | 
				
			||||||
 | 
					    config = jsondecode(jsonText);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					%% CONFIG MASK TOOLS
 | 
				
			||||||
 | 
					function update_mask_from_config(blockPath, config)
 | 
				
			||||||
 | 
					    blockPath = [blockPath '/MCU'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Проверяем, была ли маска открыта
 | 
				
			||||||
 | 
					    wasOpen = isMaskDialogOpen(blockPath);
 | 
				
			||||||
 | 
					    close_system(blockPath, 0);
 | 
				
			||||||
 | 
					    mask = Simulink.Mask.get(blockPath);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    tableNames = {'incTable', 'srcTable'};
 | 
				
			||||||
 | 
					    columns_backup = clear_tables(blockPath, tableNames);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    containerName = 'configTabAll';
 | 
				
			||||||
 | 
					    clear_all_from_container(mask, containerName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Ищем контейнер, в который будем добавлять вкладки
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    container = find_container_by_name(allControls, containerName);
 | 
				
			||||||
 | 
					    if isempty(container)
 | 
				
			||||||
 | 
					        error('Контейнер "%s" не найден в маске.', containerName);
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Проходим по каждому модулю (ADC, TIM...)
 | 
				
			||||||
 | 
					    periphs = fieldnames(config);
 | 
				
			||||||
 | 
					    for i = 1:numel(periphs)
 | 
				
			||||||
 | 
					        periph = periphs{i};
 | 
				
			||||||
 | 
					        defines = config.(periph).Defines;
 | 
				
			||||||
 | 
					        defNames = fieldnames(defines);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Создаём вкладку для модуля
 | 
				
			||||||
 | 
					        tabCtrl = mask.addDialogControl( ...
 | 
				
			||||||
 | 
					            'Type', 'Tab', ...
 | 
				
			||||||
 | 
					            'Prompt', periph, ...
 | 
				
			||||||
 | 
					            'Name', [periph '_Tab'], ...
 | 
				
			||||||
 | 
					            'Container', containerName ...
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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)
 | 
				
			||||||
 | 
					                valStr = logical(val) * "on" + ~val * "off";
 | 
				
			||||||
 | 
					            elseif isnumeric(val)
 | 
				
			||||||
 | 
					                valStr = num2str(val);
 | 
				
			||||||
 | 
					            elseif ischar(val)
 | 
				
			||||||
 | 
					                valStr = val;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Добавляем параметр в соответствующую вкладку
 | 
				
			||||||
 | 
					            mask.addParameter( ...
 | 
				
			||||||
 | 
					                'Type', paramType, ...
 | 
				
			||||||
 | 
					                'Prompt', defPrompt, ...
 | 
				
			||||||
 | 
					                'Name', paramName, ...
 | 
				
			||||||
 | 
					                'Value', valStr, ...
 | 
				
			||||||
 | 
					                'Container', periph ...
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            param = mask.getParameter(paramName);
 | 
				
			||||||
 | 
					            param.Alias = def.Def;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Восстанавливаем таблицы
 | 
				
			||||||
 | 
					    restore_tables(blockPath, tableNames, columns_backup);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Повторно открываем маску, если она была открыта
 | 
				
			||||||
 | 
					    if wasOpen
 | 
				
			||||||
 | 
					        open_system(blockPath, 'mask');
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function clear_all_from_container(mask, containerName)
 | 
				
			||||||
 | 
					    allControls = mask.getDialogControls();
 | 
				
			||||||
 | 
					    container = find_container_by_name(allControls, containerName);
 | 
				
			||||||
 | 
					    if isempty(container)
 | 
				
			||||||
 | 
					        warning('Контейнер "%s" не найден.', containerName);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Рекурсивно собрать все параметры (не вкладки)
 | 
				
			||||||
 | 
					    paramsToDelete = collect_all_parameters(container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Удаляем все параметры
 | 
				
			||||||
 | 
					    for i = 1:numel(paramsToDelete)
 | 
				
			||||||
 | 
					        try
 | 
				
			||||||
 | 
					            mask.removeParameter(paramsToDelete{i});
 | 
				
			||||||
 | 
					        catch
 | 
				
			||||||
 | 
					            warning('Не удалось удалить параметр %s', paramsToDelete{i});
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    % Рекурсивно удалить все вкладки внутри контейнера
 | 
				
			||||||
 | 
					    delete_all_tabs(mask, container);
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function params = collect_all_parameters(container)
 | 
				
			||||||
 | 
					    params = {};
 | 
				
			||||||
 | 
					    children = container.DialogControls;
 | 
				
			||||||
 | 
					    for i = 1:numel(children)
 | 
				
			||||||
 | 
					        ctrl = children(i);
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
				
			||||||
 | 
					            % Если вкладка — рекурсивно собираем параметры внутри неё
 | 
				
			||||||
 | 
					            params = [params, collect_all_parameters(ctrl)];
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            % Иначе это параметр — добавляем имя
 | 
				
			||||||
 | 
					            params{end+1} = ctrl.Name; %#ok<AGROW>
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function delete_all_tabs(mask, container)
 | 
				
			||||||
 | 
					    children = container.DialogControls;
 | 
				
			||||||
 | 
					    % Идём в обратном порядке, чтобы безопасно удалять
 | 
				
			||||||
 | 
					    for i = numel(children):-1:1
 | 
				
			||||||
 | 
					        ctrl = children(i);
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
				
			||||||
 | 
					            % Рекурсивно удаляем вкладки внутри текущей вкладки
 | 
				
			||||||
 | 
					            delete_all_tabs(mask, ctrl);
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					                mask.removeParameter(ctrl.Name);
 | 
				
			||||||
 | 
					            catch
 | 
				
			||||||
 | 
					                warning('Не удалось удалить вкладку %s', ctrl.Name);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isOpen = isMaskDialogOpen(blockPath)
 | 
				
			||||||
 | 
					    isOpen = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try
 | 
				
			||||||
 | 
					        % Получаем имя блока
 | 
				
			||||||
 | 
					        blockName = get_param(blockPath, 'Name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Получаем список окон MATLAB GUI
 | 
				
			||||||
 | 
					        jWindows = java.awt.Window.getWindows();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for i = 1:numel(jWindows)
 | 
				
			||||||
 | 
					            win = jWindows(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            % Проверка, что окно видимое и активно
 | 
				
			||||||
 | 
					            if win.isShowing()
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
 | 
					                    title = char(win.getTitle());
 | 
				
			||||||
 | 
					                    % Проверка по ключевому слову, соответствующему заголовку маски
 | 
				
			||||||
 | 
					                    if contains(title, ['Mask Editor: ' blockName]) || ...
 | 
				
			||||||
 | 
					                       contains(title, ['Mask: ' blockName]) || ...
 | 
				
			||||||
 | 
					                       contains(title, blockName)
 | 
				
			||||||
 | 
					                        isOpen = true;
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    end
 | 
				
			||||||
 | 
					                catch
 | 
				
			||||||
 | 
					                    % Окно не имеет заголовка — пропускаем
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    catch
 | 
				
			||||||
 | 
					        isOpen = false;
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function column_titles = clear_tables(block, table_names)
 | 
				
			||||||
 | 
					    % Очищает столбцы в каждой таблице из массива имен table_names
 | 
				
			||||||
 | 
					    % Возвращает cell-массив с названиями первых столбцов каждой таблицы
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Получить объект маски блока
 | 
				
			||||||
 | 
					    maskObj = Simulink.Mask.get(block);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Инициализировать cell-массив для хранения названий столбцов
 | 
				
			||||||
 | 
					    column_titles = cell(size(table_names));
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for k = 1:numel(table_names)
 | 
				
			||||||
 | 
					        table_name = table_names{k};
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить объект управления таблицей
 | 
				
			||||||
 | 
					        tableControl = maskObj.getDialogControl(table_name);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить количество столбцов
 | 
				
			||||||
 | 
					        nCols = tableControl.getNumberOfColumns;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if nCols > 0
 | 
				
			||||||
 | 
					            % Получить первый столбец (который будем удалять)
 | 
				
			||||||
 | 
					            column = tableControl.getColumn(1);
 | 
				
			||||||
 | 
					            column_titles{k} = column.Name;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            % Удаляем все столбцы
 | 
				
			||||||
 | 
					            % Важно: при удалении столбцов индексы меняются, 
 | 
				
			||||||
 | 
					            % поэтому удаляем всегда первый столбец nCols раз
 | 
				
			||||||
 | 
					            for i = 1:nCols
 | 
				
			||||||
 | 
					                tableControl.removeColumn(1);
 | 
				
			||||||
 | 
					            end
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            % Если столбцов нет, возвращаем пустую строку
 | 
				
			||||||
 | 
					            column_titles{k} = '';
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					    end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function restore_tables(block, table_names, column_titles)
 | 
				
			||||||
 | 
					    % Восстанавливает первый столбец в каждой таблице из массива имен
 | 
				
			||||||
 | 
					    % Использует массив column_titles для установки имени столбца
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    % Получить объект маски блока
 | 
				
			||||||
 | 
					    maskObj = Simulink.Mask.get(block);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    for k = 1:numel(table_names)
 | 
				
			||||||
 | 
					        table_name = table_names{k};
 | 
				
			||||||
 | 
					        title = column_titles{k};
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Получить объект управления таблицей
 | 
				
			||||||
 | 
					        tableControl = maskObj.getDialogControl(table_name);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        % Добавить новый столбец
 | 
				
			||||||
 | 
					        column = tableControl.addColumn(Name='title', Type='edit');
 | 
				
			||||||
 | 
					        column.Name = title;
 | 
				
			||||||
 | 
					    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 container = find_container_by_name(controls, targetName)
 | 
				
			||||||
 | 
					    container = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for i = 1:numel(controls)
 | 
				
			||||||
 | 
					        ctrl = controls(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Проверяем, контейнер ли это и совпадает ли имя
 | 
				
			||||||
 | 
					        if isa(ctrl, 'Simulink.dialog.Container') && strcmp(ctrl.Name, targetName)
 | 
				
			||||||
 | 
					            container = ctrl;
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        % Если это вложенный контрол — обходим его детей
 | 
				
			||||||
 | 
					        children = get_children(ctrl);
 | 
				
			||||||
 | 
					        if ~isempty(children)
 | 
				
			||||||
 | 
					            container = find_container_by_name(children, targetName);
 | 
				
			||||||
 | 
					            if ~isempty(container)
 | 
				
			||||||
 | 
					                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
 | 
				
			||||||
 | 
				
			|||||||
@ -1,38 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "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
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user