pre-release 1.04

This commit is contained in:
2025-11-07 14:52:52 +03:00
parent 041322a62e
commit 49be34efc9
16 changed files with 974 additions and 676 deletions

View File

@@ -1,36 +1,51 @@
classdef mcuPorts
% Класс для управления портами ввода-вывода в маске Simulink
% Генерирует конфигурационные файлы для портов на основе параметров маски
methods(Static)
function write()
% Основная функция записи конфигурации портов в файлы
% Генерирует заголовочный файл и файл реализации для портов
block = gcb;
mask = Simulink.Mask.get(block);
% Пути к конфигурационным файлам
hPath = fullfile(mcuPath.get('wrapperPath'), 'mcu_wrapper_conf.h');
cPath = fullfile(mcuPath.get('wrapperPath'), 'mcu_wrapper.c');
% Устанавливаем значения по умолчанию для неиспользуемых портов
mcuPorts.defaultUnused();
%% CREATE
%% СОЗДАНИЕ КОНФИГУРАЦИИ ДЛЯ ВХОДНЫХ ПОРТОВ
prefixNumb = 'IN';
[widths, portPrefixes] = mcuPorts.getMaskNames('in');
% Генерируем текст для заголовочного файла и файла реализации
headerText = mcuPorts.addPortHeaderDefines('', widths, prefixNumb, portPrefixes);
cText = mcuPorts.addPortCDefines('', widths, prefixNumb, portPrefixes);
%% СОЗДАНИЕ КОНФИГУРАЦИИ ДЛЯ ВЫХОДНЫХ ПОРТОВ
prefixNumb = 'OUT';
[widths, portPrefixes] = mcuPorts.getMaskNames('out');
% Добавляем выходные порты к существующей конфигурации
headerText = mcuPorts.addPortHeaderDefines(headerText, widths, prefixNumb, portPrefixes);
cText = mcuPorts.addPortCDefines(cText, widths, prefixNumb, portPrefixes);
%% WRITE
%% ЗАПИСЬ В ФАЙЛЫ
% Читаем существующее содержимое файлов
hCode = fileread(hPath);
hCode = regexprep(hCode, '\r\n?', '\n');
cCode = fileread(cPath);
cCode = regexprep(cCode, '\r\n?', '\n');
% Вставляем сгенерированную конфигурацию в заголовочный файл
code = editCode.insertSection(hCode, '// INPUT/OUTPUTS PARAMS', headerText.PARAMS);
code = editCode.insertSection(code, '// INPUT/OUTPUTS AUTO-PARAMS', headerText.AUTO_PARAMS);
% Записываем обновленный заголовочный файл
fid = fopen(hPath, 'w', 'n', 'UTF-8');
if fid == -1
error('Не удалось открыть файл для записи');
@@ -38,7 +53,10 @@ classdef mcuPorts
fwrite(fid, code);
fclose(fid);
% Вставляем сгенерированную конфигурацию в файл реализации
code = editCode.insertSection(cCode, '// INPUT/OUTPUTS AUTO-PARAMS', cText);
% Записываем обновленный файл реализации
fid = fopen(cPath, 'w', 'n', 'UTF-8');
if fid == -1
error('Не удалось открыть файл для записи');
@@ -47,39 +65,46 @@ classdef mcuPorts
fclose(fid);
end
function [portwidth, defnames] = getMaskNames(port_prefix)
% Получение имен и ширин портов из параметров маски
% port_prefix - префикс портов ('in' или 'out')
% Возвращает ширины портов и их имена
block = gcb;
% Получаем значение из спиннера
mask = Simulink.Mask.get(block);
% Получаем количество портов из спиннера
paramName = sprintf('%sNumb', port_prefix);
param = mask.getParameter(paramName);
numb = str2double(param.Value);
% Инициализируем массив для значений
% Инициализируем массивы для имен и ширин портов
defnames = strings(1, numb);
portwidth = [];
% Чтение значений edit-параметров
% Читаем значения параметров для каждого порта
for i = 1:numb
% Получаем имя порта
paramName = sprintf('%s_port_%d_name', port_prefix, i);
param = mask.getParameter(paramName);
defnames(i) = param.Value;
% Получаем ширину порта
paramName = sprintf('%s_port_%d_width', port_prefix, i);
param = mask.getParameter(paramName);
portwidth(i) = str2double(param.Value);
end
end
function updateMask()
% Обновление видимости параметров портов в маске
% Вызывается при изменении количества портов
mcuPorts.updateMask_prefix('in');
mcuPorts.updateMask_prefix('out');
end
function defaultUnused()
% Установка значений по умолчанию для неиспользуемых портов
mcuPorts.defaultUnused_prefix('in');
mcuPorts.defaultUnused_prefix('out');
end
@@ -87,84 +112,93 @@ classdef mcuPorts
methods(Static, Access=private)
function updateMask_prefix(port_prefix)
% Обновление видимости параметров для конкретного типа портов
% port_prefix - префикс портов ('in' или 'out')
block = gcb;
% Получаем значение из спиннера
mask = Simulink.Mask.get(block);
% Получаем текущее количество портов
paramName = sprintf('%sNumb', port_prefix);
param = mask.getParameter(paramName);
n = str2double(param.Value);
% Максимальное количество портов
% Максимальное количество портов из диапазона параметра
maxPorts = param.Range(2);
% Проходим по всем edit-полям
% Обходим все возможные порты
for i = 1:maxPorts
% Формируем имя параметра
% Формируем имена параметров для имени и ширины порта
paramDefName = sprintf('%s_port_%d_name', port_prefix, i);
paramWidthName = sprintf('%s_port_%d_width', port_prefix, i);
paramDef = mask.getParameter(paramDefName);
paramWidth = mask.getParameter(paramWidthName);
if i <= n
% Показываем параметр
% Показываем параметры для используемых портов
paramDef.Visible = 'on';
paramWidth.Visible = 'on';
% Если значение пустое — задаём дефолтное
% Устанавливаем значения по умолчанию если пустые
if isempty(strtrim(paramDef.Value))
paramDef.Value = upper(port_prefix);
end
% Если значение пустое — задаём дефолтное
if isempty(strtrim(paramWidth.Value)) || strcmp(paramWidth.Value, '0')
paramWidth.Value = '16';
end
else
% Скрываем параметр
% Скрываем параметры для неиспользуемых портов
paramDef.Visible = 'off';
paramWidth.Visible = 'off';
end
end
end
function defaultUnused_prefix(port_prefix)
% Установка значений по умолчанию для неиспользуемых портов
% port_prefix - префикс портов ('in' или 'out')
block = gcb;
% Получаем значение из спиннера
mask = Simulink.Mask.get(block);
% Получаем количество используемых портов
paramName = sprintf('%sNumb', port_prefix);
param = mask.getParameter(paramName);
numb = str2double(param.Value);
% Максимальное количество портов
maxPorts = param.Range(2);
% Чтение значений edit-параметров
% Устанавливаем значения по умолчанию для неиспользуемых портов
for i = numb+1:maxPorts
paramName = sprintf('%s_port_%d_name', port_prefix, i);
param = mask.getParameter(paramName);
param.Value = upper(port_prefix);
param.Value = upper(port_prefix); % Имя по умолчанию
paramName = sprintf('%s_port_%d_width', port_prefix, i);
param = mask.getParameter(paramName);
param.Value = '16';
param.Value = '16'; % Ширина по умолчанию
end
end
function headerText = addPortHeaderDefines(existingText, widths, prefixNumb, portPrefixes)
% existingText — структура с полями PARAMS, AUTO_PARAMS
% widths — вектор ширин портов
% prefixNumb — префикс общего счётчика (например, 'OUT')
% portPrefixes — {'OUT', 'OUT', ...}
% Генерация define-макросов для заголовочного файла
% existingText - существующий текст конфигурации
% widths - вектор ширин портов
% prefixNumb - общий префикс ('IN' или 'OUT')
% portPrefixes - массив префиксов для каждого порта
% Возвращает структуру с PARAMS и AUTO_PARAMS
n = numel(widths);
upperPrefix = upper(prefixNumb);
% === PARAMS ===
% === БАЗОВЫЕ ПАРАМЕТРЫ ===
lines = {
sprintf('#define %s_PORT_NUMB %d', upperPrefix, n)
};
% Добавляем define для ширины каждого порта
for i = 1:n
lines{end+1} = sprintf('#define %s_PORT_%d_WIDTH %d', ...
upper(portPrefixes{i}), i, widths(i));
@@ -172,10 +206,10 @@ classdef mcuPorts
newParams = strjoin(lines, newline);
newParams = [newParams, newline];
% === AUTO-PARAMS ===
% === АВТОМАТИЧЕСКИ ГЕНЕРИРУЕМЫЕ ПАРАМЕТРЫ ===
lines = {};
% Формируем выражение суммы ширин с добавлением PORT
% Формируем выражение для общего размера буфера
sumExprParts = cell(1,n);
for i = 1:n
sumExprParts{i} = sprintf('%s_PORT_%d_WIDTH', upper(portPrefixes{i}), i);
@@ -188,6 +222,7 @@ classdef mcuPorts
lines{end+1} = '';
lines{end+1} = sprintf('/// === Смещения массивов (внутри общего буфера) ===');
% Генерируем define для смещений каждого массива в буфере
for i = 1:n
if i == 1
lines{end+1} = sprintf('#define OFFSET_%s_ARRAY_1 0', upperPrefix);
@@ -198,7 +233,7 @@ classdef mcuPorts
end
newAuto = strjoin(lines, newline);
% === Добавление к существующему ===
% === ОБЪЕДИНЕНИЕ С СУЩЕСТВУЮЩИМ ТЕКСТОМ ===
if isfield(existingText, 'PARAMS')
headerText.PARAMS = [existingText.PARAMS, newline, newParams];
else
@@ -212,40 +247,43 @@ classdef mcuPorts
end
end
function cText = addPortCDefines(existingText, widths, prefixNumb, portPrefixes)
% existingText — существующий текст .c
% widths — вектор ширин портов
% prefixNumb — общий префикс ('OUT')
% portPrefixes — {'OUT', 'LOG', ...}
% Генерация кода для файла реализации (.c)
% existingText - существующий текст
% widths - вектор ширин портов
% prefixNumb - общий префикс ('IN' или 'OUT')
% portPrefixes - массив префиксов для каждого порта
% Возвращает текст для вставки в .c файл
n = numel(widths);
upperPrefix = upper(prefixNumb);
lowerPrefix = lower(prefixNumb);
lines = {};
% === Таблица длин ===
% === ТАБЛИЦА ДЛИН МАССИВОВ ===
lines{end+1} = '/**';
lines{end+1} = sprintf(' * @brief Таблица длин массивов %s', upperPrefix);
lines{end+1} = ' */';
% Здесь используем общий префикс для количества портов
lines{end+1} = sprintf('const int %sLengths[%s_PORT_NUMB] = {', lowerPrefix, upperPrefix);
% Заполняем таблицу длин
for i = 1:n
comma = ',';
if i == n
comma = '';
end
% Используем макросы с портовыми префиксами из portPrefixes
lines{end+1} = sprintf(' %s_PORT_%d_WIDTH%s', upper(portPrefixes{i}), i, comma);
end
lines{end+1} = '};';
% === Таблица смещений ===
% === ТАБЛИЦА СМЕЩЕНИЙ ===
lines{end+1} = '/**';
lines{end+1} = sprintf(' * @brief Таблица смещений в выходном массиве %s', upperPrefix);
lines{end+1} = ' */';
lines{end+1} = sprintf('const int %sOffsets[%s_PORT_NUMB] = {', lowerPrefix, upperPrefix);
% Заполняем таблицу смещений
for i = 1:n
comma = ',';
if i == n
@@ -258,6 +296,7 @@ classdef mcuPorts
newText = strjoin(lines, newline);
% Объединяем с существующим текстом
if nargin < 1 || isempty(existingText)
cText = newText;
else
@@ -265,20 +304,14 @@ classdef mcuPorts
end
end
function val = iff(cond, a, b)
% Условное выражение inline
% Вспомогательная функция - тернарный оператор
% cond - условие, a - значение если true, b - значение если false
if cond
val = a;
else
val = b;
end
end
end
end