chore: refine project documentation

This commit is contained in:
2026-08-25 22:44:36 +03:00
parent 8237f03930
commit 98d90e1e5a
45 changed files with 457 additions and 516 deletions
+11 -18
View File
@@ -20,7 +20,7 @@
unit TCIProtocol;
{
TCIProtocol.pas — протокол TCI 2.0 (Expert Electronics), чистый слой.
TCIProtocol.pas — протокол TCI 2.0, чистый слой.
Только разбор/сборка строк и словари протокола: ни сокетов, ни контроллера.
Роль та же, что у CATEngine в CAT-подсистеме, но парсер тут тривиальный, и
@@ -34,7 +34,7 @@ unit TCIProtocol;
Зарезервированные символы: ':' ',' ';' — внутри аргументов запрещены и
заменяются на '^' '~' '*' (§3.2.1), обратная подстановка — TCIUnescape.
Регистр значения не имеет. ExpertSDR3 шлёт всё в нижнем регистре, и часть
Регистр значения не имеет. TCI шлёт всё в нижнем регистре, и часть
клиентов сравнивает строки как есть — поэтому наружу тоже пишем строчными,
а внутрь принимаем любой.
}
@@ -52,17 +52,17 @@ uses
const
TCI_VERSION = '2.0'; // версия протокола, отдаётся в PROTOCOL
TCI_APP_NAME = 'EWSDR';
TCI_DEFAULT_PORT = 40001; // порт TCI-сервера ExpertSDR3
TCI_DEFAULT_PORT = 40001; // стандартный порт TCI-сервера
TCI_CHANNELS = 2; // каналов приёма на приёмник (A/B)
// Список видов связи для MODULATIONS_LIST. Первые десять — словарь
// ExpertSDR3 (клиенты сверяются именно с ними), dmr/fmraw — наше
// расширение: протокол расширяемый по замыслу (§1.4).
// Список видов связи для MODULATIONS_LIST. Первые десять — стандартные
// режимы TCI; dmr/fmraw — расширения EWSDR. Протокол допускает расширение
// этого списка (§1.4).
TCI_MODULATIONS = 'am,sam,dsb,lsb,usb,cw,nfm,wfm,digl,digu,dmr,fmraw';
// Границы, оговорённые протоколом (клампим сами — клиент шлёт что угодно).
// Бинарные потоки (§3.4). data[16384] в структуре Stream — это ПОТОЛОК блока,
// а не его размер: больше в один блок не кладут ни ExpertSDR3, ни клиенты.
// а не его размер: больше в один блок не кладут ни TCI, ни клиенты.
TCI_STREAM_DATA_MAX = 16384; // байт данных в блоке
TCI_STREAM_HDR_SIZE = 64; // 16 × uint32
TCI_STREAM_MAX = TCI_STREAM_HDR_SIZE + TCI_STREAM_DATA_MAX;
@@ -164,7 +164,7 @@ function TCISampleTypeByName(const S: string; out T: TTCISampleType): Boolean;
function TCISampleTypeName(T: TTCISampleType): string;
function TCISampleBytes(T: TTCISampleType): Integer;
{ Сколько сэмплов НА КАНАЛ класть в блок по умолчанию (§4.3): у ExpertSDR3
{ Сколько сэмплов НА КАНАЛ класть в блок по умолчанию (§4.3): у TCI
своё число на каждую частоту дискретизации, и все они дают ~42 мс звучания. }
function TCIDefaultAudioSamples(RateHz: Integer): Integer;
@@ -178,22 +178,15 @@ function TCIMaxBlockSamples(T: TTCISampleType; Channels: Integer): Integer;
Для IQ так прямо написано в §3.4 («количество комплексных вычисляется как
Stream.length/Stream.channels»), а для аудио формулировка §4.3 про
AUDIO_STREAM_SAMPLES («arg1 — количество сэмплов, указываемое в поле
Stream.length») однажды уже увела нас в «сэмплы на канал». ★Так делать
нельзя, и вот доказательство из живого клиента — MSHV, network.cpp:
int cr2 = (int)pStream->length*bit_s; // сколько БАЙТ разбирать
for (int i = 0; i < cr2; i+=chan*bit_s) // шаг = кадр всех каналов
...
quint32 cr3 = pStream->length*bit_s; //plength = plength*channels*4-bytes
То есть клиент считает по length число байт блока. Стоит объявить length «на
Stream.length») может быть прочитана как «сэмплы на канал». ★Так делать
нельзя: клиент вычисляет по length число байт блока. Стоит объявить length «на
канал» — и у стерео он разбирает ровно половину блока, а вторую выбрасывает:
звук идёт с дырами в 50%, водопад становится шире и грязнее, FT4/FT8 не
декодируются вовсе. Замерено стендом test/tci/ft4_bench.py: 50% темпа набора
звука и 1649 не до конца разобранных блоков за минуту.
Размер блока при этом остаётся прежним: AUDIO_STREAM_SAMPLES — сэмплы НА
КАНАЛ (2048 при 48 кГц = 42.7 мс, как у ExpertSDR3), и потолок data[16384]
КАНАЛ (2048 при 48 кГц = 42.7 мс), и потолок data[16384]
сходится ровно: 2048 × 2 канала × float32. }
procedure TCIFillHeader(out H: TTCIStreamHeader; Kind: TTCIStreamType;
Rx, RateHz: Integer; T: TTCISampleType; Count, Channels: Integer);