mcu_matlab/McuLib/m/mcuMask.m
2025-11-07 14:52:52 +03:00

336 lines
14 KiB
Matlab
Raw 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
% Главный класс управления маской блока Simulink для микроконтроллера
% Содержит callback-функции и утилиты для работы с маской
%% CALLBACKS - функции обратного вызова для элементов маски
methods(Static)
% Функция инициализации маски - вызывается при загрузке блока
function MaskInitialization(maskInitContext)
% Получаем хэндл текущего блока
blk = gcbh;
% Получаем объект маски текущего блока
mask = Simulink.Mask.get(gcb);
% Разрешаем самомодификацию маски и отключаем ссылки
set_param(blk,"MaskSelfModifiable","on")
set_param(blk, 'LinkStatus', 'none');
% Проверяем доступность findjobj для внешней консоли
try
findjobjAvailable = exist('findjobj', 'file') == 2;
catch
findjobjAvailable = false;
end
% Настраиваем параметры внешней консоли в зависимости от доступности findjobj
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 - callback-функции для параметров обёртки
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 - callback-функции для пользовательского кода
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 - callback-функции для пользовательского кода
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 - callback-функции для конфигурации периферии
function periphPath_add(callbackContext)
% Добавление пути к конфигурационному файлу периферии
mcuPath.addAnyFile('periphPath');
end
function periphUpdate(callbackContext)
% Обновление конфигурации периферии с асинхронным управлением
modelName = bdroot(gcb);
blockName = gcb;
mgr = asynchManage(modelName, blockName);
mgr.updateGUIfromConfig(); % Запуск обновления через таймер
end
%% COMPILE - callback-функции для компиляции
function compile(callbackContext)
% Компиляция S-функции
compiler.compile();
end
function setSFuncName(callbackContext)
% Установка имени S-функции в исходном коде
block = gcb;
newName = mcuMask.get_name();
% Путь к файлу MCU.c
cFilePath = fullfile(pwd, mcuPath.get('wrapperPath'), 'MCU.c');
% Чтение файла
try
fileText = fileread(cFilePath);
catch
return;
end
% Поиск и замена определения имени S-функции
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 - callback для внешней консоли
function findjobj_link(callbackContext)
% Открытие ссылки на утилиту findjobj
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()
% Обновление модели с компиляцией S-функции
addpath(mcuPath.get('wrapperPath'));
res = mexing(1);
if res ~= 0
return;
end
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()
% Получение имени S-функции из параметра маски
block = gcb;
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;
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)
% Установка текста подсказки и примера в элементы маски
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
function v = getMyLibVersion()
% Получение версии библиотеки
v = 'pre-1.04';
end
end
end