diff --git a/config_reader.m b/config_reader.m index 713783e..5915015 100644 --- a/config_reader.m +++ b/config_reader.m @@ -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 diff --git a/mcu_test_r2023.slx b/mcu_test_r2023.slx index 898e9d4..2e50257 100644 Binary files a/mcu_test_r2023.slx and b/mcu_test_r2023.slx differ diff --git a/mexing.asv b/mexing.asv index 5220da6..1f19a0c 100644 --- a/mexing.asv +++ b/mexing.asv @@ -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 diff --git a/mexing.m b/mexing.m index 6a99822..dae1b07 100644 --- a/mexing.m +++ b/mexing.m @@ -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 diff --git a/periph_config.json b/periph_config.json index 8973e22..379ebce 100644 --- a/periph_config.json +++ b/periph_config.json @@ -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 }