mcu_matlab/McuLib/m/mcuMask.m
2025-06-19 13:29:33 +03:00

329 lines
13 KiB
Matlab
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

classdef mcuMask
%% CALLBACKS
methods(Static)
% Following properties of 'maskInitContext' are avalaible to use:
% - BlockHandle
% - MaskObject
% - MaskWorkspace - Use get/set APIs to work with mask workspace.
function MaskInitialization(maskInitContext)
% Получаем хэндл текущего блока
blk = gcbh;
% Получаем объект маски текущего блока
mask = Simulink.Mask.get(gcb);
set_param(blk,"MaskSelfModifiable","on")
set_param(blk, 'LinkStatus', 'none');
% mcuMask.disp(1,'');
try
% Проверка наличия findjobj
findjobjAvailable = exist('findjobj', 'file') == 2;
catch
findjobjAvailable = false;
end
% Имя checkbox-параметра (укажите точное имя из маски)
checkboxParamName = 'extConsol'; % пример
findjobjLinkName = 'findjobj_link'; % пример
% Получаем параметр по имени
checkboxParam = mask.getParameter(checkboxParamName);
findjobjLink = mask.getDialogControl(findjobjLinkName);
if isempty(findjobjLink)
error('Параметр %s не найден в маске.', findjobjLinkName);
end
if isempty(checkboxParam)
error('Параметр %s не найден в маске.', checkboxParamName);
end
% Блокируем чекбокс, если findjobj не найден
if ~findjobjAvailable
checkboxParam.Enabled = 'off';
checkboxParam.Value = 'off'; % и на всякий случай снимаем галочку
checkboxParam.Prompt = 'External Console (requires findjobj)';
findjobjLink.Visible = 'on';
else
checkboxParam.Enabled = 'on';
checkboxParam.Prompt = 'External Console';
findjobjLink.Visible = 'off';
end
% формирование таблицы на всю ширину
table_names = {'srcTable', 'incTable'};
for k = 1:numel(table_names)
table_name = table_names{k};
customtable.format(table_name);
end
% запись описания блока
textDesc = ['Блок для настройки параметров симуляции микроконтроллера. ' newline ...
'Позволяет задавать параметры оболочки, приложения МК и периферии'];
% Получаем объект описания
toolTextArea = mask.getDialogControl('BlockDesc');
toolTextArea.Prompt = textDesc;
end
%% WRAPPER PARAMS
function wrapperPath_add(callbackContext)
mcuPath.addPath('wrapperPath');
end
function enableThreading(callbackContext)
mainWrap.enableThreading();
end
function enableDeinit(callbackContext)
mainWrap.enableDeinit();
end
function extConsol(callbackContext)
mainWrap.extConsol();
end
%% USER WRAPPER CODE
function appWrapperPath_add(callbackContext)
mcuPath.addPath('appWrapperPath');
end
function appWrapperFunc(callbackContext)
appWrap.appWrapperFunc();
end
function saveAppWrapperCode(callbackContext)
appWrap.saveAppWrapperCode();
end
function openAppWrapperCode(callbackContext)
appWrap.openAppWrapperCode();
end
%% USER CODE
function srcTable(callbackContext)
customtable.update('srcTable');
end
function incTable(callbackContext)
customtable.update('incTable');
end
function btnAddSrc(callbackContext)
mcuPath.addSourceFileTable('srcTable', 'Выберите исходные файлы');
end
function btnAddInc(callbackContext)
mcuPath.addPathTable('incTable', 'Выберите папку с заголовочными файлами');
end
%% PERIPH CONFIG
function periphPath_add(callbackContext)
mcuPath.addAnyFile('periphPath');
end
function periphUpdate(callbackContext)
modelName = bdroot(gcb); % получить имя верхнего уровня модели
blockName = gcb;
mgr = asynchManage(modelName, blockName); % создать объект класса
mgr.updateGUIfromConfig(); % запустить сохранение и обновление
end
%% COMPILE
function compile(callbackContext)
compiler.compile();
end
function setSFuncName(callbackContext)
block = gcb;
% Получаем параметр имени S-Function из маски блока
newName = mcuMask.get_name();
% Путь к файлу, в котором надо заменить строку
cFilePath = fullfile(pwd, mcuPath.get('wrapperPath'), 'MCU.c'); % <-- укажи правильный путь
% Считаем файл в память
try
fileText = fileread(cFilePath);
catch
return;
end
% Регулярное выражение для поиска строки с define
% Заменим строку вида: #define S_FUNCTION_NAME old_name
pattern = '#define\s+S_FUNCTION_NAME\s+\w+';
% Новая строка
newLine = ['#define S_FUNCTION_NAME ', newName];
% Замена
updatedText = regexprep(fileText, pattern, newLine);
% Записываем обратно в файл
fid = fopen(cFilePath, 'w', 'n', 'UTF-8');
if fid == -1
error('Не удалось открыть файл для записи.');
end
fwrite(fid, updatedText);
fclose(fid);
end
%% LINK TO EXTERNAL CONSOLE
function findjobj_link(callbackContext)
web https://www.mathworks.com/matlabcentral/fileexchange/14317-findjobj-find-java-handles-of-matlab-graphic-objects;
end
end
%% GENERAL TOOLS
methods(Static, Access = public)
function updateModel()
addpath(mcuPath.get('wrapperPath'));
res = mexing(1);
if res ~= 0
return;
end
% modelName = bdroot(gcb); % получить имя верхнего уровня модели
% blockName = gcb;
% mgr = asynchManage(modelName, blockName); % создать объект класса
% mgr.saveAndUpdateModel(); % запустить сохранение и обновление
end
function close(blockPath)
try
% Считываем текущее имя модели
modelName = bdroot(blockPath);
% Включаем возможность изменения маски
set_param(blockPath, 'MaskSelfModifiable', 'on');
% Считываем текущие значения параметров маски
currentMaskValues = get_param(blockPath, 'MaskValues');
% Применяем текущие значения заново, чтобы "применить" маску
set_param(blockPath, 'MaskValues', currentMaskValues);
save_system(modelName);
catch ME
warning('progr:Nneg', 'Ошибка при сохранении маски: %s', ME.message);
end
close_system(blockPath, 0);
end
function open(blockPath, clear_flag)
open_system(blockPath, 'mask');
mcuMask.disp(clear_flag, '');
end
function name = get_name()
block = gcb;
% Получаем параметр имени S-Function из маски блока
name = get_param(block, 'sfuncName');
end
function checkbox_state = read_checkbox(checkboxName)
maskValues = get_param(gcbh, 'MaskValues');
paramNames = get_param(gcbh, 'MaskNames');
inxCheckBox = find(strcmp(paramNames, checkboxName));
checkbox_state_str = maskValues{inxCheckBox};
if strcmpi(checkbox_state_str, 'on')
checkbox_state = 1;
else
checkbox_state = 0;
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
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, mcuMask.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')
% Сначала рекурсивно удаляем вкладки внутри текущей вкладки
mcuMask.delete_all_tabs(mask, ctrl);
try
container.removeDialogControl(ctrl.Name);
catch ME
warning('Не удалось удалить вкладку %s: %s', ctrl.Name, ME.message);
end
end
end
end
function tool(text, example)
% Устанавливает заданный текст в параметр Text Area 'toolText' через объект маски
% Получаем ссылку на текущий блок
block = gcb;
% Получаем объект маски
mask = Simulink.Mask.get(block);
toolTextArea = mask.getDialogControl('toolText');
exampleTextArea = mask.getDialogControl('exampleText');
toolTextArea.Prompt = text;
exampleTextArea.Prompt = example;
end
function disp(clcFlag, varargin)
if clcFlag
set_param(gcb, 'consoleOutput', '');
end
if length(varargin) == 1 && ischar(varargin{1})
% Если передан один аргумент — просто строка, передаем напрямую
out = varargin{1};
else
% Иначе считаем, что первый аргумент — формат, остальные — параметры
out = sprintf(varargin{:});
end
out_now = get_param(gcb, 'consoleOutput');
if ~strcmp(out, '') && ~strcmp(out_now, '')
set_param(gcb, 'consoleOutput', [out_now newline out]);
else
set_param(gcb, 'consoleOutput', [out_now out]);
end
end
function updateModelAsync()
mdl = bdroot(gcb);
try
% Применить изменения, если есть
set_param(mdl, 'ApplyChanges', 'on');
catch
beep
% Игнорировать, если не удалось
end
t = timer('StartDelay', 0.01, 'TimerFcn', @(~,~) set_param(mdl, 'SimulationCommand', 'update'));
start(t);
end
end
end