/**
 * @file comms_sband_intf.c
 *
 * @brief This file has all the function definitions of S-Band driver interfacing functions
 *
 * @copyright Copyright 2023 Antaris, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "exo_common.h"
#include "sdr_common_intf.h"
#include "comms_sband_xlink_api.h"
#include "comms_uhf_rf_cfg.h"
#include "comms_uhf_main.h"
#include "comms_csw.h"
#include "comms_sband_xlink_api.h"
#include "comms_sband_xlink_ss.h"

/** Number of UDP frames transmitted */
extern uint32 PLACE_IN_EXT_RAM_MEM tx_udp_frame;
/** S-band TX configuration */
extern s_comms_xlinks_tx_cfg PLACE_IN_EXT_RAM_MEM iqs_tx_cfg_global;
/** S-band RX configuration */
extern s_comms_xlinks_rx_cfg PLACE_IN_EXT_RAM_MEM iqs_rx_cfg_global;
/** UHF TX configuration from NVM */
extern s_uhf_rf_tx_cfg PLACE_IN_EXT_RAM_MEM uhf_nvm_tx_cfg;
/** UHF RX configuration from NVM */ 
extern s_uhf_rf_rx_cfg PLACE_IN_EXT_RAM_MEM uhf_nvm_rx_cfg;
/** UHF TX packet configuration from NVM */
extern s_uhf_rf_tx_pkt_cfg PLACE_IN_EXT_RAM_MEM uhf_nvm_tx_pkt_cfg;
/** UHF RX packet configuration from NVM */
extern s_uhf_rf_rx_pkt_cfg PLACE_IN_EXT_RAM_MEM uhf_nvm_rx_pkt_cfg;
/** S-band service housekeeping */
extern SERVICE_HOUSE_KEEP_STRUCT PLACE_IN_EXT_RAM_MEM sband_serv_house_keep;
/** S-band service device configuration */
extern SERVICE_DEVICE_CONF_STRUCT PLACE_IN_EXT_RAM_MEM sband_serv_device_conf;
/** UHF telemetry properties */
s_comms_uhf_tm_prop PLACE_IN_EXT_RAM_MEM comms_uhf_tm;

/**
 * @brief Get RSSI value 0 for radio  
 * @param radio_id Radio ID
 * @return uint8_t RSSI value 0
*/
uint8_t sdr_get_rssi0(uint8_t radio_id)
{
    uint8_t rssi = 0;
    float act_rssi = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                act_rssi = comms_xlink_s_get_rssi(0);

                rssi = comms_rssi_map(act_rssi);
            }
            break;

        case COMMS_UHF:
            {
                act_rssi = comms_uhf_tm.last_rssi;

                rssi = comms_rssi_map(act_rssi);
            }
            break;
    }
    return rssi;
}

/**  
 * @brief Get RSSI value 1 for radio
 * @param radio_id Radio ID  
 * @return uint8_t RSSI value 1
*/
uint8_t sdr_get_rssi1(uint8_t radio_id)
{
    uint8_t rssi = 0;
    float act_rssi =0;

    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                act_rssi = comms_xlink_s_get_rssi(1);

                rssi = comms_rssi_map(act_rssi);
            }
            break;
        case COMMS_UHF:
            {
                /**NA */
            }
            break;
    }
    return rssi;
}

/**
 * @brief Get RX error count for radio 
 * @param radio_id Radio ID
 * @return uint32_t RX error count  
*/
uint32_t sdr_get_rx_err_cnt(uint8_t radio_id)
{
    uint32_t rx_err_cnt = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                rx_err_cnt = sband_serv_house_keep.HouseKeep.RcvInfCh[0].BchErrCount +\
                             sband_serv_house_keep.HouseKeep.RcvInfCh[1].BchErrCount;
            }
            break;

        case COMMS_UHF:
            {
                rx_err_cnt = comms_uhf_tm.packets_rejected_checksum + \
                             comms_uhf_tm.packets_rejected_reserved + \
                             comms_uhf_tm.packets_rejected_other;
            }
            break;
    }
    return rx_err_cnt;
}

/**
 * @brief Get TX frame count for radio
 * @param radio_id Radio ID
 * @return uint32_t TX frame count
*/
uint32_t sdr_get_tx_frm_cnt(uint8_t radio_id)
{
    uint32_t tx_frm_cnt = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                tx_frm_cnt = tx_udp_frame;
            }
            break;

        case COMMS_UHF:
            {
                tx_frm_cnt = comms_uhf_tm.packets_sent;
            }
            break;
    }
    return tx_frm_cnt;
}

/**
 * @brief Get RX frequency for radio 
 * @param radio_id Radio ID 
 * @return uint32_t RX frequency
*/ 
uint32_t sdr_get_rx_freq(uint8_t radio_id)
{
    uint32_t rx_freq = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                rx_freq = iqs_rx_cfg_global.rx_freq;
            }
            break;
        case COMMS_UHF:
            {
                rx_freq = uhf_nvm_rx_cfg.base_freq;
            }
            break;
    }
    return rx_freq;
}

/**
 * @brief Get modulation type for radio
 * @param radio_id Radio ID
 * @return uint8_t Modulation type 
*/
uint8_t sdr_get_mod(uint8_t radio_id)
{
    uint8_t mod = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                mod = iqs_tx_cfg_global.tx_type;
            }
            break;
        case COMMS_UHF:
            {
                mod = SDR_UHF_2_FSK; /*TODO: update based on configuration */
            }
            break;
    }
    return mod;
}

