pre-release 1.02

This commit is contained in:
2025-06-19 13:29:33 +03:00
parent 966ddc3bac
commit 1aa3c5b955
16 changed files with 1623 additions and 654 deletions

View File

@@ -1,171 +1,424 @@
classdef periphConfig
methods(Static)
function update(blockPath, config)
function updateMask(blockPath, config)
% blockPath = [blockPath '/MCU'];
% Проверяем, была ли маска открыта
% wasOpen = isMaskDialogOpen(blockPath);
mask = Simulink.Mask.get(blockPath);
periphPath = get_param(blockPath, 'periphPath');
[periphPath, ~, ~] = fileparts(periphPath);
tableNames = {'incTable', 'srcTable'};
columns_backup = customtable.save_all_tables(tableNames);
containerName = 'configTabAll';
periphConfig.clear_all_from_container(mask, containerName);
% Ищем контейнер, в который будем добавлять вкладки
container = mask.getDialogControl(containerName);
if isempty(container)
error('Контейнер "%s" не найден в маске.', containerName);
end
if ~isempty(config)
try
rowWidth = str2double(get_param(blockPath, 'rowWidth'));
if isfield(config, 'Code')
res = periphConfig.addCodeConfig(config.Code, periphPath);
if res == 0
error('Ошибка: неудачное добавление кода периферии. Проверьте корректность файлов и путей в конфигурационном файле')
end
else
error('Ошибка: в конфигурационном файле не задан исходный код для симуляции периферии')
containerName = 'configTabAll';
periphConfig.clear_all_from_container(mask, containerName);
% Ищем контейнер, в который будем добавлять вкладки
container = mask.getDialogControl(containerName);
if isempty(container)
error('Контейнер "%s" не найден в маске.', containerName);
end
if ~isempty(config)
% Проходим по каждому модулю (ADC, TIM...)
periphs = fieldnames(config);
for i = 1:numel(periphs)
periph = periphs{i};
% Сохраняем код, если он есть
periphConfig.store_single_periph_code(mask, periph, config.(periph));
% Проверяем наличие Defines
if ~isfield(config.(periph), 'Defines')
continue;
end
defines = config.(periph).Defines;
defNames = fieldnames(defines);
if isfield(config, 'UserCode')
res = periphConfig.addUserCodeConfig(config.UserCode);
if res == 0
error('Ошибка: неудачное добавление функций для симуляции. Проверьте корректность названий функций в конфигурационном файле')
end
else
error('Ошибка: в конфигурационном файле не заданы функции для симуляции периферии')
end
% Проходим по каждому модулю (ADC, TIM...)
periphs = fieldnames(config);
for i = 1:numel(periphs)
periph = periphs{i};
% Пропускаем Code и UserCode, они уже обработаны
if strcmp(periph, 'Code') || strcmp(periph, 'UserCode')
continue;
end
defines = config.(periph).Defines;
defNames = fieldnames(defines);
% Создаём вкладку для модуля
tabCtrl = container.addDialogControl('tab', periph);
tabCtrl.Prompt = [periph ' Config'];
for j = 1:numel(defNames)
defPrompt = defNames{j};
def = defines.(defPrompt);
% Вызов функции добавления одного параметра
periphConfig.addDefineConfig(mask, containerName, periph, defPrompt, def);
% Создаём вкладку для модуля
tabCtrl = container.addDialogControl('tab', periph);
tabCtrl.Prompt = [periph ' Config'];
rowCountMap = containers.Map();
for j = 1:numel(defNames)
defPrompt = defNames{j};
def = defines.(defPrompt);
% Вызов функции добавления одного параметра
periphConfig.addConfig(mask, containerName, periph, defPrompt, def, rowCountMap, rowWidth);
end
end
end
periphConfig.create_all_code_storage_params(blockPath, config);
% periphConfig.cleanup_obsolete_code_params(blockPath, config);
periphConfig.update();
% Восстанавлиperiph = allTabNamesваем таблицы
customtable.restore_all_tables(tableNames, columns_backup);
catch
% Восстанавливаем таблицы
customtable.restore_all_tables(tableNames, columns_backup);
end
% Восстанавливаем таблицы
customtable.restore_all_tables(tableNames, columns_backup);
% % Повторно открываем маску, если она была открыта
% if wasOpen
% open_system(blockPath, 'mask');
% end
end
function config = update_config(blockPath, config)
if isempty(config)
function update()
blockPath = gcb;
mask = Simulink.Mask.get(blockPath);
config = configJs.read(blockPath);
containerName = 'configTabAll';
container = mask.getDialogControl(containerName);
paramsAll = mcuMask.collect_all_parameters(container);
% Получаем все имена в кладок из container (у вас должен быть container)
allTabs = container.DialogControls;
allTabNames = arrayfun(@(t) t.Name, allTabs, 'UniformOutput', false);
fieldsConfig = fieldnames(config);
% Цикл по всем вкладкам в контейнере
for i = 1:length(allTabNames)
periph = fieldsConfig{i};
% Попытка найти параметр чекбокса Tab_<Periph>_Enable
checkboxName = ['Tab_' periph '_Enable'];
if ismember(checkboxName, paramsAll)
% Чекбокс есть - проверяем его состояние
paramObj = mask.getParameter(checkboxName);
val = paramObj.Value;
try
tab = container.getDialogControl(periph);
if strcmpi(val, 'off')
tab.Enabled = 'off';
% Рекурсивно очищаем связанные скрытые параметры
periphConfig.clear_tab_params(mask, config.(periph), periph);
else
tab.Enabled = 'on';
periphConfig.sync_tab_params(mask, config.(periph), periph);
end
catch
warning('Вкладка с именем "%s" не найдена.', periph);
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
function periphParamCallback(paramName)
blockPath = gcb;
mask = Simulink.Mask.get(blockPath);
hObj = mask.getParameter(paramName);
config = configJs.read(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
return;
end
mask = Simulink.Mask.get(blockPath);
maskParams = mask.Parameters;
paramNames = arrayfun(@(p) p.Name, maskParams, 'UniformOutput', false);
% === Проверка на параметр, связанный с 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 = configJs.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
return;
end
% Обработка остальных секций (с дефайнами)
periphs = fieldnames(config);
for i = 1:numel(periphs)
periph = periphs{i};
% Пропускаем Code и UserCode, они уже обработаны
if strcmp(periph, 'Code') || strcmp(periph, 'UserCode')
continue;
end
% === Если не подошло ни под одно из условий ===
% warning('Объект "%s" не поддерживается универсальным коллбеком.', paramName);
end
function updatePeriphRunMexBat()
% Запись run_mex.bat
blockPath = gcb;
CodeStruct = periphConfig.restore_periph_code_from_mask(blockPath);
periphPath = mcuPath.get('periphPath');
[periphPath, ~, ~] = fileparts(periphPath);
periphConfig.addCodeBat(CodeStruct, periphPath);
end
% Проверяем есть ли Defines
if ~isfield(config.(periph), 'Defines')
continue;
end
end
methods(Static, Access=private)
defines = config.(periph).Defines;
defNames = fieldnames(defines);
function addHiddenParam(mask, containerName, nameBase, kind, existingParams)
% Преобразуем к красивому имени
prettyName = strrep(nameBase, '_', ' ');
paramName = ['Hidden_' char(nameBase) '_' kind];
if ismember(paramName, existingParams)
return;
end
for j = 1:numel(defNames)
defPrompt = defNames{j};
paramName = matlab.lang.makeValidName(defPrompt);
mask.addParameter( ...
'Name', paramName, ...
'Type', 'edit', ...
'Prompt', ['Hidden ' prettyName ' ' kind], ...
'Value', '', ...
'Visible', 'off', ...
'Container', containerName ...
);
fprintf('Создан скрытый параметр: %s\n', paramName);
end
function clear_tab_params(mask, configStruct, prefix, depth)
if nargin < 4
depth = 0;
end
maxDepth = 3; % Максимальная глубина рекурсии
fields = fieldnames(configStruct);
% Проверка, существует ли параметр с таким именем
if ismember(paramName, paramNames)
param = mask.getParameter(paramName);
valStr = param.Value;
for i = 1:numel(fields)
key = fields{i};
value = configStruct.(key);
paramName = [prefix '_' key];
% Проверяем, существует ли элемент defPrompt в структуре defines
if isfield(defines, defPrompt)
% Преобразуем строку в соответствующий тип
if strcmpi(defines.(defPrompt).Type, 'checkbox')
config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
elseif strcmpi(defines.(defPrompt).Type, 'edit')
valNum = str2double(valStr);
if isnan(valNum)
config.(periph).Defines.(defPrompt).Default = valStr;
else
config.(periph).Defines.(defPrompt).Default = valNum;
end
end
end
if isstruct(value)
if depth < maxDepth
% Рекурсивный вызов для вложенных структур с увеличением глубины
periphConfig.clear_tab_params(mask, value, paramName, depth + 1);
end
else
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
baseName = configJs.get_final_name_from_prefix(prefix);
periphConfig.clear_single_periph_code_param(mask, baseName);
end
end
end
end
function config = read_config(blockPath)
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 = configJs.get_final_name_from_prefix(prefix);
periphConfig.store_single_periph_code(mask, baseName, configStruct);
end
end
end
end
function create_all_code_storage_params(blockPath, config)
mask = Simulink.Mask.get(blockPath);
pathparam = mask.getParameter('periphPath');
config_path = pathparam.Value;
containerName = 'configTabAll';
container = mask.getDialogControl(containerName);
existingParams = mcuMask.collect_all_parameters(container);
if ~isempty(config_path)
jsonText = fileread(config_path);
config = jsondecode(jsonText);
% Убедимся, что контейнер существует
tabName = 'hiddenCodeTab';
tab = mask.getDialogControl(tabName);
if isempty(tab)
tab = container.addDialogControl('tab', tabName);
tab.Prompt = 'Hidden Code Settings';
tab.Visible = 'off';
else
config = [];
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 write_config(config)
if isempty(config)
return
end
blockHandle = gcbh;
mask = Simulink.Mask.get(blockHandle);
function cleanup_obsolete_code_params(blockPath, config)
mask = Simulink.Mask.get(blockPath);
maskParams = mask.Parameters;
pathparam = mask.getParameter('periphPath');
config_path = pathparam.Value;
% Получаем список актуальных периферий
validPeriphs = fieldnames(config);
jsonText = jsonencode(config, 'PrettyPrint', true);
fid = fopen(config_path, 'w', 'n', 'UTF-8');
if fid == -1
error('Не удалось открыть файл periph_config.json для записи.');
for i = 1:numel(maskParams)
paramName = maskParams(i).Name;
% Проверяем, является ли параметром хранения Sources или Includes
expr = '^Hidden_(\w+)_(Sources|Includes)$';
tokens = regexp(paramName, expr, 'tokens');
if ~isempty(tokens)
periph = tokens{1}{1};
% Если периферии больше нет удаляем параметр
if ~ismember(periph, validPeriphs)
mask.removeParameter(paramName);
fprintf('Удалён устаревший параметр: %s\n', paramName);
end
end
end
fwrite(fid, jsonText, 'char');
fclose(fid);
end
function codeStruct = restore_periph_code_from_mask(blockPath)
mask = Simulink.Mask.get(blockPath);
maskParams = mask.Parameters;
allSources = {};
allIncludes = {};
for i = 1:numel(maskParams)
name = maskParams(i).Name;
% Ищем параметры Sources
tokensSrc = regexp(name, '^Hidden_(\w+)_Sources$', 'tokens');
if ~isempty(tokensSrc)
val = maskParams(i).Value;
if ischar(val) || isstring(val)
valStr = strtrim(char(val));
% Пропускаем пустые строки и '[]'
if isempty(valStr) || strcmp(valStr, '[]')
continue;
end
lines = splitlines(valStr);
lines = lines(~cellfun(@(x) all(isspace(x)) || isempty(x), lines));
allSources = [allSources; lines]; %#ok<AGROW>
end
continue;
end
% Ищем параметры Includes
tokensInc = regexp(name, '^Hidden_(\w+)_Includes$', 'tokens');
if ~isempty(tokensInc)
val = maskParams(i).Value;
if ischar(val) || isstring(val)
valStr = strtrim(char(val));
if isempty(valStr) || strcmp(valStr, '[]')
continue;
end
lines = splitlines(valStr);
lines = lines(~cellfun(@(x) all(isspace(x)) || isempty(x), lines));
allIncludes = [allIncludes; lines]; %#ok<AGROW>
end
continue;
end
end
codeStruct = struct();
codeStruct.Sources = allSources;
codeStruct.Includes = allIncludes;
end
function clear_all_from_container(mask, containerName)
% allControls = mask.getDialogControls();
container = mask.getDialogControl(containerName);
@@ -190,69 +443,25 @@ classdef periphConfig
mcuMask.delete_all_tabs(mask, container);
end
end
methods(Static, Access=private)
function res = addCodeConfig(codeConfig, periphPath)
function res = addCodeBat(codeConfig, codePath)
% Добавить сурсы и пути в батник
% Возвращает 0 при успехе, 1 при ошибке
try
% Источники
srcList = {};
if isfield(codeConfig, 'Sources') && isfield(codeConfig.Sources, 'Options')
srcFiles = codeConfig.Sources.Options;
for i = 1:numel(srcFiles)
fullPath = fullfile(periphPath, srcFiles{i});
srcList{end+1} = [strrep(fullPath, '\', '\\')];
end
end
% Формируем srcText с переносами строк и ^
srcText = '';
for i = 1:numel(srcList)
if i < numel(srcList)
srcText = [srcText srcList{i} '^' newline ' '];
else
srcText = [srcText srcList{i}];
end
end
% Инклуды
incList = {};
if isfield(codeConfig, 'Includes') && isfield(codeConfig.Includes, 'Options')
incPaths = codeConfig.Includes.Options;
for i = 1:numel(incPaths)
fullPath = fullfile(periphPath, incPaths{i});
incList{end+1} = ['-I"' strrep(fullPath, '\', '\\') '"'];
end
end
% Формируем incText с переносами строк и ^
incText = '';
for i = 1:numel(incList)
if i == 1 && numel(incList) ~= 1
incText = [incText incList{i} '^' newline];
elseif i < numel(incList)
incText = [incText ' ' incList{i} '^' newline];
else
incText = [incText ' ' incList{i}];
end
end
% Добавляем префиксы
srcText = ['set code_PERIPH' '=' srcText];
incText = ['set includes_PERIPH' '=' incText];
% Формируем строки
srcText = compiler.createSourcesBat('code_PERIPH', codeConfig.Sources, codePath);
incText = compiler.createIncludesBat('includes_PERIPH', codeConfig.Includes, codePath);
% Записываем результат
res = periphConfig.updateRunMexBat(srcText, incText); % Всё прошло успешно
res = compiler.updateRunMexBat(srcText, incText, ':: PERIPH BAT'); % Всё прошло успешно
catch
% В случае ошибки просто возвращаем 1
res = 1;
end
end
function res = addUserCodeConfig(userCodeConfig)
function res = addUserFunctions(userCodeConfig)
% Добавить функции и дефайны в исходный код wrapper
% userCodeConfig — структура config.UserCode
initFuncsText = '';
@@ -262,34 +471,33 @@ classdef periphConfig
if isfield(userCodeConfig, 'Functions')
funcs = userCodeConfig.Functions;
if isfield(funcs, 'PeriphInit') && isfield(funcs.PeriphInit, 'Options')
initFuncs = funcs.PeriphInit.Options;
if isfield(funcs, 'PeriphInit')
initFuncs = funcs.PeriphInit;
initFuncsText = strjoin(strcat('\t', initFuncs, ';'), '\n');
end
if isfield(funcs, 'PeriphSimulation') && isfield(funcs.PeriphSimulation, 'Options')
simFuncs = funcs.PeriphSimulation.Options;
if isfield(funcs, 'PeriphSimulation')
simFuncs = funcs.PeriphSimulation;
simFuncsText = strjoin(strcat('\t', simFuncs, ';'), '\n');
end
if isfield(funcs, 'PeriphDeinit') && isfield(funcs.PeriphDeinit, 'Options')
deinitFuncs = funcs.PeriphDeinit.Options;
if isfield(funcs, 'PeriphDeinit')
deinitFuncs = funcs.PeriphDeinit;
deinitFuncsText = strjoin(strcat('\t', deinitFuncs, ';'), '\n');
end
res = periphConfig.updateWrapperCode(initFuncsText, simFuncsText, deinitFuncsText);
res = periphConfig.writeWrapperCode(initFuncsText, simFuncsText, deinitFuncsText);
end
end
function res = updateWrapperCode(initFuncsText, simFuncsText, deinitFuncsText)
function res = writeWrapperCode(initFuncsText, simFuncsText, deinitFuncsText)
% Входные параметры:
% srcText - текст для записи set code_...
% incText - текст для записи set includes_...
%
% Возвращает:
% res - 0 при успехе, 1 при ошибке
wrapPath = fullfile('.\MCU_Wrapper', 'mcu_wrapper.c');
wrapPath = fullfile(mcuPath.get('wrapperPath'), 'mcu_wrapper.c');
res = 1;
try
code = fileread(wrapPath);
@@ -311,47 +519,27 @@ classdef periphConfig
error('Ошибка: неудачная запись в файл при записи файла: %s', ME.message);
end
end
function res = updateRunMexBat(srcText, incText)
% Входные параметры:
% srcText - текст для записи set code_...
% incText - текст для записи set includes_...
%
% Возвращает:
% res - 0 при успехе, 1 при ошибке
periphBat = [srcText '\n\n' incText];
batPath = fullfile('.\MCU_Wrapper', 'run_mex.bat');
res = 1;
try
code = fileread(batPath);
code = regexprep(code, '\r\n?', '\n');
% Записываем строки srcText и incText с переносами строк
code = editCode.insertSection(code, ':: PERIPH BAT', periphBat);
fid = fopen(batPath, 'w', 'n', 'UTF-8');
if fid == -1
error('Не удалось открыть файл для записи');
end
fwrite(fid, code);
fclose(fid);
res = 1;
catch ME
mcuMask.disp(0, '\nОшибка: неудачная запись в файл при записи файла: %s', ME.message);
end
end
function addDefineConfig(mask, containerName, periphName, defPrompt, def)
function addConfig(mask, containerName, periphName, defPrompt, def, rowCountMap, rowWidth)
% mask — объект маски Simulink.Mask.get(blockPath)
% containerName — имя контейнера, в который добавляем параметр (например, 'configTabAll')
% periphName — имя вкладки / контейнера для текущего периферийного блока (например, 'ADC')
% defPrompt — имя параметра в Defines (например, 'shift_enable')
% def — структура с описанием параметра (Prompt, Def, Type, Default, NewRow и т.п.)
if ~isKey(rowCountMap, periphName)
rowCountMap(periphName) = 0;
end
rowCount = rowCountMap(periphName) + 1;
% Устанавливаем NewRow, если он не задан
if ~isfield(def, 'NewRow')
def.NewRow = mod(rowCount - 1, rowWidth) == 0;
elseif def.NewRow == true
rowCount = 1;
end
rowCountMap(periphName) = rowCount;
% Найдем контейнер с таким именем
container = mask.getDialogControl(containerName);
if isempty(container)
@@ -371,6 +559,8 @@ classdef periphConfig
paramType = 'checkbox';
case 'edit'
paramType = 'edit';
case 'popup'
paramType = 'popup';
otherwise
% Игнорируем остальные типы
return;
@@ -378,26 +568,48 @@ classdef periphConfig
paramName = matlab.lang.makeValidName(defPrompt);
% Преобразуем значение Default в строку для Value
val = def.Default;
if islogical(val)
valStr = mcuMask.ternary(val, 'on', 'off');
elseif isnumeric(val)
valStr = num2str(val);
elseif ischar(val)
valStr = val;
% Получаем значение
if strcmp(paramType, 'popup')
if isfield(def, 'Def') && iscell(def.Def) && ~isempty(def.Def)
choices = def.Def;
valStr = ''; % по умолчанию — ничего
elseif isfield(def, 'Options')
choices = def.Def;
valStr = ''; % по умолчанию — ничего
else
warning('Popout параметр "%s" не содержит допустимого списка в Def.', defPrompt);
return;
end
else
error('Unsupported default value type for %s.%s', periphName, defPrompt);
val = def.Default;
if islogical(val)
valStr = periphConfig.ternary(val, 'on', 'off');
elseif isnumeric(val)
valStr = num2str(val);
elseif ischar(val)
valStr = val;
else
error('Unsupported default value type for %s.%s', periphName, defPrompt);
end
end
% Добавляем параметр в маску
param = mask.addParameter( ...
'Type', paramType, ...
'Prompt', def.Prompt, ...
'Name', paramName, ...
'Value', valStr, ...
'Container', periphName ...
);
if strcmp(paramType, 'popup')
param = mask.addParameter( ...
'Type', paramType, ...
'Prompt', def.Prompt, ...
'Name', paramName, ...
'Container', periphName ...
);
else
param = mask.addParameter( ...
'Type', paramType, ...
'Prompt', def.Prompt, ...
'Name', paramName, ...
'Value', valStr, ...
'Container', periphName ...
);
end
param.Evaluate = 'off';
@@ -406,9 +618,80 @@ classdef periphConfig
else
param.DialogControl.Row = 'current';
end
param.Alias = def.Def;
if isfield(def, 'Def')
if strcmp(paramType, 'popup')
if iscell(def.Def)
param.TypeOptions = def.Def;
elseif isfield(def, 'Options')
param.Alias = def.Def;
param.TypeOptions = def.Options;
end
else
param.Alias = def.Def;
end
end
callback = sprintf('periphConfig.periphParamCallback("%s");', paramName);
param.Callback = callback;
end
%% ELEMENTARY
function clear_single_periph_code_param(mask, periph)
% Очистка кода одного поля конфига
paramNames = {
['Hidden_' char(periph) '_Sources'],
['Hidden_' char(periph) '_Includes']
};
for i = 1:numel(paramNames)
paramName = paramNames{i};
try
param = mask.getParameter(paramName);
param.Value = '';
catch
% Параметр не существует — ничего не делаем
end
end
end
function store_single_periph_code(mask, periph, code)
% Запись кода одного поля конфига
% Сохраняем Sources, если они есть
if isfield(code, 'Sources')
paramName = ['Hidden_' char(periph) '_Sources'];
try
param = mask.getParameter(paramName);
param.Value = configJs.convert_code_value(code.Sources);
catch
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
end
end
% Сохраняем Includes, если они есть
if isfield(code, 'Includes')
paramName = ['Hidden_' char(periph) '_Includes'];
try
param = mask.getParameter(paramName);
param.Value = configJs.convert_code_value(code.Includes);
catch
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
end
end
end
function res = ternary(cond, valTrue, valFalse)
if cond
res = valTrue;
else
res = valFalse;
end
end
end
end