No description
  • C 91.4%
  • C++ 5.3%
  • Python 2.8%
  • CMake 0.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
PazdnikOFF e6f537b42d api: класс Tvp5150 + README/CLAUDE + быстрый захват (минимальный перебор)
- Tvp5150.hpp: полноценный C++-класс (конструктор-инициализатор, capture,
  доступ к кадру в PSRAM data/width/height/size/frame, copyTo, scaleToWidth/scale,
  release, ok/hasFrame/standard/detectStandard). Только TVP5150/захват, без UART.
- логику захвата не меняли — класс оборачивает C-ядро
- grab_best_field: минимальный перебор (до 3) — первый полный кадр, рваные отсекаются
- TOP_TRIM: фикс. срез верхних VBI-строк (стабильная высота)
- README.md (для людей) + CLAUDE.md (модель интеграции для ИИ)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:37:48 +05:00
.vscode api: класс Tvp5150 + README/CLAUDE + быстрый захват (минимальный перебор) 2026-06-25 14:37:48 +05:00
components api: класс Tvp5150 + README/CLAUDE + быстрый захват (минимальный перебор) 2026-06-25 14:37:48 +05:00
src capture: чистый кадр — bounce-DMA + надёжный yoff + детект синхры по темноте 2026-06-22 17:10:33 +05:00
tools capture: чистый кадр — bounce-DMA + надёжный yoff + детект синхры по темноте 2026-06-22 17:10:33 +05:00
.DS_Store checkpoint: рабочий VH-режим (софт-кроп по дисперсии), читаемый кадр PAL 2026-06-21 19:05:26 +05:00
.gitignore checkpoint: рабочий VH-режим — чистый кадр, VBI-детект + валидация поля 2026-06-22 09:51:09 +05:00
best_width.png capture: чистый кадр — bounce-DMA + надёжный yoff + детект синхры по темноте 2026-06-22 17:10:33 +05:00
CLAUDE.md api: класс Tvp5150 + README/CLAUDE + быстрый захват (минимальный перебор) 2026-06-25 14:37:48 +05:00
CMakeLists.txt fix: remove old i2c driver, use sensor->get_reg() for TVP5150 status polling 2026-06-18 20:02:46 +05:00
final.png capture: чистый кадр — bounce-DMA + надёжный yoff + детект синхры по темноте 2026-06-22 17:10:33 +05:00
ntsc.png checkpoint: рабочий VH-режим (софт-кроп по дисперсии), читаемый кадр PAL 2026-06-21 19:05:26 +05:00
pal.png checkpoint: рабочий VH-режим (софт-кроп по дисперсии), читаемый кадр PAL 2026-06-21 19:05:26 +05:00
partitions.csv fix: xclk_freq_hz=20MHz to avoid div-by-zero in ll_cam_config; remove mem_info sketch 2026-06-18 20:21:31 +05:00
platformio.ini capture: GRAB_LATEST + отбор целого поля + быстрый таймаут 100мс 2026-06-22 12:39:01 +05:00
README.md api: класс Tvp5150 + README/CLAUDE + быстрый захват (минимальный перебор) 2026-06-25 14:37:48 +05:00
sdkconfig.defaults checkpoint: рабочий VH-режим (софт-кроп по дисперсии), читаемый кадр PAL 2026-06-21 19:05:26 +05:00
sdkconfig.mem-info fix: xclk_freq_hz=20MHz to avoid div-by-zero in ll_cam_config; remove mem_info sketch 2026-06-18 20:21:31 +05:00
todo.md initial: cvbs_video component + demo + viewer 2026-06-18 19:44:52 +05:00

tvp5150_cap — захват CVBSвидео на ESP32S3 + TVP5150

Библиотека для оцифровки аналогового видео (композитный сигнал CVBS, PAL/NTSC) на ESP32S3 через декодер TVP5150AM1 и встроенный модуль LCD_CAM. По команде захватывает один кадр, отдаёт его как grayscaleизображение в PSRAM и умеет масштабировать под нужную ширину (например, под термопечатающую головку).

Целевой сценарий: снять кадр с медицинского/промышленного видеовыхода (УЗИ, эндоскоп, камера) по нажатию и подготовить к печати или передаче.


Как это работает

