+библиотека .c/.h переписана под универсальные дефайны intX_t uintX_t

+сделано задание размера короткого имени
+ добавлена бета поддержка stm:+
   - парс переменных из файла преокта Keil или makefile CubeIDE
   - запись в utf-8 для STM, вместо cp1251 для TMS
   - другой размер int (32 бита, вместо 16 бит) для STM
This commit is contained in:
Razvalyaev 2025-07-17 09:18:03 +03:00
parent 4de53090a1
commit ae2c90160e
7 changed files with 284 additions and 341 deletions

View File

@ -1,4 +1,4 @@
# DebugTools - Просмотр переменных через терминалку # DebugTools - Просмотр переменных по указателям
Модуль состоит из трех файлов: Модуль состоит из трех файлов:
- **debug_tools.c** - реализация считывания переменных - **debug_tools.c** - реализация считывания переменных
- **debug_tools.h** - объявление всякого для считывания переменных - **debug_tools.h** - объявление всякого для считывания переменных
@ -7,8 +7,9 @@
Этот модуль предоставляет функциональность для чтения значений переменных во встроенной системе, включая работу с IQ-форматами, защиту доступа и проверку диапазонов памяти. Этот модуль предоставляет функциональность для чтения значений переменных во встроенной системе, включая работу с IQ-форматами, защиту доступа и проверку диапазонов памяти.
Для чтения переменных можно использовать функции: Для чтения переменных можно использовать функции:
```c ```c
int Debug_ReadVar(int var_ind, long *return_long); int Debug_ReadVar(int var_ind, int32_t *return_long);
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr); int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr);
``` ```
@ -19,19 +20,19 @@ int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr);
// Определение массива с указателями на переменные для отладки // Определение массива с указателями на переменные для отладки
int DebugVar_Qnt = 5; int DebugVar_Qnt = 5;
#pragma DATA_SECTION(dbg_vars,".dbgvar_info") #pragma DATA_SECTION(dbg_vars,".dbgvar_info")
// pointer_type iq_type return_iq_type short_name // pointer_type iq_type return_iq_type short_name
DebugVar_t dbg_vars[] = {\ DebugVar_t dbg_vars[] = {\
{(char *)&freqTerm, pt_float, t_iq_none, t_iq10, "freqT" }, \ {(uint8_t *)&freqTerm, pt_float, t_iq_none, t_iq10, "freqT" }, \
{(char *)&ADC_sf[0][0], pt_int16, t_iq_none, t_iq_none, "ADC_sf00" }, \ {(uint8_t *)&ADC_sf[0][0], pt_int16, t_iq_none, t_iq_none, "ADC_sf00" }, \
{(char *)&ADC_sf[0][1], pt_int16, t_iq_none, t_iq_none, "ADC_sf01" }, \ {(uint8_t *)&ADC_sf[0][1], pt_int16, t_iq_none, t_iq_none, "ADC_sf01" }, \
{(char *)&ADC_sf[0][2], pt_int16, t_iq_none, t_iq_none, "ADC_sf02" }, \ {(uint8_t *)&ADC_sf[0][2], pt_int16, t_iq_none, t_iq_none, "ADC_sf02" }, \
{(char *)&ADC_sf[0][3], pt_int16, t_iq_none, t_iq_none, "ADC_sf03" }, \ {(uint8_t *)&ADC_sf[0][3], pt_int16, t_iq_none, t_iq_none, "ADC_sf03" }, \
{(char *)&Bender[0].KOhms, pt_uint16, t_iq, t_iq10, "Bend0.KOhm" }, \ {(uint8_t *)&Bender[0].KOhms, pt_uint16, t_iq, t_iq10, "Bend0.KOhm" }, \
{(char *)&Bender[0].Times, pt_uint16, t_iq_none, t_iq_none, "Bend0.Time" }, \ {(char *)&Bender[0].Times, pt_uint16, t_iq_none, t_iq_none, "Bend0.Time" }, \
}; };
``` ```
# DebugVarEdit - Настройка переменных для терминалки # DebugVarEdit - Настройка переменных
**DebugVarEdit** — графическое приложение для Windows, предназначенное для настройки и генерации отладочных переменных (`debug_vars.c`) на основе исходного C-проекта. Работает с `makefile` проекта, сохраняет изменения в XML и позволяет удобно редактировать переменные и их типы через интерфейс. **DebugVarEdit** — графическое приложение для Windows, предназначенное для настройки и генерации отладочных переменных (`debug_vars.c`) на основе исходного C-проекта. Работает с `makefile` проекта, сохраняет изменения в XML и позволяет удобно редактировать переменные и их типы через интерфейс.
Программа — один исполняемый файл `DebugVarEdit.exe`, не требующий установки и дополнительных зависимостей. Программа — один исполняемый файл `DebugVarEdit.exe`, не требующий установки и дополнительных зависимостей.
@ -44,11 +45,12 @@ DebugVar_t dbg_vars[] = {\
1. Запустите **DebugVarEdit.exe.** 1. Запустите **DebugVarEdit.exe.**
2. Укажите пути: 2. Укажите пути и контроллер:
- **Путь к XML** — новый или существующий файл настроек переменных; - **Путь к XML** — новый или существующий файл настроек переменных;
- **Путь к проекту** — путь к корню проека (папка, которая является корнем для проекта в Code Composer); - **Путь к проекту** — путь к корню проека (папка, которая является корнем для проекта в Code Composer);
- **Путь к makefile** — путь к `makefile` относительно корня проекта; - **Путь к makefile** — путь к `makefile` относительно корня проекта;
- **Путь для debug_vars.c** — папка, куда будет сгенерирован файл `debug_vars.c` с переменными. - **Путь для debug_vars.c** — папка, куда будет сгенерирован файл `debug_vars.c` с переменными.
- **МК** — TMS или STM. Они отличаются размером int, и также принятыми кодировками файлов (utf-8/cp1251)
3. Нажмите **Сканировать переменные**: 3. Нажмите **Сканировать переменные**:
- Программа проанализирует исходники, указанные в makefile, и найдёт все переменные. - Программа проанализирует исходники, указанные в makefile, и найдёт все переменные.
@ -92,7 +94,7 @@ DebugVar_t dbg_vars[] = {\
## Пример XML-файла ## Пример XML-файла
```xml ```xml
<project proj_path="C:/myproj" makefile_path="Debug/Makefile" structs_path="debugVars/structs.xml"> <project proj_path="C:/myproj" makefile_path="Debug/Makefile" structs_path="Src/DebugTools/structs.xml">
<variables> <variables>
<var name="g_myvar"> <var name="g_myvar">
<enable>true</enable> <enable>true</enable>
@ -139,14 +141,14 @@ Src
Для запуска приложения: Для запуска приложения:
- **Python 3.7+** - **Python 3.7+**
- **clang** — используется для парсинга C-кода (требуется `libclang.dll`) - **clang** — используется для парсинга C-кода (требуется `libclang.dll`, лежит в папке Src)
- **PySide2** — GUI-фреймворк - **PySide2** — GUI-фреймворк
- **lxml** — работа с XML - **lxml** — работа с XML
> Python 3.7 и PySide2 рекомендуется для совместимости с Windows 7 > Python 3.7 и PySide2 рекомендуется для совместимости с Windows 7
Для сборки `.exe`: Для сборки `.exe`:
- **Nuitka** — создает полностью автономный `.exe` без внешних зависимостей - **Nuitka** — создает полностью автономный `.exe` без внешних зависимостей
- **PyInstaller** — создает `.exe` с зависимостью от `pythonXX.dll` (Python должен быть установлен) - **PyInstaller** — создает `.exe` с зависимостью от `pythonXX.dll` (Python должен быть установлен для запуска `.exe`)
### Сборка: ### Сборка:
@ -166,5 +168,5 @@ Src
### Установка зависимостей ### Установка зависимостей
```bash ```bash
pip install PySide2 lxml nuitka pyinstaller pip install clang PySide2 lxml nuitka pyinstaller
``` ```

View File

@ -127,19 +127,28 @@ class VarEditor(QWidget):
# Добавляем чекбокс для выбора типовой карты # Добавляем чекбокс для выбора типовой карты
# --- Создаем верхнее меню --- # --- Создаем верхнее меню ---
menubar = QMenuBar(self) menubar = QMenuBar(self)
target_menu = QMenu("Target", menubar) menubar.setToolTip('Разные размеры int и кодировки файлов')
self.target_menu = QMenu("МК:", menubar)
# Создаем действия для выбора Target # Создаем действия для выбора Target
self.action_tms = QAction("TMS", self, checkable=True) self.action_tms = QAction("TMS", self, checkable=True)
self.action_stm = QAction("STM", self, checkable=True) self.action_stm = QAction("STM", self, checkable=True)
# Инициализируем QSettings с именем организации и приложения
self.settings = QSettings("SET", "DebugVarEdit_MainWindow")
# Восстанавливаем сохранённое состояние, если есть
mcu = self.settings.value("mcu_choosen", True, type=str)
self.on_target_selected(mcu)
self.target_menu.setToolTip(f'TMS: Размер int 16 бит. Кодировка cp1251\nSTM: Размер int 32 бита. Кодировка utf-8')
# Группируем действия чтобы выбирался только один # Группируем действия чтобы выбирался только один
self.action_tms.setChecked(True) # по умолчанию TMS self.action_tms.triggered.connect(lambda: self.on_target_selected("TMS"))
self.action_tms.triggered.connect(lambda: self.on_target_selected("tms")) self.action_tms.setToolTip('Размер int 16 бит. Кодировка cp1251')
self.action_stm.triggered.connect(lambda: self.on_target_selected("stm")) self.action_stm.triggered.connect(lambda: self.on_target_selected("STM"))
self.action_stm.setToolTip('Размер int 32 бита. Кодировка utf-8')
target_menu.addAction(self.action_tms) self.target_menu.addAction(self.action_tms)
target_menu.addAction(self.action_stm) self.target_menu.addAction(self.action_stm)
menubar.addMenu(target_menu) menubar.addMenu(self.target_menu)
# Кнопка сохранения # Кнопка сохранения
btn_save = QPushButton(build_title) btn_save = QPushButton(build_title)
@ -171,8 +180,10 @@ class VarEditor(QWidget):
def on_target_selected(self, target): def on_target_selected(self, target):
self.target_menu.setTitle(f'МК: {target}')
self.settings.setValue("mcu_choosen", target)
self.target = target.lower() self.target = target.lower()
if target == "stm": if self.target == "stm":
choose_type_map(True) choose_type_map(True)
self.action_stm.setChecked(True) self.action_stm.setChecked(True)
self.action_tms.setChecked(False) self.action_tms.setChecked(False)
@ -272,7 +283,7 @@ class VarEditor(QWidget):
return return
try: try:
run_generate(self.proj_path, self.xml_path, self.output_path) run_generate(self.proj_path, self.xml_path, self.output_path, self.table._shortname_size)
QMessageBox.information(self, "Готово", "Файл debug_vars.c успешно сгенерирован.") QMessageBox.information(self, "Готово", "Файл debug_vars.c успешно сгенерирован.")
self.update() self.update()
except Exception as e: except Exception as e:

View File

@ -12,6 +12,7 @@ from xml.dom import minidom
import myXML import myXML
import argparse import argparse
shortnameSize = 10
# === Словарь соответствия типов XML → DebugVarType_t === # === Словарь соответствия типов XML → DebugVarType_t ===
type_map_tms = dict([ type_map_tms = dict([
@ -186,13 +187,16 @@ type_map_stm32 = dict([
)], )],
]) ])
type_map = type_map_tms type_map = type_map_tms
stm_flag_global = 0
def choose_type_map(stm_flag): def choose_type_map(stm_flag):
global type_map # объявляем, что будем менять глобальную переменную global type_map # объявляем, что будем менять глобальную переменную
global stm_flag_global # объявляем, что будем менять глобальную переменную
if stm_flag: if stm_flag:
type_map = type_map_stm32 type_map = type_map_stm32
stm_flag_global = 1
else: else:
type_map = type_map_tms type_map = type_map_tms
stm_flag_global = 0
def map_type_to_pt(typename, varname=None, typedef_map=None): def map_type_to_pt(typename, varname=None, typedef_map=None):
typename_orig = typename.strip() typename_orig = typename.strip()
@ -286,9 +290,9 @@ def add_new_vars_to_xml(proj_path, xml_rel_path, output_path):
if os.path.isfile(output_path): if os.path.isfile(output_path):
with open(output_path, 'r', encoding='utf-8', errors='ignore') as f: with open(output_path, 'r', encoding='utf-8', errors='ignore') as f:
for line in f: for line in f:
# {(char *)&some.deep.var.name , pt_uint16 , t_iq15 , "ShortName"}, # {(uint8_t *)&some.deep.var.name , pt_uint16 , t_iq15 , "ShortName"},
m = re.match( m = re.match(
r'{\s*\(char\s*\*\)\s*&([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\s*,\s*(pt_\w+)\s*,\s*(t?iq_\w+)\s*,\s*"([^"]+)"', r'{\s*\(uint8_t\s*\*\)\s*&([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)\s*,\s*(pt_\w+)\s*,\s*(t?iq_\w+)\s*,\s*"([^"]+)"',
line) line)
if m: if m:
full_varname = m.group(1) # e.g., some.deep.var.name full_varname = m.group(1) # e.g., some.deep.var.name
@ -426,12 +430,27 @@ def read_vars_from_xml(proj_path, xml_rel_path):
return unique_vars, include_files, vars_need_extern return unique_vars, include_files, vars_need_extern
def read_file_try_encodings(filepath):
if not os.path.isfile(filepath):
# Файл не существует — просто вернуть пустую строку или None
return "", None
for enc in ['utf-8', 'cp1251']:
try:
with open(filepath, 'r', encoding=enc) as f:
content = f.read()
return content, enc
except UnicodeDecodeError:
continue
raise UnicodeDecodeError(f"Не удалось прочитать файл {filepath} с кодировками utf-8 и cp1251")
def generate_vars_file(proj_path, xml_path, output_dir): def generate_vars_file(proj_path, xml_path, output_dir):
output_dir = os.path.join(proj_path, output_dir) output_dir = os.path.join(proj_path, output_dir)
os.makedirs(output_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True)
output_path = os.path.join(output_dir, 'debug_vars.c') output_path = os.path.join(output_dir, 'debug_vars.c')
LIBC_path = os.path.join(output_dir, 'debug_tools.c')
LIBH_path = os.path.join(output_dir, 'debug_tools.h')
# Запись новых переменных для в XML # Запись новых переменных для в XML
@ -479,7 +498,7 @@ def generate_vars_file(proj_path, xml_path, output_dir):
# Дополнительные поля, например комментарий # Дополнительные поля, например комментарий
comment = info.get("comment", "") comment = info.get("comment", "")
short_name = info.get("shortname", f'"{vname}"') short_name = info.get("shortname", f'"{vname}"')
short_trimmed = short_name[:10] # ограничиваем длину до 10 short_trimmed = short_name[:shortnameSize] # ограничиваем длину до 10
if pt_type not in ('pt_struct', 'pt_union'): if pt_type not in ('pt_struct', 'pt_union'):
f_name = f'{vname},' f_name = f'{vname},'
@ -489,7 +508,7 @@ def generate_vars_file(proj_path, xml_path, output_dir):
f_short_name = f'"{short_trimmed}"' # оборачиваем в кавычки f_short_name = f'"{short_trimmed}"' # оборачиваем в кавычки
# Добавим комментарий после записи, если он есть # Добавим комментарий после записи, если он есть
comment_str = f' // {comment}' if comment else '' comment_str = f' // {comment}' if comment else ''
line = f'{{(char *)&{f_name:<57} {f_type:<15} {f_iq:<15} {f_ret_iq:<15} {f_short_name:<21}}}, \\{comment_str}' line = f'{{(uint8_t *)&{f_name:<58} {f_type:<15} {f_iq:<15} {f_ret_iq:<15} {f_short_name:<21}}}, \\{comment_str}'
new_debug_vars[vname] = line new_debug_vars[vname] = line
else: else:
@ -535,14 +554,19 @@ def generate_vars_file(proj_path, xml_path, output_dir):
out_lines.append(f'\n\n// Определение массива с указателями на переменные для отладки') out_lines.append(f'\n\n// Определение массива с указателями на переменные для отладки')
out_lines.append(f'int DebugVar_Qnt = {len(all_debug_lines)};') out_lines.append(f'int DebugVar_Qnt = {len(all_debug_lines)};')
out_lines.append('#pragma DATA_SECTION(dbg_vars,".dbgvar_info")') if stm_flag_global == 0:
out_lines.append('#pragma DATA_SECTION(dbg_vars,".dbgvar_info")')
out_lines.append('// pointer_type iq_type return_iq_type short_name')
out_lines.append('DebugVar_t dbg_vars[] = {\\') out_lines.append('DebugVar_t dbg_vars[] = {\\')
out_lines.extend(all_debug_lines) out_lines.extend(all_debug_lines)
out_lines.append('};') out_lines.append('};')
out_lines.append('') out_lines.append('')
# Выберем кодировку для записи файла # Выберем кодировку для записи файла
# Если встречается несколько, возьмем первую из set # Если встречается несколько, возьмем первую из set
enc_to_write = 'cp1251' if stm_flag_global == 0:
enc_to_write = 'cp1251'
else:
enc_to_write = 'utf-8'
#print("== GLOBAL VARS FOUND ==") #print("== GLOBAL VARS FOUND ==")
#for vname, (vtype, path) in vars_in_c.items(): #for vname, (vtype, path) in vars_in_c.items():
@ -552,6 +576,16 @@ def generate_vars_file(proj_path, xml_path, output_dir):
with open(output_path, 'w', encoding=enc_to_write) as f: with open(output_path, 'w', encoding=enc_to_write) as f:
f.write('\n'.join(out_lines)) f.write('\n'.join(out_lines))
if os.path.isfile(LIBC_path):
libc_code, _ = read_file_try_encodings(LIBC_path)
with open(LIBC_path, 'w', encoding=enc_to_write) as f:
f.write(libc_code)
if os.path.isfile(LIBH_path):
libh_code, _ = read_file_try_encodings(LIBH_path)
with open(LIBH_path, 'w', encoding=enc_to_write) as f:
f.write(libh_code)
print(f'Файл debug_vars.c сгенерирован в кодировке, переменных: {len(all_debug_lines)}') print(f'Файл debug_vars.c сгенерирован в кодировке, переменных: {len(all_debug_lines)}')
@ -613,16 +647,17 @@ Usage example:
print(f"Error: Project path '{proj_path}' не является директорией или не существует.") print(f"Error: Project path '{proj_path}' не является директорией или не существует.")
sys.exit(1) sys.exit(1)
generate_vars_file(proj_path, xml_path_rel, output_dir_rel) generate_vars_file(proj_path, xml_path_rel, output_dir_rel, 0)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
def run_generate(proj_path, xml_path, output_dir): def run_generate(proj_path, xml_path, output_dir, shortname_size):
import os import os
global shortnameSize
shortnameSize = shortname_size
# Normalize absolute paths # Normalize absolute paths
proj_path = os.path.abspath(proj_path) proj_path = os.path.abspath(proj_path)
xml_path_abs = os.path.abspath(xml_path) xml_path_abs = os.path.abspath(xml_path)

