209 lines
13 KiB
Matlab
209 lines
13 KiB
Matlab
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 |