From 9eab1f32c499e544e1aa2f2e351cc071aaa7644c Mon Sep 17 00:00:00 2001 From: Maxim Date: Fri, 10 Jul 2026 15:26:14 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0.=20=D0=9F=D0=BE=D0=BC=D0=B5=D0=BD=D1=8F=D0=BB=20?= =?UTF-8?q?=D1=87=D0=B0=D1=81=D1=82=D0=BE=D1=82=D1=8B=20=D0=B8=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=20FIR-=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80,=20=D0=B5?= =?UTF-8?q?=D0=B3=D0=BE=20=D1=88=D1=82=D0=B0=D1=82=D0=BD=D0=BE=20=D0=B3?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D1=80=D0=B8=D1=80=D1=83=D0=B5=D1=82=20=D0=B8?= =?UTF-8?q?=20=D0=B3=D1=80=D1=83=D0=B7=D0=B8=D1=82=20ad9361=5Fset=5Fbb=5Fr?= =?UTF-8?q?ate()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- makefile | 5 +-- scripts/build_deps.sh | 48 +++++++++++++++++++++++++--- src/common.c | 74 +++++++++++++++++++++---------------------- src/common.h | 18 ++++++----- src/receiver.c | 12 +++++-- src/transmitter.c | 13 ++++++-- 6 files changed, 112 insertions(+), 58 deletions(-) diff --git a/makefile b/makefile index b47e8c5..20b1049 100644 --- a/makefile +++ b/makefile @@ -25,10 +25,10 @@ $(BIN): mkdir -p $(BIN) $(BIN)/transmitter: $(SRC)/transmitter.c $(SRC)/common.c $(SRC)/common.h | $(BIN) - $(CC) $(CFLAGS) $(SRC)/transmitter.c $(SRC)/common.c -o $@ $(LDFLAGS) -liio $(LDLIBS) + $(CC) $(CFLAGS) $(SRC)/transmitter.c $(SRC)/common.c -o $@ $(LDFLAGS) -lad9361 -liio $(LDLIBS) $(BIN)/receiver: $(SRC)/receiver.c $(SRC)/common.c $(SRC)/common.h | $(BIN) - $(CC) $(CFLAGS) $(SRC)/receiver.c $(SRC)/common.c -o $@ $(LDFLAGS) -liio $(LDLIBS) + $(CC) $(CFLAGS) $(SRC)/receiver.c $(SRC)/common.c -o $@ $(LDFLAGS) -lad9361 -liio $(LDLIBS) $(BIN)/ofdm_bench: $(SRC)/ofdm_bench.c | $(BIN) $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) $(LDLIBS) @@ -49,6 +49,7 @@ check-env: @which $(CC) >/dev/null || { echo "нет $(CC): sudo apt install gcc-arm-linux-gnueabihf"; exit 1; } @test -f $(XARM)/lib/libliquid.a || { echo "нет libliquid.a: запусти scripts/build_deps.sh"; exit 1; } @test -f $(XARM)/lib/libfftw3f.a || { echo "нет libfftw3f.a: запусти scripts/build_deps.sh"; exit 1; } + @test -f $(XARM)/lib/libad9361.a || { echo "нет libad9361.a: запусти scripts/build_deps.sh"; exit 1; } @echo "OK: тулчейн и зависимости на месте" clean: diff --git a/scripts/build_deps.sh b/scripts/build_deps.sh index db03180..f51f22f 100755 --- a/scripts/build_deps.sh +++ b/scripts/build_deps.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # build_deps.sh — кросс-сборка статических armhf-зависимостей в $XARM -# Собирает: FFTW 3.3.10 (single+NEON), liquid-dsp 1.8.0, libiio (local backend) +# Собирает: FFTW 3.3.10 (single+NEON), liquid-dsp 1.8.0, libiio (local backend), +# libad9361-iio (FIR-фильтр для sample rate < 2.083 MSPS) # Запуск: scripts/build_deps.sh (один раз, ~15-20 мин на RPi4) set -euo pipefail source "$(dirname "$0")/../toolchain.env" @@ -50,11 +51,15 @@ else echo "уже собран, пропускаю" fi -echo "=== [3/4] libiio v0.25 (static, только local backend) ===" +echo "=== [3/5] libiio v0.25 (static, только local backend) ===" if [ ! -f "$XARM/lib/libiio.a" ]; then [ -d libiio ] || git clone --depth 1 --branch v0.25 \ https://github.com/analogdevicesinc/libiio.git cd libiio + + # ХАК: Полностью перезаписываем статус Threads, чтобы CMake даже не заходил в модуль проверки + sed -i '/find_package(Threads/c\set(Threads_FOUND ON)\nset(CMAKE_THREAD_LIBS_INIT "-lpthread")\nset(CMAKE_HAVE_PTHREADS_CREATE ON)\nadd_library(Threads::Threads INTERFACE IMPORTED)\nset_property(TARGET Threads::Threads PROPERTY INTERFACE_LINK_LIBRARIES "-lpthread")' CMakeLists.txt + cat > toolchain-armhf.cmake < toolchain-armhf.cmake < #include #include +#include #include // Параметры OFDM-модуляции @@ -27,14 +28,15 @@ #define RS_DATA 223 #define RS_ENC 255 -// Параметры радиотракта по умолчанию -#define DEFAULT_FREQ 1265000000LL -#define DEFAULT_RATE 3840000LL -#define DEFAULT_BW 3000000LL +// Параметры радиотракта по умолчанию (согласовано с CLAUDE.md/README §6) +#define DEFAULT_FREQ 915000000LL +#define DEFAULT_RATE 1920000LL // НЕ поднимать: бюджет CPU +#define DEFAULT_BW 1500000LL -// Адреса PlutoSDR -#define TX_URI_DEFAULT "ip:192.168.3.1" // адрес Pluto передатчика -#define RX_URI_DEFAULT "ip:192.168.2.1" // адрес Pluto приемника +// URI PlutoSDR: код исполняется НА плате → контекст local: +// (сетевой ip: в статических бинарях недоступен — libiio без network backend) +#define TX_URI_DEFAULT "local:" +#define RX_URI_DEFAULT "local:" // Формат заголовка кадра #define HDR_SIGNATURE_0 0xF0 @@ -55,7 +57,7 @@ void print_config(const char *mode, long long freq, long long rate, long long bw, int fec_on); int pluto_init(const char *uri, struct iio_context **ctx, struct iio_device **phy, struct iio_device **dev, int is_tx); -void pluto_configure(struct iio_device *phy, long long freq, long long rate, +int pluto_configure(struct iio_device *phy, long long freq, long long rate, long long bw, double gain, int is_tx); #endif \ No newline at end of file diff --git a/src/receiver.c b/src/receiver.c index 94d6977..9cb47e7 100644 --- a/src/receiver.c +++ b/src/receiver.c @@ -44,7 +44,9 @@ static int callback(unsigned char *hdr, int hdr_valid, if (fec_on && decoder && pay_len >= RS_ENC) { size_t nblocks = pay_len / RS_ENC; - if (nblocks == 0 || nblocks > 100) return 0; + // recovered[4096] вмещает 4096/RS_DATA = 18 блоков. Битый/чужой кадр + // с большим pay_len иначе переполнил бы стек (техдолг #2). + if (nblocks == 0 || nblocks > 4096 / RS_DATA) return 0; uint8_t recovered[4096]; int rs_ok = 1; @@ -115,7 +117,11 @@ int main(int argc, char *argv[]) { struct iio_device *phy = NULL, *rx = NULL; if (pluto_init(uri, &ctx, &phy, &rx, 0) != 0) return 1; - pluto_configure(phy, freq, rate, bw, RX_GAIN, 0); + if (pluto_configure(phy, freq, rate, bw, RX_GAIN, 0) != 0) { + LOG_ERROR("Настройка радиотракта не удалась"); + iio_context_destroy(ctx); + return 1; + } iio_channel_enable(iio_device_find_channel(rx, "voltage0", false)); iio_channel_enable(iio_device_find_channel(rx, "voltage1", false)); @@ -153,6 +159,8 @@ int main(int argc, char *argv[]) { iio_context_destroy(ctx); return 1; } + // Тот же 12-байтовый заголовок, что и на TX (иначе байты 8..11 — мусор) + ofdmflexframesync_set_header_len(fs, HDR_SIZE); fprintf(stderr, "Приёмник готов. Ожидание сигнала...\n\n"); fprintf(stderr, "Кадры | Загол. | CRC | RS испр | Вывод | RSSI | EVM | CFO\n"); diff --git a/src/transmitter.c b/src/transmitter.c index 0a1a22d..7dcb58a 100644 --- a/src/transmitter.c +++ b/src/transmitter.c @@ -1,8 +1,8 @@ /** * transmitter.c — OFDM-передатчик с RS(255,223) FEC для PlutoSDR * - * ОПТИМАЛЬНАЯ КОМАНДА ЗАПУСКА: - * cat test.bin | ./transmitter -f 1265000000 -r 3840000 -b 2000000 -g -20 -a 0.3 -p 0 -c rs8 + * ОПТИМАЛЬНАЯ КОМАНДА ЗАПУСКА (кабель + аттенюатор): + * cat test.bin | ./transmitter -f 915000000 -r 1920000 -b 1500000 -g -40 -a 0.2 -p 0 -c rs8 -u local: */ #include "common.h" @@ -68,7 +68,11 @@ int main(int argc, char *argv[]) { if (pluto_init(uri, &ctx, &phy, &tx, 1) != 0) return 1; // Настройка радиотракта - pluto_configure(phy, freq, rate, bw, gain, 1); + if (pluto_configure(phy, freq, rate, bw, gain, 1) != 0) { + LOG_ERROR("Настройка радиотракта не удалась"); + iio_context_destroy(ctx); + return 1; + } // Включение каналов передатчика iio_channel_enable(iio_device_find_channel(tx, "voltage0", true)); @@ -89,6 +93,9 @@ int main(int argc, char *argv[]) { ofdmflexframegenprops_init_default(&fgp); fgp.check = LIQUID_CRC_32; ofdmflexframegen fg = ofdmflexframegen_create(OFDM_M, OFDM_CP, OFDM_TAPER, NULL, &fgp); + // Наш заголовок 12 Б; по умолчанию liquid шлёт 8 — байты 8..11 (nblocks, + // last_block_bytes) без этого в эфир не уходят. RX выставляет то же. + ofdmflexframegen_set_header_len(fg, HDR_SIZE); // Счётчики статистики uint64_t frames = 0, bytes_tx = 0;