переделана структура задавания дефайнов

теперь для дефайна используется альтернативное имя alias. и есть функция, которая выставляет дефайн по chekcbox/edit и его альтернативной функции

для конфигов такая механика тоже реализована - и  она работает
This commit is contained in:
Razvalyaev 2025-06-12 12:08:34 +03:00
parent a6c5a9edab
commit ead46d7d82
5 changed files with 403 additions and 111 deletions

View File

@ -4,12 +4,26 @@ model = 'mcu_test_r2023';
block = [model '/MCU_UPP'];
load_system(model); % если модель ещё не загружена
config = load_periph_config();
update_mask_from_config(block, config);
update_mask_from_config(block);
disp('Маска обновлена по конфигу');
disp('Маска обновлена по конфигу.');
function update_mask_from_config(blockPath)
config = load_periph_config();
%% чтение конфигов
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)
@ -48,7 +62,7 @@ function update_mask_from_config(blockPath)
continue;
end
paramName = matlab.lang.makeValidName([periph '_' defPrompt]);
paramName = matlab.lang.makeValidName([defPrompt]);
val = def.Default;
if islogical(val)
@ -73,45 +87,9 @@ function update_mask_from_config(blockPath)
'Name', paramName, ...
'Value', valStr, ...
'Container', tabName);
end
end
end
function config = load_periph_config()
jsonText = fileread('periph_config.json');
config = jsondecode(jsonText);
end
function clear_params_from_tab(blockPath, tabName)
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, tabName)
tabName = tabs(i).Name; % внутреннее имя вкладки
break;
end
end
if isempty(tabName)
error('Вкладка с названием "%s" не найдена.', tabName);
end
% Удаляем параметры с TabName == tabName
i = 1;
while i <= numel(mask.Parameters)
if strcmp(mask.Parameters(i).TabName, tabName)
mask.removeParameter(i);
else
i = i + 1;
param = mask.getParameter(paramName);
param.Alias = def.Def;
end
end
end

Binary file not shown.

View File

