Add shared emulator services, waveform generation and STM32 USB boot ports
This commit is contained in:
228
c/set-protocol/docs/EMULATOR_SERVICES.md
Normal file
228
c/set-protocol/docs/EMULATOR_SERVICES.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# Универсальное адресное пространство эмуляторов
|
||||
|
||||
Общий код находится в `templates/c/set-protocol`. Прошивка платы задаёт память,
|
||||
GPIO и аппаратные callbacks; протокол и модели не включают STM32/HAL/USB/ОС,
|
||||
не выделяют heap и не читают системное время. Все вызовы одного экземпляра
|
||||
сериализуются главным циклом или блокировкой вызывающего.
|
||||
|
||||
## Слои и точка расширения
|
||||
|
||||
- `set_regmap.h/.c`: таблица непересекающихся регионов и общий вызов
|
||||
`set_regmap_request(map, function, address, value, out, capacity, &count)`.
|
||||
Function 3 читает `value` слов, function 6 пишет одно слово.
|
||||
- `set_emu_ump`, `set_emu_tms`, `set_emu_igbt`, `set_wavegen`:
|
||||
независимые экземпляры моделей. Callbacks получают **относительный offset**,
|
||||
а не внешний адрес. Один модуль можно разместить несколько раз по разным адресам.
|
||||
- `set_emu_server`: готовая композиция для текущего стенда, режим УМП/2812,
|
||||
подготовка настроек с применением через 500 тиков.
|
||||
- `set_regmap_rtu` и `set_regmap_can`: готовые транспортные кодеки над одной картой.
|
||||
`set_emu_server_rtu/can` дополнительно сохраняют legacy поведение стенда.
|
||||
USB CDC, UART, TCP или иной поток только доставляет полный RTU-кадр.
|
||||
Другой протокол разбирает собственную оболочку и вызывает `set_regmap_request`.
|
||||
|
||||
Вызов с неизвестной функцией возвращает 1; неизвестный адрес, RO-запись,
|
||||
чтение через границу региона — 2; неверное значение или размер буфера — 3;
|
||||
ошибка аппаратного порта — 4; занятый модуль — 6. При ошибке `count=0`.
|
||||
Длина успешного чтения равна запрошенной, запись возвращает адрес/значение.
|
||||
Максимум — 124 слова. RTU-обёртка требует буфер 253 байта до выполнения команды;
|
||||
CAN — 124 слова. Недостаточный буфер не может выполнить запись без ответа.
|
||||
При ошибке содержимое выходного буфера не используется.
|
||||
|
||||
`set_regmap_init` проверяет границы 16-битного пространства, пересечения,
|
||||
права и callbacks. Таблица и состояния принадлежат вызывающему и должны жить
|
||||
дольше карты. После регистрации таблица неизменна; для изменения карты
|
||||
инициализируйте её заново в момент, когда нет обслуживаемых запросов.
|
||||
|
||||
## Каталог и стандартная карта
|
||||
|
||||
Каталог доступен на адресе 0 через любой транспорт.
|
||||
|
||||
| Слово заголовка | Значение |
|
||||
|---|---|
|
||||
| 0 | 0x5345, сигнатура SE |
|
||||
| 1 | версия каталога 1 |
|
||||
| 2 | количество регионов |
|
||||
| 3 | начало дескрипторов: 8 |
|
||||
| 4 | длина дескриптора: 8 |
|
||||
| 5 | максимум слов в одном чтении: 124 |
|
||||
| 6, 7 | резерв: 0 |
|
||||
|
||||
Дескриптор: `kind, version, instance, base, words, flags, 0, 0`.
|
||||
Flags: bit0 чтение, bit1 запись. Права описывают возможности региона;
|
||||
отдельные регистры внутри могут быть только для чтения. Пропуски внутри
|
||||
региона возвращают ошибку, если модуль их не поддерживает.
|
||||
|
||||
| Kind | Стандартный адрес | Размер | Модуль |
|
||||
|---|---|---|---|
|
||||
| 1 | 0x1000 | 0x17C | УМП: статус, окно, онлайн |
|
||||
| 2 | 0x1200 | 36 | управление, конфигурация и indexed capability |
|
||||
| 3 | 0x1300 | 8 | генератор DAC |
|
||||
| 4 | 0x1400 | 112 | IGBT, версия 3 |
|
||||
| 5 | 0x1500 | 80 | 2812 через регистры |
|
||||
| 6 | 0x2000 | capacity × 40 | архив/банк УМП |
|
||||
| 7 | 0xA000 | wave capacity | таблица DAC |
|
||||
|
||||
Эта карта — готовая композиция, а не требование к новым платам.
|
||||
`set_regmap` позволяет выбирать адреса, подмножество и несколько экземпляров
|
||||
модуля; каталог сообщает фактическую карту. Настройка UART и выбор УМП/2812
|
||||
принадлежат только готовому `set_emu_server`. Максимальная ёмкость УМП
|
||||
в этой карте — 819 записей на банк; текущая STM32 использует 800.
|
||||
|
||||
В режиме 2812 прямое обращение к регистрам УМП возвращает busy, legacy
|
||||
RTU/CAN к этим диапазонам игнорируются для совместимости. Остальные сервисы
|
||||
и каталог доступны. Регистры управления 2812 принимают запись только в режиме 2812.
|
||||
Чтение его состояния не запускает модель.
|
||||
|
||||
## IGBT
|
||||
|
||||
Предыдущий локальный диапазон IGBT 0x1300 конфликтовал с DAC. Его alias
|
||||
сохранить нельзя: он обращается к генератору. Используйте каталог kind=4 или
|
||||
новый стандартный адрес 0x1400.
|
||||
|
||||
| Offset | Назначение |
|
||||
|---|---|
|
||||
| 0, 1 | 0x4947, версия 3 |
|
||||
| 2 | enable 0/1; выключение сразу очищает состояние RX и ожидаемые ACK |
|
||||
| 3 | чтение последнего TX; запись подготовленной TX-маски |
|
||||
| 4 | RX-маска |
|
||||
| 5 | резерв 0 |
|
||||
| 6 | FAULT-маска 0…255 |
|
||||
| 7 | задержка ACK 0…1000 мс |
|
||||
| 8 | ширина ACK 1…255 мс |
|
||||
| 9 | счётчик фронтов modulo 65536; запись 0 сбрасывает |
|
||||
| 10 | число каналов 8 |
|
||||
| 11 | один шаг модели = 1 мс |
|
||||
| 12 | источник TX: 0 переданные GPIO, 1 подготовленная маска |
|
||||
| 13 | подготовленная TX-маска, чтение/запись |
|
||||
| 14 | запись маски запуска одиночного TX; чтение 0 |
|
||||
| 15 | длина записи канала: 12 слов |
|
||||
|
||||
Версия 3 сохраняет первые 14 регистров. Общие delay/width при записи
|
||||
устанавливают значения для всех каналов; при чтении показывают последнее
|
||||
общее задание, а не поканальные значения. Полное состояние: FC03 0x1400 / 112 слов.
|
||||
Запуск TX требует enabled=1, source=1, разрешённого TX канала и низкого TX;
|
||||
повторный запуск высокого TX отвергается кодом 6. Длительность отсчитывает
|
||||
сама модель, не клиент COM. Ручная запись TX отменяет все текущие TX-импульсы.
|
||||
Выключение эмуляции отменяет импульсы и сбрасывает их TX; статическое задание
|
||||
TX сохраняется. PB остаются входами: тестовый TX — внутренняя подстановка,
|
||||
физическая обратная связь RX выводится на PC0…PC7.
|
||||
|
||||
Поканальные регистры: `0x1410 + 12 * channel`, channel=0…7.
|
||||
|
||||
| Offset канала | Значение |
|
||||
|---|---|
|
||||
| 0 | flags: bit0 разрешение TX, bit1 разрешение RX, bit2 ACK active-low |
|
||||
| 1 | RX mode: 0 ACK, 1 физический 0, 2 физическая 1, 3 пропуск ACK |
|
||||
| 2, 3 | задержка ACK ON 0…1000 мс, ширина 1…1000 мс |
|
||||
| 4, 5 | задержка ACK OFF 0…1000 мс, ширина 1…1000 мс |
|
||||
| 6 | одиночный TX: 1…60000 мс |
|
||||
| 7 | маска фронтов для ACK: bit0 ON, bit1 OFF |
|
||||
| 8 | ширина FAULT 1…60000 мс; 0 — удержание до снятия FAULT |
|
||||
| 9 | RO счётчик фронтов канала, modulo 65536 |
|
||||
| 10, 11 | RO оставшаяся задержка / длительность ACK в мс |
|
||||
|
||||
Изменение flags/mode отменяет ожидаемый и активный ACK канала.
|
||||
Отключённый RX и выключенная модель всегда дают физический 0.
|
||||
Инверсия применяется к автоматическому ответу и idle при пропуске ACK;
|
||||
ручные уровни 0/1 не инвертируются. Сброс общего счётчика сбрасывает и канальные.
|
||||
FAULT моделирует длинный/удерживаемый ответ после фронта; это не модель Vce,
|
||||
Vge, DESAT, внутренней защиты или блокировки конкретного силового драйвера.
|
||||
|
||||
`set_igbt_tick(state, pins)` получает маску входов от порта платы.
|
||||
Фронт на тике T запускает ACK на T+delay. Повторный фронт до начала ACK
|
||||
перезапускает задержку; это определённая модельная обработка слишком частых команд.
|
||||
Каждый из восьми каналов независим. FAULT удерживает RX после его активации;
|
||||
снятие FAULT освобождает только ранее аварийные каналы и сохраняет обычные ACK.
|
||||
Чтобы TX через регистры не перезаписывался GPIO, выберите source=1.
|
||||
|
||||
**Текущая IGBT-модель имеет шаг 1 мс.** Она проверяет логическую последовательность
|
||||
Vin/Vstat, но не воспроизводит ACK 250/380 нс и ширины профилей 1SP/1SD в DSLogic.
|
||||
Такую аппаратную точность нельзя получить переносом модели или вызовом из SysTick:
|
||||
для неё требуется отдельный быстрый аппаратный порт и соответствующая модель времени.
|
||||
|
||||
## 2812
|
||||
|
||||
Состояние едино для legacy CMD_STD и адресного API:
|
||||
|
||||
| Offset | Назначение |
|
||||
|---|---|
|
||||
| 0, 1 | 0x544D, версия 1 |
|
||||
| 2, 3, 4 | running, частота и задание (int16 ×100 Гц) |
|
||||
| 8…11 | четыре подготовленных analog int16 |
|
||||
| 12…17 | шесть подготовленных управляющих байт (значение 0…255) |
|
||||
| 18 | записать 1: атомарно применить подготовленную команду |
|
||||
| 32…45 | 28 байт дискретов; младший байт слова — первый байт |
|
||||
| 46…79 | 34 аналоговых int16 |
|
||||
| остальные | чтение 0 |
|
||||
|
||||
Модель остаётся упрощённой BALZAM_7: Go, выбор remote, Setspeed,
|
||||
разгон 10 Гц/с и синтетическая телеметрия. Legacy CMD_STD имеет отдельный
|
||||
адрес 2812, запрос 18 и ответ 101 байт, с проверкой CRC до изменения состояния.
|
||||
Буфер ответа менее 101 байта запрещает выполнение команды.
|
||||
|
||||
## УМП и DAC
|
||||
|
||||
УМП сохраняет прежние записи по 40 слов, банк/архив, фронтовой триггер,
|
||||
постинтервал 1000 мс и indexed-чтение без изменения курсора. Два разных
|
||||
буфера по `capacity*40` слов предоставляет плата. Размещение SRAM/CCM
|
||||
не является частью библиотеки.
|
||||
|
||||
DAC использует прежний `set_wave_port` с `start/stop`, транзакционную загрузку,
|
||||
commit, чтение таблицы и запрет изменений при работе. Регистровые callbacks
|
||||
и прежний `set_wave_rtu` вызывают одну реализацию. До повторного init вызывающий
|
||||
останавливает аппаратный вывод; библиотека не угадывает текущее состояние DMA.
|
||||
|
||||
## Обёртки и новая плата
|
||||
|
||||
Пример: [ports/example-emulator/service.c](../ports/example-emulator/service.c).
|
||||
Он регистрирует два экземпляра IGBT и показывает прямой, RTU и CAN вызов.
|
||||
Порт новой платы должен:
|
||||
|
||||
1. Создать состояния и таблицу регионов, вызвать init и проверить результат.
|
||||
2. Предоставить буферы и аппаратный DAC-порт, если нужен генератор.
|
||||
3. Передавать реальные тики и входы; читать результат модели и обновлять GPIO.
|
||||
4. Доставлять запросы через выбранную оболочку в одну карту, сериализуя доступ.
|
||||
|
||||
CAN-envelope совместим с UMP: BE address/value/0x1F00/token/function.
|
||||
Идентификаторы CAN и маршрутизацию задаёт порт. Ответ делится по два слова,
|
||||
нечётное чтение дополняется нулём до чётного числа; клиент отбрасывает последнее
|
||||
слово по длине исходного запроса. Токен 1…255; один незавершённый ответ на соединение.
|
||||
Проверенная копия слов хранится до отправки всех фрагментов.
|
||||
|
||||
`set_emu_stream` — только сборщик известных запросов FC03/FC06 и CMD_STD,
|
||||
по одному экземпляру на поток. Он принимает монотонные uint32 миллисекунды,
|
||||
сохраняет кадр между USB-пакетами, сбрасывает незавершённый после паузы >1000 мс
|
||||
и восстанавливается после плохого CRC. Это не универсальный Modbus-парсер
|
||||
FC16/FC23: для другого формата нужна другая тонкая оболочка.
|
||||
|
||||
## Сборка и проверки
|
||||
|
||||
C99-ядро подключается через `setprotocol_static`/DLL, определения публичного
|
||||
API экспортируются через PCAN_ABI_API. Включить `set_regmap.h` или
|
||||
`set_emu_server.h`. Для иной архитектуры проверить наличие uint8/16/32_t;
|
||||
существующий 16-битный C28x octet-порт UMP остаётся отдельным, этот новый
|
||||
байтовый API пока не проверен TI-компилятором.
|
||||
|
||||
`test_emulator_services.c` проверяет каталог, пересечения, границы и короткие
|
||||
буферы, два экземпляра, переназначение адресов, RTU/CAN/stream, совместное
|
||||
состояние 2812 и DAC, длинные задержки IGBT и освобождение FAULT.
|
||||
Существующие тесты прошивки дополнительно проверяют архив УМП, USB-фрагментацию,
|
||||
смену режима/адресов и совместимость с декодерами SETGUI.
|
||||
|
||||
## Выбор единственного эмулятора
|
||||
|
||||
В SETGUI: «Эмулятор → Настройки STM → Тип эмулятора», затем
|
||||
«Применить в STM и проверить» и «Открыть управление эмулятором».
|
||||
Конфигурация версии 3: режим 0 — УМП, 1 — 2812, 2 — IGBT, 3 — ЦАП.
|
||||
Регистр 0x1219 подготавливает режим; 0x1218 = 0xA55A применяет его через
|
||||
500 мс после подтверждения. Статус FC03 0x1210 / 10 слов содержит версию 3,
|
||||
действующий режим в слове 8 и подготовленный в слове 9.
|
||||
|
||||
При смене режима останавливаются TIM6/DMA/DAC, ЦАП устанавливается в ноль,
|
||||
IGBT отключается и его выходы обнуляются, 2812 сбрасывается, УМП останавливается.
|
||||
Новый режим не запускается автоматически. Для IGBT нужно явно включить
|
||||
эмуляцию; для ЦАП заново загрузить таблицу и дать команду пуска.
|
||||
Повторное применение того же режима не прерывает текущую работу.
|
||||
Записи невыбранным IGBT/ЦАП/2812 отклоняются с кодом 6; чтение статуса
|
||||
и явные команды остановки IGBT/ЦАП доступны. Настройки связи доступны всегда.
|
||||
После сброса выбран УМП, IGBT выключен, ЦАП не запущен.
|
||||
126
c/set-protocol/docs/SIGNAL_GENERATOR.md
Normal file
126
c/set-protocol/docs/SIGNAL_GENERATOR.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# Генератор произвольного сигнала WG v1
|
||||
|
||||
Общее C99-ядро строит кривые по точкам, преобразует напряжения в коды ЦАП и
|
||||
принимает таблицы через RTU поверх USB CDC/COM. Оно не зависит от Qt, HAL или ОС.
|
||||
Память предоставляет вызывающий; скрытого heap и глобального состояния нет.
|
||||
|
||||
```text
|
||||
SETGUI: точки -> Python/ctypes -> set_signal.c -> график / CSV / C
|
||||
-> set_wavegen.c -> USB CDC
|
||||
MCU: USB stream -> set_wave_rtu -> set_wave_port -> TIM6/DMA/DAC
|
||||
```
|
||||
|
||||
| Файл | Зависимости и назначение |
|
||||
|---|---|
|
||||
| `include/set_signal.h`, `src/set_signal.c` | C99/math: МНК 1…5, linear, PCHIP, natural cubic spline, 12-bit DAC |
|
||||
| `include/set_wavegen.h`, `src/set_wavegen.c` | C99 + `set_crc.c`: транзакционная загрузка и wire codec |
|
||||
| `ports/stm32f407-wavegen` | CMSIS F407: PA4/DAC1, TIM6, DMA1 Stream5 Channel7 |
|
||||
| `ports/stm32g474-wavegen` | STM32G4 HAL: готовые DAC/TIM/DMA handles из CubeMX |
|
||||
| `python/set_devices/signal_reconstruction.py`, `waveform.py` | Модели, JSON/экспорт, ctypes; алгоритмов на Python нет |
|
||||
| `python/set_devices/wavegen_protocol.py`, `qt_ports/wavegen.py` | ctypes-кодек и Qt COM worker с проверкой чтением обратно |
|
||||
|
||||
## Интерполяция и таблица
|
||||
|
||||
`set_signal_reconstruct` принимает раздельные X/Y и workspace `14*N+128`
|
||||
элементов double. Сортировка, усреднение одинаковых времён, нормализация,
|
||||
МНК через QR и интерполяция выполняются в C. Максимум 100000 входных/10000
|
||||
выходных точек. Переданный workspace может повторно использоваться.
|
||||
Большие расчёты предназначены для хоста; на MCU можно строить малые таблицы
|
||||
или принимать готовую таблицу без затрат на интерполяцию.
|
||||
|
||||
`endpoint=1` включает последний X (анализ логов); `endpoint=0` строит один
|
||||
период `[0,T)` без дублированного отсчёта стыка. Частота Fs и период T задают
|
||||
целое `N=Fs*T`; для WG максимум N=4096, Fs=1…50000 Гц, один канал, циклический
|
||||
выход. При разных значениях первой и последней точки на стыке будет скачок.
|
||||
Напряжения 0…Vref округляются к ближайшему коду 0…4095; выход за диапазон
|
||||
отклоняется целиком. Это относится и к выбросам сплайна. Vref должен
|
||||
соответствовать фактическому VDDA/VREF+ платы; это не программируемое питание.
|
||||
|
||||
Пример хоста (DLL передаётся через `SETPROTOCOL_LIBRARY`):
|
||||
|
||||
```python
|
||||
from set_devices.waveform import generate, c_header
|
||||
points = [(0, 0), (10, 3.3), (20, 0)]
|
||||
wave = generate(points, sample_rate=10000, vref=3.3, method="linear")
|
||||
assert len(wave.codes) == 200
|
||||
with open("waveform.h", "w", encoding="utf-8") as output:
|
||||
output.write(c_header(wave))
|
||||
```
|
||||
|
||||
## Контракт порта
|
||||
|
||||
`start(context, samples, count, sample_rate)` возвращает 0 при успехе;
|
||||
`stop(context)` синхронно прекращает DMA и устанавливает нулевой выход.
|
||||
Память таблицы принадлежит `set_wave_state`, её нельзя менять до stop.
|
||||
Вызывайте RTU и обслуживание состояния из одного основного потока, не из IRQ.
|
||||
IRQ USB помещает байты в очередь; USB-пакеты не являются границами RTU.
|
||||
|
||||
```c
|
||||
static uint16_t samples[SET_WAVE_MAX]; /* DMA-accessible SRAM, not CCM */
|
||||
static set_wave_state wave;
|
||||
static set_wave_f407 hardware = {72000000};
|
||||
void application_init(void) {
|
||||
set_wave_port port = set_wave_f407_port(&hardware);
|
||||
set_wave_init(&wave, samples, SET_WAVE_MAX, &port);
|
||||
}
|
||||
size_t on_rtu(const uint8_t *frame, size_t n, uint8_t reply[256]) {
|
||||
return set_wave_rtu(&wave, 16, frame, n, reply, 256);
|
||||
}
|
||||
```
|
||||
|
||||
Для F407 DAC_CH1 — PA4, TIM6 TRGO_UPDATE, DMA1 Stream5/Channel7. Порт использует
|
||||
только нижние 16 бит DAC_CR и не меняет канал 2. Таблица лежит в SRAM1/2
|
||||
`0x20000000…0x2001FFFF`, не в CCM. Перед первым отсчётом есть один такт
|
||||
предзагрузки последнего значения предыдущего периода. Для гарантированной
|
||||
целой частоты порт принимает только делители входной частоты TIM6; при
|
||||
72 МГц подходят, например, 100, 1000, 5000, 10000, 20000 Гц.
|
||||
Частоту таймера передавайте с учётом удвоения при делителе APB1 > 1.
|
||||
Ошибку DMA/underrun проверяйте через `set_wave_f407_fault()` и останавливайте
|
||||
состояние. На F407-проекте этот вызов включён в главный цикл.
|
||||
|
||||
Для G474 настройте CubeMX: DAC1 channel1 (PA4), output buffer enabled,
|
||||
TIM6 TRGO_UPDATE, DMA memory-to-peripheral, circular, halfword/halfword,
|
||||
memory increment, запрос `DMA_REQUEST_DAC1_CHANNEL1`; подключите HAL IRQ
|
||||
для выбранного канала DMA и DAC. Передайте handles и timer_hz в
|
||||
`set_wave_g474`. Обработчики ошибок DMA/DAC в приложении должны вызвать stop
|
||||
и сбросить `wave.running/ready`. Порт проверен компиляцией с CubeG4 1.6.1;
|
||||
конкретная плата G474 здесь не прошита.
|
||||
|
||||
## USB / Modbus RTU
|
||||
|
||||
Адрес по умолчанию 16, FC03/FC06, CRC16 Modbus. Максимальный запрос — 8 байт,
|
||||
ответ — 21 байт; существующий потоковый USB RTU parser F407 подходит без
|
||||
изменения формата. Все поля строит/проверяет C-кодек, GUI не пакует байты.
|
||||
|
||||
| Регистр | Значение |
|
||||
|---|---|
|
||||
| `0x1300`, FC03, 8 слов | `0x5747`, версия 1, running, Fs, count, received, ready, capacity |
|
||||
| `0x1302`, FC06 | 0: stop и нулевой выход; 1: start только после commit |
|
||||
| `0x1303`, FC06 | Частота 1…50000; сбрасывает ready |
|
||||
| `0x1304`, FC06 | Начать загрузку, число отсчётов 2…4096; сброс received/ready |
|
||||
| `0xA000+i`, FC06 | Последовательная загрузка отсчёта 0…4095; повтор того же значения допустим |
|
||||
| `0xA000+i`, FC03, 1 слово | Чтение загруженного отсчёта для проверки |
|
||||
| `0x1306`, FC06 | `0xA55A`: commit, только если все отсчёты загружены |
|
||||
|
||||
Во время running разрешены чтение и stop; запись/перезагрузка дают исключение
|
||||
6. Неполная таблица не запускается. Повреждённый CRC и чужой адрес не меняют
|
||||
состояние. При reset ready/running=0, таблица не сохраняется во Flash.
|
||||
Профиль и регистры генератора не являются регистратором УМП или протоколом 2812.
|
||||
|
||||
Хост выполняет probe → stop → Fs → count → samples → readback каждого
|
||||
отсчёта → commit → status. Пуск — отдельная пользовательская команда.
|
||||
После потери USB уже запущенный DAC продолжает автономное воспроизведение;
|
||||
при таймауте состояние неизвестно до повторного status/stop. Одновременно
|
||||
используйте одного клиента, не открывайте этот же COM во вкладке подключения.
|
||||
|
||||
## Потребители и проверки
|
||||
|
||||
- SETGUI: «Логи и графики → Генератор», JSON, CSV и C header.
|
||||
- `home/407vet6_emul_TMS_Periph`: USB CDC и UART, штатный адрес настройки STM,
|
||||
отдельный PA4 DAC выход; HAL/CMSIS и настройки платы остаются в проекте.
|
||||
- G474: переносимый HAL-порт; board init остаётся в целевой прошивке.
|
||||
- `tests/test_signal_wave.c`: C-векторы интерполяции, DAC, CRC, неполной
|
||||
загрузки, readback и блокировки running. Общие байты проверены Python
|
||||
ctypes и фактическим USB stream parser эмулятора.
|
||||
|
||||
Аппаратная проверка амплитуды, периода и формы осциллографом не выполнена.
|
||||
Reference in New Issue
Block a user