View File

@ -154,6 +154,7 @@ def analyze_variables_across_files(c_files, h_files, include_dirs, global_defs):
# Проверяем, начинается ли имя с "_" и содержит заглавные буквы или служебные символы # Проверяем, начинается ли имя с "_" и содержит заглавные буквы или служебные символы
return bool(re.match(r"^_[_A-Z]", var_name)) return bool(re.match(r"^_[_A-Z]", var_name))
if node.kind == clang.cindex.CursorKind.VAR_DECL: if node.kind == clang.cindex.CursorKind.VAR_DECL:
if node.semantic_parent.kind == clang.cindex.CursorKind.TRANSLATION_UNIT: if node.semantic_parent.kind == clang.cindex.CursorKind.TRANSLATION_UNIT:
is_extern = (node.storage_class == clang.cindex.StorageClass.EXTERN) is_extern = (node.storage_class == clang.cindex.StorageClass.EXTERN)
@ -170,7 +171,12 @@ def analyze_variables_across_files(c_files, h_files, include_dirs, global_defs):
return # игнорируем только явно известные служебные переменные return # игнорируем только явно известные служебные переменные
if node.spelling == 'HUGE': # еще одна служеюная, которую хз как выделять if node.spelling == 'HUGE': # еще одна служеюная, которую хз как выделять
return return
if 'Drivers' in node.location.file.name:
return
if 'uint' in node.spelling:
a = 1
# Проверяем, является ли тип указателем на функцию # Проверяем, является ли тип указателем на функцию
# Признак: в типе есть '(' и ')' и '*', например: "void (*)(int)" # Признак: в типе есть '(' и ')' и '*', например: "void (*)(int)"
if "(" in var_type and "*" in var_type and ")" in var_type: if "(" in var_type and "*" in var_type and ")" in var_type:
@ -464,8 +470,6 @@ def analyze_typedefs_and_structs_across_files(c_files, include_dirs, global_defs
def visit(node): def visit(node):
if node.kind == clang.cindex.CursorKind.TYPEDEF_DECL: if node.kind == clang.cindex.CursorKind.TYPEDEF_DECL:
name = node.spelling name = node.spelling
if 'ADC_HandleTypeDef' in name:
a =1
underlying = node.underlying_typedef_type.spelling underlying = node.underlying_typedef_type.spelling
typedefs[name] = underlying typedefs[name] = underlying
@ -473,10 +477,7 @@ def analyze_typedefs_and_structs_across_files(c_files, include_dirs, global_defs
prefix = "struct " if node.kind == clang.cindex.CursorKind.STRUCT_DECL else "union " prefix = "struct " if node.kind == clang.cindex.CursorKind.STRUCT_DECL else "union "
raw_name = node.spelling raw_name = node.spelling
if 'struct (unnamed struct at F:\\Work\\Projects\\NIIET\\MZKT\\MZKT\\Drivers\\STM32F4xx_HAL_Driver\\Inc\\stm32f4xx_hal_adc.h:195:9)' in raw_name:
a =1
normalized_name = normalize_type_name(raw_name) normalized_name = normalize_type_name(raw_name)
# struct_name всегда с префиксом # struct_name всегда с префиксом
if node.spelling and "unnamed" not in normalized_name: if node.spelling and "unnamed" not in normalized_name:
struct_name = f"{prefix}{normalized_name}" struct_name = f"{prefix}{normalized_name}"

View File

@ -1,10 +1,10 @@
from PySide2.QtWidgets import ( from PySide2.QtWidgets import (
QTableWidget, QTableWidgetItem, QCheckBox, QComboBox, QLineEdit, QCompleter, QTableWidget, QTableWidgetItem, QCheckBox, QComboBox, QLineEdit, QCompleter,
QAbstractItemView, QHeaderView, QLabel, QAbstractItemView, QHeaderView, QLabel, QSpacerItem, QSizePolicy, QSpinBox,
QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QScrollArea, QWidget QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QScrollArea, QWidget
) )
from PySide2.QtGui import QColor, QBrush, QPalette from PySide2.QtGui import QColor, QBrush, QPalette
from PySide2.QtCore import Qt from PySide2.QtCore import Qt, QSettings
from enum import IntEnum from enum import IntEnum
from generate_debug_vars import type_map from generate_debug_vars import type_map
import time import time
@ -60,6 +60,57 @@ class FilterDialog(QDialog):
return [cb.text() for cb in self.checkboxes if cb.isChecked()] return [cb.text() for cb in self.checkboxes if cb.isChecked()]
class SetSizeDialog(QDialog):
"""
Диалоговое окно для выбора числового значения (размера).
"""
def __init__(self, parent=None, initial_value=10, min_value=1, max_value=50, title="Укажите размер короткого имени"):
super().__init__(parent)
self.setWindowTitle(title)
self.setFixedSize(320, 120) # Задаем фиксированный размер для аккуратного вида
# Основной вертикальный макет
main_layout = QVBoxLayout(self)
# Макет для ввода значения
input_layout = QHBoxLayout()
label = QLabel("Количество символов:", self)
self.spin_box = QSpinBox(self)
self.spin_box.setRange(min_value, max_value) # Устанавливаем диапазон допустимых значений
initial_value = parent._shortname_size
self.spin_box.setValue(initial_value) # Устанавливаем начальное значение
self.spin_box.setFocus() # Устанавливаем фокус на поле ввода
input_layout.addWidget(label)
input_layout.addWidget(self.spin_box)
main_layout.addLayout(input_layout)
# Добавляем пустое пространство для лучшего разделения
main_layout.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding))
# Макет для кнопок
btn_layout = QHBoxLayout()
btn_layout.addStretch() # Добавляем растягивающийся элемент, чтобы кнопки были справа
btn_ok = QPushButton("OK")
btn_cancel = QPushButton("Отмена")
btn_layout.addWidget(btn_ok)
btn_layout.addWidget(btn_cancel)
main_layout.addLayout(btn_layout)
# Подключение сигналов к слотам
btn_ok.clicked.connect(self.accept) # При нажатии "OK" диалог закроется со статусом "Accepted"
btn_cancel.clicked.connect(self.reject) # При нажатии "Отмена" - со статусом "Rejected"
def get_selected_size(self):
"""
Возвращает значение, выбранное в QSpinBox.
"""
return self.spin_box.value()
class CtrlScrollComboBox(QComboBox): class CtrlScrollComboBox(QComboBox):
def wheelEvent(self, event): def wheelEvent(self, event):
if event.modifiers() & Qt.ControlModifier: if event.modifiers() & Qt.ControlModifier:
@ -83,6 +134,11 @@ class VariableTableWidget(QTableWidget):
]) ])
self.setEditTriggers(QAbstractItemView.AllEditTriggers) self.setEditTriggers(QAbstractItemView.AllEditTriggers)
self.var_list = [] self.var_list = []
# Инициализируем QSettings с именем организации и приложения
self.settings = QSettings("SET", "DebugVarEdit_VarTable")
# Восстанавливаем сохранённое состояние, если есть
shortsize = self.settings.value("shortname_size", True, type=int)
self._shortname_size = shortsize
self.type_options = list(dict.fromkeys(type_map.values())) self.type_options = list(dict.fromkeys(type_map.values()))
self.pt_types_all = [t.replace('pt_', '') for t in self.type_options] self.pt_types_all = [t.replace('pt_', '') for t in self.type_options]
@ -231,7 +287,7 @@ class VariableTableWidget(QTableWidget):
t3 = time.time() t3 = time.time()
shortname = short_name_edit.text() if short_name_edit else "" shortname = short_name_edit.text() if short_name_edit else ""
long_shortname = len(shortname) > 10 long_shortname = len(shortname) > self._shortname_size
found = name in var_names_set found = name in var_names_set
color = None color = None
@ -293,6 +349,13 @@ class VariableTableWidget(QTableWidget):
if dlg.exec_(): if dlg.exec_():
self._ret_type_filter = dlg.get_selected() self._ret_type_filter = dlg.get_selected()
self.update_comboboxes({rows.ret_type: self._ret_type_filter}) self.update_comboboxes({rows.ret_type: self._ret_type_filter})
elif logicalIndex == rows.short_name:
dlg = SetSizeDialog(self)
if dlg.exec_():
self._shortname_size = dlg.get_selected_size()
self.settings.setValue("shortname_size", self._shortname_size)
self.check()