@ -11,9 +11,10 @@ delete(".\MCU_Wrapper\Outputs\*.*");
set_param(gcb, 'consoleOutput', '');
% Флаг режима отладки
definesArg = buildWrapperDefinesString();
definesWrapperArg = buildWrapperDefinesString();
definesUserArg = parseDefinesMaskText();
definesAllArg = [definesArg + " " + definesUserArg];
definesConfigArg = buildConfigDefinesString();
definesAllArg = [definesUserArg + " " + definesWrapperArg + " " + definesConfigArg];
if read_checkbox('enableDebug')
@ -53,7 +54,7 @@ beep
%% DEFINE PARAMS
%% COMPILE PARAMS
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
@ -96,38 +97,45 @@ end
function definesWrapperArg = buildWrapperDefinesString()
blockHandle = gcbh;
% Получаем MaskValues и MaskNames
maskValues = get_param(blockHandle, 'MaskValues');
paramNames = get_param(blockHandle, 'MaskNames');
definesWrapperArg = '';
definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
% Индексы параметров
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) '"'];
definesArg = strjoin({def1, def2, def3, def4}, ' ');
% 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
@ -182,6 +190,73 @@ function definesUserArg = parseDefinesMaskText()
end
function definesWrapperArg = buildConfigDefinesString()
blockHandle = gcbh;
mask = Simulink.Mask.get(blockHandle);
tabName = 'configTab'; % Имя вкладки (Prompt)
allControls = mask.getDialogControls();
tabCtrl = find_tab_by_name(allControls, tabName);
if isempty(tabCtrl)
error('Вкладка с названием "%s" не найдена в маске', tabName);
end
definesWrapperArg = '';
% Получаем все контролы внутри вкладки
children = tabCtrl.DialogControls;
for i = 1:numel(children)
ctrl = children(i);
isprop(ctrl, 'Type')
isprop(ctrl, 'Name')
if isprop(ctrl, 'Type') && isprop(ctrl, 'Name')
switch lower(ctrl.Type)
case 'checkbox'
definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 0);
case 'edit'
definesWrapperArg = addDefineByParam(definesWrapperArg, ctrl.ParameterName, 1);
otherwise
% Пропускаем другие типы
end
end
end
% blockHandle = gcbh;
%
% % Получаем MaskValues и MaskNames
% maskValues = get_param(blockHandle, 'MaskValues');
% paramNames = get_param(blockHandle, 'MaskNames');
%
% % Индексы параметров
% idxCycles = find(strcmp(paramNames, 'threadCycles'));
% idxClk = find(strcmp(paramNames, 'mcuClk'));
%
% % Значения
% cyclesVal = maskValues{idxCycles};
% clkMHz = str2double(maskValues{idxClk});
% clkHz = round(clkMHz * 1e6);
%
% % Формируем defines в формате: -D"NAME=VALUE"
% if read_checkbox('enableThreading')
% def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
% else
% def1 = [''];
% end
%
% if read_checkbox('enableDeinit')
% def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
% else
% def2 = [''];
% end
%
% def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
% def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
%
% definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
end
%% PARSE FUNCTIONS
function out = parseCellString(str)
@ -211,6 +286,49 @@ function str = cellArrayToString(cellArray)
end
function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
blockHandle = gcbh;
mask = Simulink.Mask.get(blockHandle);
% Получаем MaskValues, MaskNames
maskValues = get_param(blockHandle, 'MaskValues');
paramNames = get_param(blockHandle, 'MaskNames');
param = mask.getParameter(paramName); % для alias
% Найдём индекс нужного параметра
idxParam = find(strcmp(paramNames, paramName), 1);
if isempty(idxParam)
error('Parameter "%s" not found in block mask parameters.', paramName);
end
% Берём alias из маски
alias = param.Alias;
if val_define ~= 0
% Значение параметра
val = maskValues{idxParam};
% Формируем define с кавычками и значением
newDefine = ['-D"' alias '__EQ__' val '"'];
else
if read_checkbox(paramName)
% Формируем define с кавычками без значения
newDefine = ['-D"' alias '"'];
else
newDefine = '';
end
end
% Добавляем новый define к существующему (string)
if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
definesWrapperArg = newDefine;
else
definesWrapperArg = definesWrapperArg + " " + newDefine;
end
end
function checkbox_state = read_checkbox(checkboxName)
maskValues = get_param(gcbh, 'MaskValues');
@ -226,6 +344,41 @@ 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

223
mexing.m
View File