CVBS (аналог) → TVP5150AM1 → DVP 8 бит (D0..D7 + VSYNC + HSYNC + PCLK)
              → LCD_CAM (ESP32S3) → YUV422 в PSRAM → берём Y (яркость) → grayscale
  • TVP5150 декодирует композит в цифровой поток YUV 4:2:2 (27 МГц, 8 бит).
  • LCD_CAM принимает поток в VHрежиме (окно кадра задают HSYNC/VSYNC).
  • DMA пишет во внутреннюю SRAM, затем копируется в PSRAM (bounceрежим — без этого на 27 МГц прямой DMA в PSRAM срывается и нижняя половина кадра идёт шумом).
  • Из YUV берётся только Y (яркость) → 8битный grayscale.
  • Захват выровнен программно: автоопределение фазы Y, детект горизонтальной синхры по тёмной полосе, отсев неполных полей, срез служебных VBIстрок сверху.

Результат: стабильный кадр ~702×572, чистый сверху донизу.


Требования к железу

Сигнал Назначение Пример GPIO
SDA / SCL I2C (SCCB) к TVP5150 1 / 2
VSYNC кадровая синхра 6
HSYNC (HREF) строчная синхра 7
PCLK пиксельный клок 27 МГц 13
D0..D7 данные 15,16,17,18,8,9,10,11
  • Нужен ESP32S3 с PSRAM (octal, 8 МБ) — кадр не влезает во внутреннюю RAM.
  • PCLK = 27 МГц на джамперах склонен звенеть. При «плывущих» строках — последовательный резистор 3347 Ω в разрыв линии PCLK у пина ESP.
  • HSYNC обязателен: без твёрдого HSYNC камера не собирает кадр (таймауты).

Замечание по стандартам. Конкретный протестированный модуль (DL968) устойчиво лочится только в PAL (рег 0x28 = 0x04). NTSC поддержан в коде, но на этом железе декодер в нём не захватывался. Стандарт форсируется в begin().


API (C++)

Класс отвечает только за TVP5150 и захват кадра — никакого UART/USB/сети внутри. Передачу готового кадра (печать/отправка) делает вызывающий код.

#include "Tvp5150.hpp"

Tvp5150::Pins pins = {
    .sda=1, .scl=2, .vsync=6, .href=7, .pclk=13,
    .d0=15,.d1=16,.d2=17,.d3=18,.d4=8,.d5=9,.d6=10,.d7=11,
};

Tvp5150 cam(pins, Tvp5150::Standard::PAL);   // конструктор: I2C + LCD_CAM + буфер PSRAM
if (!cam.ok()) { /* ошибка инициализации */ }

if (cam.capture()) {                          // снять один корректный кадр в PSRAM
    const uint8_t* img = cam.data();          // grayscale 8 бит, cam.width()×cam.height()
    // ... передать img на печать ...
    cam.release();                            // освободить под следующий захват
}

Методы Tvp5150

Метод Назначение
Tvp5150(const Pins&, Standard = PAL) конструктор: инициализация чипа, LCD_CAM, буфер PSRAM
Tvp5150() + begin(pins, std) отложенная инициализация
bool ok() инициализация прошла успешно
bool capture() захватить один корректный кадр в PSRAM; true — готов
bool hasFrame() есть ли валидный захваченный кадр
const uint8_t* data() указатель на grayscaleбуфер в PSRAM
int width() / height() / size_t size() геометрия и размер кадра (байт)
Frame frame() всё разом: .gray .width .height .standard
size_t copyTo(dst, cap) скопировать кадр в свой буфер (своя область PSRAM)
bool scaleToWidth(dst, width, outHeight) масштаб под ширину (термоголовка) с сохранением пропорций
bool scale(dst, w, h) масштаб в произвольный размер
void release() освободить буфер под следующий захват
Standard standard() / detectStandard() активный / определить стандарт

Кадр (data()/frame().gray) принадлежит драйверу и валиден между capture()==true и release(). Нужно хранить дольше — copyTo() в свой буфер.

CAPI

Тот же функционал доступен как plainC (tvp5150_cap.h): tvp5150_init, capture_frame, get_frame_buffer, frame_scale_to_width, release_frame_buffer. Класс — тонкая обёртка над ними.


Подготовка под термопечать

static uint8_t* printBuf;   // ширина_головки * макс_высота, в PSRAM
int printH = 0;
if (cam.capture()) {
    cam.scaleToWidth(printBuf, 1284 /*px головки*/, printH);
    // printBuf[printH][1284] — построчно в термоголовку
    cam.release();
}

Сборка

PlatformIO + ESPIDF. Компонент лежит в components/tvp5150_cap, рядом вшит components/esp32-camera с правками под TVP5150 (дискретная синхра, FRAMESIZE, bounceDMA). Пример использования — src/demo.c.

pio run -t upload          # прошить
pio device monitor         # логи (USBJTAG)

Инструмент tools/cvbs_save.py принимает кадр по UART и сохраняет PNG/RAW (захват по пробелу в окне скрипта или по кнопке BOOT).