View File

@ -1,18 +1,22 @@
#include "debug_tools.h" #include "debug_tools.h"
#include "IQmathLib.h"
#if !defined(GLOBAL_Q)
#define GLOBAL_Q 16
#endif
DebugLowLevel_t debug_ll = DEBUG_LOWLEVEL_INIT; ///< Структура отладки нижнего уровня (инициализация) DebugLowLevel_t debug_ll = DEBUG_LOWLEVEL_INIT; ///< Структура отладки нижнего уровня (инициализация)
static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var); static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var);
static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var); static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var);
///////////////////////////----EXAPLE-----////////////////////////////// ///////////////////////////----EXAPLE-----//////////////////////////////
long var_numb = 1; ///< Ïðèìåð ïåðåìåííîé äëÿ îòëàäêè int var_numb = 1; ///< Ïðèìåð ïåðåìåííîé äëÿ îòëàäêè
DebugVarName_t var_name; ///< Имя переменной DebugVarName_t var_name; ///< Имя переменной
long return_var; ///< Ïåðåìåííàÿ äëÿ âîçâðàòà ðåçóëüòàòà int32_t return_var; ///< Ïåðåìåííàÿ äëÿ âîçâðàòà ðåçóëüòàòà
long return_ll_var; ///< Âîçâðàùàåìîå çíà÷åíèå ñ íèæíåãî óðîâíÿ int32_t return_ll_var; ///< Âîçâðàùàåìîå çíà÷åíèå ñ íèæíåãî óðîâíÿ
int result; ///< Переменная результата int result; ///< Переменная результата
char ext_date[] = {7, 233, 11, 07, 16, 50}; ///< Ïðèìåð âíåøíåé äàòû ñáîðêè DateTime_t ext_date = {2025, 11, 07, 16, 50}; ///< Ïðèìåð âíåøíåé äàòû ñáîðêè
/** /**
* @brief Пример использования функций отладки. * @brief Пример использования функций отладки.
@ -24,7 +28,7 @@ void Debug_Test_Example(void)
result = Debug_ReadVarName(var_numb, var_name); result = Debug_ReadVarName(var_numb, var_name);
if(Debug_LowLevel_Initialize(ext_date) == 0) if(Debug_LowLevel_Initialize(&ext_date) == 0)
result = Debug_LowLevel_ReadVar(&return_ll_var); result = Debug_LowLevel_ReadVar(&return_ll_var);
} }
@ -33,25 +37,23 @@ void Debug_Test_Example(void)
/** /**
* @brief Читает переменную по индексу. * @brief Читает переменную по индексу.
* @param var_ind индекс переменной. * @param var_ind индекс переменной.
* @param return_long óêàçàòåëü äëÿ âîçâðàòà ðåçóëüòàòà. * @param return_32b óêàçàòåëü äëÿ âîçâðàòà ðåçóëüòàòà.
* @return int 0: успех, 1: ошибка. * @return int 0: успех, 1: ошибка.
* @details Используется для чтения значений переменных по их индексу. * @details Используется для чтения значений переменных по их индексу.
*/ */
int Debug_ReadVar(int var_ind, long *return_long) int Debug_ReadVar(int var_ind, int32_t *return_32b)
{ {
if(return_long == NULL) if(return_32b == NULL)
return 1; return 1;
long tmp_var; int32_t tmp_var;
if (var_ind >= DebugVar_Qnt) if (var_ind >= DebugVar_Qnt)
return 1; return 1;
if((dbg_vars[var_numb].ptr_type == pt_struct) || (dbg_vars[var_numb].ptr_type == pt_union) || if((dbg_vars[var_ind].ptr_type == pt_struct) || (dbg_vars[var_ind].ptr_type == pt_union) ||
(dbg_vars[var_numb].ptr_type == pt_unknown)) (dbg_vars[var_ind].ptr_type == pt_unknown))
return 1; return 1;
return convertDebugVarToIQx(&dbg_vars[var_ind], return_32b);
return convertDebugVarToIQx(&dbg_vars[var_numb], return_long);
} }
/** /**
@ -71,14 +73,14 @@ int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr)
int i; int i;
// Копирование с защитой от переполнения и явной остановкой по '\0' // Копирование с защитой от переполнения и явной остановкой по '\0'
for (i = 0; i < sizeof(dbg_vars[var_numb].name); i++) for (i = 0; i < sizeof(dbg_vars[var_ind].name); i++)
{ {
name_ptr[i] = dbg_vars[var_numb].name[i]; name_ptr[i] = dbg_vars[var_ind].name[i];
if (dbg_vars[var_numb].name[i] == '\0') if (dbg_vars[var_ind].name[i] == '\0')
break; break;
} }
// Гарантированное завершение строки (на случай, если в var->name не было '\0') // Гарантированное завершение строки (на случай, если в var->name не было '\0')
name_ptr[sizeof(dbg_vars[var_numb].name) - 1] = '\0'; name_ptr[sizeof(dbg_vars[var_ind].name) - 1] = '\0';
return 0; return 0;
} }
@ -86,19 +88,19 @@ int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr)
/** /**
* @brief Читает значение переменной отладки с нижнего уровня. * @brief Читает значение переменной отладки с нижнего уровня.
* @param return_long óêàçàòåëü íà ïåðåìåííóþ, êóäà çàïèñûâàåòñÿ ðåçóëüòàò. * @param return_32b óêàçàòåëü íà ïåðåìåííóþ, êóäà çàïèñûâàåòñÿ ðåçóëüòàò.
* @return int 0: успех, 1: ошибка, 2: недопустимый адрес. * @return int 0: успех, 1: ошибка, 2: недопустимый адрес.
* @details Использует адресс, передаваемый с терминалки для получения значения. * @details Использует адресс, передаваемый с терминалки для получения значения.
*/ */
int Debug_LowLevel_ReadVar(long *return_long) int Debug_LowLevel_ReadVar(int32_t *return_32b)
{ {
if (return_long == NULL) if (return_32b == NULL)
return 1; return 1;
if (debug_ll.isVerified == 0) if (debug_ll.isVerified == 0)
return 1; return 1;
char *addr = debug_ll.dbg_var.Ptr; uint8_t *addr = debug_ll.dbg_var.Ptr;
unsigned long addr_val = (unsigned long)addr; uint32_t addr_val = (uint32_t)addr;
// Разрешённые диапазоны памяти (из .cmd файла) // Разрешённые диапазоны памяти (из .cmd файла)
if (!( if (!(
@ -114,37 +116,28 @@ int Debug_LowLevel_ReadVar(long *return_long)
return 2; // Запрещённый адрес — нельзя читать return 2; // Запрещённый адрес — нельзя читать
} }
return convertDebugVarToIQx(&debug_ll.dbg_var, return_long); return convertDebugVarToIQx(&debug_ll.dbg_var, return_32b);
;
} }
/** /**
* @brief Инициализация отладки на нижнем уровне по дате сборки. * @brief Инициализация отладки на нижнем уровне по дате сборки.
* @param external_date óêàçàòåëü íà ìàññèâ èç 6 áàéò: {year_hi, year_lo, day, month, hour, minute}. * @param external_date ñòðóêòóðà ñ äàòîé DateTime_t
* @return int 0: совпадает, 1: не совпадает, -1: ошибка. * @return int 0: совпадает, 1: не совпадает, -1: ошибка.
* @details Сравнивает дату компиляции с запрашиваемой и инициализирует отладочную переменную. * @details Сравнивает дату компиляции с запрашиваемой и инициализирует отладочную переменную.
*/ */
int Debug_LowLevel_Initialize(const char* external_date) int Debug_LowLevel_Initialize(DateTime_t* external_date)
{ {
if (external_date == NULL) { if (external_date == NULL) {
return -1; return -1;
} }
// Ïðåîáðàçóåì external_date â ñòðóêòóðó
DateTime_t ext;
ext.year = (external_date[0] << 8) | external_date[1];
ext.day = external_date[2];
ext.month = external_date[3];
ext.hour = external_date[4];
ext.minute = external_date[5];
// Сравнение всех полей // Сравнение всех полей
if (ext.year == debug_ll.build_date.year && if (external_date->year == debug_ll.build_date.year &&
ext.month == debug_ll.build_date.month && external_date->month == debug_ll.build_date.month &&
ext.day == debug_ll.build_date.day && external_date->day == debug_ll.build_date.day &&
ext.hour == debug_ll.build_date.hour && external_date->hour == debug_ll.build_date.hour &&
ext.minute == debug_ll.build_date.minute) external_date->minute == debug_ll.build_date.minute)
{ {
debug_ll.isVerified = 1; debug_ll.isVerified = 1;
return 0; // Совпало return 0; // Совпало
@ -180,13 +173,13 @@ static int iqTypeToQ(DebugVarIQType_t t)
/** /**
* @brief Преобразует переменную отладки в IQ формат. * @brief Преобразует переменную отладки в IQ формат.
* @param var указатель на переменную отладки. * @param var указатель на переменную отладки.
* @param ret_var óêàçàòåëü äëÿ âîçâðàòà çíà÷åíèÿ â ôîðìàòå long. * @param ret_var óêàçàòåëü äëÿ âîçâðàòà çíà÷åíèÿ â ôîðìàòå 32 áèòà.
* @return int 0: успех, 1: ошибка чтения, 2: неправильный формат, 3: переполнение. * @return int 0: успех, 1: ошибка чтения, 2: неправильный формат, 3: переполнение.
* @details Îïðåäåëÿåò ôîðìàò IQ ïåðåìåííîé, êîíâåðòèðóåò å¸ â long ñ ó÷¸òîì ìàñøòàáà. * @details Îïðåäåëÿåò ôîðìàò IQ ïåðåìåííîé, êîíâåðòèðóåò å¸ â 32b ñ ó÷¸òîì ìàñøòàáà.
*/ */
static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var) static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var)
{ {
long iq_numb, iq_united, iq_final; int32_t iq_numb, iq_united, iq_final;
float float_numb; float float_numb;
if(getDebugVar(var, &iq_numb, &float_numb) != 0) if(getDebugVar(var, &iq_numb, &float_numb) != 0)
@ -198,30 +191,30 @@ static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var)
if (src_q < 0 || dst_q < 0) if (src_q < 0 || dst_q < 0)
return 2; // неправильный формат return 2; // неправильный формат
long long iq_united64 = 0; int64_t iq_united64 = 0;
long long iq_final64 = 0; int64_t iq_final64 = 0;
// Конвертация к GLOBAL_Q (64-бит) // Конвертация к GLOBAL_Q (64-бит)
if (var->iq_type == t_iq_none) { if (var->iq_type == t_iq_none) {
if (var->ptr_type == pt_float) { if (var->ptr_type == pt_float) {
// float_numb умножаем на 2^GLOBAL_Q (2^24=16777216) // float_numb умножаем на 2^GLOBAL_Q (2^24=16777216)
// Ðåçóëüòàò ïðèâîäèì ê long long // Ðåçóëüòàò ïðèâîäèì ê 64 áèòà
iq_united64 = (long long)(float_numb * 16777216.0f); iq_united64 = (int64_t)(float_numb * 16777216.0f);
} else { } else {
iq_united64 = ((long long)iq_numb) << GLOBAL_Q; iq_united64 = ((int64_t)iq_numb) << GLOBAL_Q;
} }
} else { } else {
int shift = GLOBAL_Q - src_q; int shift = GLOBAL_Q - src_q;
if (shift >= 0) if (shift >= 0)
iq_united64 = ((long long)iq_numb) << shift; iq_united64 = ((int64_t)iq_numb) << shift;
else else
iq_united64 = ((long long)iq_numb) >> (-shift); iq_united64 = ((int64_t)iq_numb) >> (-shift);
} }
// Конвертация из GLOBAL_Q в целевой IQ (64-бит) // Конвертация из GLOBAL_Q в целевой IQ (64-бит)
if (var->return_type == t_iq_none) { if (var->return_type == t_iq_none) {
// Возвращаем целое, отбросив дробную часть // Возвращаем целое, отбросив дробную часть
*ret_var = (long)(iq_united64 >> GLOBAL_Q); *ret_var = (uint32_t)(iq_united64 >> GLOBAL_Q);
} else { } else {
int shift = dst_q - GLOBAL_Q; int shift = dst_q - GLOBAL_Q;
if (shift >= 0) if (shift >= 0)
@ -230,10 +223,10 @@ static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var)
iq_final64 = iq_united64 >> (-shift); iq_final64 = iq_united64 >> (-shift);
// Проверяем переполнение int32_t // Проверяем переполнение int32_t
if (iq_final64 > LONG_MAX || iq_final64 < LONG_MIN) if (iq_final64 > 2147483647 || iq_final64 < -2147483648)
return 3; // переполнение return 3; // переполнение
*ret_var = (long)iq_final64; *ret_var = (uint32_t)iq_final64;
} }
return 0; return 0;
@ -242,50 +235,53 @@ static int convertDebugVarToIQx(DebugVar_t *var, long *ret_var)
/** /**
* @brief Прочитать значение переменной отладки. * @brief Прочитать значение переменной отладки.
* @param var указатель на структуру DebugVar. * @param var указатель на структуру DebugVar.
* @param int_var óêàçàòåëü íà ïåðåìåííóþ òèïà long äëÿ âîçâðàòà öåëî÷èñëåííîãî çíà÷åíèÿ. * @param int_var óêàçàòåëü íà ïåðåìåííóþ òèïà 32 áèòà äëÿ âîçâðàòà öåëî÷èñëåííîãî çíà÷åíèÿ.
* @param float_var указатель на переменную типа float для возврата значения с плавающей точкой. * @param float_var указатель на переменную типа float для возврата значения с плавающей точкой.
* @return int 0: успех, 1: ошибка указателей или неподдерживаемый тип, 3/4: ошибка выравнивания. * @return int 0: успех, 1: ошибка указателей или неподдерживаемый тип, 3/4: ошибка выравнивания.
* @details В зависимости от типа переменной считывает её значение и сохраняет в соответствующем указателе. * @details В зависимости от типа переменной считывает её значение и сохраняет в соответствующем указателе.
*/ */
static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var) static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var)
{ {
if (!var || !int_var || !float_var || !var->Ptr) if (!var || !int_var || !float_var || !var->Ptr)
return 1; // ошибка: null указатель return 1; // ошибка: null указатель
char *addr = var->Ptr; uint8_t *addr = var->Ptr;
unsigned long addr_val = (unsigned long)addr; uint32_t addr_val = (uint32_t)addr;
switch (var->ptr_type) switch (var->ptr_type)
{ {
case pt_int8: // 8 бит case pt_int8: // 8 бит
if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int8_t *)addr);
case pt_uint8: case pt_uint8:
// âûðàâíèâàíèå íå íóæíî äëÿ 8 áèò if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
*int_var = *((volatile char *)addr); return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint8_t *)addr);
break; break;
case pt_int16: // 16 бит (int) case pt_int16: // 16 бит (int)
if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int16_t *)addr);
case pt_uint16: case pt_uint16:
*int_var = *((volatile int *)addr); if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint16_t *)addr);
break; break;
case pt_int32: // 32 áèò (long) case pt_int32: // 32 áèò
case pt_uint32: if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
if (addr_val & 0x1) // ïðîâåðÿåì âûðàâíèâàíèå ïî 2 ñëîâàì (4 áàéòà)
return 3; // ошибка выравнивания return 3; // ошибка выравнивания
*int_var = *((volatile long *)addr); *int_var = *((volatile int32_t *)addr);
case pt_uint32:
if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 3; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint32_t *)addr);
break; break;
// case pt_int64: // 64 áèò (long long)
// case pt_uint64:
// if (addr_val & 0x3) // ïðîâåðêà âûðàâíèâàíèÿ ïî 4 ñëîâàì (8 áàéòàì)
// return 2; // îøèáêà âûðàâíèâàíèÿ
// // Òóò ïðîñòî ÷èòàåì, íî long long ìîæåò íå ïîìåñòèòüñÿ â *int_var
// // Ìîæíî çàìåíèòü ëîãèêó ïîä 64-áèòíîå ÷òåíèå ïðè íåîáõîäèìîñòè
// *int_var = *((volatile long long *)addr);
// break;
case pt_float: // float (4 байта) case pt_float: // float (4 байта)
if (addr_val & 0x1) // ïðîâåðêà âûðàâíèâàíèÿ ïî 2 ñëîâàì if ((addr_val & ALIGN_FLOAT) != 0) // ïðîâåðêà âûðàâíèâàíèÿ
return 4; // ошибка выравнивания return 4; // ошибка выравнивания
*float_var = *((volatile float *)addr); *float_var = *((volatile float *)addr);
break; break;
@ -310,211 +306,3 @@ static int getDebugVar(DebugVar_t *var, long *int_var, float *float_var)
return 0; // успех return 0; // успех
} }
///////////// OUTDATE ////////////////
//
// // ïðèâåäåíèå ê îäíîìó IQ
// switch(var->iq_type)
// {
// case t_iq_none:
// if(var->ptr_type == pt_float)
// {
// iq_united = _IQ(float_numb);
// }
// else
// {
// iq_united = _IQ(iq_numb);
// }
// break;
// case t_iq1:
// iq_united = _IQ1toIQ(iq_numb);
// break;
// case t_iq2:
// iq_united = _IQ2toIQ(iq_numb);
// break;
// case t_iq3:
// iq_united = _IQ3toIQ(iq_numb);
// break;
// case t_iq4:
// iq_united = _IQ4toIQ(iq_numb);
// break;
// case t_iq5:
// iq_united = _IQ5toIQ(iq_numb);
// break;
// case t_iq6:
// iq_united = _IQ6toIQ(iq_numb);
// break;
// case t_iq7:
// iq_united = _IQ7toIQ(iq_numb);
// break;
// case t_iq8:
// iq_united = _IQ8toIQ(iq_numb);
// break;
// case t_iq9:
// iq_united = _IQ9toIQ(iq_numb);
// break;
// case t_iq10:
// iq_united = _IQ10toIQ(iq_numb);
// break;
// case t_iq11:
// iq_united = _IQ11toIQ(iq_numb);
// break;
// case t_iq12:
// iq_united = _IQ12toIQ(iq_numb);
// break;
// case t_iq13:
// iq_united = _IQ13toIQ(iq_numb);
// break;
// case t_iq14:
// iq_united = _IQ14toIQ(iq_numb);
// break;
// case t_iq15:
// iq_united = _IQ15toIQ(iq_numb);
// break;
// case t_iq16:
// iq_united = _IQ16toIQ(iq_numb);
// break;
// case t_iq17:
// iq_united = _IQ17toIQ(iq_numb);
// break;
// case t_iq18:
// iq_united = _IQ18toIQ(iq_numb);
// break;
// case t_iq19:
// iq_united = _IQ19toIQ(iq_numb);
// break;
// case t_iq20:
// iq_united = _IQ20toIQ(iq_numb);
// break;
// case t_iq21:
// iq_united = _IQ21toIQ(iq_numb);
// break;
// case t_iq22:
// iq_united = _IQ22toIQ(iq_numb);
// break;
// case t_iq23:
// iq_united = _IQ23toIQ(iq_numb);
// break;
// case t_iq24:
// iq_united = _IQ24toIQ(iq_numb);
// break;
// case t_iq25:
// iq_united = _IQ25toIQ(iq_numb);
// break;
// case t_iq26:
// iq_united = _IQ26toIQ(iq_numb);
// break;
// case t_iq27:
// iq_united = _IQ27toIQ(iq_numb);
// break;
// case t_iq28:
// iq_united = _IQ28toIQ(iq_numb);
// break;
// case t_iq29:
// iq_united = _IQ29toIQ(iq_numb);
// break;
// case t_iq30:
// iq_united = _IQ30toIQ(iq_numb);
// break;
// }
//
// // ïðèâåäåíèå îáùåãî IQ ê çàïðàøèâàåìîìó
// switch(var->return_type)
// {
// case t_iq_none:
// iq_final = (long)_IQtoF(iq_united);
// break;
// case t_iq1:
// iq_final = _IQtoIQ1(iq_united);
// break;
// case t_iq2:
// iq_final = _IQtoIQ2(iq_united);
// break;
// case t_iq3:
// iq_final = _IQtoIQ3(iq_united);
// break;
// case t_iq4:
// iq_final = _IQtoIQ4(iq_united);
// break;
// case t_iq5:
// iq_final = _IQtoIQ5(iq_united);
// break;
// case t_iq6:
// iq_final = _IQtoIQ6(iq_united);
// break;
// case t_iq7:
// iq_final = _IQtoIQ7(iq_united);
// break;
// case t_iq8:
// iq_final = _IQtoIQ8(iq_united);
// break;
// case t_iq9:
// iq_final = _IQtoIQ9(iq_united);
// break;
// case t_iq10:
// iq_final = _IQtoIQ10(iq_united);
// break;
// case t_iq11:
// iq_final = _IQtoIQ11(iq_united);
// break;
// case t_iq12:
// iq_final = _IQtoIQ12(iq_united);
// break;
// case t_iq13:
// iq_final = _IQtoIQ13(iq_united);
// break;
// case t_iq14:
// iq_final = _IQtoIQ14(iq_united);
// break;
// case t_iq15:
// iq_final = _IQtoIQ15(iq_united);
// break;
// case t_iq16:
// iq_final = _IQtoIQ16(iq_united);
// break;
// case t_iq17:
// iq_final = _IQtoIQ17(iq_united);
// break;
// case t_iq18:
// iq_final = _IQtoIQ18(iq_united);
// break;
// case t_iq19:
// iq_final = _IQtoIQ19(iq_united);
// break;
// case t_iq20:
// iq_final = _IQtoIQ20(iq_united);
// break;
// case t_iq21:
// iq_final = _IQtoIQ21(iq_united);
// break;
// case t_iq22:
// iq_final = _IQtoIQ22(iq_united);
// break;
// case t_iq23:
// iq_final = _IQtoIQ23(iq_united);
// break;
// case t_iq24:
// iq_final = _IQtoIQ24(iq_united);
// break;
// case t_iq25:
// iq_final = _IQtoIQ25(iq_united);
// break;
// case t_iq26:
// iq_final = _IQtoIQ26(iq_united);
// break;
// case t_iq27:
// iq_final = _IQtoIQ27(iq_united);
// break;
// case t_iq28:
// iq_final = _IQtoIQ28(iq_united);
// break;
// case t_iq29:
// iq_final = _IQtoIQ29(iq_united);
// break;
// case t_iq30:
// iq_final = _IQtoIQ30(iq_united);
// break;
// }
// *ret_var = iq_final;

