сделано подключение сурсов по конфигу, но надо бы как-то структуризировать
This commit is contained in:
parent
982d29560f
commit
5a92e0bec0
@ -54,9 +54,11 @@ classdef periphConfig
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
periphConfig.create_all_code_storage_params(blockPath, config);
|
periphConfig.create_all_code_storage_params(blockPath, config);
|
||||||
periphConfig.cleanup_obsolete_code_params(blockPath, config);
|
% periphConfig.cleanup_obsolete_code_params(blockPath, config);
|
||||||
|
|
||||||
% Восстанавливаем таблицы
|
periphConfig.update_all();
|
||||||
|
|
||||||
|
% Восстанавлиperiph = allTabNamesваем таблицы
|
||||||
customtable.restore_all_tables(tableNames, columns_backup);
|
customtable.restore_all_tables(tableNames, columns_backup);
|
||||||
catch
|
catch
|
||||||
% Восстанавливаем таблицы
|
% Восстанавливаем таблицы
|
||||||
@ -157,65 +159,149 @@ classdef periphConfig
|
|||||||
fclose(fid);
|
fclose(fid);
|
||||||
end
|
end
|
||||||
|
|
||||||
function update_callback()
|
function update_all()
|
||||||
blockPath = gcb;
|
blockPath = gcb;
|
||||||
mask = Simulink.Mask.get(blockPath);
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
|
||||||
config = periphConfig.read_config(blockPath);
|
config = periphConfig.read_config(blockPath);
|
||||||
|
|
||||||
periphs = fieldnames(config);
|
|
||||||
for i = 1:numel(periphs)
|
|
||||||
periph = periphs{i};
|
|
||||||
|
|
||||||
% Сохраняем код, если он есть
|
|
||||||
periphConfig.store_single_periph_code(mask, periph, config.(periph));
|
|
||||||
end
|
|
||||||
|
|
||||||
containerName = 'configTabAll';
|
containerName = 'configTabAll';
|
||||||
container = mask.getDialogControl(containerName);
|
container = mask.getDialogControl(containerName);
|
||||||
paramsAll = mcuMask.collect_all_parameters(container);
|
paramsAll = mcuMask.collect_all_parameters(container);
|
||||||
% Цикл по параметрам
|
% Получаем все имена в кладок из container (у вас должен быть container)
|
||||||
for i = 1:length(paramsAll)
|
allTabs = container.DialogControls;
|
||||||
name = paramsAll{i};
|
allTabNames = arrayfun(@(t) t.Name, allTabs, 'UniformOutput', false);
|
||||||
|
|
||||||
% Ищем параметры вида Tab_<Periph>_Enable
|
fieldsConfig = fieldnames(config);
|
||||||
expr = '^Tab_(\w+)_Enable$';
|
% Цикл по всем вкладкам в контейнере
|
||||||
tokens = regexp(name, expr, 'tokens');
|
for i = 1:length(allTabNames)
|
||||||
|
periph = fieldsConfig{i};
|
||||||
|
|
||||||
if ~isempty(tokens)
|
% Попытка найти параметр чекбокса Tab_<Periph>_Enable
|
||||||
periph = tokens{1}{1}; % Извлекаем имя вкладки
|
checkboxName = ['Tab_' periph '_Enable'];
|
||||||
paramObj = mask.getParameter(name);
|
if ismember(checkboxName, paramsAll)
|
||||||
|
% Чекбокс есть - проверяем его состояние
|
||||||
|
paramObj = mask.getParameter(checkboxName);
|
||||||
val = paramObj.Value;
|
val = paramObj.Value;
|
||||||
|
|
||||||
if strcmpi(val, 'off')
|
try
|
||||||
% Найдём вкладку по имени
|
tab = container.getDialogControl(periph);
|
||||||
try
|
if strcmpi(val, 'off')
|
||||||
tab = container.getDialogControl(periph);
|
|
||||||
tab.Enabled = 'off';
|
tab.Enabled = 'off';
|
||||||
periphConfig.clear_single_periph_code_param(mask, periph);
|
% Рекурсивно очищаем связанные скрытые параметры
|
||||||
catch
|
periphConfig.clear_tab_params(mask, config.(periph), periph);
|
||||||
warning('Вкладка с именем "%s" не найдена.', periph);
|
else
|
||||||
end
|
|
||||||
else
|
|
||||||
% Найдём вкладку по имени
|
|
||||||
try
|
|
||||||
tab = container.getDialogControl(periph);
|
|
||||||
tab.Enabled = 'on';
|
tab.Enabled = 'on';
|
||||||
periphConfig.store_single_periph_code(mask, periph, config.(periph));
|
periphConfig.sync_tab_params(mask, config.(periph), periph);
|
||||||
catch
|
|
||||||
warning('Вкладка с именем "%s" не найдена.', periph);
|
|
||||||
end
|
end
|
||||||
|
catch
|
||||||
|
warning('Вкладка с именем "%s" не найдена.', periph);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
% Чекбокса нет — просто пытаемся включить вкладку, если она есть
|
||||||
|
try
|
||||||
|
tab = container.getDialogControl(periph);
|
||||||
|
tab.Enabled = 'on';
|
||||||
|
% Опционально можно синхронизировать параметры, если есть config поле
|
||||||
|
if isfield(config, periph)
|
||||||
|
periphConfig.sync_tab_params(mask, config.(periph), periph);
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
% Можно не выводить предупреждение — вкладка может быть необязательной
|
||||||
|
% warning('Вкладка с именем "%s" не найдена.', periph);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
periphConfig.getWrapperCode();
|
periphConfig.getWrapperCode();
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function update_callback(paramName)
|
||||||
|
blockPath = gcb;
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
hObj = mask.getParameter(paramName);
|
||||||
|
config = periphConfig.read_config(blockPath);
|
||||||
|
container = mask.getDialogControl('configTabAll');
|
||||||
|
|
||||||
|
% === Проверка на Tab_<Periph>_Enable ===
|
||||||
|
exprTab = '^Tab_(\w+)_Enable$';
|
||||||
|
tokensTab = regexp(paramName, exprTab, 'tokens');
|
||||||
|
|
||||||
|
if ~isempty(tokensTab)
|
||||||
|
periph = tokensTab{1}{1};
|
||||||
|
|
||||||
|
try
|
||||||
|
tab = container.getDialogControl(periph);
|
||||||
|
paramVal = hObj.Value;
|
||||||
|
|
||||||
|
if strcmpi(paramVal, 'off')
|
||||||
|
tab.Enabled = 'off';
|
||||||
|
if isfield(config, periph)
|
||||||
|
periphConfig.clear_tab_params(mask, config.(periph), periph);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
tab.Enabled = 'on';
|
||||||
|
if isfield(config, periph)
|
||||||
|
periphConfig.sync_tab_params(mask, config.(periph), periph);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
warning('Ошибка обработки вкладки "%s".', periph);
|
||||||
|
end
|
||||||
|
|
||||||
|
periphConfig.getWrapperCode();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
% === Проверка на параметр, связанный с Sources/Includes ===
|
||||||
|
% Проверка: это параметр, у которого есть соответствующий Hidden_<Name>_Sources или Hidden_<Name>_Includes
|
||||||
|
nameBase = paramName;
|
||||||
|
|
||||||
|
paramNames = string({mask.Parameters.Name});
|
||||||
|
hasSources = any(paramNames == "Hidden_" + nameBase + "_Sources");
|
||||||
|
hasIncludes = any(paramNames == "Hidden_" + nameBase + "_Includes");
|
||||||
|
|
||||||
|
|
||||||
|
if hasSources || hasIncludes
|
||||||
|
useVal = hObj.Value;
|
||||||
|
|
||||||
|
% Получаем содержимое config по nameBase — возможно, вложенное
|
||||||
|
try
|
||||||
|
valueStruct = periphConfig.get_field(config, nameBase);
|
||||||
|
catch
|
||||||
|
warning('Не удалось найти путь %s в config.', nameBase);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
if strcmpi(useVal, 'on')
|
||||||
|
try
|
||||||
|
periphConfig.store_single_periph_code(mask, nameBase, valueStruct);
|
||||||
|
catch
|
||||||
|
warning('Не удалось сохранить параметры для %s.', nameBase);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
periphConfig.clear_single_periph_code_param(mask, nameBase);
|
||||||
|
end
|
||||||
|
|
||||||
|
periphConfig.getWrapperCode();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
% === Если не подошло ни под одно из условий ===
|
||||||
|
warning('Объект "%s" не поддерживается универсальным коллбеком.', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getWrapperCode()
|
function getWrapperCode()
|
||||||
blockPath = gcb;
|
blockPath = gcb;
|
||||||
CodeStruct = periphConfig.restore_periph_code_from_mask(blockPath);
|
CodeStruct = periphConfig.restore_periph_code_from_mask(blockPath);
|
||||||
@ -231,54 +317,163 @@ classdef periphConfig
|
|||||||
|
|
||||||
methods(Static, Access=private)
|
methods(Static, Access=private)
|
||||||
|
|
||||||
function create_all_code_storage_params(blockPath, config)
|
function clear_tab_params(mask, configStruct, prefix, depth)
|
||||||
mask = Simulink.Mask.get(blockPath);
|
if nargin < 4
|
||||||
existingParams = arrayfun(@(p) p.Name, mask.Parameters, 'UniformOutput', false);
|
depth = 0;
|
||||||
|
end
|
||||||
|
maxDepth = 3; % Максимальная глубина рекурсии
|
||||||
|
|
||||||
periphs = fieldnames(config);
|
fields = fieldnames(configStruct);
|
||||||
for i = 1:numel(periphs)
|
|
||||||
periph = periphs{i};
|
|
||||||
|
|
||||||
% Проверяем, нужно ли создавать параметры
|
for i = 1:numel(fields)
|
||||||
hasSources = isfield(config.(periph), 'Sources');
|
key = fields{i};
|
||||||
hasIncludes = isfield(config.(periph), 'Includes');
|
value = configStruct.(key);
|
||||||
|
paramName = [prefix '_' key];
|
||||||
|
|
||||||
if ~hasSources && ~hasIncludes
|
if isstruct(value)
|
||||||
continue;
|
if depth < maxDepth
|
||||||
end
|
% Рекурсивный вызов для вложенных структур с увеличением глубины
|
||||||
|
periphConfig.clear_tab_params(mask, value, paramName, depth + 1);
|
||||||
% Добавляем параметр для Sources
|
|
||||||
if hasSources
|
|
||||||
srcParamName = ['Hidden_' periph '_Sources'];
|
|
||||||
if ~ismember(srcParamName, existingParams)
|
|
||||||
mask.addParameter( ...
|
|
||||||
'Name', srcParamName, ...
|
|
||||||
'Type', 'edit', ...
|
|
||||||
'Prompt', '', ...
|
|
||||||
'Value', '', ...
|
|
||||||
'Visible', 'off' ...
|
|
||||||
);
|
|
||||||
fprintf('Создан скрытый параметр: %s\n', srcParamName);
|
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
||||||
% Добавляем параметр для Includes
|
baseName = periphConfig.get_final_name_from_prefix(prefix);
|
||||||
if hasIncludes
|
periphConfig.clear_single_periph_code_param(mask, baseName);
|
||||||
incParamName = ['Hidden_' periph '_Includes'];
|
|
||||||
if ~ismember(incParamName, existingParams)
|
|
||||||
mask.addParameter( ...
|
|
||||||
'Name', incParamName, ...
|
|
||||||
'Type', 'edit', ...
|
|
||||||
'Prompt', '', ...
|
|
||||||
'Value', '', ...
|
|
||||||
'Visible', 'off' ...
|
|
||||||
);
|
|
||||||
fprintf('Создан скрытый параметр: %s\n', incParamName);
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function sync_tab_params(mask, configStruct, prefix, depth)
|
||||||
|
if nargin < 4
|
||||||
|
depth = 0;
|
||||||
|
end
|
||||||
|
maxDepth = 3; % Максимальная глубина рекурсии
|
||||||
|
|
||||||
|
fields = fieldnames(configStruct);
|
||||||
|
|
||||||
|
for i = 1:numel(fields)
|
||||||
|
key = fields{i};
|
||||||
|
value = configStruct.(key);
|
||||||
|
paramName = [prefix '_' key];
|
||||||
|
|
||||||
|
if isstruct(value)
|
||||||
|
if depth < maxDepth
|
||||||
|
% Рекурсивный вызов для вложенных структур с увеличением глубины
|
||||||
|
periphConfig.sync_tab_params(mask, value, paramName, depth + 1);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
||||||
|
baseName = periphConfig.get_final_name_from_prefix(prefix);
|
||||||
|
periphConfig.store_single_periph_code(mask, baseName, configStruct);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function short = get_final_name_from_prefix(prefix)
|
||||||
|
% Берёт последнее имя после "_" (читаемое имя)
|
||||||
|
parts = strsplit(prefix, '_');
|
||||||
|
short = parts{end};
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function value = get_field(configStruct, targetConfig)
|
||||||
|
value = [];
|
||||||
|
fields = fieldnames(configStruct);
|
||||||
|
|
||||||
|
for i = 1:numel(fields)
|
||||||
|
key = fields{i};
|
||||||
|
if strcmp(key, targetConfig)
|
||||||
|
value = configStruct.(key);
|
||||||
|
return; % нашли и возвращаем
|
||||||
|
elseif isstruct(configStruct.(key))
|
||||||
|
value = periphConfig.get_field(configStruct.(key), targetConfig);
|
||||||
|
if ~isempty(value)
|
||||||
|
return; % нашли во вложенной структуре
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Если не нашли, можно выбросить ошибку или вернуть пустое
|
||||||
|
if isempty(value)
|
||||||
|
% error('Поле "%s" не найдено в структуре.', targetConfig);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function create_all_code_storage_params(blockPath, config)
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
|
||||||
|
containerName = 'configTabAll';
|
||||||
|
container = mask.getDialogControl(containerName);
|
||||||
|
existingParams = mcuMask.collect_all_parameters(container);
|
||||||
|
|
||||||
|
% Убедимся, что контейнер существует
|
||||||
|
tabName = 'hiddenCodeTab';
|
||||||
|
tab = mask.getDialogControl(tabName);
|
||||||
|
if isempty(tab)
|
||||||
|
tab = container.addDialogControl('tab', tabName);
|
||||||
|
tab.Prompt = 'Hidden Code Settings';
|
||||||
|
tab.Visible = 'off';
|
||||||
|
else
|
||||||
|
tab.Visible = 'off';
|
||||||
|
end
|
||||||
|
|
||||||
|
% Запуск рекурсивного обхода
|
||||||
|
periphConfig.process_struct_recursive(mask, tabName, config, {}, existingParams);
|
||||||
|
end
|
||||||
|
|
||||||
|
function process_struct_recursive(mask, tabName, currentStruct, nameStack, existingParams)
|
||||||
|
fields = fieldnames(currentStruct);
|
||||||
|
for i = 1:numel(fields)
|
||||||
|
fieldName = fields{i};
|
||||||
|
value = currentStruct.(fieldName);
|
||||||
|
newStack = [nameStack, fieldName]; % Добавляем уровень к имени
|
||||||
|
|
||||||
|
% Если value — структура, обходим дальше
|
||||||
|
if isstruct(value)
|
||||||
|
% Проверяем: это структура с Sources/Includes или просто промежуточный узел?
|
||||||
|
hasSources = isfield(value, 'Sources');
|
||||||
|
hasIncludes = isfield(value, 'Includes');
|
||||||
|
|
||||||
|
if hasSources
|
||||||
|
periphConfig.addHiddenParam(mask, tabName, fieldName, 'Sources', existingParams);
|
||||||
|
end
|
||||||
|
if hasIncludes
|
||||||
|
periphConfig.addHiddenParam(mask, tabName, fieldName, 'Includes', existingParams);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Рекурсивно продолжаем обход
|
||||||
|
periphConfig.process_struct_recursive(mask, tabName, value, newStack, existingParams);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function addHiddenParam(mask, containerName, nameBase, kind, existingParams)
|
||||||
|
% Преобразуем к красивому имени
|
||||||
|
prettyName = strrep(nameBase, '_', ' ');
|
||||||
|
paramName = ['Hidden_' nameBase '_' kind];
|
||||||
|
if ismember(paramName, existingParams)
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
mask.addParameter( ...
|
||||||
|
'Name', paramName, ...
|
||||||
|
'Type', 'edit', ...
|
||||||
|
'Prompt', ['Hidden ' prettyName ' ' kind], ...
|
||||||
|
'Value', '', ...
|
||||||
|
'Visible', 'off', ...
|
||||||
|
'Container', containerName ...
|
||||||
|
);
|
||||||
|
fprintf('Создан скрытый параметр: %s\n', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
function cleanup_obsolete_code_params(blockPath, config)
|
function cleanup_obsolete_code_params(blockPath, config)
|
||||||
mask = Simulink.Mask.get(blockPath);
|
mask = Simulink.Mask.get(blockPath);
|
||||||
maskParams = mask.Parameters;
|
maskParams = mask.Parameters;
|
||||||
@ -357,8 +552,6 @@ classdef periphConfig
|
|||||||
codeStruct.Includes = allIncludes;
|
codeStruct.Includes = allIncludes;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function clear_single_periph_code_param(mask, periph)
|
function clear_single_periph_code_param(mask, periph)
|
||||||
% Формируем имена параметров
|
% Формируем имена параметров
|
||||||
paramNames = {
|
paramNames = {
|
||||||
@ -380,7 +573,7 @@ classdef periphConfig
|
|||||||
function store_single_periph_code(mask, periph, code)
|
function store_single_periph_code(mask, periph, code)
|
||||||
% Сохраняем Sources, если они есть
|
% Сохраняем Sources, если они есть
|
||||||
if isfield(code, 'Sources')
|
if isfield(code, 'Sources')
|
||||||
paramName = ['Hidden_' periph '_Sources'];
|
paramName = ['Hidden_' char(periph) '_Sources'];
|
||||||
try
|
try
|
||||||
param = mask.getParameter(paramName);
|
param = mask.getParameter(paramName);
|
||||||
param.Value = periphConfig.convert_code_value(code.Sources);
|
param.Value = periphConfig.convert_code_value(code.Sources);
|
||||||
@ -411,7 +604,7 @@ classdef periphConfig
|
|||||||
elseif iscell(codeField)
|
elseif iscell(codeField)
|
||||||
value = strjoin(codeField, newline);
|
value = strjoin(codeField, newline);
|
||||||
else
|
else
|
||||||
warning('Неподдерживаемый тип данных: сохранено как пустая строка');
|
% warning('Неподдерживаемый тип данных: сохранено как пустая строка');
|
||||||
value = '';
|
value = '';
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -598,7 +791,8 @@ classdef periphConfig
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
param.Callback = 'periphConfig.update_callback();';
|
callback = sprintf('periphConfig.update_callback("%s");', paramName);
|
||||||
|
param.Callback = callback;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user