добавлен экспорт и импорт настроек оболочки и приложения МК
работа с конфигом (чтение запись) перенесена в отдельный файл добавлена возможность через popup сделать define = чему-то
This commit is contained in:
parent
e77a659710
commit
5648875cd2
Binary file not shown.
Binary file not shown.
@ -75,14 +75,14 @@ classdef appWrap
|
|||||||
errordlg('Файл не найден');
|
errordlg('Файл не найден');
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
%% SPECIFIC TOOLS
|
%% SPECIFIC TOOLS
|
||||||
methods(Static, Access = private)
|
function [filename, section, tool, example] = getAppWrapperUserFile(block, sel)
|
||||||
|
if (nargin < 2)
|
||||||
function [filename, section, tool, example] = getAppWrapperUserFile(block)
|
|
||||||
sel = get_param(block, 'appWrapperFunc');
|
sel = get_param(block, 'appWrapperFunc');
|
||||||
|
end
|
||||||
|
|
||||||
basePath = mcuPath.get('appWrapperPath');
|
basePath = mcuPath.get('appWrapperPath');
|
||||||
if isempty(basePath)
|
if isempty(basePath)
|
||||||
errordlg('Не указан путь к файлам обёртки (wrapperPath).');
|
errordlg('Не указан путь к файлам обёртки (wrapperPath).');
|
||||||
@ -150,7 +150,5 @@ classdef appWrap
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
143
McuLib/m/configJs.m
Normal file
143
McuLib/m/configJs.m
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
classdef configJs
|
||||||
|
|
||||||
|
methods(Static)
|
||||||
|
|
||||||
|
function config = update(blockPath, config)
|
||||||
|
if isempty(config)
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
maskParams = mask.Parameters;
|
||||||
|
paramNames = arrayfun(@(p) p.Name, maskParams, 'UniformOutput', false);
|
||||||
|
|
||||||
|
% Обработка остальных секций (с дефайнами)
|
||||||
|
periphs = fieldnames(config);
|
||||||
|
for i = 1:numel(periphs)
|
||||||
|
periph = periphs{i};
|
||||||
|
|
||||||
|
% Проверяем есть ли Defines
|
||||||
|
if ~isfield(config.(periph), 'Defines')
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
defines = config.(periph).Defines;
|
||||||
|
defNames = fieldnames(defines);
|
||||||
|
|
||||||
|
for j = 1:numel(defNames)
|
||||||
|
defPrompt = defNames{j};
|
||||||
|
paramName = matlab.lang.makeValidName(defPrompt);
|
||||||
|
|
||||||
|
% Проверка, существует ли параметр с таким именем
|
||||||
|
if ismember(paramName, paramNames)
|
||||||
|
param = mask.getParameter(paramName);
|
||||||
|
valStr = param.Value;
|
||||||
|
|
||||||
|
% Проверяем, существует ли элемент defPrompt в структуре defines
|
||||||
|
if isfield(defines, defPrompt)
|
||||||
|
% Преобразуем строку в соответствующий тип
|
||||||
|
if strcmpi(defines.(defPrompt).Type, 'checkbox')
|
||||||
|
config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
|
||||||
|
elseif strcmpi(defines.(defPrompt).Type, 'edit')
|
||||||
|
valNum = str2double(valStr);
|
||||||
|
if isnan(valNum)
|
||||||
|
config.(periph).Defines.(defPrompt).Default = valStr;
|
||||||
|
else
|
||||||
|
config.(periph).Defines.(defPrompt).Default = valNum;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function config = read(blockPath)
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
|
||||||
|
pathparam = mask.getParameter('periphPath');
|
||||||
|
config_path = pathparam.Value;
|
||||||
|
|
||||||
|
if ~isempty(config_path)
|
||||||
|
jsonText = fileread(config_path);
|
||||||
|
config = jsondecode(jsonText);
|
||||||
|
else
|
||||||
|
config = [];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function write(config)
|
||||||
|
if isempty(config)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
blockHandle = gcbh;
|
||||||
|
mask = Simulink.Mask.get(blockHandle);
|
||||||
|
|
||||||
|
pathparam = mask.getParameter('periphPath');
|
||||||
|
config_path = pathparam.Value;
|
||||||
|
|
||||||
|
jsonText = jsonencode(config, 'PrettyPrint', true);
|
||||||
|
fid = fopen(config_path, 'w', 'n', 'UTF-8');
|
||||||
|
if fid == -1
|
||||||
|
error('Не удалось открыть файл periph_config.json для записи.');
|
||||||
|
end
|
||||||
|
fwrite(fid, jsonText, 'char');
|
||||||
|
fclose(fid);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function value = get_field(configStruct, targetConfig)
|
||||||
|
% получить targetConfig структуру из конфига (для глубоко вложенных)
|
||||||
|
value = [];
|
||||||
|
fields = fieldnames(configStruct);
|
||||||
|
|
||||||
|
for i = 1:numel(fields)
|
||||||
|
key = fields{i};
|
||||||
|
if strcmp(key, targetConfig)
|
||||||
|
value = configStruct.(key);
|
||||||
|
return; % нашли и возвращаем
|
||||||
|
elseif isstruct(configStruct.(key))
|
||||||
|
value = configJs.get_field(configStruct.(key), targetConfig);
|
||||||
|
if ~isempty(value)
|
||||||
|
return; % нашли во вложенной структуре
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Если не нашли, можно выбросить ошибку или вернуть пустое
|
||||||
|
if isempty(value)
|
||||||
|
% error('Поле "%s" не найдено в структуре.', targetConfig);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function short = get_final_name_from_prefix(prefix)
|
||||||
|
% Берёт последнее имя после "_" (читаемое имя)
|
||||||
|
parts = strsplit(prefix, '_');
|
||||||
|
short = parts{end};
|
||||||
|
end
|
||||||
|
|
||||||
|
function value = convert_code_value(codeField)
|
||||||
|
% Преобразует значение поля Options в строку
|
||||||
|
if ischar(codeField)
|
||||||
|
value = codeField;
|
||||||
|
elseif isstring(codeField)
|
||||||
|
value = char(codeField);
|
||||||
|
elseif iscell(codeField)
|
||||||
|
value = strjoin(codeField, newline);
|
||||||
|
else
|
||||||
|
% warning('Неподдерживаемый тип данных: сохранено как пустая строка');
|
||||||
|
value = '';
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
methods(Static, Access=private)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
274
McuLib/m/mainConfig.m
Normal file
274
McuLib/m/mainConfig.m
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
classdef mainConfig
|
||||||
|
|
||||||
|
methods(Static)
|
||||||
|
|
||||||
|
function config = export()
|
||||||
|
blockPath = gcb;
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
wrapParamToExport = {'wrapperPath', 'enableDebug', 'mcuClk', ...
|
||||||
|
'threadCycles', 'enableThreading', 'enableDeinit'};
|
||||||
|
portParamToExport = {'inNumb', ...
|
||||||
|
'in_port_1_name', 'in_port_1_width', ...
|
||||||
|
'in_port_2_name', 'in_port_2_width', ...
|
||||||
|
'in_port_3_name', 'in_port_3_width', ...
|
||||||
|
'in_port_4_name', 'in_port_4_width', ...
|
||||||
|
'in_port_5_name', 'in_port_5_width', ...
|
||||||
|
'outNumb', ...
|
||||||
|
'out_port_1_name', 'out_port_1_width', ...
|
||||||
|
'out_port_2_name', 'out_port_2_width', ...
|
||||||
|
'out_port_3_name', 'out_port_3_width', ...
|
||||||
|
'out_port_4_name', 'out_port_4_width', ...
|
||||||
|
'out_port_5_name', 'out_port_5_width',};
|
||||||
|
appParamToExport = {'appWrapperPath', 'srcTable', 'incTable', 'userDefs'};
|
||||||
|
|
||||||
|
config = struct();
|
||||||
|
for i = 1:numel(wrapParamToExport)
|
||||||
|
paramName = wrapParamToExport{i};
|
||||||
|
def = mainConfig.exportParamToConfig(mask, paramName);
|
||||||
|
config.(paramName) = def;
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1:numel(portParamToExport)
|
||||||
|
paramName = portParamToExport{i};
|
||||||
|
def = mainConfig.exportParamToConfig(mask, paramName);
|
||||||
|
config.(paramName) = def;
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1:numel(appParamToExport)
|
||||||
|
paramName = appParamToExport{i};
|
||||||
|
def = mainConfig.exportParamToConfig(mask, paramName);
|
||||||
|
config.(paramName) = def;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
jsonStr = jsonencode(config, 'PrettyPrint', true); % 'PrettyPrint' для форматирования
|
||||||
|
|
||||||
|
|
||||||
|
% Диалог сохранения файла
|
||||||
|
[file, path] = uiputfile('*.json', 'Сохранить конфигурацию как', 'WrapperConfig.json');
|
||||||
|
if isequal(file, 0) || isequal(path, 0)
|
||||||
|
disp('Сохранение отменено пользователем.');
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
filepath = fullfile(path, file);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% Сохраняем в файл
|
||||||
|
fid = fopen(filepath, 'w');
|
||||||
|
if fid == -1
|
||||||
|
mcuMask.disp(0, 'Не удалось открыть файл для записи: %s', filename);
|
||||||
|
end
|
||||||
|
|
||||||
|
fwrite(fid, jsonStr, 'char');
|
||||||
|
fclose(fid);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function import()
|
||||||
|
% Получаем путь к текущему блоку
|
||||||
|
blockPath = gcb;
|
||||||
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
|
||||||
|
% Выбор JSON-файла через диалоговое окно
|
||||||
|
[file, path] = uigetfile('*.json', 'Выберите файл конфигурации');
|
||||||
|
if isequal(file, 0)
|
||||||
|
mcuMask.disp(0, 'Импорт отменён пользователем.');
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
fullpath = fullfile(path, file);
|
||||||
|
|
||||||
|
% Чтение и декодирование JSON
|
||||||
|
try
|
||||||
|
jsonStr = fileread(fullpath);
|
||||||
|
config = jsondecode(jsonStr);
|
||||||
|
catch err
|
||||||
|
mcuMask.disp(0, 'Ошибка при чтении или разборе JSON: %s', err.message);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Применение параметров из конфигурации
|
||||||
|
paramNames = fieldnames(config);
|
||||||
|
for i = 1:numel(paramNames)
|
||||||
|
paramName = paramNames{i};
|
||||||
|
def = config.(paramName);
|
||||||
|
|
||||||
|
try
|
||||||
|
mainConfig.applyDefToMask(mask, paramName, def);
|
||||||
|
catch err
|
||||||
|
mcuMask.disp(0, 'Ошибка при применении параметра "%s": %s', paramName, err.message);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
mcuMask.disp(0, 'Конфигурация успешно импортирована.');
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
methods(Static, Access=private)
|
||||||
|
|
||||||
|
|
||||||
|
function def = exportParamToConfig(mask, paramName)
|
||||||
|
% mask — объект Simulink.Mask.get(blockPath)
|
||||||
|
% paramName — имя параметра (как в mask.Parameters.Name)
|
||||||
|
|
||||||
|
param = mask.getParameter(paramName);
|
||||||
|
if isempty(param)
|
||||||
|
mcuMask.disp(0, 'Параметр "%s" не найден в маске.', paramName);
|
||||||
|
def = [];
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
def = struct();
|
||||||
|
|
||||||
|
% Prompt
|
||||||
|
def.Prompt = param.Prompt;
|
||||||
|
|
||||||
|
% Тип параметра
|
||||||
|
def.Type = param.Type;
|
||||||
|
|
||||||
|
% Значение по умолчанию
|
||||||
|
val = param.Value;
|
||||||
|
switch lower(param.Type)
|
||||||
|
case 'checkbox'
|
||||||
|
def.Default = strcmp(val, 'on');
|
||||||
|
case {'edit', 'spinbox'}
|
||||||
|
num = str2double(val);
|
||||||
|
if ~isnan(num)
|
||||||
|
def.Default = num;
|
||||||
|
else
|
||||||
|
def.Default = val;
|
||||||
|
end
|
||||||
|
case 'customtable'
|
||||||
|
def.Default = customtable.parse(param.Name); % или можно попытаться распарсить значение позже
|
||||||
|
case 'text'
|
||||||
|
def.Default = ''; % или можно попытаться распарсить значение позже
|
||||||
|
otherwise
|
||||||
|
def.Default = val;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Alias, если есть
|
||||||
|
if ~isempty(param.Alias)
|
||||||
|
def.Def = param.Alias;
|
||||||
|
end
|
||||||
|
|
||||||
|
% % Row (new/current)
|
||||||
|
% try
|
||||||
|
% rowSetting = param.DialogControl.Row;
|
||||||
|
% def.NewRow = strcmp(rowSetting, 'new');
|
||||||
|
% catch
|
||||||
|
% def.NewRow = false;
|
||||||
|
% end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function applyDefToMask(mask, paramName, def)
|
||||||
|
% mask — объект Simulink.Mask.get(blockPath)
|
||||||
|
% paramName — имя параметра маски
|
||||||
|
% def — структура, полученная из extractDefFromMask
|
||||||
|
|
||||||
|
% Получаем параметр
|
||||||
|
param = mask.getParameter(paramName);
|
||||||
|
if isempty(param)
|
||||||
|
mcuMask.disp(0, 'Параметр "%s" не найден в маске.', paramName);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
if isempty(def)
|
||||||
|
mcuMask.disp(0, 'Параметр "%s" не найден в конфиге.', paramName);
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
switch lower(def.Type)
|
||||||
|
case 'checkbox'
|
||||||
|
% Логическое значение true/false
|
||||||
|
if islogical(def.Default)
|
||||||
|
param.Value = mainConfig.ternary(def.Default, 'on', 'off');
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'Ожидалось логическое значение для checkbox "%s".', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
case {'edit', 'spinbox'}
|
||||||
|
% Строка или число
|
||||||
|
if isnumeric(def.Default)
|
||||||
|
param.Value = num2str(def.Default);
|
||||||
|
elseif ischar(def.Default) || isstring(def.Default)
|
||||||
|
param.Value = char(def.Default);
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'Некорректный формат значения для edit "%s".', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
case 'customtable'
|
||||||
|
% Массив строк
|
||||||
|
if iscell(def.Default)
|
||||||
|
customtable.collect(paramName, def.Default);
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'customtable "%s" требует cell-массив строк.', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
case 'text'
|
||||||
|
% Просто текстовая строка
|
||||||
|
if ischar(def.Default) || isstring(def.Default)
|
||||||
|
param.Value = char(def.Default);
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'text-параметр "%s" должен быть строкой.', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
case 'popup'
|
||||||
|
% popup — установить значение, если оно есть в списке
|
||||||
|
if ischar(def.Default) && isfield(def, 'Def') && any(strcmp(def.Default, def.Def))
|
||||||
|
param.Value = def.Default;
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'popup-параметр "%s" имеет неверное значение или список.', paramName);
|
||||||
|
end
|
||||||
|
|
||||||
|
otherwise
|
||||||
|
% По умолчанию просто устанавливаем строковое значение
|
||||||
|
if ischar(def.Default) || isstring(def.Default)
|
||||||
|
param.Value = char(def.Default);
|
||||||
|
elseif isnumeric(def.Default)
|
||||||
|
param.Value = num2str(def.Default);
|
||||||
|
else
|
||||||
|
mcuMask.disp(0, 'Неизвестный формат значения параметра "%s".', paramName);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Применение Prompt, если нужно
|
||||||
|
if isfield(def, 'Prompt')
|
||||||
|
param.Prompt = def.Prompt;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Применение Alias, если есть
|
||||||
|
if isfield(def, 'Def') && ischar(def.Def)
|
||||||
|
param.Alias = def.Def;
|
||||||
|
end
|
||||||
|
|
||||||
|
% % Установка Row, если поддерживается
|
||||||
|
% if isfield(def, 'NewRow')
|
||||||
|
% try
|
||||||
|
% if def.NewRow
|
||||||
|
% param.DialogControl.Row = 'new';
|
||||||
|
% else
|
||||||
|
% param.DialogControl.Row = 'current';
|
||||||
|
% end
|
||||||
|
% catch
|
||||||
|
% % Некоторым типам параметров Row может быть неприменим
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function result = ternary(cond, a, b)
|
||||||
|
if cond
|
||||||
|
result = a;
|
||||||
|
else
|
||||||
|
result = b;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -66,9 +66,9 @@ function res = mexing(compile_mode)
|
|||||||
beep
|
beep
|
||||||
else
|
else
|
||||||
blockPath = gcb;
|
blockPath = gcb;
|
||||||
config = periphConfig.read_config(blockPath);
|
config = configJs.read(blockPath);
|
||||||
config = periphConfig.update_config(blockPath, config);
|
config = configJs.update(blockPath, config);
|
||||||
periphConfig.write_config(config);
|
configJs.write(config);
|
||||||
periphConfig.updateMask(blockPath, config);
|
periphConfig.updateMask(blockPath, config);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -232,10 +232,16 @@ function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_
|
|||||||
end
|
end
|
||||||
|
|
||||||
% Берём alias из маски
|
% Берём alias из маски
|
||||||
|
val = '';
|
||||||
if ~strcmp(param.Type, 'popup')
|
if ~strcmp(param.Type, 'popup')
|
||||||
def_name = param.Alias;
|
def_name = param.Alias;
|
||||||
else
|
else
|
||||||
|
if strcmp(param.Alias, '')
|
||||||
def_name = param.Value;
|
def_name = param.Value;
|
||||||
|
else
|
||||||
|
def_name = param.Alias;
|
||||||
|
val = param.Value;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if strcmp(def_name, '')
|
if strcmp(def_name, '')
|
||||||
@ -259,7 +265,7 @@ function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_
|
|||||||
newDefine = '';
|
newDefine = '';
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
newDefine = ['-D"' def_name '"'];
|
newDefine = ['-D"' def_name '__EQ__' val '"'];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ classdef periphConfig
|
|||||||
blockPath = gcb;
|
blockPath = gcb;
|
||||||
mask = Simulink.Mask.get(blockPath);
|
mask = Simulink.Mask.get(blockPath);
|
||||||
|
|
||||||
config = periphConfig.read_config(blockPath);
|
config = configJs.read(blockPath);
|
||||||
containerName = 'configTabAll';
|
containerName = 'configTabAll';
|
||||||
container = mask.getDialogControl(containerName);
|
container = mask.getDialogControl(containerName);
|
||||||
paramsAll = mcuMask.collect_all_parameters(container);
|
paramsAll = mcuMask.collect_all_parameters(container);
|
||||||
@ -130,7 +130,7 @@ classdef periphConfig
|
|||||||
blockPath = gcb;
|
blockPath = gcb;
|
||||||
mask = Simulink.Mask.get(blockPath);
|
mask = Simulink.Mask.get(blockPath);
|
||||||
hObj = mask.getParameter(paramName);
|
hObj = mask.getParameter(paramName);
|
||||||
config = periphConfig.read_config(blockPath);
|
config = configJs.read(blockPath);
|
||||||
container = mask.getDialogControl('configTabAll');
|
container = mask.getDialogControl('configTabAll');
|
||||||
|
|
||||||
% === Проверка на Tab_<Periph>_Enable ===
|
% === Проверка на Tab_<Periph>_Enable ===
|
||||||
@ -175,7 +175,7 @@ classdef periphConfig
|
|||||||
|
|
||||||
% Получаем содержимое config по nameBase — возможно, вложенное
|
% Получаем содержимое config по nameBase — возможно, вложенное
|
||||||
try
|
try
|
||||||
valueStruct = periphConfig.get_field(config, nameBase);
|
valueStruct = configJs.get_field(config, nameBase);
|
||||||
catch
|
catch
|
||||||
warning('Не удалось найти путь %s в config.', nameBase);
|
warning('Не удалось найти путь %s в config.', nameBase);
|
||||||
return;
|
return;
|
||||||
@ -209,97 +209,6 @@ classdef periphConfig
|
|||||||
periphConfig.addCodeBat(CodeStruct, periphPath);
|
periphConfig.addCodeBat(CodeStruct, periphPath);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function config = update_config(blockPath, config)
|
|
||||||
if isempty(config)
|
|
||||||
return;
|
|
||||||
end
|
|
||||||
|
|
||||||
mask = Simulink.Mask.get(blockPath);
|
|
||||||
maskParams = mask.Parameters;
|
|
||||||
paramNames = arrayfun(@(p) p.Name, maskParams, 'UniformOutput', false);
|
|
||||||
|
|
||||||
% Обработка остальных секций (с дефайнами)
|
|
||||||
periphs = fieldnames(config);
|
|
||||||
for i = 1:numel(periphs)
|
|
||||||
periph = periphs{i};
|
|
||||||
|
|
||||||
% Пропускаем Code и UserCode
|
|
||||||
if strcmp(periph, 'Code') || strcmp(periph, 'UserCode')
|
|
||||||
continue;
|
|
||||||
end
|
|
||||||
|
|
||||||
% Проверяем есть ли Defines
|
|
||||||
if ~isfield(config.(periph), 'Defines')
|
|
||||||
continue;
|
|
||||||
end
|
|
||||||
|
|
||||||
defines = config.(periph).Defines;
|
|
||||||
defNames = fieldnames(defines);
|
|
||||||
|
|
||||||
for j = 1:numel(defNames)
|
|
||||||
defPrompt = defNames{j};
|
|
||||||
paramName = matlab.lang.makeValidName(defPrompt);
|
|
||||||
|
|
||||||
% Проверка, существует ли параметр с таким именем
|
|
||||||
if ismember(paramName, paramNames)
|
|
||||||
param = mask.getParameter(paramName);
|
|
||||||
valStr = param.Value;
|
|
||||||
|
|
||||||
% Проверяем, существует ли элемент defPrompt в структуре defines
|
|
||||||
if isfield(defines, defPrompt)
|
|
||||||
% Преобразуем строку в соответствующий тип
|
|
||||||
if strcmpi(defines.(defPrompt).Type, 'checkbox')
|
|
||||||
config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
|
|
||||||
elseif strcmpi(defines.(defPrompt).Type, 'edit')
|
|
||||||
valNum = str2double(valStr);
|
|
||||||
if isnan(valNum)
|
|
||||||
config.(periph).Defines.(defPrompt).Default = valStr;
|
|
||||||
else
|
|
||||||
config.(periph).Defines.(defPrompt).Default = valNum;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function config = read_config(blockPath)
|
|
||||||
mask = Simulink.Mask.get(blockPath);
|
|
||||||
|
|
||||||
pathparam = mask.getParameter('periphPath');
|
|
||||||
config_path = pathparam.Value;
|
|
||||||
|
|
||||||
if ~isempty(config_path)
|
|
||||||
jsonText = fileread(config_path);
|
|
||||||
config = jsondecode(jsonText);
|
|
||||||
else
|
|
||||||
config = [];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function write_config(config)
|
|
||||||
if isempty(config)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
blockHandle = gcbh;
|
|
||||||
mask = Simulink.Mask.get(blockHandle);
|
|
||||||
|
|
||||||
pathparam = mask.getParameter('periphPath');
|
|
||||||
config_path = pathparam.Value;
|
|
||||||
|
|
||||||
jsonText = jsonencode(config, 'PrettyPrint', true);
|
|
||||||
fid = fopen(config_path, 'w', 'n', 'UTF-8');
|
|
||||||
if fid == -1
|
|
||||||
error('Не удалось открыть файл periph_config.json для записи.');
|
|
||||||
end
|
|
||||||
fwrite(fid, jsonText, 'char');
|
|
||||||
fclose(fid);
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -347,7 +256,7 @@ classdef periphConfig
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
||||||
baseName = periphConfig.get_final_name_from_prefix(prefix);
|
baseName = configJs.get_final_name_from_prefix(prefix);
|
||||||
periphConfig.clear_single_periph_code_param(mask, baseName);
|
periphConfig.clear_single_periph_code_param(mask, baseName);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -375,7 +284,7 @@ classdef periphConfig
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
if strcmp(key, 'Sources') || strcmp(key, 'Includes')
|
||||||
baseName = periphConfig.get_final_name_from_prefix(prefix);
|
baseName = configJs.get_final_name_from_prefix(prefix);
|
||||||
periphConfig.store_single_periph_code(mask, baseName, configStruct);
|
periphConfig.store_single_periph_code(mask, baseName, configStruct);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -535,10 +444,6 @@ classdef periphConfig
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function res = addCodeBat(codeConfig, codePath)
|
function res = addCodeBat(codeConfig, codePath)
|
||||||
% Добавить сурсы и пути в батник
|
% Добавить сурсы и пути в батник
|
||||||
% Возвращает 0 при успехе, 1 при ошибке
|
% Возвращает 0 при успехе, 1 при ошибке
|
||||||
@ -668,6 +573,9 @@ classdef periphConfig
|
|||||||
if isfield(def, 'Def') && iscell(def.Def) && ~isempty(def.Def)
|
if isfield(def, 'Def') && iscell(def.Def) && ~isempty(def.Def)
|
||||||
choices = def.Def;
|
choices = def.Def;
|
||||||
valStr = ''; % по умолчанию — ничего
|
valStr = ''; % по умолчанию — ничего
|
||||||
|
elseif isfield(def, 'Options')
|
||||||
|
choices = def.Def;
|
||||||
|
valStr = ''; % по умолчанию — ничего
|
||||||
else
|
else
|
||||||
warning('Popout параметр "%s" не содержит допустимого списка в Def.', defPrompt);
|
warning('Popout параметр "%s" не содержит допустимого списка в Def.', defPrompt);
|
||||||
return;
|
return;
|
||||||
@ -713,7 +621,12 @@ classdef periphConfig
|
|||||||
|
|
||||||
if isfield(def, 'Def')
|
if isfield(def, 'Def')
|
||||||
if strcmp(paramType, 'popup')
|
if strcmp(paramType, 'popup')
|
||||||
|
if iscell(def.Def)
|
||||||
param.TypeOptions = def.Def;
|
param.TypeOptions = def.Def;
|
||||||
|
elseif isfield(def, 'Options')
|
||||||
|
param.Alias = def.Def;
|
||||||
|
param.TypeOptions = def.Options;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
param.Alias = def.Def;
|
param.Alias = def.Def;
|
||||||
end
|
end
|
||||||
@ -752,7 +665,7 @@ classdef periphConfig
|
|||||||
paramName = ['Hidden_' char(periph) '_Sources'];
|
paramName = ['Hidden_' char(periph) '_Sources'];
|
||||||
try
|
try
|
||||||
param = mask.getParameter(paramName);
|
param = mask.getParameter(paramName);
|
||||||
param.Value = periphConfig.convert_code_value(code.Sources);
|
param.Value = configJs.convert_code_value(code.Sources);
|
||||||
catch
|
catch
|
||||||
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
|
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
|
||||||
end
|
end
|
||||||
@ -763,56 +676,14 @@ classdef periphConfig
|
|||||||
paramName = ['Hidden_' char(periph) '_Includes'];
|
paramName = ['Hidden_' char(periph) '_Includes'];
|
||||||
try
|
try
|
||||||
param = mask.getParameter(paramName);
|
param = mask.getParameter(paramName);
|
||||||
param.Value = periphConfig.convert_code_value(code.Includes);
|
param.Value = configJs.convert_code_value(code.Includes);
|
||||||
catch
|
catch
|
||||||
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
|
mcuMask.disp(0, ['Параметр ' paramName ' не найден']);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function value = get_field(configStruct, targetConfig)
|
|
||||||
% получить targetConfig структуру из конфига (для глубоко вложенных)
|
|
||||||
value = [];
|
|
||||||
fields = fieldnames(configStruct);
|
|
||||||
|
|
||||||
for i = 1:numel(fields)
|
|
||||||
key = fields{i};
|
|
||||||
if strcmp(key, targetConfig)
|
|
||||||
value = configStruct.(key);
|
|
||||||
return; % нашли и возвращаем
|
|
||||||
elseif isstruct(configStruct.(key))
|
|
||||||
value = periphConfig.get_field(configStruct.(key), targetConfig);
|
|
||||||
if ~isempty(value)
|
|
||||||
return; % нашли во вложенной структуре
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
% Если не нашли, можно выбросить ошибку или вернуть пустое
|
|
||||||
if isempty(value)
|
|
||||||
% error('Поле "%s" не найдено в структуре.', targetConfig);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function short = get_final_name_from_prefix(prefix)
|
|
||||||
% Берёт последнее имя после "_" (читаемое имя)
|
|
||||||
parts = strsplit(prefix, '_');
|
|
||||||
short = parts{end};
|
|
||||||
end
|
|
||||||
|
|
||||||
function value = convert_code_value(codeField)
|
|
||||||
% Преобразует значение поля Options в строку
|
|
||||||
if ischar(codeField)
|
|
||||||
value = codeField;
|
|
||||||
elseif isstring(codeField)
|
|
||||||
value = char(codeField);
|
|
||||||
elseif iscell(codeField)
|
|
||||||
value = strjoin(codeField, newline);
|
|
||||||
else
|
|
||||||
% warning('Неподдерживаемый тип данных: сохранено как пустая строка');
|
|
||||||
value = '';
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function res = ternary(cond, valTrue, valFalse)
|
function res = ternary(cond, valTrue, valFalse)
|
||||||
if cond
|
if cond
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<deployment-project plugin="plugin.toolbox" plugin-version="1.0">
|
<deployment-project plugin="plugin.toolbox" plugin-version="1.0">
|
||||||
<configuration build-checksum="2658716694" file="E:\.WORK\MATLAB\mcu_matlab\mcuwrapper.prj" location="E:\.WORK\MATLAB\mcu_matlab" name="mcuwrapper" target="target.toolbox" target-name="Package Toolbox">
|
<configuration build-checksum="2658716694" file="F:\Work\Projects\MATLAB\mcu_matlab_lib\mcuwrapper.prj" location="F:\Work\Projects\MATLAB\mcu_matlab_lib" name="mcuwrapper" target="target.toolbox" target-name="Package Toolbox">
|
||||||
<param.appname>MCU Wrapper</param.appname>
|
<param.appname>MCU Wrapper</param.appname>
|
||||||
<param.authnamewatermark>Razvalyaev</param.authnamewatermark>
|
<param.authnamewatermark>Razvalyaev</param.authnamewatermark>
|
||||||
<param.email>wot890089@mail.ru</param.email>
|
<param.email>wot890089@mail.ru</param.email>
|
||||||
@ -27,7 +27,7 @@
|
|||||||
<param.exported.on.package>false</param.exported.on.package>
|
<param.exported.on.package>false</param.exported.on.package>
|
||||||
<param.required.addons>
|
<param.required.addons>
|
||||||
<requiredaddons>
|
<requiredaddons>
|
||||||
<requiredAddOn earliest="earliest" fromRepository="true" id="e5534541-4a80-11e4-9553-005056977bd0" include="true" latest="latest">findjobj - find java handles of Matlab graphic objects</requiredAddOn>
|
<requiredAddOn earliest="earliest" fromRepository="true" id="e5534541-4a80-11e4-9553-005056977bd0" include="false" latest="latest">findjobj - find java handles of Matlab graphic objects</requiredAddOn>
|
||||||
</requiredaddons>
|
</requiredaddons>
|
||||||
</param.required.addons>
|
</param.required.addons>
|
||||||
<param.matlab.project.id />
|
<param.matlab.project.id />
|
||||||
@ -96,12 +96,49 @@
|
|||||||
<fileset.depfun.excluded />
|
<fileset.depfun.excluded />
|
||||||
<fileset.package />
|
<fileset.package />
|
||||||
<build-deliverables>
|
<build-deliverables>
|
||||||
<file location="${PROJECT_ROOT}" name="MCU Wrapper.mltbx" optional="false">E:\.WORK\MATLAB\mcu_matlab\MCU Wrapper.mltbx</file>
|
<file location="${PROJECT_ROOT}" name="MCU Wrapper.mltbx" optional="false">F:\Work\Projects\MATLAB\mcu_matlab_lib\MCU Wrapper.mltbx</file>
|
||||||
</build-deliverables>
|
</build-deliverables>
|
||||||
<workflow />
|
<workflow />
|
||||||
<matlab>
|
<matlab>
|
||||||
<root>C:\Program Files\MyProgs\MATLAB\R2023a</root>
|
<root>C:\Program Files\MATLAB\R2023a</root>
|
||||||
<toolboxes />
|
<toolboxes>
|
||||||
|
<toolbox name="matlabcoder" />
|
||||||
|
<toolbox name="embeddedcoder" />
|
||||||
|
<toolbox name="gpucoder" />
|
||||||
|
<toolbox name="fixedpoint" />
|
||||||
|
<toolbox name="matlabhdlcoder" />
|
||||||
|
<toolbox name="neuralnetwork" />
|
||||||
|
</toolboxes>
|
||||||
|
<toolbox>
|
||||||
|
<matlabcoder>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</matlabcoder>
|
||||||
|
</toolbox>
|
||||||
|
<toolbox>
|
||||||
|
<embeddedcoder>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</embeddedcoder>
|
||||||
|
</toolbox>
|
||||||
|
<toolbox>
|
||||||
|
<gpucoder>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</gpucoder>
|
||||||
|
</toolbox>
|
||||||
|
<toolbox>
|
||||||
|
<fixedpoint>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</fixedpoint>
|
||||||
|
</toolbox>
|
||||||
|
<toolbox>
|
||||||
|
<matlabhdlcoder>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</matlabhdlcoder>
|
||||||
|
</toolbox>
|
||||||
|
<toolbox>
|
||||||
|
<neuralnetwork>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</neuralnetwork>
|
||||||
|
</toolbox>
|
||||||
</matlab>
|
</matlab>
|
||||||
<platform>
|
<platform>
|
||||||
<unix>false</unix>
|
<unix>false</unix>
|
||||||
|
Loading…
Reference in New Issue
Block a user