# Логгер запуска и отключения УМП: прошивка Бальзам 166 и SetGUI Текущая логика дискретов описана в [SIFU_START_STOP.md](SIFU_START_STOP.md): CAN-фронты обрабатываются при приёме, импульсы снимаются таймером, STOP имеет приоритет. Формат записи v2 и интерфейс SetGUI сохранены. ## Назначение и работа оператора В SetGUI открыть **periph_28335 → rs232_periph_28335 → Настройки**, выбрать COM, скорость (обычно 115200) и собственный адрес платы `Mode` (для платы нагрузки 5 или 6), затем **Логгер УМП**. Для CAN использовать **can_periph_28335**, выбрать соответствующую плату и **Логгер УМП**. Общий RS-адрес 16 здесь не рекомендуется: ответ содержит собственный адрес, и SetGUI проверяет совпадение адресов. CAN-настройки: [PERIPH28335_CAN.md](PERIPH28335_CAN.md). Перенесён протокол v2 из 167: 40 слов на запись, два банка по 800 записей. Существующий SetGUI понимает эту прошивку без изменений программы. Кнопки записи управляют регистратором; команду запуска УМП подаёт контроллер. 1. **Начать запись** включает только регистратор, не пуск УМП. Период снимков по умолчанию 20 мс, диапазон 1–1000 мс. 2. Флажки выбирают отображаемые сигналы. Аналоги рисуются линиями, дискретные сигналы — отдельными дорожками. Выбор не меняет состав записи на плате: скрытую кривую можно включить после захвата. 3. **Онлайн** подключает график к уже идущей записи, в том числе после восстановления соединения. Тайм-аут не посылает плате команду останова. 4. Фронт `cUMPreset` (бит 6 команды 0x7F) или спад `cUMPstart` (бит 7) запускает фиксацию отключения. Ещё через 1000 тиков таймера / 1 секунду банк становится архивом. Повторные команды внутри этой секунды не продлевают интервал. Другие изменения команд не служат триггером. 5. **Прочитать отключение** загружает архив, не останавливая запись на плате. На время чтения и просмотра архива онлайн-график приостанавливается; вернуться к нему можно кнопкой **Онлайн**. 6. **Остановить и прочитать** останавливает только регистратор и читает текущий банк. При этом существующий архив отключения остаётся доступным. 7. **Сохранить CSV** сохраняет все поля загруженного/онлайн-буфера, включая невидимые кривые, время и код события. История GUI ограничена 800 последними точками; это не непрерывная запись на диск. При разрыве связи журнал на плате продолжает работать. Архив хранится в ОЗУ до следующей фиксации отключения либо перезагрузки/пропадания питания. EEPROM не используется: под отключением в этой задаче понимается команда управляющего контроллера, а не потеря питания. ## Память и точность Использована существующая секция `.logg` по адресу 0x200000: 64000 16-битных слов. Два банка по 800 записей × 40 слов занимают её целиком. Текущий банк кольцевой. При триггере сохраняются последние до 399 записей, добавляется событие отключения, оставшаяся половина банка отведена постинтервалу. При 20 мс это до примерно 8 секунд до отключения и 1 секунды после. Дополнительные события CAN и дискретов сокращают временную глубину. При интенсивном потоке событий или периоде 1 мс постинтервал может заполнить свои места раньше секунды. Последнее место зарезервировано под конечный снимок; он помечается `event & 0x200`, и GUI сообщает об усечении. Событие отключения и предыстория при этом не вытесняются. Время — 32-битный счётчик миллисекунд записи. Он идёт только при включённом регистраторе и не является абсолютным временем. События в одном тике имеют одинаковую отметку; порядок сохраняется порядком записей. На перезапуске регистратора счётчик продолжает прежнюю шкалу, при перезагрузке платы — 0. Онлайн-опрос возвращает три последних записи каждые 40 мс. Он не гарантирует передачу каждого события при высоком CAN-трафике, медленном UART или паузах GUI. Номера записей позволяют убрать дубликаты и явно показать пропуски. Полный сохранившийся фрагмент следует читать кнопкой архива. Частота 20 мс выбрана с учётом размера кадра; на низких скоростях нужна большая пауза снимков и подходящий тайм-аут RS. Все писатели и чтение одного Modbus-блока используют короткие критические секции с восстановлением прежнего состояния IRQ. Внутри нет ожидания UART, EEPROM, выделения памяти или копирования целого банка. Реальную задержку прерываний и длительность критических секций нужно измерить на F28335. ## Состав записи: 40 слов | Слова | Данные | Единицы/смысл | |---|---|---| | 0–1 | Время, младшее/старшее слово | мс записи | | 2 | Событие | 1 период, 2 CAN RX, 3 изменение I/O, 4 RS-команда, 5 конец постинтервала | | 2, бит 8 | Триггер отключения | флаг поверх причины события | | 2, бит 9 | Усечён постинтервал | установлен в конечном снимке | | 3 | Commands / modbus[0x7F] | все 16 бит, в том числе пуск, сброс, инициализация и калибровка ЦАП | | 4 | Входы OMEGA, Start_1, Res_in | биты 0,1,2, активный уровень приведён к 1 | | 5 | START_DPTB, STOP_DPTB, RES_OUT_2 | биты 0,1,2, активный уровень приведён к 1 | | 6 | IMPowse | остаток импульса, мс | | 7 | WAKEpowse | остаток инициализации, тики DAC_FREQ | | 8 | modbus[0x7B] | 12-битный код, переданный функцией dSEND в ЦАП | | 9 | modbus[0x1C] | расчётное задание в 0.1 мА; GUI/CSV переводит в мА | | 10–13 | sens_data[0..3] | измеренные сигналы, знаковое 16-битное значение в исходном масштабе | | 14–17 | modbus[0..3] | маски ошибок измерений | | 18 | CAN заголовок | адрес регистра в младших 13 битах и маска трёх слов в старших | | 19–21 | Три слова последнего принятого CAN-кадра | без преобразования | | 22 | Счётчик записанных CAN RX | младшие 16 бит | | 23 | CanTimeOutErrorTR | младшие 16 бит счётчика тайм-аутов CAN TX | | 24–25 | Фиксированные границы разгона 166 | 6 и 16 мА; это не регистры настройки | | 26–28 | DAC_min(), DAC_max(), DAC_cal() | коды калибровки и ручного задания ЦАП | | 29–30 | DAC_04, DAC_20 | значения соответствующих регистров | | 31–32 | count_load, time_dac | положение и длительность разгона в тиках | | 33–34 | Эффективные границы разгона 166 | 60 и 160 в 0.1 мА; GUI показывает 6 и 16 мА | | 35 | kod | целочисленное положение, используемое Anal_output | | 36–39 | adc_table_lem[0..3] | ADCRESULT2..5 после сдвига на 4, диапазон 0..4095 | **Отправленный код ЦАП не является измеренным током выхода.** В этом проекте не установлено, какой вход аппаратно измеряет ток ЦАП. При включённом `cCalibrDac` отправляется `DAC_cal()`, а расчётное задание 0x1C остаётся результатом алгоритма разгона. Для диагностики это различие сохранено. В 166 каналы «АЦП 0..3» берутся из `adc_table_lem`, обновляемой в режиме нагрузки. Таблица `adc_table_tpl` в этом режиме не обновляется и не используется. Управляющая формула 166 сохранена: `sinus = 10/16 * count_load + 2/16 * time_dac`. Регулируемый разгон и ограничители 167 не переносились. Поля границ показывают фиксированные 6..16 мА; записи в регистры 0x50/0x51 или 0x64/0x65 их не меняют. `READY` в 166 — обратный счётчик начальной задержки: запись разрешена при `READY == 0`. Это противоположно флагу готовности 167 и учтено при переносе. ## Протокол расширения Modbus Технологические адреса 0..127 сохранены. Новая область использует полный 16-битный адрес; исходная реализация игнорировала старший байт. Сначала GUI читает 16 слов 0x1000 и проверяет сигнатуру, версию, размер записи и тип платы. До успешной проверки расширенные записи запрещены. Обычный ответ расширения не содержит исторических хвостовых нулей. Между ответом и следующим запросом GUI выдерживает паузу RTU. FC03, 0x1000, 16 слов: | Смещение | Значение | |---|---| | 0,1 | 0x554D, версия 2 | | 2,3 | состояние и число записей выбранного источника | | 4,5 | 40 слов в записи, 800 записей в банке | | 6 | период периодических снимков, мс | | 7,8 | счётчик времени, младшее/старшее слово | | 9,10 | Desk (требуется 6 / dsk_LOAD), Mode | | 11 | частота временной базы, 1000 Гц | | 12 | поколение архива, mod 65536 | | 13 | число записей архива | | 14 | оставшиеся миллисекунды постинтервала | | 15 | состояние текущего регистратора независимо от выбора источника | Состояния: 0 — ещё не запущен, 1 — запись, 3 — остановлен/архив. FC06: - 0x1000: 1 — новый текущий журнал, 0 — остановить его; - 0x1001: период 1..1000, менять только при остановленном журнале; - 0x1002: хронологический индекс первой записи окна 0..799; - 0x1003: источник окна, 0 — текущий остановленный банк, 1 — архив отключения. FC03, 0x1010, до 120 слов: окно до трёх записей от установленного индекса. Чтение текущего банка этим окном во время записи не выдаёт изменяющиеся данные. GUI сначала останавливает его; архив можно читать при работающем текущем банке. После всех блоков GUI повторно проверяет поколение архива; при замене во время чтения результат не подменяет предыдущий график. FC03, 0x1100, ровно 124 слова: онлайн-блок. Слова 0,1 — 32-битный номер первой записи, 2 — число записей 0..3, 3 — поколение архива, далее до трёх записей по 40 слов. Неиспользованные слова равны нулю. Окно онлайн не зависит от курсора/выбора архива. Разделение 0x1010 и 0x1100 предотвращает пересечение двух окон. Недопустимые диапазоны и значения возвращают исключения Modbus 2/3. CRC и разбор стандартного ответа GUI используют существующее общее ядро. Расширение описано отдельно в core/ump_logger.py, без изменения общей библиотеки и без необходимости пересобирать её DLL. ## Проверка и запуск Перенесены регистратор и RS/CAN-доступ из коммитов 167 `df71922` и `a3633d8`. Сборка всех 27 C/ASM-файлов и линковка TI C2000 22.6.1.LTS (Debug, COFF, FPU32, O1) прошли. Остались шесть прежних предупреждений в measure.c/peripher.c. В MAP: RAML0 занято 0x38D1 из 0x4000 слов, .ebss — 0xFA9 из 0x3000, .stack — 0x3F0 слов, .logg — 0xFA00 слов во внешней RAM ZONE7A. Это проверка размещения, не измерение максимального использования стека. Сборка проверки лежит вне репозитория, штатные файлы Bin не заменены. Host-тест компилирует настоящий log_to_mem.c с подменой GPIO/IRQ. Проверяет кольцо, архив, переполнение постинтервала, онлайн-окно, CAN-протокол, готовность именно 166, фиксированные границы и четыре канала АЦП. Запуск из корня 166: `py -3 tests/ump_logger/run_test.py` (Clang/lld или MSVC в PATH); при необходимости передать `--compiler "полный путь к cl.exe"`. Тест не проверяет физические GPIO, тайминги прерываний и 16-битную ABI TI. Для устройства собрать Debug в CCS и загрузить прошивку. На стенде: начать запись → подать CAN-пуск → подать отключение → через секунду прочитать архив. Сверить START/STOP с физическими выходами и измерениями, повторить с разрывом RS/CAN. Проверить период 1 мс и задержки IRQ под нагрузкой. Тесты существующего SetGUI (`test_ump_logger.py`, `test_ump_logger_can.py`, `test_periph28335_tab.py`) в окружении Qt 5: **47 passed**. Проверены протокол, онлайн/архив, CAN-фрагменты, графики, курсоры и CSV. Проверка на устройстве не выполнялась.