View File

@ -1,7 +1,48 @@
#ifndef DEBUG_TOOLS #ifndef DEBUG_TOOLS
#define DEBUG_TOOLS #define DEBUG_TOOLS
#include "IQmathLib.h" #include <stdint.h>
#include "DSP281x_Device.h" #include <limits.h>
//#if (LONG_MAX != 2147483647L)
//# error "debug_tools: this code assumes 32-bit long. Please update DebugValue_t typedef."
//#endif
#if defined(uint8_t) && defined(int8_t) // Åñëè åñòü òèï 8 áèò - çí÷à÷èò àäðåñàöèÿ ïî 8 áèò
#define ALIGN_8BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_16BIT 0x1 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 2 (addr & 0x1 == 0)
#define ALIGN_32BIT 0x3 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 4 (addr & 0x3 == 0)
#define ALIGN_64BIT 0x7 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 8 (addr & 0x7 == 0)
#define ALIGN_FLOAT ALIGN_32BIT
#else // Åñëè íåò òèïà 8 áèò - çíà÷èò àäðåñàöèÿ ïî 16 áèò
#define ALIGN_8BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_16BIT 0x0 ///< Âûðàâíèâàíèå áåç îãðàíè÷åíèé (ëþáîé àäðåñ)
#define ALIGN_32BIT 0x1 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 4 (addr & 0x1 == 0)
#define ALIGN_64BIT 0x3 ///< Âûðàâíèâàíèå: àäðåñ äîëæåí áûòü êðàòåí 8 (addr & 0x3 == 0)
#define ALIGN_FLOAT ALIGN_32BIT
#endif //STM32/TMS32
#if !defined(uint8_t)
typedef unsigned char uint8_t;
#endif
#if !defined(int8_t)
typedef signed char int8_t;
#endif
#if !defined(NULL)
#define NULL 0
#endif
#if !defined(NULL)
#define NULL 0
#endif
/** /**
* @brief Òèï äàííûõ, íà êîòîðûé óêàçûâàåò óêàçàòåëü ïåðåìåííîé îòëàäêè. * @brief Òèï äàííûõ, íà êîòîðûé óêàçûâàåò óêàçàòåëü ïåðåìåííîé îòëàäêè.
@ -17,7 +58,7 @@ typedef enum
pt_uint16, // unsigned int pt_uint16, // unsigned int
pt_uint32, // unsigned long pt_uint32, // unsigned long
pt_uint64, // unsigned long pt_uint64, // unsigned long
pt_float, // float pt_float, // floatf
pt_struct, // struct pt_struct, // struct
pt_union, // struct pt_union, // struct
// pt_ptr_int8, // signed char* // pt_ptr_int8, // signed char*
@ -80,22 +121,24 @@ typedef char DebugVarName_t[11]; ///<
*/ */
typedef struct typedef struct
{ {
char* Ptr; ///< Óêàçàòåëü íà çíà÷åíèå ïåðåìåííîé uint8_t* Ptr; ///< Óêàçàòåëü íà çíà÷åíèå ïåðåìåííîé
DebugVarPtrType_t ptr_type; ///< Òèï çíà÷åíèÿ DebugVarPtrType_t ptr_type; ///< Òèï çíà÷åíèÿ
DebugVarIQType_t iq_type; ///< Òèï IQ ïåðåìåííîé (åñëè åñòü) DebugVarIQType_t iq_type; ///< Òèï IQ ïåðåìåííîé (åñëè åñòü)
DebugVarIQType_t return_type;///< Òèï IQ âîçâðàùàåìîãî çíà÷åíèÿ DebugVarIQType_t return_type;///< Òèï IQ âîçâðàùàåìîãî çíà÷åíèÿ
DebugVarName_t name; ///< Èìÿ ïåðåìåííîé DebugVarName_t name; ///< Èìÿ ïåðåìåííîé
} DebugVar_t; } DebugVar_t;
typedef long DebugValue_t;
/** /**
* @brief Ñòðóêòóðà äàòû è âðåìåíè. * @brief Ñòðóêòóðà äàòû è âðåìåíè.
*/ */
typedef struct { typedef struct {
int year; ///< Ãîä (íàïðèìåð, 2025) uint16_t year; ///< Ãîä (íàïðèìåð, 2025)
char month; ///< Ìåñÿö (1-12) uint8_t month; ///< Ìåñÿö (1-12)
char day; ///< Äåíü (1-31) uint8_t day; ///< Äåíü (1-31)
char hour; ///< ×àñû (0-23) uint8_t hour; ///< ×àñû (0-23)
char minute; ///< Ìèíóòû (0-59) uint8_t minute; ///< Ìèíóòû (0-59)
} DateTime_t; } DateTime_t;
/** /**
@ -126,12 +169,12 @@ extern DebugVar_t dbg_vars[]; ///<
void Debug_Test_Example(void); void Debug_Test_Example(void);
/* ×èòàåò çíà÷åíèå ïåðåìåííîé ïî èíäåêñó */ /* ×èòàåò çíà÷åíèå ïåðåìåííîé ïî èíäåêñó */
int Debug_ReadVar(int var_ind, long *return_long); int Debug_ReadVar(int var_ind, int32_t *return_long);
/* ×èòàåò èìÿ ïåðåìåííîé ïî èíäåêñó */ /* ×èòàåò èìÿ ïåðåìåííîé ïî èíäåêñó */
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr); int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr);
/* ×èòàåò çíà÷åíèå ïåðåìåííîé ñ íèæíåãî óðîâíÿ */ /* ×èòàåò çíà÷åíèå ïåðåìåííîé ñ íèæíåãî óðîâíÿ */
int Debug_LowLevel_ReadVar(long *return_long); int Debug_LowLevel_ReadVar(int32_t *return_long);
/* Èíèöèàëèçèðóåò îòëàäêó íèæíåãî óðîâíÿ */ /* Èíèöèàëèçèðóåò îòëàäêó íèæíåãî óðîâíÿ */
int Debug_LowLevel_Initialize(const char* external_date); int Debug_LowLevel_Initialize(DateTime_t *external_date);
#endif //DEBUG_TOOLS #endif //DEBUG_TOOLS