чуть ранее работало идеально, но ща решил сделать парс конфига по вкладкам
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.
513
mexing.asv
513
mexing.asv
@ -1,59 +1,54 @@
|
||||
% Компилирует 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";
|
||||
function mexing(compile_mode)
|
||||
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];
|
||||
|
||||
%режимы компиляции
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -103,45 +98,11 @@ function definesWrapperArg = buildWrapperDefinesString()
|
||||
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');
|
||||
@ -208,52 +169,25 @@ function definesWrapperArg = buildConfigDefinesString()
|
||||
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
|
||||
% Пропускаем другие типы
|
||||
% Получаем имя параметра из контрола
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
@ -344,42 +278,6 @@ function checkbox_state = read_checkbox(checkboxName)
|
||||
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)
|
||||
@ -456,3 +354,284 @@ function logWindow_append(line)
|
||||
jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
|
||||
drawnow;
|
||||
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
|
||||
|
||||
511
mexing.m
511
mexing.m
@ -1,59 +1,54 @@
|
||||
% Компилирует 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";
|
||||
function mexing(compile_mode)
|
||||
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];
|
||||
|
||||
%режимы компиляции
|
||||
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);
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -103,45 +98,11 @@ function definesWrapperArg = buildWrapperDefinesString()
|
||||
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');
|
||||
@ -227,39 +188,6 @@ function definesWrapperArg = buildConfigDefinesString()
|
||||
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
|
||||
|
||||
|
||||
@ -350,42 +278,6 @@ function checkbox_state = read_checkbox(checkboxName)
|
||||
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)
|
||||
@ -462,3 +354,310 @@ function logWindow_append(line)
|
||||
jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
|
||||
drawnow;
|
||||
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