/**
 * @brief Get roll-off factor for radio
 * @param radio_id Radio ID
 * @return uint8_t Roll-off factor
*/
uint8_t sdr_get_roll_off(uint8_t radio_id)
{
    uint8_t roll_off = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                roll_off = SDR_ROLL_OFF_0p25;
            }
            break;
        case COMMS_UHF:
            {
                roll_off = SDR_ROLL_OFF_0;
            }
            break;
    }
    return roll_off;
}


/**
 * @brief Get symbol frequency for radio
 * @param radio_id Radio ID
 * @return uint8_t Symbol frequency
*/ 
uint8_t sdr_get_symb_freq(uint8_t radio_id)
{
    uint8_t symb_freq = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                symb_freq |= (comms_sband_get_sym_freq_map(sband_serv_device_conf.SymbFreq.RcvSymbFreq) & 0x0F) ;
                symb_freq |= ((comms_sband_get_sym_freq_map(sband_serv_device_conf.SymbFreq.XmtSymbFreq) << 4) & 0xF0) ;
            }
            break;
        case COMMS_UHF:
            {
                symb_freq = SDR_SYM_8_KSPS;
            }
            break;
    }
    return symb_freq;
}

/**
 * @brief Get CC enable status for radio
 * @param radio_id Radio ID
 * @return uint8_t CC enable status
*/
uint8_t sdr_get_cc_enb(uint8_t radio_id)
{
    uint8_t cc_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                cc_enb = iqs_rx_cfg_global.rx_cc;
            }
            break;
        case COMMS_UHF:
            {
                cc_enb |= (uhf_nvm_rx_cfg.fec_enb&0x01);
                cc_enb |= (uhf_nvm_tx_cfg.fec_enb<<1)&0x02;
            }
            break;
    }
    return cc_enb;
}

/**
 * @brief Get randomizer enable for radio
 * @param radio_id Radio ID 
 * @return uint8_t Randomizer enable status  
*/
uint8_t sdr_get_rand_enb(uint8_t radio_id)
{
    uint8_t rand_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                rand_enb = iqs_rx_cfg_global.rx_rand;
            }
            break;
        case COMMS_UHF:
            {
                rand_enb = (uhf_nvm_rx_pkt_cfg.whitening_enb &0x01);
                rand_enb = (uhf_nvm_tx_pkt_cfg.whitening_enb << 1)&0x02;
            }
            break;
    }
    return rand_enb;
}

/**
 * @brief Get CRC enable for radio
 * @param radio_id Radio ID
 * @return uint8_t CRC enable status
*/
uint8_t sdr_get_crc_enb(uint8_t radio_id)
{
    uint8_t crc_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                crc_enb = iqs_rx_cfg_global.rx_crc;
            }
            break;
        case COMMS_UHF:
            {
                crc_enb = (uhf_nvm_rx_pkt_cfg.crc_enb &0x01);
                crc_enb = (uhf_nvm_tx_pkt_cfg.crc_enb << 1)&0x02;
            }
            break;
    }
    return crc_enb;
}

/**
 * @brief Get Reed-Solomon(rs) enable for radio
 * @param radio_id Radio ID
 * @return uint8_t Reed-Solomon enable status  
*/
uint8_t sdr_get_rs_enb(uint8_t radio_id)
{
    uint8_t rs_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                rs_enb = iqs_rx_cfg_global.rx_rs;
            }
            break;
        case COMMS_UHF:
            {
                /**NA */
            }
            break;
    }
    return rs_enb;
}


/**
 * @brief Get DC filter enable for radio
 * @param radio_id Radio ID
 * @return uint8_t DC filter enable status
*/ 
uint8_t sdr_get_dc_filter_enb(uint8_t radio_id)
{
    uint8_t dc_filter_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                /**NA */
            }
            break;
        case COMMS_UHF:
            {
                dc_filter_enb = (uhf_nvm_rx_cfg.enb_dc_filter &0x01);
                dc_filter_enb = (uhf_nvm_tx_cfg.enb_dc_filter << 1)&0x02;
            }
            break;
    }
    return dc_filter_enb;
}


/**
 * @brief Get Manchester encoding enable for radio
 * @param radio_id Radio ID
 * @return uint8_t Manchester enable status
*/
uint8_t sdr_get_manchester_enb(uint8_t radio_id)
{
    uint8_t manchester_enb = 0;
    switch(radio_id)
    {
        case COMMS_SBAND_IQS:
            {
                /**NA */
            }
            break;
        case COMMS_UHF:
            {
                 manchester_enb = (uhf_nvm_rx_cfg.manchester_enable &0x01);
                 manchester_enb = (uhf_nvm_tx_cfg.manchester_enable << 1)&0x02;
            }
            break;
    }
    return manchester_enb;
}

/**
 * @brief Map S-band symbol frequency to parameter
 * @param iqs_sym_freq S-band symbol frequency value 
 * @return uint8_t Mapped parameter value
*/

uint8_t comms_sband_get_sym_freq_map(uint16_t iqs_sym_freq)
{
    uint8_t symb_freq = 0;

    if(iqs_sym_freq == 64)
    {
        symb_freq = SDR_SYM_64_KSPS;
    }
    return symb_freq;
}

/**
 * @brief Map RSSI value to parameter
 * @param act_rssi Actual RSSI value
 * @return uint8_t Mapped parameter value
*/ 
uint8_t comms_rssi_map(float act_rssi)
{
    uint8_t rssi = 0;

    if(act_rssi < -105)
    {
        rssi = SDR_RSSI_NOISE; 
    }
    else if((act_rssi < -102) && (act_rssi > -104))
    {
        rssi = SDR_RSSI_AVG;
    }
    else if((act_rssi < -90) && (act_rssi > -101))
    {
        rssi = SDR_RSSI_BETTER;
    }
    else if((act_rssi < -40) && (act_rssi > -89))
    {
        rssi = SDR_RSSI_GOOD;
    }

    return rssi;
}
