/**
 * common.c — Реализация общих функций
 */

#include "common.h"

volatile sig_atomic_t stop = 0;

static void sigint_handler(int s) {
    (void)s;
    stop = 1;
}

void setup_signal_handlers(void) {
    signal(SIGINT, sigint_handler);
    signal(SIGTERM, sigint_handler);
    signal(SIGPIPE, SIG_IGN);
}

void print_usage(const char *prog_name, const char *mode) {
    fprintf(stderr, "═══════════════════════════════════════════════════\n");
    fprintf(stderr, "OFDM %s — PlutoSDR Radio Link\n", mode);
    fprintf(stderr, "═══════════════════════════════════════════════════\n");
    fprintf(stderr, "Использование: %s [ОПЦИИ]\n\n", prog_name);
    fprintf(stderr, "ОБЩИЕ ОПЦИИ:\n");
    fprintf(stderr, "  -f ЧАСТОТА   Частота несущей в Гц (по умолчанию: %lld)\n", DEFAULT_FREQ);
    fprintf(stderr, "  -r СКОРОСТЬ  Частота дискретизации (по умолчанию: %lld)\n", DEFAULT_RATE);
    fprintf(stderr, "  -b ПОЛОСА    Полоса пропускания (по умолчанию: %lld)\n", DEFAULT_BW);
    fprintf(stderr, "  -u URI       URI PlutoSDR\n");
    fprintf(stderr, "  -c РЕЖИМ     FEC: rs8 или none (по умолчанию: rs8)\n");
    fprintf(stderr, "  -h           Показать эту справку\n");
}

void print_config(const char *mode, long long freq, long long rate,
                  long long bw, int fec_on) {
    fprintf(stderr, "═══════════════════════════════════════════════════\n");
    fprintf(stderr, "КОНФИГУРАЦИЯ %s\n", mode);
    fprintf(stderr, "Частота:     %.1f МГц\n", freq / 1e6);
    fprintf(stderr, "Дискрет.:    %.2f МГц\n", rate / 1e6);
    fprintf(stderr, "Полоса:      %.2f МГц\n", bw / 1e6);
    fprintf(stderr, "OFDM:        M=%d, CP=%d, Taper=%d\n", OFDM_M, OFDM_CP, OFDM_TAPER);
    fprintf(stderr, "FEC:         %s\n", fec_on ? "RS(255,223)" : "ОТКЛЮЧЕН");
}

int pluto_init(const char *uri, struct iio_context **ctx,
               struct iio_device **phy, struct iio_device **dev, int is_tx) {
    *ctx = iio_create_context_from_uri(uri);
    if (!*ctx) {
        LOG_ERROR("Не удалось подключиться к PlutoSDR по адресу %s", uri);
        return -1;
    }

    *phy = iio_context_find_device(*ctx, "ad9361-phy");
    *dev = iio_context_find_device(*ctx,
        is_tx ? "cf-ad9361-dds-core-lpc" : "cf-ad9361-lpc");

    if (!*phy || !*dev) {
        LOG_ERROR("Радиоустройства не найдены в контексте");
        iio_context_destroy(*ctx);
        return -1;
    }

    return 0;
}

void pluto_configure(struct iio_device *phy, long long freq, long long rate,
                    long long bw, double gain, int is_tx) {
    if (is_tx) {
        // Настройка передатчика
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "altvoltage1", true),
            "frequency", freq);
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "voltage0", true),
            "sampling_frequency", rate);
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "voltage0", true),
            "rf_bandwidth", bw);
        iio_channel_attr_write(
            iio_device_find_channel(phy, "voltage0", true),
            "rf_port_select", "A");
        iio_channel_attr_write_double(
            iio_device_find_channel(phy, "voltage0", true),
            "hardwaregain", gain);
    } else {
        // Настройка приёмника
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "altvoltage0", true),
            "frequency", freq);
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "voltage0", false),
            "sampling_frequency", rate);
        iio_channel_attr_write_longlong(
            iio_device_find_channel(phy, "voltage0", false),
            "rf_bandwidth", bw);
        iio_channel_attr_write(
            iio_device_find_channel(phy, "voltage0", false),
            "gain_control_mode", "manual");
        iio_channel_attr_write_double(
            iio_device_find_channel(phy, "voltage0", false),
            "hardwaregain", gain);
        iio_channel_attr_write(
            iio_device_find_channel(phy, "voltage0", false),
            "rf_port_select", "A_BALANCED");
    }
}