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

284 lines
11 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 mcuPorts
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('Не удалось открыть файл для записи');
end
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('Не удалось открыть файл для записи');
end
fwrite(fid, code);
fclose(fid);
end
function [portwidth, defnames] = getMaskNames(port_prefix)
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
end
methods(Static, Access=private)
function updateMask_prefix(port_prefix)
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)
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);
paramName = sprintf('%s_port_%d_width', port_prefix, i);
param = mask.getParameter(paramName);
param.Value = '16';
end
end
function headerText = addPortHeaderDefines(existingText, widths, prefixNumb, portPrefixes)
% existingText — структура с полями PARAMS, AUTO_PARAMS
% widths — вектор ширин портов
% prefixNumb — префикс общего счётчика (например, 'OUT')
% portPrefixes — {'OUT', 'OUT', ...}
n = numel(widths);
upperPrefix = upper(prefixNumb);
% === PARAMS ===
lines = {
sprintf('#define %s_PORT_NUMB %d', upperPrefix, n)
};
for i = 1:n
lines{end+1} = sprintf('#define %s_PORT_%d_WIDTH %d', ...
upper(portPrefixes{i}), i, widths(i));
end
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);
end
sumExpr = strjoin(sumExprParts, ' + ');
lines{end+1} = sprintf('/// === Полный размер буфера ===');
lines{end+1} = sprintf('#define TOTAL_%s_SIZE (%s)', upperPrefix, sumExpr);
lines{end+1} = '';
lines{end+1} = sprintf('/// === Смещения массивов (внутри общего буфера) ===');
for i = 1:n
if i == 1
lines{end+1} = sprintf('#define OFFSET_%s_ARRAY_1 0', upperPrefix);
else
lines{end+1} = sprintf('#define OFFSET_%s_ARRAY_%d (OFFSET_%s_ARRAY_%d + %s_PORT_%d_WIDTH)', ...
upperPrefix, i, upperPrefix, i - 1, upper(portPrefixes{i - 1}), i - 1);
end
end
newAuto = strjoin(lines, newline);
% === Добавление к существующему ===
if isfield(existingText, 'PARAMS')
headerText.PARAMS = [existingText.PARAMS, newline, newParams];
else
headerText.PARAMS = newParams;
end
if isfield(existingText, 'AUTO_PARAMS')
headerText.AUTO_PARAMS = [existingText.AUTO_PARAMS, newline, newAuto, newline];
else
headerText.AUTO_PARAMS = [newAuto, newline];
end
end
function cText = addPortCDefines(existingText, widths, prefixNumb, portPrefixes)
% existingText — существующий текст .c
% widths — вектор ширин портов
% prefixNumb — общий префикс ('OUT')
% portPrefixes — {'OUT', 'LOG', ...}
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
comma = '';
end
lines{end+1} = sprintf(' OFFSET_%s_ARRAY_%d%s', upperPrefix, i, comma);
end
lines{end+1} = '};';
lines{end+1} = '';
newText = strjoin(lines, newline);
if nargin < 1 || isempty(existingText)
cText = newText;
else
cText = [existingText, newline, newText];
end
end
function val = iff(cond, a, b)
% Условное выражение inline
if cond
val = a;
else
val = b;
end
end
end
end