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

209 lines
13 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 appWrap
% Класс для редактирования кода обёртки МК прямо внутри MATLAB/Simulink
% Позволяет работать с кодом микроконтроллера без переключения между IDE
methods(Static)
function appWrapperFunc()
% Загружает код обёртки из файлов в интерфейс MATLAB для редактирования
% Автоматически вызывается при выборе типа кода в маске блока
block = gcb; % Получаем текущий блок Simulink для редактирования
% Определяем какой файл и секцию нужно редактировать
[filename, section, tool, example] = appWrap.getAppWrapperUserFile(block);
% Показываем подсказку по выбранному типу кода прямо в MATLAB
mcuMask.tool(tool, example);
% Очищаем поле редактирования перед загрузкой нового кода
set_param(block, 'appWrapperCode', '');
% Загружаем код из файла в интерфейс MATLAB
try
% Читаем исходный код из файла
code = fileread(filename);
code = regexprep(code, '\r\n?', '\n'); % унифицируем переводы строк для MATLAB
% Вырезаем только нужную секцию для редактирования
includesText = editCode.extractSection(code, section);
% Загружаем код в текстовое поле маски для редактирования
set_param(block, 'appWrapperCode', includesText);
catch
% Если файл не найден или ошибка чтения - оставляем поле пустым
% Пользователь сможет написать код с нуля прямо в MATLAB
end
end
function saveAppWrapperCode()
% Сохраняет отредактированный код из MATLAB обратно в файлы обёртки
% Вызывается при нажатии кнопки "Сохранить" в интерфейсе
block = gcb; % Текущий редактируемый блок
% Определяем куда сохранять based на выборе пользователя в MATLAB
[filename, section] = appWrap.getAppWrapperUserFile(block);
% Проверяем что файл существует перед сохранением
if ~isfile(filename)
errordlg(['Файл не найден: ', filename], 'Ошибка сохранения в MATLAB');
return;
end
% Получаем выбранный тип кода и путь к файлам
sel = get_param(block, 'appWrapperFunc');
basePath = get_param(block, 'appWrapperPath');
if isempty(basePath)
errordlg('Не указан путь к файлам обёртки.', 'Ошибка в MATLAB');
return;
end
% Получаем код который пользователь написал/отредактировал в MATLAB
newBody = get_param(block, 'appWrapperCode');
% Читаем текущее содержимое файла чтобы сохранить структуру
code = fileread(filename);
code = regexprep(code, '\r\n?', '\n');
% Экранируем специальные символы для корректного сохранения из MATLAB
newBody = strrep(newBody, '\', '\\');
% Вставляем отредактированную в MATLAB секцию обратно в файл
code = editCode.insertSection(code, section, newBody);
% Сохраняем изменения прямо из MATLAB без внешних редакторов
fid = fopen(filename, 'w', 'n', 'UTF-8');
if fid == -1
errordlg('Не удалось сохранить файл из MATLAB', 'Ошибка записи');
return;
end
% Записываем обновленный код
fwrite(fid, code);
fclose(fid);
% Подтверждаем успешное сохранение в интерфейсе MATLAB
mcuMask.disp(1, ['Сохранено в MATLAB: ' sel]);
end
function openAppWrapperCode()
% Альтернативный способ: открывает файл в системном редакторе
% Для случаев когда нужно работать во внешней IDE
block = gcb;
% Получаем абсолютный путь к файлу для открытия
filename = mcuPath.getAbsolutePath(appWrap.getAppWrapperUserFile(block));
if exist(filename, 'file') == 2
% Открываем через системный диалог "Открыть с помощью"
% Полезно если нужно использовать привычную IDE вместо редактора MATLAB
cmd = sprintf('rundll32.exe shell32.dll,OpenAs_RunDLL %s', filename);
status = system(cmd);
if status ~= 0
errordlg('Не удалось открыть файл во внешнем редакторе');
end
else
errordlg('Файл не найден для открытия');
end
end
%% SPECIFIC TOOLS
function [filename, section, tool, example] = getAppWrapperUserFile(block, sel)
% Маппинг типов кода на файлы и секции для редактирования в MATLAB
% Центральное место настройки - здесь определяется где что редактировать
if (nargin < 2)
% Получаем какой тип кода пользователь выбрал в интерфейсе MATLAB
sel = get_param(block, 'appWrapperFunc');
end
% Базовый путь к файлам обёртки (настраивается в маске)
basePath = mcuPath.get('appWrapperPath');
if isempty(basePath)
errordlg('Не указан путь к файлам обёртки.');
return;
end
% В зависимости от выбора в MATLAB - определяем что редактировать:
if strcmp(sel, 'Includes')
% Редактирование подключения заголовочных файлов
filename = fullfile(basePath, 'app_includes.h');
section = '// INCLUDES';
tool = 'Инклюды для доступа к коду МК в коде оболочке';
example = '#include "main.h"'; % Пример для подсказки в MATLAB
elseif strcmp(sel, 'Dummy')
% Редактирование заглушек для симуляции
filename = fullfile(basePath, 'app_wrapper.c');
section = '// DUMMY';
tool = 'Заглушки для различных функций и переменных';
example = ['CAN_HandleTypeDef hcan = {0};' newline...
'void hardware_func(handle *huart) {}' newline...
'int wait_for_hardware_flag(int *flag) {' newline...
' return 1;' newline...
'}' newline...
''];
elseif strcmp(sel, 'App Init')
% Редактирование кода инициализации приложения
filename = fullfile(basePath, 'app_init.c');
section = '// USER APP INIT';
tool = ['Код для инициализации приложения МК.' newline newline...
'Вызов функций инициализации, если не используется отдельный поток для main().'];
example = 'init_func();';
elseif strcmp(sel, 'App Step')
% Редактирование кода выполняемого на каждом шаге симуляции
filename = fullfile(basePath, 'app_wrapper.c');
section = '// USER APP STEP';
tool = ['Код приложения МК для вызова в шаге симуляции.' newline newline ...
'Вызов функций программы МК, если не используется отдельный поток для main().'];
example = 'step_func();';
elseif strcmp(sel, 'App Inputs')
% Редактирование обработки входных данных от Simulink
filename = fullfile(basePath, 'app_io.c');
section = '// USER APP INPUT';
tool = ['Работа с буффером для портов S-Function' newline newline ...
'Буфер в начале хранит входные порты S-Function, далее идут выходные порты:' newline ...
'Buffer[0:15] - входной порт, Buffer[16:31] - входной 1 порт, ' newline ...
'Buffer[32:47] - выходной 1 порт, Buffer[48:63] - выходной 2 порт'];
example = ['// чтение 1-го элемента 0-го входного массива' newline...
'app_variable_2 = ReadInputArray(0, 1);' newline newline...
'// запись в буфер выходов' newline ...
'app_variable_2 = Buffer[10];'];
elseif strcmp(sel, 'App Outputs')
% Редактирование формирования выходных данных для Simulink
filename = fullfile(basePath, 'app_io.c');
section = '// USER APP OUTPUT';
tool = ['Работа с буффером для портов S-Function' newline newline ...
'Буфер в начале хранит входные порты S-Function, далее идут выходные порты:' newline ...
'Buffer[0:15] - входной порт, Buffer[16:31] - входной 1 порт, ' newline ...
'Buffer[32:47] - выходной 1 порт, Buffer[48:63] - выходной 2 порт'];
example = ['// запись в 1-й элемент 0-го выходного массива' newline...
'WriteOutputArray(app_variable, 0, 1);' newline newline ...
'// запись в буфер выходов' newline ...
'Buffer[XD_OUTPUT_START + 10] = app_variable_2;'];
elseif strcmp(sel, 'App Deinit')
% Редактирование кода деинициализации
filename = fullfile(basePath, 'app_init.c');
section = '// USER APP DEINIT';
tool = ['Код для деинициализации приложения МК.' newline newline ...
'Можно деинициализировать приложение МК, для повторного запуска.'];
example = 'memset(&htim1, sizeof(htim1), 0;';
else
% Неизвестный тип кода - выводим сообщение в консоль MATLAB
tool = '';
mcuMask.disp(0, '\nОшибка выбора типа секции кода: неизвестное значение');
end
end
end
end