@ -13,7 +13,8 @@ set_param(gcb, 'consoleOutput', '');
% Флаг режима отладки
definesWrapperArg = buildWrapperDefinesString();
definesUserArg = parseDefinesMaskText();
definesAllArg = [definesWrapperArg + " " + definesUserArg];
definesConfigArg = buildConfigDefinesString();
definesAllArg = [definesUserArg + " " + definesWrapperArg + " " + definesConfigArg];
if read_checkbox('enableDebug')
@ -53,7 +54,7 @@ beep
%% DEFINE PARAMS
%% COMPILE PARAMS
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
@ -96,38 +97,45 @@ end
function definesWrapperArg = buildWrapperDefinesString()
blockHandle = gcbh;
% Получаем MaskValues и MaskNames
maskValues = get_param(blockHandle, 'MaskValues');
paramNames = get_param(blockHandle, 'MaskNames');
definesWrapperArg = '';
definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
% Индексы параметров
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}, ' ');
% 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
@ -182,6 +190,79 @@ function definesUserArg = parseDefinesMaskText()
end
function definesWrapperArg = buildConfigDefinesString()
blockHandle = gcbh;
mask = Simulink.Mask.get(blockHandle);
tabName = 'configTab'; % Имя вкладки (Prompt)
allControls = mask.getDialogControls();
tabCtrl = find_tab_by_name(allControls, tabName);
if isempty(tabCtrl)
error('Вкладка с названием "%s" не найдена в маске', tabName);
end
definesWrapperArg = '';
% Получаем все контролы внутри вкладки
children = tabCtrl.DialogControls;
for i = 1:numel(children)
ctrl = children(i);
% Получаем имя параметра из контрола
paramName = ctrl.Name;
try
% Получаем объект параметра по имени
param = mask.getParameter(paramName);
% Определяем тип параметра
switch lower(param.Type)
case 'checkbox'
definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
case 'edit'
definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
otherwise
% Необрабатываемые типы
end
catch ME
warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
end
end
% blockHandle = gcbh;
%
% % Получаем MaskValues и MaskNames
% maskValues = get_param(blockHandle, 'MaskValues');
% paramNames = get_param(blockHandle, 'MaskNames');
%
% % Индексы параметров
% idxCycles = find(strcmp(paramNames, 'threadCycles'));
% idxClk = find(strcmp(paramNames, 'mcuClk'));
%
% % Значения
% cyclesVal = maskValues{idxCycles};
% clkMHz = str2double(maskValues{idxClk});
% clkHz = round(clkMHz * 1e6);
%
% % Формируем defines в формате: -D"NAME=VALUE"
% if read_checkbox('enableThreading')
% def1 = ['-D"RUN_APP_MAIN_FUNC_THREAD"'];
% else
% def1 = [''];
% end
%
% if read_checkbox('enableDeinit')
% def2 = ['-D"DEINITIALIZE_AFTER_SIM"'];
% else
% def2 = [''];
% end
%
% def3 = ['-D"DEKSTOP_CYCLES_FOR_MCU_APP__EQ__' cyclesVal '"'];
% def4 = ['-D"MCU_CORE_CLOCK__EQ__' num2str(clkHz) '"'];
%
% definesWrapperArg = strjoin({def1, def2, def3, def4}, ' ');
end
%% PARSE FUNCTIONS
function out = parseCellString(str)
@ -211,6 +292,49 @@ function str = cellArrayToString(cellArray)
end
function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
blockHandle = gcbh;
mask = Simulink.Mask.get(blockHandle);
% Получаем MaskValues, MaskNames
maskValues = get_param(blockHandle, 'MaskValues');
paramNames = get_param(blockHandle, 'MaskNames');
param = mask.getParameter(paramName); % для alias
% Найдём индекс нужного параметра
idxParam = find(strcmp(paramNames, paramName), 1);
if isempty(idxParam)
error('Parameter "%s" not found in block mask parameters.', paramName);
end
% Берём alias из маски
alias = param.Alias;
if val_define ~= 0
% Значение параметра
val = maskValues{idxParam};
% Формируем define с кавычками и значением
newDefine = ['-D"' alias '__EQ__' val '"'];
else
if read_checkbox(paramName)
% Формируем define с кавычками без значения
newDefine = ['-D"' alias '"'];
else
newDefine = '';
end
end
% Добавляем новый define к существующему (string)
if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
definesWrapperArg = newDefine;
else
definesWrapperArg = definesWrapperArg + " " + newDefine;
end
end
function checkbox_state = read_checkbox(checkboxName)
maskValues = get_param(gcbh, 'MaskValues');
@ -226,6 +350,41 @@ 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

View File

@ -11,7 +11,8 @@
"Type": "checkbox",
"Default": true
},
"SAMPLE_RATE": {
"Sample Rate (Hz)": {
"Def": "SAMPLE_RATE",
"Type": "edit",
"Default": 48000
}
@ -20,16 +21,17 @@
"TIM": {
"Defines": {
"TIM1 Enable": {
"Def": "ADC1_ENABLE",
"Def": "TIM1_ENABLE",
"Type": "checkbox",
"Default": true
},
"TIM2 Enable": {
"Def": "ADC2_ENABLE",
"Def": "TIM2_ENABLE",
"Type": "checkbox",
"Default": true
},
"AHB Buf Clock Rate (MHz)": {
"Def": "AHB_BUS_FREQ",
"Type": "edit",
"Default": 72
}