//
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#include "neon_radio_ctrl_impl.hpp"
#include "neon_constants.hpp"
#include <uhd/utils/math.hpp>

/*
 * Neon frequency bands:
 *
 * For RX:
 *     Band   Freq      BSEL-210 BSEL-543         TX/RX                RX2
 *                                         SEL_10   |   FE_SEL_210    SEL_10
 *                                                   chan 1 | chan 2
 *     -------------------------------------------------------------------------
 *     LB_B2: < 450     RF5 100  RF6 101    01       RF3 100  RF1 001   10
 *     LB_B3: 450-700   RF6 101  RF5 100    01       RF3 100  RF1 001   10
 *     LB_B4: 700-1200  RF3 010  RF4 011    01       RF3 100  RF1 001   10
 *     LB_B5: 1200-1800 RF4 011  RF3 010    01       RF3 100  RF1 001   10
 *     LB_B6: 1800-2350 RF1 000  RF2 001    01       RF3 100  RF1 001   10
 *     LB_B7: 2350-2600 RF2 001  RF1 000    01       RF3 100  RF1 001   10
 *     HB:    2600+     --- 111  --- 111    10       RF3 100  RF1 001   01
 *
 *     SEL_1 SEL_0
 *      1    0    ANT1(RX_HB)--TX/RX, ANT2(RX_LB)--RX
 *      0    1    ANT1(RX_HB)--RX, ANT2(RX_LB)--TX/RX
 *
 * For TX:
 *     Band-Freq              BSEL-210 BSEL-543       TX/RX
 *                                                 FE_SEL_210
 *                                               chan 1 | chan 2
 *     ------------------------------------------------------------
 *     LB_80   < 117.7        RF7 011  RF8 111   RF1 001   RF3 100
 *     LB_160  117.7-178.2    RF8 111  RF7 011   RF1 001   RF3 100
 *     LB_225  178.2-284.3    RF5 001  RF6 101   RF1 001   RF3 100
 *     LB_400  284.3-453.7    RF6 101  RF5 001   RF1 001   RF3 100
 *     LB_575  453.7-723.8    RF3 010  RF4 110   RF1 001   RF3 100
 *     LB_1000 723.8-1154.9   RF4 110  RF3 010   RF1 001   RF3 100
 *     LB_1700 1154.9-1842.6  RF1 000  RF2 100   RF1 001   RF3 100
 *     LB_2750 1842.6-2940.0  RF2 100  RF1 000   RF1 001   RF3 100
 *     HB_5850 > 2490.0       --- ---  --- ---   RF2 010   RF2 010
 *
 */

using namespace uhd;
using namespace uhd::usrp;
using namespace uhd::rfnoc;
using namespace uhd::math::fp_compare;

namespace {
    /* Note on the RX filter bank:
     *
     * The RX path has 7 bands, which we call LB_B2, B3, .. HB same as
     * the schematic.
     *
     * The following constants define lower cutoff frequencies for each band.
     * LB_B2 does not have a lower cutoff frequency, it is implied by
     * AD9361_MIN_FREQ. NEON_RX_BAND1_MIN_FREQ is the cutover frequency
     * for switching from LB_B2 to LB_B3, and so on.
     *
     * Bands 1-6 have both high- and low-pass filters (effectively band
     * passes). Frequencies need to be chosen to allow as much of the full
     * bandwidth through unattenuated.
     */
    constexpr double NEON_RX_LB_BAND3_MIN_FREQ = 450e6;
    constexpr double NEON_RX_LB_BAND4_MIN_FREQ = 700e6;
    constexpr double NEON_RX_LB_BAND5_MIN_FREQ = 1200e6;
    constexpr double NEON_RX_LB_BAND6_MIN_FREQ = 1800e6;
    constexpr double NEON_RX_LB_BAND7_MIN_FREQ = 2350e6;
    constexpr double NEON_RX_HB_MIN_FREQ = 2600e6;

    /* Note on the TX filter bank:
     *
     * The TX path has 9 bands, which we name according to the schematic.
     *
     * The following constants define lower cutoff frequencies for each band.
     * LB_80 does not have a lower cutoff frequency, it is implied by
     * AD9361_MIN_FREQ. NEON_TX_LB_160_MIN_FREQ is the cutover frequency
     * for switching from LB_80 to LB_160, and so on.
     *
     * On current Neon revisions, all filters on the TX filter bank are
     * low pass filters (no high pass filters).
     * Frequencies need to be chosen to allow as much of the full bandwidth
     * through unattenuated (so don't go all the way up to the cutoff frequency
     * of that filter).
     */
    constexpr double NEON_TX_LB_160_MIN_FREQ = 117.7e6;
    constexpr double NEON_TX_LB_225_MIN_FREQ = 178.2e6;
    constexpr double NEON_TX_LB_400_MIN_FREQ = 284.3e6;
    constexpr double NEON_TX_LB_575_MIN_FREQ = 453.7e6;
    constexpr double NEON_TX_LB_1000_MIN_FREQ = 723.8e6;
    constexpr double NEON_TX_LB_1700_MIN_FREQ = 1154.9e6;
    constexpr double NEON_TX_LB_2750_MIN_FREQ = 1842.6e6;
    constexpr double NEON_TX_HB_MIN_FREQ = 2940.0e6;
}

neon_radio_ctrl_impl::rx_band
neon_radio_ctrl_impl::_map_freq_to_rx_band(const double freq) {
    neon_radio_ctrl_impl::rx_band band;

    if (fp_compare_epsilon<double>(freq) < AD9361_RX_MIN_FREQ) {
        band = rx_band::INVALID_BAND;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND3_MIN_FREQ) {
        band = rx_band::LB_B2;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND4_MIN_FREQ) {
        band = rx_band::LB_B3;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND5_MIN_FREQ) {
        band = rx_band::LB_B4;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND6_MIN_FREQ) {
        band = rx_band::LB_B5;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_LB_BAND7_MIN_FREQ) {
        band = rx_band::LB_B6;
    } else if (fp_compare_epsilon<double>(freq) < NEON_RX_HB_MIN_FREQ) {
        band = rx_band::LB_B7;
    } else if (fp_compare_epsilon<double>(freq) <= AD9361_RX_MAX_FREQ) {
        band = rx_band::HB;
    } else {
        band = rx_band::INVALID_BAND;
    }

    return band;
}

neon_radio_ctrl_impl::tx_band
neon_radio_ctrl_impl::_map_freq_to_tx_band(const double freq) {
    neon_radio_ctrl_impl::tx_band band;

    if (fp_compare_epsilon<double>(freq) < AD9361_TX_MIN_FREQ) {
        band = tx_band::INVALID_BAND;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_160_MIN_FREQ) {
        band = tx_band::LB_80;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_225_MIN_FREQ) {
        band = tx_band::LB_160;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_400_MIN_FREQ) {
        band = tx_band::LB_225;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_575_MIN_FREQ) {
        band = tx_band::LB_400;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_1000_MIN_FREQ) {
        band = tx_band::LB_575;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_1700_MIN_FREQ) {
        band = tx_band::LB_1000;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_LB_2750_MIN_FREQ) {
        band = tx_band::LB_1700;
    } else if (fp_compare_epsilon<double>(freq) < NEON_TX_HB_MIN_FREQ) {
        band = tx_band::LB_2750;
    } else if (fp_compare_epsilon<double>(freq) <= AD9361_TX_MAX_FREQ) {
        band = tx_band::HB;
    } else {
        band = tx_band::INVALID_BAND;
    }

    return band;
}

